diff --git a/packages/compiler-sfc/__tests__/compileStyle.spec.ts b/packages/compiler-sfc/__tests__/compileStyle.spec.ts index 70c6af557ab..fa1b7fe44b5 100644 --- a/packages/compiler-sfc/__tests__/compileStyle.spec.ts +++ b/packages/compiler-sfc/__tests__/compileStyle.spec.ts @@ -247,6 +247,42 @@ color: red .div[data-v-test]:is(.foo:hover) { color: blue; }" `) + + expect(compileScoped(`#app :is(.foo) { color: red; }`)) + .toMatchInlineSnapshot(` + "#app :is(.foo[data-v-test]) { color: red; + }" + `) + + expect(compileScoped(`#app :is(:is(.foo)) { color: red; }`)) + .toMatchInlineSnapshot(` + "#app :is(:is(.foo[data-v-test])) { color: red; + }" + `) + + expect(compileScoped(`#app :where(.foo) { color: red; }`)) + .toMatchInlineSnapshot(` + "#app :where(.foo[data-v-test]) { color: red; + }" + `) + + expect(compileScoped(`#app :where(:where(.foo)) { color: red; }`)) + .toMatchInlineSnapshot(` + "#app :where(:where(.foo[data-v-test])) { color: red; + }" + `) + + expect(compileScoped(`#app :is(:where(.foo)) { color: red; }`)) + .toMatchInlineSnapshot(` + "#app :is(:where(.foo[data-v-test])) { color: red; + }" + `) + + expect(compileScoped(`#app :where(:is(.foo)) { color: red; }`)) + .toMatchInlineSnapshot(` + "#app :where(:is(.foo[data-v-test])) { color: red; + }" + `) }) test('media query', () => { diff --git a/packages/compiler-sfc/src/style/pluginScoped.ts b/packages/compiler-sfc/src/style/pluginScoped.ts index 4845d8eee39..262e3174d84 100644 --- a/packages/compiler-sfc/src/style/pluginScoped.ts +++ b/packages/compiler-sfc/src/style/pluginScoped.ts @@ -226,9 +226,15 @@ function rewriteSelector( (n.type !== 'pseudo' && n.type !== 'combinator' && n.type !== 'universal') || - (n.type === 'pseudo' && - (n.value === ':is' || n.value === ':where') && - !node) + (isPseudoClassIsOrWhere(n) && + (!node || + n.nodes.some( + s => + // has nested :is or :where + s.nodes.some(x => isPseudoClassIsOrWhere(x)) || + // has non-pseudo selector + !s.nodes.some(x => x.type === 'pseudo'), + ))) ) { node = n starNode = null @@ -248,8 +254,7 @@ function rewriteSelector( } if (node) { - const { type, value } = node as selectorParser.Node - if (type === 'pseudo' && (value === ':is' || value === ':where')) { + if (isPseudoClassIsOrWhere(node)) { ;(node as selectorParser.Pseudo).nodes.forEach(value => rewriteSelector(id, rule, value, selectorRoot, deep, slotted), ) @@ -300,6 +305,14 @@ function isSpaceCombinator(node: selectorParser.Node) { return node.type === 'combinator' && /^\s+$/.test(node.value) } +function isPseudoClassIsOrWhere( + node: selectorParser.Node, +): node is selectorParser.Pseudo { + return ( + node.type === 'pseudo' && (node.value === ':is' || node.value === ':where') + ) +} + function extractAndWrapNodes(parentNode: Rule | AtRule) { if (!parentNode.nodes) return const nodes = parentNode.nodes.filter(