Skip to content

Commit 95e16b7

Browse files
JakeQZoliverklee
authored andcommitted
[BUGFIX] Parse @font-face src property as comma-delimited list
Fixes #789. Also adds an initial `TestCase` for `Rule/Rule`. This is the 8.x backport of #790.
1 parent 6098bee commit 95e16b7

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
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+
- Parse `@font-face` `src` property as comma-delimited list (#794)
19+
1820
## 8.7.0: Add support for PHP 8.4
1921

2022
### Added

src/Rule/Rule.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,26 @@ public static function parse(ParserState $oParserState)
114114
}
115115

116116
/**
117+
* Returns a list of delimiters (or separators).
118+
* The first item is the innermost separator (or, put another way, the highest-precedence operator).
119+
* The sequence continues to the outermost separator (or lowest-precedence operator).
120+
*
117121
* @param string $sRule
118122
*
119-
* @return array<int, string>
123+
* @return list<non-empty-string>
120124
*/
121125
private static function listDelimiterForRule($sRule)
122126
{
123127
if (preg_match('/^font($|-)/', $sRule)) {
124128
return [',', '/', ' '];
125129
}
126-
return [',', ' ', '/'];
130+
131+
switch ($sRule) {
132+
case 'src':
133+
return [' ', ','];
134+
default:
135+
return [',', ' ', '/'];
136+
}
127137
}
128138

129139
/**

tests/Unit/Rule/RuleTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS\Tests\Unit\Rule;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Sabberworm\CSS\Parsing\ParserState;
9+
use Sabberworm\CSS\Settings;
10+
use Sabberworm\CSS\Rule\Rule;
11+
use Sabberworm\CSS\Value\RuleValueList;
12+
use Sabberworm\CSS\Value\ValueList;
13+
14+
/**
15+
* @covers \Sabberworm\CSS\Rule\Rule
16+
*/
17+
final class RuleTest extends TestCase
18+
{
19+
/**
20+
* @return array<string, array{0: string, 1: list<class-string>}>
21+
*/
22+
public static function provideRulesAndExpectedParsedValueListTypes(): array
23+
{
24+
return [
25+
'src (e.g. in @font-face)' => [
26+
"
27+
src: url('../fonts/open-sans-italic-300.woff2') format('woff2'),
28+
url('../fonts/open-sans-italic-300.ttf') format('truetype');
29+
",
30+
[RuleValueList::class, RuleValueList::class],
31+
],
32+
];
33+
}
34+
35+
/**
36+
* @test
37+
*
38+
* @param list<class-string> $expectedTypeClassnames
39+
*
40+
* @dataProvider provideRulesAndExpectedParsedValueListTypes
41+
*/
42+
public function parsesValuesIntoExpectedTypeList(string $rule, array $expectedTypeClassnames): void
43+
{
44+
$subject = Rule::parse(new ParserState($rule, Settings::create()));
45+
46+
$value = $subject->getValue();
47+
self::assertInstanceOf(ValueList::class, $value);
48+
49+
$actualClassnames = \array_map(
50+
/**
51+
* @param Value|string $component
52+
*/
53+
static function ($component): string {
54+
return \is_string($component) ? 'string' : \get_class($component);
55+
},
56+
$value->getListComponents()
57+
);
58+
59+
self::assertSame($expectedTypeClassnames, $actualClassnames);
60+
}
61+
}

0 commit comments

Comments
 (0)