mirror of
https://github.com/lutinglt/gitea-github-theme.git
synced 2026-10-28 09:44:55 +00:00
nodejs -> bun
This commit is contained in:
102 files changed
+611
-708
No files matched your search
Vendored
+5
-5
@@ -25,16 +25,16 @@ jobs:
|
||||
- "vite.config.ts"
|
||||
- "package.json"
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
node-version: 24
|
||||
bun-version: "1.3.14"
|
||||
|
||||
- name: Build theme
|
||||
id: build
|
||||
if: steps.changes.outputs.src == 'true'
|
||||
run: |
|
||||
npm install
|
||||
npm run build:ci
|
||||
bun install
|
||||
bun bundle:ci
|
||||
|
||||
- name: Upload css assets
|
||||
if: steps.build.outcome == 'success'
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
id: locales
|
||||
if: steps.build.outcome =='success'
|
||||
continue-on-error: true
|
||||
run: npm run update:locale
|
||||
run: bun update:locale
|
||||
|
||||
- name: Upload locales assets
|
||||
if: steps.locales.outcome =='success'
|
||||
|
||||
Vendored
+4
-4
@@ -11,13 +11,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
node-version: 24
|
||||
bun-version: "1.3.14"
|
||||
- name: Build theme
|
||||
run: |
|
||||
npm install
|
||||
npm run release
|
||||
bun install
|
||||
bun release
|
||||
- name: Create release
|
||||
run: |
|
||||
tar -zcf dist/theme-github-base.tar.gz \
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
dist
|
||||
node_modules
|
||||
bun.lock
|
||||
bun.lockb
|
||||
package-lock.json
|
||||
.env
|
||||
.VSCodeCounter
|
||||
@@ -1,3 +1,8 @@
|
||||
### ⚠️ Breaking Changes
|
||||
|
||||
- Starting from this version, CSS nesting will no longer be expanded, which will reduce the volume by 40% and improve
|
||||
loading speed,ensure styles are applied correctly by keeping Chrome/Edge >= 120, Firefox >= 121, Safari >= 16.5.
|
||||
|
||||
### ✨ Feature
|
||||
|
||||
- Add high contrast color themes.
|
||||
|
||||
@@ -37,8 +37,8 @@ accepted.
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Because the project uses new CSS features, ensure styles are applied correctly by keeping Chrome/Edge >= 105,
|
||||
> Firefox >= 121, Safari >= 15.4
|
||||
> Because the project uses new CSS features, ensure styles are applied correctly by keeping Chrome/Edge >= 120,
|
||||
> Firefox >= 121, Safari >= 16.5
|
||||
|
||||
1. Download the latest CSS theme file from the release page and place it in the `data/gitea/public/assets/css` directory
|
||||
(This directory may not be available by default and needs to be manually created)
|
||||
@@ -214,13 +214,13 @@ Add the following code at the beginning or end of the theme's CSS file
|
||||
|
||||
You might want to use the development version of the theme instead of the released version
|
||||
|
||||
Please ensure you have Node.js environment installed, Node.js 24.12.0 or above is recommended
|
||||
Please ensure you have Bun environment installed, Bun 1.3.14 or above is recommended
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lutinglt/gitea-github-theme.git
|
||||
cd gitea-github-theme
|
||||
npm install
|
||||
npm run build
|
||||
bun install
|
||||
bun bundle
|
||||
```
|
||||
|
||||
After compilation, theme files will be generated in the `dist` directory. You can place the theme files into the
|
||||
|
||||
+4
-4
@@ -35,7 +35,7 @@ Gitea 理论上小版本号变更不会修改前端布局, 所以主题的小版
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 因为项目使用了 CSS 新特性, 确保样式正确应用需保持 Chrome/Edge >= 105, Firefox >= 121, Safari >= 15.4
|
||||
> 因为项目使用了 CSS 新特性, 确保样式正确应用需保持 Chrome/Edge >= 120, Firefox >= 121, Safari >= 16.5
|
||||
|
||||
1. 在发布页下载最新的 CSS 主题文件放入 `data/gitea/public/assets/css` 目录下 (默认可能没有此目录需手动创建)
|
||||
2. 修改 `data/gitea/conf/app.ini`,并将 CSS 文件名去掉 `theme-` 的名称附加到 `[ui]` 下的 `THEMES` 末尾
|
||||
@@ -208,13 +208,13 @@ THEMES = github-catppuccin-auto, github-catppuccin-latte, github-catppuccin-frap
|
||||
|
||||
也许你会想使用开发中的主题, 而不是发布的主题
|
||||
|
||||
请确保你已经安装了 Node.js 环境, 推荐使用 Node.js 24.12.0 或以上版本
|
||||
请确保你已经安装了 Bun 环境, 推荐使用 Bun 1.3.14 或以上版本
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lutinglt/gitea-github-theme.git
|
||||
cd gitea-github-theme
|
||||
npm install
|
||||
npm run build
|
||||
bun install
|
||||
bun bundle
|
||||
```
|
||||
|
||||
编译完成后, 会在 `dist` 目录下生成主题文件, 你可以将主题文件放入 `gitea/public/assets/css` 目录下, 然后在
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# bunfig.toml
|
||||
[install]
|
||||
registry = "https://registry.npmjs.org"
|
||||
+23
-16
@@ -1,5 +1,14 @@
|
||||
{
|
||||
"name": "gitea-github-theme",
|
||||
"name": "@lutinglt/gitea-github-theme",
|
||||
"exports": {
|
||||
"./theme.config.ts": "./theme.config.ts",
|
||||
"./core": "./src/index.ts",
|
||||
"./vite-plugin": "./src/vite-plugin/index.ts",
|
||||
"./styles": "./styles/index.ts",
|
||||
"./styles/common": "./styles/common/index.ts",
|
||||
"./themes": "./themes/index.ts",
|
||||
"./primer": "./primer/index.ts"
|
||||
},
|
||||
"version": "1.26.2",
|
||||
"license": "Apache-2.0",
|
||||
"author": {
|
||||
@@ -8,20 +17,19 @@
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "vitest",
|
||||
"lint": "eslint .",
|
||||
"format": "prettier --write .",
|
||||
"build": "tsgo -b -v && vite build",
|
||||
"commit": "npm run format && npm run lint && npm run test && npm run build",
|
||||
"version": "node scripts/version.ts",
|
||||
"release": "npm run build && npm run update:locale",
|
||||
"sync:theme": "node scripts/syncTheme.ts",
|
||||
"update:primer": "node scripts/buildPrimerTSToken.ts",
|
||||
"update:locale": "node scripts/translate.ts",
|
||||
"update:gitea": "node scripts/updateGitea.ts",
|
||||
"install:clean": "npm cache clean --force && rm -rf node_modules package-lock.json && npm install",
|
||||
"build:ci": "npm run lint && npm run test && npm run build",
|
||||
"build:dev": "npm run build && npm run sync:theme"
|
||||
"lint": "bun eslint .",
|
||||
"format": "bun prettier --write .",
|
||||
"bundle": "tsgo -b -v && bunx --bun vite build",
|
||||
"commit": "bun format && bun lint && bun test && bun bundle",
|
||||
"version": "bun scripts/version.ts",
|
||||
"release": "bun bundle && bun update:locale",
|
||||
"sync:theme": "bun scripts/syncTheme.ts",
|
||||
"update:primer": "bun scripts/buildPrimerTSToken.ts",
|
||||
"update:locale": "bun scripts/translate.ts",
|
||||
"update:gitea": "bun scripts/updateGitea.ts",
|
||||
"install:clean": "rm -rf node_modules bun.lock bun.lockb && bun install",
|
||||
"bundle:ci": "bun lint && bun vitest && bun bundle",
|
||||
"bundle:dev": "bun bundle && bun sync:theme"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@catppuccin/palette": "^1.8.0",
|
||||
@@ -41,7 +49,6 @@
|
||||
"prettier-plugin-organize-imports": "^4.3.0",
|
||||
"style-dictionary": "^5.4.1",
|
||||
"typescript-eslint": "^8.59.1",
|
||||
"typescript-plugin-css-modules": "^5.2.0",
|
||||
"undici": "^7.0.0",
|
||||
"vite": "^8.0.5",
|
||||
"vitest": "^4.1.7"
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { MapLeafNodes } from "@gitea-github-theme/core";
|
||||
import type { MapLeafNodes } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
import dark from "./dark";
|
||||
import darkColorblind from "./dark-colorblind";
|
||||
|
||||
@@ -21,7 +21,7 @@ import dotenv from "dotenv";
|
||||
import child_process from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { pkg, rootDir, setGlobalProxy } from "./utils.ts";
|
||||
import { pkg, rootDir, setGlobalProxy } from "./utils";
|
||||
|
||||
dotenv.config({ quiet: true });
|
||||
setGlobalProxy();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { pkg, rootDir, setGlobalProxy } from "./utils.ts";
|
||||
import { pkg, rootDir, setGlobalProxy } from "./utils";
|
||||
|
||||
setGlobalProxy();
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { ProxyAgent, setGlobalDispatcher } from "undici";
|
||||
import pkg from "../package.json" with { type: "json" };
|
||||
import pkg from "../package.json";
|
||||
|
||||
export function setGlobalProxy() {
|
||||
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.ALL_PROXY;
|
||||
|
||||
+1
-1
@@ -17,6 +17,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { pkg } from "./utils.ts";
|
||||
import { pkg } from "./utils";
|
||||
|
||||
console.log(pkg.version);
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,90 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { StyleRule } from "@vanilla-extract/css";
|
||||
import { transform } from "lightningcss";
|
||||
import { getCallerInfo } from "../utils";
|
||||
import { captureStyle } from "../vanilla-extract";
|
||||
|
||||
declare const CSSBrand: unique symbol;
|
||||
type CSSObject = { [CSSBrand]: true };
|
||||
type CSSPrimitive = string | number;
|
||||
type CSSInterpolation = CSSPrimitive | CSSObject | undefined;
|
||||
type SelectorStyleRule =
|
||||
| StyleRule
|
||||
| {
|
||||
[key: string]: StyleRule | SelectorStyleRule;
|
||||
};
|
||||
|
||||
const SHARED_CACHE_KEY = "__GITEA_GITHUB_THEME_CSS_CACHE__";
|
||||
const g = globalThis as Record<string, unknown>;
|
||||
const cssCache: string[] = (g[SHARED_CACHE_KEY] as string[]) || (g[SHARED_CACHE_KEY] = []);
|
||||
|
||||
/**
|
||||
* css 模板字符串 —— 类式 linaria 的 css tag,用于 vscode-styled-components 高亮。
|
||||
* 运行时校验 CSS 语法,收集输出到缓存,供 flushCSS() 获取。
|
||||
*/
|
||||
export function css(strings: TemplateStringsArray, ...values: CSSInterpolation[]): string {
|
||||
const result = strings.reduce((acc, s, i) => acc + s + String(values[i] ?? ""), "");
|
||||
// 构建时校验 CSS 语法
|
||||
transform({ filename: getCallerInfo(1), code: Buffer.from(result) });
|
||||
cssCache.push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 构建时一次性获取所有通过 css() 收集的 CSS */
|
||||
export function flushCSS(): string {
|
||||
const all = cssCache.join("\n");
|
||||
cssCache.length = 0;
|
||||
return all;
|
||||
}
|
||||
|
||||
/** cssStyle 用于 css 模板字符串的插值
|
||||
* 提取可复用的样式, 并保留 vanilla-extract 的类型检查
|
||||
* - 属性访问:保留原值(如 style.padding → "0px 6px")
|
||||
* - 字符串插值:自动输出 CSS 片段(如 `${style}` → "padding:0px 6px;")
|
||||
*/
|
||||
export function cssStyle<T extends SelectorStyleRule>(input: T): T & CSSObject {
|
||||
const flat: Record<string, CSSPrimitive> = {};
|
||||
const nested: Record<string, SelectorStyleRule> = {};
|
||||
|
||||
// Object.entries 对无索引签名的 StyleRule 只能返回 any/unknown,
|
||||
// 这里做最小断言:entry 的值是 CSS 叶子值(string|number)或嵌套对象
|
||||
for (const [key, val] of Object.entries(input) as [string, CSSPrimitive | SelectorStyleRule][]) {
|
||||
if (val === null || val === undefined) continue;
|
||||
if (typeof val === "object") {
|
||||
nested[key] = cssStyle(val);
|
||||
} else {
|
||||
flat[key] = val;
|
||||
}
|
||||
}
|
||||
|
||||
// 构建 CSS 字符串
|
||||
const cssParts: string[] = [];
|
||||
if (Object.keys(flat).length > 0) {
|
||||
cssParts.push(captureStyle(flat));
|
||||
}
|
||||
for (const [key, val] of Object.entries(nested)) {
|
||||
cssParts.push(`${key}{${String(val)}}`);
|
||||
}
|
||||
const cssText = cssParts.join("");
|
||||
input.toString = () => cssText;
|
||||
|
||||
return input as T & CSSObject;
|
||||
}
|
||||
@@ -17,6 +17,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { createChroma } from "./chroma";
|
||||
export { createCodeMirror } from "./codemirror";
|
||||
export { css, cssStyle, flushCSS } from "./css";
|
||||
export { createThemeMetaInfo, type ColorblindType, type GiteaThemeMeta } from "./meta";
|
||||
export { createTheme, defineTheme } from "./theme";
|
||||
export type { Theme, ThemeVars } from "./theme";
|
||||
export type { CSSVarFunction, MapLeafNodes } from "./types";
|
||||
File renamed without changes.
+15
-7
@@ -18,13 +18,24 @@
|
||||
*/
|
||||
|
||||
import { createGlobalTheme, globalKeyframes, globalStyle } from "@vanilla-extract/css";
|
||||
import pkg from "../../package.json";
|
||||
import type { GiteaColor, GitHubColor, ThemeColor } from "../palette";
|
||||
import { gitea2ThemeVars, github2ThemeColor, primer2Chroma, primer2CodeMirror, theme2ThemeVars } from "../palette";
|
||||
import selectors from "../selectors";
|
||||
import { createChroma, createCodeMirror } from "../styles";
|
||||
import { otherThemeVars, syntaxVars, themeVars, type Syntax } from "../types";
|
||||
import { createChroma } from "./chroma";
|
||||
import { createCodeMirror } from "./codemirror";
|
||||
import type { MapLeafNodes } from "./types";
|
||||
|
||||
function getThemeVersion(): string {
|
||||
// 版本号: 版本号.YYMMDD
|
||||
const now = new Date();
|
||||
const year = now.getFullYear().toString().slice(-2);
|
||||
const month = (now.getMonth() + 1).toString().padStart(2, "0");
|
||||
const day = now.getDate().toString().padStart(2, "0");
|
||||
return `${pkg.version}.${year}${month}${day}`;
|
||||
}
|
||||
|
||||
export type ThemeVars = { isDarkTheme: boolean } & MapLeafNodes<typeof themeVars, string>;
|
||||
export type ThemeColors =
|
||||
| { colorType: "github"; themeColor: GitHubColor }
|
||||
@@ -41,8 +52,8 @@ export type Theme = {
|
||||
* - "theme": GiteaGitHubTheme 用于简化 Gitea 颜色变量设置的配色, 使用 Gitea 的代码语法高亮色
|
||||
*
|
||||
* @example
|
||||
* import type { Console, Diff, Other, Github, ThemeColor, Syntax } from "@gitea-github-theme/core";
|
||||
* import { defineTheme, themeVars } from "@gitea-github-theme/core";
|
||||
* import type { Console, Diff, Other, Github, ThemeColor, Syntax } from "@lutinglt/gitea-github-theme/core";
|
||||
* import { defineTheme, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
*
|
||||
* const console: Console = {
|
||||
* fg: {
|
||||
@@ -77,9 +88,6 @@ export function defineTheme(themeColors: ThemeColors): Theme {
|
||||
};
|
||||
}
|
||||
|
||||
// vite define 编译时注入的常量
|
||||
declare const __THEME_VERSION__: string;
|
||||
|
||||
export function createTheme(theme: Theme): void {
|
||||
const { isDarkTheme, ...themeVarsColor } =
|
||||
theme.colorType === "github"
|
||||
@@ -90,7 +98,7 @@ export function createTheme(theme: Theme): void {
|
||||
|
||||
// 注入主题标识和版本号
|
||||
createGlobalTheme(selectors.root, {
|
||||
theme: { version: `"${__THEME_VERSION__}"` },
|
||||
theme: { version: `"${getThemeVersion()}"` },
|
||||
is: { dark: { theme: isDarkTheme.toString() } },
|
||||
});
|
||||
// 全局主题变量
|
||||
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as lightningcss from "lightningcss";
|
||||
import type { CSSObject } from "./toCSS";
|
||||
|
||||
const sharedCacheKey = "__GITEA_GITHUB_THEME_CSS_CACHE__";
|
||||
const g = globalThis as Record<string, unknown>;
|
||||
const cssCache: string[] = (g[sharedCacheKey] as string[]) || (g[sharedCacheKey] = []);
|
||||
|
||||
type CSSInterpolation = string | number | boolean | CSSObject | undefined | null;
|
||||
|
||||
function getCallerInfo(): string {
|
||||
const stack = new Error().stack?.split("\n") || [];
|
||||
// stack[0] = "Error"
|
||||
// stack[1] = " at getCallerInfo (css.ts:...)"
|
||||
// stack[2] = " at css (css.ts:...)"
|
||||
// stack[3] = " at <caller> (styles/components/heatmap.ts:23:18)" ← 目标
|
||||
const frame = stack[3] || "";
|
||||
const match = frame.match(/\((.+?):(\d+):(\d+)\)/) ?? frame.match(/at\s+(.+?):(\d+):(\d+)/);
|
||||
return match ? `${match[1]}:${match[2]}` : frame.trim() || "unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
* css 模板字符串 —— 类式 linaria 的 css tag,用于 vscode-styled-components 高亮。
|
||||
* 运行时校验 CSS 语法,收集输出到缓存,供 flushCSS() 获取。
|
||||
*/
|
||||
export function css(strings: TemplateStringsArray, ...values: CSSInterpolation[]): string {
|
||||
const result = strings.reduce((acc, s, i) => acc + s + String(values[i] ?? ""), "");
|
||||
// 构建时校验 CSS 语法
|
||||
lightningcss.transform({ filename: getCallerInfo(), code: Buffer.from(result) });
|
||||
cssCache.push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 构建时一次性获取所有通过 css() 收集的 CSS */
|
||||
export function flushCSS(): string {
|
||||
const all = cssCache.join("\n");
|
||||
cssCache.length = 0;
|
||||
return all;
|
||||
}
|
||||
+2
-5
@@ -19,8 +19,7 @@
|
||||
|
||||
import selectors from "./selectors";
|
||||
|
||||
export { createTheme, defineTheme, type MapLeafNodes } from "./core";
|
||||
export { css, flushCSS } from "./css";
|
||||
export { css, cssStyle, defineTheme, type MapLeafNodes } from "./core";
|
||||
export { extractVarName, scaleColorLight } from "./functions";
|
||||
export {
|
||||
catppuccin2Syntax,
|
||||
@@ -30,10 +29,8 @@ export {
|
||||
primer2GitHubColor,
|
||||
} from "./palette";
|
||||
export type { DisplayColor, GitHubColor, GiteaColor, ThemeColor } from "./palette";
|
||||
export { createThemeMetaInfo } from "./styles";
|
||||
export { toCSS } from "./toCSS";
|
||||
export { chromaVars, customThemeVars, otherThemeVars, syntaxVars, themeVars } from "./types";
|
||||
export type { Ansi, Chroma, Console, Diff, GitHub, Message, Named, Other, Primary, Secondary, Syntax } from "./types";
|
||||
export { deepOverride } from "./utils";
|
||||
export { defineThemeConfig } from "./vite-plugin";
|
||||
export { defineThemeConfig } from "./vite-plugin/themeConfig";
|
||||
export { selectors };
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Primer } from "@gitea-github-theme/primer";
|
||||
import type { Primer } from "@lutinglt/gitea-github-theme/primer";
|
||||
import { saturate } from "polished";
|
||||
import { scaleColorLight } from "../functions";
|
||||
import { deepOverride } from "../utils";
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Primer } from "@gitea-github-theme/primer";
|
||||
import type { Primer } from "@lutinglt/gitea-github-theme/primer";
|
||||
import { mix, saturate } from "polished";
|
||||
import { scaleColorLight } from "../functions";
|
||||
import type { Ansi, Console, Diff, GitHub, Message, Other } from "../types";
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Primer } from "@gitea-github-theme/primer";
|
||||
import type { Primer } from "@lutinglt/gitea-github-theme/primer";
|
||||
import type { Chroma, CodeMirror } from "../types";
|
||||
import { deepOverride } from "../utils";
|
||||
import type { GitHubColor } from "./github";
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { createChroma } from "./chroma";
|
||||
export { createCodeMirror } from "./codemirror";
|
||||
export { createThemeMetaInfo, type ColorblindType, type GiteaThemeMeta } from "./meta";
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { StyleRule } from "@vanilla-extract/css";
|
||||
import { globalStyle } from "@vanilla-extract/css";
|
||||
import { removeAdapter, setAdapter } from "@vanilla-extract/css/adapter";
|
||||
import { endFileScope, setFileScope } from "@vanilla-extract/css/fileScope";
|
||||
import { transformCss } from "@vanilla-extract/css/transformCss";
|
||||
|
||||
/** 使用 vanilla-extract 适配器序列化一个扁平 StyleRule 为 CSS 属性行 */
|
||||
function captureStyleRule(style: StyleRule): string {
|
||||
const captured: unknown[] = [];
|
||||
|
||||
setAdapter({
|
||||
appendCss: css => captured.push(css),
|
||||
registerClassName: () => {},
|
||||
registerComposition: () => {},
|
||||
markCompositionUsed: () => {},
|
||||
onEndFileScope: () => {},
|
||||
getIdentOption: () => "short",
|
||||
});
|
||||
|
||||
setFileScope("");
|
||||
globalStyle("_x", style);
|
||||
endFileScope();
|
||||
removeAdapter();
|
||||
|
||||
const css = transformCss({
|
||||
localClassNames: [],
|
||||
composedClassLists: [],
|
||||
cssObjs: captured as Parameters<typeof transformCss>[0]["cssObjs"],
|
||||
}).join("");
|
||||
|
||||
// 去掉 "_x { ... }" 外壳,只留内部属性
|
||||
const inner = css
|
||||
.replace(/^_x\s*\{/, "")
|
||||
.replace(/\}\s*$/, "")
|
||||
.trim();
|
||||
return inner ? inner + ";" : "";
|
||||
}
|
||||
|
||||
// ─── toCSS ──────────────────────────────────────────────
|
||||
|
||||
type SelectorStyleRule = {
|
||||
[key: string]: StyleRule | SelectorStyleRule;
|
||||
};
|
||||
|
||||
type SelectorsStyleRule = StyleRule | SelectorStyleRule;
|
||||
|
||||
declare const CSSBrand: unique symbol;
|
||||
export type CSSObject = { [CSSBrand]: true };
|
||||
|
||||
/**
|
||||
* 将 SelectorsStyleRule 转为可复用的对象:
|
||||
* - 属性访问:保留原值(如 style.padding → "0px 6px")
|
||||
* - 字符串插值:自动输出 CSS 片段(如 `${style}` → "padding:0px 6px;")
|
||||
*/
|
||||
export function toCSS<T extends SelectorsStyleRule>(input: T): T & CSSObject {
|
||||
const flat: Record<string, string | number> = {};
|
||||
const nested: Record<string, SelectorsStyleRule> = {};
|
||||
|
||||
// Object.entries 对无索引签名的 StyleRule 只能返回 any/unknown,
|
||||
// 这里做最小断言:entry 的值是 CSS 叶子值(string|number)或嵌套对象
|
||||
for (const [key, val] of Object.entries(input) as [string, string | number | SelectorsStyleRule][]) {
|
||||
if (val === null || val === undefined) continue;
|
||||
if (typeof val === "object") {
|
||||
nested[key] = toCSS(val);
|
||||
} else {
|
||||
flat[key] = val;
|
||||
}
|
||||
}
|
||||
|
||||
// 构建 CSS 字符串
|
||||
const cssParts: string[] = [];
|
||||
if (Object.keys(flat).length > 0) {
|
||||
cssParts.push(captureStyleRule(flat));
|
||||
}
|
||||
for (const [key, val] of Object.entries(nested)) {
|
||||
cssParts.push(`${key}{${String(val)}}`);
|
||||
}
|
||||
const cssText = cssParts.join("");
|
||||
|
||||
input.toString = () => cssText;
|
||||
|
||||
return input as T & CSSObject;
|
||||
}
|
||||
@@ -32,3 +32,26 @@ export function deepOverride<T extends object>(target: T, patch: DeepPartial<T>)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* 从调用堆栈中获取调用者信息(文件名:行号)。
|
||||
*
|
||||
* 堆栈帧结构(0-based):
|
||||
* stack[0] = "Error"
|
||||
* stack[1] = getCallerInfo 自身 ← 始终跳过
|
||||
* stack[2] = 直接调用者 ← skipFrames=0 时返回此行
|
||||
* stack[3] = 上层调用者 ← skipFrames=1 时返回此行
|
||||
* ...
|
||||
*
|
||||
* 每层中间函数由调用方自行声明需要跳过的帧数,
|
||||
* 而非将调用深度硬编码在此函数中。
|
||||
*
|
||||
* @param skipFrames 额外跳过的帧数(默认 0:返回直接调用者)
|
||||
* @returns 格式 "path/file:line",无法解析时返回 "unknown"
|
||||
*/
|
||||
export function getCallerInfo(skipFrames: number = 0): string {
|
||||
const stack = new Error().stack?.split("\n") || [];
|
||||
const index = 2 + skipFrames;
|
||||
const frame = stack[index] || stack[stack.length - 1] || "";
|
||||
const match = frame.match(/\((.+?):(\d+):(\d+)\)/) ?? frame.match(/at\s+(.+?):(\d+):(\d+)/);
|
||||
return match ? `${match[1]}:${match[2]}` : frame.trim() || "unknown";
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { StyleRule } from "@vanilla-extract/css";
|
||||
import { globalStyle } from "@vanilla-extract/css";
|
||||
import { removeAdapter, setAdapter } from "@vanilla-extract/css/adapter";
|
||||
import { endFileScope, setFileScope } from "@vanilla-extract/css/fileScope";
|
||||
import { transformCss } from "@vanilla-extract/css/transformCss";
|
||||
import { getCallerInfo } from "./utils";
|
||||
|
||||
type CSS = Parameters<typeof transformCss>[0]["cssObjs"][number];
|
||||
type Composition = Parameters<typeof transformCss>[0]["composedClassLists"][number];
|
||||
|
||||
/** 执行 vanilla-extract API 并序列化为 CSS 字符串 */
|
||||
export function compileCSS(compileFn: () => void): string {
|
||||
const capturedCssObjs: CSS[] = [];
|
||||
const localClassNames = new Set<string>();
|
||||
const composedClassLists: Composition[] = [];
|
||||
|
||||
setAdapter({
|
||||
appendCss: css => capturedCssObjs.push(css),
|
||||
registerClassName: className => localClassNames.add(className),
|
||||
registerComposition: composition => composedClassLists.push(composition),
|
||||
markCompositionUsed: () => {},
|
||||
onEndFileScope: () => {},
|
||||
getIdentOption:
|
||||
() =>
|
||||
({ debugId }) =>
|
||||
`${debugId}`,
|
||||
});
|
||||
setFileScope(getCallerInfo(1));
|
||||
|
||||
compileFn();
|
||||
|
||||
endFileScope();
|
||||
removeAdapter();
|
||||
|
||||
return transformCss({
|
||||
localClassNames: Array.from(localClassNames),
|
||||
composedClassLists,
|
||||
cssObjs: capturedCssObjs,
|
||||
}).join("\n");
|
||||
}
|
||||
|
||||
/** 使用 vanilla-extract 适配器序列化一个扁平 StyleRule 为 CSS 属性行 */
|
||||
export function captureStyle(style: StyleRule): string {
|
||||
const css = compileCSS(() => globalStyle("_CAPTURED_STYLE", style));
|
||||
const inner = css
|
||||
.replace(/^_CAPTURED_STYLE\s*\{/, "")
|
||||
.replace(/\}\s*$/, "")
|
||||
.trim();
|
||||
return inner ? inner + ";" : "";
|
||||
}
|
||||
@@ -1,325 +0,0 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { removeAdapter, setAdapter } from "@vanilla-extract/css/adapter";
|
||||
import { endFileScope, setFileScope } from "@vanilla-extract/css/fileScope";
|
||||
import { transformCss } from "@vanilla-extract/css/transformCss";
|
||||
import * as lightningcss from "lightningcss";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { rolldown } from "rolldown";
|
||||
import type { PluginOption } from "vite";
|
||||
import type { Theme } from "./core";
|
||||
import { createTheme } from "./core";
|
||||
import { flushCSS } from "./css";
|
||||
import type { ColorblindType, GiteaThemeMeta } from "./styles";
|
||||
import { createThemeMetaInfo } from "./styles";
|
||||
|
||||
interface Composition {
|
||||
identifier: string;
|
||||
classList: string;
|
||||
}
|
||||
|
||||
type ThemeEntry = {
|
||||
/** 主题名称 */
|
||||
themeName: string;
|
||||
/** Gitea 主题 元数据 */
|
||||
meta: GiteaThemeMeta;
|
||||
/** 主题颜色 */
|
||||
theme: Theme;
|
||||
};
|
||||
|
||||
type AutoThemeEntry = { darkThemeName: string; lightThemeName: string };
|
||||
|
||||
type ThemeConfig = {
|
||||
/** 主题名称, 用于生成文件名, 未指定时取 themes 中的键名 */
|
||||
themeName?: string;
|
||||
/** 显示名称, 用于 Gitea UI 显示的名称
|
||||
* - 未指定时根据 themeName 生成
|
||||
* - 指定时将覆盖生成的名称, 仅包含主题插件前缀, 不包含主题系列名称
|
||||
*/
|
||||
displayName?: string;
|
||||
/** 色盲类型, 仅用于声明主题为色盲主题 */
|
||||
colorblindType?: ColorblindType;
|
||||
theme: Theme;
|
||||
};
|
||||
|
||||
type Themes =
|
||||
| {
|
||||
/** 主题系列的深色模式主题 */
|
||||
dark: ThemeConfig;
|
||||
[themeKeyName: string]: ThemeConfig;
|
||||
}
|
||||
| {
|
||||
/** 主题系列的浅色模式主题 */
|
||||
light: ThemeConfig;
|
||||
[themeKeyName: string]: ThemeConfig;
|
||||
};
|
||||
|
||||
type ThemeSeries = {
|
||||
/** 主题系列名称, 做为前缀用于生成文件名和显示名称 */
|
||||
themeSeriesName: string;
|
||||
/** 主题系列自动颜色主题配置 */
|
||||
autoTheme?: {
|
||||
/** 自动颜色主题用于 Gitea UI 显示的名称 */
|
||||
displayName?: string;
|
||||
/** 色盲类型, 仅用于声明主题为色盲主题 */
|
||||
colorblindType?: ColorblindType;
|
||||
};
|
||||
/** 必须至少声明 dark/light 其中一个, 如果 dark & light 都声明了, 会生成自动颜色主题 */
|
||||
themes: Themes;
|
||||
};
|
||||
|
||||
/** 定义主题配置 */
|
||||
export function defineThemeConfig(config: ThemeSeries[]): ThemeSeries[] {
|
||||
// 检查主题系列名称是否重复
|
||||
const names = config.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;
|
||||
}
|
||||
|
||||
/** 使用 Vanilla Extract 的 adapter + transformCss 在 Node.js 中编译主题 CSS */
|
||||
function compileThemeCSS(compileFn: () => void): string {
|
||||
const capturedCssObjs: Parameters<typeof transformCss>[0]["cssObjs"] = [];
|
||||
const localClassNames = new Set<string>();
|
||||
const composedClassLists: Composition[] = [];
|
||||
|
||||
setAdapter({
|
||||
appendCss: css => capturedCssObjs.push(css),
|
||||
registerClassName: className => localClassNames.add(className),
|
||||
registerComposition: composition => composedClassLists.push(composition),
|
||||
markCompositionUsed: () => {},
|
||||
onEndFileScope: () => {},
|
||||
getIdentOption:
|
||||
() =>
|
||||
({ debugId }) =>
|
||||
`${debugId}`,
|
||||
});
|
||||
setFileScope("theme.css.ts");
|
||||
|
||||
compileFn();
|
||||
|
||||
endFileScope();
|
||||
removeAdapter();
|
||||
|
||||
return transformCss({
|
||||
localClassNames: Array.from(localClassNames),
|
||||
composedClassLists,
|
||||
cssObjs: capturedCssObjs,
|
||||
}).join("\n");
|
||||
}
|
||||
|
||||
/** Gitea GitHub Theme 主题插件: 解析入口文件, 生成主题 */
|
||||
export function giteaGitHubThemePlugin(): PluginOption {
|
||||
const PLUGIN_NAME = "GiteaGitHubThemePlugin";
|
||||
const PREFIX = "theme-github-";
|
||||
let themeEntries: ThemeEntry[];
|
||||
const autoThemeEntries = new Map<string, AutoThemeEntry>();
|
||||
let themeVersion = "";
|
||||
let styles = "";
|
||||
|
||||
return {
|
||||
name: PLUGIN_NAME,
|
||||
|
||||
async config(userConfig) {
|
||||
const root = userConfig.root || process.cwd();
|
||||
const entry = path.join(root, "theme.config.ts");
|
||||
const entryPath = path.isAbsolute(entry) ? entry : path.resolve(root, entry);
|
||||
|
||||
// 提取 __THEME_VERSION__ 定义, 用于后续在 Node.js 中编译主题时注入
|
||||
const themeVersionDefine = userConfig.define?.__THEME_VERSION__;
|
||||
if (typeof themeVersionDefine === "string") {
|
||||
themeVersion = JSON.parse(themeVersionDefine);
|
||||
}
|
||||
|
||||
// 1. 创建临时目录
|
||||
const hash = crypto.randomBytes(6).toString("hex");
|
||||
const tmpDir = path.join(userConfig.build?.outDir || "dist", `.gitea-theme-tmp-${hash}`);
|
||||
fs.mkdirSync(tmpDir, { recursive: true });
|
||||
|
||||
// 2. 使用 rolldown 打包入口文件为 ESM, 以便在 Node.js 中 import
|
||||
// 第三方包标记为外部依赖, 运行时从项目的 node_modules 解析
|
||||
const resolveAlias: Record<string, string> = {};
|
||||
if (userConfig.resolve?.alias) {
|
||||
const aliases = userConfig.resolve.alias;
|
||||
if (Array.isArray(aliases)) {
|
||||
for (const alias of aliases) {
|
||||
if (typeof alias.find === "string") {
|
||||
resolveAlias[alias.find] = alias.replacement;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Object.assign(resolveAlias, aliases);
|
||||
}
|
||||
}
|
||||
|
||||
const tmpBundle = path.join(tmpDir, "_themes_entry.mjs");
|
||||
const bundle = await rolldown({
|
||||
input: entryPath,
|
||||
platform: "node",
|
||||
// 第三方包标记为外部依赖, 运行时从项目的 node_modules 解析, 避免无谓打包提速
|
||||
external: id => {
|
||||
if (id.startsWith(".") || path.isAbsolute(id)) return false;
|
||||
// alias 路径 (如 "src/core", "themes/dark", "styles") 是项目内部模块, 需要打包
|
||||
if (Object.keys(resolveAlias).some(alias => id === alias || id.startsWith(alias + "/"))) return false;
|
||||
return true;
|
||||
},
|
||||
resolve: {
|
||||
alias: resolveAlias,
|
||||
extensions: [".ts", ".js"],
|
||||
},
|
||||
});
|
||||
const { output } = await bundle.generate({ format: "esm" });
|
||||
fs.writeFileSync(tmpBundle, output[0].code);
|
||||
await bundle.close();
|
||||
|
||||
// 3. 动态导入打包后的入口文件, 获取主题配置
|
||||
const themeConfig: ThemeSeries[] = (await import(pathToFileURL(tmpBundle).href)).default;
|
||||
|
||||
if (!themeConfig || typeof themeConfig !== "object") {
|
||||
throw new Error(`[${PLUGIN_NAME}] Entry file must default-export a defineThemeConfig result`);
|
||||
}
|
||||
|
||||
/** 辅助函数: 按 "-" 分割字符串并首字母大写 */
|
||||
function kebabToTitle(str: string): string {
|
||||
return str
|
||||
.split("-")
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ");
|
||||
}
|
||||
/** 辅助函数: 将主题名称转为正式主题名称 */
|
||||
function buildFullThemeName(themeSeries: ThemeSeries, themeName: string): string {
|
||||
return `${PREFIX}${themeSeries.themeSeriesName !== "default" ? `${themeSeries.themeSeriesName}-` : ""}${themeName}`;
|
||||
}
|
||||
/** 辅助函数: 将显示名称转为正式名称 */
|
||||
function buildFullDisplayName(themeSeries: ThemeSeries, displayName: string): string {
|
||||
return `GitHub ${kebabToTitle(themeSeries.themeSeriesName)} ${kebabToTitle(displayName)}`;
|
||||
}
|
||||
|
||||
// 4. 解析主题条目
|
||||
themeEntries = themeConfig.flatMap(themeSeries =>
|
||||
Object.entries(themeSeries.themes).map(([themeKeyName, entry]) => {
|
||||
const name = entry.themeName ?? themeKeyName;
|
||||
// 直接修改主题名用于自动主题生成使用, 避免重复计算
|
||||
entry.themeName = buildFullThemeName(themeSeries, name);
|
||||
return {
|
||||
themeName: entry.themeName,
|
||||
meta: {
|
||||
colorScheme: entry.theme.isDarkTheme ? "dark" : "light",
|
||||
displayName: entry.displayName ? `GitHub ${entry.displayName}` : buildFullDisplayName(themeSeries, name),
|
||||
colorblindType: entry.colorblindType,
|
||||
},
|
||||
theme: entry.theme,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// 5. 解析自动主题条目
|
||||
for (const themeSeries of themeConfig) {
|
||||
if (themeSeries.themes.dark && themeSeries.themes.light) {
|
||||
const themeName = buildFullThemeName(themeSeries, "auto");
|
||||
const meta: GiteaThemeMeta = {
|
||||
colorScheme: "auto",
|
||||
displayName: themeSeries.autoTheme?.displayName
|
||||
? `GitHub ${themeSeries.autoTheme.displayName}`
|
||||
: buildFullDisplayName(themeSeries, "auto"),
|
||||
colorblindType: themeSeries.autoTheme?.colorblindType,
|
||||
};
|
||||
autoThemeEntries.set(themeName, {
|
||||
darkThemeName: themeSeries.themes.dark.themeName!,
|
||||
lightThemeName: themeSeries.themes.light.themeName!,
|
||||
});
|
||||
// 将自动主题也加入 themeEntries 以便编译 CSS
|
||||
themeEntries.push({ themeName, meta, theme: null as unknown as Theme });
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 编译公共样式 (替代 wyw-in-js)
|
||||
// 使用 jiti 直接执行源文件,无需 rolldown 打包,避免 tree-shaking
|
||||
const { createJiti } = await import("jiti");
|
||||
const jitiInstance = createJiti(import.meta.url, {
|
||||
alias: resolveAlias,
|
||||
});
|
||||
await jitiInstance.import(path.join(root, "styles/index.ts"));
|
||||
const rawStyles = flushCSS();
|
||||
// LightningCSS 展开嵌套 + 压缩
|
||||
styles = lightningcss
|
||||
.transform({
|
||||
filename: "styles.css",
|
||||
code: Buffer.from(rawStyles),
|
||||
targets: { chrome: 100 << 16 },
|
||||
minify: true,
|
||||
})
|
||||
.code.toString();
|
||||
|
||||
// 7. 提供占位入口,Vite 需要至少一个输入才会触发 generateBundle
|
||||
const placeholder = path.join(tmpDir, "_placeholder.js");
|
||||
fs.writeFileSync(placeholder, "// placeholder\n");
|
||||
return { build: { rollupOptions: { input: placeholder } } };
|
||||
},
|
||||
|
||||
generateBundle(this, _options, bundle) {
|
||||
// 清除占位入口产物
|
||||
for (const key of Object.keys(bundle)) {
|
||||
delete bundle[key];
|
||||
}
|
||||
|
||||
// 注入 __THEME_VERSION__ 全局变量, createTheme 中使用
|
||||
(globalThis as Record<string, unknown>).__THEME_VERSION__ = themeVersion;
|
||||
|
||||
// 编译每个主题的 CSS 并输出
|
||||
for (const entry of themeEntries) {
|
||||
const { themeName, meta } = entry;
|
||||
const autoTheme = autoThemeEntries.get(themeName);
|
||||
|
||||
let themeCSS = compileThemeCSS(() => {
|
||||
createThemeMetaInfo(meta);
|
||||
// 自动主题不需要颜色变量, 只有 metaInfo
|
||||
if (!autoTheme) {
|
||||
createTheme(entry.theme);
|
||||
}
|
||||
});
|
||||
themeCSS = lightningcss
|
||||
.transform({ filename: themeName + ".css", code: Buffer.from(themeCSS), minify: true })
|
||||
.code.toString();
|
||||
const source = autoTheme
|
||||
? [
|
||||
`@import "./${autoTheme.darkThemeName}.css" (prefers-color-scheme: dark);`,
|
||||
`@import "./${autoTheme.lightThemeName}.css" (prefers-color-scheme: light);`,
|
||||
themeCSS,
|
||||
].join("\n")
|
||||
: `${themeCSS}${styles}`;
|
||||
|
||||
this.emitFile({
|
||||
type: "asset",
|
||||
fileName: `${themeName}.css`,
|
||||
source,
|
||||
});
|
||||
}
|
||||
|
||||
// 清理全局变量
|
||||
delete (globalThis as Record<string, unknown>).__THEME_VERSION__;
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { transform } from "lightningcss";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { PluginOption } from "vite";
|
||||
import type { GiteaThemeMeta, Theme } from "../core";
|
||||
import { createTheme, createThemeMetaInfo } from "../core";
|
||||
import { flushCSS } from "../core/css";
|
||||
import { compileCSS } from "../vanilla-extract";
|
||||
import { buildFullDisplayName, buildFullThemeName } from "./utils";
|
||||
|
||||
type ThemeEntry = { themeName: string; meta: GiteaThemeMeta; theme: Theme };
|
||||
type AutoThemeEntry = { darkThemeName: string; lightThemeName: string };
|
||||
|
||||
export function giteaGitHubTheme(): PluginOption {
|
||||
const themeEntries = new Array<ThemeEntry>();
|
||||
const autoThemeEntries = new Map<string, AutoThemeEntry>();
|
||||
|
||||
return {
|
||||
name: "lutinglt-gitea-github-theme",
|
||||
|
||||
async config(userConfig) {
|
||||
// 1. 动态导入 theme.config.ts(Bun 原生 TS + exports 自引用)
|
||||
const themeConfig = (await import("@lutinglt/gitea-github-theme/theme.config.ts")).default;
|
||||
|
||||
// 2. 解析主题条目
|
||||
for (const themeSeries of themeConfig) {
|
||||
for (const [themeKeyName, entry] of Object.entries(themeSeries.themes)) {
|
||||
const name = entry.themeName ?? themeKeyName;
|
||||
// 直接修改主题名用于自动主题生成使用, 避免重复计算
|
||||
entry.themeName = buildFullThemeName(themeSeries, name);
|
||||
themeEntries.push({
|
||||
themeName: entry.themeName,
|
||||
meta: {
|
||||
colorScheme: entry.theme.isDarkTheme ? "dark" : "light",
|
||||
displayName: entry.displayName ? `GitHub ${entry.displayName}` : buildFullDisplayName(themeSeries, name),
|
||||
colorblindType: entry.colorblindType,
|
||||
},
|
||||
theme: entry.theme,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 解析自动主题条目
|
||||
for (const themeSeries of themeConfig) {
|
||||
if (themeSeries.themes.dark && themeSeries.themes.light) {
|
||||
const themeName = buildFullThemeName(themeSeries, "auto");
|
||||
const meta: GiteaThemeMeta = {
|
||||
colorScheme: "auto",
|
||||
displayName: themeSeries.autoTheme?.displayName
|
||||
? `GitHub ${themeSeries.autoTheme.displayName}`
|
||||
: buildFullDisplayName(themeSeries, "auto"),
|
||||
colorblindType: themeSeries.autoTheme?.colorblindType,
|
||||
};
|
||||
autoThemeEntries.set(themeName, {
|
||||
darkThemeName: themeSeries.themes.dark.themeName!,
|
||||
lightThemeName: themeSeries.themes.light.themeName!,
|
||||
});
|
||||
// 将自动主题也加入 themeEntries 以便编译 CSS
|
||||
themeEntries.push({ themeName, meta, theme: null as unknown as Theme });
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 提供占位入口,Vite 需要至少一个输入才会触发 generateBundle
|
||||
const outDir = userConfig.build?.outDir || "dist";
|
||||
const placeholder = path.join(outDir, "_placeholder.js");
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
fs.writeFileSync(placeholder, "// placeholder\n");
|
||||
return { build: { outDir, rolldownOptions: { input: placeholder } } };
|
||||
},
|
||||
|
||||
async generateBundle(this, _options, bundle) {
|
||||
// 清除占位入口产物
|
||||
for (const key of Object.keys(bundle)) {
|
||||
delete bundle[key];
|
||||
}
|
||||
|
||||
// 1. 编译公共样式 (替代 wyw-in-js)
|
||||
// Bun 原生 TS + exports 自引用,导入即触发所有 css() 副作用
|
||||
await import("@lutinglt/gitea-github-theme/styles");
|
||||
const rawStyles = Buffer.from(flushCSS());
|
||||
const styles = transform({ filename: "styles.css", code: rawStyles, minify: true }).code.toString();
|
||||
|
||||
// 编译每个主题的 CSS 并输出
|
||||
for (const entry of themeEntries) {
|
||||
const { themeName, meta } = entry;
|
||||
const autoTheme = autoThemeEntries.get(themeName);
|
||||
|
||||
const rawThemeCSS = Buffer.from(
|
||||
compileCSS(() => {
|
||||
createThemeMetaInfo(meta);
|
||||
// 自动主题不需要颜色变量, 只有 metaInfo
|
||||
if (!autoTheme) createTheme(entry.theme);
|
||||
})
|
||||
);
|
||||
const themeCSS = transform({ filename: themeName + ".css", code: rawThemeCSS, minify: true }).code.toString();
|
||||
const source = autoTheme
|
||||
? [
|
||||
`@import "./${autoTheme.darkThemeName}.css" (prefers-color-scheme: dark);`,
|
||||
`@import "./${autoTheme.lightThemeName}.css" (prefers-color-scheme: light);`,
|
||||
themeCSS,
|
||||
].join("\n")
|
||||
: `${themeCSS}${styles}`;
|
||||
|
||||
this.emitFile({
|
||||
type: "asset",
|
||||
fileName: `${themeName}.css`,
|
||||
source,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ColorblindType, Theme } from "../core";
|
||||
|
||||
type ThemeConfig = {
|
||||
/** 主题名称, 用于生成文件名, 未指定时取 themes 中的键名 */
|
||||
themeName?: string;
|
||||
/** 显示名称, 用于 Gitea UI 显示的名称
|
||||
* - 未指定时根据 themeName 生成
|
||||
* - 指定时将覆盖生成的名称, 仅包含主题插件前缀, 不包含主题系列名称
|
||||
*/
|
||||
displayName?: string;
|
||||
/** 色盲类型, 仅用于声明主题为色盲主题 */
|
||||
colorblindType?: ColorblindType;
|
||||
theme: Theme;
|
||||
};
|
||||
type Themes =
|
||||
| {
|
||||
/** 主题系列的深色模式主题 */
|
||||
dark: ThemeConfig;
|
||||
[themeKeyName: string]: ThemeConfig;
|
||||
}
|
||||
| {
|
||||
/** 主题系列的浅色模式主题 */
|
||||
light: ThemeConfig;
|
||||
[themeKeyName: string]: ThemeConfig;
|
||||
};
|
||||
export type ThemeSeries = {
|
||||
/** 主题系列名称, 做为前缀用于生成文件名和显示名称 */
|
||||
themeSeriesName: string;
|
||||
/** 主题系列自动颜色主题配置 */
|
||||
autoTheme?: {
|
||||
/** 自动颜色主题用于 Gitea UI 显示的名称 */
|
||||
displayName?: string;
|
||||
/** 色盲类型, 仅用于声明主题为色盲主题 */
|
||||
colorblindType?: ColorblindType;
|
||||
};
|
||||
/** 必须至少声明 dark/light 其中一个, 如果 dark & light 都声明了, 会生成自动颜色主题 */
|
||||
themes: Themes;
|
||||
};
|
||||
|
||||
/** 定义主题配置 */
|
||||
export function defineThemeConfig(config: ThemeSeries[]): ThemeSeries[] {
|
||||
// 检查主题系列名称是否重复
|
||||
const names = config.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;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
* Copyright (c) https://github.com/lutinglt
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ThemeSeries } from "./themeConfig";
|
||||
|
||||
/** 按 "-" 分割字符串并首字母大写 */
|
||||
function kebabToTitle(str: string): string {
|
||||
return str
|
||||
.split("-")
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ");
|
||||
}
|
||||
/** 将主题名称转为正式主题名称 */
|
||||
export function buildFullThemeName(themeSeries: ThemeSeries, themeName: string): string {
|
||||
return `theme-github-${themeSeries.themeSeriesName !== "default" ? `${themeSeries.themeSeriesName}-` : ""}${themeName}`;
|
||||
}
|
||||
/** 将显示名称转为正式名称 */
|
||||
export function buildFullDisplayName(themeSeries: ThemeSeries, displayName: string): string {
|
||||
return `GitHub ${kebabToTitle(themeSeries.themeSeriesName)} ${kebabToTitle(displayName)}`;
|
||||
}
|
||||
@@ -17,12 +17,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { otherThemeVars, themeVars, toCSS } from "@gitea-github-theme/core";
|
||||
import { cssStyle, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
/** 激活项后缀样式
|
||||
* @example 菜单激活子项前面的竖线, 方便识别
|
||||
*/
|
||||
export const activeItemAfterStyle = toCSS({
|
||||
export const activeItemAfterStyle = cssStyle({
|
||||
content: `""`,
|
||||
backgroundColor: themeVars.github.borderColor.accent.emphasis,
|
||||
borderRadius: otherThemeVars.border.radius,
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { selectors, toCSS } from "@gitea-github-theme/core";
|
||||
import { cssStyle, selectors } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 出现动画
|
||||
export const animation = toCSS({
|
||||
export const animation = cssStyle({
|
||||
animation: selectors.overlayAppear,
|
||||
animationDuration: "80ms",
|
||||
animationFillMode: "forwards",
|
||||
@@ -28,14 +28,14 @@ export const animation = toCSS({
|
||||
});
|
||||
|
||||
// 向下出现动画
|
||||
export const animationDown = toCSS({
|
||||
export const animationDown = cssStyle({
|
||||
animation: selectors.overlayAppearDown,
|
||||
animationDuration: "200ms",
|
||||
animationTimingFunction: "cubic-bezier(0.33, 1, 0.68, 1)",
|
||||
});
|
||||
|
||||
// 向上出现动画
|
||||
export const animationUp = toCSS({
|
||||
export const animationUp = cssStyle({
|
||||
animation: selectors.overlayAppearUp,
|
||||
animationDuration: "200ms",
|
||||
animationTimingFunction: "cubic-bezier(0.33, 1, 0.68, 1)",
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { themeVars, toCSS } from "@gitea-github-theme/core";
|
||||
import { cssStyle, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
/** 主色调按钮样式 */
|
||||
export const primaryButtonStyle = toCSS({
|
||||
export const primaryButtonStyle = cssStyle({
|
||||
color: themeVars.github.button.primary.fgColor.rest,
|
||||
backgroundColor: themeVars.github.button.primary.bgColor.rest,
|
||||
borderColor: themeVars.github.button.primary.borderColor.rest,
|
||||
@@ -28,7 +28,7 @@ export const primaryButtonStyle = toCSS({
|
||||
});
|
||||
|
||||
/** 主色调按钮悬停样式 */
|
||||
export const primaryButtonHoverStyle = toCSS({
|
||||
export const primaryButtonHoverStyle = cssStyle({
|
||||
color: themeVars.github.button.primary.fgColor.rest,
|
||||
backgroundColor: themeVars.github.button.primary.bgColor.hover,
|
||||
borderColor: themeVars.github.button.primary.borderColor.hover,
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { themeVars, toCSS } from "@gitea-github-theme/core";
|
||||
import { cssStyle, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const deleteHoverActiveStyle = toCSS({
|
||||
export const deleteHoverActiveStyle = cssStyle({
|
||||
"&:hover": {
|
||||
backgroundColor: `${themeVars.github.control.danger.bgColor.hover} !important`,
|
||||
color: `${themeVars.github.control.danger.fgColor.hover} !important`,
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { toCSS } from "@gitea-github-theme/core";
|
||||
import { cssStyle } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
/** 基本标签样式 */
|
||||
export const labelStyle = toCSS({
|
||||
export const labelStyle = cssStyle({
|
||||
padding: "0px 6px",
|
||||
});
|
||||
|
||||
/** bot 标签样式 */
|
||||
export const botLabelStyle = toCSS({
|
||||
export const botLabelStyle = cssStyle({
|
||||
height: "20px",
|
||||
padding: "0 6px !important",
|
||||
marginLeft: "4px",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 修改 action 页面 svg 颜色 (主要为了覆盖工作流状态中的白色图标)
|
||||
export const actionSVG = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 仓库 Actions 页面
|
||||
export const actions = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 工作流详情页标题
|
||||
export const actionViewHeader = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { animationDown } from "@gitea-github-theme/styles/common";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { animationDown } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 工作流右侧作业步骤日志详情
|
||||
export const actionViewRight = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const summaryView = css`
|
||||
.action-view-right:has(.action-run-summary-view) {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { labelStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { labelStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const dashboard = css`
|
||||
.page-content.dashboard {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { fallbackVar } from "@vanilla-extract/css";
|
||||
|
||||
const userRepoVar = fallbackVar(customThemeVars.userRepolistColumns, "2");
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const footer = css`
|
||||
.page-footer {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const heatmap = css`
|
||||
#user-heatmap {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const button = css`
|
||||
/* 工单&PR标题右侧按钮 */
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { botLabelStyle, deleteHoverActiveStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { botLabelStyle, deleteHoverActiveStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 评论
|
||||
export const comment = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, extractVarName, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, extractVarName, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 工单&PR 列表
|
||||
export const issueList = css`
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars, toCSS } from "@gitea-github-theme/core";
|
||||
import { deleteHoverActiveStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, cssStyle, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { deleteHoverActiveStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
const sidebarPadding = toCSS({
|
||||
const sidebarPadding = cssStyle({
|
||||
padding: "4px 8px",
|
||||
});
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { botLabelStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { botLabelStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 时间线
|
||||
export const timeline = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { fallbackVar } from "@vanilla-extract/css";
|
||||
|
||||
export const navbarRight = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css } from "@gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css } from "@lutinglt/gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 新建仓库页面下拉菜单
|
||||
export const newRepo = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 用户订阅/关注页面
|
||||
export const notification = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const org = css`
|
||||
.page-content.organization {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 克隆按钮的弹窗
|
||||
export const clone = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 提交列表
|
||||
export const commit = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const diff = css`
|
||||
/* 这里的折叠行和代码行高度与 GitHub 的 release 和 review 的差异对比时的高度一致, 不需要像 commit 中的差异对比那样行高过高 */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const milestone = css`
|
||||
/* 里程碑头部 */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 组织/仓库的软件包列表(包含用户但未测试)
|
||||
export const packagesList = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// release 顶部栏左侧按钮组
|
||||
export const releaseTagMenu = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 仓库头信息
|
||||
export const repoHeader = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { activeItemAfterStyle, deleteHoverActiveStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { activeItemAfterStyle, deleteHoverActiveStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 仓库打开文件时的视图
|
||||
export const repoFileView = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { animationDown } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { animationDown } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 文件列表页面下的分支按钮
|
||||
export const branchButton = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 仓库代码布局调整, 侧边栏宽度调整
|
||||
export const repoGrid = css`
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars, toCSS } from "@gitea-github-theme/core";
|
||||
import { primaryButtonHoverStyle, primaryButtonStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, cssStyle, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { primaryButtonHoverStyle, primaryButtonStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
const tinyStyle = toCSS({
|
||||
const tinyStyle = cssStyle({
|
||||
color: themeVars.github.themeExtra.button.primary.fgColor.accent,
|
||||
backgroundColor: themeVars.color.button,
|
||||
borderColor: themeVars.color.light.border,
|
||||
});
|
||||
|
||||
const tinyHoverStyle = toCSS({
|
||||
const tinyHoverStyle = cssStyle({
|
||||
color: themeVars.github.button.primary.fgColor.rest,
|
||||
backgroundColor: themeVars.github.button.primary.bgColor.hover,
|
||||
borderColor: themeVars.github.button.primary.borderColor.hover,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css } from "@gitea-github-theme/core";
|
||||
import { css } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 注册/登录界面
|
||||
export const signIn = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 用户点星仓库列表
|
||||
export const stars = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const attached = css`
|
||||
/* 设置右面板的内容 */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css } from "@gitea-github-theme/core";
|
||||
import { css } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const body = css`
|
||||
body {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { primaryButtonHoverStyle, primaryButtonStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { primaryButtonHoverStyle, primaryButtonStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 普通按钮和主色调按钮
|
||||
export const baseButton = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { animationDown } from "@gitea-github-theme/styles/common";
|
||||
import { css, customThemeVars, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { animationDown } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
import { fallbackVar } from "@vanilla-extract/css";
|
||||
|
||||
// 分支菜单
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { activeItemAfterStyle, animationDown, animationUp } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { activeItemAfterStyle, animationDown, animationUp } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const dropdown = css`
|
||||
.ui.dropdown,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 包含表情的下拉菜单
|
||||
export const emojiDropdown = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 选择框的下拉菜单看起来像普通按钮
|
||||
export const selectionDropdown = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const input = css`
|
||||
textarea,
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { labelStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { labelStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const label = css`
|
||||
.ui.label {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 仓库标签 (私有/公开/内部)
|
||||
export const repoLabel = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 提交中的 SHA 标签
|
||||
export const shaLabel = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 任务状态标签, 目前仅在管理员页面 Runner 状态中看到
|
||||
export const taskStatusLabel = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 单行双选项菜单
|
||||
export const smallCompactMenu = css`
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { labelStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { labelStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const menu = css`
|
||||
.ui.menu {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 分页菜单
|
||||
export const paginationMenu = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const secondaryMenu = css`
|
||||
/* 二级菜单, 比如 Issue/PR/Actions 的筛选菜单 */
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { activeItemAfterStyle } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const verticalMenu = css`
|
||||
/* 垂直菜单, 用于左侧边栏 */
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { animationDown } from "@gitea-github-theme/styles/common";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { animationDown } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
export const modal = css`
|
||||
.ui.modal {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const text = css`
|
||||
/* 默认颜色是 --color-text-light, 主题下此颜色是亮白色, 修改为灰色 */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 全部圆角替换
|
||||
export const radius = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const table = css`
|
||||
.ui.table > tr > td,
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { animation, animationDown } from "@gitea-github-theme/styles/common";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
import { animation, animationDown } from "@lutinglt/gitea-github-theme/styles/common";
|
||||
|
||||
// 一些界面内的提示框, 比如克隆按钮, PR信息, Runner信息 等
|
||||
export const tippyBox = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css } from "@gitea-github-theme/core";
|
||||
import { css } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
// 简单的渐变过渡
|
||||
export const transition = css`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const commitSignBadge = css`
|
||||
a.ui.label.commit-id-short.gitea-github-theme-commit-sha {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
const primary = "primary" as const;
|
||||
const secondary = "secondary" as const;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const repoButtonRow = css`
|
||||
.gitea-github-theme-templates {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { css, otherThemeVars, themeVars } from "@gitea-github-theme/core";
|
||||
import { css, otherThemeVars, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
export const repoFileLastCommit = css`
|
||||
/* 仓库页和文件列表文件夹页的最后一次提交 */
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineThemeConfig } from "@gitea-github-theme/core";
|
||||
import themes from "@gitea-github-theme/themes";
|
||||
import { defineThemeConfig } from "@lutinglt/gitea-github-theme/core";
|
||||
import themes from "@lutinglt/gitea-github-theme/themes";
|
||||
|
||||
export default defineThemeConfig([
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
import { flavors, type CatppuccinFlavor } from "@catppuccin/palette";
|
||||
import { catppuccin2Syntax, catppuccin2ThemeColor, defineTheme } from "@gitea-github-theme/core";
|
||||
import { catppuccin2Syntax, catppuccin2ThemeColor, defineTheme } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
function defineCatppuccinTheme(flavor: CatppuccinFlavor) {
|
||||
return defineTheme({
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ import type {
|
||||
Primary,
|
||||
Secondary,
|
||||
Syntax,
|
||||
} from "@gitea-github-theme/core";
|
||||
import { defineTheme, themeVars } from "@gitea-github-theme/core";
|
||||
} from "@lutinglt/gitea-github-theme/core";
|
||||
import { defineTheme, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
const primary: Primary = {
|
||||
self: "#4183c4",
|
||||
|
||||
@@ -32,8 +32,8 @@ import type {
|
||||
Primary,
|
||||
Secondary,
|
||||
Syntax,
|
||||
} from "@gitea-github-theme/core";
|
||||
import { defineTheme, themeVars } from "@gitea-github-theme/core";
|
||||
} from "@lutinglt/gitea-github-theme/core";
|
||||
import { defineTheme, themeVars } from "@lutinglt/gitea-github-theme/core";
|
||||
|
||||
const primary: Primary = {
|
||||
self: "#4183c4",
|
||||
|
||||
+3
-3
@@ -21,9 +21,9 @@
|
||||
* @author lutinglt
|
||||
*/
|
||||
|
||||
import type { GitHubColor } from "@gitea-github-theme/core";
|
||||
import { deepOverride, defineTheme, display2GitHubColor, primer2GitHubColor } from "@gitea-github-theme/core";
|
||||
import { default as primer } from "@gitea-github-theme/primer";
|
||||
import type { GitHubColor } from "@lutinglt/gitea-github-theme/core";
|
||||
import { deepOverride, defineTheme, display2GitHubColor, primer2GitHubColor } from "@lutinglt/gitea-github-theme/core";
|
||||
import { default as primer } from "@lutinglt/gitea-github-theme/primer";
|
||||
|
||||
/** - 仅适用于 Dark 主题的颜色转换 */
|
||||
function darkConvert(color: GitHubColor) {
|
||||
|
||||
Loaded 100 of 102 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user