feat(scripts): check-doc-links 两向扩展 —— 扫描面扩到 examples/** 与根 README,自仓 GitHub URL 离线校验 - #3542
Merged
Merged
Conversation
`check-doc-links` 原本只看 `content/docs`,且按 scheme 跳过所有 https 链接。 两个已有实证的盲区因此各自积累过死链,本次一并补上(objectui#3536)。 ## 扩展一:扫描面 → `examples/**` + 根 `README.md`,但用另一套规则 关键不是"多扫两个目录",而是**这两组文件的链接语义根本不同**:它们在 GitHub 上 被阅读,相对链接是**磁盘路径**,不是 fumadocs 路由。因此新增按扫描根分流的 `SCAN_ROOTS` 表,`disk` 规则只问"存在与否": - 目录(`./packages/core`)、非 markdown 文件(`./vite.config.ts`)、无扩展名文件 (`./LICENSE`)都是合法目标 —— docs 规则的 `routeCandidates()` 在这里没有意义; - 没有"collection"可逃逸 —— console-starter 的 README 链到 `../../packages/...` 和 `../../content/docs/...` 都能正常渲染,唯一的边界是仓库根; - markdown 文件的无扩展名写法在 docs 规则下放行(浏览器可能解析),在 GitHub 上 却是实打实的 404,故 `disk` 规则不放行。 把 docs 规则硬套到这两组文件上会误报 **61 条**当前渲染正常的链接(已实测,见 PR 正文)。 绝对 `/...` href 判为拒绝(`example-absolute`):这两组文件里目前一条都没有,属预防性, 但方向是渲染器决定的 —— GitHub 把开头的 `/` 解析到 github.com 而非本仓, 根 README 里的 `/packages/core` 指向 https://github.com/packages/core。 ## 扩展二:`.../(blob|tree)/main/<path>` 的离线路径校验 这类"写成外链的仓内引用"卡在两个门禁之间:本脚本按 scheme 跳过,lychee 是 周 cron + continue-on-error 不 gate PR,曾有两条死了约三个月(#3507)。现在在 **所有**扫描面校验其路径存在于工作树 —— 包括 `content/docs`,因为 `escapes-collection` 的提示本就推荐这种写法,不校验等于推荐一种没人管的形态。 刻意收窄:只认 `main`、只认本仓、只认路径(`#fragment` 不在范围)、只认 blob|tree (`/issues` 与 badge URL 是 github.com 站内路由,继续跳过)。 ## 其他 - `collectBrokenLinks(repoRoot)` 改为只收仓库根:调用方无法再配置掉某个扫描面或 `apps/site` 真源而得到一个"其实什么都没看"的绿。CLI 的仓库根由脚本自身位置推导, 避免从子目录运行时扫不到东西却报成功。 - 新增三个 reason 与对应 HINTS:`example-relative` / `example-absolute` / `self-repo-url`;新增测试覆盖两向扩展的拒绝类与放行类,并含两条规则的对照用例。 - 按 AGENTS.md #2 就近更正 `ci-cd-pipeline.md` 中已被本次改动证伪的描述。 Fixes #3536 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
在 markdown 表格的 code span 里写 `blob\|tree` 依赖转义竖线的渲染行为, 不同渲染器结果不一致。拆成 `blob/main/` 与 `tree/main/` 两个 span,语义不变。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
This was referenced Aug 7, 2026
yinlianghui
marked this pull request as ready for review
August 7, 2026 04:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3536
PR #3506 在头注释里明确列了两个"没有买"的面,各自已有实证需求。本 PR 一并买下,并把那段声明按事实重写。
扩展一:扫描面 →
examples/**+ 根README.md(用另一套规则)关键不是"多扫两个目录",而是这两组文件的链接语义与
content/docs根本不同:它们在 GitHub 上被阅读,相对链接是磁盘路径,不是 fumadocs 路由。所以新增按扫描根分流的SCAN_ROOTS表,disk规则只问"存在与否":content/docs(docs规则)examples/**、根 README(disk规则)routeCandidates()命中./packages/core、./vite.config.ts、./LICENSE)escapes-collection拒绝把 docs 规则硬套上去会误报 61 条当前渲染正常的链接 —— 这不是推测,是实测(见下方逆向验证 C)。
绝对
/...href:判为拒绝(example-absolute)。这两组文件里目前一条都没有,属预防性;方向是渲染器决定的 —— GitHub 把开头的/解析到 github.com 而非本仓,根 README 里的/packages/core会指向https://github.com/packages/core。提示里同时给出两种修法(写成相对路径,或真想要 github.com 就写全 URL),因为罕见的"故意写 github.com 路径"是真实存在的。默认放行才是 #3490 花 18 条 404 才拆掉的那种静默豁免。扩展二:本仓
(blob|tree)/main/GitHub URL 的离线路径校验这类"写成外链的仓内引用"卡在两个门禁之间(#3507):本脚本按 scheme 跳过,lychee 是周 cron +
continue-on-error,不 gate PR。两条曾死了约三个月。现在在所有扫描面校验其路径存在于工作树 —— 包括content/docs,因为escapes-collection的提示本就推荐这种写法,不校验等于推荐一种没人管的形态。刻意收窄(其余离线不可判定):只认
main(tag/sha 指向别的 ref)、只认本仓(别人的仓归 lychee)、只认路径(#fragment不在本单范围,校验前剥离)、只认blob|tree(/issues与workflows/.../badge.svg是 github.com 站内路由,继续跳过)。真实仓运行:零新红(与预测一致)
#3507 的 25 目标复扫已重跑(该 issue 评论区的 one-liner,对本分支 HEAD):27 个不同目标全部 OK,零死链 —— 即 #3506 新引入的 8 条同形态链接全部是活的,与 #3509 清零后的预期一致。目标数从 25 涨到 27,是 #3506 新增
examples/console-starter、packages/core、packages/react,同时 #3509 移除了examples/crm、examples/todo。逆向验证:先预测方向,再跑
三组,都事先写下预期再执行:
A. 删掉
SCAN_ROOTS里的两个 disk 根(等于撤销扩展一) → 预测 12 红,实测 12 红。accepts a directory...、accepts a relative link that leaves the example、leaves external URLs alone、does not walk into an example dependency tree)在此变异下依旧绿 —— 不是因为逻辑对,而是因为整个面没被扫,断言[]拿到[]。这正是"因为什么都没产出所以通过"的陷阱。挡住它的是专门加的really scans every surface in SCAN_ROOTS这条(变异下第一个红),它直接断言三个扫描根各自真的收到了文件。这条测试的存在理由就是这个,不是凑数。B. 删掉
judgeHref里的 self-repo 分支(等于撤销扩展二) → 预测 5 红,实测 5 红。同样地,放行类测试空绿;exposes selfRepoPath(纯单元)与has no dead self-repo GitHub URLs(直接复扫,不走门禁接线)按设计保持绿 —— 后者是把 #3507 的人工 one-liner 固化成断言,故意独立于门禁接线。C. 把 disk 面强行改判为
docs规则(检验"分流"本身是否承重) → 预测真实仓测试转红,实测:12 条测试红,含
has no broken internal links in any scanned surface。这是分流规则承重的硬证据:是真实内容上的 61 条误报,不是 fixture 造出来的。顺带的两处设计收紧
collectBrokenLinks(docsRoot, siteRoot)→collectBrokenLinks(repoRoot)。调用方不再能配置掉某个扫描面或apps/site真源,拿到一个"其实什么都没看"的绿;SCAN_ROOTS是唯一的"检查了什么"清单。仅测试文件引用此函数,无其他调用方。collectFiles现在对不存在的根返回[],cwd 相对根会让"从子目录运行"变成扫不到东西却报成功 —— 假绿是这个门禁唯一不能有的失效模式。文档更正(AGENTS.md #2,主动披露)
content/docs/guide/ci-cd-pipeline.md两处被本次改动证伪,做了最小事实更正:第 253 行"walks every.md/.mdxfile undercontent/docs/"与第 309 行表格里"Internal links incontent/docs/"。改为如实描述三个扫描根、两套规则,以及跨面生效的自仓 URL 校验。未动content/docs/releases/。验证
pnpm exec vitest run scripts/(仓库根,flock,--maxWorkers=2)check-doc-links.test.tsnode scripts/check-doc-links.mjspnpm type-check:scripts@ts-expect-error)pnpm exec eslint(改动的 script/test)node scripts/check-control-bytes.mjs无 changeset:脚本/CI 门禁,非发布包(#3506 先例)。
越界记录
扫描过程中在扫描面之外发现 3 条真实死链(
CONTRIBUTING.md2 条、ROADMAP.md1 条)。按 Prime Directive #10 未在本 PR 修复,另立 issue。#3533 在飞的runner.mdx/objectos-integration.mdx本次扫描未flag任何内容,无冲突。🤖 Generated with Claude Code
https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Generated by Claude Code