一条 Markdown 内容流水线:lint、白名单与发布门禁
六百多个页面的知识库怎么保证内容质量?一条从源文件到上线的流水线:校验器、标准号白名单、禁词表、锚句锁定,以及'导入不等于上线'的教训。
主站的六百多个百科页面,不是在后台手打的。它们全部来自一条内容流水线:源文件在本地的仓库里,经校验器放行后批量导入上线。这篇拆解这条流水线的设计——为什么一个“写百科”的活需要工程化到这个程度。
为什么必须流水线
工程百科的内容有个致命特性:错误是有后果的。一个数值写错,读者可能拿去做工程判断。所以内容的红线不是“读起来顺”,是“每个论断可追溯、每个数值有依据、每句话不越权”。人肉写作无法系统性满足这个要求,必须靠机器校验兜底。
流水线的四道闸
**第一道:源文件与格式约束。**每个页面是仓库里的一个源文件,头部声明标题、分类等元数据。全部内容进版本管理,谁改了什么可追溯。
**第二道:校验器。**导入前的强制门槛,规则随事故持续加码:结构骨架必须完整;加粗语法用站内约定而不是通用写法(曾因两套语法混用返工);数值区间用半角连接符;禁词表拦截“全文如下”“摘自某百科”这类降低可信度的表述;锚句锁定——几个法律性质的免责句一字不许动,动了即失败。站点上线门槛曾长期是“校验四百六十五页全过”,页数随内容涨,门槛随页数涨。
**第三道:标准号白名单。**工程内容大量引用标准编号,引用错号就是事故。规则是:文中出现的每个标准号必须在白名单里登记过,登记时附官方题录。新引用先登记再使用,漏登记的引用直接校验失败。这个机制把“标准号写错”这类事故在源头上掐灭,白名单本身也成长为一份经过核实的标准清单资产。
**第四道:导入与验收。**导入工具把源文件渲染上线,但这条线上藏着本次要讲的最大教训。
“导入不等于上线”
一批案例页上线后,自查发现:页面导入成功、分类标签也挂了,但分类页的成员列表没有它。深查发现,分类页展示的清单是一份静态生成的数据产物,而重新生成不在导入命令里;同时页面的配图是独立上传的,漏传就是红链。这两个环节都不报错,只有人肉翻分类页才看得见。
教训固化成双自检纪律:每个内容批次交付前,一查图片引用是否全部已上传,二做全分类审计——接口拉取的成员、数据产物的成员、线上可见的成员,三方对账。这套自检后来又抓出二十多条漏项。
顺带一提这条线上另一个阴险的坑:导入工具对目录层级的映射只认第一级,包一层夹层目录,浅层文件就会被导成垃圾标题页——而且深层文件侥幸正确,正确的假象掩盖了错误的一半。规矩随之而来:发布后必须抽查“更新类”页面的实际内容,不能只验新页面能不能打开。
规则是随事故生长的
校验器最初只有骨架与基础格式几条规则,如今的长清单是逐条事故换来的。举三个例子:某次批量改写引入了通用加粗语法,与站内约定冲突,渲染出一片纯文本星号——此后加粗语法进校验;某页数值区间用了全角连接符,检索与比对都受影响——此后连接符全库半角;几次引用了未登记的标准号,核实发现号本身写错一位——此后白名单机制上线。每条规则的注释里都写着触发它的事故,新同事读校验器源码,等于读一部微缩事故史。
这套思路反过来也成立:校验器拦截的每一批失败,都要人工复核是不是误报——误报多的规则要么修正,要么撤下。门禁的权威性来自它既不放走真问题,也不制造假问题。
导入映射的三个变体坑
导入工具的目录映射规则只认相对路径的第一级作为命名空间目录,这个简单规则衍生出三个真实踩过的变体坑。变体一:包了一层夹层目录再导入,深层文件侥幸映射正确、浅层文件被导成带夹层前缀的垃圾标题页——正确与错误各占一半的假象最迷惑人,页面都能打开,错的混在对里。变体二:直接以元数据子目录为根导入,顶层文件丢失命名空间层级,四十四个页面全部变成主命名空间的垃圾标题。变体三:根目录里混着受保护的接口页面目录,导入直接撞保护报错中断。
三个坑的共性是:导入结果必须抽查标题,而且要抽查“更新类”目标页的实际内容,不能只验新页面返回两百。配套的清理姿势也要熟:垃圾页按标题模式列出、逐个删除,数据库层面验证清零。
批量导入后的固定动作
每次批量导入,后面跟着一组固定动作,一个不能少:重建搜索索引(防索引碎片化膨胀,这坑恶化起来以秒计);清程序层缓存(否则线上最多旧一个缓存周期);重新生成站点地图与机器说明文件(新页面要进通道);向各推送通道提交新地址。这组动作曾因一步遗漏返工过——新内容上线半小时,地图里没有它,推送通道也没喂,机器世界对这次更新一无所知。后来它被固化成发布脚本的一部分,脚本跑完输出逐项检查结果,人只看结果页。
沉淀
有人问:为几十个页面搞这套,值得吗?账是这么算的:流水线的成本一次性,收益随页数线性增长;而内容事故的成本——工程读者拿着错数值去做判断——没有上限。这条线上每个看似偏执的规则背后,都站着一次真实的返工。内容质量不是写出来的,是门禁拦出来的。