1(function (global) { 2 "use strict"; 3 4 var STORAGE_KEY = "bhis.theme.mode"; 5 var restoring = false; 6 7 function readStored() { 8 try { 9 return global.localStorage.getItem(STORAGE_KEY); 10 } catch { 11 return null; 12 } 13 } 14 15 function writeStored(mode) { 16 try { 17 global.localStorage.setItem(STORAGE_KEY, mode); 18 } catch { 19 /* private browsing */ 20 } 21 } 22 23 function resolveTheme() { 24 var stored = readStored(); 25 if (stored === "light" || stored === "dark") { 26 return stored; 27 } 28 // First-time visitors default to light mode (rather than following the OS preference). 29 return "light"; 30 } 31 32 function refreshAppearance() { 33 // Re-read --site-bg-style (and palette tokens) after Blazor swaps per-page <style> tags. 34 // Hex hides itself when the token is binary-aura; aura pauseAndClear()s when leaving aura. 35 if (global.bhisHexBackground && typeof global.bhisHexBackground.refreshTheme === "function") { 36 global.bhisHexBackground.refreshTheme(); 37 } 38 if (global.bhisBinaryAura && typeof global.bhisBinaryAura.refreshTheme === "function") { 39 global.bhisBinaryAura.refreshTheme(); 40 } 41 if (global.bhisBuffaloTrail && typeof global.bhisBuffaloTrail.refreshTheme === "function") { 42 global.bhisBuffaloTrail.refreshTheme(); 43 } 44 } 45 46 function clearLife() { 47 if (global.bhisHexBackground && typeof global.bhisHexBackground.clearLife === "function") { 48 global.bhisHexBackground.clearLife(); 49 } 50 } 51 52 function clearPreview() { 53 var preview = global.document.getElementById("theme-live-preview"); 54 if (!preview) { 55 return false; 56 } 57 58 preview.remove(); 59 refreshAppearance(); 60 return true; 61 } 62 63 function applyPreview(css) { 64 var el = global.document.getElementById("theme-live-preview"); 65 if (!el) { 66 el = global.document.createElement("style"); 67 el.id = "theme-live-preview"; 68 global.document.head.appendChild(el); 69 } 70 71 el.textContent = css || ""; 72 refreshAppearance(); 73 } 74 75 function syncSavedTheme(stylesheetUrl) { 76 // Drop unsaved editor preview so published stylesheet wins again. 77 var preview = global.document.getElementById("theme-live-preview"); 78 if (preview) { 79 preview.remove(); 80 } 81 82 var link = global.document.getElementById("site-theme-stylesheet"); 83 if (link && stylesheetUrl) { 84 link.onload = function () { 85 refreshAppearance(); 86 }; 87 link.href = stylesheetUrl; 88 if (link.sheet) { 89 refreshAppearance(); 90 } 91 return; 92 } 93 94 refreshAppearance(); 95 } 96 97 function apply(theme) { 98 var mode = theme === "light" ? "light" : "dark"; 99 var root = global.document.documentElement; 100 restoring = true; 101 try { 102 root.setAttribute("data-theme", mode); 103 root.setAttribute("data-bs-theme", mode); 104 root.style.colorScheme = mode; 105 } finally { 106 restoring = false; 107 } 108 writeStored(mode); 109 refreshAppearance(); 110 return mode; 111 } 112 113 function isDark() { 114 return global.document.documentElement.getAttribute("data-theme") !== "light"; 115 } 116 117 function toggle() { 118 return apply(isDark() ? "light" : "dark"); 119 } 120 121 /** 122 * Blazor can re-render <html> from App.razor and strip JS-set data-theme / data-bs-theme. 123 * Without those attributes, site-theme.css (html[data-theme="â¦"]) stops applying â white page, 124 * default tokens, and a jarring hex/aura refresh that looks like a "giant" unloaded theme. 125 */ 126 function ensureThemeAttribute() { 127 if (restoring) { 128 return; 129 } 130 131 var root = global.document.documentElement; 132 var current = root.getAttribute("data-theme"); 133 if (current === "light" || current === "dark") { 134 if (root.getAttribute("data-bs-theme") !== current) { 135 restoring = true; 136 try { 137 root.setAttribute("data-bs-theme", current); 138 root.style.colorScheme = current; 139 } finally { 140 restoring = false;
141 } 142 } 143 return; 144 } 145 146 apply(resolveTheme()); 147 } 148 149 function watchThemeAttribute() { 150 if (!global.MutationObserver || !global.document || !global.document.documentElement) { 151 return; 152 } 153 154 var observer = new MutationObserver(function () { 155 ensureThemeAttribute(); 156 }); 157 observer.observe(global.document.documentElement, { 158 attributes: true, 159 attributeFilter: ["data-theme", "data-bs-theme"] 160 }); 161 162 // Blazor enhanced navigations / circuit reconnects. 163 global.document.addEventListener("enhancedload", ensureThemeAttribute); 164 if (global.Blazor && typeof global.Blazor.addEventListener === "function") { 165 try { 166 global.Blazor.addEventListener("enhancedload", ensureThemeAttribute); 167 } catch { 168 /* older hosts */ 169 } 170 } 171 172 // Cheap backstop if something strips attributes between observer ticks. 173 global.setInterval(ensureThemeAttribute, 2000); 174 } 175 176 global.bhisTheme = { 177 apply: apply, 178 applyPreview: applyPreview, 179 clearPreview: clearPreview, 180 refreshAppearance: refreshAppearance, 181 clearLife: clearLife, 182 syncSavedTheme: syncSavedTheme, 183 ensureThemeAttribute: ensureThemeAttribute, 184 get: function () { 185 // Match resolveTheme()/boot script: unset means light. 186 return global.document.documentElement.getAttribute("data-theme") || "light"; 187 }, 188 isDark: isDark, 189 toggle: toggle, 190 init: function () { 191 return apply(resolveTheme()); 192 } 193 }; 194 195 apply(resolveTheme()); 196 watchThemeAttribute(); 197})(window);
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.