fix(compiler-sfc): fix css v-bind inside other css functions
fix #5302, close #5306
This commit is contained in:
parent
283df0ad68
commit
16fa18da6d
@ -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 }
|
||||
}
|
||||
|
||||
}"
|
||||
|
@ -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)
|
||||
|
@ -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)})`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user