All files / server-renderer/src/helpers ssrRenderAttrs.ts

92.85% Statements 39/42
93.54% Branches 29/31
100% Functions 6/6
92.85% Lines 39/42

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 9813x 13x                         13x   13x       146x 146x 133x         19x   114x 114x 24x 90x 8x   82x     146x       13x         82x 6x     76x     76x 19x 57x 57x                     13x 8x 2x   6x       90x 4x   86x 86x     13x 35x     13x 15x     15x 2x   13x 13x    
import { escapeHtml, stringifyStyle } from '@vue/shared'
import {
  normalizeClass,
  normalizeStyle,
  propsToAttrMap,
  isString,
  isOn,
  isSSRSafeAttrName,
  isBooleanAttr,
  includeBooleanAttr,
  makeMap
} from '@vue/shared'
 
// leading comma for empty string ""
const shouldIgnoreProp = makeMap(`,key,ref,innerHTML,textContent`)
 
export function ssrRenderAttrs(
  props: Record<string, unknown>,
  tag?: string
): string {
  let ret = ''
  for (const key in props) {
    if (
      shouldIgnoreProp(key) ||
      isOn(key) ||
      (tag === 'textarea' && key === 'value')
    ) {
      continue
    }
    const value = props[key]
    if (key === 'class') {
      ret += ` class="${ssrRenderClass(value)}"`
    } else if (key === 'style') {
      ret += ` style="${ssrRenderStyle(value)}"`
    } else {
      ret += ssrRenderDynamicAttr(key, value, tag)
    }
  }
  return ret
}
 
// render an attr with dynamic (unknown) key.
export function ssrRenderDynamicAttr(
  key: string,
  value: unknown,
  tag?: string
): string {
  if (!isRenderableValue(value)) {
    return ``
  }
  const attrKey =
    tag && tag.indexOf('-') > 0
      ? key // preserve raw name on custom elements
      : propsToAttrMap[key] || key.toLowerCase()
  if (isBooleanAttr(attrKey)) {
    return includeBooleanAttr(value) ? ` ${attrKey}` : ``
  } else if (isSSRSafeAttrName(attrKey)) {
    return value === '' ? ` ${attrKey}` : ` ${attrKey}="${escapeHtml(value)}"`
  } else E{
    console.warn(
      `[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`
    )
    return ``
  }
}
 
// Render a v-bind attr with static key. The key is pre-processed at compile
// time and we only need to check and escape value.
export function ssrRenderAttr(key: string, value: unknown): string {
  if (!isRenderableValue(value)) {
    return ``
  }
  return ` ${key}="${escapeHtml(value)}"`
}
 
function isRenderableValue(value: unknown): boolean {
  if (value == null) {
    return false
  }
  const type = typeof value
  return type === 'string' || type === 'number' || type === 'boolean'
}
 
export function ssrRenderClass(raw: unknown): string {
  return escapeHtml(normalizeClass(raw))
}
 
export function ssrRenderStyle(raw: unknown): string {
  Iif (!raw) {
    return ''
  }
  if (isString(raw)) {
    return escapeHtml(raw)
  }
  const styles = normalizeStyle(raw)
  return escapeHtml(stringifyStyle(styles))
}