PageSourceSearch

https://www.blackhillsinfosec.com/_content/WebsiteBuilder.Blazor/js/website-builder/theme.v4pu8qfbkk.js

js blackhillsinfosec.com collected 2026-10-01 10:38:27 UTC 6,232 bytes, 197 lines download raw bytes

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.