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