Compare commits

..

62 Commits

Author SHA1 Message Date
lutinglt
c130e6c778 1.25.5 release 2026-03-13 21:03:41 +08:00
lutinglt
c6134161bf Fix no auto-focus of search filter on issue/PR properties #27 2026-02-26 11:51:55 +08:00
lutinglt
d65a5e8f67 navbar style 2026-02-02 15:53:43 +08:00
lutinglt
86d67a4559 version change 2026-01-23 19:22:34 +08:00
lutinglt
5b9b7372a6 fix ci 2026-01-23 19:05:54 +08:00
lutinglt
59b9c66c4e 1.25.4 & fix package details width on phone 2026-01-23 19:02:50 +08:00
lutinglt
ec0f8660e9 update readme 2025-12-22 20:34:26 +08:00
lutinglt
673b7a13de version change & update readme 2025-12-22 20:29:44 +08:00
lutinglt
de0cac06b2 1.25.3 release 2025-12-22 20:09:01 +08:00
lutinglt
bd7899114b Optimize the width of the left side of the workflow details page in different zoom levels 2025-12-10 10:21:14 +08:00
lutinglt
9c67ea1697 fix ci 2025-12-05 09:35:55 +08:00
lutinglt
4a60775c32 vite 8.0 2025-12-05 09:29:26 +08:00
lutinglt
d27376a800 typescript 7.0 (tsgo) 2025-12-04 15:38:22 +08:00
lutinglt
6494e4468b optimize readme header 2025-12-04 11:25:43 +08:00
lutinglt
1729cfe2df fix ci 2025-12-03 11:39:20 +08:00
lutinglt
7a4851eb21 optimize action view 2025-12-03 10:56:46 +08:00
lutinglt
a0b51b863d tmpl Handlebars 2025-12-02 22:18:04 +08:00
lutinglt
13cd887d97 add translate 2025-12-02 17:33:57 +08:00
lutinglt
824eb26f1d build 2025-12-02 14:41:44 +08:00
lutinglt
6a0a92cd94 build test 2025-12-02 14:39:12 +08:00
lutinglt
76e547987b build test 2025-12-02 14:37:32 +08:00
lutinglt
86e488aafb fix issue/pr element styles 2025-12-02 13:43:36 +08:00
lutinglt
b3cc3ab82f sign badge icon -> font 2025-11-30 14:15:34 +08:00
lutinglt
f2787efcd9 optimize sign badge style 2025-11-30 12:09:21 +08:00
lutinglt
2b2f2e8a1e format 2025-11-29 21:14:51 +08:00
lutinglt
2a95d85fb6 fix commit sign badge style 2025-11-29 21:12:38 +08:00
lutinglt
e2838df051 Supplement the PR operation panel status style in PR 2025-11-29 21:04:40 +08:00
lutinglt
c1a0f96b6c optimize commit style 2025-11-29 20:04:31 +08:00
lutinglt
3084a5f54e Synchronized repository commit page layout and styles 2025-11-29 18:09:27 +08:00
lutinglt
ca7207db06 update readme 2025-11-28 19:30:41 +08:00
lutinglt
7d5c600f18 rc version 2025-11-28 16:17:16 +08:00
lutinglt
24f541180f Optimize menu item & code block styles 2025-11-28 16:11:37 +08:00
lutinglt
15d741ff66 optimize latest commit style 2025-11-28 11:51:42 +08:00
lutinglt
91ef8da69c remove pr button 2025-11-27 18:23:46 +08:00
lutinglt
47519afe4a Synchronized repository template 2025-11-27 17:50:57 +08:00
lutinglt
2da9dda3af Fixed extra lines under heatmap 2025-11-23 12:22:09 +08:00
lutinglt
8216986aef version change 2025-11-23 11:11:49 +08:00
lutinglt
f91d295b42 1.25.2 2025-11-23 11:07:46 +08:00
lutinglt
6e3f207c6c Fix the spacing of Issue WIP prompts 2025-11-22 17:46:45 +08:00
lutinglt
5c36998d5e release templates 2025-11-21 14:31:31 +08:00
lutinglt
a83fe43cbb Navigation bar Issue & PR moved to the right side. 2025-11-21 14:28:40 +08:00
lutinglt
678beb2c0d Optimize pr branch label 2025-11-13 20:44:55 +08:00
lutinglt
fd12236144 Optimize top navbar style on mobile 2025-11-13 20:32:45 +08:00
lutinglt
f33a0ae81c Optimize action list line height 2025-11-13 18:40:52 +08:00
鲁汀
a1d531ba36 Remove Downloads History from README
Removed Downloads History section and associated images.
2025-11-12 00:10:40 +08:00
lutinglt
32d0274b56 star history 2025-11-09 23:14:30 +08:00
lutinglt
74c98fbd5d update 2025-11-09 23:07:23 +08:00
lutinglt
d6567618d9 update readme 2025-11-09 23:04:29 +08:00
lutinglt
0cc4f61984 update readme 2025-11-09 22:59:42 +08:00
lutinglt
fd20862833 add --color-logo 2025-11-09 22:15:45 +08:00
lutinglt
ea49cf94dd Fix packages details page style 2025-11-09 10:04:35 +08:00
lutinglt
4fd01c50b0 Optimize organization detail page style 2025-11-09 09:50:25 +08:00
lutinglt
f500f2aae3 remove org label style 2025-11-08 23:56:21 +08:00
lutinglt
b220a17829 fix label 2025-11-08 23:51:20 +08:00
lutinglt
0a0cd77b3f Optimize repository header name style 2025-11-08 20:38:26 +08:00
lutinglt
aa36f52d83 Optimize repository header style 2025-11-08 20:37:23 +08:00
lutinglt
a841636737 Optimize global line height 2025-11-08 20:09:13 +08:00
lutinglt
fb1ebd6f18 fuck issue 2025-11-07 09:00:54 +08:00
lutinglt
4ae9a2754f Optimize the workflow log page style 2025-11-06 19:24:51 +08:00
lutinglt
914d5228e3 perf action step container 2025-11-06 18:05:12 +08:00
lutinglt
efec911021 Fix fixed height when scrolling through step titles on workflow detail pages 2025-11-06 17:43:10 +08:00
lutinglt
5e3f2ec2c2 Fix the disabled operation button interval in the code preview interface 2025-11-06 17:36:09 +08:00
67 changed files with 2079 additions and 227 deletions

View File

@@ -14,5 +14,5 @@ trim_trailing_whitespace = true
max_line_length = 120
# documentation, utils
[*.{md,mdx,diff}]
[*.{md,diff}]
trim_trailing_whitespace = false

View File

@@ -5,4 +5,6 @@ SSH_SERVER=localhost
# 上传到服务器的用户名称, 不支持密码, 请确保有 SSH 免密登录权限
SSH_USER=root
# 上传到服务器的主题路径, 请使用绝对路径
GITEA_THEME_PATH=/data/gitea/public/assets/css/
GITEA_THEME_PATH=/data/gitea/public/assets/css/
# Gitea 数据路径, 用于上传到服务器的模板路径, 请使用绝对路径
GITEA_PATH=/data/gitea/

6
.gitattributes vendored
View File

