From a271cdc884d8370a6a7c2d5fc37e4b093158f66b Mon Sep 17 00:00:00 2001 From: Daniel Puckowski Date: Mon, 25 Nov 2024 19:46:14 -0500 Subject: [PATCH] fix(issue:4268) nested pseudo-selector parsing * Fix nested pseudo-selector parsing where selectors are separated by one or more commas. --- packages/less/src/less/parser/parser.js | 28 +++++++++++++++++--- packages/test-data/css/_main/selectors.css | 6 +++++ packages/test-data/less/_main/selectors.less | 8 ++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/packages/less/src/less/parser/parser.js b/packages/less/src/less/parser/parser.js index 59aa2eef4..532124e89 100644 --- a/packages/less/src/less/parser/parser.js +++ b/packages/less/src/less/parser/parser.js @@ -5,6 +5,8 @@ import getParserInput from './parser-input'; import * as utils from '../utils'; import functionRegistry from '../functions/function-registry'; import { ContainerSyntaxOptions, MediaSyntaxOptions } from '../tree/atrule-syntax'; +import Selector from '../tree/selector'; +import Anonymous from '../tree/anonymous'; // // less.js - parser @@ -1312,9 +1314,25 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) { if (!e) { parserInput.save(); if (parserInput.$char('(')) { - if ((v = this.selector(false)) && parserInput.$char(')')) { - e = new(tree.Paren)(v); - parserInput.forget(); + if ((v = this.selector(false))) { + let selectors = []; + while (parserInput.$char(',')) { + selectors.push(v); + selectors.push(new Anonymous(',')); + v = this.selector(false); + } + selectors.push(v); + + if (parserInput.$char(')')) { + if (selectors.length > 1) { + e = new (tree.Paren)(new Selector(selectors)); + } else { + e = new(tree.Paren)(v); + } + parserInput.forget(); + } else { + parserInput.restore('Missing closing \')\''); + } } else { parserInput.restore('Missing closing \')\''); } @@ -1395,7 +1413,9 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) { } else { if (allExtends) { error('Extend can only be used at the end of selector'); } c = parserInput.currentChar(); - if (elements) { + if (Array.isArray(e)){ + e.forEach(ele => elements.push(ele)); + } if (elements) { elements.push(e); } else { elements = [ e ]; diff --git a/packages/test-data/css/_main/selectors.css b/packages/test-data/css/_main/selectors.css index 9e0a31579..92c8b824f 100644 --- a/packages/test-data/css/_main/selectors.css +++ b/packages/test-data/css/_main/selectors.css @@ -183,3 +183,9 @@ blank blank blank blank blank blank blank blank blank blank blank blank blank bl .first-level .second-level.active2 { content: '\2661'; } +a:is(.b, :is(.c)) { + color: blue; +} +a:is(.b, :is(.c), :has(div)) { + color: red; +} diff --git a/packages/test-data/less/_main/selectors.less b/packages/test-data/less/_main/selectors.less index 8f8bc6f1a..c976380a8 100644 --- a/packages/test-data/less/_main/selectors.less +++ b/packages/test-data/less/_main/selectors.less @@ -200,3 +200,11 @@ blank blank blank blank blank blank blank blank blank blank blank blank blank bl &.active2:extend(.extend-this) { } } } + +a:is(.b, :is(.c)) { + color: blue; +} + +a:is(.b, :is(.c), :has(div)) { + color: red; +}