setup(__props) {
const count = ref(0)
+ const style = { color: 'red' }
return (_ctx, _push, _parent, _attrs) => {
const _cssVars = { style: {
- \\"--xxxxxxxx-count\\": (count.value)
+ \\"--xxxxxxxx-count\\": (count.value),
+ \\"--xxxxxxxx-style\\\\\\\\.color\\": (style.color)
}}
_push(\`<!--[--><div\${
_ssrRenderAttrs(_cssVars)
<script setup>
import { ref } from 'vue'
const count = ref(0)
+ const style = { color: 'red' }
</script>
<template>
<div>{{ count }}</div>
</template>
<style>
div { color: v-bind(count) }
+ span { color: v-bind(style.color) }
</style>
`,
{
expect(content).toMatch(`ssrInterpolate`)
expect(content).not.toMatch(`useCssVars`)
expect(content).toMatch(`"--${mockId}-count": (count.value)`)
+ expect(content).toMatch(`"--${mockId}-style\\\\.color": (style.color)`)
assertCode(content)
})
export const cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
-export function getEscapedCssVarName(key: string) {
- return key.replace(cssVarNameEscapeSymbolsRE, s => `\\${s}`)
+export function getEscapedCssVarName(key: string, doubleEscape: boolean) {
+ return key.replace(cssVarNameEscapeSymbolsRE, s =>
+ doubleEscape ? `\\\\${s}` : `\\${s}`
+ )
}
): string {
return `{\n ${vars
.map(
- key => `"${isSSR ? `--` : ``}${genVarName(id, key, isProd)}": (${key})`
+ key =>
+ `"${isSSR ? `--` : ``}${genVarName(id, key, isProd, isSSR)}": (${key})`
)
.join(',\n ')}\n}`
}
-function genVarName(id: string, raw: string, isProd: boolean): string {
+function genVarName(
+ id: string,
+ raw: string,
+ isProd: boolean,
+ isSSR = false
+): string {
if (isProd) {
return hash(id + raw)
} else {
// escape ASCII Punctuation & Symbols
- return `${id}-${getEscapedCssVarName(raw)}`
+ // #7823 need to double-escape in SSR because the attributes are rendered
+ // into an HTML string
+ return `${id}-${getEscapedCssVarName(raw, isSSR)}`
}
}