mirror of
https://github.com/hugo-fixit/FixIt.git
synced 2026-08-24 15:28:57 +00:00
17d7bc1781
* feat(assets): refactor SCSS variables with Hugo config via hugo:vars Use Hugo's hugo:vars mechanism (v0.161.0+) to configure SCSS variables via [params.appearance] in hugo.toml, replacing the override.scss file. - Add [params.appearance] config section in hugo.toml - Create scss-vars.html partial for SCSS default values - Pass vars to toCSS via head/index.html - Rewrite _variables.scss to use @use "hugo:vars" as h with !default - Update all 20 consumer files from @use "override" to @use "variables" - Delete override.scss - Add admonition mixin in core/mixins/_admonition.scss - Update deprecation detection to use fileExists * refactor(assets): standardize module setup() and simplify main.ts init - Add setup() method to all modules (menu, theme, search, enc, misc, events) - Rename initMenu to setup, initMenuDesktop/initMenuMobile to initDesktop/initMobile - Rename initSearch, initFixItDecryptor to setup - Standardize setup() position at end of each module class and interface - Simplify main.ts init sequence to uniform setup() calls * refactor(assets): replace config.template.scss with hugo:vars/internal - Delete config.template.scss and its ExecuteAsTemplate pipeline - Pass internal config (base URL, logo, loading) via hugo:vars/internal namespace - Move CSS custom properties to _root.scss using set-fi-vars mixin - Simplify _variables.scss by removing config namespace dependency - Update CLAUDE.md to reflect new SCSS architecture * style(i18n): fix spacing in Korean translation strings * fix(assets): resolve dead SCSS config keys and deduplicate defaults - Wire up 5 config keys with v.$ references: menu-active-color, tag-cloud-start, tag-cloud-end, tag-cloud-end-dark, pagination-link-color-dark (were reading from SCSS vars, ignoring hugo:vars overrides) - Remove dead !default flags from all v.$ references (hugo:vars always provides values, making !default unreachable) - Compute derived defaults in scss-vars.html from base values instead of hardcoding duplicates - Extract admonition mixin set-fi-vars map to shared $vars variable
86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
import type { CoreService, ThemeService } from '../core/tokens'
|
|
import { eventBus } from '../core/event-bus'
|
|
|
|
/**
|
|
* Theme module — color scheme switching and theme-color meta tag management.
|
|
*
|
|
* Responsibilities:
|
|
* - Toggle between light, dark, and auto color schemes.
|
|
* - Update `<meta name="theme-color">` based on current scheme.
|
|
* - Persist user preference to localStorage.
|
|
*/
|
|
export class ThemeModule implements ThemeService {
|
|
private readonly mql = window.matchMedia('(prefers-color-scheme: dark)')
|
|
|
|
constructor(private readonly core: CoreService) {}
|
|
|
|
/**
|
|
* Apply a theme mode and emit the `fixit:switch-theme` event.
|
|
* @param mode - `'auto'`, `'light'`, or `'dark'`.
|
|
* @param persist - Whether to save the choice to localStorage (default: `true`).
|
|
*/
|
|
setThemeMode(mode: string, persist = true) {
|
|
const prevIsDark = this.core.isDark
|
|
this.core.themeMode = mode
|
|
document.documentElement.dataset.themeMode = mode
|
|
this.core.isDark = mode === 'auto' ? this.mql.matches : mode === 'dark'
|
|
|
|
if (persist) {
|
|
window.localStorage?.setItem('theme-mode', mode)
|
|
}
|
|
|
|
eventBus.emit('fixit:switch-theme', {
|
|
isDark: this.core.isDark,
|
|
mode,
|
|
isChanged: prevIsDark !== this.core.isDark,
|
|
})
|
|
}
|
|
|
|
/** Sync the `<meta name="theme-color">` tag with the current color scheme. */
|
|
initThemeColor() {
|
|
const $meta = document.querySelector<HTMLMetaElement>('[name="theme-color"]')
|
|
if (!$meta)
|
|
return
|
|
const applyThemeColor = (isDark: boolean) => {
|
|
$meta.content = isDark ? $meta.dataset.dark! : $meta.dataset.light!
|
|
}
|
|
eventBus.on('fixit:switch-theme', ({ detail }) => {
|
|
if (!detail.isChanged)
|
|
return
|
|
applyThemeColor(detail.isDark)
|
|
})
|
|
applyThemeColor(this.core.isDark)
|
|
}
|
|
|
|
/** Initialize the theme switch button cycle and system preference listener. */
|
|
initSwitchTheme() {
|
|
const modes = ['auto', 'light', 'dark'] as const
|
|
|
|
document.querySelectorAll('.theme-switch').forEach(($themeSwitch: Element) => {
|
|
$themeSwitch.addEventListener('click', () => {
|
|
const currentIndex = modes.indexOf(this.core.themeMode as typeof modes[number])
|
|
const nextMode = modes[(currentIndex + 1) % modes.length]
|
|
this.setThemeMode(nextMode)
|
|
}, false)
|
|
})
|
|
|
|
this.mql.addEventListener('change', (e: MediaQueryListEvent) => {
|
|
if (this.core.themeMode !== 'auto')
|
|
return
|
|
const prevIsDark = this.core.isDark
|
|
this.core.isDark = e.matches
|
|
eventBus.emit('fixit:switch-theme', {
|
|
isDark: this.core.isDark,
|
|
mode: 'auto',
|
|
isChanged: prevIsDark !== this.core.isDark,
|
|
})
|
|
})
|
|
}
|
|
|
|
/** Initialize theme color and switch handler. */
|
|
setup() {
|
|
this.initThemeColor()
|
|
this.initSwitchTheme()
|
|
}
|
|
}
|