Browse Source

fix(compiler-sfc): `<style vars scoped>` prefixing should only apply to pre-transform source

fix #1623
Evan You 5 years ago
parent
commit
4951d43526

+ 7 - 1
packages/compiler-sfc/src/compileStyle.ts

@@ -7,6 +7,7 @@ import postcss, {
 } from 'postcss'
 } from 'postcss'
 import trimPlugin from './stylePluginTrim'
 import trimPlugin from './stylePluginTrim'
 import scopedPlugin from './stylePluginScoped'
 import scopedPlugin from './stylePluginScoped'
+import scopedVarsPlugin from './stylePluginScopedVars'
 import {
 import {
   processors,
   processors,
   StylePreprocessor,
   StylePreprocessor,
@@ -95,11 +96,16 @@ export function doCompileStyle(
   const source = preProcessedSource ? preProcessedSource.code : options.source
   const source = preProcessedSource ? preProcessedSource.code : options.source
 
 
   const plugins = (postcssPlugins || []).slice()
   const plugins = (postcssPlugins || []).slice()
+  if (vars && scoped) {
+    // vars + scoped, only applies to raw source before other transforms
+    // #1623
+    plugins.unshift(scopedVarsPlugin(id))
+  }
   if (trim) {
   if (trim) {
     plugins.push(trimPlugin())
     plugins.push(trimPlugin())
   }
   }
   if (scoped) {
   if (scoped) {
-    plugins.push(scopedPlugin({ id, vars }))
+    plugins.push(scopedPlugin(id))
   }
   }
   let cssModules: Record<string, string> | undefined
   let cssModules: Record<string, string> | undefined
   if (modules) {
   if (modules) {

+ 28 - 39
packages/compiler-sfc/src/stylePluginScoped.ts

@@ -3,10 +3,8 @@ import selectorParser, { Node, Selector } from 'postcss-selector-parser'
 
 
 const animationNameRE = /^(-\w+-)?animation-name$/
 const animationNameRE = /^(-\w+-)?animation-name$/
 const animationRE = /^(-\w+-)?animation$/
 const animationRE = /^(-\w+-)?animation$/
-const cssVarRE = /\bvar\(--(global:)?([^)]+)\)/g
 
 
-export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
-  const { id, vars: hasInjectedVars } = options as { id: string; vars: boolean }
+export default postcss.plugin('vue-scoped', (id: any) => (root: Root) => {
   const keyframes = Object.create(null)
   const keyframes = Object.create(null)
   const shortId = id.replace(/^data-v-/, '')
   const shortId = id.replace(/^data-v-/, '')
 
 
@@ -135,46 +133,37 @@ export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
     }).processSync(node.selector)
     }).processSync(node.selector)
   })
   })
 
 
-  const hasKeyframes = Object.keys(keyframes).length
-  if (hasKeyframes || hasInjectedVars)
+  if (Object.keys(keyframes).length) {
+    // If keyframes are found in this <style>, find and rewrite animation names
+    // in declarations.
+    // Caveat: this only works for keyframes and animation rules in the same
+    // <style> element.
+    // individual animation-name declaration
     root.walkDecls(decl => {
     root.walkDecls(decl => {
-      // If keyframes are found in this <style>, find and rewrite animation names
-      // in declarations.
-      // Caveat: this only works for keyframes and animation rules in the same
-      // <style> element.
-      if (hasKeyframes) {
-        // individual animation-name declaration
-        if (animationNameRE.test(decl.prop)) {
-          decl.value = decl.value
-            .split(',')
-            .map(v => keyframes[v.trim()] || v.trim())
-            .join(',')
-        }
-        // shorthand
-        if (animationRE.test(decl.prop)) {
-          decl.value = decl.value
-            .split(',')
-            .map(v => {
-              const vals = v.trim().split(/\s+/)
-              const i = vals.findIndex(val => keyframes[val])
-              if (i !== -1) {
-                vals.splice(i, 1, keyframes[vals[i]])
-                return vals.join(' ')
-              } else {
-                return v
-              }
-            })
-            .join(',')
-        }
+      if (animationNameRE.test(decl.prop)) {
+        decl.value = decl.value
+          .split(',')
+          .map(v => keyframes[v.trim()] || v.trim())
+          .join(',')
       }
       }
-
-      // rewrite CSS variables
-      if (hasInjectedVars && cssVarRE.test(decl.value)) {
-        decl.value = decl.value.replace(cssVarRE, (_, $1, $2) => {
-          return $1 ? `var(--${$2})` : `var(--${shortId}-${$2})`
-        })
+      // shorthand
+      if (animationRE.test(decl.prop)) {
+        decl.value = decl.value
+          .split(',')
+          .map(v => {
+            const vals = v.trim().split(/\s+/)
+            const i = vals.findIndex(val => keyframes[val])
+            if (i !== -1) {
+              vals.splice(i, 1, keyframes[vals[i]])
+              return vals.join(' ')
+            } else {
+              return v
+            }
+          })
+          .join(',')
       }
       }
     })
     })
+  }
 })
 })
 
 
 function isSpaceCombinator(node: Node) {
 function isSpaceCombinator(node: Node) {

+ 15 - 0
packages/compiler-sfc/src/stylePluginScopedVars.ts

@@ -0,0 +1,15 @@
+import postcss, { Root } from 'postcss'
+
+const cssVarRE = /\bvar\(--(global:)?([^)]+)\)/g
+
+export default postcss.plugin('vue-scoped', (id: any) => (root: Root) => {
+  const shortId = id.replace(/^data-v-/, '')
+  root.walkDecls(decl => {
+    // rewrite CSS variables
+    if (cssVarRE.test(decl.value)) {
+      decl.value = decl.value.replace(cssVarRE, (_, $1, $2) => {
+        return $1 ? `var(--${$2})` : `var(--${shortId}-${$2})`
+      })
+    }
+  })
+})