deno.land / x / hono@v4.2.5 / utils / html.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
export const HtmlEscapedCallbackPhase = { Stringify: 1, BeforeStream: 2, Stream: 3,} as consttype HtmlEscapedCallbackOpts = { buffer?: [string] phase: (typeof HtmlEscapedCallbackPhase)[keyof typeof HtmlEscapedCallbackPhase] context: object // An object unique to each JSX tree. This object is used as the WeakMap key.}export type HtmlEscapedCallback = (opts: HtmlEscapedCallbackOpts) => Promise<string> | undefinedexport type HtmlEscaped = { isEscaped: true callbacks?: HtmlEscapedCallback[]}export type HtmlEscapedString = string & HtmlEscaped
/** * StringBuffer contains string and Promise<string> alternately * The length of the array will be odd, the odd numbered element will be a string, * and the even numbered element will be a Promise<string>. * When concatenating into a single string, it must be processed from the tail. * @example * [ * 'framework.', * Promise.resolve('ultra fast'), * 'a ', * Promise.resolve('is '), * 'Hono', * ] */export type StringBuffer = (string | Promise<string>)[]
export const raw = (value: unknown, callbacks?: HtmlEscapedCallback[]): HtmlEscapedString => { const escapedString = new String(value) as HtmlEscapedString escapedString.isEscaped = true escapedString.callbacks = callbacks
return escapedString}
// The `escapeToBuffer` implementation is based on code from the MIT licensed `react-dom` package.// https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/server/escapeTextForBrowser.js
const escapeRe = /[&<>'"]/
export const stringBufferToString = async (buffer: StringBuffer): Promise<HtmlEscapedString> => { let str = '' const callbacks: HtmlEscapedCallback[] = [] for (let i = buffer.length - 1; ; i--) { str += buffer[i] i-- if (i < 0) { break }
let r = await buffer[i] if (typeof r === 'object') { callbacks.push(...((r as HtmlEscapedString).callbacks || [])) }
const isEscaped = (r as HtmlEscapedString).isEscaped r = await (typeof r === 'object' ? (r as HtmlEscapedString).toString() : r) if (typeof r === 'object') { callbacks.push(...((r as HtmlEscapedString).callbacks || [])) }
if ((r as HtmlEscapedString).isEscaped ?? isEscaped) { str += r } else { const buf = [str] escapeToBuffer(r, buf) str = buf[0] } }
return raw(str, callbacks)}
export const escapeToBuffer = (str: string, buffer: StringBuffer): void => { const match = str.search(escapeRe) if (match === -1) { buffer[0] += str return }
let escape let index let lastIndex = 0
for (index = match; index < str.length; index++) { switch (str.charCodeAt(index)) { case 34: // " escape = '&quot;' break case 39: // ' escape = '&#39;' break case 38: // & escape = '&amp;' break case 60: // < escape = '&lt;' break case 62: // > escape = '&gt;' break default: continue }
buffer[0] += str.substring(lastIndex, index) + escape lastIndex = index + 1 }
buffer[0] += str.substring(lastIndex, index)}
export const resolveCallback = async ( str: string | HtmlEscapedString, phase: (typeof HtmlEscapedCallbackPhase)[keyof typeof HtmlEscapedCallbackPhase], preserveCallbacks: boolean, context: object, buffer?: [string]): Promise<string> => { const callbacks = (str as HtmlEscapedString).callbacks as HtmlEscapedCallback[] if (!callbacks?.length) { return Promise.resolve(str) } if (buffer) { buffer[0] += str } else { buffer = [str] }
const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then((res) => Promise.all( res // eslint-disable-next-line @typescript-eslint/no-explicit-any .filter<string>(Boolean as any) .map((str) => resolveCallback(str, phase, false, context, buffer)) ).then(() => (buffer as [string])[0]) )
if (preserveCallbacks) { return raw(await resStr, callbacks) } else { return resStr }}
hono

Version Info

Tagged at
a month ago