refactor: reuse parseStringStyle across compiler and runtime

This commit is contained in:
Evan You 2020-05-06 11:22:49 -04:00
parent 2d9f136077
commit 8df6bc0132
3 changed files with 28 additions and 33 deletions

View File

@ -5,6 +5,7 @@ import {
SimpleExpressionNode, SimpleExpressionNode,
SourceLocation SourceLocation
} from '@vue/compiler-core' } from '@vue/compiler-core'
import { parseStringStyle } from '@vue/shared'
// Parse inline CSS strings for static style attributes into an object. // Parse inline CSS strings for static style attributes into an object.
// This is a NodeTransform since it works on the static `style` attribute and // This is a NodeTransform since it works on the static `style` attribute and
@ -30,19 +31,10 @@ export const transformStyle: NodeTransform = (node, context) => {
} }
} }
const listDelimiterRE = /;(?![^(]*\))/g const parseInlineCSS = (
const propertyDelimiterRE = /:(.+)/
function parseInlineCSS(
cssText: string, cssText: string,
loc: SourceLocation loc: SourceLocation
): SimpleExpressionNode { ): SimpleExpressionNode => {
const res: Record<string, string> = {} const normalized = parseStringStyle(cssText)
cssText.split(listDelimiterRE).forEach(item => { return createSimpleExpression(JSON.stringify(normalized), false, loc, true)
if (item) {
const tmp = item.split(propertyDelimiterRE)
tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())
}
})
return createSimpleExpression(JSON.stringify(res), false, loc, true)
} }

View File

@ -258,7 +258,8 @@ describe('vnode', () => {
} }
}) })
}) })
test('style', () => {
test('style w/ strings', () => {
let props1: Data = { let props1: Data = {
style: 'width:100px;right:10;top:10' style: 'width:100px;right:10;top:10'
} }
@ -281,8 +282,8 @@ describe('vnode', () => {
width: '300px', width: '300px',
height: '300px', height: '300px',
fontSize: 30, fontSize: 30,
right: 10, right: '10',
top: 10 top: '10'
} }
}) })
}) })

View File

@ -1,14 +1,16 @@
import { isArray, isString, isObject, hyphenate } from './' import { isArray, isString, isObject, hyphenate } from './'
import { isNoUnitNumericStyleProp } from './domAttrConfig' import { isNoUnitNumericStyleProp } from './domAttrConfig'
export function normalizeStyle( export type NormalizedStyle = Record<string, string | number>
value: unknown
): Record<string, string | number> | undefined { export function normalizeStyle(value: unknown): NormalizedStyle | undefined {
if (isArray(value)) { if (isArray(value)) {
const res: Record<string, string | number> = {} const res: Record<string, string | number> = {}
for (let i = 0; i < value.length; i++) { for (let i = 0; i < value.length; i++) {
const styles = isString(value[i]) ? strStyleToObj(value[i]) : value[i] const item = value[i]
const normalized = normalizeStyle(styles) const normalized = normalizeStyle(
isString(item) ? parseStringStyle(item) : item
)
if (normalized) { if (normalized) {
for (const key in normalized) { for (const key in normalized) {
res[key] = normalized[key] res[key] = normalized[key]
@ -21,21 +23,21 @@ export function normalizeStyle(
} }
} }
function strStyleToObj(style: string) { const listDelimiterRE = /;(?![^(]*\))/g
const ret: Record<string, string | number> = {} const propertyDelimiterRE = /:(.+)/
style
.replace(/\s*/g, '') export function parseStringStyle(cssText: string): NormalizedStyle {
.split(';') const ret: NormalizedStyle = {}
.forEach((item: string) => { cssText.split(listDelimiterRE).forEach(item => {
const [key, val] = item.split(':') if (item) {
ret[key] = isNaN(Number(val)) ? val : Number(val) const tmp = item.split(propertyDelimiterRE)
}) tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim())
}
})
return ret return ret
} }
export function stringifyStyle( export function stringifyStyle(styles: NormalizedStyle | undefined): string {
styles: Record<string, string | number> | undefined
): string {
let ret = '' let ret = ''
if (!styles) { if (!styles) {
return ret return ret