Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ultraviolet
Path: blob/main/src/rewrite/index.js
304 views
1
import HTML from "./html.js";
2
import CSS from "./css.js";
3
import JS from "./js.js";
4
import setCookie from "set-cookie-parser";
5
import { xor, base64, plain } from "./codecs.js";
6
import {
7
validateCookie,
8
db,
9
getCookies,
10
setCookies,
11
serialize,
12
} from "./cookie.js";
13
import {
14
attributes,
15
isUrl,
16
isForbidden,
17
isHtml,
18
isSrcset,
19
isStyle,
20
text,
21
injectHead,
22
createHtmlInject,
23
createJsInject,
24
} from "./rewrite.html.js";
25
//import { call, destructureDeclaration, dynamicImport, getProperty, importDeclaration, setProperty, sourceMethods, wrapEval, wrapIdentifier } from './rewrite.script.js';
26
import {
27
dynamicImport,
28
importMeta,
29
identifier,
30
importDeclaration,
31
property,
32
unwrap,
33
wrapEval,
34
} from "./rewrite.script.js";
35
import { openDB } from "idb";
36
import { BareClient } from "@mercuryworkshop/bare-mux";
37
import EventEmitter from "events";
38
39
/**
40
* @typedef {import('../uv.js').UVConfig} UVConfig
41
*/
42
43
class Ultraviolet {
44
/**
45
*
46
* @param {UVConfig} [options]
47
*/
48
constructor(options = {}) {
49
this.prefix = options.prefix || "/service/";
50
//this.urlRegex = /^(#|about:|data:|mailto:|javascript:)/;
51
this.urlRegex = /^(#|about:|data:|mailto:)/;
52
this.rewriteUrl = options.rewriteUrl || this.rewriteUrl;
53
this.rewriteImport = options.rewriteImport || this.rewriteImport;
54
this.sourceUrl = options.sourceUrl || this.sourceUrl;
55
this.encodeUrl = options.encodeUrl || this.encodeUrl;
56
this.decodeUrl = options.decodeUrl || this.decodeUrl;
57
this.vanilla = "vanilla" in options ? options.vanilla : false;
58
this.meta = options.meta || {};
59
this.meta.base ||= undefined;
60
this.meta.origin ||= "";
61
this.bundleScript = options.bundle || "/uv.bundle.js";
62
this.handlerScript = options.handler || "/uv.handler.js";
63
this.clientScript =
64
options.client ||
65
(options.bundle &&
66
options.bundle.includes("uv.bundle.js") &&
67
options.bundle.replace("uv.bundle.js", "uv.client.js")) ||
68
"/uv.client.js";
69
this.configScript = options.config || "/uv.config.js";
70
this.meta.url ||= this.meta.base || "";
71
this.codec = Ultraviolet.codec;
72
this.html = new HTML(this);
73
this.css = new CSS(this);
74
this.js = new JS(this);
75
this.openDB = this.constructor.openDB;
76
this.master = "__uv";
77
this.dataPrefix = "__uv$";
78
this.attributePrefix = "__uv";
79
this.createHtmlInject = createHtmlInject;
80
this.createJsInject = createJsInject;
81
this.attrs = {
82
isUrl,
83
isForbidden,
84
isHtml,
85
isSrcset,
86
isStyle,
87
};
88
if (!this.vanilla) this.implementUVMiddleware();
89
this.cookie = {
90
validateCookie,
91
db: () => {
92
return db(this.constructor.openDB);
93
},
94
getCookies,
95
setCookies,
96
serialize,
97
setCookie,
98
};
99
}
100
/**
101
*
102
* @param {string} str Script being imported
103
* @param {string} src Script that is importing
104
* @param {*} meta
105
*/
106
rewriteImport(str, src, meta = this.meta) {
107
// use importiing script as the base
108
return this.rewriteUrl(str, {
109
...meta,
110
base: src,
111
});
112
}
113
rewriteUrl(str, meta = this.meta) {
114
str = new String(str).trim();
115
if (!str || this.urlRegex.test(str)) return str;
116
117
if (str.startsWith("javascript:")) {
118
return "javascript:" + this.js.rewrite(str.slice("javascript:".length));
119
}
120
121
try {
122
return (
123
meta.origin + this.prefix + this.encodeUrl(new URL(str, meta.base).href)
124
);
125
} catch (e) {
126
return meta.origin + this.prefix + this.encodeUrl(str);
127
}
128
}
129
sourceUrl(str, meta = this.meta) {
130
if (!str || this.urlRegex.test(str)) return str;
131
try {
132
return new URL(
133
this.decodeUrl(str.slice(this.prefix.length + meta.origin.length)),
134
meta.base
135
).href;
136
} catch (e) {
137
return this.decodeUrl(str.slice(this.prefix.length + meta.origin.length));
138
}
139
}
140
encodeUrl(str) {
141
return encodeURIComponent(str);
142
}
143
decodeUrl(str) {
144
return decodeURIComponent(str);
145
}
146
implementUVMiddleware() {
147
// HTML
148
attributes(this);
149
text(this);
150
injectHead(this);
151
// JS
152
importDeclaration(this);
153
dynamicImport(this);
154
importMeta(this);
155
property(this);
156
wrapEval(this);
157
identifier(this);
158
unwrap(this);
159
}
160
get rewriteHtml() {
161
return this.html.rewrite.bind(this.html);
162
}
163
get sourceHtml() {
164
return this.html.source.bind(this.html);
165
}
166
get rewriteCSS() {
167
return this.css.rewrite.bind(this.css);
168
}
169
get sourceCSS() {
170
return this.css.source.bind(this.css);
171
}
172
get rewriteJS() {
173
return this.js.rewrite.bind(this.js);
174
}
175
get sourceJS() {
176
return this.js.source.bind(this.js);
177
}
178
static codec = { xor, base64, plain };
179
static setCookie = setCookie;
180
static openDB = openDB;
181
static BareClient = BareClient;
182
static EventEmitter = EventEmitter;
183
}
184
185
export default Ultraviolet;
186
if (typeof self === "object") self.Ultraviolet = Ultraviolet;
187
188