@@ -1,5 +1 @@
.github/* linguist-vendored
.vscode/* linguist-vendored
screenshots/* linguist-vendored
scripts/* linguist-vendored
eslint.config.js linguist-vendored
*.tmpl linguist-language=Handlebars

View File

@@ -6,7 +6,9 @@
### 🌈 Style
##### 更符合 GitHub 风格
#### 更符合 GitHub 风格
##### 模板文件
### 🐞 Fix
@@ -14,7 +16,9 @@
#### CSS Variable
##### More GitHub-like style
#### More GitHub-like style
##### Template File
```text
在 English 下方补充上面 Feature 以下部分的内容的中译英​

View File

@@ -5,6 +5,7 @@ body:
- type: markdown
attributes:
value: |
!!! Please read the readme and ensure that the theme is used correctly before submitting !!!
1. Please use the latest theme and refresh the page with Ctrl+F5 to see if the Bug has disappeared.
2. Please check the CHANGELOG.md file in the project root directory for descriptions of fixes related to this Bug.
3. If there are related descriptions, you can check if the Bug has been fixed by compiling the development version yourself in the README.md.

57
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: build
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
src:
- ".github/workflows/*.yml"
- "scripts/*"
- "src/**/*.ts"
- "styles/**/*.ts"
- "themes/*.css.ts"
- "vite.config.ts"
- "package.json"
- name: Build theme
id: build
if: steps.changes.outputs.src == 'true'
run: |
npm install
npm run build
- name: Upload css assets
if: steps.build.outcome == 'success'
uses: actions/upload-artifact@v4
with:
name: themes
path: dist/*.css
- name: Upload templates assets
if: steps.build.outcome == 'success'
uses: actions/upload-artifact@v4
with:
name: templates
path: templates
- name: Build locales
id: locales
if: steps.build.outcome =='success'
run: npm run tr
- name: Upload locales assets
if: steps.locales.outcome =='success'
uses: actions/upload-artifact@v4
with:
name: locales
path: dist/options/locale

View File

@@ -13,8 +13,8 @@ jobs:
- uses: actions/checkout@v4
- name: Build theme
run: |
npm install
npm run build
npm run install:vite8
npm run release
- name: Create release
run: |
tar -zcf dist/theme-github-base.tar.gz --remove-files \
@@ -29,7 +29,9 @@ jobs:
tar -zcf dist/theme-github-extra-pink.tar.gz --remove-files \
dist/theme-github-pink-auto.css dist/theme-github-pink-light.css dist/theme-github-pink-dark.css dist/theme-github-pink-soft-dark.css
tar -zcf dist/theme-github-templates.tar.gz templates
tar -zcf dist/theme-github-translations.tar.gz --remove-files dist/options
TAG="v$(npm run -s version)"
gh release create "$TAG" dist/* --notes-file CHANGELOG.md --draft -t $TAG
gh release create "$TAG" dist/*.tar.gz --notes-file CHANGELOG.md --draft -t $TAG
env:
GH_TOKEN: ${{ github.token }}

View File

@@ -4,6 +4,7 @@
"dbaeumer.vscode-eslint",
"usernamehw.errorlens",
"mikestead.dotenv",
"styled-components.vscode-styled-components"
"styled-components.vscode-styled-components",
"typescriptteam.native-preview"
]
}

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"typescript.experimental.useTsgo": false
}

View File

@@ -1,7 +1,9 @@
### 🌈 Style
##### More aligned with GitHub style
#### More aligned with GitHub style
- Fine-tune the style of the navigation bar.
### 🐞 Fix
- Fix the problem of missing background color and width when there is a unicode character in the diff
- Fix no auto-focus of search filter on issue/PR properties. #27

View File

@@ -46,15 +46,16 @@ accepted.
## Installation
1. Download the latest CSS theme file from the release page and place it in the `gitea/public/assets/css` directory
2. Modify `gitea/conf/app.ini` and append the CSS filename without the `theme-` prefix to the end of `THEMES` under the
`[ui]` section
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
the `[ui]` section
3. Restart Gitea
4. Check the theme in the settings
Example: If the theme filename is `theme-github-dark.css`, add `github-dark` to the end of `THEMES`
Example `gitea/conf/app.ini`:
Example `data/gitea/conf/app.ini`:
```ini
[ui]
@@ -68,6 +69,31 @@ For details, please refer to the Gitea documentation
>
> Automatic color theme requires both light and dark theme files.
### Template File Installation (Optional)
1. Download the latest template files from the release page and place them in the `data/gitea/templates` directory (This
directory may not be available by default and needs to be manually created)
2. Restart Gitea
> [!IMPORTANT]
>
> The template modifies Gitea's layout to make it closer to GitHub's layout. Do not use template files across versions,
> as this may lead to missing functionality and other issues.
>
> Template layout is bound to the Gitea instance and will affect all themes, impacting the experience of other
> non-project themes.
### Translation File Installation (Optional)
> [!TIP]
>
> Translation files are only needed when using this project's template files to provide support for non-English
> languages.
1. Download the latest translation files from the release page and place them in the `data/gitea/options/locale`
directory (This directory may not be available by default and needs to be manually created)
2. Restart Gitea
## Screenshots
### Basic Themes
@@ -169,3 +195,13 @@ npm run build
After compilation, theme files will be generated in the `dist` directory. You can place the theme files into the
`gitea/public/assets/css` directory, then add the theme name to the end of `THEMES` in `gitea/conf/app.ini`
## Star History
<a href="https://www.star-history.com/#lutinglt/gitea-github-theme&type=date&legend=top-left">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=lutinglt/gitea-github-theme&type=date&theme=dark&legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=lutinglt/gitea-github-theme&type=date&legend=top-left" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=lutinglt/gitea-github-theme&type=date&legend=top-left" />
</picture>
</a>

View File

@@ -41,14 +41,14 @@ Gitea 理论上小版本号变更不会修改前端布局, 所以主题的小版
## 安装
1. 在发布页下载最新的 CSS 主题文件放入 `gitea/public/assets/css` 目录下
2. 修改 `gitea/conf/app.ini`,并将 CSS 文件名去掉 `theme-` 的名称附加到 `[ui]` 下的 `THEMES` 末尾
1. 在发布页下载最新的 CSS 主题文件放入 `data/gitea/public/assets/css` 目录下 (默认可能没有此目录需手动创建)
2. 修改 `data/gitea/conf/app.ini`,并将 CSS 文件名去掉 `theme-` 的名称附加到 `[ui]` 下的 `THEMES` 末尾
3. 重启 Gitea
4. 在设置中查看主题
例: 主题文件名为 `theme-github-dark.css`,则添加 `github-dark``THEMES` 末尾
`gitea/conf/app.ini` 例:
`data/gitea/conf/app.ini` 例:
```ini
[ui]
@@ -62,6 +62,30 @@ THEMES = gitea-auto, gitea-light, gitea-dark, github-auto, github-light, github-
>
> 自动颜色主题需要亮色和暗色的主题文件
### 模板文件安装 (可选)
1. 在发布页下载最新的模板文件放入 `data/gitea/templates` 目录下 (默认可能没有此目录需手动创建)
2. 重启 Gitea
> [!IMPORTANT]
>
> 模板修改了 Gitea 的布局, 使其更接近 GitHub 的布局, 请勿跨版本使用模板文件, 可能会导致功能缺失等问题
>
> 模板布局跟 Gitea 实例绑定, 所有主题都会生效, 会影响其他非本项目的主题的体验
### 翻译文件安装 (可选)
> [!TIP]
>
> 仅在使用本项目的模板文件时需要安装翻译文件以提供非英文语言的支持
1. 在发布页下载最新的翻译文件放入 `data/gitea/options/locale` 目录下 (默认可能没有此目录需手动创建)
2. 重启 Gitea
> [!NOTE]
>
> 中文翻译中还额外将 "工单" 替换为 "议题", "合并请求" 替换为 "拉取请求", 以与 GitHub 手机版中文保持一致
## 截图
### 基本主题

View File

@@ -1,15 +1,14 @@
import js from "@eslint/js";
import { defineConfig } from "eslint/config";
import globals from "globals";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
}
);
export default defineConfig({
ignores: ["dist"],
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
});

1
gitea/README.md Normal file
View File

@@ -0,0 +1 @@
模板的原始文件

View File

@@ -0,0 +1,180 @@
<nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}">
<div class="navbar-left">
<!-- the logo -->
<a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}">
<img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true">
</a>
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
<div class="ui secondary menu navbar-mobile-right only-mobile">
{{template "base/head_navbar_icons" dict "PageGlobalData" .PageGlobalData}}
<button class="item ui icon mini button tw-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "home.nav_menu"}}">{{svg "octicon-three-bars"}}</button>
</div>
<!-- navbar links non-mobile -->
{{if and .IsSigned .MustChangePassword}}
{{/* No links */}}
{{else if .IsSigned}}
{{if not ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled}}
<a class="item{{if .PageIsIssues}} active{{end}}" href="{{AppSubUrl}}/issues">{{ctx.Locale.Tr "issues"}}</a>
{{end}}
{{if not ctx.Consts.RepoUnitTypePullRequests.UnitGlobalDisabled}}
<a class="item{{if .PageIsPulls}} active{{end}}" href="{{AppSubUrl}}/pulls">{{ctx.Locale.Tr "pull_requests"}}</a>
{{end}}
{{if not (and ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled ctx.Consts.RepoUnitTypePullRequests.UnitGlobalDisabled)}}
{{if .ShowMilestonesDashboardPage}}
<a class="item{{if .PageIsMilestonesDashboard}} active{{end}}" href="{{AppSubUrl}}/milestones">{{ctx.Locale.Tr "milestones"}}</a>
{{end}}
{{end}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
{{else if .IsLandingPageOrganizations}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{ctx.Locale.Tr "explore"}}</a>
{{else}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
{{end}}
{{template "custom/extra_links" .}}
{{if not .IsSigned}}
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">{{ctx.Locale.Tr "help"}}</a>
{{end}}
</div>
<!-- the full dropdown menus -->
<div class="navbar-right">
{{if and .IsSigned .MustChangePassword}}
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
<span class="text">
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
<span class="only-mobile">{{.SignedUser.Name}}</span>
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
</span>
<div class="menu user-menu">
<div class="header">
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
</div>
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
{{else if .IsSigned}}
{{template "base/head_navbar_icons" dict "ItemExtraClass" "not-mobile" "PageGlobalData" .PageGlobalData}}
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "create_new"}}">
<span class="text">
{{svg "octicon-plus"}}
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
<span class="only-mobile">{{ctx.Locale.Tr "create_new"}}</span>
</span>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/repo/create">
{{svg "octicon-plus"}} {{ctx.Locale.Tr "new_repo"}}
</a>
{{if not .DisableMigrations}}
<a class="item" href="{{AppSubUrl}}/repo/migrate">
{{svg "octicon-repo-push"}} {{ctx.Locale.Tr "new_migrate"}}
</a>
{{end}}
{{if .SignedUser.CanCreateOrganization}}
<a class="item" href="{{AppSubUrl}}/org/create">
{{svg "octicon-organization"}} {{ctx.Locale.Tr "new_org"}}
</a>
{{end}}
</div><!-- end content create new menu -->
</div><!-- end dropdown menu create new -->
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
<span class="text">
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
<span class="only-mobile">{{.SignedUser.Name}}</span>
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
</span>
<div class="menu user-menu">
<div class="header">
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
</div>
<div class="divider"></div>
<a class="item" href="{{.SignedUser.HomeLink}}">
{{svg "octicon-person"}}
{{ctx.Locale.Tr "your_profile"}}
</a>
{{if not .DisableStars}}
<a class="item" href="{{.SignedUser.HomeLink}}?tab=stars">
{{svg "octicon-star"}}
{{ctx.Locale.Tr "your_starred"}}
</a>
{{end}}
<a class="item" href="{{AppSubUrl}}/notifications/subscriptions">
{{svg "octicon-bell"}}
{{ctx.Locale.Tr "notification.subscriptions"}}
</a>
<a class="{{if .PageIsUserSettings}}active {{end}}item" href="{{AppSubUrl}}/user/settings">
{{svg "octicon-tools"}}
{{ctx.Locale.Tr "your_settings"}}
</a>
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">
{{svg "octicon-question"}}
{{ctx.Locale.Tr "help"}}
</a>
{{if .IsAdmin}}
<div class="divider"></div>
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/-/admin">
{{svg "octicon-server"}}
{{ctx.Locale.Tr "admin_panel"}}
</a>
{{end}}
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
{{else}}
{{if .ShowRegistrationButton}}
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up">
{{svg "octicon-person"}}
<span class="tw-ml-1">{{ctx.Locale.Tr "register"}}</span>
</a>
{{end}}
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}">
{{svg "octicon-sign-in"}}
<span class="tw-ml-1">{{ctx.Locale.Tr "sign_in"}}</span>
</a>
{{end}}
</div><!-- end full right menu -->
{{$activeStopwatch := and .PageGlobalData (call .PageGlobalData.GetActiveStopwatch)}}
{{if $activeStopwatch}}
<div class="active-stopwatch-popup tippy-target">
<div class="tw-flex tw-items-center tw-gap-2 tw-p-3">
<a class="stopwatch-link tw-flex tw-items-center tw-gap-2 muted" href="{{$activeStopwatch.IssueLink}}">
{{svg "octicon-issue-opened" 16}}
<span class="stopwatch-issue">{{$activeStopwatch.RepoSlug}}#{{$activeStopwatch.IssueIndex}}</span>
</a>
<div class="tw-flex tw-gap-1">
<form class="stopwatch-commit form-fetch-action" method="post" action="{{$activeStopwatch.IssueLink}}/times/stopwatch/stop">
{{.CsrfTokenHtml}}
<button
type="submit"
class="ui button mini compact basic icon tw-mr-0"
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.stop_tracking"}}"
>{{svg "octicon-square-fill"}}</button>
</form>
<form class="stopwatch-cancel form-fetch-action" method="post" action="{{$activeStopwatch.IssueLink}}/times/stopwatch/cancel">
{{.CsrfTokenHtml}}
<button
type="submit"
class="ui button mini compact basic icon tw-mr-0"
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.cancel_tracking"}}"
>{{svg "octicon-trash"}}</button>
</form>
</div>
</div>
</div>
{{end}}
</nav>

View File

@@ -0,0 +1,25 @@
{{- $itemExtraClass := .ItemExtraClass -}}
{{- $data := .PageGlobalData -}}
{{if and $data $data.IsSigned}}{{/* data may not exist, for example: rendering 503 page before the PageGlobalData middleware */}}
{{- $activeStopwatch := call $data.GetActiveStopwatch -}}
{{- $notificationUnreadCount := call $data.GetNotificationUnreadCount -}}
{{if $activeStopwatch}}
<a class="item active-stopwatch {{$itemExtraClass}}" href="{{$activeStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{$activeStopwatch.Seconds}}">
<div class="tw-relative">
{{svg "octicon-stopwatch"}}
<span class="header-stopwatch-dot"></span>
</div>
</a>
{{end}}
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}">
<div class="tw-relative">
{{svg "octicon-bell"}}
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
</div>
</a>
{{if $data.IsSiteAdmin}}
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/-/admin" data-tooltip-content="{{ctx.Locale.Tr "admin_panel"}}">
{{svg "octicon-server"}}
</a>
{{end}}
{{end}}

View File

@@ -0,0 +1,81 @@
{{/* Template attributes:
* Commit
* CommitBaseLink
* CommitSignVerification
If you'd like to modify this template, you could test it on the devtest page.
ATTENTION: this template could be re-rendered many times (on the graph and commit list page),
so this template should be kept as small as possible, DO NOT put large components like modal/dialog into it.
*/}}
{{- $commit := $.Commit -}}
{{- $commitBaseLink := $.CommitBaseLink -}}
{{- $verification := $.CommitSignVerification -}}{{- /* asymkey.CommitVerification */ -}}
{{- $extraClass := "" -}}
{{- $verified := false -}}
{{- $signingUser := NIL -}}
{{- $signingEmail := "" -}}
{{- $msgReasonPrefix := "" -}}
{{- $msgReason := "" -}}
{{- $msgSigningKey := "" -}}
{{- if $verification -}}
{{- $signingUser = $verification.SigningUser -}}
{{- $signingEmail = $verification.SigningEmail -}}
{{- $extraClass = print $extraClass " commit-is-signed" -}}
{{- if $verification.Verified -}}
{{- /* reason is "{name} / {key-id}" */ -}}
{{- $msgReason = $verification.Reason -}}
{{- $verified = true -}}
{{- if eq $verification.TrustStatus "trusted" -}}
{{- $extraClass = print $extraClass " sign-trusted" -}}
{{- else if eq $verification.TrustStatus "untrusted" -}}
{{- $extraClass = print $extraClass " sign-untrusted" -}}
{{- $msgReasonPrefix = ctx.Locale.Tr "repo.commits.signed_by_untrusted_user" -}}
{{- else -}}
{{- $extraClass = print $extraClass " sign-unmatched" -}}
{{- $msgReasonPrefix = ctx.Locale.Tr "repo.commits.signed_by_untrusted_user_unmatched" -}}
{{- end -}}
{{- else -}}
{{- if $verification.Warning -}}
{{- $extraClass = print $extraClass " sign-warning" -}}
{{- else -}}
{{- $extraClass = "" -}}{{/* the commit is not signed */}}
{{- end -}}
{{- $msgReason = ctx.Locale.Tr $verification.Reason -}}{{- /* dirty part: it is the translation key ..... */ -}}
{{- end -}}
{{- if $msgReasonPrefix -}}
{{- $msgReason = print $msgReasonPrefix ": " $msgReason -}}
{{- end -}}
{{- if $verification.SigningSSHKey -}}
{{- $msgSigningKey = print (ctx.Locale.Tr "repo.commits.ssh_key_fingerprint") ": " $verification.SigningSSHKey.Fingerprint -}}
{{- else if $verification.SigningKey -}}{{- /* asymkey.GPGKey */ -}}
{{- $msgSigningKey = print (ctx.Locale.Tr "repo.commits.gpg_key_id") ": " $verification.SigningKey.PaddedKeyID -}}
{{- end -}}
{{- end -}}
{{- if $commit -}}
<a {{if $commitBaseLink}}href="{{$commitBaseLink}}/{{$commit.ID}}"{{end}} class="ui label commit-id-short {{$extraClass}}" rel="nofollow">
{{- ShortSha $commit.ID.String -}}
{{- end -}}
{{- if or (not $commit) $extraClass}}{{/* only show the lock icon if there is no commit info (icon only) or the commit is really signed */}}
<span class="ui label commit-sign-badge {{$extraClass}}">
{{- if $verified -}}
{{- if and $signingUser $signingUser.ID -}}
<span data-tooltip-content="{{$msgReason}}">{{svg "gitea-lock"}}</span>
<span data-tooltip-content="{{$msgSigningKey}}">{{ctx.AvatarUtils.Avatar $signingUser 16}}</span>
{{- else -}}
<span data-tooltip-content="{{$msgReason}}">{{svg "gitea-lock-cog"}}</span>
<span data-tooltip-content="{{$msgSigningKey}}">{{ctx.AvatarUtils.AvatarByEmail $signingEmail "" 16}}</span>
{{- end -}}
{{- else -}}
<span data-tooltip-content="{{$msgReason}}">{{svg "gitea-unlock"}}</span>
{{- end -}}
</span>
{{- end -}}
{{- if $commit -}}
</a>
{{- end -}}
{{- /* This template should be kept as small as possible, DO NOT put large components like modal/dialog into it. */ -}}

View File

