Skip to content

Commit b6213a6

Browse files
committed
[BUGFIX] Allow at-rules to be parsed in strict mode (#456)
The reverts the change to `CSSList` in 134f4e6 and adds a comment that `null` is an expected return value when the end of the list (or block) is reached. Fixes #352
1 parent 07b4287 commit b6213a6

File tree

3 files changed

+58
-23
lines changed

3 files changed

+58
-23
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
1515

1616
### Fixed
1717

18+
- Fix (regression) failure to parse at-rules with strict parsing (#456)
19+
1820
## 8.5.0
1921

2022
### Added

src/CSSList/CSSList.php

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,15 @@ private static function parseListItem(ParserState $oParserState, CSSList $oList)
131131
}
132132
return $oAtRule;
133133
} elseif ($oParserState->comes('}')) {
134-
if (!$oParserState->getSettings()->bLenientParsing) {
135-
throw new UnexpectedTokenException('CSS selector', '}', 'identifier', $oParserState->currentLine());
136-
} else {
137-
if ($bIsRoot) {
138-
if ($oParserState->getSettings()->bLenientParsing) {
139-
return DeclarationBlock::parse($oParserState);
140-
} else {
141-
throw new SourceException("Unopened {", $oParserState->currentLine());
142-
}
134+
if ($bIsRoot) {
135+
if ($oParserState->getSettings()->bLenientParsing) {
136+
return DeclarationBlock::parse($oParserState);
143137
} else {
144-
return null;
138+
throw new SourceException("Unopened {", $oParserState->currentLine());
145139
}
140+
} else {
141+
// End of list
142+
return null;
146143
}
147144
} else {
148145
return DeclarationBlock::parse($oParserState, $oList);

tests/CSSList/AtRuleBlockListTest.php

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,46 @@
77
use Sabberworm\CSS\CSSList\AtRuleBlockList;
88
use Sabberworm\CSS\Parser;
99
use Sabberworm\CSS\Renderable;
10+
use Sabberworm\CSS\Settings;
1011

1112
/**
1213
* @covers \Sabberworm\CSS\CSSList\AtRuleBlockList
1314
*/
1415
final class AtRuleBlockListTest extends TestCase
1516
{
17+
/**
18+
* @return array<string, array{0: string}>
19+
*/
20+
public static function provideMinWidthMediaRule(): array
21+
{
22+
return [
23+
'without spaces around arguments' => ['@media(min-width: 768px){.class{color:red}}'],
24+
'with spaces around arguments' => ['@media (min-width: 768px) {.class{color:red}}'],
25+
];
26+
}
27+
28+
/**
29+
* @return array<string, array{0: string}>
30+
*/
31+
public static function provideSyntacticlyCorrectAtRule(): array
32+
{
33+
return [
34+
'media print' => ['@media print { html { background: white; color: black; } }'],
35+
'keyframes' => ['@keyframes mymove { from { top: 0px; } }'],
36+
'supports' => ['
37+
@supports (display: flex) {
38+
.flex-container > * {
39+
text-shadow: 0 0 2px blue;
40+
float: none;
41+
}
42+
.flex-container {
43+
display: flex;
44+
}
45+
}
46+
'],
47+
];
48+
}
49+
1650
/**
1751
* @test
1852
*/
@@ -43,23 +77,12 @@ public function implementsCommentable()
4377
self::assertInstanceOf(Commentable::class, $subject);
4478
}
4579

46-
/**
47-
* @return array<string, array<int, string>>
48-
*/
49-
public static function mediaRuleDataProvider()
50-
{
51-
return [
52-
'without spaces around arguments' => ['@media(min-width: 768px){.class{color:red}}'],
53-
'with spaces around arguments' => ['@media (min-width: 768px) {.class{color:red}}'],
54-
];
55-
}
56-
5780
/**
5881
* @test
5982
*
6083
* @param string $css
6184
*
62-
* @dataProvider mediaRuleDataProvider
85+
* @dataProvider provideMinWidthMediaRule
6386
*/
6487
public function parsesRuleNameOfMediaQueries($css)
6588
{
@@ -74,7 +97,7 @@ public function parsesRuleNameOfMediaQueries($css)
7497
*
7598
* @param string $css
7699
*
77-
* @dataProvider mediaRuleDataProvider
100+
* @dataProvider provideMinWidthMediaRule
78101
*/
79102
public function parsesArgumentsOfMediaQueries($css)
80103
{
@@ -83,4 +106,17 @@ public function parsesArgumentsOfMediaQueries($css)
83106

84107
self::assertSame('(min-width: 768px)', $atRuleBlockList->atRuleArgs());
85108
}
109+
110+
/**
111+
* @test
112+
*
113+
* @dataProvider provideMinWidthMediaRule
114+
* @dataProvider provideSyntacticlyCorrectAtRule
115+
*/
116+
public function parsesSyntacticlyCorrectAtRuleInStrictMode(string $css): void
117+
{
118+
$contents = (new Parser($css, Settings::create()->beStrict()))->parse()->getContents();
119+
120+
self::assertNotEmpty($contents, 'Failing CSS: `' . $css . '`');
121+
}
86122
}

0 commit comments

Comments
 (0)