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