2 lines
22 KiB
PHP
2 lines
22 KiB
PHP
|
<?php
|
||
|
namespace Sabberworm\CSS; use Sabberworm\CSS\CSSList\CSSList; use Sabberworm\CSS\CSSList\Document; use Sabberworm\CSS\CSSList\KeyFrame; use Sabberworm\CSS\Parsing\SourceException; use Sabberworm\CSS\Property\AtRule; use Sabberworm\CSS\Property\Import; use Sabberworm\CSS\Property\Charset; use Sabberworm\CSS\Property\CSSNamespace; use Sabberworm\CSS\RuleSet\AtRuleSet; use Sabberworm\CSS\CSSList\AtRuleBlockList; use Sabberworm\CSS\RuleSet\DeclarationBlock; use Sabberworm\CSS\Value\CSSFunction; use Sabberworm\CSS\Value\CalcFunction; use Sabberworm\CSS\Value\RuleValueList; use Sabberworm\CSS\Value\CalcRuleValueList; use Sabberworm\CSS\Value\Size; use Sabberworm\CSS\Value\Color; use Sabberworm\CSS\Value\URL; use Sabberworm\CSS\Value\CSSString; use Sabberworm\CSS\Value\LineName; use Sabberworm\CSS\Rule\Rule; use Sabberworm\CSS\Parsing\UnexpectedTokenException; use Sabberworm\CSS\Comment\Comment; class Parser { private $sText; private $aText; private $iCurrentPosition; private $oParserSettings; private $sCharset; private $iLength; private $blockRules; private $aSizeUnits; private $iLineNo; public function __construct($sText, Settings $oParserSettings = null, $iLineNo = 1) { $this->sText = $sText; $this->iCurrentPosition = 0; $this->iLineNo = $iLineNo; if ($oParserSettings === null) { $oParserSettings = Settings::create(); } $this->oParserSettings = $oParserSettings; $this->blockRules = explode('/', AtRule::BLOCK_RULES); foreach (explode('/', Size::ABSOLUTE_SIZE_UNITS.'/'.Size::RELATIVE_SIZE_UNITS.'/'.Size::NON_SIZE_UNITS) as $val) { $iSize = strlen($val); if(!isset($this->aSizeUnits[$iSize])) { $this->aSizeUnits[$iSize] = array(); } $this->aSizeUnits[$iSize][strtolower($val)] = $val; } ksort($this->aSizeUnits, SORT_NUMERIC); } public function setCharset($sCharset) { $this->sCharset = $sCharset; $this->aText = $this->strsplit($this->sText); $this->iLength = count($this->aText); } public function getCharset() { return $this->sCharset; } public function parse() { $this->setCharset($this->oParserSettings->sDefaultCharset); $oResult = new Document($this->iLineNo); $this->parseDocument($oResult); return $oResult; } private function parseDocument(Document $oDocument) { $this->parseList($oDocument, true); } private function parseList(CSSList $oList, $bIsRoot = false) { while (!$this->isEnd()) { $comments = $this->consumeWhiteSpace(); $oListItem = null; if($this->oParserSettings->bLenientParsing) { try { $oListItem = $this->parseListItem($oList, $bIsRoot); } catch (UnexpectedTokenException $e) { $oListItem = false; } } else { $oListItem = $this->parseListItem($oList, $bIsRoot); } if($oListItem === null) { return; } if($oListItem) { $oListItem->setComments($comments); $oList->append($oListItem); } $this->consumeWhiteSpace(); } if (!$bIsRoot && !$this->oParserSettings->bLenientParsing) { throw new SourceException("Unexpected end of document", $this->iLineNo); } } private function parseListItem(CSSList $oList, $bIsRoot = false) { if ($this->comes('@')) { $oAtRule = $this->parseAtRule(); if($oAtRule instanceof Charset) { if(!$bIsRoot) { throw new UnexpectedTokenException('@charset may only occur in root document', '', 'custom', $this->iLineNo); } if(count($oList->getContents()) > 0) { throw new UnexpectedTokenException('@charset must be the first parseable token in a document', '', 'custom', $this->iLineNo); } $this->setCharset($oAtRule->getCharset()->getString()); } return $oAtRule; } else if ($this->comes('}')) { $this->consume('}'); if ($bIsRoot) { if ($this->oParserSettings->bLenientParsing) { while ($this->comes('}')) $this->consume('}'); return $this->parseSelector(); } else { throw new SourceException("Unopened {", $this->iLineNo); } } else { return null; } } else { return $this->parseSelector(); } } private function parseAtRule() { $this->consume('@'); $sIdentifier = $this->parseIdentifier(false); $iIdentifierLineNum = $this->iLineNo; $this->consumeWhiteSpace(); if ($sIdentifier === 'import') { $oLocation = $this->parseURLValue(); $this->consumeWhiteSpace(); $sMediaQuery = null; if (!$this->comes(';')) { $sMediaQuery = $this->consu
|