import VNode from 'core/vdom/vnode' import { isDef, isObject } from 'shared/util' import type { VNodeData, VNodeWithData } from 'types/vnode' export function genClassForVnode(vnode: VNodeWithData): string { let data = vnode.data let parentNode: VNode | VNodeWithData | undefined = vnode let childNode: VNode | VNodeWithData = vnode while (isDef(childNode.componentInstance)) { childNode = childNode.componentInstance._vnode! if (childNode && childNode.data) { data = mergeClassData(childNode.data, data) } } // @ts-expect-error parentNode.parent not VNodeWithData while (isDef((parentNode = parentNode.parent))) { if (parentNode && parentNode.data) { data = mergeClassData(data, parentNode.data) } } return renderClass(data.staticClass!, data.class) } function mergeClassData( child: VNodeData, parent: VNodeData ): { staticClass: string class: any } { return { staticClass: concat(child.staticClass, parent.staticClass), class: isDef(child.class) ? [child.class, parent.class] : parent.class } } export function renderClass( staticClass: string | null | undefined, dynamicClass: any ): string { if (isDef(staticClass) || isDef(dynamicClass)) { return concat(staticClass, stringifyClass(dynamicClass)) } /* istanbul ignore next */ return '' } export function concat(a?: string | null, b?: string | null): string { return a ? (b ? a + ' ' + b : a) : b || '' } export function stringifyClass(value: any): string { if (Array.isArray(value)) { return stringifyArray(value) } if (isObject(value)) { return stringifyObject(value) } if (typeof value === 'string') { return value } /* istanbul ignore next */ return '' } function stringifyArray(value: Array): string { let res = '' let stringified for (let i = 0, l = value.length; i < l; i++) { if (isDef((stringified = stringifyClass(value[i]))) && stringified !== '') { if (res) res += ' ' res += stringified } } return res } function stringifyObject(value: Object): string { let res = '' for (const key in value) { if (value[key]) { if (res) res += ' ' res += key } } return res }