mirror of
https://github.com/lutinglt/gitea-github-theme.git
synced 2025-10-26 04:40:31 +00:00
src 结构调整, 添加 functions
This commit is contained in:
1
src/core/index.ts
Normal file
1
src/core/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { createTheme } from "./theme";
|
||||
48
src/core/theme.ts
Normal file
48
src/core/theme.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { createGlobalTheme, globalStyle } from "@vanilla-extract/css";
|
||||
import { otherThemeVars, themeVars } from "src/types/vars";
|
||||
import type { MapLeafNodes, WithOptionalLayer } from "./types";
|
||||
|
||||
type Theme = WithOptionalLayer<MapLeafNodes<typeof themeVars, string>>;
|
||||
|
||||
function stringToBoolean(str: string, name: string): boolean {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw new Error(`Invalid boolean value(${name}): ${str}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** 定义主题, 用于生成颜色主题
|
||||
* @example
|
||||
* 文件名: `color-dark.css.ts`
|
||||
* import type { Primary } from "src/types";
|
||||
* import { defineTheme, themeVars } from "src";
|
||||
*
|
||||
* const primary: Primary = {
|
||||
* self: "#000000",
|
||||
* contrast: themeVars.color.white,
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* export default defineTheme({
|
||||
* isDarkTheme: "true",
|
||||
* color: {
|
||||
* primary,
|
||||
* ...
|
||||
* }
|
||||
* })
|
||||
*/
|
||||
export const defineTheme = (theme: Theme) => theme;
|
||||
export function createTheme(theme: Theme): void {
|
||||
createGlobalTheme(":root", themeVars, theme);
|
||||
createGlobalTheme(":root", otherThemeVars, {
|
||||
border: {
|
||||
radius: "6px",
|
||||
},
|
||||
});
|
||||
globalStyle(":root", {
|
||||
accentColor: themeVars.color.blue,
|
||||
colorScheme: stringToBoolean(theme.isDarkTheme, "isDarkTheme") ? "dark" : "light",
|
||||
});
|
||||
}
|
||||
@@ -3,6 +3,14 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { Plugin } from "vite";
|
||||
|
||||
/**
|
||||
* 生成主题输入
|
||||
* @param outDir 输出目录与 vite 配置中的 outDir 一致, 用于生成临时目录
|
||||
* @param themeDir 颜色主题目录
|
||||
* @param devTheme 开发模式下的主题, 仅打包该主题
|
||||
* @param mode 模式, 开发模式为 dev `vite build --mode dev`
|
||||
* @returns vite.rollupOptions.input 的配置
|
||||
*/
|
||||
export function themeInput(
|
||||
outDir: string,
|
||||
themeDir: string,
|
||||
@@ -25,7 +33,7 @@ export function themeInput(
|
||||
if (mode === "dev" && fileName !== devTheme) continue;
|
||||
// 创建颜色主题的 css.ts 文件, vanilla-extract 需要这个文件后缀名并生成 css
|
||||
const tmpCssTs = path.join(tmpDir, `${fileName}.css.ts`);
|
||||
const createImport = `import { createTheme } from "src/theme";`;
|
||||
const createImport = `import { createTheme } from "src/core";`;
|
||||
const themeImport = `import theme from "themes/${fileName}";`;
|
||||
const createFn = `createTheme(theme);`;
|
||||
fs.writeFileSync(tmpCssTs, `${createImport}\n${themeImport}\n${createFn}`);
|
||||
@@ -43,6 +51,10 @@ export function themeInput(
|
||||
|
||||
const prefix = "theme-github-";
|
||||
|
||||
/**
|
||||
* 生成主题文件
|
||||
* @important vite.rollupOptions.output 配置 `assetFileNames: "[name].[ext]"`
|
||||
*/
|
||||
export function themePlugin(): Plugin {
|
||||
return {
|
||||
name: "themePlugin",
|
||||
1
src/functions/index.ts
Normal file
1
src/functions/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { scaleColorLight } from "./scss";
|
||||
27
src/functions/scss.ts
Normal file
27
src/functions/scss.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { hsl, parseToHsl } from "polished";
|
||||
|
||||
/**
|
||||
* 改变颜色的亮度, 等同于 sass 中的 `color.scale` 函数
|
||||
* @param color 颜色值
|
||||
* @param lightnessScale 亮度变化比例,负数表示变暗,正数表示变亮
|
||||
* @returns 新的颜色值
|
||||
* @example
|
||||
* const newColor = scaleColorLight("#ff0000", 20); // 变亮
|
||||
* const newColor = scaleColorLight("#ff0000", -20); // 变暗
|
||||
* 等同于 sass `@use "sass:color"`;
|
||||
* color: color.scale(#ff0000, $lightness: 20%)
|
||||
* color: color.scale(#ff0000, $lightness: -20%)
|
||||
*/
|
||||
export function scaleColorLight(color: string, lightness: number) {
|
||||
const hslColor = parseToHsl(color);
|
||||
let newLightness;
|
||||
|
||||
if (lightness < 0) {
|
||||
newLightness = hslColor.lightness * (1 + lightness / 100); // 变暗
|
||||
} else {
|
||||
newLightness = hslColor.lightness + (1 - hslColor.lightness) * (lightness / 100); // 变亮
|
||||
}
|
||||
|
||||
newLightness = Math.min(1, Math.max(0, newLightness)); // 确保亮度值在 0 到 1 之间
|
||||
return hsl(hslColor.hue, hslColor.saturation, newLightness);
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
export * as color from "src/color";
|
||||
export { defineTheme, themeVars } from "src/theme";
|
||||
|
||||
export { css } from "@linaria/core";
|
||||
export { defineTheme } from "./core/theme";
|
||||
export { themeVars } from "./types/vars";
|
||||
|
||||
35
src/theme.ts
35
src/theme.ts
@@ -1,35 +0,0 @@
|
||||
import { createGlobalTheme, createGlobalThemeContract, globalStyle } from "@vanilla-extract/css";
|
||||
import type { MapLeafNodes, WithOptionalLayer } from "src/types";
|
||||
import { varMapper, vars } from "src/vars";
|
||||
|
||||
function stringToBoolean(str: string, name: string): boolean {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw new Error(`Invalid boolean value(${name}): ${str}`);
|
||||
}
|
||||
}
|
||||
|
||||
const otherVars = {
|
||||
border: {
|
||||
radius: null,
|
||||
},
|
||||
};
|
||||
const otherThemeVars = createGlobalThemeContract(otherVars, varMapper);
|
||||
export const themeVars = createGlobalThemeContract(vars, varMapper);
|
||||
export type Theme = WithOptionalLayer<MapLeafNodes<typeof themeVars, string>>;
|
||||
export const defineTheme = (theme: Theme) => theme;
|
||||
|
||||
export function createTheme(theme: Theme): void {
|
||||
createGlobalTheme(":root", themeVars, theme);
|
||||
createGlobalTheme(":root", otherThemeVars, {
|
||||
border: {
|
||||
radius: "6px",
|
||||
},
|
||||
});
|
||||
globalStyle(":root", {
|
||||
accentColor: themeVars.color.blue,
|
||||
colorScheme: stringToBoolean(theme.isDarkTheme, "isDarkTheme") ? "dark" : "light",
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { MapLeafNodes } from "src/types";
|
||||
import { color } from "src/vars";
|
||||
import type { MapLeafNodes } from "src/core/types";
|
||||
import * as color from "./color";
|
||||
|
||||
export type Primary = MapLeafNodes<typeof color.primary, string>;
|
||||
export type Secondary = MapLeafNodes<typeof color.secondary, string>;
|
||||
29
src/types/vars.ts
Normal file
29
src/types/vars.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { createGlobalThemeContract } from "@vanilla-extract/css";
|
||||
import * as color from "./color";
|
||||
|
||||
export function varMapper(value: string | null, path: string[]) {
|
||||
if (value === null) {
|
||||
path = path.filter(item => item !== "self");
|
||||
path = path.map(item => item.replace(/^num/, ""));
|
||||
return path.join("-");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const vars = {
|
||||
/** 用于标识当前是否为暗色主题: `"true"` 暗色 `"false"` 亮色 */
|
||||
isDarkTheme: "is-dark-theme",
|
||||
color: {
|
||||
blue: null,
|
||||
primary: color.primary,
|
||||
},
|
||||
};
|
||||
|
||||
const otherVars = {
|
||||
border: {
|
||||
radius: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const themeVars = createGlobalThemeContract(vars, varMapper);
|
||||
export const otherThemeVars = createGlobalThemeContract(otherVars, varMapper);
|
||||
@@ -1,21 +0,0 @@
|
||||
import * as color from "src/vars/color";
|
||||
|
||||
export function varMapper(value: string | null, path: string[]) {
|
||||
if (value === null) {
|
||||
path = path.filter((item) => item !== "self");
|
||||
path = path.map((item) => item.replace(/^num/, ""))
|
||||
return path.join("-");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const vars = {
|
||||
/** 用于标识当前是否为暗色主题: `"true"` 暗色 `"false"` 亮色 */
|
||||
isDarkTheme: "is-dark-theme",
|
||||
color: {
|
||||
blue: null,
|
||||
primary: color.primary,
|
||||
},
|
||||
};
|
||||
|
||||
export { color };
|
||||
@@ -1,15 +1,22 @@
|
||||
import { mix } from "polished";
|
||||
import { css, themeVars } from "src";
|
||||
import { scaleColorLight } from "src/functions";
|
||||
|
||||
const red = "#cc4848";
|
||||
|
||||
export const setting_global = css`
|
||||
@use "sass:color";
|
||||
.lines-num span:after {
|
||||
color: ${themeVars.color.primary.hover};
|
||||
}
|
||||
.ui.cards > .card,
|
||||
.ui.card {
|
||||
> .extra a:not(.ui):hover {
|
||||
color: ${mix(0.1, "#fff", "#cc4848")};
|
||||
background-color: scale-color(#cc4848, $lightness: 10%);
|
||||
color: ${scaleColorLight(red, 10)};
|
||||
background-color: color.scale(#cc4848, $lightness: 10%);
|
||||
}
|
||||
.text {
|
||||
color: ${scaleColorLight(red, -20)};
|
||||
background-color: color.scale(#cc4848, $lightness: -20%);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { color } from "src";
|
||||
import type { Primary } from "src/types";
|
||||
import { defineTheme, themeVars } from "src";
|
||||
|
||||
const dark = {
|
||||
@@ -33,7 +33,7 @@ const alpha = {
|
||||
num90: "#3683c0e1",
|
||||
};
|
||||
|
||||
const primary: color.Primary = {
|
||||
const primary: Primary = {
|
||||
self: themeVars.color.blue,
|
||||
contrast: "#fff",
|
||||
dark,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import * as sass from "sass-embedded";
|
||||
import { defineConfig } from "vite";
|
||||
import { themeInput, themePlugin } from "./src/vite";
|
||||
import { themeInput, themePlugin } from "./src/core/vite";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user