From f6b90f11a2bf1430939e4a6c373b89bb2190dbee Mon Sep 17 00:00:00 2001 From: liaoyinglong Date: Sat, 30 Mar 2024 17:06:24 +0800 Subject: [PATCH] support nested @container Close support nested @container #389 --- src/parser/cssParser.ts | 14 +++++++++++--- src/parser/lessParser.ts | 2 +- src/parser/scssParser.ts | 2 +- src/test/less/parser.test.ts | 1 + src/test/scss/parser.test.ts | 1 + 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/parser/cssParser.ts b/src/parser/cssParser.ts index 5811965f..37ea6f6a 100644 --- a/src/parser/cssParser.ts +++ b/src/parser/cssParser.ts @@ -325,7 +325,7 @@ export class Parser { || this._parseViewPort() || this._parseNamespace() || this._parseDocument() - || this._parseContainer() + || this._parseContainer(isNested) || this._parseUnknownAtRule(); } @@ -365,6 +365,7 @@ export class Parser { return this._parseMedia(true) || this._parseSupports(true) || this._parseLayer(true) + || this._parseContainer(true) || this._parseUnknownAtRule(); } @@ -1296,8 +1297,15 @@ export class Parser { this.resync([], [TokenType.CurlyL]); // ignore all the rules return this._parseBody(node, this._parseStylesheetStatement.bind(this)); } + public _parseContainerDeclaration(isNested = false): nodes.Node | null { + if (isNested) { + // if nested, the body can contain rulesets, but also declarations + return this._tryParseRuleset(true) || this._tryToParseDeclaration() || this._parseStylesheetStatement(true); + } + return this._parseStylesheetStatement(false); + } - public _parseContainer(): nodes.Node | null { + public _parseContainer(isNested: boolean = false): nodes.Node | null { if (!this.peekKeyword('@container')) { return null; } @@ -1307,7 +1315,7 @@ export class Parser { node.addChild(this._parseIdent()); // optional container name node.addChild(this._parseContainerQuery()); - return this._parseBody(node, this._parseStylesheetStatement.bind(this)); + return this._parseBody(node, this._parseContainerDeclaration.bind(this, isNested)); } public _parseContainerQuery(): nodes.Node | null { diff --git a/src/parser/lessParser.ts b/src/parser/lessParser.ts index 22de90a0..ad5259ac 100644 --- a/src/parser/lessParser.ts +++ b/src/parser/lessParser.ts @@ -320,7 +320,7 @@ export class LESSParser extends cssParser.Parser { || this._parseSupports(true) // @supports || this._parseLayer() // @layer || this._parsePropertyAtRule() // @property - || this._parseContainer() // @container + || this._parseContainer(true) // @container || this._parseDetachedRuleSetMixin() // less detached ruleset mixin || this._parseVariableDeclaration() // Variable declarations || this._parseRuleSetDeclarationAtStatement(); diff --git a/src/parser/scssParser.ts b/src/parser/scssParser.ts index e345f580..4ff9e71b 100644 --- a/src/parser/scssParser.ts +++ b/src/parser/scssParser.ts @@ -256,7 +256,7 @@ export class SCSSParser extends cssParser.Parser { || this._parseSupports(true) // @supports || this._parseLayer() // @layer || this._parsePropertyAtRule() // @property - || this._parseContainer() // @container + || this._parseContainer(true) // nested @container || this._parseRuleSetDeclarationAtStatement(); } return this._parseVariableDeclaration() // variable declaration diff --git a/src/test/less/parser.test.ts b/src/test/less/parser.test.ts index 04f2e03c..2b94ff44 100644 --- a/src/test/less/parser.test.ts +++ b/src/test/less/parser.test.ts @@ -352,5 +352,6 @@ suite('LESS - Parser', () => { test('@container', function () { const parser = new LESSParser(); assertNode(`.item-icon { @container (max-height: 100px) { .item-icon { display: none; } } }`, parser, parser._parseStylesheet.bind(parser)); + assertNode(`:root { @container (max-height: 100px) { display: none;} }`,parser,parser._parseStylesheet.bind(parser)); }); }); diff --git a/src/test/scss/parser.test.ts b/src/test/scss/parser.test.ts index 259168e0..680e3767 100644 --- a/src/test/scss/parser.test.ts +++ b/src/test/scss/parser.test.ts @@ -292,6 +292,7 @@ suite('SCSS - Parser', () => { const parser = new SCSSParser(); assertNode(`@container (min-width: #{$minWidth}) { .scss-interpolation { line-height: 10cqh; } }`, parser, parser._parseStylesheet.bind(parser)); assertNode(`.item-icon { @container (max-height: 100px) { .item-icon { display: none; } } }`, parser, parser._parseStylesheet.bind(parser)); + assertNode(`:root { @container (max-height: 100px) { display: none;} }`,parser,parser._parseStylesheet.bind(parser)); }); test('@use', function () {