Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Please also have a look at our

### Added

- Add support for modern CSS at-rules: `@layer`, `@scope`, and `@starting-style` (#1549)

### Changed

### Deprecated
Expand Down
4 changes: 3 additions & 1 deletion src/Property/AtRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ interface AtRule extends CSSListItem
/**
* Since there are more set rules than block rules,
* we’re whitelisting the block rules and have anything else be treated as a set rule.
* NOTE: The new line when assigning the value is added to avoid the line length limit of codesniffer.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment belongs in the PR discussion or commit message, not the code.

Suggested change
* NOTE: The new line when assigning the value is added to avoid the line length limit of codesniffer.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs to be removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just waiting for confirmation that BLOCK_RULES will not be converted to array in this PR.

*
* @internal since 8.5.2
*/
public const BLOCK_RULES = 'media/document/supports/region-style/font-feature-values/container';
public const BLOCK_RULES =
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to change this to an array, but that's for another PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a quick win. Are you sure you want it in a separate PR?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a quick win. Are you sure you want it in a separate PR?

Having PRs only addressing one thing makes it easier to backport them or temporarily undo them if a problem is found. So, yes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1556 for this.

'media/document/supports/region-style/font-feature-values/container/layer/scope/starting-style';

/**
* @return non-empty-string
Expand Down
111 changes: 111 additions & 0 deletions tests/CSSList/AtRuleBlockListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,21 @@ public static function provideSyntacticallyCorrectAtRule(): array
'container' => [
'@container (min-width: 60rem) { .items { background: blue; } }',
],
'layer named' => [
'@layer theme { .button { color: blue; } }',
],
'layer anonymous' => [
'@layer { .card { padding: 1rem; } }',
],
'scope with selector' => [
'@scope (.card) { .title { font-size: 2rem; } }',
],
'scope root only' => [
'@scope { .content { margin: 0; } }',
],
'starting-style' => [
'@starting-style { .dialog { opacity: 0; transform: translateY(-10px); } }',
],
];
}

Expand Down Expand Up @@ -94,4 +109,100 @@ public function parsesSyntacticallyCorrectAtRuleInStrictMode(string $css): void

self::assertNotEmpty($contents, 'Failing CSS: `' . $css . '`');
}

/**
* @return array<string, array{0: string, 1: string, 2: string, 3: int}>
*/
public static function provideAtRuleParsingData(): array
{
return [
'layer with named argument' => [
'@layer theme { .button { color: blue; } }',
'layer',
'theme',
1,
],
'layer without arguments' => [
'@layer { .card { padding: 1rem; } }',
'layer',
'',
1,
],
'scope with selector' => [
'@scope (.card) { .title { font-size: 2rem; } }',
'scope',
'(.card)',
1,
],
Comment on lines +134 to +139
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to have a test for scope with a limt, e.g. @scope (.article-body) to (figure)? Or does that not currently parse correctly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It parses correctly.

'scope without selector' => [
'@scope { .content { margin: 0; } }',
'scope',
'',
1,
],
'starting-style' => [
'@starting-style { .dialog { opacity: 0; transform: translateY(-10px); } }',
'starting-style',
'',
1,
],
];
}

/**
* @return array<string, array{0: string, 1: list<string>}>
*/
public static function provideAtRuleRenderingData(): array
{
return [
'layer with named argument' => [
'@layer theme { .button { color: blue; } }',
['@layer theme', '.button', 'color: blue'],
],
'scope with selector' => [
'@scope (.card) { .title { font-size: 2rem; } }',
['@scope (.card)', '.title', 'font-size: 2rem'],
],
'starting-style' => [
'@starting-style { .dialog { opacity: 0; } }',
['@starting-style', '.dialog', 'opacity: 0'],
],
];
}

/**
* @test
*
* @dataProvider provideAtRuleParsingData
*/
public function parsesAtRuleBlockList(
string $css,
string $expectedName,
string $expectedArgs,
int $expectedContentCount
): void {
$contents = (new Parser($css))->parse()->getContents();
$atRuleBlockList = $contents[0];

self::assertInstanceOf(AtRuleBlockList::class, $atRuleBlockList);
self::assertSame($expectedName, $atRuleBlockList->atRuleName());
self::assertSame($expectedArgs, $atRuleBlockList->atRuleArgs());
self::assertCount($expectedContentCount, $atRuleBlockList->getContents());
}

/**
* @test
*
* @dataProvider provideAtRuleRenderingData
*
* @param list<string> $expectedSubstrings
*/
public function rendersAtRuleBlockListCorrectly(string $css, array $expectedSubstrings): void
{
$rendered = (new Parser($css))->parse()->render();

foreach ($expectedSubstrings as $expected) {
self::assertStringContainsString($expected, $rendered);
}
}
}
12 changes: 11 additions & 1 deletion tests/Unit/Property/AtRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,17 @@ final class AtRuleTest extends TestCase
public function blockRulesConstantIsCorrect(): void
{
self::assertEqualsCanonicalizing(
['media', 'document', 'supports', 'region-style', 'font-feature-values', 'container'],
[
'media',
'document',
'supports',
'region-style',
'font-feature-values',
'container',
'layer',
'scope',
'starting-style',
],
explode('/', AtRule::BLOCK_RULES)
);
}
Expand Down