Skip to content

Commit 3191ce9

Browse files
committed
[BUGFIX] Allow CSS containing only whitespace or comments
The tests added are functional rather than unit tests, as they are indirectly testing `CSSList` rather than `Parser` itself. Fixes #349
1 parent b88cb8b commit 3191ce9

3 files changed

Lines changed: 55 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Please also have a look at our
2020

2121
### Fixed
2222

23+
- Allow CSS containing only whitespace or comments (#1593)
2324
- Only allow strings as `LineName` components (#1590)
2425

2526
### Documentation

src/CSSList/CSSList.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ public static function parseList(ParserState $parserState, CSSList $list): void
6767
$isRoot = $list instanceof Document;
6868
$usesLenientParsing = $parserState->getSettings()->usesLenientParsing();
6969
$comments = [];
70+
$parserState->consumeWhiteSpace($comments);
7071
while (!$parserState->isEnd()) {
71-
$parserState->consumeWhiteSpace($comments);
7272
$listItem = null;
7373
if ($usesLenientParsing) {
7474
try {
@@ -77,7 +77,7 @@ public static function parseList(ParserState $parserState, CSSList $list): void
7777
} catch (UnexpectedTokenException $e) {
7878
$listItem = false;
7979
// If the failed parsing did not consume anything that was to come ...
80-
if ($parserState->currentColumn() === $positionBeforeParse && !$parserState->isEnd()) {
80+
if ($parserState->currentColumn() === $positionBeforeParse) {
8181
// ... the unexpected token needs to be skipped, otherwise there'll be an infinite loop.
8282
$parserState->consume(1);
8383
}

tests/Functional/ParserTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use PHPUnit\Framework\TestCase;
88
use Sabberworm\CSS\CSSList\Document;
99
use Sabberworm\CSS\Parser;
10+
use Sabberworm\CSS\Settings;
11+
use TRegx\PhpUnit\DataProviders\DataProvider;
1012

1113
/**
1214
* @covers \Sabberworm\CSS\Parser
@@ -36,4 +38,54 @@ public function parseWithOneRuleSetReturnsDocument(): void
3638

3739
self::assertInstanceOf(Document::class, $result);
3840
}
41+
42+
/**
43+
* @return array<non-empty-string, array{0: string}>
44+
*/
45+
public static function provideEmptyCss(): array
46+
{
47+
return [
48+
'empty string' => [''],
49+
'space' => [' '],
50+
'newline' => ["\n"],
51+
'carriage return' => ["\r"],
52+
'tab' => ["\t"],
53+
'Windows line ending' => ["\r\n"],
54+
'comment' => ['/* I get put in a separate property */'],
55+
];
56+
}
57+
58+
/**
59+
* @return array<non-empty-string, array{0: bool}>
60+
*/
61+
public static function provideLenientParsingFlag(): array
62+
{
63+
return [
64+
'strict parsing' => [false],
65+
'lenient parsing' => [true],
66+
];
67+
}
68+
69+
/**
70+
* @return DataProvider<non-empty-string, array{0: string, 1: bool}>
71+
*/
72+
public static function provideEmptyCssAndLenientParsingFlag(): DataProvider
73+
{
74+
return DataProvider::cross(static::provideEmptyCss(), static::provideLenientParsingFlag());
75+
}
76+
77+
/**
78+
* @test
79+
*
80+
* @dataProvider provideEmptyCssAndLenientParsingFlag
81+
*/
82+
public function parsesEmptyCss(string $css, bool $parseLeniently): void
83+
{
84+
$parser = new Parser($css, Settings::create()->withLenientParsing($parseLeniently));
85+
86+
$result = $parser->parse();
87+
88+
// Note: Comments for the document are accessed separately via `getComments()`.
89+
self::assertSame([], $result->getContents());
90+
}
3991
}

0 commit comments

Comments
 (0)