From a3d56a03cc4d2a06ca961cbbed64a4808b5762ab Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Fri, 29 Nov 2024 16:47:55 +0800 Subject: [PATCH 1/2] refactor: setStyle reuse from runtime-dom --- packages/runtime-dom/src/modules/style.ts | 73 ++------------------- packages/runtime-shared/src/index.ts | 1 + packages/runtime-shared/src/style.ts | 64 +++++++++++++++++++ packages/runtime-vapor/src/dom/style.ts | 78 ++--------------------- 4 files changed, 75 insertions(+), 141 deletions(-) create mode 100644 packages/runtime-shared/src/style.ts diff --git a/packages/runtime-dom/src/modules/style.ts b/packages/runtime-dom/src/modules/style.ts index 383628a6a..17b235060 100644 --- a/packages/runtime-dom/src/modules/style.ts +++ b/packages/runtime-dom/src/modules/style.ts @@ -1,5 +1,6 @@ -import { capitalize, hyphenate, isArray, isString } from '@vue/shared' -import { camelize, warn } from '@vue/runtime-core' +import { isString } from '@vue/shared' +import { warn } from '@vue/runtime-core' +import { type Style, setStyle } from '@vue/runtime-shared' import { type VShowElement, vShowHidden, @@ -7,8 +8,6 @@ import { } from '../directives/vShow' import { CSS_VAR_TEXT } from '../helpers/useCssVars' -type Style = string | Record | null - const displayRE = /(^|;)\s*display\s*:/ export function patchStyle(el: Element, prev: Style, next: Style): void { @@ -20,14 +19,14 @@ export function patchStyle(el: Element, prev: Style, next: Style): void { if (!isString(prev)) { for (const key in prev) { if (next[key] == null) { - setStyle(style, key, '') + setStyle(style, key, '', warn) } } } else { for (const prevStyle of prev.split(';')) { const key = prevStyle.slice(0, prevStyle.indexOf(':')).trim() if (next[key] == null) { - setStyle(style, key, '') + setStyle(style, key, '', warn) } } } @@ -36,7 +35,7 @@ export function patchStyle(el: Element, prev: Style, next: Style): void { if (key === 'display') { hasControlledDisplay = true } - setStyle(style, key, next[key]) + setStyle(style, key, next[key], warn) } } else { if (isCssString) { @@ -63,63 +62,3 @@ export function patchStyle(el: Element, prev: Style, next: Style): void { } } } - -const semicolonRE = /[^\\];\s*$/ -const importantRE = /\s*!important$/ - -function setStyle( - style: CSSStyleDeclaration, - name: string, - val: string | string[], -) { - if (isArray(val)) { - val.forEach(v => setStyle(style, name, v)) - } else { - if (val == null) val = '' - if (__DEV__) { - if (semicolonRE.test(val)) { - warn( - `Unexpected semicolon at the end of '${name}' style value: '${val}'`, - ) - } - } - if (name.startsWith('--')) { - // custom property definition - style.setProperty(name, val) - } else { - const prefixed = autoPrefix(style, name) - if (importantRE.test(val)) { - // !important - style.setProperty( - hyphenate(prefixed), - val.replace(importantRE, ''), - 'important', - ) - } else { - style[prefixed as any] = val - } - } - } -} - -const prefixes = ['Webkit', 'Moz', 'ms'] -const prefixCache: Record = {} - -function autoPrefix(style: CSSStyleDeclaration, rawName: string): string { - const cached = prefixCache[rawName] - if (cached) { - return cached - } - let name = camelize(rawName) - if (name !== 'filter' && name in style) { - return (prefixCache[rawName] = name) - } - name = capitalize(name) - for (let i = 0; i < prefixes.length; i++) { - const prefixed = prefixes[i] + name - if (prefixed in style) { - return (prefixCache[rawName] = prefixed) - } - } - return rawName -} diff --git a/packages/runtime-shared/src/index.ts b/packages/runtime-shared/src/index.ts index af482926e..8df7cbca8 100644 --- a/packages/runtime-shared/src/index.ts +++ b/packages/runtime-shared/src/index.ts @@ -1,2 +1,3 @@ export { toHandlers } from './toHandlers' export { type Data } from './typeUtils' +export { type Style, setStyle } from './style' diff --git a/packages/runtime-shared/src/style.ts b/packages/runtime-shared/src/style.ts new file mode 100644 index 000000000..e74e04872 --- /dev/null +++ b/packages/runtime-shared/src/style.ts @@ -0,0 +1,64 @@ +import { camelize, capitalize, hyphenate, isArray } from '@vue/shared' + +export type Style = string | Record | null + +const semicolonRE = /[^\\];\s*$/ +const importantRE = /\s*!important$/ + +export function setStyle( + style: CSSStyleDeclaration, + name: string, + val: string | string[], + warn: (msg: string, ...args: any[]) => void, +): void { + if (isArray(val)) { + val.forEach(v => setStyle(style, name, v, warn)) + } else { + if (val == null) val = '' + if (__DEV__) { + if (semicolonRE.test(val)) { + warn( + `Unexpected semicolon at the end of '${name}' style value: '${val}'`, + ) + } + } + if (name.startsWith('--')) { + // custom property definition + style.setProperty(name, val) + } else { + const prefixed = autoPrefix(style, name) + if (importantRE.test(val)) { + // !important + style.setProperty( + hyphenate(prefixed), + val.replace(importantRE, ''), + 'important', + ) + } else { + style[prefixed as any] = val + } + } + } +} + +const prefixes = ['Webkit', 'Moz', 'ms'] +const prefixCache: Record = {} + +function autoPrefix(style: CSSStyleDeclaration, rawName: string): string { + const cached = prefixCache[rawName] + if (cached) { + return cached + } + let name = camelize(rawName) + if (name !== 'filter' && name in style) { + return (prefixCache[rawName] = name) + } + name = capitalize(name) + for (let i = 0; i < prefixes.length; i++) { + const prefixed = prefixes[i] + name + if (prefixed in style) { + return (prefixCache[rawName] = prefixed) + } + } + return rawName +} diff --git a/packages/runtime-vapor/src/dom/style.ts b/packages/runtime-vapor/src/dom/style.ts index 5ee233a0c..e96068a71 100644 --- a/packages/runtime-vapor/src/dom/style.ts +++ b/packages/runtime-vapor/src/dom/style.ts @@ -1,11 +1,5 @@ -import { - camelize, - capitalize, - hyphenate, - isArray, - isString, - normalizeStyle, -} from '@vue/shared' +import { isString, normalizeStyle } from '@vue/shared' +import { type Style, setStyle as setStyleValue } from '@vue/runtime-shared' import { warn } from '../warning' import { recordPropMetadata } from '../componentMetadata' import { mergeInheritAttr } from './prop' @@ -19,10 +13,6 @@ export function setStyle(el: HTMLElement, value: any, root?: boolean): void { patchStyle(el, prev, value) } -// TODO copied from packages/runtime-dom/src/modules/style.ts - -type Style = string | Record | null - function patchStyle(el: Element, prev: Style, next: Style) { const style = (el as HTMLElement).style const isCssString = isString(next) @@ -30,13 +20,13 @@ function patchStyle(el: Element, prev: Style, next: Style) { if (prev && !isString(prev)) { for (const key in prev) { if (next[key] == null) { - setStyleValue(style, key, '') + setStyleValue(style, key, '', warn) } } } for (const key in next) { - setStyleValue(style, key, next[key]) + setStyleValue(style, key, next[key], warn) } } else { if (isCssString) { @@ -49,63 +39,3 @@ function patchStyle(el: Element, prev: Style, next: Style) { } } } - -const semicolonRE = /[^\\];\s*$/ -const importantRE = /\s*!important$/ - -function setStyleValue( - style: CSSStyleDeclaration, - name: string, - val: string | string[], -) { - if (isArray(val)) { - val.forEach(v => setStyleValue(style, name, v)) - } else { - if (val == null) val = '' - if (__DEV__) { - if (semicolonRE.test(val)) { - warn( - `Unexpected semicolon at the end of '${name}' style value: '${val}'`, - ) - } - } - if (name.startsWith('--')) { - // custom property definition - style.setProperty(name, val) - } else { - const prefixed = autoPrefix(style, name) - if (importantRE.test(val)) { - // !important - style.setProperty( - hyphenate(prefixed), - val.replace(importantRE, ''), - 'important', - ) - } else { - style[prefixed as any] = val - } - } - } -} - -const prefixes = ['Webkit', 'Moz', 'ms'] -const prefixCache: Record = {} - -function autoPrefix(style: CSSStyleDeclaration, rawName: string): string { - const cached = prefixCache[rawName] - if (cached) { - return cached - } - let name = camelize(rawName) - if (name !== 'filter' && name in style) { - return (prefixCache[rawName] = name) - } - name = capitalize(name) - for (let i = 0; i < prefixes.length; i++) { - const prefixed = prefixes[i] + name - if (prefixed in style) { - return (prefixCache[rawName] = prefixed) - } - } - return rawName -} From cc3d3a6efe334d11042ab467539a98af0a549fc4 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Sun, 1 Dec 2024 17:27:31 +0800 Subject: [PATCH 2/2] refactor: no runtime-shared --- packages/runtime-dom/src/index.ts | 5 ++ packages/runtime-dom/src/modules/style.ts | 66 ++++++++++++++++++++++- packages/runtime-shared/src/index.ts | 1 - packages/runtime-shared/src/style.ts | 64 ---------------------- packages/runtime-vapor/src/dom/style.ts | 2 +- 5 files changed, 70 insertions(+), 68 deletions(-) delete mode 100644 packages/runtime-shared/src/style.ts diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index ca9a307dd..923908b49 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -306,3 +306,8 @@ export const initDirectivesForSSR: () => void = __SSR__ export * from '@vue/runtime-core' export * from './jsx' + +/** + * @internal + */ +export { type Style, setStyle } from './modules/style' diff --git a/packages/runtime-dom/src/modules/style.ts b/packages/runtime-dom/src/modules/style.ts index 17b235060..d07f8b9a9 100644 --- a/packages/runtime-dom/src/modules/style.ts +++ b/packages/runtime-dom/src/modules/style.ts @@ -1,6 +1,5 @@ -import { isString } from '@vue/shared' +import { camelize, capitalize, hyphenate, isArray, isString } from '@vue/shared' import { warn } from '@vue/runtime-core' -import { type Style, setStyle } from '@vue/runtime-shared' import { type VShowElement, vShowHidden, @@ -8,6 +7,8 @@ import { } from '../directives/vShow' import { CSS_VAR_TEXT } from '../helpers/useCssVars' +export type Style = string | Record | null + const displayRE = /(^|;)\s*display\s*:/ export function patchStyle(el: Element, prev: Style, next: Style): void { @@ -62,3 +63,64 @@ export function patchStyle(el: Element, prev: Style, next: Style): void { } } } + +const semicolonRE = /[^\\];\s*$/ +const importantRE = /\s*!important$/ + +export function setStyle( + style: CSSStyleDeclaration, + name: string, + val: string | string[], + warn: (msg: string, ...args: any[]) => void, +): void { + if (isArray(val)) { + val.forEach(v => setStyle(style, name, v, warn)) + } else { + if (val == null) val = '' + if (__DEV__) { + if (semicolonRE.test(val)) { + warn( + `Unexpected semicolon at the end of '${name}' style value: '${val}'`, + ) + } + } + if (name.startsWith('--')) { + // custom property definition + style.setProperty(name, val) + } else { + const prefixed = autoPrefix(style, name) + if (importantRE.test(val)) { + // !important + style.setProperty( + hyphenate(prefixed), + val.replace(importantRE, ''), + 'important', + ) + } else { + style[prefixed as any] = val + } + } + } +} + +const prefixes = ['Webkit', 'Moz', 'ms'] +const prefixCache: Record = {} + +function autoPrefix(style: CSSStyleDeclaration, rawName: string): string { + const cached = prefixCache[rawName] + if (cached) { + return cached + } + let name = camelize(rawName) + if (name !== 'filter' && name in style) { + return (prefixCache[rawName] = name) + } + name = capitalize(name) + for (let i = 0; i < prefixes.length; i++) { + const prefixed = prefixes[i] + name + if (prefixed in style) { + return (prefixCache[rawName] = prefixed) + } + } + return rawName +} diff --git a/packages/runtime-shared/src/index.ts b/packages/runtime-shared/src/index.ts index 8df7cbca8..af482926e 100644 --- a/packages/runtime-shared/src/index.ts +++ b/packages/runtime-shared/src/index.ts @@ -1,3 +1,2 @@ export { toHandlers } from './toHandlers' export { type Data } from './typeUtils' -export { type Style, setStyle } from './style' diff --git a/packages/runtime-shared/src/style.ts b/packages/runtime-shared/src/style.ts deleted file mode 100644 index e74e04872..000000000 --- a/packages/runtime-shared/src/style.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { camelize, capitalize, hyphenate, isArray } from '@vue/shared' - -export type Style = string | Record | null - -const semicolonRE = /[^\\];\s*$/ -const importantRE = /\s*!important$/ - -export function setStyle( - style: CSSStyleDeclaration, - name: string, - val: string | string[], - warn: (msg: string, ...args: any[]) => void, -): void { - if (isArray(val)) { - val.forEach(v => setStyle(style, name, v, warn)) - } else { - if (val == null) val = '' - if (__DEV__) { - if (semicolonRE.test(val)) { - warn( - `Unexpected semicolon at the end of '${name}' style value: '${val}'`, - ) - } - } - if (name.startsWith('--')) { - // custom property definition - style.setProperty(name, val) - } else { - const prefixed = autoPrefix(style, name) - if (importantRE.test(val)) { - // !important - style.setProperty( - hyphenate(prefixed), - val.replace(importantRE, ''), - 'important', - ) - } else { - style[prefixed as any] = val - } - } - } -} - -const prefixes = ['Webkit', 'Moz', 'ms'] -const prefixCache: Record = {} - -function autoPrefix(style: CSSStyleDeclaration, rawName: string): string { - const cached = prefixCache[rawName] - if (cached) { - return cached - } - let name = camelize(rawName) - if (name !== 'filter' && name in style) { - return (prefixCache[rawName] = name) - } - name = capitalize(name) - for (let i = 0; i < prefixes.length; i++) { - const prefixed = prefixes[i] + name - if (prefixed in style) { - return (prefixCache[rawName] = prefixed) - } - } - return rawName -} diff --git a/packages/runtime-vapor/src/dom/style.ts b/packages/runtime-vapor/src/dom/style.ts index e96068a71..06deafa4c 100644 --- a/packages/runtime-vapor/src/dom/style.ts +++ b/packages/runtime-vapor/src/dom/style.ts @@ -1,5 +1,5 @@ import { isString, normalizeStyle } from '@vue/shared' -import { type Style, setStyle as setStyleValue } from '@vue/runtime-shared' +import { type Style, setStyle as setStyleValue } from '@vue/runtime-dom' import { warn } from '../warning' import { recordPropMetadata } from '../componentMetadata' import { mergeInheritAttr } from './prop'