Files
GiteaMailTemplates/docs/CONTRIBUTING.zh-CN.md
T
KenanZhu cb9382ade4
Validate / Validate (push) Successful in 2m47s
docs: modify contribution guides
2026-10-12 10:18:29 +08:00

365 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 贡献指南
---
[English](../CONTRIBUTING.md)
欢迎改进主题、工具、文档和翻译。本指南介绍开发环境、命令行工具和贡献流程。安装邮件模板和选择发行版本,请参阅 [README](README.zh-CN.md#安装)及[兼容性表](COMPATIBILITY.zh-CN.md#兼容性表)。
## 本地开发
使用 **Go 1.24 或更高版本**。在仓库根目录执行以下命令,准备依赖和锁定的官方文件,运行测试并生成预览:
```bash
cd tools
go mod download
go run . upstream prepare
go test ./...
go run . preview all
```
随后在浏览器中打开 [preview/index.html](../preview/index.html),或运行 `go run . dev` 使用实时预览。检查与打包工作流使用 Python 3.11。
项目按共享框架、主题样式和构建工具组织。官方模板提供通知内容、条件、主题行和链接;共享框架负责邮件呈现,主题通过元数据和 CSS 选择布局、定义样式。目录说明见 [README](README.zh-CN.md#项目目录结构)。
> [!NOTE]
> 下载的官方文件、生成的模板和预览数据不纳入版本控制。贡献时提交相应源码、测试和文档,无需提交 `build/`、`dist/` 或生成的预览数据。
## 开发工具
命令行工具提供官方文件准备、主题管理、模板构建和预览功能。
> [!TIP]
> 以下命令均在 `tools/` 中执行;带有位置参数时,将选项放在位置参数之前。示例中的 `my-theme` 表示主题名称,包含空格的路径需要加引号。
| 命令 | 用途 |
|---|---|
| `upstream` | 准备、同步或校验锁定的官方构建输入 |
| `build` | 根据官方输入和共享控件生成可安装的主题 |
| `list` | 列出可用主题及其元数据 |
| `create` | 创建使用共享框架的主题 CSS 和元数据 |
| `delete` | 删除一个或多个主题源码目录 |
| `preview` | 预渲染邮件模板,生成预览和测试数据 |
| `dev` | 启动通过 SSE 刷新页面的热重载开发服务器 |
| `help`、`h` | 显示命令列表或指定命令的帮助 |
### upstream
`upstream` 管理 `gitea.lock.json` 锁定的官方文件,包括邮件模板、语言文件、图标、许可证和已评审的适配参考源码。下载的文件保存到 `build/upstream/`。
| 子命令 | 行为 |
|---|---|
| `prepare` | 读取根锁文件。缓存缺失时下载并校验;已有缓存则校验后使用。不修改根锁文件。 |
| `sync --tag <TAG>` | 下载指定稳定版本的官方文件,校验后替换缓存并更新根锁文件。 |
| `verify` | 对照根锁文件,只读、离线校验已有缓存。 |
首次准备或单独检查输入时执行:
```bash
go run . upstream prepare
go run . upstream verify
```
三个子命令均支持 `--root`,默认值为相对当前工作目录的 `..`。例如:
```powershell
go run . upstream verify --root "C:\Projects\GiteaMailTemplates"
```
根锁文件记录 Gitea 标签、对应提交和文件的 SHA-256。`verify` 检查文件哈希、已评审的适配参考源码,以及官方模板引用的英文翻译键;非英文语言缺少的键会报告警告,并在预览中回退为英文。构建和渲染还会检查框架使用的翻译键及操作链接锚点,缓存校验不能代替这些检查。
#### 更新官方版本
只有需要评审新的官方版本时才使用 `sync`。例如,明确同步到 `v28.0.0`:
```bash
go run . upstream sync --tag v28.0.0
go run . upstream verify
go test ./...
go run . preview all
```
标签必须采用 `vX.Y.Z` 格式,并且是 Gitea 28 或更高版本的稳定标签;不支持 `latest`、预发布标签或旧版本标签。`sync` 通过 `api.github.com` 解析标签,通过 `raw.githubusercontent.com` 下载文件,不接受本地 Gitea 克隆或认证令牌参数。
同步后检查锁文件差异,按需调整适配逻辑和预览数据,完成验证后更新兼容性记录。同步不会自动更新文档、发行标签或兼容性结论。
> [!IMPORTANT]
> 适配参考源码发生变化时,须先评审相关行为,再更新对应参考哈希,不应仅修改哈希以跳过检查。
网络或校验错误发生在缓存替换前时,原有文件保持不变。缓存替换和根锁文件写入是两个操作;文件系统错误中断操作后,重试前应检查二者是否一致。更新输入前先停止 `dev`,避免多个进程同时写入缓存。
### build
`build` 根据锁定的官方文件、共享框架和主题源码生成可安装的邮件模板。必须指定一个或多个主题,或使用 `all` 构建全部主题:
```bash
go run . build aurora
go run . build aurora bloom
go run . build all
```
| 选项 | 默认值 | 说明 |
|---|---|---|
| `--folder` | `../themes` | 主题源码目录;工具将其父目录作为项目根目录 |
使用其他项目路径时,该项目根目录也需要提供锁文件和共享框架:
```powershell
go run . build --folder "C:\Projects\GiteaMailTemplates\themes" aurora
```
结果写入 `build/themes/<名称>/mail/`,同级的 `build.json` 记录构建来源和生成文件的校验值。重新构建会更新所选主题的模板并清理其过时模板,不清理未选中的主题。构建不会部署邮件模板,安装步骤见 [README](README.zh-CN.md#安装主题)。
> [!TIP]
> 需要修改模板时,应编辑主题源码、共享框架或构建适配逻辑。直接修改生成的 `.tmpl` 文件会在后续构建中被覆盖,也会导致打包时的来源校验失败。
### list
`list` 按名称排序,显示主题名称、模式和简短说明:
```bash
go run . list
```
可通过 `--folder` 指定主题目录,默认值为 `../themes`。命令会校验主题元数据和样式,不下载官方文件,也不生成模板。主题格式无效时,应先修复报告的问题。
### create
`create` 为新主题创建 `theme.json` 和 `theme.css`,支持一次创建多个主题:
```bash
go run . create my-theme
go run . create first-theme second-theme
```
可通过 `--folder` 指定主题源码目录,默认值为 `../themes`。命令不会覆盖已存在的目录。主题名称以小写字母开头,仅包含小写字母、数字和连字符;避免使用 `all`,因为构建和预览命令将其作为全部主题的选择参数。
编辑生成的元数据和 CSS,定义主题说明及样式。例如:
```json
{
"name": "my-theme",
"description": "主题的简短说明",
"mode": "framed",
"layout": "standard"
}
```
`name` 必须与目录名称一致。主题目录仅保存这两个源码文件,不保存官方邮件模板或翻译副本。
| 模式 | 展示结构 |
|---|---|
| `framed` | 使用共享控件和布局,由主题 CSS 定义样式。新主题默认使用此模式及 `standard` 布局。 |
| `shared` | 在官方页头片段中加入 CSS,并保留官方页脚片段;不增加框架控件或各类邮件的覆盖模板。 |
`framed` 主题可通过 `layout` 选择 `framework/layouts/` 中的布局预设。页头、操作按钮、备用链接、侧栏和页脚位于 `framework/mail/base/`。多个主题共用的结构调整应放在共享框架中,官方内容与控件之间的适配位于 `tools/builder/framework.go`。
主题 CSS 使用 `email-heading`、`email-text`、`email-subtext` 等现有类定义标题、正文和辅助说明层级。保留官方通知文字、翻译键、变量和功能链接,不通过 CSS 生成文案或隐藏业务内容。样式校验器会拒绝模板表达式、外部资源引用和不受支持的隐藏规则。
完成主题后运行测试并生成预览:
```bash
go test ./...
go run . preview my-theme
```
### delete
`delete` 删除指定主题的源码目录,支持一个或多个名称:
```bash
go run . delete my-theme
go run . delete first-theme second-theme
```
可通过 `--folder` 指定主题目录,默认值为 `../themes`。
> [!WARNING]
> 命令校验主题后直接删除目录,不提供确认提示或回收站恢复。执行前确认名称,并保留需要的修改。
不存在的主题会报告警告;无效主题或符号链接目录会被拒绝。多个主题依次处理,后续失败不会恢复已删除的目录。`all` 不表示删除全部主题。
删除源码不会移除之前生成的构建文件、预览数据或已部署的模板。重新执行 `preview all` 更新预览清单;需要移除部署的主题时,按实际安装路径单独处理。
### preview
`preview` 构建所选主题,并使用示例数据渲染全部锁定的官方语言。必须指定一个或多个主题,或使用 `all`:
```bash
go run . preview aurora
go run . preview aurora bloom
go run . preview all
```
| 选项 | 默认值 | 说明 |
|---|---|---|
| `--folder` | `../themes` | 主题源码目录;其父目录作为项目根目录 |
| `--config` | `./data/templates_config.json` | 邮件类型说明和预览示例数据 |
| `--output` | 项目根目录下的 `preview/rendered.js` | 预览清单路径 |
默认输出包括 `preview/rendered.js` 和 `preview/rendered/<语言>.js`。在浏览器中打开 [preview/index.html](../preview/index.html) 即可查看,无需启动服务器。操作和快捷键见 [README](README.zh-CN.md#控制和快捷键)。
> [!IMPORTANT]
> 每次生成会覆盖输出位置的预览清单,不与先前选择的主题合并。例如,执行 `preview aurora` 后,该清单只包含 Aurora;需要恢复全部主题时执行 `preview all`。
自定义输出示例:
```bash
go run . preview --config ./data/templates_config.json --output ../build/preview-review/rendered.js all
```
> [!NOTE]
> 语言数据写入输出文件同级的 `rendered/` 目录。命令不会复制预览界面或修改其脚本引用;现有 `preview/index.html` 仍读取默认位置的数据。
新增邮件类型或渲染分支时,补充 `tools/data/templates_config.json` 中的说明和示例上下文。JSON 中用于计数、大小等数值的整数应保持整数形式。正文、发布说明和评审内容等 HTML 字段应使用可控的测试内容,避免包含个人信息或真实凭据。
> [!NOTE]
> 预览用于检查模板结构和展示效果。它使用示例上下文,不能代替目标 Gitea 版本的参数兼容性评审;浏览器与邮件客户端对 CSS 的支持也存在差异。
### dev
`dev` 启动本地开发服务器,首次启动时构建全部主题并准备预览数据:
```bash
go run . dev
```
打开 [http://127.0.0.1:3456](http://127.0.0.1:3456)。默认端口为 `3456`,可通过 `--port` 修改:
```bash
go run . dev --port 3457
```
服务器仅监听 `127.0.0.1`。在终端中按 `Ctrl + C` 停止运行。该命令按当前 `tools/` 工作目录定位项目,不提供 `--folder`、`--config` 或 `--root` 选项。
服务器监听主题源码、共享框架、根锁文件、官方缓存及 `tools/data/` 中的预览数据。文件变化后重新构建,通过服务器发送事件(SSE)刷新预览。构建失败时,根据终端输出修复问题,再保存文件。
> [!TIP]
> 修改 `preview/index.html` 后手动刷新页面;修改 Go 工具代码后停止并重新启动服务器。这些文件不属于当前的自动重建监听范围。
### help、h
查看全部命令或指定命令的帮助:
```bash
go run . help
go run . h
go run . help build
go run . preview --help
```
查看 `upstream` 子命令的参数时,将 `--help` 放在子命令后:
```bash
go run . upstream prepare --help
go run . upstream sync --help
go run . upstream verify --help
```
工具诊断信息采用 `[LEVEL] [NAME] Message` 格式,`[I]`、`[W]`、`[E]`、`[F]` 分别表示信息、警告、错误和致命错误。在支持颜色的终端中,等级标记使用不同颜色;设置 `NO_COLOR` 可禁用颜色。命令失败时返回非零退出码,排查时保留完整输出。
## 常见问题
### 缺少锁文件或官方缓存怎么办?
已有克隆缺少 `gitea.lock.json` 时,应恢复受版本控制的根锁文件。缓存中的 `build/upstream/lock.json` 不能代替它。仅缺少缓存时执行 `upstream prepare`,不要为了恢复缓存而同步到其他版本。`build`、`preview` 和 `dev` 会自动准备官方输入。缓存、Go 工具链和依赖齐备后可以离线使用;`upstream verify` 始终只检查本地文件。首次下载遇到网络错误或 GitHub API 限流时,解决网络问题后重试。
### 缓存损坏或与锁文件不匹配怎么办?
`prepare` 不会自动修复损坏的缓存,`sync` 也会拒绝替换非空的无效快照。先停止开发服务器,保留根锁文件,将缓存移至备份位置后重新准备。例如,在**仓库根目录的 PowerShell** 中,使用尚不存在的备份名称:
```powershell
Move-Item -LiteralPath .\build\upstream -Destination .\build\upstream.backup
Set-Location tools
go run . upstream prepare
go run . upstream verify
```
> [!WARNING]
> 不要直接修改缓存中的官方文件,也不要删除 `build/` 中的其他内容。回退官方版本时,恢复此前已评审的根锁文件,再按同样方式重建缓存。
### 为什么同步新版本时提示适配源码发生变化?
项目固定了已评审的邮件渲染和翻译参考源码。上游修改这些实现后,工具会要求重新评审,避免继续使用不匹配的预览函数或变量结构。检查官方改动,调整适配逻辑和相关测试,再更新参考哈希。新增邮件、翻译键、函数或变量路径都可能需要对应修改。验证通过后再更新[兼容性记录](COMPATIBILITY.zh-CN.md),不要把成功下载等同于完成兼容性确认。
### 为什么部分语言使用英文或出现格式警告?
官方英文必须包含所有引用的翻译键;其他语言缺少的键回退为英文,并报告警告。保留官方语言文件,不在缓存中补写译文。
例如 Gitea v28.0.0 的波兰语 `mail.team_invite.text_1` 存在已知占位符缺陷。预览对已评审的完整原文保留官方输出并报告警告,该例外不适用于其他格式错误。新增问题应提供版本、翻译键和复现信息,以便评审和向上游反馈。
### 为什么预览没有显示新主题或最新修改?
静态预览不会自动构建。重新执行 `preview all` 并刷新页面,确认预览清单包含所需主题。使用自定义输出路径时,检查预览界面实际读取的位置;使用 `dev` 时,先查看终端是否报告重建失败。Go 代码变更需要重启服务器,预览界面变更需要手动刷新。默认端口被占用时,使用 `--port` 指定其他端口。
### 构建成功是否意味着支持所有 Gitea 版本?
构建结果针对根锁文件指定的官方输入。不同版本可能修改模板目录、函数或变量结构,不能仅凭构建或预览成功确认向下兼容。部署时按[兼容性表](COMPATIBILITY.zh-CN.md#兼容性表)选择发行包,不将新版本模板直接用于旧版本实例。
### 为什么打包脚本拒绝当前产物?
打包前执行 `preview all`,确保全部主题和语言数据齐备,且生成文件与当前源码一致。版本参数必须与根锁文件中的标签一致。源码或生成文件变化后,应重新构建和预览。脚本不会覆盖已有发行压缩包。重新打包时选择新的输出目录,保留需要对照的旧产物。
## 其它事宜
### 主题与共享框架
使用适合邮件客户端的 CSS。修改已有主题时,保留其配色、字体、边框和布局特征,使标题、正文和辅助说明的层级清晰,并考虑长文本、长 URL 和移动端宽度。布局片段使用展示性标记,支持 `table`、`tbody`、`tr`、`td`、`div`、`span` 及校验器允许的属性。组合后的标签必须完整配对;`__HEADER__` 插入共享页头,`__MAIL_TYPE__` 展开为邮件 ID,页脚中的 `__SIDEBAR__` 插入共享侧栏。业务变量和通知条件的变更应在构建适配逻辑中评审,不放入主题 CSS 或布局预设。
新增主题时更新中英文 README 的画廊。图片使用 PNG,单张不超过 50 KiB,建议为 10–20 KiB;主题、模板、语言和裁切方式按[截图指南](images/README.md)保持一致。
### 提交与拉取请求
围绕一个明确问题组织改动,避免混入无关的格式调整。拉取请求说明修改原因、影响范围和验证结果;涉及视觉变化时,可附上使用示例数据生成的对照图。修改主题、共享框架或 Go 工具时,在 `tools/` 中运行:
```bash
go test ./...
go run . preview all
```
涉及邮件内容、链接、变量或函数适配时,补充对应的回归测试,覆盖受影响的条件分支。现有测试检查生成结果、翻译键及全部主题和语言的通知主题行、正文与链接,包括推送、评审、回复、工作流和附件分支。
修改打包脚本时,在仓库根目录运行:
```bash
python -B -m unittest discover -s .github/scripts -p 'test_*.py'
```
纯文档修改检查文字、命令示例和链接即可。中文文档与英文文档应保持内容一致;翻译时保留命令、路径、变量和版本信息,不改变原意。
提交信息使用简短说明,可参考以下前缀:
| 前缀 | 范围 |
|---|---|
| `style(<名称>):` | 主题展示样式 |
| `preview:` | 预览工具 |
| `tools:` | CLI、构建与快照工具 |
| `docs:` | 文档和翻译 |
| `fix:` | 问题修复 |
| `project:` | 仓库配置和项目结构 |
| `refactor:` | 代码重构 |
| `chore:` | 日常维护 |
### 版本与发布维护
发行标签必须与锁定的 Gitea 标签一致。版本标记、徽章和兼容性记录由维护者手动更新;修改官方输入不会自动触发版本维护。历史发行附件应保留,文档和兼容性记录应在打标签前检查。完成验证并生成全部预览后,可在仓库根目录手动打包:
```bash
python .github/scripts/package_release.py --version v28.0.0 --output build/release-review
```
将示例版本替换为根锁文件中的标签,并使用没有同名发行压缩包的输出目录。脚本检查源码与产物的校验值,打包主题、预览、文档、官方许可证和来源信息,排除残留的旧主题构建。
`.github/workflows/validate.yml` 负责普通推送和拉取请求检查,也供 Release 工作流调用。Release 验证通过后打包归档,并通过发布 Action 上传附件,以标签作为标题,新建 Release 的正文为空,不要求发行说明文件。重新发布已有标签时保留已有正文并替换同名附件;失败后重试前检查发行版及附件状态。
工作流使用 `linux-amd64-docker-small` Runner 标签,并通过安装步骤准备 Go、Python 和发布所需的 Node.js。Action 使用 `actions/...@版本` 引用,由 Runner 的 Action 来源配置解析;维护时应考虑当前 `github_mirror` 配置。发布使用内置 `GITEA_TOKEN`,仓库需具备发行版写入权限。
### 报告问题
问题报告应包含 Gitea 版本、模板发行版或源码提交、主题、邮件类型、语言和复现步骤。构建或预览问题还应提供根锁文件中的标签、相关命令和完整错误输出;显示问题注明邮件客户端,并附上移除个人信息后的截图。
提出改进建议时,说明使用场景、预期效果及涉及的主题或工具。发现官方模板或翻译问题时,保留原始输入,提供能够复现问题的最小示例。
### 许可证
本项目采用 [MIT 许可证](../LICENSE)。贡献应使用能够合法分发的代码、样式和图片。生成和分发派生模板时,保留 Gitea 版权、官方许可证及快照来源信息;发行包已包含相关文件。