Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/lib/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ const DARK_QUERY = '(prefers-color-scheme: dark)';

/**
* Inline <head> script that sets data-theme before the first paint, so a stored preference
* applies without a flash. Keep it in step with applyTheme below.
* applies without a flash. Keep it, and the literal storage key and media query inside it, in
* step with THEME_STORAGE_KEY, DARK_QUERY and applyTheme below.
*
* Written out as a fixed string rather than built by interpolating those constants into it:
* this is injected into <head> via dangerouslySetInnerHTML, so splicing a value into it, even
* this module's own constant, is exactly the "code built from an interpolated value" pattern
* CodeQL's js/bad-code-sanitization flags (a later, easy-to-miss change to either constant, such
* as reading one from configuration, would turn this into a real DOM-based injection).
*/
export const THEME_SCRIPT = `(function(){var p;try{p=localStorage.getItem(${JSON.stringify(THEME_STORAGE_KEY)})}catch(e){}var d=p==='dark'||(p!=='light'&&matchMedia(${JSON.stringify(DARK_QUERY)}).matches);document.documentElement.setAttribute('data-theme',d?'dark':'light')})()`;
export const THEME_SCRIPT = `(function(){var p;try{p=localStorage.getItem("orcahouse-ui.theme")}catch(e){}var d=p==='dark'||(p!=='light'&&matchMedia("(prefers-color-scheme: dark)").matches);document.documentElement.setAttribute('data-theme',d?'dark':'light')})()`;

export function readThemePreference(): ThemePreference {
try {
Expand Down
Loading