markdown

前面3个` {include} file.md
  • 测试引用
    我是引用

ok

有些人活着,他已经死了

ok

有些人活着,他已经死了.

  • 测试链接

图片

fishy

列表

  • 代办事项 代办事项不同于restructed的TODO, 它可以展示完成未完成的状态. restructed不支持这个特性

    • todo

    • done

待处理

TODO

备注

TODO

图表

end是group里的end,不能随便用

流程图

通过:::可以设置类, (){},<>,>/,可以设置框外观
通过subgraph可以添加组

        flowchart TB;
    Start --> check{校验是\n否橙色}
    Start ~~~ 隐藏的线
    check --> |是| orange:::orange
    check --> |否| red:::red
    red & orange --> tooltip --> End
    subgraph "tooltip"
        a --> b
        b --> c
    end
    classDef orange fill:#f96
    classDef red color: #f00
    

稳定锚点: 防止外部链接失效 {#stable-anchor}

问题

很多渲染器默认按标题出现顺序生成锚点(#id22 这样)。文档里增删一个标题, 它后面的所有锚点重新编号, 指向它们的的外部链接全部失效。

三种锚点的稳定性对比:

锚点类型

例子

增删其他标题时

修改标题文字时

是否可控

顺序号

#id22

全部移位

侥幸不变

不可控

文本 slug

#需求编号与优先级

稳定

失效

不可控

手工锚点

{#req-structure}

稳定

稳定

完全可控

方案一: 给被外链的标题手工指定锚点(最可靠)

MyST / Pandoc 语法, 本项目已启用 attrs_inline, 可直接用:

## 需求编号与优先级 {#req-structure}

GFM(GitHub 等)不支持 {#id} 语法, 用内联 HTML, 几乎所有渲染器都会保留:

<a id="req-structure"></a>
## 需求编号与优先级

规则: 对外只链接手工锚点, 自动生成的锚点永远不进入 URL。

方案二: 锚点即接口, 发布后 immutable

  • 手工锚点一旦发布, 不改名、不删除; 标题文字随便改, 锚点不动;

  • 章节废弃时保留空占位 <a id="old-anchor"></a>, 而不是直接删掉;

  • 新增锚点只加不改, 旧链接自然一直有效。

方案三: 渲染器能配就配成文本 slug 模式

  • Sphinx/MyST: myst_heading_anchors = 7(本项目 conf.py 已配置), 锚点由标题文字生成, 与出现位置无关, 增删标题不再连锁失效; 手工 {#id} 优先级更高, 两者可共存;

  • GitHub/GitLab 天然就是文本 slug;

  • 如果发布平台强制 #id22 且提供配置, 找 slug / permalink 类的开关;

  • 如果平台既强制顺序号、又剥离自定义 HTML 锚点, 锚点层面无解, 用方案四缓解。

方案四: 平台不可救时的缓解

  • 外链尽量指向文件而不是标题: doc.md 比 doc.md#id22 活得久;

  • 大文档拆小, 让"指向某小节"变成"指向某文件";

  • 发布时用脚本导出"标题 → 锚点"映射, 外部链接由脚本批量生成, 编号变了也能整体重刷。

方案五: 内部链接自动化检查

外链的稳定性只能靠上面的"锚点契约"保证, 内部链接可以让工具把关:

  • sphinx-build -b linkcheck . _build/linkcheck 检查外部 URL 可达性;

  • MyST 对失效的内部锚点引用会发出 myst.xref_missing 警告——本项目 conf.py 里把它 suppress 了, 想启用检查就从 suppress_warnings 中移除。