Skip to content

Commit 54c68ce

Browse files
authored
Properly parse @container queries (#473)
* Add (failing) test for standalone property in `style()` query * Properly parse standalone properties in `style()` query * Add (failing) tests for multiple container queries * Properly parse multiple container queries * Add (failing) test for container name with no query * Properly parse container name without query
1 parent 39d6045 commit 54c68ce

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

src/parser/cssParser.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,8 @@ export class Parser {
473473
return hasContent ? this.finish(node) : null;
474474
}
475475

476-
public _parseDeclaration(stopTokens?: TokenType[]): nodes.Declaration | null {
477-
const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens);
476+
public _parseDeclaration(stopTokens?: TokenType[], standaloneCustomPropertyValid = false): nodes.Declaration | null {
477+
const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens, standaloneCustomPropertyValid);
478478
if (customProperty) {
479479
return customProperty;
480480
}
@@ -502,7 +502,7 @@ export class Parser {
502502
return this.finish(node);
503503
}
504504

505-
public _tryParseCustomPropertyDeclaration(stopTokens?: TokenType[]): nodes.CustomPropertyDeclaration | null {
505+
public _tryParseCustomPropertyDeclaration(stopTokens?: TokenType[], standaloneCustomPropertyValid = false): nodes.CustomPropertyDeclaration | null {
506506
if (!this.peekRegExp(TokenType.Ident, /^--/)) {
507507
return null;
508508
}
@@ -512,6 +512,9 @@ export class Parser {
512512
}
513513

514514
if (!this.accept(TokenType.Colon)) {
515+
if (standaloneCustomPropertyValid) {
516+
return this.finish(node);
517+
}
515518
return this.finish(node, ParseError.ColonExpected, [TokenType.Colon]);
516519
}
517520
if (this.prevToken) {
@@ -1415,7 +1418,16 @@ export class Parser {
14151418
this.consumeToken(); // @container
14161419

14171420
node.addChild(this._parseIdent()); // optional container name
1418-
node.addChild(this._parseContainerQuery());
1421+
if (node.addChild(this._parseContainerQuery())) {
1422+
while (this.accept(TokenType.Comma)) {
1423+
if (this.peek(TokenType.CurlyL)) {
1424+
break;
1425+
}
1426+
1427+
node.addChild(this._parseIdent()); // optional container name
1428+
node.addChild(this._parseContainerQuery());
1429+
}
1430+
}
14191431

14201432
return this._parseBody(node, this._parseContainerDeclaration.bind(this, isNested));
14211433
}
@@ -1427,7 +1439,7 @@ export class Parser {
14271439
if (this.acceptIdent('not')) {
14281440
node.addChild(this._parseContainerQueryInParens());
14291441
} else {
1430-
node.addChild(this._parseContainerQueryInParens());
1442+
node.addChild(this._parseContainerQueryInParens(true));
14311443
if (this.peekIdent('and')) {
14321444
while (this.acceptIdent('and')) {
14331445
node.addChild(this._parseContainerQueryInParens());
@@ -1441,7 +1453,7 @@ export class Parser {
14411453
return this.finish(node);
14421454
}
14431455

1444-
public _parseContainerQueryInParens(): nodes.Node {
1456+
public _parseContainerQueryInParens(optional = false): nodes.Node | null {
14451457
// <query-in-parens> = ( <container-query> )
14461458
// | ( <size-feature> )
14471459
// | style( <style-query> )
@@ -1465,6 +1477,9 @@ export class Parser {
14651477
return this.finish(node, ParseError.RightParenthesisExpected, [], [TokenType.CurlyL]);
14661478
}
14671479
} else {
1480+
if (optional) {
1481+
return null;
1482+
}
14681483
return this.finish(node, ParseError.LeftParenthesisExpected, [], [TokenType.CurlyL]);
14691484
}
14701485
return this.finish(node);
@@ -1493,7 +1508,7 @@ export class Parser {
14931508
}
14941509
}
14951510
} else {
1496-
node.addChild(this._parseDeclaration([TokenType.ParenthesisR]));
1511+
node.addChild(this._parseDeclaration([TokenType.ParenthesisR], true));
14971512
}
14981513
return this.finish(node);
14991514
}

src/test/css/parser.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,13 @@ suite('CSS - Parser', () => {
178178

179179
test('@container', function () {
180180
const parser = new Parser();
181+
assertNode(`@container card { #inner { background-color: skyblue; }}`, parser, parser._parseStylesheet.bind(parser));
181182
assertNode(`@container (width <= 150px) { #inner { background-color: skyblue; }}`, parser, parser._parseStylesheet.bind(parser));
182183
assertNode(`@container card (inline-size > 30em) and style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser));
184+
assertNode(`@container card style(--responsive) { }`, parser, parser._parseStylesheet.bind(parser));
185+
assertNode(`@container (inline-size > 30em), style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser));
186+
assertNode(`@container card (inline-size > 30em), style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser));
187+
assertNode(`@container card (inline-size > 30em), summary style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser));
183188
assertNode(`@container card (inline-size > 30em) { @container style(--responsive: true) {} }`, parser, parser._parseStylesheet.bind(parser));
184189
});
185190

0 commit comments

Comments
 (0)