Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
QuiteAFancyEmerald
GitHub Repository: QuiteAFancyEmerald/Holy-Unblocker
Path: blob/master/views/assets/js/loader.js
11112 views
1
(() => {
2
const windowEventListeners = [],
3
documentEventListeners = [],
4
loadedModules = [];
5
let _addEventListener = addEventListener,
6
_document = document,
7
_window = window,
8
origin = location;
9
_addEventListener('keydown', (event) => {
10
if (event.ctrlKey && event.code === 'KeyM' && event.isTrusted) {
11
if (localStorage.getItem('{{hu-lts}}-loader-key') !== navigator.userAgent)
12
localStorage.setItem('{{hu-lts}}-loader-key', navigator.userAgent);
13
else localStorage.removeItem('{{hu-lts}}-loader-key');
14
_window.location.reload();
15
}
16
});
17
const setListeners = () => {
18
const currentWindow = _window,
19
currentDoc = _document;
20
currentWindow.Window.prototype.addEventListener = (...args) => {
21
windowEventListeners.push([...args]);
22
return _addEventListener.bind(currentWindow)(...args);
23
};
24
currentWindow.Document.prototype.addEventListener = (...args) => {
25
documentEventListeners.push([...args]);
26
return _addEventListener.bind(currentDoc)(...args);
27
};
28
};
29
setListeners();
30
const displayErrorPage = (overwrite = false, currentDoc = _document) => {
31
currentDoc.body.removeAttribute('style');
32
if (overwrite)
33
currentDoc.body.replaceWith(currentDoc.createElement('body'));
34
currentDoc.body.insertAdjacentHTML(
35
'afterbegin',
36
'<center><h1>403 Forbidden</h1></center><center>You don’t have permission to access this page.</center><hr><center>nginx</center>'
37
);
38
let head = currentDoc.createElement('head'),
39
title = currentDoc.createElement('title');
40
title.textContent = '500 Internal Server Error';
41
head.appendChild(title);
42
currentDoc.head.replaceWith(head);
43
if (currentDoc.currentScript) currentDoc.currentScript.remove();
44
};
45
if (
46
_window.localStorage.getItem('{{hu-lts}}-loader-key') !==
47
navigator.userAgent
48
)
49
return displayErrorPage();
50
const lastUpdated = '{{cacheVal}}',
51
retrieveUrl = (pathname) => {
52
let capturedUrl = new URL(pathname, origin),
53
capturedParams = new URLSearchParams(capturedUrl.search);
54
capturedParams.set('cache', lastUpdated);
55
capturedUrl.search = capturedParams.toString();
56
return capturedUrl;
57
};
58
59
const loadAttachments = () => {
60
if (_document.readyState === 'complete') loadPage()();
61
else addEventListener('load', loadPage());
62
_addEventListener('popstate', () => {
63
if (_window.location.href.includes('#')) return;
64
_window.console.clear();
65
loadPage(location, false)();
66
});
67
};
68
69
const loadPage =
70
(destination = origin, pushState = true) =>
71
() => {
72
_window
73
.fetch(
74
retrieveUrl(
75
destination.pathname.replace(/\/+/g, '/').replace(/\/$/, '') +
76
'.ico'
77
),
78
{ mode: 'same-origin' }
79
)
80
.then((response) => {
81
let i = windowEventListeners.length - 1;
82
for (; i >= 0; i--) {
83
_window.removeEventListener(...windowEventListeners[i]);
84
windowEventListeners.pop();
85
}
86
for (i = documentEventListeners.length - 1; i >= 0; i--) {
87
_document.removeEventListener(...documentEventListeners[i]);
88
documentEventListeners.pop();
89
}
90
if (destination !== _window.location && pushState) {
91
_window.console.clear();
92
if (response.status === 200) {
93
if (_window === window)
94
_window.history.pushState({}, '', retrieveUrl(destination));
95
} else return _window.location.assign(new URL(destination, origin));
96
}
97
response.blob().then((blob) => {
98
new _window.Response(
99
blob.stream().pipeThrough(new _window.DecompressionStream('gzip'))
100
)
101
.text()
102
.then((text) => {
103
((currentDoc, newDoc) => {
104
const deferScripts = [],
105
syncScripts = [];
106
let reachedEnd = false,
107
waitForHead = false,
108
headScripts = 0;
109
const bodyLoader = () => {
110
headScripts--;
111
if (waitForHead && headScripts <= 0) {
112
waitForHead = false;
113
currentDoc.body.replaceWith(recursiveClone(newDoc.body));
114
if (reachedEnd) loadNextScript(false)();
115
}
116
return waitForHead;
117
};
118
const loadNextScript = (isDefer, currentScript) => () => {
119
if (
120
!isDefer &&
121
currentScript &&
122
'head' ===
123
currentScript.parentElement.tagName.toLowerCase()
124
)
125
bodyLoader();
126
let nextScript = [...currentDoc.scripts].find(
127
(script) =>
128
script.getAttribute('itemprop') === 'script-insert' &&
129
script.defer === isDefer
130
);
131
if (nextScript) {
132
const replacement = isDefer
133
? deferScripts.shift()
134
: syncScripts.shift();
135
nextScript.replaceWith(replacement);
136
if (replacement.childNodes.length > 0)
137
loadNextScript(isDefer, replacement)();
138
} else if (!isDefer && !waitForHead) loadNextScript(true)();
139
else {
140
reachedEnd = true;
141
if (waitForHead) return;
142
[
143
...windowEventListeners,
144
...documentEventListeners,
145
].forEach((listenerParams) => {
146
if (listenerParams[0] === 'DOMContentLoaded')
147
listenerParams[1](
148
new _window.Event('DOMContentLoaded')
149
);
150
});
151
windowEventListeners.forEach((listenerParams) => {
152
if (listenerParams[0] === 'load')
153
listenerParams[1](new _window.Event('load'));
154
});
155
}
156
};
157
const recursiveClone = (node) => {
158
if (node.nodeType !== Node.ELEMENT_NODE) return node;
159
const nodeName = node.tagName.toLowerCase();
160
let src = { pathname: node.src || '' };
161
if (
162
node.src &&
163
'./'.indexOf(node.getAttribute('src')[0]) >= 0
164
) {
165
src = retrieveUrl(node.src);
166
node.setAttribute(
167
'src',
168
src.pathname + src.search + src.hash
169
);
170
}
171
if (['svg', 'xml'].includes(nodeName))
172
return node.cloneNode(1);
173
let elementCopy = currentDoc.createElement(nodeName);
174
let j = 0,
175
nodeList = [...node.attributes];
176
for (; j < nodeList.length; j++) {
177
let attrName = nodeList[j].nodeName;
178
let attrValue = nodeList[j].nodeValue;
179
elementCopy.setAttribute(attrName, attrValue || '');
180
if (attrName.toLowerCase() === 'href')
181
try {
182
new URL(attrValue);
183
} catch (e) {
184
if ('./?'.indexOf(attrValue[0]) !== -1)
185
if (
186
nodeName === 'a' &&
187
attrValue.indexOf('#') === -1
188
)
189
elementCopy.addEventListener('click', (event) => {
190
event.preventDefault();
191
if (attrValue === '{{route}}{{/}}')
192
attrValue = '{{route}}{{/index}}';
193
loadPage(new URL(attrValue, origin))();
194
});
195
else if (nodeName === 'link') {
196
src = retrieveUrl(node.href);
197
elementCopy.setAttribute(
198
'href',
199
src.pathname + src.search + src.hash
200
);
201
}
202
}
203
}
204
nodeList = [...node.childNodes];
205
for (j = 0; j < nodeList.length; j++)
206
elementCopy.appendChild(recursiveClone(nodeList[j]));
207
if ('script' === nodeName) {
208
if (
209
node.async ||
210
'module' === node.type.toLowerCase() ||
211
node.hasAttribute('data-module')
212
) {
213
if (
214
loadedModules.includes(
215
src.pathname || node.textContent
216
)
217
)
218
return currentDoc.createElement('script');
219
loadedModules.push(src.pathname || node.textContent);
220
if (node.async) return elementCopy;
221
}
222
const isDefer =
223
node.defer || 'module' === node.type.toLowerCase();
224
let replacement = currentDoc.createElement('script');
225
if (isDefer) replacement.setAttribute('defer', '');
226
replacement.setAttribute('itemprop', 'script-insert');
227
if (node.childNodes.length <= 0) {
228
elementCopy.addEventListener(
229
'load',
230
loadNextScript(isDefer, elementCopy)
231
);
232
elementCopy.addEventListener(
233
'error',
234
loadNextScript(isDefer, elementCopy)
235
);
236
}
237
if (isDefer) deferScripts.push(elementCopy);
238
else {
239
syncScripts.push(elementCopy);
240
if ('head' === node.parentElement.tagName.toLowerCase())
241
headScripts++;
242
}
243
return replacement;
244
} else if (['style', 'link'].includes(nodeName)) {
245
if (
246
'link' === nodeName &&
247
!/^stylesheet$/i.test(node.rel)
248
)
249
return elementCopy;
250
else if (node.childNodes.length <= 0) {
251
elementCopy.addEventListener('load', bodyLoader);
252
elementCopy.addEventListener('error', bodyLoader);
253
if ('head' === node.parentElement.tagName.toLowerCase())
254
headScripts++;
255
}
256
}
257
/*
258
if (node.id === 'newtab')
259
elementCopy.addEventListener('click', () => {
260
origin = new URL(location.href);
261
_window = open();
262
_addEventListener = _addEventListener.bind(_window);
263
_document = _window.document;
264
setListeners();
265
loadAttachments();
266
});
267
*/
268
return elementCopy;
269
};
270
let currentType = currentDoc.doctype,
271
newType = newDoc.doctype,
272
currentDocNode = currentDoc.documentElement,
273
newDocNode = newDoc.documentElement;
274
if (currentType)
275
if (newType) currentType.replaceWith(newType);
276
else currentType.remove();
277
else if (newType) currentDoc.prepend(newType);
278
if (currentDocNode)
279
if (newDocNode) {
280
if (
281
currentDocNode.tagName === newDocNode.tagName &&
282
currentDoc.head &&
283
newDoc.head &&
284
currentDoc.body &&
285
newDoc.body
286
) {
287
[...currentDocNode.attributes].forEach((attribute) => {
288
currentDocNode.removeAttribute(attribute.nodeName);
289
});
290
[...newDocNode.attributes].forEach((attribute) => {
291
currentDocNode.setAttribute(
292
attribute.nodeName,
293
attribute.nodeValue || ''
294
);
295
});
296
waitForHead = true;
297
currentDoc.head.replaceWith(
298
recursiveClone(newDoc.head)
299
);
300
} else
301
currentDocNode.replaceWith(recursiveClone(newDocNode));
302
} else currentDocNode.remove();
303
else if (newDocNode)
304
currentDocNode.appendChild(recursiveClone(newDocNode));
305
306
loadNextScript(false)();
307
})(
308
_document,
309
new _window.DOMParser().parseFromString(text, 'text/html')
310
);
311
});
312
});
313
})
314
.catch((error) => {
315
_window.console.log(error);
316
displayErrorPage(true);
317
});
318
};
319
loadAttachments();
320
})();
321
322