Skip to content

docs: clear the remaining 13 dangling in-site anchors across all three locales (#866) - #934

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-866-dangling-anchors
Aug 6, 2026
Merged

docs: clear the remaining 13 dangling in-site anchors across all three locales (#866)#934
yinlianghui merged 1 commit into
mainfrom
claude/issue-866-dangling-anchors

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #866

清掉 content/docs 里剩余的悬空站内锚点。全仓三语重扫:修前 13 条悬空,修后 0 条src/ 零改动,content/docs/releases/ 未触碰。

一、重验先行:面从 17 缩到 13

立单基线 ed6885e2 已陈旧,按 issue 的测法在 origin/main (4855d50) 上重扫,4 处已被本轮并行 PR 修掉,从本单剔除:

issue 清单里的位置 现状 谁修的
service/cases.zh-Hans.mdx:89 #case-escalation 已去锚,现为 [工单升级流程](/zh-Hans/docs/service/sla-and-escalation) PR #922
service/cases.zh-Hant.mdx:89 #case-escalation 同上 PR #922
service/index.zh-Hans.mdx:30 #case-escalation 该链接已随正文重写移除 PR #913
service/index.zh-Hant.mdx:30 #case-escalation 同上 PR #913

另有行号漂移(不影响内容):A 类三处由 sla-and-escalation.*:95 移到 :113(经 #918 / #924 两轮改动)。剩余 13 处逐条复测确认仍然悬空,即本 PR 的全部面。与 #912 / #927 / #928 三个并行单的文件面零交集

二、测法本身被证伪了一条:{#id} 不是 fumadocs 的显式锚点写法

issue 正文的测法段落写着「显式 {#id} 优先」,派单裁定也按这条给了 ### 🚦 Case Triage {#case-triage} 的例子。实测(fumadocs-core 16.9.3 的 remarkHeading,不是推断)这条是错的:

标题源码 生成的 id 渲染出的标题文字
### 🚦 Case Triage -case-triage 🚦 Case Triage
### 🚦 Case Triage {#case-triage} -case-triage-case-triage 🚦 Case Triage {#case-triage}
### 🚦 Case Triage [#case-triage] case-triage 🚦 Case Triage

更要紧的是:.mdx 里的 {#case-triage} 会被当成 JSX 表达式送进 acorn,#case-triage 不是合法 JS 表达式,整页解析直接失败:

[140:56: Could not parse expression with acorn]
  source: 'micromark-extension-mdx-expression'

也就是说,按裁定原样写 {#id} 不只是渲染出一段字面垃圾,而是把这一页的构建打挂。本 PR 因此一律用 [#id]。同时把一次性重扫脚本从「自己复刻 slug 规则」改成直接调用 fumadocs 自己的 remarkHeading 读它吐出的 TOC,不再有第二套规则可以跑偏 —— 这一点建议同步进 #867 的实现约束(那张单目前只写了「必须用同一个 github-slugger」,不足以覆盖显式 id 与 MDX 解析)。

顺带整树验证:content/docs 全部 198 页在改后均能通过 MDX 解析(失败 0)。

三、逐处取舍

A 类(emoji 标题导致前导连字符 slug)—— 3 处

en 侧保留锚点,给目标标题加显式 id:content/docs/ai-copilot/skills.mdx### 🚦 Case Triage 改为 ### 🚦 Case Triage [#case-triage]。emoji 被 slugger 删掉但它后面那个空格仍变成连字符,所以「显而易见的」#case-triage 永远解析不到;加显式 id 之后作者的直觉写法成立。只加 id,标题文字一字未动。 zh 两处(sla-and-escalation.zh-Han{s,t}.mdx:113)按裁定去锚只链页面。

B 类之一(标题后来长了)—— 3 处

en 侧同样加显式 id:content/docs/guides/import-and-export.mdx### Scheduled export to a warehouse (not shipped yet) 改为 … [#scheduled-export],正是 performance-and-limits 一直在用的锚点;标题当初长出「(not shipped yet)」后缀时链接没跟上,加 id 之后这个锚点对未来的标题改动也免疫了。zh 两处去锚。

B 类之二(#sales-dashboard 与标题不同名)—— 3 处,含 en

这一处 en 侧也去锚,是本 PR 唯一偏离「en 优先加显式 id」的取舍,理由是实测出来的硬约束而非偏好:

  1. 三语 analytics/dashboards 页都没有 Sales Dashboard 这个标题。产品里 sales_dashboard 是该仪表盘的元数据 name(src/dashboards/sales.dashboard.ts:21),它的 label 是 Sales Performance —— 锚点当初是照 name 拼的,而文档小节标题用的是 label。

  2. 给这个标题加显式 id 会打挂现有守卫test/docs-drift.test.ts:383headingLabel() 只剥掉标题开头的非字母字符(^[^A-Za-z]+),尾部的 [#id] 会留在里面,于是 ## 📈 Sales Performance [#sales-performance] 不再等于 dashboard 的 label。做过一次红/绿实测,方向与预测一致:

    × every registered dashboard has a section on the page
    AssertionError: content/docs/analytics/dashboards.mdx has no section for: Sales Performance.
    Test Files  1 failed (1)   Tests  1 failed | 33 passed (34)
    

    {#id}[#id] 两种写法都试过,都是这条红;实验后已 git checkout 复原,本 PR 不含该改动。

  3. 现存真实 slug 是 -sales-performance(前导连字符),裁定明确要避开。

三条路都被堵死,所以三语一致去锚指向 dashboards 页 —— 该页开头的「五个仪表盘」表格正是销售经理第一屏需要的导航,📈 Sales Performance 就在第二行。链接文字 Sales Dashboard 未改:它是 src/pages/home.page.ts:89 的首页组件标题,是产品里真实存在的字符串,不是笔误。

C 类(zh 页沿用英文锚点)—— 剩余 4 处

marketing/campaign-members.zh-Han{s,t}.mdx:14sales/opportunities.zh-Han{s,t}.mdx:148,按裁定去锚只链页面,与 #755 / #762 / #749 / #913 / #922 五次先例一致。administration/sharing-and-security 现存的本地化锚点(#字段级安全)是活写法,保留不动、未扩散

四、归零重扫

脚本用 fumadocs 自己的 remarkHeading 解析目标页 TOC,一次性使用,已删,未入库。

### 修前 (origin/main 4855d50b)
scanned files: 198
anchored in-site links: 29
dangling: 13

### 修后
scanned files: 198
anchored in-site links: 18
target pages parsed: 11, heading ids extracted: 162
dangling: 0

other link forms carrying #anchor (href=/url=/reference-style): 0

heading ids extracted: 162 是防空转的计数:解析不到标题的空扫描同样会报 0 悬空。issue 说的「其它链接形式全仓零命中」本次复测仍然成立。

站内锚点正确性由这次重扫承担 —— CI 的 link-check 只扫 .md 不扫 .mdx,对产品文档实际空转(#867 已记这条)。

五、门禁

六道全绿(共享锁内串行):

EXIT(validate)=0   EXIT(typecheck)=0   EXIT(lint)=0
EXIT(hygiene)=0    EXIT(build)=0       EXIT(test)=0
Test Files  70 passed (70)
Tests  1602 passed | 1 skipped (1603)

hygiene 含控制字节扫描(✓ no raw control bytes in first-party files),另做过一次改动文件的 grep -naP 自扫,无命中。#919 守卫读的 state-machines 列表项本次未触碰,已单跑 status-state-machines / docs-drift / docs-object-coverage / skills-integrity 四个最近的守卫复核:101 passed。

未起 dev server。


Generated by Claude Code

…e locales (#866)

Two English links keep their anchor and the target heading gained an explicit
id (`[#case-triage]` on ai-copilot/skills, `[#scheduled-export]` on
guides/import-and-export). Eleven links drop the anchor and point at the page:
the nine Chinese ones because their target headings are translated, and the
three `#sales-dashboard` links because no dashboards page has a heading by that
name in any locale.

Measured with fumadocs-core 16.9.3's own remarkHeading rather than a
reimplemented slug rule: 13 dangling before, 0 after.
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 6, 2026 10:13am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

content/docs 还剩 17 处悬空锚点(全仓实测),三类新成因:emoji 标题、标题后来加了后缀、zh 页沿用英文锚点

2 participants