Files
ARTEX-chixuweihu/web/src/scripts/theme-boot.tsx
T
Autumn-27andClaude Opus 4.8 0ef8561411 chore: ARTEX 初始化
ARTEX — AI 自主渗透测试系统(Go 后端 + Next.js 前端,单二进制内嵌)。

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-26 04:27:45 -04:00

114 lines
4.5 KiB
TypeScript

/**
* Boot script that reads user preference values (theme mode, theme preset,
* content layout, navbar style) from cookies or localStorage based on the
* configured persistence mode.
*
* Runs early in <head> to apply the correct data attributes before hydration,
* preventing layout or theme flicker and keeping RootLayout fully static.
*/
import { PREFERENCE_DEFAULTS, PREFERENCE_PERSISTENCE } from "@/lib/preferences/preferences-config";
export function ThemeBootScript() {
const persistence = JSON.stringify({
theme_mode: PREFERENCE_PERSISTENCE.theme_mode,
theme_preset: PREFERENCE_PERSISTENCE.theme_preset,
font: PREFERENCE_PERSISTENCE.font,
content_layout: PREFERENCE_PERSISTENCE.content_layout,
navbar_style: PREFERENCE_PERSISTENCE.navbar_style,
sidebar_variant: PREFERENCE_PERSISTENCE.sidebar_variant,
sidebar_collapsible: PREFERENCE_PERSISTENCE.sidebar_collapsible,
});
const defaults = JSON.stringify({
theme_mode: PREFERENCE_DEFAULTS.theme_mode,
theme_preset: PREFERENCE_DEFAULTS.theme_preset,
font: PREFERENCE_DEFAULTS.font,
content_layout: PREFERENCE_DEFAULTS.content_layout,
navbar_style: PREFERENCE_DEFAULTS.navbar_style,
sidebar_variant: PREFERENCE_DEFAULTS.sidebar_variant,
sidebar_collapsible: PREFERENCE_DEFAULTS.sidebar_collapsible,
});
const code = `
(function () {
try {
var root = document.documentElement;
var PERSISTENCE = ${persistence};
var DEFAULTS = ${defaults};
function readCookie(name) {
var match = document.cookie.split("; ").find(function(c) {
return c.startsWith(name + "=");
});
return match ? decodeURIComponent(match.split("=")[1]) : null;
}
function readLocal(name) {
try {
return window.localStorage.getItem(name);
} catch (e) {
return null;
}
}
function readPreference(key, fallback) {
var mode = PERSISTENCE[key];
var value = null;
if (mode === "localStorage") {
value = readLocal(key);
}
if (!value && (mode === "client-cookie" || mode === "server-cookie")) {
value = readCookie(key);
}
if (!value || typeof value !== "string") {
return fallback;
}
return value;
}
var rawMode = readPreference("theme_mode", DEFAULTS.theme_mode);
var rawPreset = readPreference("theme_preset", DEFAULTS.theme_preset);
var rawFont = readPreference("font", DEFAULTS.font);
var rawContentLayout = readPreference("content_layout", DEFAULTS.content_layout);
var rawNavbarStyle = readPreference("navbar_style", DEFAULTS.navbar_style);
var rawSidebarVariant = readPreference("sidebar_variant", DEFAULTS.sidebar_variant);
var rawSidebarCollapsible = readPreference("sidebar_collapsible", DEFAULTS.sidebar_collapsible);
var isValidMode = rawMode === "dark" || rawMode === "light" || rawMode === "system";
var mode = isValidMode ? rawMode : DEFAULTS.theme_mode;
var resolvedMode =
mode === "system" && window.matchMedia
? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light")
: mode;
var preset = rawPreset || DEFAULTS.theme_preset;
var font = rawFont || DEFAULTS.font;
var contentLayout = rawContentLayout || DEFAULTS.content_layout;
var navbarStyle = rawNavbarStyle || DEFAULTS.navbar_style;
var sidebarVariant = rawSidebarVariant || DEFAULTS.sidebar_variant;
var sidebarCollapsible = rawSidebarCollapsible || DEFAULTS.sidebar_collapsible;
root.classList.toggle("dark", resolvedMode === "dark");
root.setAttribute("data-theme-mode", mode);
root.setAttribute("data-theme-preset", preset);
root.setAttribute("data-font", font);
root.setAttribute("data-content-layout", contentLayout);
root.setAttribute("data-navbar-style", navbarStyle);
root.setAttribute("data-sidebar-variant", sidebarVariant);
root.setAttribute("data-sidebar-collapsible", sidebarCollapsible);
root.style.colorScheme = resolvedMode === "dark" ? "dark" : "light";
} catch (e) {
console.warn("ThemeBootScript error:", e);
}
})();
`;
/* biome-ignore lint/security/noDangerouslySetInnerHtml: required for pre-hydration boot script */
return <script dangerouslySetInnerHTML={{ __html: code }} />;
}