-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
/
Copy pathssrRenderAttrs.ts
106 lines (100 loc) · 2.59 KB
/
ssrRenderAttrs.ts
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
98
99
100
101
102
103
104
105
106
import {
escapeHtml,
isBooleanAttrValue,
isOverloadedBooleanAttr,
isRenderableAttrValue,
isSVGTag,
stringifyStyle,
} from '@vue/shared'
import {
includeBooleanAttr,
isBooleanAttr,
isOn,
isSSRSafeAttrName,
isString,
makeMap,
normalizeClass,
normalizeStyle,
propsToAttrMap,
} from '@vue/shared'
// leading comma for empty string ""
const shouldIgnoreProp = /*@__PURE__*/ makeMap(
`,key,ref,innerHTML,textContent,ref_key,ref_for`,
)
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 if (key === 'className') {
ret += ` class="${String(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 (!isRenderableAttrValue(value)) {
return ``
}
const attrKey =
tag && (tag.indexOf('-') > 0 || isSVGTag(tag))
? key // preserve raw name on custom elements and svg
: propsToAttrMap[key] || key.toLowerCase()
if (
isBooleanAttr(attrKey) ||
(isOverloadedBooleanAttr(attrKey) && isBooleanAttrValue(value))
) {
return includeBooleanAttr(value) ? ` ${attrKey}` : ``
} else if (isSSRSafeAttrName(attrKey)) {
return value === '' ? ` ${attrKey}` : ` ${attrKey}="${escapeHtml(value)}"`
} else {
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 (!isRenderableAttrValue(value)) {
return ``
}
if (isOverloadedBooleanAttr(key) && isBooleanAttrValue(value)) {
return includeBooleanAttr(value) ? ` ${key}` : ``
}
return ` ${key}="${escapeHtml(value)}"`
}
export function ssrRenderClass(raw: unknown): string {
return escapeHtml(normalizeClass(raw))
}
export function ssrRenderStyle(raw: unknown): string {
if (!raw) {
return ''
}
if (isString(raw)) {
return escapeHtml(raw)
}
const styles = normalizeStyle(raw)
return escapeHtml(stringifyStyle(styles))
}