diff --git a/packages/compiler-sfc/__tests__/__snapshots__/cssVars.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/cssVars.spec.ts.snap index b44f584b..c290eb6f 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/cssVars.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/cssVars.spec.ts.snap @@ -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 } } }" diff --git a/packages/compiler-sfc/__tests__/cssVars.spec.ts b/packages/compiler-sfc/__tests__/cssVars.spec.ts index 965c9a52..f92852e8 100644 --- a/packages/compiler-sfc/__tests__/cssVars.spec.ts +++ b/packages/compiler-sfc/__tests__/cssVars.spec.ts @@ -204,8 +204,13 @@ describe('CSS vars injection', () => { `\n` + `` ) 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) diff --git a/packages/compiler-sfc/src/cssVars.ts b/packages/compiler-sfc/src/cssVars.ts index da3e164a..c7572e58 100644 --- a/packages/compiler-sfc/src/cssVars.ts +++ b/packages/compiler-sfc/src/cssVars.ts @@ -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 = 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)})` }) } }