]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): add scoping tag to trailing universal selector (#12918)
authorthecodewarrior <code@thecodewarrior.dev>
Thu, 22 May 2025 00:41:27 +0000 (17:41 -0700)
committerGitHub <noreply@github.com>
Thu, 22 May 2025 00:41:27 +0000 (08:41 +0800)
close #12906

packages/compiler-sfc/__tests__/compileStyle.spec.ts
packages/compiler-sfc/src/style/pluginScoped.ts

index 78fd52425e8ffe7dfa30658c57f9d9e3aac9c689..70c6af557abb592445b1f1c08554923282bc22d0 100644 (file)
@@ -493,7 +493,31 @@ describe('SFC style preprocessors', () => {
       }"
     `)
     expect(compileScoped(`.foo * { color: red; }`)).toMatchInlineSnapshot(`
-      ".foo[data-v-test] * { color: red;
+      ".foo[data-v-test] [data-v-test] { color: red;
+      }"
+    `)
+    expect(compileScoped(`.foo :active { color: red; }`))
+      .toMatchInlineSnapshot(`
+      ".foo[data-v-test] :active { color: red;
+      }"
+    `)
+    expect(compileScoped(`.foo *:active { color: red; }`))
+      .toMatchInlineSnapshot(`
+      ".foo[data-v-test] [data-v-test]:active { color: red;
+      }"
+    `)
+    expect(compileScoped(`.foo * .bar { color: red; }`)).toMatchInlineSnapshot(`
+      ".foo * .bar[data-v-test] { color: red;
+      }"
+    `)
+    expect(compileScoped(`:last-child * { color: red; }`))
+      .toMatchInlineSnapshot(`
+      "[data-v-test]:last-child [data-v-test] { color: red;
+      }"
+    `)
+    expect(compileScoped(`:last-child *:active { color: red; }`))
+      .toMatchInlineSnapshot(`
+      "[data-v-test]:last-child [data-v-test]:active { color: red;
       }"
     `)
   })
index d0aaddd7676ba41d59eb1ed8899718dcbb89f746..4845d8eee39568b6e91aa49ece544740635ff7fe 100644 (file)
@@ -102,6 +102,7 @@ function rewriteSelector(
   slotted = false,
 ) {
   let node: selectorParser.Node | null = null
+  let starNode: selectorParser.Node | null = null
   let shouldInject = !deep
   // find the last child node to insert attribute selector
   selector.each(n => {
@@ -216,17 +217,21 @@ function rewriteSelector(
           return false
         }
       }
-      // .foo * -> .foo[xxxxxxx] *
-      if (node) return
+      // store the universal selector so it can be rewritten later
+      // .foo * -> .foo[xxxxxxx] [xxxxxxx]
+      starNode = n
     }
 
     if (
-      (n.type !== 'pseudo' && n.type !== 'combinator') ||
+      (n.type !== 'pseudo' &&
+        n.type !== 'combinator' &&
+        n.type !== 'universal') ||
       (n.type === 'pseudo' &&
         (n.value === ':is' || n.value === ':where') &&
         !node)
     ) {
       node = n
+      starNode = null
     }
   })
 
@@ -274,6 +279,20 @@ function rewriteSelector(
         quoteMark: `"`,
       }),
     )
+    // Used for trailing universal selectors (#12906)
+    // `.foo * {}` -> `.foo[xxxxxxx] [xxxxxxx] {}`
+    if (starNode) {
+      selector.insertBefore(
+        starNode,
+        selectorParser.attribute({
+          attribute: idToAdd,
+          value: idToAdd,
+          raws: {},
+          quoteMark: `"`,
+        }),
+      )
+      selector.removeChild(starNode)
+    }
   }
 }