From 6d2c510148b0029c79e76d1b7dd56bffb7e33504 Mon Sep 17 00:00:00 2001 From: lutinglt Date: Sun, 7 Jun 2026 19:36:02 +0800 Subject: [PATCH] organize code --- CONTRIBUTING.md | 4 +- CONTRIBUTING_CN.md | 3 +- package.json | 1 - src/core/css.ts | 4 +- src/vite-plugin/index.ts | 23 ++-- src/vite-plugin/themeConfig.ts | 25 +++-- theme.config.ts | 200 +++++++++++++++++---------------- tsconfig.json | 1 - vite.config.ts | 3 +- 9 files changed, 141 insertions(+), 123 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09bc754..ff662fa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -115,8 +115,8 @@ Please add your author info at the top of the color theme file so Issue reporter It is recommended to use `defineTheme` with the `ThemeColor` type to define theme colors. The framework will automatically compute and generate all Gitea CSS variables. -Color calculation functions can be imported from `@lutinglt/gitea-github-theme/core` (`scaleColorLight`, `rgba`), -or use the `color2k` library for additional color manipulation. +Color calculation functions can be imported from `@lutinglt/gitea-github-theme/core` (`scaleColorLight`, `rgba`), or use +the `color2k` library for additional color manipulation. Example: `themes/my-theme.ts` diff --git a/CONTRIBUTING_CN.md b/CONTRIBUTING_CN.md index 5ff16f0..915845d 100644 --- a/CONTRIBUTING_CN.md +++ b/CONTRIBUTING_CN.md @@ -106,7 +106,8 @@ bun commit 推荐使用 `defineTheme` 配合 `ThemeColor` 类型来定义主题颜色, 框架会自动计算生成所有 Gitea CSS 变量. -颜色计算函数可从 `@lutinglt/gitea-github-theme/core` 导入 `scaleColorLight` 和 `rgba`, 或使用 `color2k` 库进行额外颜色操作. +颜色计算函数可从 `@lutinglt/gitea-github-theme/core` 导入 `scaleColorLight` 和 `rgba`, 或使用 `color2k` +库进行额外颜色操作. 例: `themes/主题名称.ts` diff --git a/package.json b/package.json index ed2627a..27475d6 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "bun": ">=1.3.14" }, "exports": { - "./theme.config.ts": "./theme.config.ts", "./core": "./src/index.ts", "./vite-plugin": "./src/vite-plugin/index.ts", "./styles": "./styles/index.ts", diff --git a/src/core/css.ts b/src/core/css.ts index c6ec8c6..01ef98c 100644 --- a/src/core/css.ts +++ b/src/core/css.ts @@ -49,8 +49,8 @@ export function css(strings: TemplateStringsArray, ...values: CSSInterpolation[] * * 合并按参数顺序排列 */ -export function cssCombine(...styles: CSSString[]): CSSString { - return styles.join("\n") as CSSString; +export function cssCombine(...styles: (CSSString | undefined)[]): CSSString { + return styles.filter(Boolean).join("\n") as CSSString; } /** cssStyle 用于 css 模板字符串的插值 diff --git a/src/vite-plugin/index.ts b/src/vite-plugin/index.ts index 6e55218..0cbfe0c 100644 --- a/src/vite-plugin/index.ts +++ b/src/vite-plugin/index.ts @@ -19,8 +19,10 @@ import { transform } from "lightningcss"; import type { PluginOption } from "vite"; -import { createTheme, createThemeMetaInfo, type CSSString, type GiteaThemeMeta, type Theme } from "../core"; +import type { CSSString, GiteaThemeMeta, Theme } from "../core"; +import { createTheme, createThemeMetaInfo, cssCombine } from "../core"; import { compileCSS } from "../vanilla-extract"; +import type { ThemeConfig } from "./themeConfig"; import { buildFullDisplayName, buildFullThemeName } from "./utils"; const VIRTUAL_ID = "virtual:gitea-github-theme-placeholder"; @@ -33,7 +35,7 @@ type ThemeEntry = { styles?: CSSString; }; -export function giteaGitHubTheme(): PluginOption { +export function giteaGitHubTheme(themeConfig: ThemeConfig): PluginOption { return { name: "lutinglt-gitea-github-theme", @@ -47,17 +49,15 @@ export function giteaGitHubTheme(): PluginOption { return { build: { rolldownOptions: { input: VIRTUAL_ID } } }; }, - async generateBundle(this, _options, bundle) { + generateBundle(this, _options, bundle) { // 清除占位入口产物 for (const key of Object.keys(bundle)) { delete bundle[key]; } // 1. 解析主题配置 - const themeConfig = (await import("@lutinglt/gitea-github-theme/theme.config.ts")).default; const themeEntries: ThemeEntry[] = []; - - for (const themeSeries of themeConfig) { + for (const themeSeries of themeConfig.themeSeries) { for (const [themeKeyName, entry] of Object.entries(themeSeries.themes)) { const name = entry.themeName ?? themeKeyName; entry.themeName = buildFullThemeName(themeSeries, name); @@ -69,7 +69,7 @@ export function giteaGitHubTheme(): PluginOption { colorblindType: entry.colorblindType, }, theme: entry.theme, - styles: themeSeries.styles, + styles: cssCombine(themeSeries.styles, entry.styles), }); } // 处理自动主题 @@ -93,8 +93,13 @@ export function giteaGitHubTheme(): PluginOption { } // 2. 编译公共样式 - const rawStyles = Buffer.from((await import("@lutinglt/gitea-github-theme/styles")).default); - const globalStyles = transform({ filename: "globalStyles.css", code: rawStyles, minify: true }).code.toString(); + const globalStyles = themeConfig.globalStyles + ? transform({ + filename: "globalStyles.css", + code: Buffer.from(themeConfig.globalStyles), + minify: true, + }).code.toString() + : ""; // 3. 编译每个主题的 CSS 并输出 for (const entry of themeEntries) { diff --git a/src/vite-plugin/themeConfig.ts b/src/vite-plugin/themeConfig.ts index 597ee18..b41e33d 100644 --- a/src/vite-plugin/themeConfig.ts +++ b/src/vite-plugin/themeConfig.ts @@ -19,7 +19,7 @@ import type { ColorblindType, CSSString, Theme } from "../core"; -type ThemeConfig = { +type ThemeSpec = { /** 主题名称, 用于生成文件名, 未指定时取 themes 中的键名 */ themeName?: string; /** 显示名称, 用于 Gitea UI 显示的名称 @@ -30,17 +30,19 @@ type ThemeConfig = { /** 色盲类型, 仅用于声明主题为色盲主题 */ colorblindType?: ColorblindType; theme: Theme; + /** 主题追加的样式, 优先级高于默认样式和主题系列样式 */ + styles?: CSSString; }; type Themes = | { /** 主题系列的深色模式主题 */ - dark: ThemeConfig; - [themeKeyName: string]: ThemeConfig; + dark: ThemeSpec; + [themeKeyName: string]: ThemeSpec; } | { /** 主题系列的浅色模式主题 */ - light: ThemeConfig; - [themeKeyName: string]: ThemeConfig; + light: ThemeSpec; + [themeKeyName: string]: ThemeSpec; }; export type ThemeSeries = { /** 主题系列名称, 做为前缀用于生成文件名和显示名称 */ @@ -58,13 +60,20 @@ export type ThemeSeries = { styles?: CSSString; }; +export type ThemeConfig = { + /** 全局样式 */ + globalStyles?: CSSString; + /** 主题系列 */ + themeSeries: ThemeSeries[]; +}; + /** 定义主题配置 */ -export function defineThemeConfig(config: ThemeSeries[]): ThemeSeries[] { +export function defineThemeConfig(themeConfig: ThemeConfig): ThemeConfig { // 检查主题系列名称是否重复 - const names = config.map(c => c.themeSeriesName); + const names = themeConfig.themeSeries.map(c => c.themeSeriesName); const duplicates = names.filter((name, index) => names.indexOf(name) !== index); if (duplicates.length > 0) { throw new Error(`Duplicate themeSeriesName found: ${[...new Set(duplicates)].join(", ")}`); } - return config; + return themeConfig; } diff --git a/theme.config.ts b/theme.config.ts index a9c0c72..e4ab347 100644 --- a/theme.config.ts +++ b/theme.config.ts @@ -18,111 +18,115 @@ */ import { defineThemeConfig } from "@lutinglt/gitea-github-theme/core"; +import styles from "@lutinglt/gitea-github-theme/styles"; import themes from "@lutinglt/gitea-github-theme/themes"; -export default defineThemeConfig([ - { - themeSeriesName: "default", - themes: { - dark: { theme: themes.github.dark }, - light: { theme: themes.github.light }, - "soft-dark": { theme: themes.github.softDark }, - }, - }, - { - themeSeriesName: "colorblind", - autoTheme: { displayName: "Default Auto Protanopia And Deuteranopia", colorblindType: "red-green" }, - themes: { - dark: { - displayName: "Default Dark Protanopia And Deuteranopia", - colorblindType: "red-green", - theme: themes.github.colorblind.dark, - }, - light: { - displayName: "Default Light Protanopia And Deuteranopia", - colorblindType: "red-green", - theme: themes.github.colorblind.light, +export default defineThemeConfig({ + globalStyles: styles, + themeSeries: [ + { + themeSeriesName: "default", + themes: { + dark: { theme: themes.github.dark }, + light: { theme: themes.github.light }, + "soft-dark": { theme: themes.github.softDark }, }, }, - }, - { - themeSeriesName: "tritanopia", - autoTheme: { displayName: "Default Auto Tritanopia", colorblindType: "blue-yellow" }, - themes: { - dark: { - displayName: "Default Dark Tritanopia", - colorblindType: "blue-yellow", - theme: themes.github.tritanopia.dark, - }, - light: { - displayName: "Default Light Tritanopia", - colorblindType: "blue-yellow", - theme: themes.github.tritanopia.light, + { + themeSeriesName: "colorblind", + autoTheme: { displayName: "Default Auto Protanopia And Deuteranopia", colorblindType: "red-green" }, + themes: { + dark: { + displayName: "Default Dark Protanopia And Deuteranopia", + colorblindType: "red-green", + theme: themes.github.colorblind.dark, + }, + light: { + displayName: "Default Light Protanopia And Deuteranopia", + colorblindType: "red-green", + theme: themes.github.colorblind.light, + }, }, }, - }, - { - themeSeriesName: "pink", - themes: { - dark: { theme: themes.github.pink.dark }, - light: { theme: themes.github.pink.light }, - "soft-dark": { theme: themes.github.pink.softDark }, - }, - }, - { - themeSeriesName: "gitea", - themes: { - dark: { theme: themes.gitea.dark }, - light: { theme: themes.gitea.light }, - }, - }, - { - themeSeriesName: "catppuccin", - themes: { - dark: { themeName: "mocha", theme: themes.catppuccin.mocha }, - light: { themeName: "latte", theme: themes.catppuccin.latte }, - frappe: { theme: themes.catppuccin.frappe }, - macchiato: { theme: themes.catppuccin.macchiato }, - }, - }, - { - themeSeriesName: "high-contrast", - themes: { - dark: { theme: themes.github.highContrast.dark }, - light: { theme: themes.github.highContrast.light }, - "soft-dark": { theme: themes.github.highContrast.softDark }, - }, - }, - { - themeSeriesName: "high-contrast-colorblind", - autoTheme: { displayName: "High Contrast Auto Protanopia And Deuteranopia", colorblindType: "red-green" }, - themes: { - dark: { - displayName: "High Contrast Dark Protanopia And Deuteranopia", - colorblindType: "red-green", - theme: themes.github.highContrast.colorblind.dark, - }, - light: { - displayName: "High Contrast Light Protanopia And Deuteranopia", - colorblindType: "red-green", - theme: themes.github.highContrast.colorblind.light, + { + themeSeriesName: "tritanopia", + autoTheme: { displayName: "Default Auto Tritanopia", colorblindType: "blue-yellow" }, + themes: { + dark: { + displayName: "Default Dark Tritanopia", + colorblindType: "blue-yellow", + theme: themes.github.tritanopia.dark, + }, + light: { + displayName: "Default Light Tritanopia", + colorblindType: "blue-yellow", + theme: themes.github.tritanopia.light, + }, }, }, - }, - { - themeSeriesName: "high-contrast-tritanopia", - autoTheme: { displayName: "High Contrast Auto Tritanopia", colorblindType: "blue-yellow" }, - themes: { - dark: { - displayName: "High Contrast Dark Tritanopia", - colorblindType: "blue-yellow", - theme: themes.github.highContrast.tritanopia.dark, - }, - light: { - displayName: "High Contrast Light Tritanopia", - colorblindType: "blue-yellow", - theme: themes.github.highContrast.tritanopia.light, + { + themeSeriesName: "pink", + themes: { + dark: { theme: themes.github.pink.dark }, + light: { theme: themes.github.pink.light }, + "soft-dark": { theme: themes.github.pink.softDark }, }, }, - }, -]); + { + themeSeriesName: "gitea", + themes: { + dark: { theme: themes.gitea.dark }, + light: { theme: themes.gitea.light }, + }, + }, + { + themeSeriesName: "catppuccin", + themes: { + dark: { themeName: "mocha", theme: themes.catppuccin.mocha }, + light: { themeName: "latte", theme: themes.catppuccin.latte }, + frappe: { theme: themes.catppuccin.frappe }, + macchiato: { theme: themes.catppuccin.macchiato }, + }, + }, + { + themeSeriesName: "high-contrast", + themes: { + dark: { theme: themes.github.highContrast.dark }, + light: { theme: themes.github.highContrast.light }, + "soft-dark": { theme: themes.github.highContrast.softDark }, + }, + }, + { + themeSeriesName: "high-contrast-colorblind", + autoTheme: { displayName: "High Contrast Auto Protanopia And Deuteranopia", colorblindType: "red-green" }, + themes: { + dark: { + displayName: "High Contrast Dark Protanopia And Deuteranopia", + colorblindType: "red-green", + theme: themes.github.highContrast.colorblind.dark, + }, + light: { + displayName: "High Contrast Light Protanopia And Deuteranopia", + colorblindType: "red-green", + theme: themes.github.highContrast.colorblind.light, + }, + }, + }, + { + themeSeriesName: "high-contrast-tritanopia", + autoTheme: { displayName: "High Contrast Auto Tritanopia", colorblindType: "blue-yellow" }, + themes: { + dark: { + displayName: "High Contrast Dark Tritanopia", + colorblindType: "blue-yellow", + theme: themes.github.highContrast.tritanopia.dark, + }, + light: { + displayName: "High Contrast Light Tritanopia", + colorblindType: "blue-yellow", + theme: themes.github.highContrast.tritanopia.light, + }, + }, + }, + ], +}); diff --git a/tsconfig.json b/tsconfig.json index d2b504f..1bc5c9c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,7 +28,6 @@ "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, "paths": { - "@lutinglt/gitea-github-theme/theme.config.ts": ["./theme.config.ts"], "@lutinglt/gitea-github-theme/core": ["./src"], "@lutinglt/gitea-github-theme/vite-plugin": ["./src/vite-plugin"], "@lutinglt/gitea-github-theme/styles": ["./styles"], diff --git a/vite.config.ts b/vite.config.ts index 686bea0..de702a3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -19,5 +19,6 @@ import { giteaGitHubTheme } from "@lutinglt/gitea-github-theme/vite-plugin"; import { defineConfig } from "vite"; +import themeConfig from "./theme.config.ts"; -export default defineConfig({ plugins: [giteaGitHubTheme()] }); +export default defineConfig({ plugins: [giteaGitHubTheme(themeConfig)] });