Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ultraviolet
Path: blob/main/src/rewrite/rewrite.html.js
304 views
1
/**
2
* @typedef {import('./index').default} Ultraviolet
3
*/
4
5
/**
6
*
7
* @param {Ultraviolet} ctx
8
*/
9
export function attributes(ctx, meta = ctx.meta) {
10
const { html, js, attributePrefix } = ctx;
11
const origPrefix = attributePrefix + "-attr-";
12
13
html.on("attr", (attr, type) => {
14
if (
15
attr.node.tagName === "base" &&
16
attr.name === "href" &&
17
attr.options.document
18
) {
19
meta.base = new URL(attr.value, meta.url);
20
}
21
22
if (type === "rewrite" && isUrl(attr.name, attr.tagName)) {
23
attr.node.setAttribute(origPrefix + attr.name, attr.value);
24
attr.value = ctx.rewriteUrl(attr.value, meta);
25
}
26
27
if (type === "rewrite" && isSrcset(attr.name)) {
28
attr.node.setAttribute(origPrefix + attr.name, attr.value);
29
attr.value = html.wrapSrcset(attr.value, meta);
30
}
31
32
if (type === "rewrite" && isHtml(attr.name)) {
33
attr.node.setAttribute(origPrefix + attr.name, attr.value);
34
attr.value = html.rewrite(attr.value, {
35
...meta,
36
document: true,
37
injectHead: attr.options.injectHead || [],
38
});
39
}
40
41
if (type === "rewrite" && isStyle(attr.name)) {
42
attr.node.setAttribute(origPrefix + attr.name, attr.value);
43
attr.value = ctx.rewriteCSS(attr.value, {
44
context: "declarationList",
45
});
46
}
47
48
if (type === "rewrite" && isForbidden(attr.name)) {
49
attr.name = origPrefix + attr.name;
50
}
51
52
if (type === "rewrite" && isEvent(attr.name)) {
53
attr.node.setAttribute(origPrefix + attr.name, attr.value);
54
attr.value = js.rewrite(attr.value, meta);
55
}
56
57
if (type === "source" && attr.name.startsWith(origPrefix)) {
58
if (attr.node.hasAttribute(attr.name.slice(origPrefix.length)))
59
attr.node.removeAttribute(attr.name.slice(origPrefix.length));
60
attr.name = attr.name.slice(origPrefix.length);
61
}
62
63
/*
64
if (isHtml(attr.name)) {
65
66
};
67
68
if (isStyle(attr.name)) {
69
70
};
71
72
if (isSrcset(attr.name)) {
73
74
};
75
*/
76
});
77
}
78
79
/**
80
*
81
* @param {Ultraviolet} ctx
82
*/
83
export function text(ctx) {
84
const { html, js, css } = ctx;
85
86
html.on("text", (text, type) => {
87
if (text.element.tagName === "script") {
88
text.value =
89
type === "rewrite" ? js.rewrite(text.value) : js.source(text.value);
90
}
91
92
if (text.element.tagName === "style") {
93
text.value =
94
type === "rewrite" ? css.rewrite(text.value) : css.source(text.value);
95
}
96
});
97
return true;
98
}
99
100
export function isUrl(name, tag) {
101
return (
102
(tag === "object" && name === "data") ||
103
[
104
"src",
105
"href",
106
"ping",
107
"movie",
108
"action",
109
"poster",
110
"profile",
111
"background",
112
].indexOf(name) > -1
113
);
114
}
115
116
export function isEvent(name) {
117
return (
118
[
119
"onafterprint",
120
"onbeforeprint",
121
"onbeforeunload",
122
"onerror",
123
"onhashchange",
124
"onload",
125
"onmessage",
126
"onoffline",
127
"ononline",
128
"onpagehide",
129
"onpopstate",
130
"onstorage",
131
"onunload",
132
"onblur",
133
"onchange",
134
"oncontextmenu",
135
"onfocus",
136
"oninput",
137
"oninvalid",
138
"onreset",
139
"onsearch",
140
"onselect",
141
"onsubmit",
142
"onkeydown",
143
"onkeypress",
144
"onkeyup",
145
"onclick",
146
"ondblclick",
147
"onmousedown",
148
"onmousemove",
149
"onmouseout",
150
"onmouseover",
151
"onmouseup",
152
"onmousewheel",
153
"onwheel",
154
"ondrag",
155
"ondragend",
156
"ondragenter",
157
"ondragleave",
158
"ondragover",
159
"ondragstart",
160
"ondrop",
161
"onscroll",
162
"oncopy",
163
"oncut",
164
"onpaste",
165
"onabort",
166
"oncanplay",
167
"oncanplaythrough",
168
"oncuechange",
169
"ondurationchange",
170
"onemptied",
171
"onended",
172
"onerror",
173
"onloadeddata",
174
"onloadedmetadata",
175
"onloadstart",
176
"onpause",
177
"onplay",
178
"onplaying",
179
"onprogress",
180
"onratechange",
181
"onseeked",
182
"onseeking",
183
"onstalled",
184
"onsuspend",
185
"ontimeupdate",
186
"onvolumechange",
187
"onwaiting",
188
].indexOf(name) > -1
189
);
190
}
191
192
/**
193
*
194
* @param {Ultraviolet} ctx
195
*/
196
export function injectHead(ctx) {
197
const { html } = ctx;
198
html.on("element", (element, type) => {
199
if (type !== "rewrite") return false;
200
if (element.tagName !== "head") return false;
201
if (!("injectHead" in element.options)) return false;
202
203
element.childNodes.unshift(...element.options.injectHead);
204
});
205
}
206
207
export function createJsInject(cookies = "", referrer = "") {
208
return (
209
`self.__uv$cookies = ${JSON.stringify(cookies)};` +
210
`self.__uv$referrer = ${JSON.stringify(referrer)};`
211
);
212
}
213
214
export function createHtmlInject(
215
handlerScript,
216
bundleScript,
217
clientScript,
218
configScript,
219
cookies,
220
referrer
221
) {
222
return [
223
{
224
tagName: "script",
225
nodeName: "script",
226
childNodes: [
227
{
228
nodeName: "#text",
229
value: createJsInject(cookies, referrer),
230
},
231
],
232
attrs: [
233
{
234
name: "__uv-script",
235
value: "1",
236
skip: true,
237
},
238
],
239
skip: true,
240
},
241
{
242
tagName: "script",
243
nodeName: "script",
244
childNodes: [],
245
attrs: [
246
{ name: "src", value: bundleScript, skip: true },
247
{
248
name: "__uv-script",
249
value: "1",
250
skip: true,
251
},
252
],
253
},
254
{
255
tagName: "script",
256
nodeName: "script",
257
childNodes: [],
258
attrs: [
259
{ name: "src", value: clientScript, skip: true },
260
{
261
name: "__uv-script",
262
value: "1",
263
skip: true,
264
},
265
],
266
},
267
{
268
tagName: "script",
269
nodeName: "script",
270
childNodes: [],
271
attrs: [
272
{ name: "src", value: configScript, skip: true },
273
{
274
name: "__uv-script",
275
value: "1",
276
skip: true,
277
},
278
],
279
},
280
{
281
tagName: "script",
282
nodeName: "script",
283
childNodes: [],
284
attrs: [
285
{ name: "src", value: handlerScript, skip: true },
286
{
287
name: "__uv-script",
288
value: "1",
289
skip: true,
290
},
291
],
292
},
293
];
294
}
295
296
export function isForbidden(name) {
297
return (
298
["http-equiv", "integrity", "sandbox", "nonce", "crossorigin"].indexOf(
299
name
300
) > -1
301
);
302
}
303
304
export function isHtml(name) {
305
return name === "srcdoc";
306
}
307
308
export function isStyle(name) {
309
return name === "style";
310
}
311
312
export function isSrcset(name) {
313
return name === "srcSet" || name === "srcset" || name === "imagesrcset";
314
}
315
316