Skip to content

Commit 5199a12

Browse files
authored
fix(cssVars): cssVar names should be double-escaped when generating code for ssr (#8824)
close #7823
1 parent 6fcec3b commit 5199a12

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,10 +1003,12 @@ export default {
10031003
setup(__props) {
10041004
10051005
const count = ref(0)
1006+
const style = { color: 'red' }
10061007
10071008
return (_ctx, _push, _parent, _attrs) => {
10081009
const _cssVars = { style: {
1009-
\\"--xxxxxxxx-count\\": (count.value)
1010+
\\"--xxxxxxxx-count\\": (count.value),
1011+
\\"--xxxxxxxx-style\\\\\\\\.color\\": (style.color)
10101012
}}
10111013
_push(\`<!--[--><div\${
10121014
_ssrRenderAttrs(_cssVars)

packages/compiler-sfc/__tests__/compileScript.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,13 +778,15 @@ describe('SFC compile <script setup>', () => {
778778
<script setup>
779779
import { ref } from 'vue'
780780
const count = ref(0)
781+
const style = { color: 'red' }
781782
</script>
782783
<template>
783784
<div>{{ count }}</div>
784785
<div>static</div>
785786
</template>
786787
<style>
787788
div { color: v-bind(count) }
789+
span { color: v-bind(style.color) }
788790
</style>
789791
`,
790792
{
@@ -799,6 +801,7 @@ describe('SFC compile <script setup>', () => {
799801
expect(content).toMatch(`ssrInterpolate`)
800802
expect(content).not.toMatch(`useCssVars`)
801803
expect(content).toMatch(`"--${mockId}-count": (count.value)`)
804+
expect(content).toMatch(`"--${mockId}-style\\\\.color": (style.color)`)
802805
assertCode(content)
803806
})
804807

packages/compiler-sfc/src/script/utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ export function getEscapedPropName(key: string) {
121121

122122
export const cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
123123

124-
export function getEscapedCssVarName(key: string) {
125-
return key.replace(cssVarNameEscapeSymbolsRE, s => `\\${s}`)
124+
export function getEscapedCssVarName(key: string, doubleEscape: boolean) {
125+
return key.replace(cssVarNameEscapeSymbolsRE, s =>
126+
doubleEscape ? `\\\\${s}` : `\\${s}`
127+
)
126128
}

packages/compiler-sfc/src/style/cssVars.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,25 @@ export function genCssVarsFromList(
2222
): string {
2323
return `{\n ${vars
2424
.map(
25-
key => `"${isSSR ? `--` : ``}${genVarName(id, key, isProd)}": (${key})`
25+
key =>
26+
`"${isSSR ? `--` : ``}${genVarName(id, key, isProd, isSSR)}": (${key})`
2627
)
2728
.join(',\n ')}\n}`
2829
}
2930

30-
function genVarName(id: string, raw: string, isProd: boolean): string {
31+
function genVarName(
32+
id: string,
33+
raw: string,
34+
isProd: boolean,
35+
isSSR = false
36+
): string {
3137
if (isProd) {
3238
return hash(id + raw)
3339
} else {
3440
// escape ASCII Punctuation & Symbols
35-
return `${id}-${getEscapedCssVarName(raw)}`
41+
// #7823 need to double-escape in SSR because the attributes are rendered
42+
// into an HTML string
43+
return `${id}-${getEscapedCssVarName(raw, isSSR)}`
3644
}
3745
}
3846

0 commit comments

Comments
 (0)