Skip to content

Commit 5b5a2b7

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 5b5a2b7

3 files changed

Lines changed: 56 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: 53 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,55 @@ 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+
/**
71+
* @return DataProvider<non-empty-string, array{0: string, 1: bool}>
72+
*/
73+
public static function provideEmptyCssAndLenientParsingFlag(): DataProvider
74+
{
75+
return DataProvider::cross(static::provideEmptyCss(), static::provideLenientParsingFlag());
76+
}
77+
78+
/**
79+
* @test
80+
*
81+
* @dataProvider provideEmptyCssAndLenientParsingFlag
82+
*/
83+
public function parsesEmptyCss(string $css, bool $parseLeniently): void
84+
{
85+
$parser = new Parser($css, Settings::create()->withLenientParsing($parseLeniently));
86+
87+
$result = $parser->parse();
88+
89+
// Note: Comments for the document are accessed separately via `getComments()`.
90+
self::assertSame([], $result->getContents());
91+
}
3992
}

0 commit comments

Comments
 (0)