@@ -0,0 +1,89 @@
<div class="ui attached table segment commit-table">
<table class="ui very basic striped table unstackable" id="commits-table">
<thead>
<tr>
<th class="three wide">{{ctx.Locale.Tr "repo.commits.author"}}</th>
<th class="two wide sha">{{StringUtils.ToUpper $.Repository.ObjectFormatName}}</th>
<th class="eight wide message">{{ctx.Locale.Tr "repo.commits.message"}}</th>
<th class="two wide tw-text-right">{{ctx.Locale.Tr "repo.commits.date"}}</th>
<th class="one wide"></th>
</tr>
</thead>
<tbody class="commit-list">
{{$commitRepoLink := $.RepoLink}}{{if $.CommitRepoLink}}{{$commitRepoLink = $.CommitRepoLink}}{{end}}
{{range .Commits}}
<tr>
<td class="author">
<div class="tw-flex">
{{$userName := .Author.Name}}
{{if .User}}
{{if and .User.FullName DefaultShowFullName}}
{{$userName = .User.FullName}}
{{end}}
{{ctx.AvatarUtils.Avatar .User 28 "tw-mr-2"}}<a class="muted author-wrapper" href="{{.User.HomeLink}}">{{$userName}}</a>
{{else}}
{{ctx.AvatarUtils.AvatarByEmail .Author.Email .Author.Name 28 "tw-mr-2"}}
<span class="author-wrapper">{{$userName}}</span>
{{end}}
</div>
</td>
<td class="sha">
{{$commitBaseLink := ""}}
{{if $.PageIsWiki}}
{{$commitBaseLink = printf "%s/wiki/commit" $commitRepoLink}}
{{else if $.PageIsPullCommits}}
{{$commitBaseLink = printf "%s/pulls/%d/commits" $commitRepoLink $.Issue.Index}}
{{else if $.Reponame}}
{{$commitBaseLink = printf "%s/commit" $commitRepoLink}}
{{end}}
{{template "repo/commit_sign_badge" dict "Commit" . "CommitBaseLink" $commitBaseLink "CommitSignVerification" .Verification}}
</td>
<td class="message">
<span class="message-wrapper">
{{if $.PageIsWiki}}
<span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary | ctx.RenderUtils.RenderEmoji}}</span>
{{else}}
{{$commitLink:= printf "%s/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
<span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink $.Repository}}</span>
{{end}}
</span>
{{if IsMultilineCommitMessage .Message}}
<button class="ui button ellipsis-button" aria-expanded="false" data-global-click="onRepoEllipsisButtonClick">...</button>
{{end}}
{{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses}}
{{if IsMultilineCommitMessage .Message}}
<pre class="commit-body tw-hidden">{{ctx.RenderUtils.RenderCommitBody .Message $.Repository}}</pre>
{{end}}
{{if $.CommitsTagsMap}}
{{range (index $.CommitsTagsMap .ID.String)}}
{{- template "repo/tag/name" dict "AdditionalClasses" "tw-py-0" "RepoLink" $.Repository.Link "TagName" .TagName "IsRelease" (not .IsTag) -}}
{{end}}
{{end}}
</td>
{{if .Committer}}
<td class="tw-text-right">{{DateUtils.TimeSince .Committer.When}}</td>
{{else}}
<td class="tw-text-right">{{DateUtils.TimeSince .Author.When}}</td>
{{end}}
<td class="tw-text-right tw-py-0">
<button class="btn interact-bg tw-p-2 copy-commit-id" data-tooltip-content="{{ctx.Locale.Tr "copy_hash"}}" data-clipboard-text="{{.ID}}">{{svg "octicon-copy"}}</button>
{{/* at the moment, wiki doesn't support these "view" links like "view at history point" */}}
{{if not $.PageIsWiki}}
{{/* view single file diff */}}
{{if $.FileTreePath}}
<a class="btn interact-bg tw-p-2 view-single-diff" data-tooltip-content="{{ctx.Locale.Tr "repo.commits.view_file_diff"}}"
href="{{$commitRepoLink}}/commit/{{.ID.String}}?files={{$.FileTreePath}}"
>{{svg "octicon-file-diff"}}</a>
{{end}}
{{/* view at history point */}}
{{$viewCommitLink := printf "%s/src/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
{{if $.FileTreePath}}{{$viewCommitLink = printf "%s/%s" $viewCommitLink (PathEscapeSegments $.FileTreePath)}}{{end}}
<a class="btn interact-bg tw-p-2 view-commit-path" data-tooltip-content="{{ctx.Locale.Tr "repo.commits.view_path"}}" href="{{$viewCommitLink}}">{{svg "octicon-file-code"}}</a>
{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
</div>

View File

@@ -0,0 +1,112 @@
{{$isTreePathRoot := not .TreeNames}}
<div class="repo-view-content-data tw-hidden" data-document-title="{{ctx.RootData.Title}}" data-document-title-common="{{ctx.RootData.PageTitleCommon}}"></div>
{{template "repo/sub_menu" .}}
<div class="repo-button-row">
<div class="repo-button-row-left">
{{if not $isTreePathRoot}}
<button class="repo-view-file-tree-toggle-show ui compact basic button icon not-mobile {{if .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}"
data-global-click="onRepoViewFileTreeToggle" data-toggle-action="show"
data-tooltip-content="{{ctx.Locale.Tr "repo.diff.show_file_tree"}}">
{{svg "octicon-sidebar-collapse"}}
</button>
{{end}}
{{template "repo/branch_dropdown" dict
"Repository" .Repository
"ShowTabBranches" true
"ShowTabTags" true
"CurrentRefType" .RefFullName.RefType
"CurrentRefShortName" .RefFullName.ShortName
"CurrentTreePath" .TreePath
"RefLinkTemplate" "{RepoLink}/src/{RefType}/{RefShortName}/{TreePath}"
"AllowCreateNewRef" .CanCreateBranch
"ShowViewAllRefsEntry" true
}}
{{if and .CanCompareOrPull .RefFullName.IsBranch (not .Repository.IsArchived)}}
{{$cmpBranch := ""}}
{{if ne .Repository.ID .BaseRepo.ID}}
{{$cmpBranch = printf "%s/%s:" (.Repository.OwnerName|PathEscape) (.Repository.Name|PathEscape)}}
{{end}}
{{$cmpBranch = print $cmpBranch (.BranchName|PathEscapeSegments)}}
{{$compareLink := printf "%s/compare/%s...%s" .BaseRepo.Link (.BaseRepo.DefaultBranch|PathEscapeSegments) $cmpBranch}}
<a id="new-pull-request" role="button" class="ui compact basic button" href="{{QueryBuild $compareLink "expand" 1}}"
data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}">
{{svg "octicon-git-pull-request"}}
</a>
{{end}}
<!-- Show go to file if on home page -->
{{if $isTreePathRoot}}
<a href="{{.Repository.Link}}/find/{{.RefTypeNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
{{end}}
{{if and .RefFullName.IsBranch (not .IsViewFile)}}
<button class="ui dropdown basic compact jump button repo-add-file" {{if not .Repository.CanEnableEditor}}disabled{{end}}>
{{ctx.Locale.Tr "repo.editor.add_file"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<a class="item" href="{{.RepoLink}}/_new/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{ctx.Locale.Tr "repo.editor.new_file"}}
</a>
{{if .RepositoryUploadEnabled}}
<a class="item" href="{{.RepoLink}}/_upload/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{ctx.Locale.Tr "repo.editor.upload_file"}}
</a>
{{end}}
<a class="item" href="{{.RepoLink}}/_diffpatch/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{ctx.Locale.Tr "repo.editor.patch"}}
</a>
</div>
</button>
{{end}}
{{if and $isTreePathRoot .Repository.IsTemplate}}
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
{{ctx.Locale.Tr "repo.use_template"}}
</a>
{{end}}
{{if not $isTreePathRoot}}
{{$treeNameIdxLast := Eval (len .TreeNames) "-" 1}}
<span class="breadcrumb">
<a class="section" href="{{.RepoLink}}/src/{{.RefTypeNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
{{- range $i, $v := .TreeNames -}}
<span class="breadcrumb-divider">/</span>
{{- if eq $i $treeNameIdxLast -}}
<span class="active section" title="{{$v}}">{{$v}}</span>
<button class="btn interact-fg tw-mx-1" data-clipboard-text="{{$.TreePath}}" data-tooltip-content="{{ctx.Locale.Tr "copy_path"}}">{{svg "octicon-copy" 14}}</button>
{{- else -}}
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
{{- end -}}
{{- end -}}
</span>
{{end}}
</div>
<div class="repo-button-row-right">
<!-- Only show clone panel in repository home page -->
{{if $isTreePathRoot}}
{{template "repo/clone_panel" .}}
{{end}}
{{if and (not $isTreePathRoot) (not .IsViewFile) (not .IsBlame)}}{{/* IsViewDirectory (not home), TODO: split the templates, avoid using "if" tricks */}}
<a class="ui button" href="{{.RepoLink}}/commits/{{.RefTypeNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
{{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}}
</a>
{{end}}
</div>
</div>
{{if .IsViewFile}}
{{template "repo/view_file" .}}
{{else if .IsBlame}}
{{template "repo/blame" .}}
{{else}}{{/* IsViewDirectory */}}
{{if $isTreePathRoot}}
{{template "repo/code/upstream_diverging_info" .}}
{{end}}
{{template "repo/view_list" .}}
{{if and .ReadmeExist (or .IsMarkup .IsPlainText)}}
{{template "repo/view_file" .}}
{{end}}
{{end}}

View File

@@ -0,0 +1,61 @@
{{/* use grid layout, still use the old ID because there are many other CSS styles depending on this ID */}}
<div id="repo-files-table" {{if .HasFilesWithoutLatestCommit}}hx-indicator="#repo-files-table .repo-file-cell.message" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}>
<div class="repo-file-line repo-file-last-commit">
{{template "repo/latest_commit" .}}
<div>{{if and .LatestCommit .LatestCommit.Committer}}{{DateUtils.TimeSince .LatestCommit.Committer.When}}{{end}}</div>
</div>
{{$.FileIconPoolHTML}}
{{if .HasParentPath}}
<a class="repo-file-line parent-link silenced" href="{{.BranchLink}}{{if .ParentPath}}{{PathEscapeSegments .ParentPath}}{{end}}">
{{index $.FileIcons ".."}} ..
</a>
{{end}}
{{range $item := .Files}}
<div class="repo-file-item">
{{$entry := $item.Entry}}
{{$commit := $item.Commit}}
{{$submoduleFile := $item.SubmoduleFile}}
<div class="repo-file-cell name muted-links {{if not $commit}}notready{{end}}">
{{index $.FileIcons $entry.Name}}
{{if $entry.IsSubModule}}
{{$submoduleLink := $submoduleFile.SubmoduleWebLinkTree ctx}}
{{if $submoduleLink}}
<a class="entry-name" href="{{$submoduleLink.RepoWebLink}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
@ <a class="text primary" href="{{$submoduleLink.CommitWebLink}}">{{ShortSha $submoduleFile.RefID}}</a>
{{else}}
<span class="entry-name" title="{{$entry.Name}}">{{$entry.Name}}</span>
@ {{ShortSha $submoduleFile.RefID}}
{{end}}
{{else}}
{{if $entry.IsDir}}
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
{{$subJumpablePathFields := StringUtils.Split $subJumpablePathName "/"}}
{{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}}
{{if eq $subJumpablePathFieldLast 0}}
{{$subJumpablePathName}}
{{else}}
{{$subJumpablePathPrefixes := slice $subJumpablePathFields 0 $subJumpablePathFieldLast}}
<span class="text light-2">{{StringUtils.Join $subJumpablePathPrefixes "/"}}</span>/{{index $subJumpablePathFields $subJumpablePathFieldLast}}
{{end}}
</a>
{{else}}
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
{{if $entry.IsLink}}
<a class="entry-symbol-link flex-text-inline" data-tooltip-content title="{{ctx.Locale.Tr "repo.find_file.follow_symlink"}}" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}?follow_symlink=1">{{svg "octicon-link" 12}}</a>
{{end}}
{{end}}
{{end}}
</div>
<div class="repo-file-cell message loading-icon-2px">
{{if $commit}}
{{$commitLink := printf "%s/commit/%s" $.RepoLink (PathEscape $commit.ID.String)}}
{{ctx.RenderUtils.RenderCommitMessageLinkSubject $commit.Message $commitLink $.Repository}}
{{else}}
{{/* will be loaded again by LastCommitLoaderURL */}}
{{end}}
</div>
<div class="repo-file-cell age">{{if $commit}}{{DateUtils.TimeSince $commit.Committer.When}}{{end}}</div>
</div>
{{end}}
</div>

View File

@@ -0,0 +1,4 @@
[github-theme]
verifed=已验证
partially_verifed=部分验证
unverifed=未验证

View File

@@ -1,22 +1,28 @@
{
"name": "gitea-github-theme",
"version": "1.25.2",
"version": "1.25.5",
"type": "module",
"scripts": {
"dev": "vite build --mode dev",
"build": "tsc -b && vite build",
"build": "tsgo -b && vite build",
"lint": "eslint .",
"format": "prettier --write .",
"commit": "npm run lint && npm run format && npm run build",
"version": "node scripts/version.cjs"
"version": "node scripts/version.cjs",
"tr": "node scripts/translate.cjs",
"tmpl": "node scripts/update_template.cjs",
"release": "npm run build && npm run tr",
"install:clean": "npm cache clean --force && rm -rf node_modules package-lock.json && npm install",
"install:vite8": "npm install --force"
},
"devDependencies": {
"@babel/preset-typescript": "^7.27.1",
"@babel/preset-typescript": "^7.28.4",
"@eslint/js": "^9.29.0",
"@linaria/core": "^6.3.0",
"@types/node": "^24.0.3",
"@vanilla-extract/css": "^1.17.4",
"@vanilla-extract/vite-plugin": "^5.0.6",
"@typescript/native-preview": "^7.0.0-dev.20251203.1",
"@vanilla-extract/css": "^1.17.5",
"@vanilla-extract/vite-plugin": "^5.1.3",
"@wyw-in-js/babel-preset": "^0.7.0",
"@wyw-in-js/vite": "^0.7.0",
"dotenv": "^17.0.0",
@@ -27,11 +33,9 @@
"prettier": "3.5.3",
"prettier-plugin-organize-imports": "^4.1.0",
"sass-embedded": "^1.89.2",
"typescript": "^5.8.3",
"typescript-eslint": "^8.34.1",
"typescript-plugin-css-modules": "^5.1.0",
"typescript-styled-plugin": "^0.18.3",
"vite": "^7.1.9"
"vite": "^7.3.1"
},
"prettier": {
"printWidth": 120,

54
scripts/translate.cjs Normal file
View File

@@ -0,0 +1,54 @@
const fs = require("fs");
const path = require("path");
const child_process = require("child_process");
const dotenv = require("dotenv");
dotenv.config({ quiet: true });
const rootDir = path.join(__dirname, "..");
const pkgPath = path.join(rootDir, "package.json");
const pkg = JSON.parse(fs.readFileSync(pkgPath));
const githubSite = "https://raw.githubusercontent.com";
const giteaRepo = "go-gitea/gitea";
const githubBranchPath = "refs/heads/release";
const githubTagPath = "refs/tags";
const localePath = "options/locale";
const [major, minor, patch, tag = ""] = pkg.version.split(".");
console.log("Version:", pkg.version);
let versionPath = "";
if (tag.includes("rc") || patch.includes("latest")) {
versionPath = `${githubBranchPath}/v${major}.${minor}`;
} else {
versionPath = `${githubTagPath}/v${major}.${minor}.${patch}`;
}
const githubUrl = `${githubSite}/${giteaRepo}/${versionPath}/${localePath}`;
const locales = fs.readdirSync(path.join(rootDir, localePath)).filter(file => file.endsWith(".ini"));
(async () => {
for (const locale of locales) {
const localUrl = `${githubUrl}/${locale}`;
console.log("LocaleUrl:", localUrl);
const themeLocale = fs.readFileSync(path.join(rootDir, localePath, locale), "utf-8");
const response = await fetch(localUrl);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
let content = await response.text();
if (locale.includes("zh-CN")) {
content = content.replaceAll("工单", "议题").replaceAll("合并请求", "拉取请求");
}
fs.mkdirSync(path.join(rootDir, "dist", localePath), { recursive: true });
fs.writeFileSync(path.join(rootDir, "dist", localePath, locale), content + themeLocale);
}
if (process.env.SSH_SERVER && process.env.GITEA_PATH && process.env.SSH_USER) {
const cmd = `scp -r dist/options ${process.env.SSH_USER}@${process.env.SSH_SERVER}:${process.env.GITEA_PATH}`;
console.log("[translate] exec:", cmd);
child_process.execSync(cmd, { stdio: "inherit" });
}
})();

View File

@@ -0,0 +1,54 @@
const fs = require("fs");
const path = require("path");
const rootDir = path.join(__dirname, "..");
const pkgPath = path.join(rootDir, "package.json");
const pkg = JSON.parse(fs.readFileSync(pkgPath));
const githubSite = "https://raw.githubusercontent.com";
const giteaRepo = "go-gitea/gitea";
const githubTagPath = "refs/tags";
const tmplPath = "templates";
const localTmplPath = path.join(rootDir, "gitea", tmplPath);
const [major, minor, patch = ""] = pkg.version.split(".");
console.log("Version:", pkg.version);
const versionPath = `${githubTagPath}/v${major}.${minor}.${patch}`;
const githubUrl = `${githubSite}/${giteaRepo}/${versionPath}/${tmplPath}`;
// 递归读取所有子目录中的 .tmpl 文件
function readTmplFilesRecursively(dir) {
const results = [];
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
// 如果是目录,递归读取
results.push(...readTmplFilesRecursively(filePath));
} else if (file.endsWith(".tmpl")) {
// 如果是 .tmpl 文件,添加到结果中(相对于模板目录的相对路径)
const relativePath = path.relative(localTmplPath, filePath);
results.push(relativePath);
}
}
return results;
}
// 读取所有模板文件
const tmpls = readTmplFilesRecursively(localTmplPath);
(async () => {
for (const tmpl of tmpls) {
const tmplUrl = `${githubUrl}/${tmpl}`;
console.log("TmplUrl:", tmplUrl);
const response = await fetch(tmplUrl);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
let content = await response.text();
fs.writeFileSync(path.join(localTmplPath, tmpl), content);
}
})();

View File

@@ -42,10 +42,10 @@ export type GithubColor = {
};
bgColor: {
accent: { emphasis: string; muted: string };
attention: { muted: string };
attention: { emphasis: string; muted: string };
emphasis: string;
success: { emphasis: string; muted: string };
danger: { muted: string };
danger: { emphasis: string; muted: string };
done: { emphasis: string };
default: string;
inset: string;
@@ -132,6 +132,7 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
};
const other: Other = {
logo: themeVars.color.primary.self,
body: githubColor.bgColor.default,
box: {
header: githubColor.bgColor.muted,
@@ -201,7 +202,7 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
bg: githubColor.bgColor.emphasis,
},
nav: {
bg: githubColor.bgColor.muted,
bg: githubColor.bgColor.inset,
hoverBg: githubColor.control.transparent.bgColor.hover,
text: themeVars.color.text.self,
},
@@ -239,6 +240,12 @@ export function github2ThemeColor(githubColor: GithubColor): ThemeColor {
success: {
emphasis: githubColor.bgColor.success.emphasis,
},
attention: {
emphasis: githubColor.bgColor.attention.emphasis,
},
danger: {
emphasis: githubColor.bgColor.danger.emphasis,
},
done: {
emphasis: githubColor.bgColor.done.emphasis,
},

View File

@@ -121,17 +121,28 @@ export function themePlugin(): Plugin {
const server = process.env.SSH_SERVER;
const user = process.env.SSH_USER || "root";
const theme_path = process.env.GITEA_THEME_PATH;
if (server && theme_path) {
const cmd = `scp dist/${prefix}*.css ${user}@${server}:${theme_path}`;
console.log("[themePlugin] exec:", cmd);
const gitea_path = process.env.GITEA_PATH;
if (server) {
try {
execSync(cmd, { stdio: "inherit" });
// eslint-disable-next-line @typescript-eslint/no-unused-vars
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");
}
if (gitea_path) {
const cmd = `scp -r templates ${user}@${server}:${gitea_path}`;
console.log("[themePlugin] exec:", cmd);
execSync(cmd, { stdio: "inherit" });
} else {
console.log("[themePlugin] no GITEA_TMPL_PATH, skip upload");
}
} catch (_) {
// continue regardless of error
}
} else {
console.log("[themePlugin] no SSH_SERVER or GITEA_THEME_PATH, skip upload");
console.log("[themePlugin] no SSH_SERVER, skip upload");
}
console.log("[themePlugin] exec end.");
},

View File

@@ -53,9 +53,22 @@ export const github = {
*/
emphasis: null,
},
attention: {
/** 注意的背景颜色
* @issue `prMerge` 头像颜色
*/
emphasis: null,
},
danger: {
/** 危险的背景颜色
* @issue `prMerge` 头像颜色
*/
emphasis: null,
},
done: {
/** 完成的背景颜色
* @issue `babel` 工单已关闭图标背景颜色
* @issue `prMerge` 头像颜色
*/
emphasis: null,
},

View File

@@ -8,6 +8,8 @@ export const otherAuto = {
};
export const other = {
/** 未登录时的介绍首页的 SVG 和链接文字颜色 */
logo: null,
/** 主要背景色 */
body: null,
/** 页面底部状态栏背景色 */

View File

@@ -63,6 +63,7 @@ export const actions = css`
color: ${themeVars.github.fgColor.accent};
font-family: var(--fonts-monospace);
font-weight: 400;
padding: 0px 6px;
&:hover {
background-color: ${themeVars.github.bgColor.accent.muted};
color: ${themeVars.github.fgColor.accent};
@@ -76,6 +77,7 @@ export const actions = css`
.flex-item {
padding: 16px;
line-height: 18px;
.flex-item-leading {
align-self: flex-start;
margin-top: 2px;
@@ -137,13 +139,21 @@ export const runWorkflow = css`
export const actionViewHeader = css`
.action-view-header {
.action-commit-summary {
a:hover {
text-decoration: inherit;
}
// 提前哈希
> a.muted:first-of-type {
text-decoration: underline;
}
// 分支标签按钮
.ui.label {
.ui.ui.ui.label {
background-color: ${themeVars.github.bgColor.accent.muted};
border-radius: ${otherThemeVars.border.radius};
color: ${themeVars.github.fgColor.accent};
font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, monospace);
font-weight: 400;
> a {
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-weight: 400;
opacity: 1;
}
}
@@ -153,10 +163,10 @@ export const actionViewHeader = css`
// 工作流左侧作业列表
export const actionViewLeft = css`
.action-view-left {
.action-view-left.action-view-left.action-view-left {
margin-right: 28px;
border-top: 1px solid ${themeVars.color.console.border};
max-width: 22vw;
&:before {
content: "Jobs";
color: ${themeVars.color.console.fg.subtle};
@@ -168,52 +178,53 @@ export const actionViewLeft = css`
top: -8px;
left: 15px;
}
.job-group-section {
padding-right: 8px;
padding-bottom: 8px;
border-bottom: 1px solid ${themeVars.color.console.border};
.job-brief-item {
border-radius: ${otherThemeVars.border.radius} !important;
padding: 8px;
position: relative;
margin-left: 0.5rem;
&.selected {
.job-brief-list {
gap: 4px;
// 双重确保覆盖原始样式
.job-brief-item.job-brief-item {
border-radius: ${otherThemeVars.border.radius} !important;
padding: 8px;
position: relative;
margin-left: 0.5rem;
&:hover {
background-color: ${themeVars.color.console.hoverBg};
}
&:after {
overflow: visible;
background: ${themeVars.github.borderColor.accent.emphasis};
border-radius: ${otherThemeVars.border.radius};
content: "";
height: 24px;
left: calc(0.5rem * -1);
position: absolute;
top: calc(50% - 12px);
width: 4px;
}
}
.job-brief-item-right {
svg.job-brief-rerun {
display: none;
color: ${themeVars.color.console.fg.subtle};
&:hover {
color: ${themeVars.color.text.self};
&.selected {
&:after {
overflow: visible;
background: ${themeVars.github.borderColor.accent.emphasis};
border-radius: ${otherThemeVars.border.radius};
content: "";
height: 24px;
left: calc(0.5rem * -1);
position: absolute;
top: calc(50% - 12px);
width: 4px;
}
}
.step-summary-duration {
color: ${themeVars.color.console.fg.subtle};
font-family: var(--fonts-monospace);
}
}
&:hover {
.job-brief-item-right {
svg.job-brief-rerun {
display: inline-block;
display: none;
color: ${themeVars.color.console.fg.subtle};
&:hover {
color: ${themeVars.color.text.self};
}
}
.step-summary-duration {
color: ${themeVars.color.console.fg.subtle};
font-family: var(--fonts-monospace);
font-size: 12px;
}
}
&:hover {
.job-brief-item-right {
svg.job-brief-rerun {
display: inline-block;
}
}
}
}
@@ -253,52 +264,57 @@ export const actionViewRight = css`
}
.job-step-container {
// 步骤标题
.job-step-summary {
color: ${themeVars.color.console.fg.subtle};
padding: 8px 10px !important;
&.selected {
// 滚动时固定在顶部的高度与 job-info-header 高度相同
top: 80px;
}
&.step-expandable:hover {
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;
.tw-mr-2:not(.svg) svg.svg {
margin: 1.5px 6px 0px 2px;
}
/* 绿色步骤状态改为白色 */
svg.svg.text.green {
color: ${themeVars.color.console.fg.subtle} !important;
}
&.selected {
// 滚动时固定在顶部的高度与 job-info-header 高度相同
top: 80px;
}
&.selected {
/* 不被 hover 效果影响 */
color: ${themeVars.color.console.fg.self} !important;
background-color: ${themeVars.color.console.activeBg} !important;
&.step-expandable:hover {
color: ${themeVars.color.console.fg.subtle};
}
.tw-mr-2:not(.svg) svg.svg {
margin: 1.5px 6px 0px 2px;
}
/* 绿色步骤状态改为白色 */
svg.svg.text.green {
color: ${themeVars.color.console.fg.subtle} !important;
}
&.selected {
/* 不被 hover 效果影响 */
color: ${themeVars.color.console.fg.self} !important;
background-color: ${themeVars.color.console.activeBg} !important;
svg.svg.text.green {
color: ${themeVars.color.console.fg.self} !important;
}
}
// 步骤耗时
.step-summary-duration {
font-size: 12px;
font-family: var(--fonts-monospace);
}
}
// 步骤耗时
.step-summary-duration {
font-size: 12px;
font-family: var(--fonts-monospace);
}
}
// 步骤日志
.job-step-logs {
animation: ${animationDown};
/* 日志字体颜色白色 */
.job-log-line {
color: ${themeVars.color.console.fg.self};
/* 被 hover 时覆盖 ANSI 颜色 */
.log-msg:hover * {
color: ${themeVars.color.console.fg.self} !important;
// 步骤日志
.job-step-logs {
animation: ${animationDown};
/* 日志字体颜色白色 */
.job-log-line {
color: ${themeVars.color.console.fg.self};
/* 被 hover 时覆盖 ANSI 颜色 */
.log-msg:hover * {
color: ${themeVars.color.console.fg.self} !important;
}
}
}
}

View File

@@ -36,12 +36,8 @@ export const commit = css`
}
// 提交信息右侧
.tw-text-right {
// 时间标签
relative-time,
// 复制 SHA 按钮
.btn.copy-commit-id,
// 查看提交路径按钮
.btn.view-commit-path {
svg {
color: ${themeVars.color.text.light.num1};
}
}

View File

@@ -1,4 +1,5 @@
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { labelStyle } from "styles/public/label";
export const dashboard = css`
// 首页仪表板, 避免选中管理员后台的维护管理面板
@@ -38,6 +39,9 @@ export const dashboard = css`
font-weight: 400;
background-color: unset !important;
margin-bottom: 0.25rem;
.ui.label {
border-color: #00000000;
}
}
// 仓库/组织列表
.ui.attached.segment {
@@ -47,6 +51,13 @@ export const dashboard = css`
&.repos-search {
border-top-left-radius: 12px;
border-top-right-radius: 12px;
> .menu.repos-filter {
.ui.circular.label {
border-color: #00000000;
min-height: fit-content;
padding: ${labelStyle.padding} !important;
}
}
}
&.table {
&:last-child {
@@ -58,6 +69,7 @@ export const dashboard = css`
li {
border-radius: ${otherThemeVars.border.radius};
padding: 6px 8px !important;
height: 32px;
&:not(:last-child) {
border-bottom: 0;
}

View File

@@ -101,11 +101,13 @@ export const repoFiles = css`
background: ${themeVars.color.body};
min-height: 48px;
padding: 0px 8px !important;
overflow-x: visible;
svg {
color: ${themeVars.color.text.light.num1};
}
.file-header-left {
padding: 8px !important;
padding: 6px 8px !important;
line-height: 1.45;
// 伪元素宽度等于按钮宽度而不是父元素宽度
position: relative;
&:hover {
@@ -116,7 +118,7 @@ export const repoFiles = css`
content: "";
background: ${themeVars.github.underlineNav.borderColor.active};
border-radius: ${otherThemeVars.border.radius};
bottom: -7px;
bottom: -8px;
left: 0;
height: 2px;
position: absolute;
@@ -127,9 +129,19 @@ export const repoFiles = css`
text-decoration-line: none;
}
}
.file-header-right:hover {
background: ${themeVars.github.control.transparent.bgColor.hover};
border-radius: ${otherThemeVars.border.radius};
.file-header-right {
.btn-octicon {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0px 8px;
border-radius: ${otherThemeVars.border.radius};
height: 28px;
width: 28px;
&:hover {
background: ${themeVars.github.control.transparent.bgColor.hover};
}
}
}
}
}
@@ -316,6 +328,10 @@ 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;
}
}
&:hover {
background: ${themeVars.color.hover.self};
@@ -395,18 +411,19 @@ export const repoSidebarTop = css`
padding: 10px 0 0 0;
// 仓库描述本身
.flex-item-title {
margin-top: 12px;
margin-top: 10px;
}
// 仓库描述内容
.flex-item-body {
> .tw-flex:first-child {
margin-top: 21px !important;
margin-top: 16px !important;
gap: 8px !important;
}
.repo-description {
color: ${themeVars.color.text.self};
}
#repo-topics {
margin: 10px 0px !important;
margin: 8px 0px !important;
}
.flex-text-block {
font-size: 14px;
@@ -444,7 +461,6 @@ export const repoSidebarBottom = css`
.flex-item-leading {
svg.svg.octicon-tag {
color: ${themeVars.color.green.self};
margin-top: 2px;
}
}
.flex-item-header .flex-item-title {

View File

@@ -69,6 +69,9 @@ export const heatmap = css`
// 动态
export const activity = css`
.activity-heatmap-container + .divider:not(.divider-text) {
border-color: #0000;
}
.flex-list#activity-feed {
border-radius: 12px;
box-shadow: ${themeVars.github.shadow.floating.small};

View File

@@ -263,7 +263,7 @@ export const prBranch = css`
font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, monospace);
font-size: 12px;
padding: 0 5px;
line-height: 20px;
line-height: 18px;
}
.repository.view.issue .pull-desc code {
@@ -275,6 +275,11 @@ export const prBranch = css`
}
`;
const botLabelStyle = {
height: "20px",
padding: "0 6px!important",
marginLeft: "4px",
};
// 评论
export const comment = css`
.comment .comment-container {
@@ -299,6 +304,26 @@ export const comment = css`
.comment-header {
padding: 4px 4px 4px 16px;
min-height: 38px;
.comment-header-left {
// bot 标签
.ui.basic.label {
${botLabelStyle}
}
a:has(relative-time) {
text-decoration: underline;
}
// 已编辑按钮
.content-history-menu {
color: ${themeVars.color.text.light.num1} !important;
.menu .item {
font-size: 12px;
.ui.avatar {
height: 20px;
width: 20px;
}
}
}
}
}
.comment-header-right {
> .item,
@@ -311,12 +336,6 @@ export const comment = css`
height: 20px;
padding: 0 6px;
}
// 隐藏顶部菜单的表情按钮
// 无法使用此样式, 评论无表情时底部的表情按钮元素不会渲染, 这是一个先有鸡还是先有蛋的问题
// 很蛋疼, 希望 Gitea 早日使用 Github 的样式, 因为 Github 的更合理, 无论是操作的方便程度还是按钮的冗余度
// .ui.dropdown.action.select-reaction {
// display: none;
// }
.context-dropdown {
height: 28px;
padding: 0 6px;
@@ -412,7 +431,6 @@ export const prMerge = css`
.repository.view.issue .comment-list .timeline-item.pull-merge-box {
// 头像
.timeline-avatar {
color: ${themeVars.color.white} !important;
border-radius: 9999px;
width: 40px;
height: 40px;
@@ -423,34 +441,67 @@ export const prMerge = css`
width: 24px;
height: 24px;
}
// 可以合并
&.green {
background-color: ${themeVars.github.bgColor.success.emphasis};
// PR 界面的 PR 操作评论
&.text {
color: ${themeVars.color.white} !important;
border-radius: ${otherThemeVars.border.radius};
// 操作评论边框
// 操作评论边框
+ .content > .ui.attached.segment {
border-left-color: ${themeVars.github.bgColor.success.emphasis};
border-right-color: ${themeVars.github.bgColor.success.emphasis};
&:first-child {
border-top-color: ${themeVars.github.bgColor.success.emphasis};
}
&:last-child {
border-bottom-color: ${themeVars.github.bgColor.success.emphasis};
border-width: 1.5px;
}
&.grey {
background-color: ${themeVars.color.text.light.num1};
}
&.green {
background-color: ${themeVars.github.bgColor.success.emphasis};
+ .content > .ui.attached.segment {
border-left-color: ${themeVars.github.bgColor.success.emphasis};
border-right-color: ${themeVars.github.bgColor.success.emphasis};
&:first-child {
border-top-color: ${themeVars.github.bgColor.success.emphasis};
}
&:last-child {
border-bottom-color: ${themeVars.github.bgColor.success.emphasis};
}
}
}
}
// 已合并
&.purple {
background-color: ${themeVars.github.bgColor.done.emphasis};
border-radius: ${otherThemeVars.border.radius};
+ .content > .ui.attached.segment {
border-left-color: ${themeVars.github.bgColor.done.emphasis};
border-right-color: ${themeVars.github.bgColor.done.emphasis};
&:first-child {
border-top-color: ${themeVars.github.bgColor.done.emphasis};
&.purple {
background-color: ${themeVars.github.bgColor.done.emphasis};
+ .content > .ui.attached.segment {
border-left-color: ${themeVars.github.bgColor.done.emphasis};
border-right-color: ${themeVars.github.bgColor.done.emphasis};
&:first-child {
border-top-color: ${themeVars.github.bgColor.done.emphasis};
}
&:last-child {
border-bottom-color: ${themeVars.github.bgColor.done.emphasis};
}
}
&:last-child {
border-bottom-color: ${themeVars.github.bgColor.done.emphasis};
}
&.yellow {
background-color: ${themeVars.github.bgColor.attention.emphasis};
+ .content > .ui.attached.segment {
border-left-color: ${themeVars.github.bgColor.attention.emphasis};
border-right-color: ${themeVars.github.bgColor.attention.emphasis};
&:first-child {
border-top-color: ${themeVars.github.bgColor.attention.emphasis};
}
&:last-child {
border-bottom-color: ${themeVars.github.bgColor.attention.emphasis};
}
}
}
&.red {
background-color: ${themeVars.github.bgColor.danger.emphasis};
+ .content > .ui.attached.segment {
border-left-color: ${themeVars.github.bgColor.danger.emphasis};
border-right-color: ${themeVars.github.bgColor.danger.emphasis};
&:first-child {
border-top-color: ${themeVars.github.bgColor.danger.emphasis};
}
&:last-child {
border-bottom-color: ${themeVars.github.bgColor.danger.emphasis};
}
}
}
}
@@ -494,11 +545,9 @@ export const prMerge = css`
padding: 16px;
display: grid;
gap: 8px;
&.no-header {
&::before,
&::after {
display: none;
}
&::before,
&::after {
display: none;
}
}
}
@@ -515,7 +564,7 @@ export const timeline = css`
}
.timeline-item,
.timeline-item-group {
padding: 16px 0;
padding: 12px 0;
.comment-text-line {
color: ${themeVars.color.text.light.num1};
}
@@ -523,10 +572,20 @@ export const timeline = css`
&.event {
// 修复覆盖后的位置问题
padding-left: 15px;
.avatar {
// 避免锚中批准的头像
.avatar-with-link .avatar {
width: 20px;
height: 20px;
}
// 批准时间的头像
// 头部居中偏移量(头像高度 - 标准行信息高度) / 2: (40px - 32px) / 2 = 4px
.timeline-avatar {
top: -4px;
}
// bot 标签
.comment-text-line .ui.basic.label {
${botLabelStyle}
}
.badge {
border: 2px solid ${themeVars.color.body};
}
@@ -592,6 +651,8 @@ export const issueSidebar = css`
color: ${themeVars.color.text.light.num1};
font-size: 12px;
}
// WIP 前缀提示
> a,
.ui.dropdown.select-branch,
.ui.form,
a.fixed-text.muted,
@@ -625,6 +686,18 @@ 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 {
color: ${themeVars.color.primary.self};
}
}
}
}
// 标签菜单项
.ui.dropdown > .menu > .scrolling.menu > .item:has(.item-secondary-info) {
// 修复标签菜单中描述文本过长没有换行挤掉标签的问题
@@ -668,6 +741,10 @@ export const issueSidebar = css`
}
}
}
// 修复菜单下拉打开时, 无法聚焦输入框
.menu input {
transition: none;
}
}
// 时间追踪
> div:not([class]):not([id]) {

View File

@@ -3,9 +3,12 @@ import { css, customThemeVars, otherThemeVars, themeVars } from "src/types/vars"
export const navbarRight = css`
#navbar {
border-bottom: 0;
padding: 0px 16px;
padding: 8px 16px; // 上下内边距 + .navbar-left & .navbar-right 的 min-height = 64px
min-height: 64px;
.navbar-left,
.navbar-right {
min-height: 48px;
}
.navbar-left {
gap: 8px;
> .item {
@@ -32,15 +35,12 @@ export const navbarRight = css`
gap: 8px;
// 右侧按钮, 但不包括头像
> .item:not(:last-child) {
display: grid;
gap: 4px;
grid-auto-columns: max-content;
align-items: center;
align-content: center;
justify-content: center;
gap: 4px;
border: 1px solid ${themeVars.color.light.border};
border-radius: ${otherThemeVars.border.radius};
padding: unset;
padding: 0;
height: 32px;
min-width: 32px;
min-height: 32px;
@@ -127,13 +127,33 @@ export const navbarRight = css`
}
}
}
// 手机下的创建菜单按钮
// 手机下的导航栏
@media (max-width: 767.98px) {
#navbar .navbar-right:has(.user-menu) > .item:not(:last-child) {
display: none;
}
#navbar.navbar-menu-open .navbar-right:has(.user-menu) > .item:not(:last-child) {
display: grid;
#navbar {
&.navbar-menu-open {
gap: 8px;
}
.navbar-mobile-right {
gap: 8px;
> .item {
align-items: center;
justify-content: center;
border: 1px solid ${themeVars.color.light.border};
border-radius: ${otherThemeVars.border.radius};
padding: 0;
height: 32px;
min-width: 32px;
min-height: 32px;
// 纠正内容保证居中
.tw-relative {
height: 16px;
width: 16px;
}
.svg {
margin: 0;
}
}
}
}
}
`;

View File

@@ -153,7 +153,7 @@ export const notification = css`
box-shadow: 2px 0 0 ${themeVars.github.borderColor.accent.emphasis} inset;
color: ${themeVars.color.text.self};
}
> .notifications-link > div{
> .notifications-link > div {
&:first-child {
font-size: 12px !important;
}

View File

@@ -2,8 +2,24 @@ import { css, themeVars } from "src/types/vars";
export const org = css`
.page-content.organization {
// 组织成员头像
.members .ui.avatar {
border-radius: 9999px;
}
// 组织头像
.org-avatar {
margin: 8px 24px 16px 0px;
}
// 组织信息
#org-info {
.ui.header {
margin-top: 8px; // 与头像对齐
gap: 8px;
// 组织名称
> .ui.header {
font-size: 24px;
> .org-visibility {
margin-left: 8px;
}
// 组织页面的 RSS 订阅按钮
.ui.label.button {
padding: 4px 16px;
@@ -16,6 +32,17 @@ export const org = css`
}
}
}
// 组织描述
> .markup {
color: ${themeVars.color.text.light.num1};
}
// 组织信息
> .meta {
font-size: 12px;
svg {
color: ${themeVars.color.text.light.num1};
}
}
}
}
`;

View File

@@ -50,8 +50,9 @@ export const packagesDetail = css`
.issue-title-header > div {
color: ${themeVars.color.text.light.num1};
}
.issue-content {
.issue-content-left {
.packages-content {
.packages-content-left {
width: calc(100% - 304px - 16px);
.ui.top.attached.header {
font-size: 14px;
padding: 16px;
@@ -79,9 +80,10 @@ export const packagesDetail = css`
}
}
}
.issue-content-right {
.packages-content-right {
border: 0;
padding: 0px 16px;
width: 304px;
> strong {
font-size: 16px;
}
@@ -121,3 +123,15 @@ export const packagesDetail = css`
}
}
`;
// 手机页面下的软件包详细信息页
export const packagesListMobile = css`
@media (max-width: 767.98px) {
.page-content.packages .packages-content {
.packages-content-left,
.packages-content-right {
width: 100%;
}
}
}
`;

View File

@@ -17,10 +17,10 @@ export const repoHeader = css`
display: flex;
align-items: center;
color: ${themeVars.color.text.self};
font-size: 16px;
font-size: 18px;
text-decoration: none !important;
min-width: 3ch;
padding: 4px 6px;
padding: 0px 6px;
border-radius: ${otherThemeVars.border.radius};
margin-top: 0.5rem;
margin-bottom: 0.5rem;
@@ -74,7 +74,8 @@ export const repoTopic = css`
border-radius: 9999px;
font-size: 12px;
font-weight: 500;
padding: 2.5px 10px;
padding: 0px 10px;
line-height: 22px;
background-color: ${themeVars.github.bgColor.accent.muted};
color: ${themeVars.github.fgColor.accent};
&:hover {

View File

@@ -83,3 +83,12 @@ export const label = css`
}
}
`;
// 修复组织设置界面的组织设置中多余的边框
export const fixOrgSetting = css`
.page-content.organization.settings {
.org-setting-content {
border: 0;
}
}
`;

View File

@@ -6,3 +6,5 @@
import "./public";
// 组件样式
import "./components";
// 模板专属样式
import "./templates";

View File

@@ -2,9 +2,13 @@ import { css } from "src/types/vars";
export const body = css`
body {
line-height: 18px;
line-height: 1.5;
}
a {
text-underline-offset: 0.2rem; // 0.2rem 可以始终保持下划线不受 overflow: hidden 的影响
}
// 默认代码块
code:not(.code-inner) {
padding: 0.2em 0.4em;
}
`;

View File

@@ -111,6 +111,7 @@ export const fixButtonHeight = css`
// 修复仓库页仓库操作按钮高度对齐和修正
.repo-button-row .ui.button {
min-height: 32px;
height: 32px;
}
// 修复因上面小按钮高度导致仓库星标克隆等按钮高度过高
.repo-header {

View File

@@ -5,6 +5,7 @@ import "./base"; // 基础样式, 确保在其他样式之前导入
import "./radius"; // 圆角, 此样式为基础样式, 确保在其他样式之前导入
import "./animation"; // 动画效果
import "./transition"; // 过渡效果
import "./table"; // 表格
import "./text"; // 文本或 SVG 的基本颜色
import "./button"; // 按钮
import "./dropdown"; // 下拉框

View File

@@ -40,7 +40,7 @@ export const input = css`
align-items: center;
}
// 下拉菜单的输入框
.ui.dropdown.dropdown .menu>.input {
.ui.dropdown.dropdown .menu > .input {
margin: 12px 10px;
}
`;

View File

@@ -1,6 +1,13 @@
import { css, themeVars } from "src/types/vars";
export const labelStyle = {
padding: "0px 6px",
};
export const label = css`
.ui.label {
border: 1px solid #00000000;
}
/* 所有标签, 但不包括 a 标签 */
/* a 标签比如仓库点星等按钮旁边的数字标签按钮,提交图中的 tag 标签 */
div.label,
@@ -9,7 +16,11 @@ export const label = css`
span.labels-list a.label {
&.ui.ui.ui {
border-radius: 9999px;
padding: 1.5px 6px;
${labelStyle}
line-height: 18px;
&.mini {
line-height: 16px;
}
// 多个标签的组合标签的圆角修复
&.scope-parent {
.scope-left {
@@ -103,7 +114,6 @@ export const shaLabel = css`
background-color: ${themeVars.color.label.hoverBg} !important;
}
span.ui.label.commit-is-signed {
padding: 3px 5px;
margin-left: 5px;
height: 25px;
}
@@ -118,6 +128,9 @@ export const shaLabel = css`
}
// 验证提交附带的图标
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;
@@ -150,6 +163,19 @@ export const shaLabel = css`
background-color: ${themeVars.color.red.badge.hover.bg} !important;
}
}
span {
display: inline-flex;
align-items: center;
justify-content: center;
}
}
span.ui.label.commit-is-signed,
.ui.label.commit-id-short,
.ui.label.commit-sign-badge {
font-size: 12px;
.ui.avatar {
border-radius: 9999px;
}
}
`;
@@ -194,10 +220,6 @@ export const repoLabel = css`
color: ${themeVars.color.text.light.num1};
font-size: 12px;
font-weight: 500;
padding: 1.5px 6px;
}
}
.org-visibility span.ui.basic.label {
font-size: 14px;
}
`;

View File

@@ -1,10 +1,11 @@
import { css, otherThemeVars, themeVars } from "src/types/vars";
import { labelStyle } from "./label";
export const activeItemAfterStyle = {
backgroundColor: themeVars.github.borderColor.accent.emphasis,
borderRadius: otherThemeVars.border.radius,
height: "24px",
left: "calc(0.5rem * -1)",
left: "-8px",
position: "absolute",
top: "calc(50% - 12px)",
width: "4px",
@@ -140,8 +141,8 @@ export const menu = css`
}
}
// 菜单标签样式
.ui.menu .item>.label:not(.floating) {
padding: 1.5px 6px;
.ui.menu .item > .label:not(.floating) {
${labelStyle}
}
`;

8
styles/public/table.ts Normal file
View File

@@ -0,0 +1,8 @@
import { css, themeVars } from "src/types/vars";
export const table = css`
.ui.table > tr > td,
.ui.table > tbody > tr > td {
border-top: 1px solid ${themeVars.color.secondary.alpha.num70};
}
`;

View File

@@ -0,0 +1 @@
import "./repo";

View File

@@ -0,0 +1,41 @@
import { css, otherThemeVars, themeVars } from "src/types/vars";
export const commitSignBadge = css`
a.ui.label.commit-id-short.github-theme-commit-sha {
gap: 8px;
padding: unset;
margin: unset;
height: 26px;
margin: 0 4px;
&.commit-is-signed {
&:hover {
background-color: unset !important;
}
span.ui.label.commit-sign-badge.commit-is-signed {
margin: unset;
}
}
.github-theme-sha {
border-radius: ${otherThemeVars.border.radius};
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji";
font-weight: 500;
padding: 0px 8px;
height: 26px;
min-width: 85px; // 非等宽字体导致不对齐, 目前看到最大长度为 83px
display: flex;
align-items: center;
justify-content: center;
&:hover {
background-color: ${themeVars.color.hover.self};
}
}
}
.ui.label.commit-sign-badge.github-theme-commit-sign-badge {
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji";
font-weight: 500;
}
`;

View File

@@ -0,0 +1,108 @@
import { css, otherThemeVars, themeVars } from "src/types/vars";
const primary = "primary" as const;
const secondary = "secondary" as const;
const metadata = "metadata" as const;
const actions = "actions" as const;
export const commitsList = css`
ul.github-theme-templates-commits-list {
margin: 0;
padding: 0;
list-style: none;
li.github-theme-commit {
border-bottom: 1px solid ${themeVars.color.secondary.self};
padding: 8px 16px;
display: grid;
grid-template-areas: "${primary} ${metadata} ${actions}" "${secondary} ${metadata} ${actions}";
grid-template-rows: repeat(2, auto);
grid-template-columns: minmax(30%, 1fr) minmax(0, max-content) min-content;
&:last-child {
border-bottom: none;
border-bottom-left-radius: ${otherThemeVars.border.radius};
border-bottom-right-radius: ${otherThemeVars.border.radius};
}
&:hover {
background-color: ${themeVars.color.hover.opaque};
}
.message {
grid-area: ${primary};
.commit-summary {
font-size: 16px;
font-weight: 500;
white-space: pre-wrap;
}
.ellipsis-button {
padding: unset;
height: 1.5rem;
min-width: 1.75rem;
background: unset;
border: unset;
vertical-align: bottom;
&:hover {
background: ${themeVars.color.hover.self};
}
}
.commit-body {
font-size: 12px;
font-weight: 400;
color: ${themeVars.color.text.light.num1};
margin: 8px 0;
}
}
.metadata {
grid-area: ${secondary};
font-size: 12px;
color: ${themeVars.color.text.light.num1};
display: flex;
align-items: center;
flex-direction: row;
gap: 4px;
img.ui.avatar {
border-radius: 9999px;
margin-right: 4px;
}
.ui.label svg {
min-width: 12px;
min-height: 12px;
width: 12px;
height: 12px;
}
}
.extra {
grid-area: ${metadata};
display: flex;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
column-gap: 8px;
.github-theme-tag {
border-width: 1.5px;
border-radius: 9999px;
height: 25px;
}
}
.actions {
grid-area: ${actions};
display: flex;
align-items: center;
flex-direction: row;
gap: 4px;
color: ${themeVars.color.text.light.num1};
.github-theme-action {
justify-content: center;
height: 28px;
width: 28px;
}
}
}
}
@media (max-width: 767.98px) {
ul.github-theme-templates-commits-list {
li.github-theme-commit {
grid-template-areas: "${primary} ${primary}" "${metadata} ${actions}" "${secondary} ${actions}";
grid-template-rows: repeat(3, auto);
}
}
}
`;

View File

@@ -0,0 +1,4 @@
import "./commit_sign_badge";
import "./commits_list";
import "./view_content";
import "./view_list";

View File

@@ -0,0 +1,38 @@
import { css, otherThemeVars, themeVars } from "src/types/vars";
export const repoButtonRow = css`
.github-theme-templates {
// 仓库按钮行
&.repo-button-row {
margin: 0 0 16px 0;
.repo-button-row-left .repository-summary {
> .item {
display: inline-flex;
align-items: center;
gap: 4px;
border-radius: ${otherThemeVars.border.radius};
color: ${themeVars.color.text.light.num1};
padding: 4px;
height: 32px;
min-height: 32px;
&:hover {
background-color: ${themeVars.github.control.transparent.bgColor.hover};
text-decoration-line: none;
}
svg {
margin-right: 4px;
}
b {
color: ${themeVars.color.caret};
}
}
}
.repo-button-row-right {
// 添加文件按钮菜单
.repo-add-file > .menu {
min-width: 152px;
}
}
}
}
`;

View File

@@ -0,0 +1,33 @@
import { css, otherThemeVars, themeVars } from "src/types/vars";
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;
gap: 4px;
border-radius: ${otherThemeVars.border.radius};
padding: 0px 8px;
min-height: 28px;
height: 28px;
font-size: 12px;
font-weight: 500;
&:hover {
background-color: ${themeVars.github.control.transparent.bgColor.hover};
color: inherit;
text-decoration-line: none;
}
svg {
color: ${themeVars.color.text.light.num1};
}
}
}
`;

View File

@@ -0,0 +1,174 @@
<nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}">
<div class="navbar-left">
<!-- the logo -->
<a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}">
<img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true">
</a>
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
<div class="ui secondary menu navbar-mobile-right only-mobile">
{{template "base/head_navbar_icons" dict "PageGlobalData" .PageGlobalData}}
<button class="item ui icon mini button tw-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "home.nav_menu"}}">{{svg "octicon-three-bars"}}</button>
</div>
<!-- navbar links non-mobile -->
{{if and .IsSigned .MustChangePassword}}
{{/* No links */}}
{{else if .IsSigned}}
{{if not (and ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled ctx.Consts.RepoUnitTypePullRequests.UnitGlobalDisabled)}}
{{if .ShowMilestonesDashboardPage}}
<a class="item{{if .PageIsMilestonesDashboard}} active{{end}}" href="{{AppSubUrl}}/milestones">{{ctx.Locale.Tr "milestones"}}</a>
{{end}}
{{end}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
{{else if .IsLandingPageOrganizations}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{ctx.Locale.Tr "explore"}}</a>
{{else}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
{{end}}
{{template "custom/extra_links" .}}
{{if not .IsSigned}}
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">{{ctx.Locale.Tr "help"}}</a>
{{end}}
</div>
<!-- the full dropdown menus -->
<div class="navbar-right">
{{if and .IsSigned .MustChangePassword}}
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
<span class="text">
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
<span class="only-mobile">{{.SignedUser.Name}}</span>
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
</span>
<div class="menu user-menu">
<div class="header">
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
</div>
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
{{else if .IsSigned}}
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "create_new"}}">
<span class="text">
{{svg "octicon-plus"}}
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
<span class="only-mobile">{{ctx.Locale.Tr "create_new"}}</span>
</span>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/repo/create">
{{svg "octicon-plus"}} {{ctx.Locale.Tr "new_repo"}}
</a>
{{if not .DisableMigrations}}
<a class="item" href="{{AppSubUrl}}/repo/migrate">
{{svg "octicon-repo-push"}} {{ctx.Locale.Tr "new_migrate"}}
</a>
{{end}}
{{if .SignedUser.CanCreateOrganization}}
<a class="item" href="{{AppSubUrl}}/org/create">
{{svg "octicon-organization"}} {{ctx.Locale.Tr "new_org"}}
</a>
{{end}}
</div><!-- end content create new menu -->
</div><!-- end dropdown menu create new -->
{{template "base/head_navbar_icons" dict "ItemExtraClass" "not-mobile" "PageGlobalData" .PageGlobalData}}
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
<span class="text">
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
<span class="only-mobile">{{.SignedUser.Name}}</span>
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
</span>
<div class="menu user-menu">
<div class="header">
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
</div>
<div class="divider"></div>
<a class="item" href="{{.SignedUser.HomeLink}}">
{{svg "octicon-person"}}
{{ctx.Locale.Tr "your_profile"}}
</a>
{{if not .DisableStars}}
<a class="item" href="{{.SignedUser.HomeLink}}?tab=stars">
{{svg "octicon-star"}}
{{ctx.Locale.Tr "your_starred"}}
</a>
{{end}}
<a class="item" href="{{AppSubUrl}}/notifications/subscriptions">
{{svg "octicon-bell"}}
{{ctx.Locale.Tr "notification.subscriptions"}}
</a>
<a class="{{if .PageIsUserSettings}}active {{end}}item" href="{{AppSubUrl}}/user/settings">
{{svg "octicon-tools"}}
{{ctx.Locale.Tr "your_settings"}}
</a>
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">
{{svg "octicon-question"}}
{{ctx.Locale.Tr "help"}}
</a>
{{if .IsAdmin}}
<div class="divider"></div>
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/-/admin">
{{svg "octicon-server"}}
{{ctx.Locale.Tr "admin_panel"}}
</a>
{{end}}
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
{{else}}
{{if .ShowRegistrationButton}}
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up">
{{svg "octicon-person"}}
<span class="tw-ml-1">{{ctx.Locale.Tr "register"}}</span>
</a>
{{end}}
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}">
{{svg "octicon-sign-in"}}
<span class="tw-ml-1">{{ctx.Locale.Tr "sign_in"}}</span>
</a>
{{end}}
</div><!-- end full right menu -->
{{$activeStopwatch := and .PageGlobalData (call .PageGlobalData.GetActiveStopwatch)}}
{{if $activeStopwatch}}
<div class="active-stopwatch-popup tippy-target">
<div class="tw-flex tw-items-center tw-gap-2 tw-p-3">
<a class="stopwatch-link tw-flex tw-items-center tw-gap-2 muted" href="{{$activeStopwatch.IssueLink}}">
{{svg "octicon-issue-opened" 16}}
<span class="stopwatch-issue">{{$activeStopwatch.RepoSlug}}#{{$activeStopwatch.IssueIndex}}</span>
</a>
<div class="tw-flex tw-gap-1">
<form class="stopwatch-commit form-fetch-action" method="post" action="{{$activeStopwatch.IssueLink}}/times/stopwatch/stop">
{{.CsrfTokenHtml}}
<button
type="submit"
class="ui button mini compact basic icon tw-mr-0"
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.stop_tracking"}}"
>{{svg "octicon-square-fill"}}</button>
</form>
<form class="stopwatch-cancel form-fetch-action" method="post" action="{{$activeStopwatch.IssueLink}}/times/stopwatch/cancel">
{{.CsrfTokenHtml}}
<button
type="submit"
class="ui button mini compact basic icon tw-mr-0"
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.cancel_tracking"}}"
>{{svg "octicon-trash"}}</button>
</form>
</div>
</div>
</div>
{{end}}
</nav>

View File

@@ -0,0 +1,35 @@
{{- $itemExtraClass := .ItemExtraClass -}}
{{- $data := .PageGlobalData -}}
{{if and $data $data.IsSigned}}{{/* data may not exist, for example: rendering 503 page before the PageGlobalData middleware */}}
{{- $activeStopwatch := call $data.GetActiveStopwatch -}}
{{- $notificationUnreadCount := call $data.GetNotificationUnreadCount -}}
{{if $activeStopwatch}}
<a class="item active-stopwatch {{$itemExtraClass}}" href="{{$activeStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{$activeStopwatch.Seconds}}">
<div class="tw-relative">
{{svg "octicon-stopwatch"}}
<span class="header-stopwatch-dot"></span>
</div>
</a>
{{end}}
{{if not ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled}}
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/issues" data-tooltip-content="{{ctx.Locale.Tr "issues"}}">
{{svg "octicon-issue-opened"}}
</a>
{{end}}
{{if not ctx.Consts.RepoUnitTypePullRequests.UnitGlobalDisabled}}
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/pulls" data-tooltip-content="{{ctx.Locale.Tr "pull_requests"}}">
{{svg "octicon-git-pull-request"}}
</a>
{{end}}
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}">
<div class="tw-relative tw-h-[16px]">
{{svg "octicon-inbox"}}
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
</div>
</a>
{{if $data.IsSiteAdmin}}
<a class="item {{$itemExtraClass}}" href="{{AppSubUrl}}/-/admin" data-tooltip-content="{{ctx.Locale.Tr "admin_panel"}}">
{{svg "octicon-server"}}
</a>
{{end}}
{{end}}

View File

@@ -0,0 +1,97 @@
{{/* Template attributes:
* Commit
* CommitBaseLink
* CommitSignVerification
If you'd like to modify this template, you could test it on the devtest page.
ATTENTION: this template could be re-rendered many times (on the graph and commit list page),
so this template should be kept as small as possible, DO NOT put large components like modal/dialog into it.
*/}}
{{- $commit := $.Commit -}}
{{- $commitBaseLink := $.CommitBaseLink -}}
{{- $verification := $.CommitSignVerification -}}{{- /* asymkey.CommitVerification */ -}}
{{- $extraClass := "" -}}
{{- $verified := false -}}
{{- $signingUser := NIL -}}
{{- $signingEmail := "" -}}
{{- $msgReasonPrefix := "" -}}
{{- $msgReason := "" -}}
{{- $msgSigningKey := "" -}}
{{- if $verification -}}
{{- $signingUser = $verification.SigningUser -}}
{{- $signingEmail = $verification.SigningEmail -}}
{{- $extraClass = print $extraClass " commit-is-signed" -}}
{{- if $verification.Verified -}}
{{- /* reason is "{name} / {key-id}" */ -}}
{{- $msgReason = $verification.Reason -}}
{{- $verified = true -}}
{{- if eq $verification.TrustStatus "trusted" -}}
{{- $extraClass = print $extraClass " sign-trusted" -}}
{{- else if eq $verification.TrustStatus "untrusted" -}}
{{- $extraClass = print $extraClass " sign-untrusted" -}}
{{- $msgReasonPrefix = ctx.Locale.Tr "repo.commits.signed_by_untrusted_user" -}}
{{- else -}}
{{- $extraClass = print $extraClass " sign-unmatched" -}}
{{- $msgReasonPrefix = ctx.Locale.Tr "repo.commits.signed_by_untrusted_user_unmatched" -}}
{{- end -}}
{{- else -}}
{{- if $verification.Warning -}}
{{- $extraClass = print $extraClass " sign-warning" -}}
{{- else -}}
{{- $extraClass = "" -}}{{/* the commit is not signed */}}
{{- end -}}
{{- $msgReason = ctx.Locale.Tr $verification.Reason -}}{{- /* dirty part: it is the translation key ..... */ -}}
{{- end -}}
{{- if $msgReasonPrefix -}}
{{- $msgReason = print $msgReasonPrefix ": " $msgReason -}}
{{- end -}}
{{- if $verification.SigningSSHKey -}}
{{- $msgSigningKey = print (ctx.Locale.Tr "repo.commits.ssh_key_fingerprint") ": " $verification.SigningSSHKey.Fingerprint -}}
{{- else if $verification.SigningKey -}}{{- /* asymkey.GPGKey */ -}}
{{- $msgSigningKey = print (ctx.Locale.Tr "repo.commits.gpg_key_id") ": " $verification.SigningKey.PaddedKeyID -}}
{{- end -}}
{{- end -}}
{{- $github_verifed := "github-theme.verifed" -}}
{{- $ctx_github_verifed := ctx.Locale.Tr $github_verifed -}}
{{- $github_partially_verifed := "github-theme.partially_verifed" -}}
{{- $ctx_github_partially_verifed := ctx.Locale.Tr $github_partially_verifed -}}
{{- $github_unverifed := "github-theme.unverifed" -}}
{{- $ctx_github_unverifed := ctx.Locale.Tr $github_unverifed -}}
{{- if $commit -}}
<a {{if $commitBaseLink}}href="{{$commitBaseLink}}/{{$commit.ID}}"{{end}} class="ui label commit-id-short {{$extraClass}} github-theme-commit-sha" rel="nofollow">
{{- end -}}
{{- if or (not $commit) $extraClass}}{{/* only show the lock icon if there is no commit info (icon only) or the commit is really signed */}}
<span class="ui label commit-sign-badge github-theme-commit-sign-badge {{$extraClass}}">
{{- if $verified -}}
{{- if and $signingUser $signingUser.ID -}}
<span data-tooltip-content="{{$msgReason}}">
{{if eq $ctx_github_verifed $github_verifed }}Verified
{{else}}{{$ctx_github_verifed}}{{end}}
</span>
<span data-tooltip-content="{{$msgSigningKey}}">{{ctx.AvatarUtils.Avatar $signingUser 16}}</span>
{{- else -}}
<span data-tooltip-content="{{$msgReason}}">
{{if eq $ctx_github_partially_verifed $github_partially_verifed }}Partially verified
{{else}}{{$ctx_github_partially_verifed}}{{end}}
</span>
<span data-tooltip-content="{{$msgSigningKey}}">{{ctx.AvatarUtils.AvatarByEmail $signingEmail "" 16}}</span>
{{- end -}}
{{- else -}}
<span data-tooltip-content="{{$msgReason}}">
{{if eq $ctx_github_unverifed $github_unverifed }}Unverified
{{else}}{{$ctx_github_unverifed}}{{end}}
</span>
{{- end -}}
</span>
{{- end -}}
{{- if $commit -}}
<span class="github-theme-sha">{{- ShortSha $commit.ID.String -}}</span>
</a>
{{- end -}}
{{- /* This template should be kept as small as possible, DO NOT put large components like modal/dialog into it. */ -}}

View File

@@ -0,0 +1,82 @@
<div class="ui attached table segment commit-table">
<ul class="github-theme-templates-commits-list">
{{$commitRepoLink := $.RepoLink}}{{if $.CommitRepoLink}}{{$commitRepoLink = $.CommitRepoLink}}{{end}}
{{range.Commits}}
<li class="github-theme-commit">
{{/* */}}
<div class="message">
{{if $.PageIsWiki}}
<span class="commit-summary" title="{{.Summary}}">{{.Summary | ctx.RenderUtils.RenderEmoji}}</span>
{{else}}
{{$commitLink:= printf "%s/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
<span class="commit-summary" title="{{.Summary}}">{{ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink $.Repository}}</span>
{{end}}
{{if IsMultilineCommitMessage .Message}}
<button class="ui button ellipsis-button" aria-expanded="false" data-global-click="onRepoEllipsisButtonClick">{{svg "octicon-ellipsis" 16}}</button>
{{end}}
{{if IsMultilineCommitMessage .Message}}
<pre class="commit-body tw-hidden">{{ctx.RenderUtils.RenderCommitBody .Message $.Repository}}</pre>
{{end}}
</div>
{{/* */}}
<div class="metadata">
{{/* */}}
{{$userName := .Author.Name}}
{{if .User}}
{{if and .User.FullName DefaultShowFullName}}
{{$userName = .User.FullName}}
{{end}}
{{ctx.AvatarUtils.Avatar .User 16}}<a class="muted author-wrapper" href="{{.User.HomeLink}}">{{$userName}}</a>
{{else}}
{{ctx.AvatarUtils.AvatarByEmail .Author.Email .Author.Name 16}}
<span class="author-wrapper">{{$userName}}</span>
{{end}}
{{/* */}}
·
{{if .Committer}}
{{DateUtils.TimeSince .Committer.When}}
{{else}}
{{DateUtils.TimeSince .Author.When}}
{{end}}
{{/* */}}
{{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses}}
</div>
{{/* */}}
<div class="extra">
{{/* */}}
{{if $.CommitsTagsMap}}
{{range (index $.CommitsTagsMap .ID.String)}}
{{- template "repo/tag/name" dict "AdditionalClasses" "github-theme-tag" "RepoLink" $.Repository.Link "TagName" .TagName "IsRelease" (not .IsTag) -}}
{{end}}
{{end}}
{{$commitBaseLink := ""}}
{{if $.PageIsWiki}}
{{$commitBaseLink = printf "%s/wiki/commit" $commitRepoLink}}
{{else if $.PageIsPullCommits}}
{{$commitBaseLink = printf "%s/pulls/%d/commits" $commitRepoLink $.Issue.Index}}
{{else if $.Reponame}}
{{$commitBaseLink = printf "%s/commit" $commitRepoLink}}
{{end}}
{{template "repo/commit_sign_badge" dict "Commit" . "CommitBaseLink" $commitBaseLink "CommitSignVerification" .Verification}}
</div>
{{/* */}}
<div class="actions">
<button class="btn interact-bg copy-commit-id github-theme-action" data-tooltip-content="{{ctx.Locale.Tr "copy_hash"}}" data-clipboard-text="{{.ID}}">{{svg "octicon-copy"}}</button>
{{/* at the moment, wiki doesn't support these "view" links like "view at history point" */}}
{{if not $.PageIsWiki}}
{{/* view single file diff */}}
{{if $.FileTreePath}}
<a class="btn interact-bg view-single-diff github-theme-action" data-tooltip-content="{{ctx.Locale.Tr "repo.commits.view_file_diff"}}"
href="{{$commitRepoLink}}/commit/{{.ID.String}}?files={{$.FileTreePath}}"
>{{svg "octicon-file-diff"}}</a>
{{end}}
{{/* view at history point */}}
{{$viewCommitLink := printf "%s/src/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
{{if $.FileTreePath}}{{$viewCommitLink = printf "%s/%s" $viewCommitLink (PathEscapeSegments $.FileTreePath)}}{{end}}
<a class="btn interact-bg view-commit-path github-theme-action" data-tooltip-content="{{ctx.Locale.Tr "repo.commits.view_path"}}" href="{{$viewCommitLink}}">{{svg "octicon-code"}}</a>
{{end}}
</div>
</li>
{{end}}
</ul>
</div>

View File

@@ -0,0 +1,106 @@
{{$isTreePathRoot := not .TreeNames}}
<div class="repo-view-content-data tw-hidden" data-document-title="{{ctx.RootData.Title}}" data-document-title-common="{{ctx.RootData.PageTitleCommon}}"></div>
{{/* {{template "repo/sub_menu" .}} */}}
<div class="github-theme-templates repo-button-row">
<div class="repo-button-row-left">
{{if not $isTreePathRoot}}
<button class="repo-view-file-tree-toggle-show ui compact basic button icon not-mobile {{if .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}"
data-global-click="onRepoViewFileTreeToggle" data-toggle-action="show"
data-tooltip-content="{{ctx.Locale.Tr "repo.diff.show_file_tree"}}">
{{svg "octicon-sidebar-collapse"}}
</button>
{{end}}
{{template "repo/branch_dropdown" dict
"Repository" .Repository
"ShowTabBranches" true
"ShowTabTags" true
"CurrentRefType" .RefFullName.RefType
"CurrentRefShortName" .RefFullName.ShortName
"CurrentTreePath" .TreePath
"RefLinkTemplate" "{RepoLink}/src/{RefType}/{RefShortName}/{TreePath}"
"AllowCreateNewRef" .CanCreateBranch
"ShowViewAllRefsEntry" true
}}
{{if and $isTreePathRoot (.Permission.CanRead ctx.Consts.RepoUnitTypeCode) (not .IsEmptyRepo)}}
<div class="repository-summary">
<a class="item muted" href="{{.RepoLink}}/branches">
{{svg "octicon-git-branch"}} <b>{{ctx.Locale.PrettyNumber .BranchesCount}}</b> {{ctx.Locale.TrN .BranchesCount "repo.branch" "repo.branches"}}
</a>
{{if $.Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
<a class="item muted" href="{{.RepoLink}}/tags">
{{svg "octicon-tag"}} <b>{{ctx.Locale.PrettyNumber .NumTags}}</b> {{ctx.Locale.TrN .NumTags "repo.tag" "repo.tags"}}
</a>
{{end}}
</div>
{{end}}
{{if not $isTreePathRoot}}
{{$treeNameIdxLast := Eval (len .TreeNames) "-" 1}}
<span class="breadcrumb">
<a class="section" href="{{.RepoLink}}/src/{{.RefTypeNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
{{- range $i, $v := .TreeNames -}}
<span class="breadcrumb-divider">/</span>
{{- if eq $i $treeNameIdxLast -}}
<span class="active section" title="{{$v}}">{{$v}}</span>
<button class="btn interact-fg tw-mx-1" data-clipboard-text="{{$.TreePath}}" data-tooltip-content="{{ctx.Locale.Tr "copy_path"}}">{{svg "octicon-copy" 14}}</button>
{{- else -}}
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
{{- end -}}
{{- end -}}
</span>
{{end}}
</div>
<div class="repo-button-row-right">
<!-- Show go to file if on home page -->
{{if $isTreePathRoot}}
<a href="{{.Repository.Link}}/find/{{.RefTypeNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
{{end}}
{{if and .RefFullName.IsBranch (not .IsViewFile)}}
<button class="ui dropdown basic compact jump button repo-add-file" {{if not .Repository.CanEnableEditor}}disabled{{end}}>
{{ctx.Locale.Tr "repo.editor.add_file"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<a class="item" href="{{.RepoLink}}/_new/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{svg "octicon-plus" 16}}{{ctx.Locale.Tr "repo.editor.new_file"}}
</a>
{{if .RepositoryUploadEnabled}}
<a class="item" href="{{.RepoLink}}/_upload/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{svg "octicon-upload" 16}}{{ctx.Locale.Tr "repo.editor.upload_file"}}
</a>
{{end}}
<a class="item" href="{{.RepoLink}}/_diffpatch/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{svg "octicon-diff" 16}}{{ctx.Locale.Tr "repo.editor.patch"}}
</a>
</div>
</button>
{{end}}
{{if and $isTreePathRoot .Repository.IsTemplate}}
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
{{ctx.Locale.Tr "repo.use_template"}}
</a>
{{end}}
<!-- Only show clone panel in repository home page -->
{{if $isTreePathRoot}}
{{template "repo/clone_panel" .}}
{{end}}
</div>
</div>
{{if .IsViewFile}}
{{template "repo/view_file" .}}
{{else if .IsBlame}}
{{template "repo/blame" .}}
{{else}}{{/* IsViewDirectory */}}
{{if $isTreePathRoot}}
{{template "repo/code/upstream_diverging_info" .}}
{{end}}
{{template "repo/view_list" .}}
{{if and .ReadmeExist (or .IsMarkup .IsPlainText)}}
{{template "repo/view_file" .}}
{{end}}
{{end}}

View File

@@ -0,0 +1,79 @@
{{/* use grid layout, still use the old ID because there are many other CSS styles depending on this ID */}}
<div id="repo-files-table" {{if .HasFilesWithoutLatestCommit}}hx-indicator="#repo-files-table .repo-file-cell.message" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}>
<div class="github-theme-templates repo-file-line repo-file-last-commit">
{{template "repo/latest_commit" .}}
<div class="github-latest-time">
{{if and .LatestCommit .LatestCommit.Committer}}
<a href="{{ (print .RepoLink "/commit") }}/{{.LatestCommit.ID}}" class="muted" rel="nofollow">
{{- ShortSha .LatestCommit.ID.String -}}
</a>
·
{{DateUtils.TimeSince .LatestCommit.Committer.When}}
{{end}}
</div>
{{if and (not .TreeNames) (.Permission.CanRead ctx.Consts.RepoUnitTypeCode) (not .IsEmptyRepo)}}
<a class="github-latest-commit item muted" href="{{.RepoLink}}/commits/{{.RefFullName.RefWebLinkPath}}">
{{svg "octicon-history" 16}} <b>{{ctx.Locale.PrettyNumber .CommitsCount}}</b> {{ctx.Locale.TrN .CommitsCount "repo.commit" "repo.commits"}}
</a>
{{end}}
{{if and .TreeNames (not .IsViewFile) (not .IsBlame)}}{{/* IsViewDirectory (not home), TODO: split the templates, avoid using "if" tricks */}}
<a class="github-latest-commit item muted" href="{{.RepoLink}}/commits/{{.RefTypeNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
{{svg "octicon-history" 16}}{{ctx.Locale.Tr "repo.file_history"}}
</a>
{{end}}
</div>
{{$.FileIconPoolHTML}}
{{if .HasParentPath}}
<a class="repo-file-line parent-link silenced" href="{{.BranchLink}}{{if .ParentPath}}{{PathEscapeSegments .ParentPath}}{{end}}">
{{index $.FileIcons ".."}} ..
</a>
{{end}}
{{range $item := .Files}}
<div class="repo-file-item">
{{$entry := $item.Entry}}
{{$commit := $item.Commit}}
{{$submoduleFile := $item.SubmoduleFile}}
<div class="repo-file-cell name muted-links {{if not $commit}}notready{{end}}">
{{index $.FileIcons $entry.Name}}
{{if $entry.IsSubModule}}
{{$submoduleLink := $submoduleFile.SubmoduleWebLinkTree ctx}}
{{if $submoduleLink}}
<a class="entry-name" href="{{$submoduleLink.RepoWebLink}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
@ <a class="text primary" href="{{$submoduleLink.CommitWebLink}}">{{ShortSha $submoduleFile.RefID}}</a>
{{else}}
<span class="entry-name" title="{{$entry.Name}}">{{$entry.Name}}</span>
@ {{ShortSha $submoduleFile.RefID}}
{{end}}
{{else}}
{{if $entry.IsDir}}
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
{{$subJumpablePathFields := StringUtils.Split $subJumpablePathName "/"}}
{{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}}
{{if eq $subJumpablePathFieldLast 0}}
{{$subJumpablePathName}}
{{else}}
{{$subJumpablePathPrefixes := slice $subJumpablePathFields 0 $subJumpablePathFieldLast}}
<span class="text light-2">{{StringUtils.Join $subJumpablePathPrefixes "/"}}</span>/{{index $subJumpablePathFields $subJumpablePathFieldLast}}
{{end}}
</a>
{{else}}
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
{{if $entry.IsLink}}
<a class="entry-symbol-link flex-text-inline" data-tooltip-content title="{{ctx.Locale.Tr "repo.find_file.follow_symlink"}}" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}?follow_symlink=1">{{svg "octicon-link" 12}}</a>
{{end}}
{{end}}
{{end}}
</div>
<div class="repo-file-cell message loading-icon-2px">
{{if $commit}}
{{$commitLink := printf "%s/commit/%s" $.RepoLink (PathEscape $commit.ID.String)}}
{{ctx.RenderUtils.RenderCommitMessageLinkSubject $commit.Message $commitLink $.Repository}}
{{else}}
{{/* will be loaded again by LastCommitLoaderURL */}}
{{end}}
</div>
<div class="repo-file-cell age">{{if $commit}}{{DateUtils.TimeSince $commit.Committer.When}}{{end}}</div>
</div>
{{end}}
</div>

View File

@@ -25,7 +25,7 @@ export const colorblindDarkGithubColors: GithubColor = {
},
bgColor: {
...darkGithubColors.bgColor,
danger: { muted: "#db6d281a" },
danger: { emphasis: "#bd561d", muted: "#db6d281a" },
success: { emphasis: "#1f6feb", muted: "#388bfd33" },
},
borderColor: {

View File

@@ -25,7 +25,7 @@ export const colorblindLightGithubColors: GithubColor = {
},
bgColor: {
...lightGithubColors.bgColor,
danger: { muted: "#fff1e5" },
danger: { emphasis: "#bc4c00", muted: "#fff1e5" },
success: { emphasis: "#0969da", muted: "#ddf4ff" },
},
borderColor: {

View File

@@ -45,8 +45,8 @@ export const darkGithubColors: GithubColor = {
},
bgColor: {
accent: { emphasis: "#1f6feb", muted: "#388bfd1a" },
attention: { muted: "#bb800926" },
danger: { muted: "#f851491a" },
attention: { emphasis: "#9e6a03", muted: "#bb800926" },
danger: { emphasis: "#da3633", muted: "#f851491a" },
default: "#0d1117",
done: { emphasis: "#8957e5" },
emphasis: "#3d444d",

View File

@@ -45,8 +45,8 @@ export const lightGithubColors: GithubColor = {
},
bgColor: {
accent: { emphasis: "#0969da", muted: "#ddf4ff" },
attention: { muted: "#fff8c5" },
danger: { muted: "#ffebe9" },
attention: { emphasis: "#9a6700", muted: "#fff8c5" },
danger: { emphasis: "#cf222e", muted: "#ffebe9" },
default: "#ffffff",
done: { emphasis: "#8250df" },
emphasis: "#25292e",

View File

@@ -39,8 +39,8 @@ export const softDarkGithubColors: GithubColor = {
},
bgColor: {
accent: { emphasis: "#316dca", muted: "#4184e41a" },
attention: { muted: "#ae7c1426" },
danger: { muted: "#e5534b1a" },
attention: { emphasis: "#966600", muted: "#ae7c1426" },
danger: { emphasis: "#c93c37", muted: "#e5534b1a" },
default: "#212830",
done: { emphasis: "#8256d0" },
emphasis: "#3d444d",

View File

@@ -30,11 +30,11 @@
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"baseUrl": ".",
"paths": {
"src/*": ["src/*"],
"styles/*": ["styles/*"],
"themes/*": ["themes/*", "themes/*.css"]
"*": ["./*"],
"src/*": ["./src/*"],
"styles/*": ["./styles/*"],
"themes/*": ["./themes/*", "./themes/*.css"]
}
},
"include": ["src", "styles", "themes", "vite.config.ts"]

View File

@@ -8,9 +8,8 @@ import * as sass from "sass-embedded";
import { defineConfig } from "vite";
import { themeInput, themePlugin } from "./src/core/vite";
dotenv.config({ quiet: true });
const require = createRequire(import.meta.url);
dotenv.config({ quiet: true });
const outDir = "dist"; // 输出目录
const themesDir = "themes"; // 颜色主题目录