Files
lingxi/docs/工程规范/03-格式化与Lint.md
T
Stev_Wang 75cedbe97b docs: 明确 Git 提交信息与 PR 标题使用中文
原 GIT-05 要求 subject 用英文祈使句,与团队实际书写习惯不符(已有提交均为
中文),且缺少中英混排与术语约定,容易写出 Chinglish、自造术语或中英标点混乱。

本次改动:
- GIT-05 改为「提交信息一律使用中文」,type / scope 保留英文小写,规定祈使句、
  字数(≤50 汉字 / 整行 ≤72 字符)与不加句末标点;
- 新增 GIT-21~GIT-23:中英文间加空格、使用全角标点与反引号、术语沿用 PRD 术语表、
  禁止 Chinglish 与无信息缩写;
- 新增 §2.2 commitlint 配置要点:中文必须关闭 subject-case、拦截中文句号,
  否则钩子校验实际无效;
- 同步 03(commit-msg 钩子说明)、07(PR-01 标题用中文)与 AGENTS §7 / §9 / 附录。

影响面:仅文档,无代码影响。新规则对后续提交生效,已推送的历史提交不改写
(GIT-15 禁止改写 main 历史)。
回滚方式:git revert 本提交。
2026-11-02 15:12:56 +08:00

142 lines
5.8 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# 03 · 格式化与 Lint
| 项 | 内容 |
| --- | --- |
| 文档版本 | V1.0(2026-11-02) |
| 依据 | 技术架构 §2.2(前端)、§10.1(工程约定)、§4.6(CI/CD) |
| 适用范围 | 全仓库可执行文件 |
| 强制级别 | 强制(CI 门禁,不允许「先合并后修」) |
---
## 1 一句话原则
**格式交给工具,评审只看逻辑。** 任何格式争论都应由配置解决,禁止在 Review 中讨论空格与换行。
---
## 2 Prettier(唯一格式化器)
| 配置项 | 值 | 说明 |
| --- | --- | --- |
| `printWidth` | `100` | 与技术架构示例行宽一致 |
| `tabWidth` | `2` | |
| `useTabs` | `false` | |
| `semi` | `true` | |
| `singleQuote` | `true` | |
| `trailingComma` | `all` | |
| `arrowParens` | `always` | |
| `endOfLine` | `lf` | 跨平台一致 |
| `plugins` | `prettier-plugin-tailwindcss`(仅 `apps/web`) | 若引入 Tailwind;未引入则不加 |
规则:
- `FMT-01` 只允许一个 Prettier 版本、一个根配置;子包**不得**覆盖。
- `FMT-02` 禁止在文件中写 `prettier-ignore`,除非是生成代码或大段 markdown 表格,并注明原因。
- `FMT-03` CI 执行 `pnpm format:check`,失败即阻断。
- `FMT-04` 禁止把格式化产生的无关改动混进功能 PR(会产生冲突与 Review 噪音)。
---
## 3 ESLint(ESLint 9 flat config)
| 项 | 约定 |
| --- | --- |
| 配置位置 | 根 `eslint.config.mjs`,按 `apps/*`、`packages/*` 分层 export |
| 基础 | `@eslint/js` recommended + `typescript-eslint` 的 `strictTypeChecked` + `stylisticTypeChecked` |
| 前端附加 | `eslint-plugin-react-hooks`、`eslint-plugin-react-refresh`、`jsx-a11y` |
| 导入排序 | `eslint-plugin-simple-import-sort` |
| 命名检查 | `@typescript-eslint/naming-convention`(对应 [02](02-代码风格.md) §1) |
### 3.1 必须为 `error` 的规则
| 规则 | 目的 |
| --- | --- |
| `@typescript-eslint/no-explicit-any` | 禁 `any` |
| `@typescript-eslint/no-floating-promises` | 禁未处理 Promise |
| `@typescript-eslint/no-misused-promises` | 禁 async 传入非异步回调位 |
| `@typescript-eslint/consistent-type-imports` | 类型导入用 `import type` |
| `@typescript-eslint/no-unnecessary-condition` | 消除冗余判断(strict 下有效) |
| `no-restricted-imports` | **UI / 图标白名单**(见 §3.2) |
| `no-console` | 业务代码禁用,`scripts/**` 与 `worker` 的 logger 除外 |
| `import/no-cycle` | 禁循环依赖 |
| `react-hooks/rules-of-hooks` / `exhaustive-deps` | Hooks 正确性 |
| `jsx-a11y/*` 关键项 | 可访问性底线 |
### 3.2 白名单(`no-restricted-imports` 强制)
**禁止导入**(含子路径):
```
@douyinfe/semi-ui ← 只能用 @douyinfe/semi-ui-19
antd @ant-design/* @arco-design/*
@douyinfe/semi-icons @ant-design/icons react-icons lucide-react @heroicons/*
element-plus naive-ui @mui/* @chakra-ui/*
```
**规则**:
- `FMT-05` 图标只能 `import { IconXxx } from '@lingxi/ui/icons'`;禁止 `import * as Icons`、禁止直接引 `remixicon/icons/...`。
- `FMT-06` SVG 内联仅允许品牌 Logo(`packages/ui/brand/`),其他一律走图标出口。
- `FMT-07` 颜色字面量(`#rrggbb`、`rgb(`)在 `apps/web` 内禁用,除非在 `packages/ui/theme/` 的 token 定义文件。
### 3.3 允许 `warn` 的规则
`@typescript-eslint/no-non-null-assertion`(须注释证明非空)、`complexity`(> 15 警告)、`max-lines-per-function`(> 50 警告)。
---
## 4 提交钩子(本地)
| 钩子 | 工具 | 行为 |
| --- | --- | --- |
| `pre-commit` | husky + lint-staged | 仅对暂存文件跑 `eslint --fix` + `prettier --write` |
| `commit-msg` | commitlint | 校验 Conventional Commits 与中文书写(配置见 [01](01-Git规范.md) §2.2) |
| `pre-push` | husky | 跑 `pnpm typecheck`(本地拦截类型错误,避免浪费 CI) |
- `FMT-08` `lint-staged` 只处理暂存文件,**禁止**在钩子里跑全量 lint / 全量测试(太慢会诱发 `--no-verify`)。
- `FMT-09` 禁止 `git commit --no-verify`;如确因钩子故障,须在 PR 描述说明并附 CI 结果。
---
## 5 CI 门禁(阻断项)
| 阶段 | 命令 | 失败后果 |
| --- | --- | --- |
| 安装 | `pnpm install --frozen-lockfile` | 阻断(lock 不一致直接失败) |
| 格式 | `pnpm format:check` | 阻断 |
| Lint | `pnpm lint --max-warnings=0` | 阻断 |
| 类型 | `pnpm typecheck` | 阻断 |
| 单测 | `pnpm test -- --coverage` | 阻断(覆盖率不得低于基线) |
| 迁移 | `prisma migrate diff` 校验 schema 与迁移一致 | 阻断 |
| 构建 | `pnpm build` | 阻断 |
| 安全 | 依赖审计 + 镜像高危漏洞 | 阻断(高危 0) |
- `FMT-10` CI 与本地必须使用**同一份配置**,禁止 CI 单独放宽规则。
- `FMT-11` 覆盖率基线只升不降;下调须在 PR 说明理由并由技术负责人批准。
---
## 6 例外与豁免
| 场景 | 做法 |
| --- | --- |
| 生成代码(Prisma Client、OpenAPI 类型) | 在 `eslint.config.mjs` 中按路径 `ignores`,禁止在生成文件内加注释 |
| 第三方类型缺陷 | 文件级 `/* eslint-disable rule -- 原因 */`,必须写原因并在 PR 说明 |
| 单行特殊语法 | 行内 `// eslint-disable-next-line rule -- 原因` |
| 全文件 disable | **禁止**;确需则改为局部 disable 或调整规则配置 |
- `FMT-12` 任何 `eslint-disable` 都必须写明原因与到期处理方式(升级依赖 / 提 issue)。
- `FMT-13` 规则调整(新增 / 降级 / 关闭)必须单独 PR,说明影响文件数与整改计划。
---
## 7 检查清单
- [ ] `pnpm format:check` 通过,无格式化噪音混入
- [ ] `pnpm lint --max-warnings=0` 通过
- [ ] `pnpm typecheck` 通过
- [ ] 无新增 `eslint-disable`;已有的都有原因
- [ ] 未引入禁用包 / 禁用图标库
- [ ] 无散落色值,样式走 token