Markdown 目录自动生成前,先把标题锚点规则定死
很多人第一次做 Markdown 目录自动生成,注意力都会放在“怎么把标题列出来”上。真到了文档越来越多、开始需要分享链接和长期维护的时候,问题往往不是目录能不能生成,而是同一篇文章在编辑器预览、导出的 HTML、线上静态页里,标题锚点是不是完全一致。
目录能生成,不代表链接一定稳定
只要能拿到标题层级,生成目录并不难。真正让人头疼的是这些细节:标题里有空格怎么办,重复标题怎么编号,中英文混排时特殊字符怎么处理,后来改了标题大小写是不是整篇旧链接都失效了。
如果这些规则交给不同工具各算各的,目录虽然都有,跳转结果却可能完全不一样。编辑器里点得开,发布后却跳不到;文章内部没问题,搜索结果里的深链接又失效。问题一旦落到用户身上,就会感觉这个站点“不太可靠”。
先统一 slug 规则,再谈目录样式
我后来更愿意把标题锚点当成一套独立规则来维护,而不是某个插件顺手帮我算出来的副产品。至少要先定清楚三件事:
- 标题文本经过什么清洗后参与生成
- 重复标题的后缀策略是什么
- 历史文章是否允许锚点规则中途变更
这样做的好处是,目录组件、正文标题渲染、搜索索引里的标题字段,都可以共用同一份结果。哪怕以后替换 Markdown 解析器,也不会把旧链接全部推倒重来。
编辑器预览和发布链路最好走同一套插件顺序
很多锚点错位,其实不是算法不同,而是处理顺序不同。比如编辑器预览先跑了一次标题增强,再跑目录;导出脚本却是先扫原始标题,再单独改写 HTML;线上页面又额外加了一层标题组件。最后每一边都“看起来合理”,合起来就乱了。
比较稳的做法,是让标题提取、锚点生成、目录注入尽量在同一条流水线上完成。哪怕你不能完全复用代码,也至少要复用配置和测试样例。这样有人改了规则,能马上看到是整个链路一起变,还是只有某一环偷偷跑偏。
给锚点准备一组容易出错的回归样例
我现在更愿意提前准备几类标题做回归检查:重复标题、纯英文标题、带括号和符号的标题、数字开头标题、中英文混排标题。只要这几个例子在预览、导出和线上都能稳定跳转,目录系统通常就不会太脆弱。
目录自动生成看起来像是个展示层功能,但锚点稳定性其实更像内容基础设施。先把规则定死,再去挑哪个 TOC 样式顺眼,后面的维护成本会低很多。
