# 反向链接与知识图谱

> 从普通 Hugo 链接推导反向链接、局部与全站图谱的三阶段设计草案。

---

LLMS 索引： [llms.txt](/zh/llms.txt)

---

> [!IMPORTANT] G1 已实现，G2/G3 仍是草案
> 2026-08-27 决议 G1 的全部待决问题并接受 G1（静态反向链接）。它已在主题 main
> 分支实现，随 OINK 0.8.0 发布。局部与全站图谱（G2/G3）保持草案状态，等待 G1 的
> 真实使用证据；它们的名称和配置在被接受之前不是公开 API。

## 前提 {#premise}

反向导航与页面连接视图是链接图的属性，不是 `[[wikilink]]` 拼写的属性。Hugo 已经接受普通
Markdown 链接和 `ref` / `relref`。OINK 可以从作者已经在写的内容中派生图谱，无需增加解析器、
Goldmark 扩展或并行创作语法。

首要价值是反向链接，而不是可视化。静态入链列表不需要 JavaScript，在 Print 与 Markdown 中也能
降级。交互图谱应当只是完整列表之上的可选增强。

## 目标与非目标 {#goals-and-non-goals}

目标：

- 每次构建为每种语言派生一份链接索引；
- 在页面上显示确定性的入链；
- 可选显示有界的局部邻接图；
- 可选发布全站视图与机器可读图数据；
- 编辑链接暂时陈旧或不完整时，普通预览仍然可用。

非目标：

- 引入 `[[wikilink]]` 语法；
- 索引外链、`mailto:`、同页锚点或自链接；
- 用 JavaScript 发现正文中已经存在的链接；
- 把可视化变成唯一导航方式；
- 承诺从任意 shortcode 参数或原始 HTML 中完整提取语义图。

## 交付阶段 {#delivery-stages}

| 阶段 | 交付物                       | 运行时                            | 独立价值                           |
| ---- | ---------------------------- | --------------------------------- | ---------------------------------- |
| G1   | 语言内链接索引与反向链接列表 | 无                                | HTML、Print、Markdown 中的反向导航 |
| G2   | 当前页面周围的局部图谱       | 既有 ECharts 加一个小型本地运行时 | 以 G1 为无障碍兜底的空间视图       |
| G3   | 全站图谱页与图数据输出       | 同一运行时                        | 全站探索与机器可读边               |

每个阶段单独验收。G1 不等待 G2，G2 也不会强迫每一页加载图谱代码。

## 提取契约 {#extraction-contract}

提议的索引按语言扫描源码一次，每对来源与目标只记录一条边。它先剥离代码围栏和行内代码，再提取
普通 Markdown 链接与 `ref` / `relref`；随后只解析站内页面，去掉 fragment 以确定页面身份，
排除自链接，并合并重复引用。

实现至少要测试：

- 同一目标的重复链接合并为一条边；
- 围栏与行内代码不产生边；
- 外链、protocol-relative URL、邮件、同页锚点与自链接被排除；
- `ref` 与 `relref` 被纳入；
- 每种语言生成相互独立的图；
- 无法解析的派生边由警告或专项检查报告，但不会让普通 `hugo server` 不可用。

扫描原始源码存在已知遗漏。自定义 shortcode 参数或原始 `<a href>` 中的 URL 可能不会进入图谱。
必须明确记录这种遗漏，不能声称得到完整语义图。

## 反向链接输出 {#backlink-output}

G1 在右栏输出一个 aside 组，与目录、分类标签云并列：目录讲这一页写了什么，反向链接
讲哪些页面指向这一页。该组默认展开，先显示前八条，其余折进原生 disclosure，避免被
大量引用的页面把右栏撑满。开关是站点键 `params.ui.backlinks`（裸布尔，默认关闭），页面用同名去前缀的
front matter 键 `backlinks` 覆盖，section 可以 cascade。排序必须确定：按稳定页面路径
排序——它与语言无关、与导航自然同组，且不需要第二个排序权威。该组使用普通链接；没有
入链时不渲染。

无法解析的派生边被静默丢弃并作为已知遗漏记录在案：G1 是本地导航增强，不是链接检查器，
让它替站点报告断链只会制造重复告警。

Print 与 Markdown 保留可读列表。除非后续 feed 研究证明反向链接能改善文章订阅而不是制造站点导航
噪音，否则 RSS 省略它。

## 交互图谱边界 {#interactive-graph-boundary}

G2 复用本地内置的 ECharts graph series。当前页面是中心，直接入链与出链邻居组成默认深度。硬性
节点上限防止视图不可读或成本失控。键盘焦点、文字替代、reduced motion、forced colors、窄屏和
Print 都是验收要求，不是后续润色。

JavaScript 或 ECharts 不可用时，G1 仍然完整可见。运行时只在真正渲染图谱的页面加载，并进入既有
feature bundle key，避免不同特性页面在资产缓存中撞车。

## 全站输出 {#global-output}

G3 可以新增专用图谱页与 opt-in JSON 输出。JSON schema 包含版本、语言、节点和带稳定 URL 的有向边，
不暴露本机文件路径或未发布页面。它必须和 G1、G2 使用同一索引，避免三种表示各自漂移。

## 兼容与迁移 {#compatibility-and-migration}

普通 Markdown 写法不变，因此无需内容迁移。配置名称继续待定，直到原型证明最小公开面。所有交互
与全站输出默认关闭；静态反向链接列表可以单独讨论，因为它只是本地导航，不涉及网络与浏览器状态。

## 验收标准 {#acceptance-criteria}

验收需要专项 graph 检查器、提取夹具、HTML/Print/Markdown golden、严格构建负向用例、浏览器无障碍
与响应式测试，以及真实双语站构建。性能在有代表性的大站上测量，但带日期的原型耗时不能自动成为
永久预算。

## 待决问题 {#open-decisions}

G1 的问题已全部决议（见决策日志）。仍然开放、属于 G2/G3 的问题：

1. 局部图只暴露一层，还是允许严格限额的第二层？
2. 哪些页面元数据值得进入 graph JSON？
3. 在 G1、G2 获得生产证据前，G3 是否值得新增输出格式？

## 决策日志 {#decision-log}

- 2026-08-19：起草三阶段设计。
- 2026-08-27：决议 G1 并接受，排入 OINK 0.8.0。G1 是 opt-in：站点键
  `params.ui.backlinks` 裸布尔默认关闭，页面覆盖键 `backlinks`，不按 shell type
  区分——策略归站点与页面，不归外壳。排序简化为稳定页面路径单键排序，删去
  「section → weight → 标题」的三级链：单一确定性权威已经满足反向导航，多级排序
  等于第二个导航权威。无法解析的边静默丢弃并记录为已知遗漏，不产生告警。
  G2/G3 与图数据输出继续等待生产证据。
- 2026-08-27：设计评审把这一块从页尾移到右栏。反向链接是页面元数据，与目录成对；
  页尾是读者的收尾区——分享、反馈、出处、翻页、评论。右栏这一组同时引入八条上限，
  其余收进原生 disclosure。

---

反链：

- [提案](/zh/docs/design/proposals/)
