import VNode from 'core/vdom/vnode'
|
import { cached, extend, toObject } from 'shared/util'
|
import type { VNodeData, VNodeWithData } from 'types/vnode'
|
|
export const parseStyleText = cached(function (cssText) {
|
const res = {}
|
const listDelimiter = /;(?![^(]*\))/g
|
const propertyDelimiter = /:(.+)/
|
cssText.split(listDelimiter).forEach(function (item) {
|
if (item) {
|
const tmp = item.split(propertyDelimiter)
|
tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())
|
}
|
})
|
return res
|
})
|
|
// merge static and dynamic style data on the same vnode
|
function normalizeStyleData(data: VNodeData): Record<string, any> {
|
const style = normalizeStyleBinding(data.style)
|
// static style is pre-processed into an object during compilation
|
// and is always a fresh object, so it's safe to merge into it
|
return data.staticStyle ? extend(data.staticStyle, style) : style
|
}
|
|
// normalize possible array / string values into Object
|
export function normalizeStyleBinding(bindingStyle: any): Record<string, any> {
|
if (Array.isArray(bindingStyle)) {
|
return toObject(bindingStyle)
|
}
|
if (typeof bindingStyle === 'string') {
|
return parseStyleText(bindingStyle)
|
}
|
return bindingStyle
|
}
|
|
/**
|
* parent component style should be after child's
|
* so that parent component's style could override it
|
*/
|
export function getStyle(vnode: VNodeWithData, checkChild: boolean): Object {
|
const res = {}
|
let styleData
|
|
if (checkChild) {
|
let childNode: VNodeWithData | VNode = vnode
|
while (childNode.componentInstance) {
|
childNode = childNode.componentInstance._vnode!
|
if (
|
childNode &&
|
childNode.data &&
|
(styleData = normalizeStyleData(childNode.data))
|
) {
|
extend(res, styleData)
|
}
|
}
|
}
|
|
if ((styleData = normalizeStyleData(vnode.data))) {
|
extend(res, styleData)
|
}
|
|
let parentNode: VNodeWithData | VNode | undefined = vnode
|
// @ts-expect-error parentNode.parent not VNodeWithData
|
while ((parentNode = parentNode.parent)) {
|
if (parentNode.data && (styleData = normalizeStyleData(parentNode.data))) {
|
extend(res, styleData)
|
}
|
}
|
return res
|
}
|