mirror of https://github.com/vuejs/core.git
fix(hydration): escape css var name to avoid mismatch (#11739)
close #11735
This commit is contained in:
parent
cb843e0be3
commit
ca12e776bc
|
@ -121,15 +121,3 @@ export const propNameEscapeSymbolsRE: RegExp =
|
|||
export function getEscapedPropName(key: string): string {
|
||||
return propNameEscapeSymbolsRE.test(key) ? JSON.stringify(key) : key
|
||||
}
|
||||
|
||||
export const cssVarNameEscapeSymbolsRE: RegExp =
|
||||
/[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
|
||||
|
||||
export function getEscapedCssVarName(
|
||||
key: string,
|
||||
doubleEscape: boolean,
|
||||
): string {
|
||||
return key.replace(cssVarNameEscapeSymbolsRE, s =>
|
||||
doubleEscape ? `\\\\${s}` : `\\${s}`,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import {
|
|||
processExpression,
|
||||
} from '@vue/compiler-dom'
|
||||
import type { SFCDescriptor } from '../parse'
|
||||
import { getEscapedCssVarName } from '../script/utils'
|
||||
import type { PluginCreator } from 'postcss'
|
||||
import hash from 'hash-sum'
|
||||
import { getEscapedCssVarName } from '@vue/shared'
|
||||
|
||||
export const CSS_VARS_HELPER = `useCssVars`
|
||||
|
||||
|
|
|
@ -2021,6 +2021,26 @@ describe('SSR hydration', () => {
|
|||
app.mount(container)
|
||||
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
|
||||
})
|
||||
|
||||
test('escape css var name', () => {
|
||||
const container = document.createElement('div')
|
||||
container.innerHTML = `<div style="padding: 4px;--foo\\.bar:red;"></div>`
|
||||
const app = createSSRApp({
|
||||
setup() {
|
||||
useCssVars(() => ({
|
||||
'foo.bar': 'red',
|
||||
}))
|
||||
return () => h(Child)
|
||||
},
|
||||
})
|
||||
const Child = {
|
||||
setup() {
|
||||
return () => h('div', { style: 'padding: 4px' })
|
||||
},
|
||||
}
|
||||
app.mount(container)
|
||||
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
|
||||
})
|
||||
})
|
||||
|
||||
describe('data-allow-mismatch', () => {
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
PatchFlags,
|
||||
ShapeFlags,
|
||||
def,
|
||||
getEscapedCssVarName,
|
||||
includeBooleanAttr,
|
||||
isBooleanAttr,
|
||||
isKnownHtmlAttr,
|
||||
|
@ -915,7 +916,10 @@ function resolveCssVars(
|
|||
) {
|
||||
const cssVars = instance.getCssVars()
|
||||
for (const key in cssVars) {
|
||||
expectedMap.set(`--${key}`, String(cssVars[key]))
|
||||
expectedMap.set(
|
||||
`--${getEscapedCssVarName(key, false)}`,
|
||||
String(cssVars[key]),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (vnode === root && instance.parent) {
|
||||
|
|
|
@ -50,3 +50,15 @@ const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g
|
|||
export function escapeHtmlComment(src: string): string {
|
||||
return src.replace(commentStripRE, '')
|
||||
}
|
||||
|
||||
export const cssVarNameEscapeSymbolsRE: RegExp =
|
||||
/[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
|
||||
|
||||
export function getEscapedCssVarName(
|
||||
key: string,
|
||||
doubleEscape: boolean,
|
||||
): string {
|
||||
return key.replace(cssVarNameEscapeSymbolsRE, s =>
|
||||
doubleEscape ? `\\\\${s}` : `\\${s}`,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue