Files
lingxi/docs/工程规范/03-格式化与Lint.md
Stev_Wang dd01b89214
ci / 质量门禁 (push) Canceled after 0s
docs(docs): 调整分支策略为仅 main 直推
背景:用户确认仓库只保留 main,不再创建任何远程分支或走 PR 合并。

改动:
- 01-Git规范 V1.1:仅 main 直推,禁止非 main 分支推送、force push 与 Merge commit;
- AGENTS V1.1:变更流程改为直接提交并推送 main;
- 07-CodeReview:PR 模板改为提交说明,合并流程改为推送与推送后观察;
- 03/06/工程规范 README 同步去除 PR 措辞;
- CI 仅保留 push main 与 workflow_dispatch 触发。

影响面:仅流程与文档,无代码/数据/接口变更。
回滚方式:git revert 本提交即可恢复旧流程。
验证:format:check、lint、typecheck 全绿(10/10)。
2026-11-02 17:40:01 +08:00

142 lines
5.8 KiB
Markdown
Raw Permalink 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` 禁止把格式化产生的无关改动混进功能提交(会产生冲突与 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`;如确因钩子故障,须在提交说明中说明并附 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` 覆盖率基线只升不降;下调须在提交说明说明理由并由技术负责人批准。
---
## 6 例外与豁免
| 场景 | 做法 |
| --- | --- |
| 生成代码(Prisma Client、OpenAPI 类型) | 在 `eslint.config.mjs` 中按路径 `ignores`,禁止在生成文件内加注释 |
| 第三方类型缺陷 | 文件级 `/* eslint-disable rule -- 原因 */`,必须写原因并在提交说明说明 |
| 单行特殊语法 | 行内 `// eslint-disable-next-line rule -- 原因` |
| 全文件 disable | **禁止**;确需则改为局部 disable 或调整规则配置 |
- `FMT-12` 任何 `eslint-disable` 都必须写明原因与到期处理方式(升级依赖 / 提 issue)。
- `FMT-13` 规则调整(新增 / 降级 / 关闭)必须单独提交,说明影响文件数与整改计划。
---
## 7 检查清单
- [ ] `pnpm format:check` 通过,无格式化噪音混入
- [ ] `pnpm lint --max-warnings=0` 通过
- [ ] `pnpm typecheck` 通过
- [ ] 无新增 `eslint-disable`;已有的都有原因
- [ ] 未引入禁用包 / 禁用图标库
- [ ] 无散落色值,样式走 token