Skip to content

Commit 3d8b0aa

Browse files
committed
[BUGFIX] Allow comma in quoted string in selector (#1323)
Split by commas during parsing, not after.
1 parent b9e3deb commit 3d8b0aa

File tree

3 files changed

+22
-7
lines changed

3 files changed

+22
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
5555

5656
### Fixed
5757

58+
- Parse quoted attribute selector value containing comma (#1323)
5859
- Allow comma in selectors (e.g. `:not(html, body)`) (#1293)
5960
- Set line number when `RuleSet::addRule()` called with only column number set
6061
(#1265)

src/RuleSet/DeclarationBlock.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,18 @@ public static function parse(ParserState $oParserState, $oList = null)
5757
$aComments = [];
5858
$oResult = new DeclarationBlock($oParserState->currentLine());
5959
try {
60+
$selectors = [];
6061
$selectorParts = [];
6162
$stringWrapperCharacter = null;
62-
static $stopCharacters = ['{', '}', '\'', '"'];
63+
$consumedNextCharacter = false;
64+
static $stopCharacters = ['{', '}', '\'', '"', ','];
6365
do {
64-
$selectorParts[] = $oParserState->consume(1)
65-
. $oParserState->consumeUntil($stopCharacters, false, false, $aComments);
66+
if (!$consumedNextCharacter) {
67+
$selectorParts[] = $oParserState->consume(1);
68+
}
69+
$selectorParts[] = $oParserState->consumeUntil($stopCharacters, false, false, $aComments);
6670
$nextCharacter = $oParserState->peek();
71+
$consumedNextCharacter = false;
6772
switch ($nextCharacter) {
6873
case '\'':
6974
// The fallthrough is intentional.
@@ -76,11 +81,20 @@ public static function parse(ParserState $oParserState, $oList = null)
7681
}
7782
}
7883
break;
84+
case ',':
85+
if (!\is_string($stringWrapperCharacter)) {
86+
$selectors[] = \implode('', $selectorParts);
87+
$selectorParts = [];
88+
$oParserState->consume(1);
89+
$consumedNextCharacter = true;
90+
}
91+
break;
7992
}
8093
} while (!\in_array($nextCharacter, ['{', '}'], true) || \is_string($stringWrapperCharacter));
81-
$oResult->setSelectors(\implode('', $selectorParts), $oList);
94+
$selectors[] = \implode('', $selectorParts); // add final or only selector
95+
$oResult->setSelectors($selectors, $oList);
8296
if ($oParserState->comes('{')) {
83-
$oParserState->consume(1);
97+
$oPparserState->consume(1);
8498
}
8599
} catch (UnexpectedTokenException $e) {
86100
if ($oParserState->getSettings()->bLenientParsing) {

tests/Unit/RuleSet/DeclarationBlockTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ public static function provideSelector(): array
5959
'type & pseudo-class' => ['a:hover'],
6060
'`not`' => [':not(#your-mug)'],
6161
'pseudo-element' => ['::before'],
62-
'attribute with `"`' => ['[alt="{}()[]\\"\'"]'],
63-
'attribute with `\'`' => ['[alt=\'{}()[]"\\\'\']'],
62+
'attribute with `"`' => ['[alt="{}()[]\\"\',"]'],
63+
'attribute with `\'`' => ['[alt=\'{}()[]"\\\',\']'],
6464
];
6565
}
6666

0 commit comments

Comments
 (0)