
上一篇聊了我把 Obsidian 笔记变成了一个网站,现在站点部署完了,我把竞品分析的监测简报推上去,打开一看,列表乱掉了。
本来应该是层级分明的子列表,全平铺成了一排。有些条目前面显示的是短横线,有些是圆点,完全不一致。在 Obsidian 里明明好好的,上网了却崩了。
我以为是渲染引擎的问题
我的第一反应是:是不是哪里没配好,主题或者模板是不是出问题了?翻了一圈没找到原因,然后才意识到,不是渲染配置的问题,是文档本身的问题。
我用 Python-Markdown 来把 .md 文件转成了 HTML。它对格式的要求比 Obsidian 严格得多。同一份文档,Obsidian 能正常显示,Python-Markdown 一解析就出错。
问题根源是:Obsidian 是宽口径,Python-Markdown 是窄口径。
Obsidian 的解析器做了大量容错处理,格式写得稍微不规范也能正常渲染。Python-Markdown 不做容错,按规范来,差一点解析就会出错。
我的文档一直是按"Obsidian 看起来对"的标准在写,从没想过换个工具会不一样。
查出来三个问题
我把问题扔给 AI,它帮我把问题拆成了三类,逐一扫描:
1. Tab 和空格混用
子列表的缩进,有些用的是 Tab,有些用的是空格,甚至同一个文件里混着用。Python-Markdown 对缩进类型极其敏感,Tab 和空格混用时,子列表大概率解析失败,直接变成平级列表。
扫描下来,7 个文件存在这个问题。
2. 子列表缩进不够
Markdown 规范要求子列表至少缩进 4 个空格(或 1 个 Tab),才会被识别为子列表。但我的文档里大量使用的是 2 个空格缩进,2 个空格在 Obsidian 里看起来是子列表,在严格解析器里会被当作和父级平级的内容处理。
这一项修复了 549 处,涉及 49 个文件。
3. 列表前没有空行
这个最隐蔽。Markdown 规范要求列表前必须有一个空行,否则列表会被解析器吞进前面那个段落的 <p>标签里——表面上是列表,实际上没有被识别为 <ul>。
我的文档里有大量「粗体标题紧接着列表」的写法,中间没有空行。Obsidian 容错,显示没问题。Python-Markdown 不容错,列表就消失了。
这一项修复了 265 处,涉及 80 多个文件。
格式对不对,不是"看起来对"
扫完这三类问题之后,我有一个很强烈的感受:
这些问题在文档不离开 Obsidian 时几乎发现不了。因为你一直在同一个工具里看,容错帮你掩盖了所有问题。只有当文档开始流转,换工具、换解析器、换平台,问题才会暴露。
格式不是视觉问题,是结构问题。看起来对,和真的对,是两回事。
这意味着格式规范不能只靠"看起来对",需要写进和 AI 协作的规则里:
缩进统一用 Tab,禁止 Tab 和空格混用。 子列表缩进必须是完整的 Tab 或 4 个空格(2 个空格不够)。 列表前必须有空行,不能紧贴着标题或文本。
现在我已经把这三条写进了 AI 的行为规则里了,每次生成 Markdown,先自检,再输出。
还有一个更大的问题
修完这些格式问题,站点显示正常了。
但这件事让我意识到一个更深的问题:Markdown 有很多方言,不同工具对它的理解不一样。你以为在写通用格式,其实是在写某个工具能读懂的格式。
正好这段时间看到一篇文章,Claude 团队的一个人说,他们内部已经不用 Markdown 了。他们用的替代方案让我很意外,不是换了另一种标记语言,而是彻底换了一个思路。下篇聊这个。
夜雨聆风