ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Vale:用自然语言Linter让文档检查像代码审查一样自动化

2026/8/30 12:51:56 拓冰建站 浏览量
Vale:用自然语言Linter让文档检查像代码审查一样自动化 代码写完后过一遍 lint这是工程团队的肌肉记忆。可轮到文档、README、API 说明很多团队又退回人肉检查。Vale 是一个开源的自然语言 Linter它把写作规范变成可执行的检查流程。我第一次用 Vale 跑自己的博客文章看到一排告警后有点愣住原来我反复混用“点击”和“单击”、“例如”和“比如”自己完全没有察觉。后来我意识到Vale 真正解决的从来不是“帮你把文章改好”——它没这个能力也不会假装有这个能力。它解决的是另一件事把写作规范变成像代码规范一样可维护、可复用、可自动执行的工程资产。这一点比它检查出来的每一处问题都重要。1. 代码有 Lint文档为什么没有1.1 文档不规范通常不是“人不认真”技术团队里最常见的文档问题是这一类README 里一会儿写 “Spring Boot”一会儿写 “spring boot”API 说明里同一个参数名三种大小写发布公告里“点击”和“单击”随机出现。这些不是低级错误而是长期没有统一检查手段的自然结果。人肉 review 的局限很明显。每个 reviewer 只能靠记忆去核对规则记不全标准也会漂移。新同学不知道团队历史上约定过什么写出来的东西自然会和旧文档不一致。更麻烦的是文档问题不像编译错误那样当场报错它会积累成一种“延迟债务”用户因为术语不一致产生困惑客户因为产品名拼法不统一觉得不专业支持团队反复解释同一个问题。所以一个团队文档规范没落地往往不是态度问题而是没有一个机制让规范真正被执行。1.2 Vale 想补的不是“编辑”而是“检查流程”Vale 定位很独特。它不是 Grammarly 那种写作助手不会给你整句改写建议它更像一个编译器前端的检查器或者代码世界里的 eslint、golangci-lint。你给它一份 Markdown、AsciiDoc、reStructuredText 或 HTML 文档它按配置好的规则输出结构化告警告诉你哪一行、哪一列、什么级别、什么消息。这个定位决定了它的使用方式。它不是某个编辑的个人审美而是一个团队共同认可的“检查基线”。一旦规则文件被提交到仓库里它就变成了一种自动化的流程约束不需要有人在群里喊“注意大小写”不需要新人靠猜来学习风格规范。2. 拆开 Vale 的设计骨架它不是正则扫描器2.1 解析器先行先理解文档再检查文字Vale 经常会被称为 “syntax-aware linter”这个“语法感知”很关键。它不是简单地把文档当成纯文本正则扫一遍而是会先解析 Markdown、AsciiDoc、reStructuredText、HTML 这些标记语言的结构再针对正文内容执行规则。这个设计带来的实际差别非常明显。代码块里的英文变量名、URL 链接、行内代码、命令行示例都不应该被当成普通正文来检查。如果工具不理解文档结构它就分不清“这一行是正文里的英文句子”和“这一行是代码块里的函数名”。Vale 把结构解析放在前面这让它在技术文档场景里能长期稳定使用而不是只在纯文本博客上好看。2.2 规则以“样式包”形态沉淀Vale 的规则不是散落在配置文件里的一条条临时正则。它要求你把规则组织成“样式包”。在配置里指定一个StylesPath目录里面每个子目录就是一个样式包每个样式包由若干 YAML 文件组成。每个 YAML 文件定义一条或一组检查规则。你可以把这套结构理解成依赖管理。团队可以基于社区维护的公共样式包起步再叠加自己私有的规则包。规则越积越多它就不再只是几份配置文件而是团队写作知识的格式化表达。比如“不要用‘点击’统一用‘选择’”这句话如果只写在规范文档里大概率会被遗忘如果写成一条 substitution 规则它就会在每次检查中生效。2.3 配置、告警级别与输出方式Vale 的核心配置是一个.vale.ini文件语法接近 INI 格式。里面指定StylesPath、MinAlertLevel以及针对不同文件后缀的规则组合。MinAlertLevel用来控制告警门槛取值为 suggestion、warning、error 之一。CI 里想只拦截严重问题可以把门槛提到 error日常本地检查想看完整列表就保留 suggestion。输出方面默认是逐条告警包含文件路径、行号、列号和消息。给 CI 解析时也可以让 Vale 输出 JSON 格式。这些细节组合起来它很像一个真正的编译工具链输入文档输出结构化告警。3. 从零跑通一次 Vale 检查3.1 安装能跑起来就行Vale 是 Go 写的发布的是单个二进制文件没有运行时依赖。macOS 上常用 Homebrew 安装Windows 上可以从 GitHub Releases 下载二进制或者用对应的包管理器。安装完先跑一下vale --version能正常输出版本号说明二进制没问题。这里不需要等团队统一安装先在自己机器上用一个文件试起来。3.2 最小目录和第一个规则一个最小的 Vale 项目只需要两个部分.vale.ini和一个样式目录。结构大致如下my-docs/ ├── .vale.ini └── styles └── TeamDemo └── Terms.yml.vale.ini里面先写最基础的内容StylesPath styles MinAlertLevel suggestion [*.md] BasedOnStyles TeamDemo然后在styles/TeamDemo/Terms.yml里写一条最简单的替换规则extends: substitution message: 倾向使用 %s 而不是 %s level: warning ignorecase: true swap: 点击: 选择 例如: 比如这条规则的含义是在 Markdown 文档的正文里遇到“点击”就提示换成“选择”遇到“例如”就提示换成“比如”。准备一份测试文档# 安装指南 1. 点击开始安装。 2. 例如你可以先查看日志。然后执行vale README.md你会在输出里看到带行列号的告警。这里建议把级别先设为 warning 而不是 error目的是先让问题可见再由团队决定哪些级别要阻止合并不要一上来就用最严格的配置。3.3 先跑单文件再看批量这里有一个重要建议先用一条样例文件把输入、输出、日志都确认正常再考虑扩大到整个目录。不要一上来就扫全部历史文档。存量文档往往积压了大量问题一次全量运行只会让告警列表变成噪音也会让团队产生“这个工具不靠谱”的错觉。注意不要一上来就把整个历史文档目录全部扫一遍。先用一个文件把输入、输出和日志都跑通再考虑扩大到批量目录。4. 规则体系从用词到整篇可读性4.1 常用规则类型Vale 的规则体系不是只有“替换词”这一种。按常见使用频率可以分成下面这几类规则类型它检查什么典型场景existence某类词是否出现禁止“众所周知”“显而易见”等套话substitution用 A 替换 B统一术语、规范动作动词capitalization大小写规则“Spring Boot”不被写成“spring boot”spelling拼写异常配合团队词汇表识别专有名词sequence多个词出现的顺序步骤里“首先 → 然后 → 最后”conditional出现 A 就必须出现 B提到“安装”就应给出“配置”readability句子复杂度长难句给出调整信号existence 规则写起来很简单extends: existence message: 避免使用 %s level: suggestion ignorecase: true tokens: - 众所周知 - 显而易见conditional 规则适合约束文档结构。比如你希望一篇安装文档里只要出现“安装”就必须出现“配置”因为缺了配置步骤用户装完也不知道下一步做什么extends: conditional message: %s 后面应包含 %s level: warning first: 安装 second: 配置这些规则类型的意义在于它们把“写作约定”从人脑记忆变成了机器可读的形式。团队里最有争议的往往不是“这个词对不对”而是“我们到底要统一成哪个词”。一旦把这个决定写进规则文件讨论就结束了。4.2 Vocab 词汇表沉淀组织专有名词拼写类规则刚上手时容易误报尤其是产品名、内部项目名、品牌专有名词。Vale 提供了词汇表机制来解决这个问题。你在styles/Vocab/下建一个目录名称在.vale.ini里通过Vocab配置指定。目录里的accept.txt放“必须接受”的词reject.txt放“必须拒绝”的词。这个机制相当于给团队做了一本“官方拼法字典”。产品名、API 名、专业术语放进去之后拼写规则就不会再对它们报错。团队新同事写文档时也不需要去翻规范文档确认某个内部项目名到底怎么写工具会直接告诉他。4.3 样式继承与团队私有包.vale.ini里的BasedOnStyles可以写多个样式包既可以引社区维护的公共样式包也可以引团队私有规则包。公共样式包帮你建立通用基线私有规则包表达团队自己的约定两者叠加使用。不过这里要提醒一点样式包叠加得越多告警重合和优先级问题越容易出现。实际落地的经验是先少而精公共样式包只选最贴合团队风格的私有规则包从三五条最关键的开始跑一段时间后再逐步增加。规则多而混乱最后只会逼着大家关掉整个工具。5. 把 Vale 放进真实工作流5.1 本地写作编辑器里的即时反馈命令行检查是最小的使用方式但真正的体验提升来自编辑器集成。VS Code 等编辑器有 Vale 相关扩展会在你写作过程中直接把告警标注在文档里类似编辑器对代码的实时纠错。这样你不需要等 CI 跑完才知道问题写完一个段落就能看到。使用编辑器集成时要注意一点扩展会读取当前工作区的.vale.ini如果你打开的是单个文件而不是项目目录它可能找不到配置。把.vale.ini和styles/放在工作区根目录下体验会稳定很多。5.2 CI文档检查成为合并卡点把 Vale 放进 CI是让它从“个人工具”变成“团队流程”的关键一步。常见做法是写一个 CI 任务对文档目录执行vale docs/然后根据返回状态决定是否阻止合并。实际工程里建议先用--minAlertLevelerror只让 error 级别问题阻塞流程等规则运行稳定了再把 warning 也纳入拦截范围。另一个常见实践是只检查本次变更的文件而不是全量检查所有历史文档。代码 review 是看 diff文档 review 也可以看 diff。如果某次 PR 只改了一个段落把整本手册全部重新扫一遍意义不大还容易把历史问题混进本次变更。5.3 存量文档分级收口而不是一次拉满针对一个已经积累了几百篇文档的仓库我把落地路径总结成三步收口法只对新增或修改的文件开启检查让新内容先符合规范。规则级别先以 suggestion、warning 为主观察命中情况别急着上 error。稳定运行两到四周后选择核心目录开启 error 门槛再逐步扩展到其他目录。这样做的原因是规范的落地本质上是一次行为改变不是一次技术部署。全量扫一遍很容易但让团队在一次次 PR 里接受告警、调整写作方式才是真正难的部分。分级收口能降低反弹也能让积累的规则逐渐变成团队共识。6. 落地时最容易踩的坑6.1 误报不是 bug是配置边界问题初用 Vale 时最常见的抱怨是“它把我的代码块也检查了”。这通常不是工具坏了而是配置没有告诉它哪些内容要跳过。代码块、行内代码、URL 和命令示例是最常见的误报源。Vale 提供了一些配置项来处理这类边界比如BlockIgnores和TokenIgnores可以用正则把命中的内容排除在检查范围之外。常见写法类似[*.md] BlockIgnores (?s) *.*? * TokenIgnores https?://[^\s]这段配置的意思是让 Markdown 代码块不被整体检查让 URL 不被当作普通词检查。实际落地时正则需要根据你文档里的具体写法调整。另外要记住Vale 的很多内置规则面向英文写作。中文没有“大小写”概念针对英文的 capitalization 规则在中文技术文档里要控制权重不然会产生大量没有实际意义的告警。6.2 排查链路按层定位问题当 Vale 表现异常时我一般按这个顺序排查而不是直接改规则看现象是误报、漏报还是命令本身没有执行成功。看输入文件扩展名是否匹配.vale.ini里的 section文件编码、BOM、换行是否异常。看配置StylesPath路径是否正确BasedOnStyles名称是否拼错Vocab是否开启。看规则YAML 缩进是否正确extends类型名是否合法level是否在允许范围内。看版本不同版本的 Vale 对个别规则字段的支持有差异升级前先看变更说明。看输出用--outputJSON拿到结构化信息排查会比看纯文本方便很多。这个顺序的核心思路是先确定问题出在哪一层再决定改哪里。很多人一遇到误报就删规则结果删掉的是真正有价值的检查问题反而没解决。6.3 别把告警数量当 KPI告警数量多不代表文档质量差告警数量少也不代表规则有效。如果一条规则长期没有命中先想想它是否真的适用如果一条规则命中极多反而要警惕它可能产生了大量“不想改”的噪音。我建议定期看规则命中分布。把命中最高的几条规则拿出来人工复核判断这些告警是真正推动了规范还是只是在刷存在感。规则少而准永远好过规则多而吵。宁可规则少而准不要规则多而吵。7. 适用边界与长期价值7.1 Vale 适合谁不适合谁Vale 不是万能工具。适合和不适合的场景都很清楚适合不适合维护 README、API 文档、发布说明的技术团队需要深层语义理解或改写建议的写作场景有内容规范但靠人记不住的团队没有风格基线、自由创作高于一致性的个人博客已经有 CI 流程、想加入文档检查的工程团队期望工具自动“理解”一句话好坏的中文语义场景需要统一产品术语、品牌名词的团队认为编辑判断可以被规则完全替代的团队特别是中文场景Vale 更适合做“词级、术语级、结构级”的检查而不是“这句话写得好不好”的语义判断。不要期待它像一个中文编辑那样理解你的行文逻辑它真正擅长的是做一致性和规范性检查。7.2 长期来看它改变的是写作规范的“版本化”如果把视角拉长Vale 最值得关注的不是某条规则而是它让写作规范第一次有了“版本化”的能力。规范一旦写成规则文件就能像代码一样被 review、迭代、审计。团队讨论某个文档问题时讨论焦点也会发生变化从“我觉得你不该用这个词”变成“我们是不是该新增一条规则”。这个转变比省几分钟人工 review 重要得多。新同事加入时不靠背规范工具会提醒对外发布时不靠某个编辑把关流程会兜底。文档写作从个人经验变成团队资产的路上Vale 是很扎实的一步。所以如果你问我 Vale 到底值不值得引入我的回答是值得但别把它当成改稿工具。它更像一面镜子让你第一次清楚看到团队的写作规范到底有没有被遵守。真正想用好它第一步不是下载安装而是先问自己我们团队最重要的三条写作规则是什么把这三条写成规则文件再用 Vale 跑一个文件你会立刻看到它和普通文档检查的差别。