]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): fix css v-bind inside other css functions
authorEvan You <yyx990803@gmail.com>
Sun, 23 Jan 2022 12:58:43 +0000 (20:58 +0800)
committerEvan You <yyx990803@gmail.com>
Sun, 23 Jan 2022 12:58:43 +0000 (20:58 +0800)
fix #5302, close #5306

packages/compiler-sfc/__tests__/__snapshots__/cssVars.spec.ts.snap
packages/compiler-sfc/__tests__/cssVars.spec.ts
packages/compiler-sfc/src/cssVars.ts

index b44f584b206b4618f1a5b0d4f8f1ede9d9abbee6..c290eb6feec3f2ef039eb6a9e93fa7440e5da3d3 100644 (file)
@@ -74,14 +74,16 @@ export default {
   expose();
 
 _useCssVars(_ctx => ({
-  \\"xxxxxxxx-_a___b____2____px__\\": ((_unref(a) + _unref(b)) / 2 + 'px' ),
+  \\"xxxxxxxx-foo\\": (_unref(foo)),
+  \\"xxxxxxxx-_a___b____2____px_\\": ((_unref(a) + _unref(b)) / 2 + 'px'),
   \\"xxxxxxxx-__a___b______2___a_\\": (((_unref(a) + _unref(b))) / (2 * _unref(a)))
 }))
 
         let a = 100
         let b = 200
+        let foo = 300
         
-return { a, b }
+return { a, b, foo }
 }
 
 }"
index 965c9a5202b5c5a64fefc58fcd51718af6a91115..f92852e859f356df2f9bbb6320b8a9319d8fe646 100644 (file)
@@ -204,8 +204,13 @@ describe('CSS vars injection', () => {
         `<script setup>
         let a = 100
         let b = 200
+        let foo = 300
         </script>\n` +
           `<style>
+          p{
+            width: calc(v-bind(foo) - 3px);
+            height: calc(v-bind('foo') - 3px);
+          }
           div {
             color: v-bind((a + b) / 2 + 'px' );
           }
@@ -218,7 +223,8 @@ describe('CSS vars injection', () => {
         </style>`
       )
       expect(content).toMatch(`_useCssVars(_ctx => ({
-  "${mockId}-_a___b____2____px__": ((_unref(a) + _unref(b)) / 2 + 'px' ),
+  "${mockId}-foo": (_unref(foo)),
+  "${mockId}-_a___b____2____px_": ((_unref(a) + _unref(b)) / 2 + 'px'),
   "${mockId}-__a___b______2___a_": (((_unref(a) + _unref(b))) / (2 * _unref(a)))
 })`)
       assertCode(content)
index da3e164aeaf9bc3e784895656839806c786e9cd7..c7572e58d973df868834295ed3a72b62b635bad4 100644 (file)
@@ -12,8 +12,8 @@ import { PluginCreator } from 'postcss'
 import hash from 'hash-sum'
 
 export const CSS_VARS_HELPER = `useCssVars`
-export const cssVarRE =
-  /\bv-bind\s*\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^;]*))\s*\)/g
+// match v-bind() with max 2-levels of nested parens.
+const cssVarRE = /v-bind\s*\(((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*)\)/g
 
 export function genCssVarsFromList(
   vars: string[],
@@ -33,6 +33,17 @@ function genVarName(id: string, raw: string, isProd: boolean): string {
   }
 }
 
+function noramlizeExpression(exp: string) {
+  exp = exp.trim()
+  if (
+    (exp[0] === `'` && exp[exp.length - 1] === `'`) ||
+    (exp[0] === `"` && exp[exp.length - 1] === `"`)
+  ) {
+    return exp.slice(1, -1)
+  }
+  return exp
+}
+
 export function parseCssVars(sfc: SFCDescriptor): string[] {
   const vars: string[] = []
   sfc.styles.forEach(style => {
@@ -40,7 +51,7 @@ export function parseCssVars(sfc: SFCDescriptor): string[] {
     // ignore v-bind() in comments /* ... */
     const content = style.content.replace(/\/\*([\s\S]*?)\*\//g, '')
     while ((match = cssVarRE.exec(content))) {
-      const variable = match[1] || match[2] || match[3]
+      const variable = noramlizeExpression(match[1])
       if (!vars.includes(variable)) {
         vars.push(variable)
       }
@@ -62,8 +73,8 @@ export const cssVarsPlugin: PluginCreator<CssVarsPluginOptions> = opts => {
     Declaration(decl) {
       // rewrite CSS variables
       if (cssVarRE.test(decl.value)) {
-        decl.value = decl.value.replace(cssVarRE, (_, $1, $2, $3) => {
-          return `var(--${genVarName(id, $1 || $2 || $3, isProd)})`
+        decl.value = decl.value.replace(cssVarRE, (_, $1) => {
+          return `var(--${genVarName(id, noramlizeExpression($1), isProd)})`
         })
       }
     }