···141141 save: "Save changes",
142142 detailsSaved: "Wiki details saved.",
143143 theme: "Theme",
144144- themeModeLabel: "Theme behavior",
145145- themeReader: "Reader's choice",
146146- themeReaderHint: "Visitors see the wiki in their preferred theme.",
147147- themeEnforce: "Enforce a theme",
148148- themeEnforceHint: "All visitors see the wiki in the theme you pick below.",
149149- themePresetLabel: "Preset",
144144+ themeChoiceLabel: "Theme",
145145+ themeReaderDefault: "User's default",
150146 themeSaved: "Theme saved.",
151147 dangerZone: "Delete this wiki",
152148 deleteWikiDescription:
+2-7
src/lib/i18n/fr.ts
···143143 save: "Enregistrer les modifications",
144144 detailsSaved: "Détails du wiki enregistrés.",
145145 theme: "Thème",
146146- themeModeLabel: "Comportement du thème",
147147- themeReader: "Choix du lecteur",
148148- themeReaderHint: "Les visiteurs voient le wiki dans leur thème préféré.",
149149- themeEnforce: "Imposer un thème",
150150- themeEnforceHint:
151151- "Tous les visiteurs voient le wiki dans le thème choisi ci-dessous.",
152152- themePresetLabel: "Préréglage",
146146+ themeChoiceLabel: "Thème",
147147+ themeReaderDefault: "Choix du lecteur",
153148 themeSaved: "Thème enregistré.",
154149 dangerZone: "Supprimer ce wiki",
155150 deleteWikiDescription:
···11-import {
22- resolveTheme,
33- type ThemeName,
44- type UserTheme,
55- type WikiThemeMode,
66-} from "./resolve.ts";
11+import type { ThemeName, UserTheme, WikiThemeMode } from "./resolve.ts";
72import { type Theme, themes } from "./themes.ts";
8394const kebab = (s: string): string =>
···9994}
1009510196/**
102102- * Wraps wiki-content HTML in a div that overrides the chrome theme when the
103103- * wiki enforces its own. In reader mode the content inherits via CSS cascade
104104- * and no wrapper is emitted. Prose vars set on <body> reference our base
105105- * tokens, so they automatically follow the wiki's overrides in this scope.
9797+ * Inline style content for the wiki-content area when the wiki enforces a
9898+ * theme. Sets the theme tokens AND the wrapper's own background/color so the
9999+ * area visibly switches palette (otherwise inner text follows the wiki theme
100100+ * via CSS vars, but the wrapper background bleeds the user theme through).
101101+ *
102102+ * Returns "" in reader mode so the area inherits chrome theme via cascade.
106103 */
107107-export function wrapWikiContent(
108108- html: string,
109109- args: { wikiThemeMode?: WikiThemeMode; wikiTheme?: ThemeName } = {},
104104+export function wikiThemeStyleAttr(
105105+ wikiThemeMode: WikiThemeMode | undefined,
106106+ wikiTheme: ThemeName | undefined,
110107): string {
111111- const theme = resolveTheme({ scope: "wikiContent", ...args });
112112- if (!theme) return html;
113113- return `<div style="${themeStyleAttr(theme)}">${html}</div>`;
108108+ if (wikiThemeMode !== "enforce" || !wikiTheme) return "";
109109+ const theme = themes[wikiTheme];
110110+ if (!theme) return "";
111111+ return `${themeStyleAttr(theme)}; background-color: var(--bg); color: var(--text); color-scheme: ${wikiTheme};`;
114112}
+8-2
src/views/theme/index.ts
···11-export { themeRootStyle, wrapWikiContent } from "./apply.ts";
22-export { resolveUserTheme, USER_THEMES, type UserTheme } from "./resolve.ts";
11+export { themeRootStyle, wikiThemeStyleAttr } from "./apply.ts";
22+export {
33+ resolveUserTheme,
44+ type ThemeName,
55+ USER_THEMES,
66+ type UserTheme,
77+ type WikiThemeMode,
88+} from "./resolve.ts";
39export {
410 dangerButtonClass,
511 dangerSmallButtonClass,
+1-26
src/views/theme/resolve.ts
···11-import { type Theme, themes } from "./themes.ts";
11+import type { themes } from "./themes.ts";
2233export const USER_THEMES = ["light", "dark", "system"] as const;
44export type UserTheme = (typeof USER_THEMES)[number];
···12121313/** Named theme keys present in `themes` (light/dark presets). */
1414export type ThemeName = keyof typeof themes;
1515-1616-type ThemeScope = "chrome" | "wikiContent";
1717-1818-type ResolveThemeArgs = {
1919- scope: ThemeScope;
2020- wikiThemeMode?: WikiThemeMode;
2121- wikiTheme?: ThemeName;
2222-};
2323-2424-/**
2525- * Returns the palette an element should apply via inline style, or null when
2626- * the element should inherit from its cascading parent.
2727- *
2828- * Chrome scope is always handled by the body <style> block (which natively
2929- * supports system preference via @media), so resolveTheme returns null for it.
3030- * Wiki-content scope returns the wiki's theme only when it enforces an
3131- * override; otherwise it inherits the chrome theme via cascade.
3232- */
3333-export function resolveTheme(args: ResolveThemeArgs): Theme | null {
3434- if (args.scope === "chrome") return null;
3535- if (args.wikiThemeMode === "enforce" && args.wikiTheme) {
3636- return themes[args.wikiTheme];
3737- }
3838- return null;
3939-}
40154116export function resolveUserTheme(
4217 cookieHeader: string | null | undefined,