1.26 syntax highlighting and code editor style

css transform from sass to lightningcss
This commit is contained in:
lutinglt committed 2026-05-11 00:20:28 +08:00
1 parent 8cce516dd1
commit 1598de8131
113 files changed
+3148 -2338

No files matched your search

-1
View File
@@ -6,4 +6,3 @@
gitea/** linguist-generated
screenshots/** linguist-vendored
scripts/** linguist-vendored
eslint.config.js linguist-vendored
+2
View File
@@ -1,3 +1,5 @@
### ⚠️ Breaking Changes
### 🎉
### ✨ Feature
Generated Vendored
+1 -8
View File
@@ -1,10 +1,3 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"usernamehw.errorlens",
"mikestead.dotenv",
"styled-components.vscode-styled-components",
"typescriptteam.native-preview"
]
"recommendations": ["styled-components.vscode-styled-components"]
}
Generated Vendored
-3
View File
@@ -1,3 +0,0 @@
{
"typescript.experimental.useTsgo": false
}
+11
View File
@@ -1,11 +1,21 @@
### ⚠️ Breaking Changes
- Because the project uses Lightning CSS to transpile CSS nesting code, it will contain a large number of :is()
selectors, and browsers below Chrome 88 are not supported. Using browsers below Chrome 88 may cause many styling
issues. Please update to Chrome 88 or above.
### ✨ Feature
- Adapt the theme color identification and color blindness identification to the new version of Gitea.
- The theme name for red-green color blindness has been synchronized with GitHub, providing a more accurate display of
the name.
- The CSS transpilation engine has been switched from SASS to LightingCSS. Thanks to the optimization provided by
LightingCSS, the CSS file size has been reduced by 10%.
### 🌈 Style
- Add transition animation to the repository/organization buttons on the dashboard page.
#### Adaptation for version 1.26
- Synchronize avatar administrator logo. #29
@@ -15,6 +25,7 @@
- Optimize the style of the actions page.
- Synchronization shortcut key prompt style.
- Synchronize the style of the pop-up window for file search results in the repository.
- Synchronize code highlighting colors and styles for online file editors.
#### More aligned with GitHub style
+6
View File
@@ -35,6 +35,12 @@ accepted.
## Installation
> [!IMPORTANT]
>
> Because the project uses Lightning CSS to transpile CSS nesting code, it will contain a large number of :is()
> selectors, and browsers below Chrome 88 are not supported. Using browsers below Chrome 88 may cause many styling
> issues. Please update to Chrome 88 or above.
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)
2. Modify `data/gitea/conf/app.ini` and append the CSS filename without the `theme-` prefix to the end of `THEMES` under
+5
View File
@@ -33,6 +33,11 @@ Gitea 理论上小版本号变更不会修改前端布局, 所以主题的小版
## 安装
> [!IMPORTANT]
>
> 因为项目使用了 Lighting CSS 转译 CSS 嵌套代码, 所以会包含大量 :is() 选择器, 不支持 Chrome
> 88 版本以下的浏览器使用 Chrome 88 以下的浏览器可能会出现大量样式问题, 请更新到 Chrome 88 以上版本
1. 在发布页下载最新的 CSS 主题文件放入 `data/gitea/public/assets/css` 目录下 (默认可能没有此目录需手动创建)
2. 修改 `data/gitea/conf/app.ini`,并将 CSS 文件名去掉 `theme-` 的名称附加到 `[ui]` 下的 `THEMES` 末尾
3. 重启 Gitea
+50
View File
@@ -0,0 +1,50 @@
/*!
* 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 js from "@eslint/js";
import { defineConfig } from "eslint/config";
import globals from "globals";
import tseslint from "typescript-eslint";
export default defineConfig([
{
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
plugins: { js },
extends: ["js/recommended"],
languageOptions: {
ecmaVersion: "latest",
globals: globals.browser,
},
rules: {
"@typescript-eslint/no-unused-vars": [
"error",
{
args: "all",
argsIgnorePattern: "^_",
caughtErrors: "all",
caughtErrorsIgnorePattern: "^_",
destructuredArrayIgnorePattern: "^_",
varsIgnorePattern: "^_",
ignoreRestSiblings: true,
},
],
},
},
tseslint.configs.recommended,
]);
+5 -6
View File
@@ -8,7 +8,6 @@
},
"type": "module",
"scripts": {
"dev": "vite build --mode dev",
"build": "tsgo -b && vite build",
"lint": "eslint .",
"format": "prettier --write .",
@@ -24,19 +23,19 @@
"@eslint/js": "^10.0.1",
"@linaria/core": "^7.0.0",
"@types/node": "^25.5.2",
"@typescript/native-preview": "^7.0.0-dev.20260406.1",
"@typescript/native-preview": "^7.0.0-dev.20260509.2",
"@vanilla-extract/css": "^1.20.1",
"@vanilla-extract/vite-plugin": "^5.2.2",
"@wyw-in-js/vite": "^1.0.7",
"dotenv": "^17.4.1",
"eslint": "^10.2.0",
"globals": "^17.4.0",
"eslint": "^10.3.0",
"globals": "^17.6.0",
"jiti": "^2.6.1",
"lightningcss": "^1.32.0",
"polished": "^4.3.1",
"prettier": "3.8.1",
"prettier-plugin-organize-imports": "^4.3.0",
"sass-embedded": "^1.99.0",
"typescript-eslint": "^8.58.0",
"typescript-eslint": "^8.59.1",
"typescript-plugin-css-modules": "^5.2.0",
"undici": "^7.0.0",
"vite": "^8.0.5"
-83
View File
@@ -1,83 +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 { prettylights2Chroma, type prettylightsColor } from "./prettylights";
export const lightPrettylights: prettylightsColor = {
syntax: {
brackethighlighter: { angle: "#59636e", unmatched: "#82071e" },
carriage: { return: { bg: "#cf222e", text: "#f6f8fa" } },
comment: "#59636e",
constant: "#0550ae",
constantOtherReferenceLink: "#0a3069",
entity: "#6639ba",
entityTag: "#0550ae",
invalid: { illegal: { bg: "#82071e", text: "#f6f8fa" } },
keyword: "#cf222e",
markup: {
bold: "#1f2328",
changed: { bg: "#ffd8b5", text: "#953800" },
deleted: { bg: "#ffebe9", text: "#82071e" },
heading: "#0550ae",
ignored: { bg: "#0550ae", text: "#d1d9e0" },
inserted: { bg: "#dafbe1", text: "#116329" },
italic: "#1f2328",
list: "#3b2300",
},
metaDiffRange: "#8250df",
storageModifierImport: "#1f2328",
string: "#0a3069",
stringRegexp: "#116329",
sublimelinterGutterMark: "#818b98",
variable: "#953800",
},
};
export const darkPrettylights: prettylightsColor = {
syntax: {
brackethighlighter: { angle: "#9198a1", unmatched: "#f85149" },
carriage: { return: { bg: "#b62324", text: "#f0f6fc" } },
comment: "#9198a1",
constant: "#79c0ff",
constantOtherReferenceLink: "#a5d6ff",
entity: "#d2a8ff",
entityTag: "#7ee787",
invalid: { illegal: { bg: "#8e1519", text: "#f0f6fc" } },
keyword: "#ff7b72",
markup: {
bold: "#f0f6fc",
changed: { bg: "#5a1e02", text: "#ffdfb6" },
deleted: { bg: "#67060c", text: "#ffdcd7" },
heading: "#1f6feb",
ignored: { bg: "#1158c7", text: "#f0f6fc" },
inserted: { bg: "#033a16", text: "#aff5b4" },
italic: "#f0f6fc",
list: "#f2cc60",
},
metaDiffRange: "#d2a8ff",
storageModifierImport: "#f0f6fc",
string: "#a5d6ff",
stringRegexp: "#7ee787",
sublimelinterGutterMark: "#3d444d",
variable: "#ffa657",
},
};
export const defaultLightChroma = prettylights2Chroma(lightPrettylights);
export const defaultDarkChroma = prettylights2Chroma(darkPrettylights);
+23 -17
View File
@@ -19,10 +19,9 @@
import { rgba, saturate } from "polished";
import { scaleColorLight } from "src/functions";
import type { Ansi, Chroma, Console, Diff, Github, Message, Named, Other, Primary, Secondary } from "src/types";
import { themeVars } from "src/types/vars";
import { defaultDarkChroma, defaultLightChroma } from "./chroma";
import type { Theme } from "./theme";
import type { Ansi, Console, Diff, Github, Message, Named, Other, Primary, Secondary } from "src/types";
import { themeVars } from "src/types";
import type { SyntaxConfig, Theme } from "./theme";
export type ThemeColor = {
/** 用于标识当前是否为暗色主题: `true` 暗色 `false` 亮色 */
@@ -78,6 +77,10 @@ export type ThemeColor = {
github: Github;
};
export type ThemeOptions = {
themeColor: ThemeColor;
} & SyntaxConfig;
/** 定义颜色, 用于生成颜色主题
* @example
* 文件名: "dark.css.ts"
@@ -103,7 +106,7 @@ export type ThemeColor = {
* github,
* })
*/
export function defineTheme(themeColor: ThemeColor, chroma?: Chroma): Theme {
export function defineTheme({ themeColor, ...syntaxConfig }: ThemeOptions): Theme {
const brightDir = themeColor.isDarkTheme ? -1 : 1;
const primary: Primary = {
@@ -391,18 +394,21 @@ export function defineTheme(themeColor: ThemeColor, chroma?: Chroma): Theme {
};
return {
isDarkTheme: themeColor.isDarkTheme.toString(),
chroma: chroma || (themeColor.isDarkTheme ? defaultDarkChroma : defaultLightChroma),
color: {
primary,
secondary,
...named,
ansi,
console: themeColor.console,
diff: themeColor.diff,
...message,
...themeColor.other,
isDarkTheme: themeColor.isDarkTheme,
...syntaxConfig,
themeColors: {
isDarkTheme: themeColor.isDarkTheme.toString(),
color: {
primary,
secondary,
...named,
ansi,
console: themeColor.console,
diff: themeColor.diff,
...message,
...themeColor.other,
},
github: themeColor.github,
},
github: themeColor.github,
};
}
+43 -144
View File
@@ -20,8 +20,7 @@
import { saturate } from "polished";
import type { Console, Diff, Other } from "src";
import { scaleColorLight } from "src/functions";
import type { Github } from "src/types";
import { themeVars } from "src/types/vars";
import { themeVars, type Github } from "src/types";
import { type ThemeColor } from "./color";
export type GithubColor = {
@@ -90,6 +89,8 @@ export type GithubColor = {
bgColor: { active: string; hover: string; rest: string };
transparent: { bgColor: { active: string; hover: string; selected: string } };
};
controlTrack: { bgColor: { rest: string } };
controlKnob: { bgColor: { rest: string } };
shadow: { floating: { small: string }; inset: string; resting: { small: string; medium: string } };
overlay: { backdrop: { bgColor: string }; bgColor: string };
underlineNav: { borderColor: { active: string } };
@@ -103,53 +104,30 @@ export type GithubColor = {
export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
const console: Console = {
fg: {
self: githubColor.fgColor.default,
subtle: githubColor.fgColor.muted,
},
fg: { self: githubColor.fgColor.default, subtle: githubColor.fgColor.muted },
bg: githubColor.bgColor.inset,
border: githubColor.borderColor.muted,
activeBg: githubColor.control.bgColor.active,
hoverBg: githubColor.control.transparent.bgColor.hover,
menu: {
bg: githubColor.overlay.bgColor,
border: githubColor.borderColor.muted,
},
menu: { bg: githubColor.overlay.bgColor, border: githubColor.borderColor.muted },
link: githubColor.fgColor.muted,
};
const diff: Diff = {
added: {
fg: githubColor.bgColor.success.emphasis,
linenum: {
bg: githubColor.diffBlob.addtionNum.bgColor,
},
row: {
bg: githubColor.bgColor.success.muted,
border: githubColor.bgColor.success.muted,
},
word: {
bg: githubColor.diffBlob.addtionWord.bgColor,
},
linenum: { bg: githubColor.diffBlob.addtionNum.bgColor },
row: { bg: githubColor.bgColor.success.muted, border: githubColor.bgColor.success.muted },
word: { bg: githubColor.diffBlob.addtionWord.bgColor },
},
removed: {
fg: githubColor.bgColor.danger.emphasis,
linenum: {
bg: githubColor.diffBlob.deletionNum.bgColor,
},
row: {
bg: githubColor.bgColor.danger.muted,
border: githubColor.bgColor.danger.muted,
},
word: {
bg: githubColor.diffBlob.deletionWord.bgColor,
},
linenum: { bg: githubColor.diffBlob.deletionNum.bgColor },
row: { bg: githubColor.bgColor.danger.muted, border: githubColor.bgColor.danger.muted },
word: { bg: githubColor.diffBlob.deletionWord.bgColor },
},
moved: {
row: {
bg: githubColor.bgColor.attention.muted,
border: githubColor.bgColor.attention.muted,
},
row: { bg: githubColor.bgColor.attention.muted, border: githubColor.bgColor.attention.muted },
},
inactive: githubColor.bgColor.muted,
};
@@ -159,10 +137,7 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
body: githubColor.bgColor.default,
box: {
header: githubColor.bgColor.muted,
body: {
self: themeVars.color.body,
highlight: githubColor.bgColor.accent.muted,
},
body: { self: themeVars.color.body, highlight: githubColor.bgColor.accent.muted },
},
text: {
self: githubColor.fgColor.default,
@@ -182,48 +157,26 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
toggleBackgound: githubColor.bgColor.inset,
border: themeVars.color.light.border,
},
light: {
self: themeVars.color.body,
border: githubColor.borderColor.default,
},
hover: {
self: githubColor.control.bgColor.hover,
opaque: themeVars.color.box.header,
},
light: { self: themeVars.color.body, border: githubColor.borderColor.default },
hover: { self: githubColor.control.bgColor.hover, opaque: themeVars.color.box.header },
active: githubColor.control.transparent.bgColor.selected,
menu: githubColor.overlay.bgColor,
card: themeVars.color.body,
markup: {
tableRow: githubColor.bgColor.muted,
code: {
block: githubColor.bgColor.muted,
inline: githubColor.bgColor.neutral.muted,
},
code: { block: githubColor.bgColor.muted, inline: githubColor.bgColor.neutral.muted },
},
button: githubColor.control.bgColor.rest,
codeBg: "unset",
shadow: {
self: githubColor.shadow.floating.small,
opaque: themeVars.color.shadow.self,
},
shadow: { self: githubColor.shadow.floating.small, opaque: themeVars.color.shadow.self },
secondaryBg: "unset",
expandButton: githubColor.diffBlob.hunkNum.bgColor.rest,
placeholderText: themeVars.color.text.light.num3,
editor: {
lineHighlight: themeVars.color.primary.light.num5,
selection: themeVars.color.editor.lineHighlight,
},
editor: { lineHighlight: themeVars.color.secondary.light.num1, selection: themeVars.color.editor.lineHighlight },
projectColumnBg: githubColor.bgColor.inset,
caret: themeVars.color.text.dark,
reaction: {
bg: "initial",
hoverBg: githubColor.bgColor.accent.muted,
activeBg: githubColor.bgColor.accent.muted,
},
tooltip: {
text: githubColor.fgColor.onEmphasis,
bg: githubColor.bgColor.emphasis,
},
reaction: { bg: "initial", hoverBg: githubColor.bgColor.accent.muted, activeBg: githubColor.bgColor.accent.muted },
tooltip: { text: githubColor.fgColor.onEmphasis, bg: githubColor.bgColor.emphasis },
nav: {
bg: githubColor.bgColor.inset,
hoverBg: githubColor.control.transparent.bgColor.hover,
@@ -238,26 +191,15 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
},
accent: themeVars.color.primary.light.num1,
smallAccent: themeVars.color.primary.light.num5,
highlight: {
fg: githubColor.fgColor.attention,
bg: githubColor.bgColor.attention.muted,
},
highlight: { fg: githubColor.fgColor.attention, bg: githubColor.bgColor.attention.muted },
overlayBackdrop: githubColor.overlay.backdrop.bgColor,
danger: themeVars.color.red.self,
transparency: {
grid: {
light: "#ffffff",
dark: "#e5e5e5",
},
},
transparency: { grid: { light: "#ffffff", dark: "#e5e5e5" } },
workflowEdgeHover: githubColor.bgColor.accent.emphasis,
};
const github: Github = {
avatar: {
bgColor: githubColor.avatar.bgColor,
borderColor: githubColor.avatar.borderColor,
},
avatar: { bgColor: githubColor.avatar.bgColor, borderColor: githubColor.avatar.borderColor },
fgColor: {
accent: githubColor.fgColor.accent,
success: githubColor.fgColor.success,
@@ -265,47 +207,22 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
onEmphasis: githubColor.fgColor.onEmphasis,
},
bgColor: {
accent: {
emphasis: githubColor.bgColor.accent.emphasis,
muted: githubColor.bgColor.accent.muted,
},
success: {
emphasis: githubColor.bgColor.success.emphasis,
},
attention: {
emphasis: githubColor.bgColor.attention.emphasis,
},
danger: {
emphasis: githubColor.bgColor.danger.emphasis,
},
done: {
emphasis: githubColor.bgColor.done.emphasis,
},
neutral: {
emphasis: githubColor.bgColor.neutral.emphasis,
},
accent: { emphasis: githubColor.bgColor.accent.emphasis, muted: githubColor.bgColor.accent.muted },
success: { emphasis: githubColor.bgColor.success.emphasis },
attention: { emphasis: githubColor.bgColor.attention.emphasis },
danger: { emphasis: githubColor.bgColor.danger.emphasis },
done: { emphasis: githubColor.bgColor.done.emphasis },
neutral: { emphasis: githubColor.bgColor.neutral.emphasis },
},
borderColor: {
accent: {
emphasis: githubColor.borderColor.accent.emphasis,
},
attention: {
emphasis: githubColor.borderColor.attention.emphasis,
},
success: {
emphasis: githubColor.borderColor.success.emphasis,
},
done: {
emphasis: githubColor.borderColor.done.emphasis,
},
accent: { emphasis: githubColor.borderColor.accent.emphasis },
attention: { emphasis: githubColor.borderColor.attention.emphasis },
success: { emphasis: githubColor.borderColor.success.emphasis },
done: { emphasis: githubColor.borderColor.done.emphasis },
emphasis: githubColor.borderColor.emphasis,
},
button: {
default: {
bgColor: {
active: githubColor.control.bgColor.active,
},
},
default: { bgColor: { active: githubColor.control.bgColor.active } },
primary: {
fgColor: {
accent: saturate(
@@ -319,39 +236,25 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
hover: githubColor.button.primary.bgColor.hover,
active: githubColor.button.primary.bgColor.active,
},
borderColor: {
rest: githubColor.borderColor.translucent,
hover: githubColor.borderColor.translucent,
},
borderColor: { rest: githubColor.borderColor.translucent, hover: githubColor.borderColor.translucent },
},
danger: {
fgColor: {
rest: githubColor.button.danger.fgColor.rest,
hover: githubColor.button.danger.fgColor.hover,
},
fgColor: { rest: githubColor.button.danger.fgColor.rest, hover: githubColor.button.danger.fgColor.hover },
bgColor: {
rest: githubColor.control.bgColor.rest,
hover: githubColor.button.danger.bgColor.hover,
active: githubColor.button.danger.bgColor.active,
},
borderColor: {
hover: githubColor.borderColor.translucent,
},
},
star: {
iconColor: githubColor.button.star.iconColor,
borderColor: { hover: githubColor.borderColor.translucent },
},
star: { iconColor: githubColor.button.star.iconColor },
},
control: {
bgColor: {
rest: githubColor.control.bgColor.rest,
},
transparent: {
bgColor: {
hover: githubColor.control.transparent.bgColor.hover,
},
},
bgColor: { rest: githubColor.control.bgColor.rest },
transparent: { bgColor: { hover: githubColor.control.transparent.bgColor.hover } },
},
controlTrack: { bgColor: { rest: githubColor.controlTrack.bgColor.rest } },
controlKnob: { bgColor: { rest: githubColor.controlKnob.bgColor.rest } },
shadow: {
floating: {
small: `0px 0px 0px 1px ${themeVars.color.light.border}, 0px 6px 12px -3px ${themeVars.color.shadow.self}, 0px 6px 18px 0px ${themeVars.color.shadow.self};`,
@@ -363,11 +266,7 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
medium: `drop-shadow(0 1px 1px ${githubColor.shadow.floating.small}) drop-shadow(0 3px 6px ${githubColor.shadow.resting.medium})`,
},
},
underlineNav: {
borderColor: {
active: githubColor.underlineNav.borderColor.active,
},
},
underlineNav: { borderColor: { active: githubColor.underlineNav.borderColor.active } },
contribution: {
default: {
bgColor: {
@@ -17,9 +17,10 @@
* limitations under the License.
*/
import type { Chroma } from "src/types";
import { type Chroma, type CodeMirror } from "src/types";
import type { GithubColor } from "./github";
export type prettylightsColor = {
export type PrettylightsColor = {
syntax: {
brackethighlighter: { angle: string; unmatched: string };
carriage: { return: { bg: string; text: string } };
@@ -49,7 +50,30 @@ export type prettylightsColor = {
};
};
export function prettylights2Chroma(prettylights: prettylightsColor): Chroma {
export type CodeMirrorColor = {
syntax: {
fgColor: {
comment: string;
constant: string;
entity: string;
keyword: string;
storage: string;
string: string;
support: string;
variable: string;
};
};
matchingBracket?: {
fgColor?: string;
};
};
export type GitHubSyntax = {
prettyLights: PrettylightsColor;
codeMirror: CodeMirrorColor;
};
export function prettylights2Chroma(prettylights: PrettylightsColor): Chroma {
return {
textWhiteSpace: prettylights.syntax.brackethighlighter.unmatched,
err: prettylights.syntax.brackethighlighter.unmatched,
@@ -117,6 +141,7 @@ export function prettylights2Chroma(prettylights: prettylightsColor): Chroma {
operator: {
self: prettylights.syntax.constant,
word: prettylights.syntax.constant,
reserved: prettylights.syntax.keyword,
},
punctuation: prettylights.syntax.markup.bold,
comment: {
@@ -144,3 +169,43 @@ export function prettylights2Chroma(prettylights: prettylightsColor): Chroma {
},
};
}
export function githubSyntax2CodeMirror(githubSyntax: GitHubSyntax, githubColor: GithubColor): CodeMirror {
return {
token: {
keyword: githubSyntax.codeMirror.syntax.fgColor.keyword,
atom: githubSyntax.codeMirror.syntax.fgColor.constant,
bool: githubSyntax.codeMirror.syntax.fgColor.constant,
variableName: githubSyntax.codeMirror.syntax.fgColor.entity,
variableName2: githubSyntax.codeMirror.syntax.fgColor.storage,
propertyName: githubSyntax.codeMirror.syntax.fgColor.constant,
typeName: githubSyntax.codeMirror.syntax.fgColor.variable,
className: githubSyntax.codeMirror.syntax.fgColor.variable,
namespace: githubSyntax.codeMirror.syntax.fgColor.variable,
macroName: githubSyntax.prettyLights.syntax.variable,
labelName: githubSyntax.codeMirror.syntax.fgColor.constant,
number: githubSyntax.codeMirror.syntax.fgColor.constant,
string: githubSyntax.codeMirror.syntax.fgColor.string,
string2: githubSyntax.codeMirror.syntax.fgColor.string,
operator: githubSyntax.codeMirror.matchingBracket?.fgColor ?? githubColor.fgColor.default,
punctuation: githubSyntax.codeMirror.matchingBracket?.fgColor ?? githubColor.fgColor.default,
comment: githubSyntax.codeMirror.syntax.fgColor.comment,
meta: githubSyntax.codeMirror.syntax.fgColor.support,
invalid: githubSyntax.codeMirror.syntax.fgColor.keyword,
link: githubSyntax.codeMirror.syntax.fgColor.string,
heading: githubSyntax.codeMirror.syntax.fgColor.entity,
emphasis: githubSyntax.codeMirror.syntax.fgColor.comment,
strong: githubSyntax.codeMirror.syntax.fgColor.comment,
inserted: githubSyntax.codeMirror.syntax.fgColor.string,
deleted: githubSyntax.codeMirror.syntax.fgColor.keyword,
},
language: {
json: githubSyntax.codeMirror.syntax.fgColor.constant,
json5: githubSyntax.codeMirror.syntax.fgColor.constant,
yaml: githubSyntax.codeMirror.syntax.fgColor.constant,
css: githubSyntax.codeMirror.syntax.fgColor.constant,
html: githubSyntax.codeMirror.syntax.fgColor.constant,
xml: githubSyntax.codeMirror.syntax.fgColor.constant,
},
};
}
+6
View File
@@ -17,4 +17,10 @@
* limitations under the License.
*/
export { defineTheme, type ThemeColor } from "./color";
export { display2GithubColor, type DisplayColor } from "./display";
export { github2ThemeColor, type GithubColor } from "./github";
export type { GitHubSyntax } from "./githubSyntax";
export { createTheme } from "./theme";
export type { Theme } from "./theme";
export type { CSSVarFunction, MapLeafNodes } from "./types";
+30 -9
View File
@@ -18,20 +18,34 @@
*/
import { createGlobalTheme, globalKeyframes, globalStyle } from "@vanilla-extract/css";
import { otherThemeVars, themeInfoVars, themeVars } from "src/types/vars";
import * as selectors from "./selectors";
import type { MapLeafNodes, WithOptionalLayer } from "./types";
import { selectors } from "src";
import { createChroma, createCodeMirror } from "src/styles";
import { otherThemeVars, syntaxVars, themeVars, type Syntax } from "src/types";
import type { GithubColor } from "./github";
import { githubSyntax2CodeMirror, prettylights2Chroma, type GitHubSyntax } from "./githubSyntax";
import type { MapLeafNodes } from "./types";
export type Theme = WithOptionalLayer<MapLeafNodes<typeof themeVars, string>>;
/** 语法高亮配置
* - "github": 使用 GitHub Syntax 代码高亮配色
* - "gitea": 使用 Gitea Syntax 代码高亮配色
*/
export type SyntaxConfig =
| { syntaxType: "github"; syntaxColors: GitHubSyntax; githubColors: GithubColor }
| { syntaxType: "gitea"; syntaxColors: Syntax };
export type Theme = {
isDarkTheme: boolean;
themeColors: MapLeafNodes<typeof themeVars, string>;
} & SyntaxConfig;
// vite define 编译时注入的常量
declare const __THEME_VERSION__: string;
export function createTheme(theme: Theme): void {
const isDarkTheme: boolean = JSON.parse(theme.isDarkTheme);
// 注入主题标识版本号
createGlobalTheme(selectors.root, { theme: { version: `"${__THEME_VERSION__}"` } });
// 全局主题变量
createGlobalTheme(selectors.root, themeInfoVars, { version: `"${__THEME_VERSION__}"` });
createGlobalTheme(selectors.root, themeVars, theme);
createGlobalTheme(selectors.root, themeVars, theme.themeColors);
createGlobalTheme(selectors.root, otherThemeVars, {
border: { radius: "6px" },
color: { git: "#f05133" },
@@ -40,9 +54,9 @@ export function createTheme(theme: Theme): void {
// 全局样式
globalStyle(selectors.root, {
accentColor: themeVars.color.accent,
colorScheme: isDarkTheme ? "dark" : "light",
colorScheme: theme.isDarkTheme ? "dark" : "light",
});
if (isDarkTheme) globalStyle(selectors.emoji, { filter: "invert(100%) hue-rotate(180deg)" });
if (theme.isDarkTheme) globalStyle(selectors.emoji, { filter: "invert(100%) hue-rotate(180deg)" });
// 全局动画
globalKeyframes(selectors.overlayAppear, {
"0%": { opacity: 0 },
@@ -56,4 +70,11 @@ export function createTheme(theme: Theme): void {
"0%": { opacity: 0, transform: "translateY(8px)" },
"100%": { opacity: 1, transform: "translateY(0)" },
});
// 代码高亮
if (theme.syntaxType === "github") {
createChroma(prettylights2Chroma(theme.syntaxColors.prettyLights));
createCodeMirror(githubSyntax2CodeMirror(theme.syntaxColors, theme.githubColors));
} else {
createGlobalTheme(selectors.root, syntaxVars, theme.syntaxColors);
}
}
View File
File renamed without changes.
-198
View File
@@ -1,198 +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 { execSync } from "node:child_process";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import type { Plugin } from "vite";
const suffix = ".css.ts";
/**
* 生成主题输入
* @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, mode: string): { [key: string]: string } {
const hash = crypto.randomBytes(6).toString("hex");
const tmpDir = `${outDir}/tmp-${hash}`; // 输出目录下的临时目录
fs.mkdirSync(tmpDir, { recursive: true });
const input: { [key: string]: string } = {};
const themeEntries = fs.readdirSync(themeDir, { withFileTypes: true });
const devTheme = process.env.DEV_THEME || "dark"; // 开发模式仅打包单个颜色主题
for (const entry of themeEntries) {
// 目录下所有的 css.ts 文件都作为主题入口
if (entry.isFile() && entry.name.endsWith(suffix)) {
const fileName = entry.name.replace(suffix, "");
// 开发模式只打包 devTheme 主题
if (mode === "dev" && fileName !== devTheme) continue;
// 创建颜色主题的 css.ts 文件, vanilla-extract 需要这个文件后缀名并生成 css
const tmpCssTs = path.join(tmpDir, `${fileName}${suffix}`);
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}`);
// 生成主题入口的 .ts 文件, 合并样式和颜色主题
const tmpInputTs = path.join(tmpDir, `${fileName}.ts`);
const stylesImport = `import "styles";`;
const cssImport = `import "./${fileName}${suffix}";`;
fs.writeFileSync(tmpInputTs, `${stylesImport}\n${cssImport}`);
input[fileName] = tmpInputTs;
}
}
if (mode === "dev") {
console.log("[themeInput] devTheme:", devTheme);
}
return input;
}
const colorBlindMap: Record<string, string> = {
colorblind: "red-green",
tritanopia: "blue-yellow",
};
function giteaThemeMetaInfo(nameGroup: string[]): string {
const colorScheme = nameGroup[nameGroup.length - 1];
const colorBlindKey = nameGroup.find(word => word in colorBlindMap);
const colorBlindType = colorBlindKey ? colorBlindMap[colorBlindKey] : "";
// 将色盲名称放在最后
// 调整顺序: 去除 colorBlindKey 和 colorScheme, 把 colorScheme 放回倒数第二, colorBlindKey 替换后放末尾
const sorted = [
...nameGroup.filter(word => word !== colorBlindKey && word !== colorScheme),
colorScheme,
...(colorBlindKey
? colorBlindKey === "colorblind"
? ["protanopia", "and", "deuteranopia"]
: [colorBlindKey]
: []),
];
const displayName = sorted.map(word => word[0].toUpperCase() + word.slice(1).toLowerCase()).join(" ");
return `gitea-theme-meta-info {
--theme-display-name: "GitHub ${displayName}";${colorBlindType ? `\n --theme-colorblind-type: "${colorBlindType}";` : ""}
--theme-color-scheme: "${colorScheme}";
}
`; // 不要省略分号, 也不要追加任何变量, 否则 Gitea 不识别
}
const prefix = "theme-github-";
/**
* 生成主题文件
* @important vite.rollupOptions.output 配置 `assetFileNames: "[name].[ext]"`
*/
export function themePlugin(): Plugin {
return {
name: "themePlugin",
generateBundle(this, _, bundle) {
let styles = "";
for (const [key, value] of Object.entries(bundle)) {
if (value.type === "chunk") {
delete bundle[key]; // 删除 chunk
} else {
// 样式文件是通过入口导入的, 没有原始文件名
if (value.originalFileNames.length === 0) {
// 收集所有的样式文件(逻辑上只有一个)
// vite 会在尾部添加注释, 后续会合并到颜色主题, 此处需要删除注释
styles += value.source.toString().replace("/*$vite$:1*/", "");
delete bundle[key];
}
}
}
// 生成所有的主题文件
for (const [key, value] of Object.entries(bundle)) {
// 仅为了类型检查, 逻辑上输出中全是 asset 类型
// vite8 中 bundle 删除后依旧有 styles.css, 追加判断需要有入口的原始文件名
if (value.type === "asset" && value.originalFileNames.length > 0) {
const name = `${prefix}${key}`;
const fileName = `${prefix}${value.fileName}`;
const originalFileName = value.originalFileNames.pop();
const type = value.type;
// 合并样式文件和主题信息
const meta = giteaThemeMetaInfo(key.split(".")[0].split("-"));
const source = `${meta}${value.source.toString()}${styles}`;
// 添加主题到输出
this.emitFile({ name, fileName, source, type, originalFileName });
// 自动颜色主题
const isDark = key.endsWith("dark.css");
const darkName = key.replace("light", "dark");
const lightName = darkName.replace("dark", "light");
const findTheme = isDark ? lightName : darkName;
if (findTheme in bundle) {
const autoName = `${prefix}${darkName.replace("dark", "auto")}`;
const lightContent = `@import "./${prefix}${lightName}" (prefers-color-scheme: light);`;
const darkContent = `@import "./${prefix}${darkName}" (prefers-color-scheme: dark);`;
const nameGroup = key.split(".")[0].split("-").slice(0, -1);
nameGroup.push("auto");
const metaInfo = giteaThemeMetaInfo(nameGroup);
this.emitFile({
name: autoName,
fileName: autoName,
type: "asset",
source: `${lightContent}\n${darkContent}\n${metaInfo}`,
});
}
// 删除原始的样式文件, 自动颜色主题因为删除, 永远不会生成两次
delete bundle[key];
}
}
},
writeBundle() {
// 上传到服务器
const server = process.env.SSH_SERVER;
const user = process.env.SSH_USER || "root";
const theme_path = process.env.GITEA_THEME_PATH;
const gitea_path = process.env.GITEA_PATH;
const sync_tmpl = process.env.SYNC_TMPL === "true";
if (server) {
try {
if (theme_path) {
const cmd = `scp dist/${prefix}*.css ${user}@${server}:${theme_path}`;
console.log("[themePlugin] exec:", cmd);
execSync(cmd, { stdio: "inherit" });
} else {
console.log("[themePlugin] no GITEA_THEME_PATH, skip upload theme");
}
if (gitea_path) {
if (sync_tmpl) {
const cmd = `scp -r templates ${user}@${server}:${gitea_path}`;
console.log("[themePlugin] exec:", cmd);
execSync(cmd, { stdio: "inherit" });
} else {
console.log("[themePlugin] not set SYNC_TMPL=true, skip upload templates");
}
} else {
console.log("[themePlugin] no GITEA_PATH, skip upload templates");
}
} catch (_) {
// continue regardless of error
}
} else {
console.log("[themePlugin] no SSH_SERVER, skip upload");
}
},
};
}
+37
View File
@@ -0,0 +1,37 @@
/*!
* 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.
*/
declare namespace NodeJS {
interface ProcessEnv {
/** 开发环境主题名称 */
DEV_THEME?: string;
/** 主题编译后上传的服务器地址 (通过 SCP 上传) */
SSH_SERVER?: string;
/** 主题编译后上传的服务器用户名 (不支持密码, 请确保有 SSH 免密登录) */
SSH_USER?: string;
/** 上传到服务器的主题目录 (请确保目录存在并使用绝对路径) */
GITEA_THEME_PATH?: string;
/** 上传到服务器的 Gitea 目录 (请使用绝对路径)
* 用于上传模板, 翻译文件
*/
GITEA_PATH?: string;
/** 是否同步模板 */
SYNC_TMPL?: string;
}
}
+1 -1
View File
@@ -18,4 +18,4 @@
*/
export { scaleColorLight } from "./scss";
export { extractVarName, fallbackVar } from "./var";
export { extractVarName } from "./var";
+3 -12
View File
@@ -17,18 +17,8 @@
* limitations under the License.
*/
import type { CSSVarFunction } from "src/core/types";
type CSSFallbackVar = `var(--${string}, ${string})`;
/** 设置 CSS 变量的回退值
* @param cssvar `var(--${string})`
* @param fallback
* @returns `var(--${string}, fallback)`
*/
export function fallbackVar(cssvar: CSSVarFunction, fallback: string): CSSFallbackVar {
const var_name = cssvar.replace("var(--", "").replace(")", "");
return `var(--${var_name}, ${fallback})`;
}
import { assertVarName } from "@vanilla-extract/css";
import type { CSSVarFunction } from "src/core";
type CSSVarName = `--${string}`;
/** 提取 CSS 变量名
@@ -36,6 +26,7 @@ type CSSVarName = `--${string}`;
* @returns `--${string}`
*/
export function extractVarName(cssvar: CSSVarFunction): CSSVarName {
assertVarName(cssvar);
const var_name = cssvar.replace("var(--", "").replace(")", "");
return `--${var_name}`;
}
+9 -4
View File
@@ -17,8 +17,13 @@
* limitations under the License.
*/
export { defaultDarkChroma, defaultLightChroma } from "./core/chroma";
export { defineTheme, type ThemeColor } from "./core/color";
export type { Theme } from "./core/theme";
import selectors from "./selectors";
export { createTheme, defineTheme, display2GithubColor, github2ThemeColor } from "./core";
export type { DisplayColor, GitHubSyntax, GithubColor, ThemeColor } from "./core";
export { extractVarName, scaleColorLight } from "./functions";
export { createThemeMetaInfo } from "./styles";
export { chromaVars, customThemeVars, otherThemeVars, syntaxVars, themeVars } from "./types";
export type { Ansi, Chroma, Console, Diff, Github, Message, Named, Other, Primary, Secondary } from "./types";
export { otherThemeVars, themeVars } from "./types/vars";
export { defineThemeConfig } from "./vite-plugin";
export { selectors };
+19 -5
View File
@@ -17,8 +17,14 @@
* limitations under the License.
*/
export const root = ":root";
export const emoji = `.emoji[aria-label="check mark"],
const root = ":root";
const metaInfo = "gitea-theme-meta-info";
const chroma = ".chroma";
const codeMirror = ".code-editor-container";
const overlayAppear = "overlayAppear";
const overlayAppearDown = "overlayAppearDown";
const overlayAppearUp = "overlayAppearUp";
const emoji = `.emoji[aria-label="check mark"],
.emoji[aria-label="currency exchange"],
.emoji[aria-label="TOP arrow"],
.emoji[aria-label="END arrow"],
@@ -39,6 +45,14 @@ export const emoji = `.emoji[aria-label="check mark"],
.emoji[aria-label="musical note"],
.emoji[aria-label="musical notes"]
`;
export const overlayAppear = "overlayAppear";
export const overlayAppearDown = "overlayAppearDown";
export const overlayAppearUp = "overlayAppearUp";
export default {
root,
metaInfo,
chroma,
codeMirror,
overlayAppear,
overlayAppearDown,
overlayAppearUp,
emoji,
} as const;
+147
View File
@@ -0,0 +1,147 @@
/*!
* 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 { createGlobalTheme, globalStyle, type StyleRule } from "@vanilla-extract/css";
import { selectors } from "src";
import { chromaVars, type Chroma } from "src/types";
function chromaStyle(selector: string, style: StyleRule): void;
function chromaStyle(selector: string[], style: StyleRule): void;
function chromaStyle(selector: string | string[], style: StyleRule): void {
globalStyle((Array.isArray(selector) ? selector : [selector]).map(s => `${selectors.chroma} ${s}`).join(","), style);
}
// 样式来源: https://github.com/go-gitea/gitea/blob/main/web_src/css/chroma/base.css
function createChromaBase(): void {
// LineTableTD
chromaStyle(".lntd", { verticalAlign: "top", padding: 0, margin: 0, border: 0 });
// LineTable
chromaStyle(".lntable", {
borderSpacing: 0,
padding: 0,
margin: 0,
border: 0,
width: "auto",
overflow: "auto",
display: "block",
});
// LineHighlight
chromaStyle(".hl", { display: "block", width: "100%" });
// LineNumbersTable
chromaStyle([".lnt", ".ln"], { marginRight: "0.4em", padding: "0 0.4em" });
// GenericStrong
chromaStyle(".gs", { fontWeight: "var(--font-weight-semibold)" });
// GenericUnderline
chromaStyle(".gl", { textDecoration: "underline" });
}
// 样式来源: https://github.com/alecthomas/chroma/blob/6428fb4e65f3c1493491571c8a6a8f1add1da822/types.go#L208
function createChromaCode(): void {
// TextWhiteSpace
chromaStyle(".w", { color: chromaVars.textWhiteSpace });
// Errorvoid
chromaStyle(".err", { color: chromaVars.err });
// Keyword
chromaStyle(".k", { color: chromaVars.keyword.self });
chromaStyle(".kc", { color: chromaVars.keyword.constant });
chromaStyle(".kd", { color: chromaVars.keyword.declaration });
chromaStyle(".kn", { color: chromaVars.keyword.namespace });
chromaStyle(".kp", { color: chromaVars.keyword.pseudo });
chromaStyle(".kr", { color: chromaVars.keyword.reserved });
chromaStyle(".kt", { color: chromaVars.keyword.type });
// Name
chromaStyle(".n", { color: chromaVars.name.self });
chromaStyle(".na", { color: chromaVars.name.attribute });
chromaStyle(".nb", { color: chromaVars.name.builtin });
chromaStyle(".bp", { color: chromaVars.name.builtinPseudo });
chromaStyle(".nc", { color: chromaVars.name.class });
chromaStyle(".no", { color: chromaVars.name.constant });
chromaStyle(".nd", { color: chromaVars.name.decorator });
chromaStyle(".ni", { color: chromaVars.name.entity });
chromaStyle(".ne", { color: chromaVars.name.exception });
chromaStyle(".nf", { color: chromaVars.name.function });
chromaStyle(".fm", { color: chromaVars.name.functionMagic });
chromaStyle(".py", { color: chromaVars.name.property });
chromaStyle(".nl", { color: chromaVars.name.label });
chromaStyle(".nn", { color: chromaVars.name.namespace });
chromaStyle(".nx", { color: chromaVars.name.other });
chromaStyle(".nt", { color: chromaVars.name.tag });
chromaStyle(".nv", { color: chromaVars.name.variable });
chromaStyle(".vc", { color: chromaVars.name.variableClass });
chromaStyle(".vg", { color: chromaVars.name.variableGlobal });
chromaStyle(".vi", { color: chromaVars.name.variableInstance });
chromaStyle(".vm", { color: chromaVars.name.variableMagic });
// Literal
chromaStyle(".l", { color: chromaVars.literal.self });
chromaStyle(".ld", { color: chromaVars.literal.date });
// String
chromaStyle(".s", { color: chromaVars.string.self });
chromaStyle(".sa", { color: chromaVars.string.affix });
chromaStyle(".sb", { color: chromaVars.string.backtick });
chromaStyle(".sc", { color: chromaVars.string.char });
chromaStyle(".dl", { color: chromaVars.string.delimiter });
chromaStyle(".sd", { color: chromaVars.string.doc });
chromaStyle(".s2", { color: chromaVars.string.double });
chromaStyle(".se", { color: chromaVars.string.escape });
chromaStyle(".sh", { color: chromaVars.string.heredoc });
chromaStyle(".si", { color: chromaVars.string.interpol });
chromaStyle(".sx", { color: chromaVars.string.other });
chromaStyle(".sr", { color: chromaVars.string.regex });
chromaStyle(".s1", { color: chromaVars.string.single });
chromaStyle(".ss", { color: chromaVars.string.symbol });
// Number
chromaStyle(".m", { color: chromaVars.number.self });
chromaStyle(".mb", { color: chromaVars.number.bin });
chromaStyle(".mf", { color: chromaVars.number.float });
chromaStyle(".mh", { color: chromaVars.number.hex });
chromaStyle(".mi", { color: chromaVars.number.integer });
chromaStyle(".il", { color: chromaVars.number.integerLong });
chromaStyle(".mo", { color: chromaVars.number.oct });
// Operator
chromaStyle(".o", { color: chromaVars.operator.self });
chromaStyle(".ow", { color: chromaVars.operator.word });
chromaStyle(".or", { color: chromaVars.operator.reserved });
// Punctuation
chromaStyle(".p", { color: chromaVars.punctuation });
// Comment
chromaStyle(".c", { color: chromaVars.comment.self });
chromaStyle(".ch", { color: chromaVars.comment.hashbang });
chromaStyle(".cm", { color: chromaVars.comment.multiline });
chromaStyle(".cp", { color: chromaVars.comment.preproc });
chromaStyle(".cpf", { color: chromaVars.comment.preprocFile });
chromaStyle(".c1", { color: chromaVars.comment.single });
chromaStyle(".cs", { color: chromaVars.comment.special });
// Generic
chromaStyle(".g", { color: chromaVars.generic.self });
chromaStyle(".gd", { color: chromaVars.generic.deleted });
chromaStyle(".ge", { color: chromaVars.generic.emph });
chromaStyle(".gr", { color: chromaVars.generic.error });
chromaStyle(".gh", { color: chromaVars.generic.heading });
chromaStyle(".gi", { color: chromaVars.generic.inserted });
chromaStyle(".go", { color: chromaVars.generic.output });
chromaStyle(".gp", { color: chromaVars.generic.prompt });
chromaStyle(".gs", { color: chromaVars.generic.strong });
chromaStyle(".gu", { color: chromaVars.generic.subheading });
chromaStyle(".gt", { color: chromaVars.generic.traceback });
chromaStyle(".gl", { color: chromaVars.generic.underline });
}
/** 创建 chroma 样式 */
export function createChroma(chroma: Chroma): void {
createChromaBase();
createChromaCode();
createGlobalTheme(selectors.chroma, chromaVars, chroma);
}
+89
View File
@@ -0,0 +1,89 @@
/*!
* 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 { createGlobalTheme, globalStyle, type StyleRule } from "@vanilla-extract/css";
import { selectors } from "src";
import { codeMirrorVars, type CodeMirror } from "src/types";
function codeMirrorStyle(selector: string, style: StyleRule): void;
function codeMirrorStyle(selector: string[], style: StyleRule): void;
function codeMirrorStyle(selector: string | string[], style: StyleRule): void {
globalStyle(
(Array.isArray(selector) ? selector : [selector]).map(s => `${selectors.codeMirror} ${s}`).join(","),
style
);
}
// 样式来源: https://github.com/go-gitea/gitea/blob/ce089f498bce32305b2d9e8c6adfd8cb7c82f88f/web_src/css/modules/codeeditor.css#L506
function createCodeMirrorBase(): void {
codeMirrorStyle(".tok-keyword", { color: codeMirrorVars.token.keyword });
codeMirrorStyle(".tok-atom", { color: codeMirrorVars.token.atom });
codeMirrorStyle(".tok-bool", { color: codeMirrorVars.token.bool });
codeMirrorStyle(".tok-variableName", { color: codeMirrorVars.token.variableName });
codeMirrorStyle(".tok-variableName2", { color: codeMirrorVars.token.variableName2 });
codeMirrorStyle(".tok-propertyName", { color: codeMirrorVars.token.propertyName });
codeMirrorStyle(".tok-typeName", { color: codeMirrorVars.token.typeName });
codeMirrorStyle(".tok-className", { color: codeMirrorVars.token.className });
codeMirrorStyle(".tok-namespace", { color: codeMirrorVars.token.namespace });
codeMirrorStyle(".tok-macroName", { color: codeMirrorVars.token.macroName });
codeMirrorStyle(".tok-labelName", { color: codeMirrorVars.token.labelName });
codeMirrorStyle(".tok-number", { color: codeMirrorVars.token.number });
codeMirrorStyle(".tok-string", { color: codeMirrorVars.token.string });
codeMirrorStyle(".tok-string2", { color: codeMirrorVars.token.string2 });
codeMirrorStyle(".tok-operator", { color: codeMirrorVars.token.operator });
codeMirrorStyle(".tok-punctuation", { color: codeMirrorVars.token.punctuation });
codeMirrorStyle(".tok-comment", { color: codeMirrorVars.token.comment });
codeMirrorStyle(".tok-meta", { color: codeMirrorVars.token.meta });
codeMirrorStyle(".tok-invalid", { color: codeMirrorVars.token.invalid });
codeMirrorStyle(".tok-link", { color: codeMirrorVars.token.link });
codeMirrorStyle(".tok-heading", { color: codeMirrorVars.token.heading });
codeMirrorStyle(".tok-emphasis", { color: codeMirrorVars.token.emphasis });
codeMirrorStyle(".tok-strong", { color: codeMirrorVars.token.strong });
codeMirrorStyle(".tok-inserted", { color: codeMirrorVars.token.inserted });
codeMirrorStyle(".tok-deleted", { color: codeMirrorVars.token.deleted });
}
// 样式来源: https://github.com/go-gitea/gitea/blob/ce089f498bce32305b2d9e8c6adfd8cb7c82f88f/web_src/css/modules/codeeditor.css#L533
function createCodeMirrorSpecific(): void {
// 语言样式
function langStyle(lang: string, style: StyleRule): void {
globalStyle(`${selectors.codeMirror}[data-language="${lang}"] .tok-propertyName`, style);
}
langStyle("json", { color: codeMirrorVars.language.json });
langStyle("json5", { color: codeMirrorVars.language.json5 });
langStyle("yaml", { color: codeMirrorVars.language.yaml });
langStyle("css", { color: codeMirrorVars.language.css });
langStyle("html", { color: codeMirrorVars.language.html });
langStyle("xml", { color: codeMirrorVars.language.xml });
// 特殊样式
// 语法中导入部分的变量变为命名空间样式
codeMirrorStyle(".tok-punctuation+.tok-variableName.tok-definition", { color: codeMirrorVars.token.namespace });
// 避免锚中变量, 变量后接的是 .tok-operator
codeMirrorStyle(".tok-keyword+.tok-variableName.tok-definition:has(+.tok-punctuation)", {
color: codeMirrorVars.token.namespace,
});
// keywork + variableName + punctuation + typeName 这种情况还原变量颜色
codeMirrorStyle(".tok-keyword+.tok-variableName.tok-definition:has(+.tok-punctuation+.tok-typeName)", {
color: codeMirrorVars.token.variableName,
});
}
/** 创建 CodeMirror 样式 */
export function createCodeMirror(codeMirror: CodeMirror): void {
createCodeMirrorBase();
createCodeMirrorSpecific();
createGlobalTheme(selectors.codeMirror, codeMirrorVars, codeMirror);
}
@@ -17,17 +17,6 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
export const monaco = css`
.monaco-editor {
--vscode-editor-background: ${themeVars.color.body} !important;
--vscode-editorGutter-background: ${themeVars.color.body} !important;
// 滚动时固定在顶部的行
.sticky-widget {
background: ${themeVars.color.body} !important;
box-shadow: 0 1px 0 ${themeVars.color.secondary.self} !important;
width: 100% !important;
}
}
`;
export { createChroma } from "./chroma";
export { createCodeMirror } from "./codemirror";
export { createThemeMetaInfo, type ColorblindType, type GiteaThemeMeta } from "./meta";
+27 -24
View File
@@ -17,29 +17,32 @@
* limitations under the License.
*/
/**
* @author lutinglt
*/
import { createGlobalTheme } from "@vanilla-extract/css";
import { selectors } from "src";
import { defineTheme } from "src";
import { display2GithubColor, type DisplayColor } from "src/core/display";
import { github2ThemeColor } from "src/core/github";
import { lightGithubColors } from "themes/light";
export const pinkLightDisplayColors: DisplayColor = {
num0: "#ffe5f1",
num1: "#fdc9e2",
num2: "#f8a5cf",
num3: "#f184bc",
num4: "#e55da5",
num5: "#ce2c85",
num6: "#b12f79",
num7: "#8e2e66",
num8: "#6e2b53",
num9: "#4d233d",
export type ColorblindType = "red-green" | "blue-yellow";
export type GiteaThemeMeta = {
colorScheme: "dark" | "light" | "auto";
displayName: string;
colorblindType?: ColorblindType;
};
export const pinkLightGithubColors = display2GithubColor(pinkLightDisplayColors, lightGithubColors);
export const pinkLightColors = github2ThemeColor(pinkLightGithubColors);
export default defineTheme(pinkLightColors);
/** 创建 Gitea 主题元信息 */
export function createThemeMetaInfo(meta: GiteaThemeMeta) {
createGlobalTheme(selectors.metaInfo, {
theme: {
color: {
scheme: meta.colorScheme,
},
display: {
name: meta.displayName,
},
...(meta.colorblindType !== undefined
? {
colorblind: {
type: meta.colorblindType,
},
}
: {}),
},
});
}
+4
View File
@@ -210,6 +210,10 @@ export const chroma = {
* @example and or not in is
*/
word: null,
/** 保留运算符
* @example not in is
*/
reserved: null,
},
/** 标点符号
* @example , . : ; ( ) [ ] { }
+150
View File
@@ -0,0 +1,150 @@
/*!
* 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.
*/
// 注释来自 AI
export const codeMirror = {
token: {
/** 关键字
* @example if else return function var let const
*/
keyword: null,
/** 原子值
* @example true false null undefined
*/
atom: null,
/** 布尔值
* @example true false
*/
bool: null,
/** 变量名
* @example const foo = 1 中的 foo
*/
variableName: null,
/** 二级作用域变量名
* @example 函数参数、局部变量
*/
variableName2: null,
/** 属性名
* @example obj.name 中的 name
*/
propertyName: null,
/** 类型名
* @example TypeScript 的 type、interface 名
*/
typeName: null,
/** 类名
* @example class MyClass 中的 MyClass
*/
className: null,
/** 命名空间
* @example namespace Foo 中的 Foo
*/
namespace: null,
/** 宏名
* @example C 的 #define 宏名, Rust 的 macro_rules!
*/
macroName: null,
/** 标签名
* @example goto label:, C 的 switch case 标签
*/
labelName: null,
/** 数字字面量
* @example 123 3.14 0xFF
*/
number: null,
/** 字符串字面量
* @example "hello" 'world'
*/
string: null,
/** 二级字符串
* @example 模板字符串、正则字面量
*/
string2: null,
/** 运算符
* @example + - * / = == &&
*/
operator: null,
/** 标点符号
* @example , . : ; ( ) [ ] { }
*/
punctuation: null,
/** 注释
* @example // 单行注释 多行注释
*/
comment: null,
/** 元信息
* @example 预处理器指令、装饰器标记
*/
meta: null,
/** 无效/错误语法
* @example 语法错误的标记
*/
invalid: null,
/** 链接
* @example Markdown 中的 [link](url)
*/
link: null,
/** 标题
* @example Markdown 中的 # Heading
*/
heading: null,
/** 强调 (斜体)
* @example Markdown 中的 *italic*
*/
emphasis: null,
/** 加粗
* @example Markdown 中的 **bold**
*/
strong: null,
/** 新增内容
* @example diff 中的 + 新增行
*/
inserted: null,
/** 删除内容
* @example diff 中的 - 删除行
*/
deleted: null,
},
language: {
/** JSON 语言中属性名的颜色
* @example {"key": "value"} 中的 key
*/
json: null,
/** JSON5 语言中属性名的颜色
* @example {unquotedKey: 'value'} 中的 unquotedKey
*/
json5: null,
/** YAML 语言中属性名的颜色
* @example key: value 中的 key
*/
yaml: null,
/** CSS 语言中属性名的颜色
* @example .selector { property: value; } 中的 property
*/
css: null,
/** HTML 语言中属性名的颜色
* @example <div class="foo"> 中的 class
*/
html: null,
/** XML 语言中属性名的颜色
* @example <element attr="value"> 中的 attr
*/
xml: null,
},
};
+16
View File
@@ -254,6 +254,22 @@ export const github = {
},
},
},
controlTrack: {
bgColor: {
/** 背景色
* @compact_menu `smallCompactMenu` 背景色
*/
rest: null,
},
},
controlKnob: {
bgColor: {
/** 背景色
* @compact_menu `smallCompactMenu` 激活项背景色
*/
rest: null,
},
},
shadow: {
floating: {
/** 悬浮阴影
+26 -8
View File
@@ -17,11 +17,29 @@
* limitations under the License.
*/
export { chroma } from "./chroma";
export { ansi, console } from "./console";
export { diff } from "./diff";
export { github } from "./github";
export { primary, secondary } from "./main";
export { message } from "./message";
export { named } from "./named";
export { other, otherAuto } from "./other";
import { chroma } from "./chroma";
import { codeMirror } from "./codemirror";
import { ansi, console } from "./console";
import { diff } from "./diff";
import { github } from "./github";
import { primary, secondary } from "./main";
import { message } from "./message";
import { named } from "./named";
import { other, otherAuto } from "./other";
import { syntax } from "./syntax";
export default {
chroma,
ansi,
codeMirror,
console,
diff,
github,
primary,
secondary,
message,
named,
other,
otherAuto,
syntax,
};
+104
View File
@@ -0,0 +1,104 @@
/*!
* 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.
*/
// 注释来自 AI
export const syntax = {
/** 关键字 */
keyword: null,
/** 布尔值 */
bool: null,
/** 控制流关键字 */
control: null,
/** 标识符名称 */
name: null,
/** 类型 */
type: null,
/** 数字 */
number: null,
/** 运算符 */
operator: null,
/** 正则表达式 */
regexp: null,
/** 字符串 */
string: null,
/** 注释 */
comment: null,
/** 无效标记 */
invalid: null,
/** 链接 */
link: null,
/** 标签 */
tag: null,
/** 属性 */
attribute: null,
/** 属性 */
property: null,
/** 变量 */
variable: null,
/** 特殊字符串 */
stringSpecial: "color-syntax-string-special",
/** 转义字符 */
escape: null,
/** 实体 */
entity: null,
/** 预处理器注释 */
preproc: null,
/** 预处理器文件注释 */
preprocFile: "color-syntax-preproc-file",
/** 装饰器 */
decorator: null,
/** 命名空间 */
namespace: null,
/** 标识符伪名称 */
namePseudo: "color-syntax-name-pseudo",
/** 特殊注释 */
commentSpecial: "color-syntax-comment-special",
/** 文本 */
text: null,
/** 备用文本颜色 */
textAlt: "color-syntax-text-alt",
/** 标点符号 */
punctuation: null,
/** 空白字符 */
whitespace: null,
/** 差异前景色 */
diffFg: "color-syntax-diff-fg",
/** 删除内容背景色 */
deletedBg: "color-syntax-deleted-bg",
/** 插入内容背景色 */
insertedBg: "color-syntax-inserted-bg",
/** 斜体强调 */
emph: null,
/** 粗体强调 */
strong: null,
/** 标题 */
heading: null,
/** 子标题 */
subheading: null,
/** 输出文本 */
output: null,
/** 提示符 */
prompt: null,
/** 堆栈跟踪 */
traceback: null,
/** 匹配括号背景色 */
matchingBracketBg: "color-syntax-matching-bracket-bg",
/** 不匹配括号背景色 */
nonmatchingBracketBg: "color-syntax-nonmatching-bracket-bg",
};
+9 -3
View File
@@ -17,11 +17,15 @@
* limitations under the License.
*/
import type { MapLeafNodes } from "src/core/types";
import * as color from "./color";
import type { MapLeafNodes } from "src/core";
import color from "./color";
/** 代码高亮色 */
/** GitHub 预览代码高亮色 */
export type Chroma = MapLeafNodes<typeof color.chroma, string>;
/** GitHub 编辑代码高亮色 */
export type CodeMirror = MapLeafNodes<typeof color.codeMirror, string>;
/** Gitea 代码高亮色 */
export type Syntax = MapLeafNodes<typeof color.syntax, string>;
/** 主色调(强调色) */
export type Primary = MapLeafNodes<typeof color.primary, string>;
/** 副色调(边框色) */
@@ -40,3 +44,5 @@ export type Diff = MapLeafNodes<typeof color.diff, string>;
export type Other = MapLeafNodes<typeof color.other, string>;
/** 仅限本主题的 Github 颜色 */
export type Github = MapLeafNodes<typeof color.github, string>;
export { chromaVars, codeMirrorVars, customThemeVars, otherThemeVars, syntaxVars, themeVars } from "./vars";
+5 -9
View File
@@ -18,7 +18,7 @@
*/
import { createGlobalThemeContract } from "@vanilla-extract/css";
import * as color from "./color";
import color from "./color";
function varMapper(prefix: string | null = null) {
return (value: string | null, path: string[]) => {
@@ -33,8 +33,8 @@ function varMapper(prefix: string | null = null) {
}
const vars = {
/** Gitea 主题的属性 */
isDarkTheme: "is-dark-theme",
chroma: color.chroma,
color: {
...color.other,
...color.message,
@@ -60,13 +60,9 @@ const customVars = {
org: { repolistColumns: "org-repolist-columns", userlistColumns: "org-userlist-columns" },
};
const themeInfo = {
version: null,
};
export const themeVars = createGlobalThemeContract(vars, varMapper());
export const otherThemeVars = createGlobalThemeContract(otherVars, varMapper());
export const customThemeVars = createGlobalThemeContract(customVars, varMapper("custom"));
export const themeInfoVars = createGlobalThemeContract(themeInfo, varMapper("theme"));
export { css } from "@linaria/core";
export const chromaVars = createGlobalThemeContract(color.chroma, varMapper("chroma"));
export const codeMirrorVars = createGlobalThemeContract(color.codeMirror, varMapper("codeMirror"));
export const syntaxVars = createGlobalThemeContract(color.syntax, varMapper("color-syntax"));
+323
View File
@@ -0,0 +1,323 @@
/*!
* 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 { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin";
import { execSync } from "node:child_process";
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 { Theme } from "src/core";
import type { ColorblindType, GiteaThemeMeta } from "src/styles";
import type { PluginOption } from "vite";
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 其中一个 */
themes: Themes;
};
/**
* 定义主题配置, 规定入口文件必须默认导出此函数的返回值
* 类似 vite 的 defineConfig, 提供类型约束
*/
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;
}
/** Gitea GitHub Theme 主题插件: 解析入口文件, 生成主题 */
export function giteaGitHubThemePlugin(): PluginOption[] {
const PREFIX = "theme-github-";
let themeEntries: ThemeEntry[];
const autoThemeEntries = new Map<string, AutoThemeEntry>();
return [
// createGlobalTheme 直接创建变量时, 仅使用对象值
vanillaExtractPlugin({ identifiers: ({ debugId }) => `${debugId}` }),
{
name: "themePlugin",
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);
// 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("[themePlugin] 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 !== "base" ? `${themeSeries.themeSeriesName}-` : ""}${themeName}`;
}
/** 辅助函数: 将显示名称转为正式名称 */
function buildFullDisplayName(themeSeries: ThemeSeries, displayName: string): string {
return `GitHub${themeSeries.themeSeriesName !== "base" ? ` ${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. 为每个主题生成临时文件
const input: Record<string, string> = {};
for (const entry of themeEntries) {
const { themeName, theme } = entry;
// 创建颜色主题的 css.ts 文件, vanilla-extract 需要这个文件后缀名并生成 css
const tmpCssTs = `${themeName}.css.ts`;
fs.writeFileSync(
path.join(tmpDir, `${tmpCssTs}`),
[
`import { createTheme, createThemeMetaInfo } from "src";`,
`createThemeMetaInfo(${JSON.stringify(entry.meta)});`,
`createTheme(${JSON.stringify(theme)});`,
].join("\n")
);
// 生成主题入口的 .ts 文件, 合并样式和颜色主题
const tmpInputTs = path.join(tmpDir, `${themeName}.ts`);
fs.writeFileSync(tmpInputTs, [`import "styles";`, `import "./${tmpCssTs}";`].join("\n"));
input[themeName] = tmpInputTs;
}
// 6. 生成自动主题入口
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,
};
const tmpCssTs = `${themeName}.css.ts`;
fs.writeFileSync(
path.join(tmpDir, `${tmpCssTs}`),
[`import { createThemeMetaInfo } from "src";`, `createThemeMetaInfo(${JSON.stringify(meta)});`].join("\n")
);
const tmpInputTs = path.join(tmpDir, `${themeName}.ts`);
fs.writeFileSync(tmpInputTs, `import "./${tmpCssTs}";`);
autoThemeEntries.set(themeName, {
darkThemeName: themeSeries.themes.dark.themeName!,
lightThemeName: themeSeries.themes.light.themeName!,
});
input[themeName] = tmpInputTs;
}
}
// 返回合并配置, 注入 rollup input
return {
build: {
rolldownOptions: {
input,
output: { assetFileNames: "[name].[ext]" },
checks: {
// 主题构建一直过慢, 不再检查各插件消耗时间
pluginTimings: false,
},
},
},
};
},
generateBundle(this, _, bundle) {
let styles = "";
for (const [key, value] of Object.entries(bundle)) {
if (value.type === "chunk") {
delete bundle[key]; // 删除 chunk
} else {
// 样式文件是通过入口导入的, 没有原始文件名
if (value.originalFileNames.length === 0) {
// 收集所有的样式文件(逻辑上只有一个)
// vite 会在尾部添加注释, 后续会合并到颜色主题, 此处需要删除注释
styles += value.source.toString().replace("/*$vite$:1*/", "");
delete bundle[key];
}
}
}
// 生成所有的主题文件
for (const [_key, value] of Object.entries(bundle)) {
// 仅为了类型检查, 逻辑上输出中全是 asset 类型
// vite8 中 bundle 删除后依旧有 styles.css, 追加判断需要有入口的原始文件名
if (value.type === "asset" && value.originalFileNames.length > 0) {
// 合并样式文件和主题信息
const themeName = path.basename(value.fileName, ".css");
const autoTheme = autoThemeEntries.get(themeName);
if (autoTheme) {
value.source = [
`@import "./${autoTheme.darkThemeName}.css" (prefers-color-scheme: dark);`,
`@import "./${autoTheme.lightThemeName}.css" (prefers-color-scheme: light);`,
`${value.source.toString()}`,
].join("\n");
} else {
value.source = `${value.source.toString()}${styles}`;
}
}
}
},
writeBundle() {
// 上传到服务器
const server = process.env.SSH_SERVER;
const user = process.env.SSH_USER || "root";
const theme_path = process.env.GITEA_THEME_PATH;
const gitea_path = process.env.GITEA_PATH;
const sync_tmpl = process.env.SYNC_TMPL === "true";
if (server) {
try {
if (theme_path) {
const cmd = `scp dist/${PREFIX}*.css ${user}@${server}:${theme_path}`;
console.log("[themePlugin] exec:", cmd);
execSync(cmd, { stdio: "inherit" });
} else {
console.log("[themePlugin] no GITEA_THEME_PATH, skip upload theme");
}
if (gitea_path) {
if (sync_tmpl) {
const cmd = `scp -r templates ${user}@${server}:${gitea_path}`;
console.log("[themePlugin] exec:", cmd);
execSync(cmd, { stdio: "inherit" });
} else {
console.log("[themePlugin] not set SYNC_TMPL=true, skip upload templates");
}
} else {
console.log("[themePlugin] no GITEA_PATH, skip upload templates");
}
} catch (e) {
console.warn("[themePlugin] upload failed:", e);
}
} else {
console.log("[themePlugin] no SSH_SERVER, skip upload");
}
},
},
];
}
@@ -17,17 +17,18 @@
* limitations under the License.
*/
/**
* @author lutinglt
import type { StyleRule } from "@vanilla-extract/css";
import { otherThemeVars, themeVars } from "src";
/** 激活项后缀样式
* @example 菜单激活子项前面的竖线, 方便识别
*/
import { defineTheme } from "src";
import { display2GithubColor } from "src/core/display";
import { github2ThemeColor } from "src/core/github";
import { softDarkGithubColors } from "themes/soft-dark";
import { pinkDarkDisplayColors } from "./pink-dark.css";
export const pinkSoftDarkGithubColors = display2GithubColor(pinkDarkDisplayColors, softDarkGithubColors, true);
export const pinkSoftDarkColors = github2ThemeColor(pinkSoftDarkGithubColors);
export default defineTheme(pinkSoftDarkColors);
export const activeItemAfterStyle = {
backgroundColor: themeVars.github.borderColor.accent.emphasis,
borderRadius: otherThemeVars.border.radius,
height: "24px",
left: "-8px",
position: "absolute",
top: "calc(50% - 12px)",
width: "4px",
} satisfies StyleRule;
@@ -17,8 +17,8 @@
* limitations under the License.
*/
import { type StyleRule } from "@vanilla-extract/css";
import * as selectors from "./selectors";
import type { StyleRule } from "@vanilla-extract/css";
import { selectors } from "src";
// 出现动画
export const animation = {
@@ -27,12 +27,14 @@ export const animation = {
animationFillMode: "forwards",
animationTimingFunction: "ease-in",
} satisfies StyleRule;
// 向下出现动画
export const animationDown = {
animation: selectors.overlayAppearDown,
animationDuration: "200ms",
animationTimingFunction: "cubic-bezier(0.33, 1, 0.68, 1)",
} satisfies StyleRule;
// 向上出现动画
export const animationUp = {
animation: selectors.overlayAppearUp,
@@ -17,29 +17,20 @@
* limitations under the License.
*/
/**
* @author lutinglt
*/
import type { StyleRule } from "@vanilla-extract/css";
import { themeVars } from "src";
import { defineTheme } from "src";
import { display2GithubColor, type DisplayColor } from "src/core/display";
import { github2ThemeColor } from "src/core/github";
import { darkGithubColors } from "themes/dark";
/** 主色调按钮样式 */
export const primaryButtonStyle = {
color: themeVars.github.button.primary.fgColor.rest,
backgroundColor: themeVars.github.button.primary.bgColor.rest,
borderColor: themeVars.github.button.primary.borderColor.rest,
boxShadow: themeVars.github.shadow.resting.small,
} satisfies StyleRule;
export const pinkDarkDisplayColors: DisplayColor = {
num0: "#2d1524",
num1: "#451c35",
num2: "#65244a",
num3: "#842a5d",
num4: "#ac2f74",
num5: "#d34591",
num6: "#e57bb2",
num7: "#ec8dbd",
num8: "#f4a9cd",
num9: "#f9bed9",
};
export const pinkDarkGithubColors = display2GithubColor(pinkDarkDisplayColors, darkGithubColors);
export const pinkDarkColors = github2ThemeColor(pinkDarkGithubColors);
export default defineTheme(pinkDarkColors);
/** 主色调按钮悬停样式 */
export const primaryButtonHoverStyle = {
color: themeVars.github.button.primary.fgColor.rest,
backgroundColor: themeVars.github.button.primary.bgColor.hover,
borderColor: themeVars.github.button.primary.borderColor.hover,
} satisfies StyleRule;
+23
View File
@@ -0,0 +1,23 @@
/*!
* 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 { activeItemAfterStyle } from "./after";
export { animation, animationDown, animationUp } from "./animation";
export { primaryButtonHoverStyle, primaryButtonStyle } from "./button";
export { botLabelStyle, labelStyle } from "./label";
+12 -13
View File
@@ -17,17 +17,16 @@
* limitations under the License.
*/
import js from "@eslint/js";
import { defineConfig } from "eslint/config";
import globals from "globals";
import tseslint from "typescript-eslint";
import type { StyleRule } from "@vanilla-extract/css";
export default defineConfig({
ignores: ["dist"],
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
});
/** 基本标签样式 */
export const labelStyle = {
padding: "0px 6px",
} satisfies StyleRule;
/** bot 标签样式 */
export const botLabelStyle = {
height: "20px",
padding: "0 6px !important",
marginLeft: "4px",
} satisfies StyleRule;
+2 -1
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// 修改 action 页面 svg 颜色 (主要为了覆盖工作流状态中的白色图标)
export const actionSVG = css`
+15 -14
View File
@@ -17,13 +17,14 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 仓库 Actions 页面
export const actions = css`
// 避免锚中设置界面里的 Actions
/* 避免锚中设置界面里的 Actions */
.page-content.repository.actions:not(.settings) .flex-container {
// Actions 列表
/* Actions 列表 */
.flex-container-nav:before {
content: "Actions";
display: block;
@@ -32,9 +33,9 @@ export const actions = css`
margin-top: 6px;
margin-bottom: 8px;
}
// 工作流列表
/* 工作流列表 */
.flex-container-main {
// 工作流列表标题栏菜单
/* 工作流列表标题栏菜单 */
.ui.top.attached.header {
padding: 16px;
&:has(+ .ui.info.attached.message) {
@@ -44,17 +45,17 @@ export const actions = css`
color: ${themeVars.color.text.light.num1};
}
}
// 事件触发器
/* 事件触发器 */
.ui.info.attached.message {
padding: 18px 16px;
// 事件触发器按钮
/* 事件触发器按钮 */
.ui.mini.button {
padding: 3px 12px;
min-height: 27px;
font-size: 12px;
}
}
// 工作流列表
/* 工作流列表 */
.ui.attached.segment {
padding: 0;
border: 0;
@@ -65,7 +66,7 @@ export const actions = css`
border-top: 0;
font-size: 12px;
// 分支标签按钮
/* 分支标签按钮 */
.run-list-ref {
background-color: ${themeVars.github.bgColor.accent.muted};
color: ${themeVars.github.fgColor.accent};
@@ -78,7 +79,7 @@ export const actions = css`
text-decoration-line: underline !important;
}
}
// 标签右侧任务信息
/* 标签右侧任务信息 */
.run-list-item-right {
color: ${themeVars.color.text.light.num1};
}
@@ -132,11 +133,11 @@ export const label = css`
export const runWorkflow = css`
#runWorkflowDispatchForm {
font-size: 12px;
// 描述类标签
/* 描述类标签 */
.ui.field label {
font-weight: 600;
}
// use workflow from 描述
/* use workflow from 描述 */
.ui.inline.field {
> :first-child {
margin-right: 8px;
@@ -145,7 +146,7 @@ export const runWorkflow = css`
margin-right: 0;
}
}
// 分支选择按钮
/* 分支选择按钮 */
.ui.dropdown.button.branch-selector-dropdown {
padding: 3px 21px 3px 12px;
min-height: 27px;
@@ -159,7 +160,7 @@ export const runWorkflow = css`
.ui.field > label {
margin-bottom: 6px;
}
// 运行工作流按钮
/* 运行工作流按钮 */
.ui.tiny.button {
padding: 0px 8px;
min-height: 27px;
+12 -11
View File
@@ -17,13 +17,14 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 工作流详情页标题
export const actionViewHeader = css`
.action-view-header {
.action-commit-summary {
// yml 文件名
/* yml 文件名 */
> span:first-child {
color: ${themeVars.github.fgColor.accent};
b {
@@ -33,15 +34,15 @@ export const actionViewHeader = css`
a:hover {
text-decoration: inherit;
}
// 提交哈希
/* 提交哈希 */
> a.muted:first-of-type {
text-decoration: underline;
}
// 提交作者
/* 提交作者 */
> a.muted:last-of-type {
font-weight: 600;
}
// 分支标签按钮
/* 分支标签按钮 */
.ui.ui.ui.label {
background-color: ${themeVars.github.bgColor.accent.muted};
border-radius: ${otherThemeVars.border.radius};
@@ -66,7 +67,7 @@ export const actionViewLeft = css`
font-weight: 600;
margin-left: 0.5rem;
}
// 双重确保覆盖原始样式
/* 双重确保覆盖原始样式 */
.job-brief-item.job-brief-item {
border-radius: ${otherThemeVars.border.radius} !important;
padding: 8px;
@@ -88,12 +89,12 @@ export const actionViewLeft = css`
width: 4px;
}
}
// 状态图标
/* 状态图标 */
a > span:first-child {
display: flex;
align-items: center;
}
// 默认隐藏重新运行按钮
/* 默认隐藏重新运行按钮 */
a > svg.link-action {
display: none;
color: ${themeVars.color.console.fg.subtle} !important;
@@ -101,17 +102,17 @@ export const actionViewLeft = css`
color: ${themeVars.color.text.self} !important;
}
}
// 运行时长
/* 运行时长 */
a > span:last-child {
color: ${themeVars.color.console.fg.subtle};
font-size: 12px;
}
// 鼠标移入时显示重新运行按钮
/* 鼠标移入时显示重新运行按钮 */
&:hover a > svg.link-action {
display: inline-block;
}
}
// Run Details 列表
/* Run Details 列表 */
.ui.relaxed.list:last-of-type {
padding: 0;
.item {
+11 -10
View File
@@ -17,8 +17,9 @@
* limitations under the License.
*/
import { animationDown } from "src/core/styles";
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
import { animationDown } from "styles/common";
// 工作流右侧作业步骤日志详情
export const actionViewRight = css`
@@ -26,7 +27,7 @@ export const actionViewRight = css`
box-shadow: ${themeVars.github.shadow.resting.small};
/* 提前加载高度和滚动条 */
min-height: calc(100vh - 245px);
// 作业详情页标题
/* 作业详情页标题 */
.job-info-header {
padding: 16px 12px 16px 24px !important;
height: 80px !important;
@@ -59,14 +60,14 @@ export const actionViewRight = css`
padding: 8px;
.job-step-section {
margin: 0 4px 4px;
// 步骤标题, 双重确保覆盖原始样式
/* 步骤标题, 双重确保覆盖原始样式 */
.job-step-summary.job-step-summary {
color: ${themeVars.color.console.fg.subtle};
padding: 8px !important;
height: 36px;
&.selected {
// 滚动时固定在顶部的高度与 job-info-header 高度相同
/* 滚动时固定在顶部的高度与 job-info-header 高度相同 */
top: 80px;
}
@@ -91,25 +92,25 @@ export const actionViewRight = css`
color: ${themeVars.color.console.fg.self} !important;
}
}
// 步骤耗时
/* 步骤耗时 */
.step-summary-duration {
font-size: 12px;
font-family: var(--fonts-monospace);
}
}
// 步骤日志
/* 步骤日志 */
.job-step-logs {
${animationDown};
/* 日志字体颜色白色 */
.job-log-line {
color: ${themeVars.color.console.fg.self};
// 日志
/* 日志 */
.log-msg:hover {
//被 hover 时覆盖 ANSI 颜色
/*被 hover 时覆盖 ANSI 颜色 */
* {
color: ${themeVars.color.console.fg.self};
}
// 日志超链接
/* 日志超链接 */
a:hover {
color: ${themeVars.color.primary.self} !important;
}
+20 -19
View File
@@ -17,23 +17,24 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
export const summaryView = css`
.action-view-right:has(.action-run-summary-view) {
min-height: auto;
}
.action-view-right .action-run-summary-view {
// 工作流运行信息
/* 工作流运行信息 */
.action-run-summary-block {
background: ${themeVars.color.body};
> .flex-text-block {
// 工作流触发方式和触发时间
/* 工作流触发方式和触发时间 */
&:first-child {
font-size: 12px;
gap: 4px;
}
// 工作流运行状态和运行时间
/* 工作流运行状态和运行时间 */
&:last-child {
color: ${themeVars.color.console.fg.self};
gap: 8px;
@@ -44,25 +45,25 @@ export const summaryView = css`
}
}
}
// 流程图
/* 流程图 */
.workflow-graph {
// 流程图工作流信息标题
/* 流程图工作流信息标题 */
.graph-header {
background: ${themeVars.color.console.bg};
border-bottom: 0;
padding: 16px;
gap: 16px;
// 流程图标题(目前仅为解释, 内容为 Workflow Dependencies), 无需显示
/* 流程图标题(目前仅为解释, 内容为 Workflow Dependencies), 无需显示 */
.graph-title {
display: none;
}
// 流程图信息
/* 流程图信息 */
.graph-stats {
align-self: flex-start;
font-size: 12px;
column-gap: 4px;
}
// 流程图操作按钮组
/* 流程图操作按钮组 */
> .flex-text-block {
gap: 8px;
.ui.compact.tiny.button {
@@ -73,21 +74,21 @@ export const summaryView = css`
}
}
}
// 流程图
/* 流程图 */
.graph-container {
background: ${themeVars.color.console.bg};
.graph-svg {
// 节点之间的连线
/* 节点之间的连线 */
.node-edge {
stroke: ${themeVars.color.light.border};
stroke-width: 2px;
}
// 高亮连线
/* 高亮连线 */
.highlighted-edge {
stroke-width: 3px !important;
}
&:has(.highlighted-edge) {
// 有高亮线时, 降低其他线的颜色, 避免后面 path 未高亮元素遮挡高亮线
/* 有高亮线时, 降低其他线的颜色, 避免后面 path 未高亮元素遮挡高亮线 */
.node-edge {
opacity: 0.3;
&.highlighted-edge {
@@ -96,12 +97,12 @@ export const summaryView = css`
}
}
.job-node-group {
// 节点
/* 节点 */
.job-rect {
fill: ${themeVars.github.workflowCardBg};
stroke-width: 1px;
}
// 节点上的端口
/* 节点上的端口 */
.node-port {
r: 5.5;
fill: ${themeVars.github.bgColor.neutral.emphasis};
@@ -110,19 +111,19 @@ export const summaryView = css`
}
&:hover {
filter: ${themeVars.github.shadow.resting.medium};
// 保留 Gitea 节点悬浮色, 因为无法实现 GitHub 悬浮时降低其他节点颜色
/* 保留 Gitea 节点悬浮色, 因为无法实现 GitHub 悬浮时降低其他节点颜色 */
.job-rect {
fill: ${themeVars.color.hover.self};
}
// 节点上的端口
/* 节点上的端口 */
.node-port {
fill: ${themeVars.color.workflowEdgeHover};
}
}
// 节点上的步骤状态图标
/* 节点上的步骤状态图标 */
.job-status-icon-wrap {
span {
line-height: 1; // 使图标垂直居中
line-height: 1; /* 使图标垂直居中 */
}
}
}
-305
View File
@@ -1,305 +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 { css, themeVars } from "src/types/vars";
// https://github.com/go-gitea/gitea/blob/main/web_src/css/chroma/base.css
export const chromaBase = css`
.chroma {
// LineTableTD
.lntd {
vertical-align: top;
padding: 0;
margin: 0;
border: 0;
}
// LineTable
.lntable {
border-spacing: 0;
padding: 0;
margin: 0;
border: 0;
width: auto;
overflow: auto;
display: block;
}
// LineHighlight
.hl {
display: block;
width: 100%;
}
// LineNumbersTable
.lnt,
// LineNumbers
.ln {
margin-right: 0.4em;
padding: 0 0.4em;
}
// GenericStrong
.gs {
font-weight: var(--font-weight-semibold);
}
// GenericUnderline
.gl {
text-decoration: underline;
}
}
`;
// https://github.com/alecthomas/chroma/blob/6428fb4e65f3c1493491571c8a6a8f1add1da822/types.go#L208
export const chromaCode = css`
.chroma {
// TextWhiteSpace
.w {
color: ${themeVars.chroma.textWhiteSpace};
}
// Error
.err {
color: ${themeVars.chroma.err};
}
// Keyword
.k {
color: ${themeVars.chroma.keyword.self};
}
.kc {
color: ${themeVars.chroma.keyword.constant};
}
.kd {
color: ${themeVars.chroma.keyword.declaration};
}
.kn {
color: ${themeVars.chroma.keyword.namespace};
}
.kp {
color: ${themeVars.chroma.keyword.pseudo};
}
.kr {
color: ${themeVars.chroma.keyword.reserved};
}
.kt {
color: ${themeVars.chroma.keyword.type};
}
// Name
.n {
color: ${themeVars.chroma.name.self};
}
.na {
color: ${themeVars.chroma.name.attribute};
}
.nb {
color: ${themeVars.chroma.name.builtin};
}
.bp {
color: ${themeVars.chroma.name.builtinPseudo};
}
.nc {
color: ${themeVars.chroma.name.class};
}
.no {
color: ${themeVars.chroma.name.constant};
}
.nd {
color: ${themeVars.chroma.name.decorator};
}
.ni {
color: ${themeVars.chroma.name.entity};
}
.ne {
color: ${themeVars.chroma.name.exception};
}
.nf {
color: ${themeVars.chroma.name.function};
}
.fm {
color: ${themeVars.chroma.name.functionMagic};
}
.py {
color: ${themeVars.chroma.name.property};
}
.nl {
color: ${themeVars.chroma.name.label};
}
.nn {
color: ${themeVars.chroma.name.namespace};
}
.nx {
color: ${themeVars.chroma.name.other};
}
.nt {
color: ${themeVars.chroma.name.tag};
}
.nv {
color: ${themeVars.chroma.name.variable};
}
.vc {
color: ${themeVars.chroma.name.variableClass};
}
.vg {
color: ${themeVars.chroma.name.variableGlobal};
}
.vi {
color: ${themeVars.chroma.name.variableInstance};
}
.vm {
color: ${themeVars.chroma.name.variableMagic};
}
// Literal
.l {
color: ${themeVars.chroma.literal.self};
}
.ld {
color: ${themeVars.chroma.literal.date};
}
// String
.s {
color: ${themeVars.chroma.string.self};
}
.sa {
color: ${themeVars.chroma.string.affix};
}
.sb {
color: ${themeVars.chroma.string.backtick};
}
.sc {
color: ${themeVars.chroma.string.char};
}
.dl {
color: ${themeVars.chroma.string.delimiter};
}
.sd {
color: ${themeVars.chroma.string.doc};
}
.s2 {
color: ${themeVars.chroma.string.double};
}
.se {
color: ${themeVars.chroma.string.escape};
}
.sh {
color: ${themeVars.chroma.string.heredoc};
}
.si {
color: ${themeVars.chroma.string.interpol};
}
.sx {
color: ${themeVars.chroma.string.other};
}
.sr {
color: ${themeVars.chroma.string.regex};
}
.s1 {
color: ${themeVars.chroma.string.single};
}
.ss {
color: ${themeVars.chroma.string.symbol};
}
// Number
.m {
color: ${themeVars.chroma.number.self};
}
.mb {
color: ${themeVars.chroma.number.bin};
}
.mf {
color: ${themeVars.chroma.number.float};
}
.mh {
color: ${themeVars.chroma.number.hex};
}
.mi {
color: ${themeVars.chroma.number.integer};
}
.il {
color: ${themeVars.chroma.number.integerLong};
}
.mo {
color: ${themeVars.chroma.number.oct};
}
// Operator
.o {
color: ${themeVars.chroma.operator.self};
}
.ow {
color: ${themeVars.chroma.operator.word};
}
// Punctuation
.p {
color: ${themeVars.chroma.punctuation};
}
// Comment
.c {
color: ${themeVars.chroma.comment.self};
}
.ch {
color: ${themeVars.chroma.comment.hashbang};
}
.cm {
color: ${themeVars.chroma.comment.multiline};
}
.cp {
color: ${themeVars.chroma.comment.preproc};
}
.cpf {
color: ${themeVars.chroma.comment.preprocFile};
}
.c1 {
color: ${themeVars.chroma.comment.single};
}
.cs {
color: ${themeVars.chroma.comment.special};
}
// Generic
.g {
color: ${themeVars.chroma.generic.self};
}
.gd {
color: ${themeVars.chroma.generic.deleted};
}
.ge {
color: ${themeVars.chroma.generic.emph};
}
.gr {
color: ${themeVars.chroma.generic.error};
}
.gh {
color: ${themeVars.chroma.generic.heading};
}
.gi {
color: ${themeVars.chroma.generic.inserted};
}
.go {
color: ${themeVars.chroma.generic.output};
}
.gp {
color: ${themeVars.chroma.generic.prompt};
}
.gs {
color: ${themeVars.chroma.generic.strong};
}
.gu {
color: ${themeVars.chroma.generic.subheading};
}
.gt {
color: ${themeVars.chroma.generic.traceback};
}
.gu {
color: ${themeVars.chroma.generic.underline};
}
}
`;
+41 -14
View File
@@ -17,34 +17,40 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { labelStyle } from "styles/public/label/label";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { labelStyle } from "styles/common";
export const dashboard = css`
.page-content.dashboard {
// 仪表板切换控制用户按钮
/* 仪表板切换控制用户按钮 */
.ui.dropdown .menu.context-user-switch .scrolling.menu {
animation: none; // 去掉嵌套菜单导致的多余动画
animation: none; /* 去掉嵌套菜单导致的多余动画 */
box-shadow: 0px 0px 0px 1px ${themeVars.color.light.border} !important;
}
}
// 首页仪表板, 避免选中管理员后台的维护管理面板
/* 首页仪表板, 避免选中管理员后台的维护管理面板 */
.page-content.dashboard.feeds {
// 仓库列表的仓库/组织切换按钮
/* 仓库列表的仓库/组织切换按钮 */
.ui.two.item.menu {
background: ${themeVars.color.hover.self};
background: ${themeVars.github.controlTrack.bgColor.rest};
border: 0;
box-shadow:
0px 0px 0px 1px ${themeVars.color.light.border},
${themeVars.github.shadow.resting.small};
border-radius: 12px;
margin-bottom: 8px;
position: relative;
overflow: hidden;
> .item {
background: unset;
border-radius: 12px;
padding: 6px 12px !important;
position: relative;
z-index: 2;
&.active {
background: ${themeVars.color.menu};
box-shadow:
0px 0px 0px 1px ${themeVars.color.light.border},
${themeVars.github.shadow.resting.small};
background: unset !important;
box-shadow: none !important;
font-weight: 600;
}
&::before {
@@ -59,8 +65,29 @@ export const dashboard = css`
}
}
}
/* 滑块指示器 */
&::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
background: ${themeVars.github.controlKnob.bgColor.rest};
border-radius: 12px;
box-shadow:
0px 0px 0px 1px ${themeVars.color.light.border},
${themeVars.github.shadow.resting.small};
transition: transform 200ms cubic-bezier(0.33, 1, 0.68, 1);
z-index: 1;
pointer-events: none;
}
/* 右侧激活 → 滑块向右滑 */
&:has(> .item:last-child.active)::after {
transform: translateX(100%);
}
}
// 仓库/组织列表标题
/* 仓库/组织列表标题 */
.ui.top.attached.header {
border: 0;
font-size: 20px;
@@ -71,7 +98,7 @@ export const dashboard = css`
border-color: #00000000;
}
}
// 仓库/组织列表
/* 仓库/组织列表 */
.ui.attached.segment {
background-color: ${themeVars.color.menu};
border: unset !important;
@@ -114,7 +141,7 @@ export const dashboard = css`
}
}
}
// 组织列表
/* 组织列表 */
.ui.tab.dashboard-orgs .ui.attached.segment.table {
border-top-left-radius: 12px;
border-top-right-radius: 12px;
+41 -40
View File
@@ -17,8 +17,9 @@
* limitations under the License.
*/
import { fallbackVar } from "src/functions";
import { css, customThemeVars, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { fallbackVar } from "@vanilla-extract/css";
import { customThemeVars, otherThemeVars, themeVars } from "src";
const userRepoVar = fallbackVar(customThemeVars.userRepolistColumns, "2");
const exploreRepoVar = fallbackVar(customThemeVars.explore.repolistColumns, "2");
@@ -26,39 +27,39 @@ const orgRepoVar = fallbackVar(customThemeVars.org.repolistColumns, "1");
// 仓库列表
export const repoList = css`
// 组织
/* 组织 */
.page-content.organization.profile > .ui.container > .ui.stackable > .ui.eleven,
// 用户
/* 用户 */
.page-content.user.profile > .ui.container > .ui.stackable > .ui.twelve,
// 探索
/* 探索 */
.page-content.explore.repositories > .ui.container {
// 排除用户的公开活动页
/* 排除用户的公开活动页 */
> .flex-list:not(#activity-feed) {
display: grid;
> .flex-item {
border: 1px solid ${themeVars.color.light.border};
border-radius: ${otherThemeVars.border.radius};
padding: 16px;
// 仓库头像
/* 仓库头像 */
> .flex-item-leading {
img,
svg {
color: ${themeVars.color.text.light.num1};
}
}
// 仓库信息
/* 仓库信息 */
> .flex-item-main {
// 仓库标题
/* 仓库标题 */
> .flex-item-header {
// 仓库名称
/* 仓库名称 */
> .flex-item-title {
gap: 8px;
// 仓库中间的间隔线
/* 仓库中间的间隔线 */
&:not(a) {
color: ${themeVars.color.text.light.num1};
}
}
// 仓库语言, 星标
/* 仓库语言, 星标 */
> .flex-item-trailing {
color: ${themeVars.color.text.light.num1};
gap: 16px;
@@ -70,15 +71,15 @@ export const repoList = css`
}
}
}
// 描述和更新时间
/* 描述和更新时间 */
> .flex-item-body {
margin-top: 8px;
// 更新时间
/* 更新时间 */
&:last-child {
font-size: 12px;
}
}
// 主题标签
/* 主题标签 */
> .label-list {
margin-top: 8px;
}
@@ -86,19 +87,19 @@ export const repoList = css`
}
}
}
// 仓库列表列数
// 组织
/* 仓库列表列数 */
/* 组织 */
.page-content.organization.profile > .ui.container > .ui.stackable > .ui.eleven > .flex-list {
grid-template-columns: repeat(${orgRepoVar}, 1fr);
gap: min(${orgRepoVar} * 8px, 16px);
}
// 用户
// 排除用户的公开活动页
/* 用户 */
/* 排除用户的公开活动页 */
.page-content.user.profile > .ui.container > .ui.stackable > .ui.twelve > .flex-list:not(#activity-feed) {
grid-template-columns: repeat(${userRepoVar}, 1fr);
gap: min(${userRepoVar} * 8px, 16px);
}
// 探索
/* 探索 */
.page-content.explore.repositories > .ui.container > .flex-list {
grid-template-columns: repeat(${exploreRepoVar}, 1fr);
gap: min(${exploreRepoVar} * 8px, 16px);
@@ -110,9 +111,9 @@ const orgUserVar = fallbackVar(customThemeVars.org.userlistColumns, "2");
// 用户列表
export const userList = css`
// 组织
/* 组织 */
.page-content.organization.members > .ui.container,
// 探索的用户和组织
/* 探索的用户和组织 */
.page-content.explore.users > .ui.container {
> .flex-list {
display: grid;
@@ -121,16 +122,16 @@ export const userList = css`
border-radius: ${otherThemeVars.border.radius};
padding: 16px;
> .flex-item-main {
// 用户名称
/* 用户名称 */
> .flex-item-title {
gap: 8px;
margin-bottom: 8px;
// 用户标签
/* 用户标签 */
> .label {
font-size: 12px;
}
}
// 用户描述
/* 用户描述 */
> .flex-item-body {
font-size: 12px;
svg {
@@ -142,13 +143,13 @@ export const userList = css`
}
}
}
// 用户列表列数
// 组织
/* 用户列表列数 */
/* 组织 */
.page-content.organization.members > .ui.container > .flex-list {
grid-template-columns: repeat(${orgUserVar}, 1fr);
gap: min(${orgUserVar} * 8px, 16px);
}
// 探索的用户和组织
/* 探索的用户和组织 */
.page-content.explore.users > .ui.container > .flex-list {
grid-template-columns: repeat(${exploreUserVar}, 1fr);
gap: min(${exploreUserVar} * 8px, 16px);
@@ -158,17 +159,17 @@ export const userList = css`
// 手机下的仓库和用户列表
export const mobileList = css`
@media (max-width: 767.98px) {
// 组织的仓库列表
/* 组织的仓库列表 */
.page-content.organization.profile > .ui.container > .ui.stackable > .ui.eleven,
// 用户的仓库列表
/* 用户的仓库列表 */
.page-content.user.profile > .ui.container > .ui.stackable > .ui.twelve,
// 探索的仓库列表
/* 探索的仓库列表 */
.page-content.explore.repositories > .ui.container,
// 组织的成员列表
/* 组织的成员列表 */
.page-content.organization.members >.ui.container,
// 探索的用户和组织列表
/* 探索的用户和组织列表 */
.page-content.explore.users >.ui.container {
// 排除用户的公开活动页
/* 排除用户的公开活动页 */
> .flex-list:not(#activity-feed) {
grid-template-columns: 1fr;
gap: 8px;
@@ -179,17 +180,17 @@ export const mobileList = css`
// 统一无搜索结果时的样式
export const notMatch = css`
// 组织的仓库列表
/* 组织的仓库列表 */
.page-content.organization.profile > .ui.container > .ui.stackable > .ui.eleven,
// 用户的仓库列表
/* 用户的仓库列表 */
.page-content.user.profile > .ui.container > .ui.stackable > .ui.twelve,
// 探索的仓库列表
/* 探索的仓库列表 */
.page-content.explore.repositories > .ui.container,
// 组织的成员列表
/* 组织的成员列表 */
.page-content.organization.members >.ui.container,
// 探索的用户和组织列表
/* 探索的用户和组织列表 */
.page-content.explore.users >.ui.container {
// 排除用户的公开活动页
/* 排除用户的公开活动页 */
> .flex-list:not(#activity-feed) {
&:has(> div:only-child):not(:has(.flex-item-main)) {
grid-template-columns: 1fr;
+4 -3
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
export const footer = css`
.page-footer {
@@ -60,11 +61,11 @@ export const footer = css`
color: ${themeVars.color.primary.self};
}
}
// 主题按钮&菜单项
/* 主题按钮&菜单项 */
.ui.dropdown .theme-menu-item {
gap: 4px;
}
// 主题菜单
/* 主题菜单 */
.menu.theme-menu > .item > .theme-menu-item {
padding: 0;
}
+14 -13
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
export const heatmap = css`
#user-heatmap {
@@ -39,20 +40,20 @@ export const heatmap = css`
0px 0px 0px 1px ${themeVars.color.light.border},
${themeVars.github.shadow.resting.small};
border-radius: 12px;
// 覆盖热力图和图例的背景色
/* 覆盖热力图和图例的背景色 */
.vch__day__square,
.vch__legend__wrapper rect {
// 圆角
/* 圆角 */
rx: 2.5px;
ry: 2.5px;
// hover 时的圆角
/* hover 时的圆角 */
border-radius: 0.75px;
// 宽度和高度可以用来控制间隔
/* 宽度和高度可以用来控制间隔 */
width: 9px;
height: 9px;
// 边框
/* 边框 */
outline: 0.5px solid ${themeVars.github.contribution.default.borderColor.num0};
// 边框向内偏移
/* 边框向内偏移 */
outline-offset: -0.5px;
&[style="fill: var(--color-secondary-alpha-60);"] {
@@ -108,10 +109,10 @@ export const activity = css`
border-radius: 9999px;
}
}
// 动态的主要内容
/* 动态的主要内容 */
> .flex-item-main {
gap: 8px !important;
// 动态的标题
/* 动态的标题 */
> div:not([class]) {
display: flex;
align-items: baseline;
@@ -119,9 +120,9 @@ export const activity = css`
flex-wrap: wrap;
> a {
color: ${themeVars.color.text.self};
// 不匹配作者
/* 不匹配作者 */
&:not([title]) {
// 尽量只选中仓库名, 不匹配标签和分支
/* 尽量只选中仓库名, 不匹配标签和分支 */
&:not([href*="tag"]):not([href*="branch"]) {
color: ${themeVars.color.primary.self};
text-decoration: underline;
@@ -133,7 +134,7 @@ export const activity = css`
font-size: 12px;
}
}
// 动态的描述
/* 动态的描述 */
> .tw-flex-col {
gap: 0px !important;
> .flex-text-block {
@@ -159,7 +160,7 @@ export const activity = css`
font-size: 12px;
}
}
// 动态的右侧 svg 图标
/* 动态的右侧 svg 图标 */
.flex-item-trailing {
align-self: center;
svg {
-2
View File
@@ -18,9 +18,7 @@
*/
import "./actions";
import "./chroma";
import "./dashboard";
import "./editor";
import "./explore";
import "./footer";
import "./heatmap";
+16 -15
View File
@@ -17,11 +17,12 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { activeItemAfterStyle } from "styles/public/menu";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { activeItemAfterStyle } from "styles/common";
export const button = css`
// 工单&PR标题右侧按钮
/* 工单&PR标题右侧按钮 */
.repository.view.issue .issue-title-buttons > .ui.button {
padding: 0 12px;
height: 32px;
@@ -31,21 +32,21 @@ export const button = css`
export const babel = css`
.issue-content-left {
.badge {
// 时间线打开状态标签
/* 时间线打开状态标签 */
&.tw-bg-green {
background-color: ${themeVars.github.bgColor.success.emphasis} !important;
}
// 时间线关闭状态标签
/* 时间线关闭状态标签 */
&.tw-bg-red {
background-color: ${themeVars.github.bgColor.done.emphasis} !important;
}
// 时间线合并状态标签
/* 时间线合并状态标签 */
&.tw-bg-purple {
background-color: ${themeVars.github.bgColor.done.emphasis} !important;
}
}
}
// 工单&PR状态标签
/* 工单&PR状态标签 */
.ui.label.issue-state-label {
border-radius: 25px !important;
&.green {
@@ -90,9 +91,9 @@ export const prBranch = css`
export const dropdown = css`
.repository {
// Issue/PR 列表下的所有筛选菜单
/* Issue/PR 列表下的所有筛选菜单 */
&.issue-list .ui.dropdown .menu, .ui.menu .ui.dropdown .menu,
// Issue/PR 详情下的右侧的上半部分选项菜单
/* Issue/PR 详情下的右侧的上半部分选项菜单 */
&.issue.view .issue-content-right .ui.dropdown .scrolling.menu {
.item:hover:after {
content: "";
@@ -105,7 +106,7 @@ export const dropdown = css`
// PR 界面的 PR 操作评论
export const prMerge = css`
.repository.view.issue .comment-list .timeline-item.pull-merge-box {
// 头像
/* 头像 */
.timeline-avatar {
border-radius: 9999px;
width: 40px;
@@ -117,11 +118,11 @@ export const prMerge = css`
width: 24px;
height: 24px;
}
// PR 界面的 PR 操作评论
/* PR 界面的 PR 操作评论 */
&.text {
color: ${themeVars.color.white} !important;
border-radius: ${otherThemeVars.border.radius};
// 操作评论边框
/* 操作评论边框 */
+ .content > .ui.attached.segment {
border-width: 1.5px;
}
@@ -182,7 +183,7 @@ export const prMerge = css`
}
}
}
// 检查状态
/* 检查状态 */
.commit-status-panel {
.commit-status-header {
background: ${themeVars.color.body};
@@ -195,7 +196,7 @@ export const prMerge = css`
font-weight: 400;
}
}
// 检查状态列表
/* 检查状态列表 */
.commit-status-list {
background: ${themeVars.color.menu};
.commit-status-item {
@@ -215,7 +216,7 @@ export const prMerge = css`
}
}
}
// 合并信息和操作
/* 合并信息和操作 */
.merge-section {
color: ${themeVars.color.text.light.num1};
padding: 16px;
+13 -16
View File
@@ -17,20 +17,17 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { botLabelStyle } from "styles/common";
export const botLabelStyle = {
height: "20px",
padding: "0 6px!important",
marginLeft: "4px",
};
// 评论
export const comment = css`
.comment .comment-container {
img.ui.avatar {
border-radius: 9999px;
}
// 去除评论标题左侧指向头像的小箭头
/* 去除评论标题左侧指向头像的小箭头 */
.comment-header,
&:target .comment-header {
&:before,
@@ -38,7 +35,7 @@ export const comment = css`
display: none;
}
}
// 评论焦点样式
/* 评论焦点样式 */
&:target {
.comment-container {
border-color: ${themeVars.github.borderColor.accent.emphasis} !important;
@@ -49,14 +46,14 @@ export const comment = css`
padding: 4px 4px 4px 16px;
min-height: 38px;
.comment-header-left {
// bot 标签
/* bot 标签 */
.ui.basic.label {
${botLabelStyle}
}
a:has(relative-time) {
text-decoration: underline;
}
// 已编辑按钮
/* 已编辑按钮 */
.content-history-menu {
color: ${themeVars.color.text.light.num1} !important;
.menu .item {
@@ -94,7 +91,7 @@ export const comment = css`
color: inherit;
}
}
// 评论菜单的删除按钮
/* 评论菜单的删除按钮 */
.menu .item.delete-comment {
color: ${themeVars.color.red.self};
&:hover {
@@ -104,7 +101,7 @@ export const comment = css`
}
}
}
// 表情菜单按钮头部+底部
/* 表情菜单按钮头部+底部 */
.ui.dropdown.action.select-reaction > a {
display: flex;
align-items: center;
@@ -117,7 +114,7 @@ export const comment = css`
height: 28px;
width: 28px;
}
// 底部表情栏
/* 底部表情栏 */
.bottom-reactions {
.ui.ui.ui.label {
background-color: unset !important;
@@ -136,11 +133,11 @@ export const comment = css`
margin-left: 0;
}
}
// 显示表情菜单按钮
/* 显示表情菜单按钮 */
.select-reaction {
padding: 0;
// 两个表情按钮看着怪怪的, 很难受
// visibility: visible;
/* 两个表情按钮看着怪怪的, 很难受 */
/* visibility: visible; */
}
}
}
+12 -12
View File
@@ -17,17 +17,17 @@
* limitations under the License.
*/
import { extractVarName } from "src/functions";
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { extractVarName, otherThemeVars, themeVars } from "src";
// 工单&PR 列表
export const issueList = css`
// 仓库页面的里程碑列表菜单栏
/* 仓库页面的里程碑列表菜单栏 */
.page-content.repository.milestones,
.page-content.repository.milestone-issue-list,
.page-content.repository.issue-list {
${extractVarName(otherThemeVars.checkbox.size)}: 16px;
// 头部筛选菜单栏
/* 头部筛选菜单栏 */
.issue-list-toolbar {
align-items: center;
align-content: center;
@@ -40,7 +40,7 @@ export const issueList = css`
padding: 8px;
margin-top: 16px;
.issue-list-toolbar-left {
// 复选框
/* 复选框 */
input {
margin: 0 8px !important;
}
@@ -93,13 +93,13 @@ export const issueList = css`
}
}
}
// 里程碑详细页面的 Issue 列表
/* 里程碑详细页面的 Issue 列表 */
.page-content.repository.milestone-issue-list,
// 顶部仪表板的 Issue 列表
/* 顶部仪表板的 Issue 列表 */
.page-content.dashboard.issues,
// 用户订阅的 Issue 列表
/* 用户订阅的 Issue 列表 */
.page-content.user.notification,
// 仓库 Issue 列表
/* 仓库 Issue 列表 */
.page-content.repository.issue-list {
.flex-list#issue-list {
border: 1px solid ${themeVars.color.light.border};
@@ -128,7 +128,7 @@ export const issueList = css`
margin-left: 16px;
> .flex-text-inline {
margin-top: 0px !important;
// 复选框
/* 复选框 */
input {
margin-right: 8px !important;
}
@@ -150,8 +150,8 @@ export const issueList = css`
}
}
}
// 里程碑列表
// [TODO] 暂时排除项目的列表
/* 里程碑列表 */
/* [TODO] 暂时排除项目的列表 */
.page-content.repository.milestones:not(.projects) .milestone-list {
border: 1px solid ${themeVars.color.light.border};
border-bottom-left-radius: ${otherThemeVars.border.radius};
+32 -30
View File
@@ -17,24 +17,26 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import type { StyleRule } from "@vanilla-extract/css";
import { otherThemeVars, themeVars } from "src";
const sidebarPadding = {
padding: "4px 8px",
};
} satisfies StyleRule;
// 侧边栏
export const issueSidebar = css`
// 创建PR页面
/* 创建PR页面 */
.page-content.repository.diff.compare.pull,
// 工单&创建工单&PR页面侧边栏
/* 工单&创建工单&PR页面侧边栏 */
.page-content.repository.issue {
.issue-content {
img.ui.avatar {
border-radius: 9999px;
}
gap: 24px;
// 侧边栏
/* 侧边栏 */
.issue-content-right {
border: 0;
font-size: 12px;
@@ -45,13 +47,13 @@ export const issueSidebar = css`
.ui.form,
a.fixed-text.muted,
span.text,
// 列表项为空时的文字
/* 列表项为空时的文字 */
span.item.empty-list,
p {
color: ${themeVars.color.text.light.num1};
font-size: 12px;
}
// WIP 前缀提示
/* WIP 前缀提示 */
> a,
.ui.dropdown.select-branch,
.ui.form,
@@ -65,7 +67,7 @@ export const issueSidebar = css`
p {
${sidebarPadding};
}
// 允许维护者编辑
/* 允许维护者编辑 */
> .ui.checkbox {
margin: 4px 8px;
strong {
@@ -86,10 +88,10 @@ export const issueSidebar = css`
margin-top: 0 !important;
margin-bottom: 0 !important;
}
// 评审人
/* 评审人 */
.ui.relaxed.list {
.item {
// 操作图标按钮
/* 操作图标按钮 */
a.muted.icon {
color: ${themeVars.color.text.light.num1};
&:hover {
@@ -98,55 +100,55 @@ export const issueSidebar = css`
}
}
}
// 标签菜单项
/* 标签菜单项 */
.ui.dropdown > .menu > .scrolling.menu > .item:has(.item-secondary-info) {
// 修复标签菜单中描述文本过长没有换行挤掉标签的问题
/* 修复标签菜单中描述文本过长没有换行挤掉标签的问题 */
display: grid !important;
grid-template-columns: auto auto 1fr;
row-gap: 0px; // 去除行间距, 仅当有描述信息时才有间距(.tw-pl-\\\[20px\\\])
// 如果是归档标签则隐藏
row-gap: 0px; /* 去除行间距, 仅当有描述信息时才有间距(.tw-pl-\\\[20px\\\]) */
/* 如果是归档标签则隐藏 */
&.tw-hidden {
display: none !important;
}
// 默认隐藏多余信息避免标签对齐问题
/* 默认隐藏多余信息避免标签对齐问题 */
.item-secondary-info {
display: none;
grid-column: 2 / -1; // 从第2列对齐
grid-column: 2 / -1; /* 从第2列对齐 */
color: ${themeVars.color.text.light.num1};
> .tw-pl-\\\[20px\\\] {
// 已经与第二列对齐, 不需要额外的 padding
/* 已经与第二列对齐, 不需要额外的 padding */
padding-left: 0px !important;
padding-top: 4px;
// 显示全部描述信息与 Github 保持一致
/* 显示全部描述信息与 Github 保持一致 */
white-space: normal;
small {
font-size: 12px;
}
}
> .archived-label-hint {
// 与父元素 item 的 padding 对齐 (dropdown.ts .ui.dropdown .menu > .item)
/* 与父元素 item 的 padding 对齐 (dropdown.ts .ui.dropdown .menu > .item) */
top: 6px;
right: 8px;
}
// 如果有描述信息则显示
/* 如果有描述信息则显示 */
&:has(.tw-pl-\\\[20px\\\]) {
display: block;
> .archived-label-hint {
top: 4px; // 有描述信息的归档标签与标签对齐需要更高点
top: 4px; /* 有描述信息的归档标签与标签对齐需要更高点 */
}
}
// 如果有归档标签则显示
/* 如果有归档标签则显示 */
&:has(.archived-label-hint > .ui.label) {
display: block;
}
}
}
// 修复菜单下拉打开时, 无法聚焦输入框
/* 修复菜单下拉打开时, 无法聚焦输入框 */
.menu input {
transition: none;
}
}
// 时间追踪
/* 时间追踪 */
> div:not([class]):not([id]) {
> .flex-text-block {
color: ${themeVars.color.text.light.num1};
@@ -165,16 +167,16 @@ export const issueSidebar = css`
}
}
}
// 选中日期颜色
/* 选中日期颜色 */
.ui.form .due-date {
color: ${themeVars.color.text.self};
}
// 分割线
/* 分割线 */
> .divider {
margin: 12px 0 12px 8px;
width: calc(100% - 16px);
}
// 订阅按钮
/* 订阅按钮 */
.ui.watching .ui.button {
padding: 0px 8px;
height: 30px;
@@ -183,15 +185,15 @@ export const issueSidebar = css`
margin: 0 !important;
}
}
// PIN 按钮
/* PIN 按钮 */
.form-fetch-action.single-button-form .ui.button,
// 底部操作按钮
/* 底部操作按钮 */
> .ui.show-modal.button {
border: 0;
background: unset;
font-weight: 400;
${sidebarPadding};
// 好像是浏览器 BUG, 最后不生效, 必须 !important
/* 好像是浏览器 BUG, 最后不生效, 必须 !important */
margin: 0 !important;
justify-content: left;
&:hover {
+15 -14
View File
@@ -17,16 +17,17 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { botLabelStyle } from "./issue_comment";
import { css } from "@linaria/core";
import { themeVars } from "src";
import { botLabelStyle } from "styles/common";
// 时间线
export const timeline = css`
.repository.view.issue {
.comment-list {
// 时间线本线
/* 时间线本线 */
.timeline::before {
// 不遮挡归档信息框, 归档信息框背景色有透明度时会漏出线
/* 不遮挡归档信息框, 归档信息框背景色有透明度时会漏出线 */
height: calc(100% - 62px);
}
.timeline-item,
@@ -35,28 +36,28 @@ export const timeline = css`
.comment-text-line {
color: ${themeVars.color.text.light.num1};
}
// 事件
/* 事件 */
&.event {
// 修复覆盖后的位置问题
/* 修复覆盖后的位置问题 */
padding-left: 15px;
// 避免锚中批准的头像
/* 避免锚中批准的头像 */
.avatar-with-link .avatar {
width: 20px;
height: 20px;
}
// 批准时间的头像
// 头部居中偏移量(头像高度 - 标准行信息高度) / 2: (40px - 32px) / 2 = 4px
/* 批准时间的头像 */
/* 头部居中偏移量(头像高度 - 标准行信息高度) / 2: (40px - 32px) / 2 = 4px */
.timeline-avatar {
top: -4px;
}
// bot 标签
/* bot 标签 */
.comment-text-line .ui.basic.label {
${botLabelStyle}
}
.badge {
border: 2px solid ${themeVars.color.body};
}
// 仅匹配只有 badge
/* 仅匹配只有 badge */
[class="badge"] {
background-color: ${themeVars.github.control.bgColor.rest};
svg {
@@ -64,16 +65,16 @@ export const timeline = css`
}
}
}
// 提交
/* 提交 */
&.commits-list {
// 每个提交之间的间隔
/* 每个提交之间的间隔 */
.flex-text-block {
padding-top: 4px;
}
.badge svg {
color: ${themeVars.color.text.light.num1};
}
// 仅覆盖左侧 commit 不覆盖右侧 SHA
/* 仅覆盖左侧 commit 不覆盖右侧 SHA */
a.muted {
font-size: 12px;
color: ${themeVars.color.text.light.num1};
+23 -21
View File
@@ -17,12 +17,13 @@
* limitations under the License.
*/
import { fallbackVar } from "src/functions";
import { css, customThemeVars, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { fallbackVar } from "@vanilla-extract/css";
import { customThemeVars, otherThemeVars, themeVars } from "src";
export const navbarRight = css`
#navbar {
padding: 8px 16px; // 上下内边距 + .navbar-left & .navbar-right 的 min-height = 64px
padding: 8px 16px; /* 上下内边距 + .navbar-left & .navbar-right 的 min-height = 64px */
min-height: 64px;
.navbar-left,
.navbar-right {
@@ -37,7 +38,7 @@ export const navbarRight = css`
font-weight: 600;
}
&#navbar-logo {
// 与下方的用户切换头像对齐
/* 与下方的用户切换头像对齐 */
padding-left: 6px;
&:hover {
background: unset;
@@ -49,10 +50,10 @@ export const navbarRight = css`
}
}
}
// 进入用户页面后, 避免注册, 登录和首页等意外覆盖
/* 进入用户页面后, 避免注册, 登录和首页等意外覆盖 */
.navbar-right:has(.user-menu) {
gap: 8px;
// 右侧按钮, 但不包括头像
/* 右侧按钮, 但不包括头像 */
> .item:not(:last-child) {
align-items: center;
justify-content: center;
@@ -63,7 +64,7 @@ export const navbarRight = css`
height: 32px;
min-width: 32px;
min-height: 32px;
// 纠正内容保证居中
/* 纠正内容保证居中 */
.tw-relative {
height: 16px;
width: 16px;
@@ -71,7 +72,7 @@ export const navbarRight = css`
.svg {
color: ${themeVars.color.text.light.num1};
}
// 带下拉菜单的按钮
/* 带下拉菜单的按钮 */
&.ui.dropdown {
padding: 0 8px;
.text {
@@ -81,7 +82,7 @@ export const navbarRight = css`
> svg {
margin-right: 4px;
}
// 三角号纠正高度保持居中
/* 三角号纠正高度保持居中 */
.not-mobile {
height: 16px;
}
@@ -92,21 +93,21 @@ export const navbarRight = css`
}
}
.item.ui.dropdown {
// 头像菜单
/* 头像菜单 */
&:last-child {
padding: 0;
.text {
// 不显示头像右侧的小箭头下拉菜单标识
/* 不显示头像右侧的小箭头下拉菜单标识 */
> .not-mobile {
display: none;
}
// 手机下的用户名
/* 手机下的用户名 */
> .only-mobile {
margin-left: 12px;
font-weight: 600;
}
.navbar-avatar {
// 头像
/* 头像 */
img {
border-radius: 9999px;
height: 32px;
@@ -115,14 +116,14 @@ export const navbarRight = css`
max-width: 32px;
margin: 0 !important;
}
// 管理员标识
/* 管理员标识 */
.navbar-admin-badge {
height: 18px;
min-width: 18px;
bottom: calc(100% - 32px);
left: calc(100% - 11px);
padding: 2px;
border-color: ${themeVars.color.nav.bg}; // 锁定边框色, 避免鼠标悬浮时改变颜色
border-color: ${themeVars.color.nav.bg}; /* 锁定边框色, 避免鼠标悬浮时改变颜色 */
}
}
}
@@ -131,12 +132,13 @@ export const navbarRight = css`
}
}
}
// 通知和计时器的圆点
/* 通知和计时器的圆点 */
a.item {
.notification_count,
.header-stopwatch-dot {
background-color: ${themeVars.github.bgColor.accent.emphasis};
border-radius: 9999px;
border-color: ${themeVars.color.nav.bg};
color: ${themeVars.color.white};
font-size: 9px;
font-weight: 600;
@@ -145,7 +147,7 @@ export const navbarRight = css`
}
}
}
// 用户菜单
/* 用户菜单 */
.navbar-right .user-menu {
width: ${fallbackVar(customThemeVars.userMenuWidth, "192px")};
max-width: 320px;
@@ -164,7 +166,7 @@ export const navbarRight = css`
}
}
}
// 手机下的导航栏
/* 手机下的导航栏 */
@media (max-width: 767.98px) {
#navbar {
&.navbar-menu-open {
@@ -181,7 +183,7 @@ export const navbarRight = css`
height: 32px;
min-width: 32px;
min-height: 32px;
// 纠正内容保证居中
/* 纠正内容保证居中 */
.tw-relative {
height: 16px;
width: 16px;
@@ -199,12 +201,12 @@ export const navbarRight = css`
export const secondaryNav = css`
.page-content > :first-child.secondary-nav {
margin-bottom: 16px;
// 仪表板界面的二级导航栏用户菜单
/* 仪表板界面的二级导航栏用户菜单 */
> .ui.secondary.stackable.menu {
gap: 0px;
min-height: 48px;
> .item {
// 修复手机下的菜单按钮没有居中的问题
/* 修复手机下的菜单按钮没有居中的问题 */
margin-top: auto;
margin-bottom: auto;
> .ui.dropdown > .text {
+2 -2
View File
@@ -17,8 +17,8 @@
* limitations under the License.
*/
import { css } from "src/types/vars";
import { activeItemAfterStyle } from "styles/public/menu";
import { css } from "@linaria/core";
import { activeItemAfterStyle } from "styles/common";
// 新建仓库页面下拉菜单
export const newRepo = css`
+10 -9
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 用户订阅/关注页面
export const notification = css`
@@ -29,7 +30,7 @@ export const notification = css`
> .divider {
display: none;
}
// 订阅列表
/* 订阅列表 */
&:has(#issue-list) {
> .tw-flex {
align-items: center;
@@ -41,7 +42,7 @@ export const notification = css`
border-top-right-radius: ${otherThemeVars.border.radius};
height: 52px;
padding: 8px;
// 左侧菜单
/* 左侧菜单 */
> .tw-flex:first-child > .ui.compact.menu {
align-items: center;
border: 0;
@@ -63,7 +64,7 @@ export const notification = css`
}
}
}
// 右侧菜单
/* 右侧菜单 */
> .tw-flex:last-child > .ui.menu {
align-items: center;
> .item {
@@ -76,7 +77,7 @@ export const notification = css`
}
}
}
// 关注列表
/* 关注列表 */
> .flex-list:not([id]) {
border: 1px solid ${themeVars.color.light.border};
border-radius: ${otherThemeVars.border.radius};
@@ -107,7 +108,7 @@ export const notification = css`
}
}
}
// 通知列表
/* 通知列表 */
&:has(#notification_table) {
> .flex-text-block:first-child {
background-color: ${themeVars.color.box.header};
@@ -118,7 +119,7 @@ export const notification = css`
height: 52px;
padding: 8px;
margin-bottom: 0 !important;
// 左侧菜单
/* 左侧菜单 */
> .ui.compact.menu {
align-items: center;
border: 0;
@@ -144,12 +145,12 @@ export const notification = css`
}
}
}
// 通知全部确认按钮
/* 通知全部确认按钮 */
.ui.ui.ui.ui.mini.button {
height: 32px;
}
}
// 通知列表
/* 通知列表 */
#notification_table {
border-top-left-radius: 0;
border-top-right-radius: 0;
+10 -9
View File
@@ -17,29 +17,30 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
export const org = css`
.page-content.organization {
// 组织成员头像
/* 组织成员头像 */
.members .ui.avatar {
border-radius: 9999px;
}
// 组织头像
/* 组织头像 */
.org-avatar {
margin: 8px 24px 16px 0px;
}
// 组织信息
/* 组织信息 */
#org-info {
margin-top: 8px; // 与头像对齐
margin-top: 8px; /* 与头像对齐 */
gap: 8px;
// 组织名称
/* 组织名称 */
> .ui.header {
font-size: 24px;
> .org-visibility {
margin-left: 8px;
}
// 组织页面的 RSS 订阅按钮
/* 组织页面的 RSS 订阅按钮 */
.ui.label.button {
padding: 4px 16px;
.svg {
@@ -51,11 +52,11 @@ export const org = css`
}
}
}
// 组织描述
/* 组织描述 */
> .markup {
color: ${themeVars.color.text.light.num1};
}
// 组织信息
/* 组织信息 */
> .meta {
font-size: 12px;
svg {
+10 -9
View File
@@ -17,28 +17,29 @@
* limitations under the License.
*/
import { css, customThemeVars, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { customThemeVars, otherThemeVars, themeVars } from "src";
// 克隆按钮的弹窗
export const clone = css`
.tippy-box {
.clone-panel-popup {
//标题和克隆地址
/*标题和克隆地址 */
> .clone-panel-field {
margin-left: 16px;
margin-right: 16px;
//标题
/* 标题 */
&:first-of-type {
font-weight: 600;
margin-top: 16px;
}
}
// 按钮组
/* 按钮组 */
.clone-panel-tab {
display: flex;
gap: 8px;
margin-left: 16px;
// 按钮
/* 按钮 */
.item {
color: ${themeVars.color.text.self};
font-weight: 600;
@@ -65,7 +66,7 @@ export const clone = css`
position: relative;
}
}
// 克隆地址
/* 克隆地址 */
.ui.input.action {
> input {
border: 1px solid ${themeVars.color.light.border};
@@ -101,11 +102,11 @@ export const clone = css`
}
}
}
// 面板操作列表之间的分割线
/* 面板操作列表之间的分割线 */
.divider {
margin: 0;
}
// 面板操作列表
/* 面板操作列表 */
.clone-panel-list {
margin: 8px;
.item {
@@ -115,7 +116,7 @@ export const clone = css`
margin: 0;
gap: 4px;
svg {
color: ${themeVars.color.text.light.num1} !important; // 覆盖 .gitea-vscodium 颜色
color: ${themeVars.color.text.light.num1} !important; /* 覆盖 .gitea-vscodium 颜色 */
margin-right: 4px;
}
}
+16 -13
View File
@@ -17,24 +17,26 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 提交列表
export const commit = css`
.page-content.repository.commits {
// 提交列表 (选择器保证同等优先级覆盖了 gitea 原生的样式)
/* 提交列表 (选择器保证同等优先级覆盖了 gitea 原生的样式) */
.ui.attached.table.segment.commit-table tbody.commit-list {
// 作者
/* 作者 */
.author {
img.ui.avatar {
border-radius: 9999px;
}
// 作者名称
/* 作者名称 */
.author-wrapper {
display: flex;
color: ${themeVars.color.text.light.num1};
}
}
// SHA 标签
/* SHA 标签 */
.sha {
a.ui.label.commit-id-short {
padding: 2px 8px;
@@ -44,16 +46,17 @@ export const commit = css`
margin-left: -8px;
}
}
// 提交信息
/* 提交信息 */
.message {
// tag 标签
/* tag 标签 */
a.ui.basic.label {
border-radius: 9999px;
border-width: 1.5px;
padding: 3px 8px !important;
margin-left: 4px;
}
}
// 提交信息右侧
/* 提交信息右侧 */
.tw-text-right {
relative-time,
svg {
@@ -61,15 +64,15 @@ export const commit = css`
}
}
tr {
// 整行悬停色
/* 整行悬停色 */
&:hover {
background-color: ${themeVars.color.hover.opaque};
}
// 偶数行悬停色
/* 偶数行悬停色 */
&:nth-child(2n):hover {
background-color: ${themeVars.color.hover.opaque} !important;
}
// 尾行圆角
/* 尾行圆角 */
&:last-child {
td:first-child {
border-bottom-left-radius: ${otherThemeVars.border.radius};
@@ -106,10 +109,10 @@ export const commitGraph = css`
img.ui.avatar {
border-radius: 9999px;
}
// 提交图的 SHA 标签
/* 提交图的 SHA 标签 */
li .ui.label.commit-id-short {
height: 25px;
// 验证提交 SHA 标签
/* 验证提交 SHA 标签 */
&.commit-is-signed {
span.ui.label.commit-is-signed {
height: 25px;
+40 -34
View File
@@ -17,30 +17,31 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const diff = css`
// 这里的折叠行和代码行高度与 GitHub 的 release 和 review 的差异对比时的高度一致, 不需要像 commit 中的差异对比那样行高过高
// release 和 review 行高为 20px, commit 行高为 24px
// 折叠行
/* 这里的折叠行和代码行高度与 GitHub 的 release 和 review 的差异对比时的高度一致, 不需要像 commit 中的差异对比那样行高过高 */
/* release 和 review 行高为 20px, commit 行高为 24px */
/* 折叠行 */
.tag-code {
// 多余的颜色
/* 多余的颜色 */
background-color: unset;
height: 28px;
// 展开按钮高度与折叠行一致
/* 展开按钮高度与折叠行一致 */
.code-expander-buttons {
.code-expander-button {
height: 28px;
}
}
// 双向展开的按钮
/* 双向展开的按钮 */
&:has(.code-expander-buttons[data-expand-direction="3"]) {
height: 40px;
.code-expander-button {
height: 20px;
}
}
// 展开按钮
/* 展开按钮 */
.code-expander-button {
color: ${themeVars.color.text.light.num1};
&:hover {
@@ -48,21 +49,21 @@ export const diff = css`
color: ${themeVars.color.white};
}
}
// 折叠行文本
/* 折叠行文本 */
.code-inner {
color: ${themeVars.color.text.light.num1};
}
}
// 代码行
/* 代码行 */
.lines-num,
.lines-code {
line-height: 20px;
}
// 行号居中
/* 行号居中 */
.lines-num {
text-align: center !important;
}
// 增加/删除行多余的颜色
/* 增加/删除行多余的颜色 */
.code-diff-unified {
.del-code,
.add-code {
@@ -70,21 +71,21 @@ export const diff = css`
border-color: unset;
}
}
// 增加/删除相关代码背景色圆角
/* 增加/删除相关代码背景色圆角 */
.added-code,
.removed-code {
border-radius: 3px;
color: ${themeVars.color.text.self};
// 覆盖掉 chroma 的颜色
/* 覆盖掉 chroma 的颜色 */
* {
color: ${themeVars.color.text.self} !important;
}
}
// 差异对比文件盒子
/* 差异对比文件盒子 */
.diff-file-box {
// 差异对比文件头
/* 差异对比文件头 */
.diff-file-header {
// 文件名
/* 文件名 */
.diff-file-name {
font-weight: 400;
.fold-file.btn svg {
@@ -101,11 +102,16 @@ export const diff = css`
font-size: 12px;
}
}
// 操作按钮
/* 操作按钮 */
.diff-file-header-actions {
color: ${themeVars.color.text.light.num1};
font-size: 12px;
font-weight: 400;
/* 增加/删除行, 基于 tailwindcss 的属性, 将来可能会失效 */
.tw-text-diff-added-fg,
.tw-text-diff-removed-fg {
font-weight: 600;
}
.diff-header-popup-btn {
border-radius: ${otherThemeVars.border.radius};
padding: 5px !important;
@@ -116,53 +122,53 @@ export const diff = css`
}
}
}
// 差异对比文件盒子
/* 差异对比文件盒子 */
.repository .diff-file-box {
.code-diff {
// 隐藏多余的空白
// 合并视图的第三列
/* 隐藏多余的空白 */
/* 合并视图的第三列 */
&.code-diff-unified colgroup col:nth-child(3),
// 拆分视图的第二列和第六列
/* 拆分视图的第二列和第六列 */
&.code-diff-split colgroup col:nth-child(2),
&.code-diff-split colgroup col:nth-child(6),
td.lines-escape {
width: 0; // 不要使用 display: none; 否则会影响布局, 无内容时为 0, 有内容时为 20(猜测可能是根据内容宽度自动调整)
/* visibility: hidden; */ // 不要使用 visibility: hidden; 当 escape 有内容时会导致背景颜色丢失, escape 目前用于显示检测 unicode 编码错误的内容
width: 0; /* 不要使用 display: none; 否则会影响布局, 无内容时为 0, 有内容时为 20(猜测可能是根据内容宽度自动调整) */
/* visibility: hidden; // 不要使用 visibility: hidden; 当 escape 有内容时会导致背景颜色丢失, escape 目前用于显示检测 unicode 编码错误的内容 */
}
// 修复当 escape 有内容时, 宽度不够的问题
/* 修复当 escape 有内容时, 宽度不够的问题 */
&:has(td.lines-escape:not(:empty)) {
// 合并视图的第三列
/* 合并视图的第三列 */
&.code-diff-unified colgroup col:nth-child(3),
// 拆分视图的第二列和第六列
/* 拆分视图的第二列和第六列 */
&.code-diff-split colgroup col:nth-child(2),
&.code-diff-split colgroup col:nth-child(6),
td.lines-escape {
width: 20;
}
}
// Gitea 分列视图下默认 100% 宽度的目的是如果单文件只增加或只删除的情况下, 保持无内容的列的宽度一致, 始终保持左右两边的列宽度一致
// 保持 Gitea 的默认设置, 不对行号宽度做处理
/* Gitea 分列视图下默认 100% 宽度的目的是如果单文件只增加或只删除的情况下, 保持无内容的列的宽度一致, 始终保持左右两边的列宽度一致 */
/* 保持 Gitea 的默认设置, 不对行号宽度做处理 */
/* &.code-diff-split table {
width: auto;
} */
// 行号宽度
/* 行号宽度
// 40px: 长度 = 9999 行
// 45px: 长度 = 99999 行
// 50px: 长度 = 999999 行
// GitHub 在 commit 中的行宽最小为 40px, 但会动态调整, 在 release 和 review 的差异对比中为 50px
// 这里折中为 45px 会根据代码行数动态调整, 45px 既不会在行数少时显得太宽, 也可以在大多数情况下保持宽度一致
// 这里折中为 45px 会根据代码行数动态调整, 45px 既不会在行数少时显得太宽, 也可以在大多数情况下保持宽度一致 */
.lines-num {
min-width: 45px;
}
// 合并视图的第四列
/* 合并视图的第四列 */
&.code-diff-unified colgroup col:nth-child(4),
// 拆分视图的第三列和第七列, -/+ 保持居中的宽度
/* 拆分视图的第三列和第七列, -/+ 保持居中的宽度 */
&.code-diff-split colgroup col:nth-child(3),
&.code-diff-split colgroup col:nth-child(7) {
width: 20;
}
}
// 修复对比视图内容中的圆角和背景溢出
/* 修复对比视图内容中的圆角和背景溢出 */
.file-body.file-code {
border-radius: 0 0 ${otherThemeVars.border.radius} ${otherThemeVars.border.radius};
overflow: hidden;
+6 -5
View File
@@ -17,24 +17,25 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
export const milestone = css`
// 里程碑头部
/* 里程碑头部 */
.milestone-header {
gap: 16px;
// 进度条
/* 进度条 */
progress {
height: 5px;
width: 300px;
max-width: 80vw;
}
}
// 里程碑 Issue 列表的进度条
/* 里程碑 Issue 列表的进度条 */
.milestone-progress-big {
height: 8px;
}
// 里程碑 Issue 列表
/* 里程碑 Issue 列表 */
.page-content.repository.milestone-issue-list {
> .ui.container {
> .flex-text-block:first-child {
+7 -6
View File
@@ -17,12 +17,13 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 组织/仓库的软件包列表(包含用户但未测试)
export const packagesList = css`
.page-content.packages {
// 这里必须要用 >, 否则会影响到软件包详细信息页的样式
/* 这里必须要用 >, 否则会影响到软件包详细信息页的样式 */
> .ui.container > div:not([class]) {
border: 1px solid ${themeVars.color.light.border};
border-radius: ${otherThemeVars.border.radius};
@@ -40,7 +41,7 @@ export const packagesList = css`
> a {
min-height: 25px;
}
// 软件包类型的标签
/* 软件包类型的标签 */
.ui.label {
gap: 4px;
padding: 3px 6px;
@@ -109,7 +110,7 @@ export const packagesDetail = css`
> .divider {
margin: 16px 0px;
}
// 详情
/* 详情 */
> .ui.relaxed.list {
margin: 16px 0px;
.item {
@@ -117,7 +118,7 @@ export const packagesDetail = css`
svg {
color: ${themeVars.color.text.self};
}
// 应该只选中版本中的 a 标签
/* 应该只选中版本中的 a 标签 */
&.tw-flex {
justify-content: space-between;
> a {
@@ -131,7 +132,7 @@ export const packagesDetail = css`
text-decoration: none;
}
}
// 不知道什么东西
/* 不知道什么东西 */
&::after {
display: none;
}
+12 -11
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// release 顶部栏左侧按钮组
export const releaseTagMenu = css`
@@ -62,7 +63,7 @@ export const rightButton = css`
// 标签页样式
export const tags = css`
.page-content.repository.tags {
// 标签的选项取消下划线
/* 标签的选项取消下划线 */
.tag-list-row {
.tag-list-row-title {
line-height: 1.5;
@@ -92,7 +93,7 @@ export const releases = css`
gap: 32px;
margin: 32px 0 16px 0;
.release-entry {
// 左侧发布元信息
/* 左侧发布元信息 */
.meta {
gap: 0.5rem;
padding-top: 24px;
@@ -113,7 +114,7 @@ export const releases = css`
margin-top: 1px;
}
}
// 分支选择按钮
/* 分支选择按钮 */
.ui.button.branch-dropdown-button {
min-height: 20px;
line-height: 20px;
@@ -121,7 +122,7 @@ export const releases = css`
font-size: 12px;
}
}
// 右侧发布详细信息
/* 右侧发布详细信息 */
.segment.detail {
padding: 16px;
img.ui.avatar {
@@ -130,12 +131,12 @@ export const releases = css`
.svg {
color: ${themeVars.color.text.light.num1};
}
// 标题
/* 标题 */
.release-list-title {
font-size: 32px;
gap: 8px;
}
// 提交信息
/* 提交信息 */
p.text.grey {
display: flex;
gap: 6px;
@@ -148,13 +149,13 @@ export const releases = css`
color: ${themeVars.color.text.self};
}
}
// 发布内容
/* 发布内容 */
.markup {
> *:first-child {
margin-top: 24px !important;
}
}
// 分割线
/* 分割线 */
.divider {
position: relative;
left: -16px;
@@ -162,7 +163,7 @@ export const releases = css`
border-top-width: 1px;
margin: 24px 0 16px 0;
}
// 下载列表
/* 下载列表 */
.download {
summary {
font-size: 16px;
@@ -181,7 +182,7 @@ export const releases = css`
.flex-text-inline {
gap: 8px;
}
// 只选中左侧文件名称
/* 只选中左侧文件名称 */
strong.flex-text-inline:hover {
text-decoration: underline !important;
}
+11 -10
View File
@@ -17,21 +17,22 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 仓库头信息
export const repoHeader = css`
.page-content.repository .repo-header {
// 点星/关注/克隆/RSS 按钮
/* 点星/关注/克隆/RSS 按钮 */
.ui.compact.button {
padding: 3px 12px;
}
// 仓库名称
/* 仓库名称 */
.flex-item {
.flex-item-title {
// 间隔线颜色
/* 间隔线颜色 */
color: ${themeVars.color.text.light.num1};
// 仓库名称
/* 仓库名称 */
a {
display: flex;
align-items: center;
@@ -51,7 +52,7 @@ export const repoHeader = css`
}
}
}
// 默认的 hover 为 primary 颜色, 修正
/* 默认的 hover 为 primary 颜色, 修正 */
a:not(.label, .button):hover {
color: ${themeVars.color.text.self} !important;
}
@@ -66,7 +67,7 @@ export const repoMenu = css`
background-color: ${themeVars.color.box.header};
.item {
color: ${themeVars.color.text.light.num1};
height: 31px; // 文件列表下与右侧输入框对齐
height: 31px; /* 文件列表下与右侧输入框对齐 */
b {
color: ${themeVars.color.text.self};
margin: 0 2px;
@@ -85,10 +86,10 @@ export const repoMenu = css`
`;
export const repoTopic = css`
// 理应只能覆盖探索/组织/用户下仓库的 topic 标签
// 避免渲染到仓库的类型标签
/* 理应只能覆盖探索/组织/用户下仓库的 topic 标签 */
/* 避免渲染到仓库的类型标签 */
.flex-item-main > .label-list .ui.label,
// 仓库文件列表下的 topic 标签
/* 仓库文件列表下的 topic 标签 */
#repo-topics .ui.label.repo-topic {
border-radius: 9999px;
font-size: 12px;
+174 -31
View File
@@ -17,35 +17,37 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { activeItemAfterStyle } from "styles/public/menu";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { activeItemAfterStyle } from "styles/common";
// 仓库打开文件时的视图
export const repoFileView = css`
// 隐藏主内容的下内容和页脚, 避免滚动文件树时滚动条遮挡
/* 隐藏主内容的下内容和页脚, 避免滚动文件树时滚动条遮挡 */
body > .full.height:has(.repo-view-file-tree-container) {
padding-bottom: 0;
+ .page-footer {
display: none;
}
}
.page-content.repository.file.list {
.page-content.repository.file.list,
.page-content.repository.file.editor {
&:has(.repo-view-file-tree-container) {
// 取消下间隔优化观看体验
/* 取消下间隔优化观看体验 */
> .secondary-nav {
margin-bottom: 0 !important;
.ui.tabs.divider {
margin-bottom: 0;
}
}
// 为文件树选中项目伪元素让出 8px 的空间
/* 为文件树选中项目伪元素让出 8px 的空间 */
> .ui.container.fluid {
margin-left: 8px;
max-width: calc(100% - calc(2 * 8px));
}
}
.repo-view-container {
// 左侧文件树
/* 左侧文件树 */
.repo-view-file-tree-container {
height: 100vh;
flex: 0 0 20%;
@@ -67,7 +69,7 @@ export const repoFileView = css`
font-size: 16px;
margin: 16px 0;
padding: 8px;
// 固定头部, 早期父元素有多余的页脚和内容高度导致滚动时无法固定, 修复后也可保留此属性无需删除
/* 固定头部, 早期父元素有多余的页脚和内容高度导致滚动时无法固定, 修复后也可保留此属性无需删除 */
position: sticky;
top: 0;
&:after {
@@ -100,7 +102,7 @@ export const repoFileView = css`
}
}
}
// 右侧文件视图内容
/* 右侧文件视图内容 */
.repo-view-content {
padding-bottom: 40px;
.repo-button-row {
@@ -108,7 +110,7 @@ export const repoFileView = css`
background: ${themeVars.color.box.header};
border: 1px solid ${themeVars.color.secondary.self};
border-radius: ${otherThemeVars.border.radius};
height: 46px; // 固定高度匹配第二固定栏的 top 值
height: 46px; /* 固定高度匹配第二固定栏的 top 值 */
margin: 16px 0;
padding: 8px;
position: sticky;
@@ -117,7 +119,7 @@ export const repoFileView = css`
.ui.button {
min-height: 32px;
}
// 打开文件树按钮
/* 打开文件树按钮 */
.repo-view-file-tree-toggle {
background: initial;
border-color: #0000;
@@ -127,11 +129,11 @@ export const repoFileView = css`
background: ${themeVars.color.hover.self};
}
}
// 分支选择按钮
/* 分支选择按钮 */
.branch-dropdown-button {
padding: 0 12px;
}
// 路径
/* 路径 */
.repo-path {
gap: 4px;
.section {
@@ -149,13 +151,13 @@ export const repoFileView = css`
}
}
.non-diff-file-content {
// 避免分支菜单遮挡
/* 避免分支菜单遮挡 */
position: relative;
z-index: 0;
h4.file-header {
padding: 8px 12px !important;
position: sticky;
// 重叠边框线, 避免过粗
/* 重叠边框线, 避免过粗 */
top: 45px;
z-index: 1;
.file-header-left {
@@ -164,9 +166,9 @@ export const repoFileView = css`
}
.file-header-right {
gap: 0px;
// 按钮组
/* 按钮组 */
> .ui.buttons {
margin: 0 8px 0 0 !important; // 完全不知道为什么浏览器最终效果没生效, 只能 !important 了
margin: 0 8px 0 0 !important; /* 完全不知道为什么浏览器最终效果没生效, 只能 !important 了 */
.ui.mini.button {
min-height: 28px;
height: 28px;
@@ -174,7 +176,7 @@ export const repoFileView = css`
padding: 0 8px;
}
}
// 右侧操作按钮
/* 右侧操作按钮 */
> .btn-octicon {
display: flex;
align-items: center;
@@ -194,7 +196,7 @@ export const repoFileView = css`
&:last-of-type {
border-top-right-radius: ${otherThemeVars.border.radius};
border-bottom-right-radius: ${otherThemeVars.border.radius};
// 与无权限按钮之间的间距
/* 与无权限按钮之间的间距 */
+ .btn-octicon.disabled {
margin-left: 8px;
}
@@ -207,7 +209,7 @@ export const repoFileView = css`
}
}
}
// 头部提交信息
/* 头部提交信息 */
.ui.segment#repo-file-commit-box {
padding: 8px 12px;
margin-bottom: 16px !important;
@@ -217,7 +219,7 @@ export const repoFileView = css`
.commit-summary {
color: ${themeVars.color.text.light.num1};
}
// 作者
/* 作者 */
.author-wrapper {
display: flex;
}
@@ -227,7 +229,7 @@ export const repoFileView = css`
height: 20px;
}
}
// 右侧提交时间
/* 右侧提交时间 */
> .age {
display: flex;
align-items: center;
@@ -241,17 +243,158 @@ export const repoFileView = css`
// 避免手机/平板下路径容器过长导致换行, 取消固定
export const repoFileViewMobile = css`
@media (max-width: 1023.98px) {
.page-content.repository.file.list .repo-view-container .repo-view-content {
.repo-button-row {
height: auto;
position: static;
z-index: 0;
}
.non-diff-file-content {
h4.file-header {
top: 0;
.page-content.repository.file.list,
.page-content.repository.file.editor {
.repo-view-container .repo-view-content {
.repo-button-row {
height: auto;
position: static;
z-index: 0;
}
.non-diff-file-content {
h4.file-header {
top: 0;
}
}
}
}
}
`;
// 代码编辑器
export const codeEditorContainer = css`
.code-editor-container {
/* Gitea 限制最小高度为 90vh, 导致手机下留白过多, 但意义不明? */
min-height: auto;
/* 搜索面板 */
.cm-panel.cm-search {
background-color: ${themeVars.color.box.header};
padding: 8px;
gap: 0;
.cm-textfield {
background-color: ${themeVars.color.body};
margin: 4px 8px 4px 0px;
}
.cm-button {
background-color: ${themeVars.color.body};
padding: 4px 8px;
margin: 4px 8px 4px 0px;
text-transform: capitalize;
&:hover {
background-color: ${themeVars.color.button};
}
&:active {
background-image: none;
background-color: ${themeVars.color.hover.self};
}
}
> label {
margin: 4px 8px 4px 0px;
font-size: 12px;
font-weight: 600;
text-transform: capitalize;
}
/* 关闭按钮 */
button[name="close"] {
color: ${themeVars.color.text.self};
width: 14px;
height: 14px;
}
}
/* 编辑区 */
.cm-scroller,
.ͼ1 .cm-scroller {
font-family:
ui-monospace,
SFMono-Regular,
SF Mono,
Menlo,
Consolas,
Liberation Mono,
monospace;
}
}
`;
// 文件编辑器
export const fileEditor = css`
.page-content.repository.file.editor {
.repo-view-content {
/* 编辑器 */
.ui.edit.form {
/* 路径栏 */
.repo-editor-header {
margin: 16px 0;
min-height: 32px;
/* 路径 */
.breadcrumb {
gap: 8px;
/* 路径段和分隔符 */
.section,
.breadcrumb-divider {
font-size: 16px;
}
> .section:first-child {
font-weight: 600;
}
input {
margin-right: 0px !important;
}
svg {
color: ${themeVars.color.text.light.num1};
}
span:has(svg) {
display: flex;
align-items: center;
}
}
}
/* 编辑器操作栏 */
.ui.top.attached.header {
padding: 8px;
/* 左侧编辑/预览切换按钮 */
.ui.compact.small.menu.small-menu-items {
/* 切换样式在 compact_menu.ts 中 */
.item svg {
display: none;
}
}
/* 右侧操作项 */
.code-editor-options {
/* 图标按钮 */
.ui.compact.icon.button {
padding: 7px;
svg {
width: 14px;
height: 14px;
min-width: 14px;
min-height: 14px;
}
}
/* 选择下拉菜单 */
select {
background: ${themeVars.color.body};
font-size: 12px;
padding: 7px 20px 7px 12px;
}
}
}
}
}
}
`;
// 提交表单(编译修改时底部的提交信息)
export const commitForm = css`
.repository.file.editor .commit-form-wrapper {
.commit-avatar {
border-radius: 9999px;
}
.commit-form.avatar-content-left-arrow {
&::before,
&::after {
display: none;
}
}
}
`;
+17 -16
View File
@@ -17,20 +17,21 @@
* limitations under the License.
*/
import { animationDown } from "src/core/styles";
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { animationDown } from "styles/common";
// 文件列表页面下的分支按钮
export const branchButton = css`
.page-content.repository.file.list {
.ui.dropdown.branch-selector-dropdown > .menu > .menu {
// 显示默认分支的标签
/* 显示默认分支的标签 */
.ui.label {
background-color: ${themeVars.color.menu};
border: 1px solid ${themeVars.color.light.border};
margin-top: 1px;
margin-left: auto;
margin-right: 20px; // gitea 有 RSS 留出足够的空间
margin-right: 20px; /* gitea 有 RSS 留出足够的空间 */
}
}
}
@@ -52,12 +53,12 @@ export const syncFork = css`
export const fileSearch = css`
.file-search-popup.file-search-popup.file-search-popup {
${animationDown};
// 统一所有下拉菜单的样式
/* 统一所有下拉菜单的样式 */
background-color: ${themeVars.color.menu};
border: unset;
border-radius: 12px;
box-shadow: ${themeVars.github.shadow.floating.small};
z-index: 2; // 避免文件内容浏览界面中的固定导航栏遮挡
z-index: 2; /* 避免文件内容浏览界面中的固定导航栏遮挡 */
.file-search-results {
padding: 12px;
.item {
@@ -82,11 +83,11 @@ export const fileSearch = css`
`;
// 仓库文件列表
export const repoFiles = css`
// 文件列表和提交列表的按钮组
/* 文件列表和提交列表的按钮组 */
.repo-button-row {
margin: 16px 0;
.repo-button-row-right {
// 转到文件搜索框
/* 转到文件搜索框 */
.repo-file-search-container .ui.input {
min-height: 32px;
height: 32px;
@@ -94,7 +95,7 @@ export const repoFiles = css`
background: unset;
}
}
// 添加文件按钮
/* 添加文件按钮 */
.repo-add-file {
padding: 0px 26px 0px 12px;
.menu > .item {
@@ -110,10 +111,10 @@ export const repoFiles = css`
.repository.file.list {
#repo-files-table {
margin: 16px 0;
// 头部最后一次提交
/* 头部最后一次提交 */
.repo-file-line {
padding-right: 16px;
// 父目录
/* 父目录 */
&.parent-link {
gap: 0.5rem;
padding-left: 16px;
@@ -121,7 +122,7 @@ export const repoFiles = css`
margin-right: 2px;
}
}
// 最后一次提交
/* 最后一次提交 */
&.repo-file-last-commit {
min-height: 3.725rem;
.latest-commit {
@@ -135,14 +136,14 @@ export const repoFiles = css`
width: 20px;
height: 20px;
}
// 作者
/* 作者 */
.author-wrapper {
display: flex;
&:hover {
color: ${themeVars.color.text.self};
}
}
// 提交哈希值
/* 提交哈希值 */
.ui.label {
display: none;
}
@@ -152,7 +153,7 @@ export const repoFiles = css`
}
}
}
// 文件列表
/* 文件列表 */
.repo-file-item {
.repo-file-cell {
height: 40px;
@@ -180,7 +181,7 @@ export const repoFiles = css`
.file-header-left {
padding: 6px 8px !important;
line-height: 1.45;
// 伪元素宽度等于按钮宽度而不是父元素宽度
/* 伪元素宽度等于按钮宽度而不是父元素宽度 */
position: relative;
&:hover {
background: ${themeVars.github.control.transparent.bgColor.hover};
+6 -5
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// 仓库代码布局调整, 侧边栏宽度调整
export const repoGrid = css`
@@ -37,7 +38,7 @@ export const repoGrid = css`
export const repoSidebarTop = css`
.page-content.repository.file.list {
.repo-home-sidebar-top {
// 搜索代码
/* 搜索代码 */
.ui.input > input {
background: unset;
}
@@ -46,11 +47,11 @@ export const repoSidebarTop = css`
}
.flex-item {
padding: 10px 0 0 0;
// 仓库描述本身
/* 仓库描述本身 */
.flex-item-title {
margin-top: 10px;
}
// 仓库描述内容
/* 仓库描述内容 */
.flex-item-body {
> .tw-flex:first-child {
margin-top: 16px !important;
@@ -108,7 +109,7 @@ export const repoSidebarBottom = css`
font-size: 12px;
}
}
// 编程语言
/* 编程语言 */
.language-stats {
height: 8px;
margin-bottom: 0px;
+15 -14
View File
@@ -17,9 +17,10 @@
* limitations under the License.
*/
import { type StyleRule } from "@vanilla-extract/css";
import { css, themeVars } from "src/types/vars";
import { primaryHoverStyle, primaryStyle } from "styles/public/button";
import { css } from "@linaria/core";
import type { StyleRule } from "@vanilla-extract/css";
import { themeVars } from "src";
import { primaryButtonHoverStyle, primaryButtonStyle } from "styles/common";
const tinyStyle = {
color: themeVars.github.button.primary.fgColor.accent,
@@ -35,12 +36,12 @@ const tinyHoverStyle = {
// 设置界面下的按钮
export const button = css`
// 不包含管理员的设置界面
/* 不包含管理员的设置界面 */
.user-main-content,
.repo-setting-content,
.user-setting-content,
.org-setting-content {
// 主色调按钮替换为普通按钮
/* 主色调按钮替换为普通按钮 */
.ui.primary.button {
color: ${themeVars.color.text.light.self};
background-color: ${themeVars.color.button};
@@ -53,7 +54,7 @@ export const button = css`
background-color: ${themeVars.github.button.default.bgColor.active};
}
}
// 迷你按钮替换为自定义的主色调按钮 (例: SSH 验证按钮)
/* 迷你按钮替换为自定义的主色调按钮 (例: SSH 验证按钮) */
.ui.primary.button.tiny {
${tinyStyle}
&:hover {
@@ -64,21 +65,21 @@ export const button = css`
}
}
}
// 所有设置界面
/* 所有设置界面 */
.user-main-content,
.repo-setting-content,
.user-setting-content,
.org-setting-content,
.admin-setting-content {
// 右上角迷你按钮替换会主色调按钮
/* 右上角迷你按钮替换会主色调按钮 */
.ui.attached.header > .ui.right {
.ui.primary.button.tiny {
${primaryStyle}
${primaryButtonStyle}
padding: 3px 12px;
min-height: 20px;
line-height: 20px;
&:hover {
${primaryHoverStyle}
${primaryButtonHoverStyle}
}
&:active {
background-color: ${themeVars.github.button.primary.bgColor.active};
@@ -86,7 +87,7 @@ export const button = css`
}
}
}
// 管理员设置界面下的自定义主色调按钮
/* 管理员设置界面下的自定义主色调按钮 */
.admin-setting-content {
.ui.primary.button {
${tinyStyle}
@@ -97,7 +98,7 @@ export const button = css`
}
&:active {
background-color: ${themeVars.github.button.primary.bgColor.active};
// 保持鼠标移开时边框颜色和文字颜色不变
/* 保持鼠标移开时边框颜色和文字颜色不变 */
border-color: ${themeVars.github.button.primary.borderColor.hover};
color: ${themeVars.github.button.primary.fgColor.rest};
}
@@ -111,9 +112,9 @@ export const button = css`
`;
export const label = css`
// Runner 标签
/* Runner 标签 */
.runner-container {
// 普通标签, runner 状态: 离线, runner 标签
/* 普通标签, runner 状态: 离线, runner 标签 */
.ui.label {
border: 1px solid ${themeVars.color.light.border};
}
+1 -1
View File
@@ -17,7 +17,7 @@
* limitations under the License.
*/
import { css } from "src/types/vars";
import { css } from "@linaria/core";
// 注册/登录界面
export const signIn = css`
+11 -10
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// 用户点星仓库列表
export const stars = css`
@@ -29,27 +30,27 @@ export const stars = css`
&:first-child {
padding-top: 14px;
}
// 仓库头像
/* 仓库头像 */
> .flex-item-leading {
img,
svg {
color: ${themeVars.color.text.light.num1};
}
}
// 仓库信息
/* 仓库信息 */
> .flex-item-main {
// 仓库标题
/* 仓库标题 */
> .flex-item-header {
// 仓库名称
/* 仓库名称 */
> .flex-item-title {
font-size: 20px;
gap: 8px;
// 仓库中间的间隔线
/* 仓库中间的间隔线 */
&:not(a) {
color: ${themeVars.color.primary.self};
}
}
// 仓库语言, 星标
/* 仓库语言, 星标 */
> .flex-item-trailing {
color: ${themeVars.color.text.light.num1};
gap: 16px;
@@ -61,15 +62,15 @@ export const stars = css`
}
}
}
// 描述和更新时间
/* 描述和更新时间 */
> .flex-item-body {
margin-top: 10px;
// 更新时间
/* 更新时间 */
&:last-child {
font-size: 12px;
}
}
// 主题标签
/* 主题标签 */
> .label-list {
margin-top: 10px;
}
+6 -5
View File
@@ -17,17 +17,18 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const attached = css`
// 设置右面板的内容
/* 设置右面板的内容 */
.user-main-content,
.repo-setting-content,
.user-setting-content,
.org-setting-content,
.admin-setting-content,
// 仓库动态页面
// 新建页面内容
/* 仓库动态页面 */
/* 新建页面内容 */
.page-content.repository.new-repo,
.page-content.repository.new.migrate,
.page-content.repository.new.fork,
@@ -56,7 +57,7 @@ export const attached = css`
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
}
// 隐藏的元素下面的元素, 目前仅适用于在后台控制中的自我检查
/* 隐藏的元素下面的元素, 目前仅适用于在后台控制中的自我检查 */
&.tw-hidden + .ui.attached.segment {
border-top-width: 1px !important;
border-top-left-radius: ${otherThemeVars.border.radius} !important;
+4 -4
View File
@@ -17,20 +17,20 @@
* limitations under the License.
*/
import { css } from "src/types/vars";
import { css } from "@linaria/core";
export const body = css`
body {
line-height: 1.5;
}
a {
text-underline-offset: 0.2rem; // 0.2rem 可以始终保持下划线不受 overflow: hidden 的影响
text-underline-offset: 0.2rem; /* 0.2rem 可以始终保持下划线不受 overflow: hidden 的影响 */
}
// 默认代码块
/* 默认代码块 */
code:not(.code-inner) {
padding: 0.2em 0.4em;
}
// 快捷键提示(输入框内)
/* 快捷键提示(输入框内) */
kbd {
background-color: #0000;
font-size: 12px;
+21 -32
View File
@@ -17,21 +17,9 @@
* limitations under the License.
*/
import { type StyleRule } from "@vanilla-extract/css";
import { css, themeVars } from "src/types/vars";
export const primaryStyle = {
color: themeVars.github.button.primary.fgColor.rest,
backgroundColor: themeVars.github.button.primary.bgColor.rest,
borderColor: themeVars.github.button.primary.borderColor.rest,
boxShadow: themeVars.github.shadow.resting.small,
} satisfies StyleRule;
export const primaryHoverStyle = {
color: themeVars.github.button.primary.fgColor.rest,
backgroundColor: themeVars.github.button.primary.bgColor.hover,
borderColor: themeVars.github.button.primary.borderColor.hover,
} satisfies StyleRule;
import { css } from "@linaria/core";
import { themeVars } from "src";
import { primaryButtonHoverStyle, primaryButtonStyle } from "styles/common";
// 普通按钮和主色调按钮
export const baseButton = css`
@@ -46,33 +34,34 @@ export const baseButton = css`
.ui.button:not(.primary):not(.red) svg {
color: ${themeVars.color.text.light.num1};
}
// 主色调按钮保持白色
.ui.primary.buttons .button svg {
color: ${themeVars.color.white};
}
/* 主色调按钮 */
.ui.primary {
&.button,
// 按钮组, PR 里的压缩合并按钮
/* 按钮组, PR 里的压缩合并按钮 */
&.buttons .button {
${primaryStyle}
${primaryButtonStyle}
&:hover {
${primaryHoverStyle}
${primaryButtonHoverStyle}
}
&:active {
${primaryButtonHoverStyle}
background-color: ${themeVars.github.button.primary.bgColor.active};
}
svg {
color: ${themeVars.github.button.primary.fgColor.rest};
}
}
// 按钮组整体有阴影
/* 按钮组整体有阴影 */
&.buttons {
box-shadow: ${themeVars.github.shadow.resting.small};
.button {
// 按钮组里的按钮无阴影
/* 按钮组里的按钮无阴影 */
box-shadow: none;
}
}
}
// 主色调基本按钮和普通按钮一样
// 作者的关注按钮
/* 主色调基本按钮和普通按钮一样 */
/* 作者的关注按钮 */
.ui.basic.primary.button {
background-color: ${themeVars.color.button};
color: ${themeVars.color.text.self};
@@ -112,7 +101,7 @@ export const redButton = css`
.ui.basic.red.button {
color: ${themeVars.github.button.danger.fgColor.rest};
background-color: ${themeVars.github.button.danger.bgColor.rest};
// 一些按钮边框色为红色, 比如危险操作区, 统一为暗色边框和 github 一致
/* 一些按钮边框色为红色, 比如危险操作区, 统一为暗色边框和 github 一致 */
border-color: ${themeVars.color.light.border};
&:hover {
color: ${themeVars.github.button.danger.fgColor.hover};
@@ -131,18 +120,18 @@ export const redButton = css`
// 修复按钮高度
export const fixButtonHeight = css`
// 修复一些主色调或者其他小按钮的高度避免过高
/* 修复一些主色调或者其他小按钮的高度避免过高 */
.ui.small.buttons .button,
.ui.ui.ui.ui.small.button {
min-height: 26px;
height: 32px;
}
// 修复仓库页仓库操作按钮高度对齐和修正
/* 修复仓库页仓库操作按钮高度对齐和修正 */
.repo-button-row .ui.button {
min-height: 32px;
height: 32px;
}
// 修复因上面小按钮高度导致仓库星标克隆等按钮高度过高
/* 修复因上面小按钮高度导致仓库星标克隆等按钮高度过高 */
.repo-header {
.ui.ui.ui.ui.small.compact.button,
.ui.labeled.button > .label {
@@ -158,11 +147,11 @@ export const fixButtonHeight = css`
`;
export const fixButton = css`
// 修复关注&派生 hover 意外点亮右侧 label 左边框
/* 修复关注&派生 hover 意外点亮右侧 label 左边框 */
.ui.ui.ui.ui.small.button {
z-index: 0;
}
// 代码复制按钮
/* 代码复制按钮 */
.ui.button.code-copy {
padding: 4px 6px;
min-height: 28px;
+6 -5
View File
@@ -17,9 +17,10 @@
* limitations under the License.
*/
import { animationDown } from "src/core/styles";
import { fallbackVar } from "src/functions";
import { css, customThemeVars, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { fallbackVar } from "@vanilla-extract/css";
import { customThemeVars, otherThemeVars, themeVars } from "src";
import { animationDown } from "styles/common";
// 分支菜单
export const branchDropdown = css`
@@ -30,7 +31,7 @@ export const branchDropdown = css`
${animationDown};
height: 32px;
}
// 分支/标签切换
/* 分支/标签切换 */
> .branch-tag-tab {
> .branch-tag-item {
font-weight: 500;
@@ -61,7 +62,7 @@ export const branchDropdown = css`
// 手机页面下的分支菜单
export const branchDropdownMobile = css`
@media (max-width: 767.98px) {
// 修复手机下分支菜单宽度过宽
/* 修复手机下分支菜单宽度过宽 */
.ui.dropdown.branch-selector-dropdown > .menu {
width: auto;
}
+35 -31
View File
@@ -17,21 +17,25 @@
* limitations under the License.
*/
import { animationDown, animationUp } from "src/core/styles";
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { activeItemAfterStyle } from "styles/public/menu";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { activeItemAfterStyle, animationDown, animationUp } from "styles/common";
export const dropdown = css`
.ui.dropdown,
.ui.menu .ui.dropdown {
.menu {
${animationDown};
// 统一所有下拉菜单的样式
background-color: ${themeVars.color.menu} !important;
border: unset !important;
/* 统一所有下拉菜单的样式 */
background-color: ${themeVars.color.menu};
border: none !important;
border-radius: 12px !important;
box-shadow: ${themeVars.github.shadow.floating.small} !important;
// 忽略隐藏
box-shadow: ${themeVars.github.shadow.floating.small};
/* 修复 lightingcss 导致的优先级问题 */
&.scrolling {
box-shadow: none !important;
}
/* 忽略隐藏 */
> .item:not(.tw-hidden) {
display: flex !important;
align-items: center;
@@ -45,14 +49,14 @@ export const dropdown = css`
}
&:not(.emoji):first-of-type {
margin-top: 8px;
// 工单详细页面的标签菜单中的清除选中标签按钮
/* 工单详细页面的标签菜单中的清除选中标签按钮 */
&.clear-selection {
margin-top: 0px;
}
}
// 不知道为什么提交差异对比页面操作中的 cherrypick 按钮无法被选中
/* 不知道为什么提交差异对比页面操作中的 cherrypick 按钮无法被选中 */
&.cherry-pick-button,
// 下一个 item 是最后一个并且被隐藏时, 目前仅在顶部导航栏工单和 PR 仪表板的菜单中出现
/* 下一个 item 是最后一个并且被隐藏时, 目前仅在顶部导航栏工单和 PR 仪表板的菜单中出现 */
&:has(+ .tw-hidden:last-of-type),
&:not(.emoji):last-of-type {
margin-bottom: 8px;
@@ -77,18 +81,18 @@ export const dropdown = css`
margin-top: 2px;
margin-right: 2px;
}
// 复选框对齐
/* 复选框对齐 */
.ui.checkbox input[type="checkbox"] {
top: 3px;
}
// 修复 Wiki 页面下搜索框中搜索时, 显示隐藏的项目
/* 修复 Wiki 页面下搜索框中搜索时, 显示隐藏的项目 */
&.filtered {
display: none !important;
}
}
// 当筛选后, 让菜单提供边距, 因为无法确定保留的是菜单中哪个 item
// 不是所有菜单都提供边距方式, 原因为比如会导致分支菜单中的查看所有分支上间隔缺失, 这种方式单独为 Wiki 菜单做处理
// 有筛选(.filtered)且有筛选结果(.selected)时提供菜单边距, 没结果时提供会导致多余的菜单边框线
/* 当筛选后, 让菜单提供边距, 因为无法确定保留的是菜单中哪个 item */
/* 不是所有菜单都提供边距方式, 原因为比如会导致分支菜单中的查看所有分支上间隔缺失, 这种方式单独为 Wiki 菜单做处理 */
/* 有筛选(.filtered)且有筛选结果(.selected)时提供菜单边距, 没结果时提供会导致多余的菜单边框线 */
&:has(> .item.filtered):has(> .item.selected) {
padding: 8px 0px;
> .item {
@@ -108,14 +112,14 @@ export const dropdown = css`
}
}
}
// 向下弹出的下拉菜单向下偏移
/* 向下弹出的下拉菜单向下偏移 */
.ui.dropdown:not(.upward),
.ui.menu .ui.dropdown:not(.upward) {
> .menu {
margin-top: 4px !important;
}
}
// 向上弹出的下拉菜单向上偏移
/* 向上弹出的下拉菜单向上偏移 */
.ui.dropdown.upward,
.ui.menu .ui.dropdown.upward {
> .menu {
@@ -123,41 +127,41 @@ export const dropdown = css`
margin-bottom: 4px !important;
}
}
// 修复 wiki 的页面下拉菜单圆角
/* 修复 wiki 的页面下拉菜单圆角 */
.ui.floating.dropdown > .menu {
border-radius: 12px !important;
}
// 修复嵌套菜单的圆角问题, wiki 页面和组织页面的用户下拉菜单
/* 修复嵌套菜单的圆角问题, wiki 页面和组织页面的用户下拉菜单 */
.ui.dropdown .menu {
.scrolling.menu {
border-radius: 0 0 12px 12px !important;
}
// 修复仪表板切换用户按钮菜单下无创建组织按钮时的菜单圆角
/* 修复仪表板切换用户按钮菜单下无创建组织按钮时的菜单圆角 */
&.context-user-switch {
.scrolling.menu:last-child {
border-radius: 0 0 12px 12px !important;
}
}
}
// 修复下拉菜单元素溢出问题
// 用户菜单
/* 修复下拉菜单元素溢出问题 */
/* 用户菜单 */
.user-menu>.item,
// Issue/PR 菜单
/* Issue/PR 菜单 */
.ui.menu .ui.dropdown.item .menu .item {
width: calc(100% - 16px); // 减去上方 item 的 margin 左右边距
width: calc(100% - 16px); /* 减去上方 item 的 margin 左右边距 */
}
// 去掉下拉菜单的边框线
// 设置里的下拉菜单
/* 去掉下拉菜单的边框线 */
/* 设置里的下拉菜单 */
.ui.selection.dropdown .menu > .item {
border: unset;
}
// 修复一些菜单下的菜单元素溢出问题
// 目前主要为分支菜单
/* 修复一些菜单下的菜单元素溢出问题 */
/* 目前主要为分支菜单 */
.ui.dropdown .menu .menu {
border-radius: 12px !important;
}
// 修复按钮阴影被覆盖缺少边框线的问题
// 仓库动态页面的右侧按钮, 比如时间周期
/* 修复按钮阴影被覆盖缺少边框线的问题 */
/* 仓库动态页面的右侧按钮, 比如时间周期 */
.ui.floating.dropdown .menu {
box-shadow: ${themeVars.github.shadow.floating.small} !important;
}
+2 -1
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// 包含表情的下拉菜单
export const emojiDropdown = css`
+35 -22
View File
@@ -17,12 +17,13 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { activeItemAfterStyle } from "styles/public/menu";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { activeItemAfterStyle } from "styles/common";
// 选择框的下拉菜单看起来像普通按钮
export const selectionDropdown = css`
// 排除可以选择的输入搜索框和创建仓库的拥有者
/* 排除可以选择的输入搜索框和创建仓库的拥有者 */
.ui.selection.dropdown:not(.search):not(.ellipsis-text-items),
.ui.selection.dropdown.active:not(.search):not(.ellipsis-text-items) {
background-color: ${themeVars.color.button};
@@ -38,23 +39,35 @@ export const selectionDropdown = css`
background: ${themeVars.color.hover.self};
border-color: ${themeVars.color.light.border};
}
// 悬停提供伪元素
/* 悬停提供伪元素 */
.item:hover:after {
content: "";
${activeItemAfterStyle};
}
}
// 修复顶部导航栏工单管理/请求合并页面搜索框旁的选择下拉框按钮内容过窄
/* 修复 Gitea 1.26 增加的阴影样式 */
.ui.selection.dropdown,
.ui.selection.dropdown.active {
/* 修复 Gitea 1.26 多余的阴影 */
&:hover {
box-shadow: none;
/* 修复 Gitea 1.26 覆盖的阴影 */
.menu {
box-shadow: ${themeVars.github.shadow.floating.small};
}
}
}
/* 修复顶部导航栏工单管理/请求合并页面搜索框旁的选择下拉框按钮内容过窄 */
.list-header-search .ui.action.input > .dropdown.small {
padding: 8px 40px 8px 16px;
}
// 发布版本页面的分支按钮, 覆盖 Gitea 的样式, 避免按钮元素高度不一致
/* 发布版本页面的分支按钮, 覆盖 Gitea 的样式, 避免按钮元素高度不一致 */
.repository.new.release .target .selection.dropdown {
padding-top: 8px;
padding-bottom: 8px;
}
// 这个按钮项目前只在创建仓库的拥有者
// 不实现伪元素, 因为 .item 设置溢出的元素会被截断
/* 这个按钮项目前只在创建仓库的拥有者 */
/* 不实现伪元素, 因为 .item 设置溢出的元素会被截断 */
.ui.selection.dropdown.ellipsis-text-items,
.ui.selection.dropdown.activeellipsis-text-items {
&:focus {
@@ -66,43 +79,43 @@ export const selectionDropdown = css`
border-color: ${themeVars.color.light.border};
}
}
// 选择输入框效果和输入框 focus 效果一样
/* 选择输入框效果和输入框 focus 效果一样 */
.ui.selection.dropdown.active.search {
background: ${themeVars.color.body};
// 向内部添加一个 1px 的边框
/* 向内部添加一个 1px 的边框 */
box-shadow: inset 0 0 0 1px ${themeVars.github.borderColor.accent.emphasis};
outline: none;
}
// 覆盖选择输入框向上弹出时的 hover 效果, 原阴影会覆盖加厚的边框线
/* 覆盖选择输入框向上弹出时的 hover 效果, 原阴影会覆盖加厚的边框线 */
.ui.selection.dropdown.active.search.upward:hover {
box-shadow: inset 0 0 0 1px ${themeVars.github.borderColor.accent.emphasis};
}
// 由于之前的排除导致样式优先级变高, 小按钮去除圆角
/* 由于之前的排除导致样式优先级变高, 小按钮去除圆角 */
.ui.action.input > .dropdown.small:not(:first-child) {
border-radius: 0;
}
// 排除一些小按钮, 例如软件包类型, 通常相邻有元素
/* 排除一些小按钮, 例如软件包类型, 通常相邻有元素 */
.ui.selection.dropdown.active:not(.small) {
border-bottom-left-radius: ${otherThemeVars.border.radius} !important;
border-bottom-right-radius: ${otherThemeVars.border.radius} !important;
}
// 修复因为上面的排除导致的圆角问题
// 具体工单页面下依赖菜单选择框
/* 修复因为上面的排除导致的圆角问题 */
/* 具体工单页面下依赖菜单选择框 */
#new-dependency-drop-list.ui.selection.dropdown.active,
// 提交图分支选择框
/* 提交图分支选择框 */
#git-graph-container #flow-select-refs-dropdown {
border-bottom-right-radius: 0 !important;
}
// 修复选择框的下拉菜单向上显示时的样式问题
/* 修复选择框的下拉菜单向上显示时的样式问题 */
.ui.upward.selection.dropdown.visible:not(.small),
.ui.active.upward.selection.dropdown:not(.small) {
border-top-left-radius: ${otherThemeVars.border.radius} !important;
border-top-right-radius: ${otherThemeVars.border.radius} !important;
}
// 工单标签菜单中的标签换行和颜色
// 标签页面的标签选择框
/* 工单标签菜单中的标签换行和颜色 */
/* 标签页面的标签选择框 */
.page-content.repository.labels .ui.selection.dropdown.active,
// 创建仓库页面的标签选择框
/* 创建仓库页面的标签选择框 */
.page-content.repository.new-repo .ui.search.selection.dropdown {
> .menu > .item {
flex-direction: column;
@@ -115,9 +128,9 @@ export const selectionDropdown = css`
`;
export const fixSelectionDropdown = css`
// 具体工单页面下依赖菜单选择框
/* 具体工单页面下依赖菜单选择框 */
#new-dependency-drop-list.ui.selection.dropdown {
// 高度对齐问题, 应该与 input 框高度一致
/* 高度对齐问题, 应该与 input 框高度一致 */
min-height: 32px;
}
`;
+11 -10
View File
@@ -17,14 +17,15 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const input = css`
textarea,
// 排除复选框和单选框
/* 排除复选框和单选框 */
input:not([type=checkbox],[type=radio]),
.ui.input input:not([type=checkbox],[type=radio]),
// 排除可以选择的输入搜索框
/* 排除可以选择的输入搜索框 */
.ui.form input:not([type]):not(.search),
.ui.form select,
.ui.form textarea,
@@ -44,9 +45,9 @@ export const input = css`
padding: 8px 12px;
&:focus,
&:focus-visible {
background: ${themeVars.color.body} !important;
background: ${themeVars.color.body};
border-color: ${themeVars.github.borderColor.accent.emphasis};
// 向内部添加一个 1px 的边框
/* 向内部添加一个 1px 的边框 */
box-shadow: inset 0 0 0 1px ${themeVars.github.borderColor.accent.emphasis};
outline: none;
}
@@ -54,19 +55,19 @@ export const input = css`
.ui.input {
height: 32px;
}
// 由于输入框高度, 需要输入框在表单中垂直居中
// 管理员页面仓库搜索表单
/* 由于输入框高度, 需要输入框在表单中垂直居中 */
/* 管理员页面仓库搜索表单 */
.ui.form#repo-search-form {
align-items: center;
}
// 下拉菜单的输入框
/* 下拉菜单的输入框 */
.ui.dropdown.dropdown .menu > .input {
margin: 12px 10px;
}
`;
// 复选框和单选框
export const checkBoxAndRadio = css`
// 复选框
/* 复选框 */
input[type="checkbox"],
.ui.checkbox input[type="checkbox"] {
background-color: ${themeVars.color.body};
@@ -80,7 +81,7 @@ export const checkBoxAndRadio = css`
background-color: ${themeVars.github.fgColor.onEmphasis};
}
}
// 单选框
/* 单选框 */
input[type="radio"],
.ui.checkbox input[type="radio"] {
background-color: ${themeVars.color.body};
+5 -7
View File
@@ -17,11 +17,9 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
export const labelStyle = {
padding: "0px 6px",
};
import { css } from "@linaria/core";
import { themeVars } from "src";
import { labelStyle } from "styles/common";
export const label = css`
.ui.label {
@@ -31,7 +29,7 @@ export const label = css`
/* a 标签比如仓库点星等按钮旁边的数字标签按钮,提交图中的 tag 标签 */
div.label,
span.label,
// 包含多个标签的元素, 比如 Issue/PR 详情页中的时间线上的标签
/* 包含多个标签的元素, 比如 Issue/PR 详情页中的时间线上的标签 */
span.labels-list a.label {
&.ui.ui.ui {
border-radius: 9999px;
@@ -40,7 +38,7 @@ export const label = css`
&.mini {
line-height: 16px;
}
// 多个标签的组合标签的圆角修复
/* 多个标签的组合标签的圆角修复 */
&.scope-parent {
.scope-left {
border-top-right-radius: 0;
+3 -2
View File
@@ -17,12 +17,13 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// 仓库标签 (私有/公开/内部)
export const repoLabel = css`
span,
// 用户切换面板的标签
/* 用户切换面板的标签 */
.org-visibility div {
&.ui.basic.label {
background-color: unset;
+10 -9
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// 提交中的 SHA 标签
export const shaLabel = css`
@@ -28,12 +29,12 @@ export const shaLabel = css`
color: ${themeVars.color.text.light.num1};
font-size: 12px;
font-weight: 500;
// 仪表盘页的提交 SHA 标签居中对齐
/* 仪表盘页的提交 SHA 标签居中对齐 */
margin-top: 2px;
&:hover {
background-color: ${themeVars.color.label.hoverBg};
}
// 验证提交 SHA 标签
/* 验证提交 SHA 标签 */
&.commit-is-signed {
border: unset !important;
background-color: unset !important;
@@ -49,16 +50,16 @@ export const shaLabel = css`
}
}
}
// 修复带验证的提交 SHA 标签的高度
/* 修复带验证的提交 SHA 标签的高度 */
.ui.label.commit-id-short {
height: 25px;
}
// 验证提交附带的图标
/* 验证提交附带的图标 */
span.ui.label.commit-is-signed {
height: 25px;
min-width: 35px;
justify-content: center;
// 验证信任
/* 验证信任 */
&.sign-trusted {
border: 1.5px solid ${themeVars.color.green.badge.self} !important;
color: ${themeVars.color.green.badge.self} !important;
@@ -66,7 +67,7 @@ export const shaLabel = css`
background-color: ${themeVars.color.green.badge.hover.bg} !important;
}
}
// 验证未信任
/* 验证未信任 */
&.sign-untrusted {
border: 1.5px solid ${themeVars.color.yellow.badge.self} !important;
color: ${themeVars.color.yellow.badge.self} !important;
@@ -74,7 +75,7 @@ export const shaLabel = css`
background-color: ${themeVars.color.yellow.badge.hover.bg} !important;
}
}
// 验证未匹配
/* 验证未匹配 */
&.sign-unmatched {
border: 1.5px solid ${themeVars.color.orange.badge.self} !important;
color: ${themeVars.color.orange.badge.self} !important;
@@ -82,7 +83,7 @@ export const shaLabel = css`
background-color: ${themeVars.color.orange.badge.hover.bg} !important;
}
}
// 验证警告
/* 验证警告 */
&.sign-warning {
border: 1.5px solid ${themeVars.color.red.badge.self} !important;
color: ${themeVars.color.red.badge.self} !important;
+2 -1
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
// 任务状态标签, 目前仅在管理员页面 Runner 状态中看到
export const taskStatusLabel = css`
+14 -11
View File
@@ -17,32 +17,35 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 单行双选项菜单
export const smallCompactMenu = css`
// 订阅/关注切换菜单(应只选中订阅/关注页面, 不能选中通知页面)
/* 编辑/预览切换菜单(仓库编辑文件时的编辑器操作栏左侧) */
.page-content.repository.file.editor .repo-view-content .ui.edit.form .ui.top.attached.header,
/* 订阅/关注切换菜单(应只选中订阅/关注页面, 不能选中通知页面) */
.page-content.user.notification > .ui.container:has(.flex-list),
// 里程碑/标签切换菜单(里程碑页)
/* 里程碑/标签切换菜单(里程碑页) */
.page-content.repository.milestones .list-header,
// 里程碑/标签切换菜单(新建里程碑页)
/* 里程碑/标签切换菜单(新建里程碑页) */
.page-content.repository.new.milestone .issue-navbar,
// 里程碑/标签切换菜单(标签页)
/* 里程碑/标签切换菜单(标签页) */
.page-content.repository.labels .issue-navbar {
.ui.compact.small.menu.small-menu-items {
background: ${themeVars.color.hover.self} !important;
border: 0;
background: ${themeVars.github.controlTrack.bgColor.rest} !important;
border: 1px solid ${themeVars.color.light.border};
font-size: 14px;
gap: 8px;
height: 32px;
min-height: 32px !important;
> .item {
background: unset !important;
border: 1px solid ${themeVars.color.hover.self};
border: 1px solid ${themeVars.github.controlTrack.bgColor.rest};
border-radius: ${otherThemeVars.border.radius};
padding: 6px 12px !important;
&.active {
background: ${themeVars.color.menu} !important;
background: ${themeVars.github.controlKnob.bgColor.rest} !important;
border-color: ${themeVars.color.light.border};
font-weight: 600;
}
@@ -54,8 +57,8 @@ export const smallCompactMenu = css`
padding: 4px 12px !important;
height: calc(100% - 8px);
position: relative;
// 该方案只适用于 2 个 item 的情况
// left / right 数值为 gap 数值的一半
/* 该方案只适用于 2 个 item 的情况 */
/* left / right 数值为 gap 数值的一半 */
&:first-child {
left: 4px;
}
-13
View File
@@ -22,16 +22,3 @@ import "./menu";
import "./pagination_menu";
import "./secondary_menu";
import "./vertical_menu";
import { type StyleRule } from "@vanilla-extract/css";
import { otherThemeVars, themeVars } from "src/types/vars";
export const activeItemAfterStyle = {
backgroundColor: themeVars.github.borderColor.accent.emphasis,
borderRadius: otherThemeVars.border.radius,
height: "24px",
left: "-8px",
position: "absolute",
top: "calc(50% - 12px)",
width: "4px",
} satisfies StyleRule;
+7 -6
View File
@@ -17,8 +17,9 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { labelStyle } from "styles/public/label/label";
import { css } from "@linaria/core";
import { themeVars } from "src";
import { labelStyle } from "styles/common";
export const menu = css`
.ui.menu {
@@ -27,7 +28,7 @@ export const menu = css`
.menu .item svg {
color: ${themeVars.color.text.light.num1};
}
// 菜单默认悬浮色更改
/* 菜单默认悬浮色更改 */
.ui.menu a.item,
.ui.secondary.pointing.menu a.item,
.ui.secondary.menu .dropdown.item {
@@ -35,14 +36,14 @@ export const menu = css`
background: ${themeVars.github.control.transparent.bgColor.hover};
}
}
// 一些水平小型菜单的颜色更改
/* 一些水平小型菜单的颜色更改 */
.small-menu-items .item {
background-color: ${themeVars.color.body} !important;
&:hover {
background: ${themeVars.github.control.transparent.bgColor.hover} !important;
}
}
// 一些菜单的悬浮色更改
/* 一些菜单的悬浮色更改 */
.ui.segment .ui.tabular.menu,
.header-wrapper .ui.tabular.menu,
.ui.secondary.pointing.menu {
@@ -53,7 +54,7 @@ export const menu = css`
}
}
}
// 菜单标签样式
/* 菜单标签样式 */
.ui.menu .item > .label:not(.floating) {
${labelStyle}
}
+5 -4
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
// 分页菜单
export const paginationMenu = css`
@@ -33,13 +34,13 @@ export const paginationMenu = css`
min-height: 32px;
height: 32px;
justify-content: center;
// 避免一些 hover 效果调整内容
/* 避免一些 hover 效果调整内容 */
padding: 5px 10px !important;
&.active {
background: ${themeVars.github.bgColor.accent.emphasis};
color: ${themeVars.color.white};
}
// 设置透明边框线避免 hover 时元素大小变化
/* 设置透明边框线避免 hover 时元素大小变化 */
&:not(.active) {
border: 1px solid #ffffff00;
&:hover {
@@ -54,7 +55,7 @@ export const paginationMenu = css`
color: ${themeVars.color.primary.self};
}
}
// 对齐文字
/* 对齐文字 */
svg {
margin-top: 2px;
}
+12 -7
View File
@@ -17,21 +17,26 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const secondaryMenu = css`
// 二级菜单, 比如 Issue/PR/Actions 的筛选菜单
/* 二级菜单, 比如 Issue/PR/Actions 的筛选菜单 */
.ui.secondary.menu {
.item {
padding: 0px 12px;
height: 32px;
font-weight: 500;
&.active,
&:first-child {
border-radius: ${otherThemeVars.border.radius};
}
}
a.item:hover {
background: ${themeVars.github.control.transparent.bgColor.hover};
}
}
// 二级导航栏, 比如仓库的导航栏, 仓库列表的导航栏, 探索的类型导航栏
/* 二级导航栏, 比如仓库的导航栏, 仓库列表的导航栏, 探索的类型导航栏 */
.ui.secondary.pointing.menu {
.overflow-menu-items {
gap: 4px;
@@ -43,7 +48,7 @@ export const secondaryMenu = css`
}
}
.item {
font-weight: 400; // 二级导航栏不需要加粗
font-weight: 400; /* 二级导航栏不需要加粗 */
}
.active.item,
.dropdown.item,
@@ -56,9 +61,9 @@ export const secondaryMenu = css`
}
}
.active.item {
// 取消激活时的下划线, 需要为透明, 保持间距
/* 取消激活时的下划线, 需要为透明, 保持间距 */
border-color: #ffffff00;
// 模仿 github 的下划线
/* 模仿 github 的下划线 */
span:after {
content: "";
background: ${themeVars.github.underlineNav.borderColor.active};
@@ -73,7 +78,7 @@ export const secondaryMenu = css`
}
}
}
// 修复仓库页面下的二级导航栏的下划线因浏览器 BUG 导致显示的异常问题(导致下划线和分割线重叠变粗)
/* 修复仓库页面下的二级导航栏的下划线因浏览器 BUG 导致显示的异常问题(导致下划线和分割线重叠变粗) */
.page-content.repository .ui.secondary.pointing.menu {
border-bottom: none !important;
}
+20 -19
View File
@@ -17,17 +17,18 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { activeItemAfterStyle } from ".";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { activeItemAfterStyle } from "styles/common";
export const verticalMenu = css`
// 垂直菜单, 用于左侧边栏
// 设置页面中的菜单, Actions 工作流菜单, WorkflowRuns Job 菜单
/* 垂直菜单, 用于左侧边栏 */
/* 设置页面中的菜单, Actions 工作流菜单, WorkflowRuns Job 菜单 */
.ui.vertical.menu {
// 去除边框, 和背景色同色
/* 去除边框, 和背景色同色 */
background: ${themeVars.color.body};
border: 0;
// 设置页面的菜单头部
/* 设置页面的菜单头部 */
.header.item {
color: ${themeVars.color.text.light.num1} !important;
font-size: 1.5rem;
@@ -35,11 +36,11 @@ export const verticalMenu = css`
background: unset;
margin-bottom: 0.5rem;
}
// 菜单项被悬停时的背景色, 限制a标签, 避免为子菜单多余渲染
/* 菜单项被悬停时的背景色, 限制a标签, 避免为子菜单多余渲染 */
a.item:hover {
background: ${themeVars.github.control.transparent.bgColor.hover};
}
// 菜单项
/* 菜单项 */
.item,
.item > summary {
font-size: 1.1rem;
@@ -47,7 +48,7 @@ export const verticalMenu = css`
border-radius: ${otherThemeVars.border.radius};
padding: 6px 8px;
}
// Actions 菜单的圆角覆盖
/* Actions 菜单的圆角覆盖 */
> .item,
> .active.item {
&:first-child,
@@ -55,37 +56,37 @@ export const verticalMenu = css`
border-radius: ${otherThemeVars.border.radius};
}
}
// 去除菜单项的边框线
/* 去除菜单项的边框线 */
.item:before {
background: unset;
}
// 激活的菜单项
/* 激活的菜单项 */
.active.item,
.active.item > summary {
font-weight: 600;
border-radius: ${otherThemeVars.border.radius};
}
// 添加伪元素, 用于指示当前激活的菜单项
/* 添加伪元素, 用于指示当前激活的菜单项 */
.active.item:after {
content: "";
${activeItemAfterStyle};
}
// 部分菜单项的子菜单
/* 部分菜单项的子菜单 */
details.item {
// 子菜单的标题
/* 子菜单的标题 */
summary:hover {
background: ${themeVars.github.control.transparent.bgColor.hover};
}
// 子菜单的选项
/* 子菜单的选项 */
.menu .item {
color: ${themeVars.color.text.self};
}
// 子菜单的选项被激活
/* 子菜单的选项被激活 */
&:has(.active.item) {
> summary {
font-weight: 600;
background: ${themeVars.color.active};
// 收回状态,悬停色
/* 收回状态,悬停色 */
&:hover {
background: ${themeVars.github.control.transparent.bgColor.hover};
}
@@ -94,7 +95,7 @@ export const verticalMenu = css`
content: "";
${activeItemAfterStyle};
}
// 子菜单的选项
/* 子菜单的选项 */
.active.item {
background: ${themeVars.color.active};
font-weight: 400;
@@ -102,7 +103,7 @@ export const verticalMenu = css`
background: ${themeVars.github.control.transparent.bgColor.hover};
}
}
// 子菜单展开时
/* 子菜单展开时 */
&[open] {
> summary {
background: unset;
+3 -2
View File
@@ -17,8 +17,9 @@
* limitations under the License.
*/
import { animationDown } from "src/core/styles";
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
import { animationDown } from "styles/common";
export const modal = css`
.ui.modal {
+11 -10
View File
@@ -17,11 +17,12 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const text = css`
// 默认颜色是 --color-text-light, 主题下此颜色是亮白色, 修改为灰色
// release 页面下一些描述信息的文本颜色
/* 默认颜色是 --color-text-light, 主题下此颜色是亮白色, 修改为灰色 */
/* release 页面下一些描述信息的文本颜色 */
.tw-text-text-light {
color: ${themeVars.color.text.light.num1} !important;
}
@@ -35,26 +36,26 @@ export const listHeader = css`
`;
export const svg = css`
// 已标星的图标
/* 已标星的图标 */
.octicon-star-fill {
color: ${themeVars.github.button.star.iconColor} !important;
}
// VSCode 图标
/* VSCode 图标 */
.gitea-vscode {
color: #007acc !important;
}
// VSCodium 图标
/* VSCodium 图标 */
.gitea-vscodium {
color: #429cf0 !important;
}
// 重新打开工单按钮设置为绿色
/* 重新打开工单按钮设置为绿色 */
.tw-text-green {
.octicon-issue-reopened,
&.octicon-issue-reopened {
color: ${themeVars.github.fgColor.success} !important;
}
}
// 关闭工单按钮设置为紫色
/* 关闭工单按钮设置为紫色 */
.tw-text-red {
.octicon-issue-closed,
&.octicon-issue-closed {
@@ -91,11 +92,11 @@ export const toggle = css`
bottom: 1.5px;
}
}
// 滑块在左
/* 滑块在左 */
input ~ label:after {
left: 1.5px;
}
// 滑块在右
/* 滑块在右 */
input:checked ~ label:after {
left: 19.5px;
}
+8 -8
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, otherThemeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars } from "src";
// 全部圆角替换
export const radius = css`
@@ -45,7 +46,7 @@ export const radius = css`
.ui.input {
textarea,
// 排除复选框和单选框
/* 排除复选框和单选框 */
input:not([type=checkbox],[type=radio]) {
border-radius: ${otherThemeVars.border.radius};
}
@@ -97,7 +98,7 @@ export const radiusImportant = css`
.ui.secondary.vertical.menu > .item {
border-radius: ${otherThemeVars.border.radius} !important;
}
// 目前为仓库列表/探索的二级菜单, 改版需要替换为全圆角
/* 目前为仓库列表/探索的二级菜单, 改版需要替换为全圆角 */
.ui.secondary.tabular.menu .item {
border-radius: ${otherThemeVars.border.radius} !important;
&.active,
@@ -272,8 +273,7 @@ export const radiusBottomRight = css`
// only-child 顺序最后生效
export const onlyChild = css`
.ui.vertical.menu > .active.item:only-child,
.ui.segments:not(.horizontal) > .segment:only-child {
:is(.ui.vertical.menu > .active.item:only-child, .ui.segments:not(.horizontal) > .segment:only-child) {
border-radius: ${otherThemeVars.border.radius};
}
@@ -293,12 +293,12 @@ export const onlyChild = css`
// 修复一些情况下圆角边框线被覆盖的问题
export const fixRadius = css`
// 评论列表标题
/* 评论列表标题 */
.repository.view.issue .comment-list .comment > .content > div:first-child {
border-top-left-radius: ${otherThemeVars.border.radius};
border-top-right-radius: ${otherThemeVars.border.radius};
}
// 评论列表内容
/* 评论列表内容 */
.repository.view.issue .comment-list .comment > .content > div:last-child {
border-bottom-left-radius: ${otherThemeVars.border.radius};
border-bottom-right-radius: ${otherThemeVars.border.radius};
@@ -307,7 +307,7 @@ export const fixRadius = css`
// 修复一些根本无法理解的生效顺序
export const fixWhyRadius = css`
// Issue 菜单第一个按钮
/* Issue 菜单第一个按钮 */
.ui.secondary.menu .item {
border-radius: ${otherThemeVars.border.radius};
}
+2 -1
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { themeVars } from "src";
export const table = css`
.ui.table > tr > td,
+7 -6
View File
@@ -17,8 +17,9 @@
* limitations under the License.
*/
import { animation, animationDown } from "src/core/styles";
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
import { animation, animationDown } from "styles/common";
// 一些界面内的提示框, 比如克隆按钮, PR信息, Runner信息 等
export const tippyBox = css`
@@ -27,9 +28,9 @@ export const tippyBox = css`
border-radius: ${otherThemeVars.border.radius};
overflow: hidden;
${animationDown};
// 克隆菜单和PR提示框为 default
/* 克隆菜单和PR提示框为 default */
&[data-theme="default"],
// 带标题的提示框 (Runner信息)
/* 带标题的提示框 (Runner信息) */
&[data-theme="box-with-header"] {
border: unset;
box-shadow: ${themeVars.github.shadow.floating.small};
@@ -46,7 +47,7 @@ export const tippyBox = css`
}
}
}
// 差异对比中文件路径行右侧的三个点菜单
/* 差异对比中文件路径行右侧的三个点菜单 */
&[data-theme="menu"] {
.tippy-content {
padding: 8px;
@@ -60,7 +61,7 @@ export const tippyBox = css`
}
}
}
// 专门用于提示信息的提示框, 比如提交的具体时间, 任务状态等
/* 专门用于提示信息的提示框, 比如提交的具体时间, 任务状态等 */
&[data-theme="tooltip"] {
${animation};
.tippy-content {
+17 -9
View File
@@ -17,23 +17,23 @@
* limitations under the License.
*/
import { css } from "src/types/vars";
import { css } from "@linaria/core";
// 简单的渐变过渡
export const transition = css`
// 差异对比的代码折叠按钮
/* 差异对比的代码折叠按钮 */
.code-expander-button,
// 仓库 README 头部的按钮
/* 仓库 README 头部的按钮 */
.file-header-left,
.file-header-right,
// 仪表板仓库列表
/* 仪表板仓库列表 */
.ui.attached.segment.table ul li,
// Issue 列表
/* Issue 列表 */
.issue-list-toolbar .item,
.flex-list#issue-list > .flex-item,
// 分页菜单
/* 分页菜单 */
.ui.borderless.pagination.menu .item,
// 迁移的元素
/* 迁移的元素 */
#navbar .item,
.header-wrapper .ui.tabular.menu .item,
.job-step-summary,
@@ -57,8 +57,8 @@ export const transition = css`
.ui.secondary.menu .item {
transition: 80ms cubic-bezier(0.33, 1, 0.68, 1);
}
// Gitea 表单元素原始过渡覆盖
// 排除复选框和单选框
/* Gitea 表单元素原始过渡覆盖 */
/* 排除复选框和单选框 */
input:not([type="checkbox"], [type="radio"]),
textarea,
tr,
@@ -78,4 +78,12 @@ export const transition = css`
.ui.form input[type="url"] {
transition: 80ms cubic-bezier(0.33, 1, 0.68, 1);
}
.ui.button {
transition:
color 80ms cubic-bezier(0.65, 0, 0.35, 1),
fill 80ms cubic-bezier(0.65, 0, 0.35, 1),
background-color 80ms cubic-bezier(0.65, 0, 0.35, 1),
border-color 80ms cubic-bezier(0.65, 0, 0.35, 1);
transition-duration: 80ms;
}
`;
+3 -2
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const commitSignBadge = css`
a.ui.label.commit-id-short.github-theme-commit-sha {
@@ -42,7 +43,7 @@ export const commitSignBadge = css`
font-weight: 500;
padding: 0px 8px;
height: 26px;
min-width: 85px; // 非等宽字体导致不对齐, 目前看到最大长度为 83px
min-width: 85px; /* 非等宽字体导致不对齐, 目前看到最大长度为 83px */
display: flex;
align-items: center;
justify-content: center;
+2 -1
View File
@@ -17,7 +17,8 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
const primary = "primary" as const;
const secondary = "secondary" as const;
+4 -3
View File
@@ -17,11 +17,12 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const repoButtonRow = css`
.github-theme-templates {
// 仓库按钮行
/* 仓库按钮行 */
&.repo-button-row {
margin: 0 0 16px 0;
.repo-button-row-left .repository-summary {
@@ -47,7 +48,7 @@ export const repoButtonRow = css`
}
}
.repo-button-row-right {
// 添加文件按钮菜单
/* 添加文件按钮菜单 */
.repo-add-file > .menu {
min-width: 152px;
}
+5 -4
View File
@@ -17,18 +17,19 @@
* limitations under the License.
*/
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { css } from "@linaria/core";
import { otherThemeVars, themeVars } from "src";
export const repoFileLastCommit = css`
// 仓库页和文件列表文件夹页的最后一次提交
/* 仓库页和文件列表文件夹页的最后一次提交 */
.repository.file.list #repo-files-table .github-theme-templates.repo-file-line.repo-file-last-commit {
padding-right: 10px;
// 提交时间
/* 提交时间 */
.github-latest-time {
color: ${themeVars.color.text.light.num1};
font-size: 12px;
}
// 提交历史按钮
/* 提交历史按钮 */
.github-latest-commit {
display: inline-flex;
align-items: center;
Loaded 100 of 113 files, more files were not shown because too many files have changed in this diff. Show more