中文排版体检官(doc-typography-doctor)
把「中文排版是否规范」从主观感觉变成可执行、可复现、可进 CI 的检查。
效果示例
坏例:我们用Python开发,冷启动从3.2s降到180ms.
好例:我们使用 Python 开发,冷启动从 3.2 s 降到 180 ms。
两条命令完成闭环:
python scripts/typo_doctor.py lint README.md # 体检,指出问题与行号
python scripts/typo_doctor.py fix README.md --level info --write --backup
何时使用
只要出现下面任意一种情况,就应调用本 Skill:
- 用户要求检查、体检、审查中文文档的排版或标点;
- 文档里出现中英文混排、全半角标点混用、
...与……混用等问题; - 需要批量清理 README、技术文档、公众号草稿、产品文案的格式;
- 需要在提交前拦截排版问题(pre-commit / CI 场景)。
不适用:改写句子语义、调整文风、繁简转换、「的地得」辨析、英文语法检查。
快速开始
先进入技能根目录(下文命令均以此为基准);用绝对路径调用也可以:
cd <SKILL_DIR>
python scripts/typo_doctor.py lint README.md
四条常用命令:
# 1. 体检:带行号、级别、规则 ID 与修复建议
python scripts/typo_doctor.py lint README.md
# 2. 体检整个目录,机器可读输出
python scripts/typo_doctor.py lint docs/ --format json --level warn
# 3. 预览修复(只打印 unified diff,不改文件)
python scripts/typo_doctor.py fix README.md
# 4. 写回文件:--level info 会连同数值单位、百分号等 info 项一起修
python scripts/typo_doctor.py fix README.md --level info --write --backup
python scripts/typo_doctor.py lint README.md
fix 默认只修 error 与 warn。想让数值单位(20ms)、百分号(92 %)
这类 info 项也一起修,必须显式加 --level info。
输出怎么读
文本报告示例:
== README.md == 体检分 42/100 9 处(3 error / 5 warn / 1 info)
7:12 error TP010 中文语境使用了半角「,」
应改为全角「,」
| 我们使用Python开发,启动更快。
| ^
- 体检分:0 到 100,按问题密度与严重度换算,干净文档为 100 分;
- 位置:
行:列,列号按字符计,全角字符占两格显示; - 规则 ID:
TPxxx,逐条依据见references/rules.md,或运行rules子命令; - 退出码:
0通过、1存在达到阈值的问题、2运行错误。
注意:--level 只影响「报告显示哪些条目」,不影响体检分与 stats.issues;
--fail-on 才决定退出码。完整依据(why 字段)只出现在 JSON 输出里。
JSON 输出(--format json)关键字段:
{
"summary": {"files": 1, "issues": 9, "error": 3, "warn": 5, "info": 1, "fixable": 7, "score": 42},
"files": [{
"path": "README.md",
"score": 42,
"stats": {"chars": 812, "lines": 40, "issues": 9, "error": 3, "warn": 5, "info": 1},
"issues": [{
"rule": "TP010", "severity": "error", "line": 7, "column": 12,
"message": "中文语境使用了半角「,」", "hint": "应改为全角「,」",
"why": "GB/T 15834《标点符号用法》:……",
"fixable": true, "suggested": ","
}]
}]
}
推荐工作流(Agent 用法)
- 先
lint,把报告按严重度分组讲给用户,不要一次性堆出全部条目; - 修复前用
fix(不带--write)拿到 diff,确认没有误伤再写回; - 写回后立刻
lint复检,用体检分的前后对比汇报结果,而不是只说「修了 N 处」; - 用户只想看问题不想改文件时,用
--format markdown输出表格,便于粘贴到评审记录。
判断标准:error 一律要改;warn 建议改;info 属于风格偏好,按团队规范决定。
用户明确说「只看看」或「不要动我的文件」时,禁止使用 --write。
覆盖的规则
共 22 条,按类别分组(完整说明见 references/rules.md):
| ID | 级别 | 规则 | 可自动修复 | | --- | --- | --- | --- | | TP001 | warn | 中英文之间缺少空格 | 是 | | TP002 | warn | 中文与数字之间缺少空格 | 是 | | TP003 | warn | 中英文之间空格过多 | 是 | | TP004 | warn | 全角标点后多余空格 | 是 | | TP005 | warn | 全角标点前多余空格 | 是 | | TP006 | info | 中文之间连续空格 | 否(纯文本对齐可能依赖空格) | | TP010 | error | 中文语境使用半角标点 | 是 | | TP011 | error | 中文句末使用半角句号 | 是 | | TP012 | error | 省略号不规范 | 是 | | TP013 | warn | 破折号不规范 | 是 | | TP014 | info | 破折号前后多余空格 | 是 | | TP015 | warn | 中文语境使用英文直引号 | 是(单引号仅提示) | | TP016 | warn | 中文语境使用半角括号 | 是 | | TP017 | warn | 连用逗号或句号 | 是 | | TP018 | info | 连用感叹号或问号 | 否(仅提示) | | TP020 | warn | 行尾多余空白 | 部分(≥2 个空格只提示) | | TP021 | info | 连续空行过多 | 是 | | TP022 | info | 全角空格误用 | 否(仅提示) | | TP030 | info | 数值与单位之间缺少空格 | 是 | | TP031 | info | 百分号写法不规范 | 是 | | TP032 | info | 数值范围使用波浪号 | 否(仅提示) | | TP040 | warn | 中文与行内代码/链接之间缺少空格 | 是 |
--rules 只跑指定规则,--exclude 排除指定规则。例如团队规范允许 第1章
连写、不希望被改成「第 1 章」,可排除 TP002:
python scripts/typo_doctor.py lint docs/ --exclude TP002
安全边界:这些区域永远不动
工具先给文本建「保护区域」遮罩,下列内容既不检测也不修改:
- 围栏代码块(``` 或 ~~~),含引用块里的围栏、嵌套围栏与未闭合的代码块;
- 四空格或 Tab 缩进的代码块;
- HTML 块级容器
<pre>、<code>、<script>、<style>的内容; - 行内代码(反引号包裹的内容);
- Markdown 链接与图片的目标地址、引用式链接定义(
[ref]: url)与引用标记(][ref]); - 裸 URL、邮箱、自动链接;
- YAML / TOML front-matter(
---或+++包裹,含...结束写法); - LaTeX 公式(行内
$...$与多行$$...$$);$5这类纯金额写法不参与遮罩; - HTML 标签与注释(含未闭合注释)、Windows 路径(含带空格的路径)。
链接文字仍然参与体检,所以 [中文,标签](url) 里的逗号会被修正,地址原样保留。
出错怎么办
退出码 2 表示运行错误,按提示处置:
| 报错 | 处置 |
| --- | --- |
| 路径不存在 | 检查参数路径;目录扫描可用 --ext 指定扩展名 |
| 未知规则 ID | 先运行 rules 查看有效 ID |
| 疑似二进制文件(含 NUL 字节) | 该文件不是文本,先转换再检查;不要强行修复 |
| 编码无法可靠判定(可能是 gb18030 / big5 / cp932) | 只读体检会继续并给出提示;写回前用 --encoding 指定真实编码 |
| 备份失败 / 写入失败 | 检查文件是否只读、是否被占用、磁盘是否可写 |
误报排查三步:先 rules 看规则依据 → 用 --rules TPxxx 单项复现 →
确认后用 --exclude TPxxx 固化到脚本或 CI。
已知边界
- 只做字符级排版,不改写句子,不做繁简转换与「的地得」辨析;
- 纯英文段落不参与中文规则判断,所以不会把英文句号改成中文句号;
- 只在符号左侧补空格:
使用C++语言会变成使用 C++语言,++、#与紧随其后的汉字之间不会插入空格; - 识别代码特征、不做修改:
--write、--help等命令行参数,print("中文")、foo(参数)这类调用写法,15"、10"这类英寸符号; - 单字母大写单位(
A、V、W)只在数字不少于两位时补空格,避免把3A 级、5V 档这类型号与等级误判成单位(220V电源仍会修); - 为符合 Markdown 规范,四空格缩进的普通正文会被当作代码块跳过体检; 正文请勿用缩进排版,代码请用围栏写法;
- 连续的全角空格只报告每段的第一处;行尾 2 个以上空格只提示(可能是 Markdown 硬换行或纯文本对齐),TP006 也只提示,两者都不自动修改;
- 非 UTF-8 文件按「文本合理性」在 gb18030 / big5 / cp932 / euc-kr 中推断;
推断存疑时只读体检会给提示,写回必须用
--encoding明确指定,避免改坏字节; - TP002 属于社区约定而非国标强制项,团队可按需排除;
- 自动修复保证幂等:
fix两次的结果完全一致,可安全接入 pre-commit。
规则依据
- GB/T 15834—2011《标点符号用法》:句号、逗号、省略号(……)、破折号(——)、引号与括号;
- GB/T 15835—2011《出版物上数字用法》:数值范围的表达;
- GB 3100 至 3102《量和单位》:数值与单位符号之间留一个空格;
- 中文技术写作社区通行规范(盘古之白):中英文、中文与数字之间加半角空格。
文件结构
doc-typography-doctor/
├── SKILL.md # 本文件:触发条件与使用方式
├── LICENSE # Apache-2.0
├── scripts/typo_doctor.py # 规则引擎 + CLI(单文件,纯标准库)
├── references/rules.md # 22 条规则的逐条说明、正反例与依据
├── references/cli.md # CLI 全参数、JSON Schema 与集成示例
├── examples/demo-broken.md # 故意写坏的演示文档
├── examples/demo-fixed.md # 自动修复后的对照(由 fix --level info 生成)
└── tests/test_typo_doctor.py # 127 个单元测试与端到端测试
自检
# 技能文档自身应为 0 处问题
python scripts/typo_doctor.py lint SKILL.md references/
# 演示文档是「故意写坏」的对照素材,预期 54 处、退出码 1;不要对它 fix
python scripts/typo_doctor.py lint examples/demo-broken.md
<!-- OB-S:7dS38xvD1u7H6PKA0kG_ng -->
微信扫一扫