diff --git a/src/CSSList/CSSList.php b/src/CSSList/CSSList.php index a99a6049..237b729a 100644 --- a/src/CSSList/CSSList.php +++ b/src/CSSList/CSSList.php @@ -131,7 +131,8 @@ private static function parseListItem(ParserState $oParserState, CSSList $oList) } elseif ($oParserState->comes('}')) { if ($bIsRoot) { if ($oParserState->getSettings()->bLenientParsing) { - return DeclarationBlock::parse($oParserState); + $oParserState->bufferForSelector(1); + return false; } else { throw new SourceException('Unopened {', $oParserState->currentLine()); } diff --git a/src/Parsing/ParserState.php b/src/Parsing/ParserState.php index cbfa89c9..7297a323 100644 --- a/src/Parsing/ParserState.php +++ b/src/Parsing/ParserState.php @@ -50,6 +50,7 @@ class ParserState * @var int */ private $iLineNo; + private $sSelectorBuffer; /** * @param string $sText the complete CSS as text (i.e., usually the contents of a CSS file) @@ -62,6 +63,7 @@ public function __construct($sText, Settings $oParserSettings, $iLineNo = 1) $this->iCurrentPosition = 0; $this->iLineNo = $iLineNo; $this->setCharset($this->oParserSettings->sDefaultCharset); + $this->sSelectorBuffer = ""; } /** @@ -126,6 +128,26 @@ public function setPosition($iPosition): void $this->iCurrentPosition = $iPosition; } + /** + * @param int $iCount + * + * @return void + */ + public function bufferForSelector($iCount) + { + $this->sSelectorBuffer .= $this->consume($iCount); + } + + /** + * @return string + */ + public function consumeSelectorBuffer() + { + $sResult = $this->sSelectorBuffer; + $this->sSelectorBuffer = ""; + return $sResult; + } + /** * @param bool $bIgnoreCase * diff --git a/src/RuleSet/DeclarationBlock.php b/src/RuleSet/DeclarationBlock.php index 6232a7fa..f56fecab 100644 --- a/src/RuleSet/DeclarationBlock.php +++ b/src/RuleSet/DeclarationBlock.php @@ -56,6 +56,10 @@ public static function parse(ParserState $oParserState, $oList = null) $oResult = new DeclarationBlock($oParserState->currentLine()); try { $aSelectorParts = []; + $sSelectorBuffer = $oParserState->consumeSelectorBuffer(); + if ($sSelectorBuffer) { + $aSelectorParts[] = $sSelectorBuffer; + } $sStringWrapperChar = false; do { $aSelectorParts[] = $oParserState->consume(1) diff --git a/tests/ParserTest.php b/tests/ParserTest.php index 2c1c7287..eb174446 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -787,6 +787,11 @@ public function invalidSelectorsInFile(): void html[dir="rtl"] .super-menu > li:last-of-type {border-left-width: 0;}} body {background-color: red;}'; self::assertSame($sExpected, $oDoc->render()); + + $oDoc = $this->parsedStructureForFile('invalid-selectors-3', Settings::create()->withMultibyteSupport(true)); + $sExpected = '#test {color: #fff;} +@media only screen and (max-width:30000px) {#test2 {color: #fff;}}'; + self::assertSame($sExpected, $oDoc->render()); } /** diff --git a/tests/fixtures/invalid-selectors-3.css b/tests/fixtures/invalid-selectors-3.css new file mode 100644 index 00000000..6ed13410 --- /dev/null +++ b/tests/fixtures/invalid-selectors-3.css @@ -0,0 +1,13 @@ +#test { + color: #fff; +} +} + +@media only screen and (max-width:30000px) { + #test { + color: #fff; + } + #test2 { + color: #fff; + } +}