diff --git a/src/parser/cssParser.ts b/src/parser/cssParser.ts index 588f24e4..e54b6817 100644 --- a/src/parser/cssParser.ts +++ b/src/parser/cssParser.ts @@ -1283,10 +1283,10 @@ export class Parser { if (this.accept(TokenType.ParenthesisL)) { // scope-start selector can start with a combinator as it defaults to :scope // Treat as nested - if (!node.setScopeStart(this._parseSelector(true))) { + if (!node.setScopeStart(this._parseScopeSelectorList())) { return this.finish(node, ParseError.SelectorExpected, [], [TokenType.ParenthesisR]) } - + if (!this.accept(TokenType.ParenthesisR)) { return this.finish(node, ParseError.RightParenthesisExpected, [], [TokenType.CurlyL]); } @@ -1299,10 +1299,10 @@ export class Parser { } // 'to' selector can start with a combinator as it defaults to :scope // Treat as nested - if (!node.setScopeEnd(this._parseSelector(true))) { + if (!node.setScopeEnd(this._parseScopeSelectorList())) { return this.finish(node, ParseError.SelectorExpected, [], [TokenType.ParenthesisR]) } - + if (!this.accept(TokenType.ParenthesisR)) { return this.finish(node, ParseError.RightParenthesisExpected, [], [TokenType.CurlyL]); } @@ -1311,6 +1311,17 @@ export class Parser { return this.finish(node) } + private _parseScopeSelectorList(): nodes.Node | null { + const selectors = this.createNode(nodes.NodeType.SelectorList); + if (!selectors.addChild(this._parseSelector(true))) { + return null; + } + while (this.accept(TokenType.Comma) && selectors.addChild(this._parseSelector(true))) { + // loop + } + return this.finish(selectors); + } + public _parseMedium(): nodes.Node | null { const node = this.create(nodes.Node); if (node.addChild(this._parseIdent())) { diff --git a/src/test/css/parser.test.ts b/src/test/css/parser.test.ts index 53a241a9..b8d96144 100644 --- a/src/test/css/parser.test.ts +++ b/src/test/css/parser.test.ts @@ -59,6 +59,8 @@ suite('CSS - Parser', () => { assertNode('@scope (.foo) {}', parser, parser._parseStylesheet.bind(parser)) assertNode('@scope to (.bar) {}', parser, parser._parseStylesheet.bind(parser)) assertNode('@scope (.foo) to (.bar) {}', parser, parser._parseStylesheet.bind(parser)) + assertNode('@scope (.foo, .bar) {}', parser, parser._parseStylesheet.bind(parser)) + assertNode('@scope (.foo, .bar) to (.baz, .qux) {}', parser, parser._parseStylesheet.bind(parser)) assertNode('@-ms-viewport { width: 320px; height: 768px; }', parser, parser._parseStylesheet.bind(parser)); assertNode('#boo, far {} \n.far boo {}', parser, parser._parseStylesheet.bind(parser)); assertNode('@-moz-keyframes darkWordHighlight { from { background-color: inherit; } to { background-color: rgba(83, 83, 83, 0.7); } }', parser, parser._parseStylesheet.bind(parser)); @@ -279,6 +281,9 @@ suite('CSS - Parser', () => { assertNode('@scope to (.bar) { }', parser, parser._parseScope.bind(parser)) assertNode('@scope (.foo) to (.bar) { }', parser, parser._parseScope.bind(parser)) assertNode('@scope (#foo) to (:has(> link)) {}', parser, parser._parseScope.bind(parser)) + assertNode('@scope (.foo, .bar) { }', parser, parser._parseScope.bind(parser)) + assertNode('@scope to (.foo, .bar) { }', parser, parser._parseScope.bind(parser)) + assertNode('@scope (.foo, .bar) to (.baz, .qux) { }', parser, parser._parseScope.bind(parser)) assertError('@scope ( { }', parser, parser._parseScope.bind(parser), ParseError.SelectorExpected) assertError('@scope () { }', parser, parser._parseScope.bind(parser), ParseError.SelectorExpected)