From a85debe588f08073939ccd00cf71757f75ad8bee Mon Sep 17 00:00:00 2001 From: ejshafran Date: Tue, 27 Jan 2026 15:51:27 +0200 Subject: [PATCH 1/6] Add (failing) test for standalone property in `style()` query --- src/test/css/parser.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/css/parser.test.ts b/src/test/css/parser.test.ts index 53a241a9..c8847bae 100644 --- a/src/test/css/parser.test.ts +++ b/src/test/css/parser.test.ts @@ -178,6 +178,7 @@ suite('CSS - Parser', () => { const parser = new Parser(); assertNode(`@container (width <= 150px) { #inner { background-color: skyblue; }}`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container card (inline-size > 30em) and style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser)); + assertNode(`@container card style(--responsive) { }`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container card (inline-size > 30em) { @container style(--responsive: true) {} }`, parser, parser._parseStylesheet.bind(parser)); }); From 91592fa114cbcf58e4fd86136849cae5401e469a Mon Sep 17 00:00:00 2001 From: ejshafran Date: Tue, 27 Jan 2026 15:51:49 +0200 Subject: [PATCH 2/6] Properly parse standalone properties in `style()` query --- src/parser/cssParser.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/parser/cssParser.ts b/src/parser/cssParser.ts index 588f24e4..963faede 100644 --- a/src/parser/cssParser.ts +++ b/src/parser/cssParser.ts @@ -473,8 +473,8 @@ export class Parser { return hasContent ? this.finish(node) : null; } - public _parseDeclaration(stopTokens?: TokenType[]): nodes.Declaration | null { - const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens); + public _parseDeclaration(stopTokens?: TokenType[], standaloneCustomPropertyValid = false): nodes.Declaration | null { + const customProperty = this._tryParseCustomPropertyDeclaration(stopTokens, standaloneCustomPropertyValid); if (customProperty) { return customProperty; } @@ -502,7 +502,7 @@ export class Parser { return this.finish(node); } - public _tryParseCustomPropertyDeclaration(stopTokens?: TokenType[]): nodes.CustomPropertyDeclaration | null { + public _tryParseCustomPropertyDeclaration(stopTokens?: TokenType[], standaloneCustomPropertyValid = false): nodes.CustomPropertyDeclaration | null { if (!this.peekRegExp(TokenType.Ident, /^--/)) { return null; } @@ -512,6 +512,9 @@ export class Parser { } if (!this.accept(TokenType.Colon)) { + if (standaloneCustomPropertyValid) { + return this.finish(node); + } return this.finish(node, ParseError.ColonExpected, [TokenType.Colon]); } if (this.prevToken) { @@ -1482,7 +1485,7 @@ export class Parser { } } } else { - node.addChild(this._parseDeclaration([TokenType.ParenthesisR])); + node.addChild(this._parseDeclaration([TokenType.ParenthesisR], true)); } return this.finish(node); } From 0a8d101f935c051966ae5d05b2e7bd7ffe5b7bb7 Mon Sep 17 00:00:00 2001 From: ejshafran Date: Tue, 27 Jan 2026 16:05:39 +0200 Subject: [PATCH 3/6] Add (failing) tests for multiple container queries --- src/test/css/parser.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/css/parser.test.ts b/src/test/css/parser.test.ts index c8847bae..5b806973 100644 --- a/src/test/css/parser.test.ts +++ b/src/test/css/parser.test.ts @@ -179,6 +179,9 @@ suite('CSS - Parser', () => { assertNode(`@container (width <= 150px) { #inner { background-color: skyblue; }}`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container card (inline-size > 30em) and style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container card style(--responsive) { }`, parser, parser._parseStylesheet.bind(parser)); + assertNode(`@container (inline-size > 30em), style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser)); + assertNode(`@container card (inline-size > 30em), style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser)); + assertNode(`@container card (inline-size > 30em), summary style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container card (inline-size > 30em) { @container style(--responsive: true) {} }`, parser, parser._parseStylesheet.bind(parser)); }); From f8b2a1ead555628438742bff7c15669eb9972ae4 Mon Sep 17 00:00:00 2001 From: ejshafran Date: Tue, 27 Jan 2026 16:06:10 +0200 Subject: [PATCH 4/6] Properly parse multiple container queries --- src/parser/cssParser.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/parser/cssParser.ts b/src/parser/cssParser.ts index 963faede..fb7e00cb 100644 --- a/src/parser/cssParser.ts +++ b/src/parser/cssParser.ts @@ -1407,7 +1407,16 @@ export class Parser { this.consumeToken(); // @container node.addChild(this._parseIdent()); // optional container name - node.addChild(this._parseContainerQuery()); + if (node.addChild(this._parseContainerQuery())) { + while (this.accept(TokenType.Comma)) { + if (this.peek(TokenType.CurlyL)) { + break; + } + + node.addChild(this._parseIdent()); // optional container name + node.addChild(this._parseContainerQuery()); + } + } return this._parseBody(node, this._parseContainerDeclaration.bind(this, isNested)); } From cb9e9094bc726eec1a58595d50e6b9b55e72852e Mon Sep 17 00:00:00 2001 From: ejshafran Date: Tue, 27 Jan 2026 16:06:19 +0200 Subject: [PATCH 5/6] Add (failing) test for container name with no query --- src/test/css/parser.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/css/parser.test.ts b/src/test/css/parser.test.ts index 5b806973..9a683bef 100644 --- a/src/test/css/parser.test.ts +++ b/src/test/css/parser.test.ts @@ -176,6 +176,7 @@ suite('CSS - Parser', () => { test('@container', function () { const parser = new Parser(); + assertNode(`@container card { #inner { background-color: skyblue; }}`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container (width <= 150px) { #inner { background-color: skyblue; }}`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container card (inline-size > 30em) and style(--responsive: true) { }`, parser, parser._parseStylesheet.bind(parser)); assertNode(`@container card style(--responsive) { }`, parser, parser._parseStylesheet.bind(parser)); From eeba4ab7ada6d47cde9530846830f08843804267 Mon Sep 17 00:00:00 2001 From: ejshafran Date: Tue, 27 Jan 2026 16:06:32 +0200 Subject: [PATCH 6/6] Properly parse container name without query --- src/parser/cssParser.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/parser/cssParser.ts b/src/parser/cssParser.ts index fb7e00cb..5542abd5 100644 --- a/src/parser/cssParser.ts +++ b/src/parser/cssParser.ts @@ -1428,7 +1428,7 @@ export class Parser { if (this.acceptIdent('not')) { node.addChild(this._parseContainerQueryInParens()); } else { - node.addChild(this._parseContainerQueryInParens()); + node.addChild(this._parseContainerQueryInParens(true)); if (this.peekIdent('and')) { while (this.acceptIdent('and')) { node.addChild(this._parseContainerQueryInParens()); @@ -1442,7 +1442,7 @@ export class Parser { return this.finish(node); } - public _parseContainerQueryInParens(): nodes.Node { + public _parseContainerQueryInParens(optional = false): nodes.Node | null { // = ( ) // | ( ) // | style( ) @@ -1466,6 +1466,9 @@ export class Parser { return this.finish(node, ParseError.RightParenthesisExpected, [], [TokenType.CurlyL]); } } else { + if (optional) { + return null; + } return this.finish(node, ParseError.LeftParenthesisExpected, [], [TokenType.CurlyL]); } return this.finish(node);