/* @flow */ import { escape } from '../util' import { isDef, isUndef, extend } from 'shared/util' import { isBooleanAttr, isEnumeratedAttr, isFalsyAttrValue, convertEnumeratedValue } from 'web/util/attrs' import { isSSRUnsafeAttr } from 'web/server/util' export default function renderAttrs (node: VNodeWithData): string { let attrs = node.data.attrs let res = '' const opts = node.parent && node.parent.componentOptions if (isUndef(opts) || opts.Ctor.options.inheritAttrs !== false) { let parent = node.parent while (isDef(parent)) { // Stop fallthrough in case parent has inheritAttrs option set to false if (parent.componentOptions && parent.componentOptions.Ctor.options.inheritAttrs === false) { break; } if (isDef(parent.data) && isDef(parent.data.attrs)) { attrs = extend(extend({}, attrs), parent.data.attrs) } parent = parent.parent } } if (isUndef(attrs)) { return res } for (const key in attrs) { if (isSSRUnsafeAttr(key)) { continue } if (key === 'style') { // leave it to the style module continue } res += renderAttr(key, attrs[key]) } return res } export function renderAttr (key: string, value: string): string { if (isBooleanAttr(key)) { if (!isFalsyAttrValue(value)) { return ` ${key}="${key}"` } } else if (isEnumeratedAttr(key)) { return ` ${key}="${escape(convertEnumeratedValue(key, value))}"` } else if (!isFalsyAttrValue(value)) { return ` ${key}="${escape(String(value))}"` } return '' }