diff --git a/src/parser/cssParser.ts b/src/parser/cssParser.ts index 588f24e4..5542abd5 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) { @@ -1404,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)); } @@ -1416,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()); @@ -1430,7 +1442,7 @@ export class Parser { return this.finish(node); } - public _parseContainerQueryInParens(): nodes.Node { + public _parseContainerQueryInParens(optional = false): nodes.Node | null { // = ( ) // | ( ) // | style( ) @@ -1454,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); @@ -1482,7 +1497,7 @@ export class Parser { } } } else { - node.addChild(this._parseDeclaration([TokenType.ParenthesisR])); + node.addChild(this._parseDeclaration([TokenType.ParenthesisR], true)); } return this.finish(node); } diff --git a/src/test/css/parser.test.ts b/src/test/css/parser.test.ts index 53a241a9..9a683bef 100644 --- a/src/test/css/parser.test.ts +++ b/src/test/css/parser.test.ts @@ -176,8 +176,13 @@ 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)); + 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)); });