1// Host/ICV/wwwroot/js/auth-scripts-loader.js 2// Loads the authenticated-only script set on demand after a SPA login. 3// App.razor omits these scripts on anonymous routes (login/signup/invitation) to keep the 4// cold login fast; because login completes via SPA navigation (no full reload), 5// nothing else would ever load them. Idempotent: skips scripts already in the DOM 6// (cold loads of authenticated routes emit them as regular <script> tags). 7// Order inside the list is preserved via s.async = false (dynamically injected 8// scripts are async by default, which would break dependent pairs like 9// html2canvas -> screenshotHelper and jquery -> jquery.signalR -> signalr-legacy). 10(function () { 11 function authScriptUrls(v) { 12 // Use raw concatenation (no encodeURIComponent) so the query string matches the 13 // ?v=@v suffix that App.razor emits on <script> tags. AssemblyInformationalVersion 14 // can contain '+' (e.g. "1.0.4+abc1234") â encodeURIComponent would turn that into 15 // %2B, producing a different cache key from the Razor-rendered URLs and defeating 16 // both the browser HTTP cache and the prefetch links added on anonymous routes. 17 var q = '?v=' + (v || '0'); 18 return [ 19 // TinyMCE intentionally NOT here â tinymce-blazor.js lazy-loads its own copy. 20 // Chart.js intentionally NOT here â chartHelper.js awaits 21 // window.ensureChartsLoaded() (App.razor) before creating a chart, so it only 22 // downloads when a Dashboard chart widget actually mounts, not on every login. 23 // libsodium-sumo.js / libsodium-wrappers.js / e2e-crypto.js intentionally NOT 24 // here either â E2ECryptoService.cs awaits window.ensureLibsodiumLoaded() 25 // (App.razor) before every e2eCrypto.* call, so the ~1.2 MB E2E crypto payload 26 // only downloads when chat E2E is actually used, not on every login. 27 'cacheData.js' + q, 28 'DownloadFileViaURLLInk.js' + q, 29 'js/navMenuHelper.js' + q, 30 'js/timelineHelper.js' + q, 31 'js/chat.js' + q, 32 'js/calendar-picker.js' + q, 33 'js/tab-overflow.js' + q, 34 'js/back-to-top.js' + q, 35 'lib/html2canvas.min.js' + q, 36 'js/screenshotHelper.js' + q, 37 'lib/livekit-client.umd.min.js' + q, 38 'js/livekit-interop.js' + q, 39 'lib/hls.min.js' + q, 40 'js/hls-player-interop.js' + q, 41 'js/acs-teams-interop.js' + q, 42 'js/zoom-meeting-interop.js' + q, 43 'lib/jquery-3.7.1.min.js' + q, 44 'lib/jquery.signalR/jquery.signalR-2.4.3.min.js' + q, 45 'js/signalr-legacy.js' + q, 46 'js/collapse.js' + q, 47 '_content/MinForening.CompositeModule.Superadmin/js/adminPageBuilder.js' + q, 48 '_content/MinForening.CompositeModule.Superadmin/customFieldsInfiniteScroll.js' + q, 49 '_content/Limitech.CompositeModule.ProcessConfigurator/limitech-download.js' + q 50 ]; 51 } 52 53 function moduleUrls(v) { 54 var q = '?v=' + (v || '0'); 55 return ['DownloadFileFromLocal.js' + q, 'Clipboard.js' + q]; 56 } 57 58 function alreadyLoaded(url) { 59 var path = url.split('?')[0]; 60 var scripts = document.querySelectorAll('script[src]'); 61 for (var i = 0; i < scripts.length; i++) { 62 var src = scripts[i].getAttribute('src') || ''; 63 if (src.split('?')[0] === path) return true; 64 } 65 return false; 66 } 67 68 function inject(url, isModule) { 69 return new Promise(function (resolve) { 70 if (alreadyLoaded(url)) { resolve(); return; } 71 var s = document.createElement('script'); 72 s.src = url; 73 s.async = false; // preserve insertion-order execution for dependent pairs 74 if (isModule) s.type = 'module'; 75 s.onload = resolve; 76 s.onerror = function () { 77 console.warn('auth-scripts-loader: failed to load ' + url); 78 resolve(); // never block the chain on one missing optional script 79 }; 80 document.body.appendChild(s); 81 }); 82 } 83 84 var loadPromise = null; 85 window.ensureAuthenticatedScripts = function () { 86 if (window.__authScriptsLoaded) return Promise.resolve(); 87 if (loadPromise) return loadPromise; 88 var v = window.__assetVersion || '0'; 89 var all = authScriptUrls(v).map(function (u) { return inject(u, false); }) 90 .concat(moduleUrls(v).map(function (u) { return inject(u, true); })); 91 loadPromise = Promise.all(all).then(function () { 92 window.__authScriptsLoaded = true; 93 }); 94 return loadPromise; 95 }; 96})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.