]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(sfc): fix v-slotted attribute injection
authorEvan You <yyx990803@gmail.com>
Thu, 19 Dec 2019 22:54:52 +0000 (17:54 -0500)
committerEvan You <yyx990803@gmail.com>
Thu, 19 Dec 2019 22:54:52 +0000 (17:54 -0500)
packages/compiler-sfc/__tests__/compileStyle.spec.ts [moved from packages/compiler-sfc/__tests__/stylePluginScoped.spec.ts with 67% similarity]
packages/compiler-sfc/src/stylePluginScoped.ts

similarity index 67%
rename from packages/compiler-sfc/__tests__/stylePluginScoped.spec.ts
rename to packages/compiler-sfc/__tests__/compileStyle.spec.ts
index ed24199a509f723b1f384e2d94eb75f24db79b01..5198e7a7e34dee19d0c926e1522f6ea862db513c 100644 (file)
@@ -55,52 +55,73 @@ describe('SFC scoped CSS', () => {
   })
 
   test('::v-deep', () => {
-    expect(compile(`::v-deep(.foo) { color: red; }`)).toMatch(
-      `[test] .foo { color: red;`
-    )
-    expect(compile(`::v-deep(.foo .bar) { color: red; }`)).toMatch(
-      `[test] .foo .bar { color: red;`
-    )
-    expect(compile(`.baz .qux ::v-deep(.foo .bar) { color: red; }`)).toMatch(
-      `.baz .qux[test] .foo .bar { color: red;`
-    )
+    expect(compile(`::v-deep(.foo) { color: red; }`)).toMatchInlineSnapshot(`
+      "[test] .foo { color: red;
+      }"
+    `)
+    expect(compile(`::v-deep(.foo .bar) { color: red; }`))
+      .toMatchInlineSnapshot(`
+      "[test] .foo .bar { color: red;
+      }"
+    `)
+    expect(compile(`.baz .qux ::v-deep(.foo .bar) { color: red; }`))
+      .toMatchInlineSnapshot(`
+      ".baz .qux[test] .foo .bar { color: red;
+      }"
+    `)
   })
 
   test('::v-slotted', () => {
-    expect(compile(`::v-slotted(.foo) { color: red; }`)).toMatch(
-      `.foo[test-s] { color: red;`
-    )
-    expect(compile(`::v-slotted(.foo .bar) { color: red; }`)).toMatch(
-      `.foo .bar[test-s] { color: red;`
-    )
-    expect(compile(`.baz .qux ::v-slotted(.foo .bar) { color: red; }`)).toMatch(
-      `.baz .qux[test] .foo .bar[test-s] { color: red;`
-    )
+    expect(compile(`::v-slotted(.foo) { color: red; }`)).toMatchInlineSnapshot(`
+      ".foo[test-s] { color: red;
+      }"
+    `)
+    expect(compile(`::v-slotted(.foo .bar) { color: red; }`))
+      .toMatchInlineSnapshot(`
+      ".foo .bar[test-s] { color: red;
+      }"
+    `)
+    expect(compile(`.baz .qux ::v-slotted(.foo .bar) { color: red; }`))
+      .toMatchInlineSnapshot(`
+      ".baz .qux .foo .bar[test-s] { color: red;
+      }"
+    `)
   })
 
   test('::v-global', () => {
-    expect(compile(`::v-global(.foo) { color: red; }`)).toMatch(
-      `.foo { color: red;`
-    )
-    expect(compile(`::v-global(.foo .bar) { color: red; }`)).toMatch(
-      `.foo .bar { color: red;`
-    )
+    expect(compile(`::v-global(.foo) { color: red; }`)).toMatchInlineSnapshot(`
+      ".foo { color: red;
+      }"
+    `)
+    expect(compile(`::v-global(.foo .bar) { color: red; }`))
+      .toMatchInlineSnapshot(`
+      ".foo .bar { color: red;
+      }"
+    `)
     // global ignores anything before it
-    expect(compile(`.baz .qux ::v-global(.foo .bar) { color: red; }`)).toMatch(
-      `.foo .bar { color: red;`
-    )
+    expect(compile(`.baz .qux ::v-global(.foo .bar) { color: red; }`))
+      .toMatchInlineSnapshot(`
+      ".foo .bar { color: red;
+      }"
+    `)
   })
 
   test('media query', () => {
-    expect(compile(`@media print { .foo { color: red }}`)).toMatch(
-      /@media print {\s+\.foo\[test\] \{ color: red/
-    )
+    expect(compile(`@media print { .foo { color: red }}`))
+      .toMatchInlineSnapshot(`
+      "@media print {
+      .foo[test] { color: red
+      }}"
+    `)
   })
 
   test('supports query', () => {
-    expect(
-      compile(`@supports(display: grid) { .foo { display: grid }}`)
-    ).toMatch(/@supports\(display: grid\) {\s+\.foo\[test\] \{ display: grid/)
+    expect(compile(`@supports(display: grid) { .foo { display: grid }}`))
+      .toMatchInlineSnapshot(`
+      "@supports(display: grid) {
+      .foo[test] { display: grid
+      }}"
+    `)
   })
 
   test('scoped keyframes', () => {
@@ -169,17 +190,23 @@ describe('SFC scoped CSS', () => {
       id: 'test'
     })
 
-    expect(code).toMatch(`.foo[test], .bar[test] { color: red;`)
+    expect(code).toMatchInlineSnapshot(`
+      ".foo[test], .bar[test] { color: red;
+      }"
+    `)
   })
 
   describe('deprecated syntax', () => {
     test('::v-deep as combinator', () => {
-      expect(compile(`::v-deep .foo { color: red; }`)).toMatch(
-        `[test] .foo { color: red;`
-      )
-      expect(compile(`.bar ::v-deep .foo { color: red; }`)).toMatch(
-        `.bar[test] .foo { color: red;`
-      )
+      expect(compile(`::v-deep .foo { color: red; }`)).toMatchInlineSnapshot(`
+        "[test] .foo { color: red;
+        }"
+      `)
+      expect(compile(`.bar ::v-deep .foo { color: red; }`))
+        .toMatchInlineSnapshot(`
+        ".bar[test] .foo { color: red;
+        }"
+      `)
       expect(
         `::v-deep usage as a combinator has been deprecated.`
       ).toHaveBeenWarned()
@@ -187,7 +214,10 @@ describe('SFC scoped CSS', () => {
 
     test('>>> (deprecated syntax)', () => {
       const code = compile(`>>> .foo { color: red; }`)
-      expect(code).toMatch(`[test] .foo { color: red;`)
+      expect(code).toMatchInlineSnapshot(`
+        "[test] .foo { color: red;
+        }"
+      `)
       expect(
         `the >>> and /deep/ combinators have been deprecated.`
       ).toHaveBeenWarned()
@@ -195,7 +225,10 @@ describe('SFC scoped CSS', () => {
 
     test('/deep/ (deprecated syntax)', () => {
       const code = compile(`/deep/ .foo { color: red; }`)
-      expect(code).toMatch(`[test] .foo { color: red;`)
+      expect(code).toMatchInlineSnapshot(`
+        "[test] .foo { color: red;
+        }"
+      `)
       expect(
         `the >>> and /deep/ combinators have been deprecated.`
       ).toHaveBeenWarned()
index 112e7944b40aced6539bd78a80618f568c02f76c..5f9abfa5b5190c0fab88662170b7ca52104e6108 100644 (file)
@@ -22,7 +22,7 @@ export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
     node.selector = selectorParser(selectors => {
       function rewriteSelector(selector: Selector, slotted?: boolean) {
         let node: Node | null = null
-
+        let shouldInject = true
         // find the last child node to insert attribute selector
         selector.each(n => {
           // DEPRECATED ">>>" and "/deep/" combinator
@@ -81,6 +81,9 @@ export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
               rewriteSelector(n.nodes[0] as Selector, true /* slotted */)
               selector.insertAfter(n, n.nodes[0])
               selector.removeChild(n)
+              // since slotted attribute already scopes the selector there's no
+              // need for the non-slot attribute.
+              shouldInject = false
               return false
             }
 
@@ -107,18 +110,20 @@ export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
           selector.first.spaces.before = ''
         }
 
-        const idToAdd = slotted ? id + '-s' : id
-        selector.insertAfter(
-          // If node is null it means we need to inject [id] at the start
-          // insertAfter can handle `null` here
-          node as any,
-          selectorParser.attribute({
-            attribute: idToAdd,
-            value: idToAdd,
-            raws: {},
-            quoteMark: `"`
-          })
-        )
+        if (shouldInject) {
+          const idToAdd = slotted ? id + '-s' : id
+          selector.insertAfter(
+            // If node is null it means we need to inject [id] at the start
+            // insertAfter can handle `null` here
+            node as any,
+            selectorParser.attribute({
+              attribute: idToAdd,
+              value: idToAdd,
+              raws: {},
+              quoteMark: `"`
+            })
+          )
+        }
       }
       selectors.each(selector => rewriteSelector(selector as Selector))
     }).processSync(node.selector)