Uh oh!
There was an error while loading. Please reload this page.
fix(docs): 非 /docs 绝对链接按站点路由校验,并修掉 18 条真实 404 (#3490) - #3506
Merged
Conversation
…s, and fix the 18 live 404s `check-doc-links.mjs` asked "does a file exist?" when the only question that matters is "does the site serve this URL?". Two waivers followed from that: a non-`/docs` absolute href was waved through unchecked, and a relative href was judged purely as a path on disk. 18 live 404s had collected behind them, all green under `lychee --offline` for the same reason. Gate (objectui#3490): - Absolute non-`/docs` hrefs now resolve against a route truth source enumerated from `apps/site/app` (App-Router segments, incl. route groups, dynamic and catch-all forms) plus static files under `apps/site/public`. - Relative hrefs that resolve outside `content/docs` are rejected: fumadocs can only resolve inside its page index, so such a link reaches the browser verbatim and 404s even though the file is really there. - Each failure is labelled with the check that rejected it, and `routeExists` throws rather than pass an absolute href when given no route table — a silent `true` is how these 18 accumulated. The script now reads `apps/site` as well as `content/docs`. That widens its responsibility and couples a `content/` gate to an `apps/` layout; the header argues the trade-off, including the cost (a docs PR can go red because the site moved under it — correct, but real). Content: all 18 links repointed at real targets — `/docs/...` pages where an equivalent exists, otherwise absolute GitHub URLs (the "Package README" form already used across `content/docs/plugins/*.mdx`). The three `/img/guide/dashboard-filters/*.png` links in the same batch were already good and are accepted by the new check. Also drops the now-stale `@ts-expect-error` in the pin test: #3494 turned on `allowJs` inference for `scripts/`, which made the directive #3489 carried unused — and an unused one is itself a tsc error, so `main` was red on `pnpm type-check:scripts` (objectui#3504).
The latest updates on your projects. Learn more about Vercel for GitHub. |
This was referenced Aug 7, 2026
yinlianghui
marked this pull request as ready for review
August 7, 2026 02:11
github-merge-queueBot
removed this pull request from the merge queue due to a conflict with the base branch
Aug 7, 2026
…e-route-links # Conflicts: # scripts/__tests__/check-doc-links.test.ts
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 7, 2026
akarma-synetal pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Aug 10, 2026
…bjectstack-ai#3509) `examples/todo` and `examples/crm` have never existed on `main` (examples/ holds README.md, byo-backend-console, console-starter, hello-world, schema-catalog), so both "Next Steps" links were live GitHub 404s. Retarget each to the page that actually answers the bullet, and retitle the label to name that page honestly rather than dressing it up as an example app that does not exist (precedent: objectstack-ai#3506's "Example: CRM Application" -> "Example: ObjectStack Console Starter"). Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Aug 10, 2026
* docs(examples): add a README for console-starter examples/console-starter was the only example directory without a README, and PR objectstack-ai#3506 retargets a docs link at its GitHub tree page. Content is measured from src/ and the configs: the app-shell building blocks App.tsx composes, the workspace packages that make `pnpm -w build` a hard prerequisite, the VITE_SERVER_URL backend requirement, and what the app actually does with no backend listening. Fixesobjectstack-ai#3520 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt * docs(examples): drop the self-invalidating file count from the console-starter README "This directory holds ten files" stops being true the moment this README lands in it. State the fact that matters instead: no schema JSON here at all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt --------- Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Aug 10, 2026
…bjectstack-ai#3571) 三条链接的目标在磁盘上都不存在,且这两个文件不在任何门禁的扫描面内 (check-doc-links 的 SCAN_ROOTS 是 content/docs + examples + 根 README; lychee 扫 content/docs、docs、README.md),所以一直静默失效。 - CONTRIBUTING.md:153 `./docs/spec/architecture.md`(`docs/spec/` 目录根本不存在) → `./content/docs/guide/architecture.md`。未按 issue 建议指向 `docs/ARCHITECTURE.md`: 该文件的 H1 是 "Console Streamlining - Architecture Guide",讲的是 app-shell/providers 那次重构的迁移路径,而链接所在的 "Architecture Overview" 一节讲的是 monorepo 包结构与 设计原则 —— `content/docs/guide/architecture.md`(标题即 "Architecture Overview", 含 Package Structure / Core Philosophy 两节)才是这句 "for details" 真正承诺的内容。 链接文字同时改成目标文档的真实标题,避免用旧标签包装另一个目标。 - CONTRIBUTING.md:469 `./docs/README.md` → 删除整句。仓库里没有、也从未有过 "Documentation Guide" 这份文档;它承诺的细节就在它所处的 Documentation 一节里 (Writing Documentation / Documentation Guidelines / Link Conventions / Validating Links), 前一句也已自成完整陈述。按 objectstack-ai#3506/objectstack-ai#3509 的先例,如实删除而不是改指别的文档。 - ROADMAP.md:1892 扩展名错 `.mdx` → `.md`。真实文件是 `content/docs/guide/plugin-development.md`;保持相对文件链接的写法,与同一列表里 `./CONTRIBUTING.md`、`./QUICK_REFERENCE.md` 一致。 本 PR 只做第 1 步。issue 的第 2 步(把这两个文件与 `docs/**` 纳入 SCAN_ROOTS) 刻意留下,不碰 scripts/check-doc-links.mjs。 Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt Co-authored-by: Claude <noreply@anthropic.com>
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 freeto 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#3490
前提复核(先证后改)
在
origin/main(f995a45)上逐条复核 issue 的清单,全部属实:非/docs绝对 href 共 20 条 = 17 条死链 + 3 条/img/guide/dashboard-filters/*.png(真实存在于apps/site/public/,是好的);跑出 collection 的相对链接 1 条。apps/site/app的路由段枚举结果与 issue 描述一字不差:没有
spec、protocol、examples;next.config.mjs只有/docs/:path*.mdx一条重写;无vercel.json。根因
门禁问的是「磁盘上有没有这个文件」,而唯一该问的是「站点服务不服务这个 URL」。两条豁免由此而来——非
/docs绝对 href 直接放行,相对 href 只按磁盘路径判定。18 条真实 404 就积在这两条豁免后面,lychee --offline判绿也是同一个原因。门禁改动(方向 3,按 PM 裁定收敛)
/docs绝对 href 按真值来源判定存在性:从apps/site/app枚举 App-Router 路由段(含 route group(home)、私有_foo、动态[slug]、catch-all[...slug]、可选 catch-all[[...slug]]),外加apps/site/public下的静态文件。source.resolveHref只在 docs 页面索引里查,packages/**不在其中,href 原样落到浏览器——文件真在磁盘上也照样 404。relative/docs-route/site-route/escapes-collection),各给各的修复提示。routeExists()拿不到路由表时抛错而不是放行绝对 href——静默true正是这 18 条积起来的方式。职责扩大的取舍(脚本头部已写明)
脚本从「只读
content/docs」变成「也读apps/site」。这是有意购买,不是顺手:apps/site/app只被枚举,从不 import、从不执行,路由变更自动被感知——不会像手维护的前缀白名单那样悄悄漂移。apps/site在它脚下挪动而变红。这个失败是正确的(那条链接确实会 404),但两棵树从此不再互相独立。没有买的:
next.config.mjs的 rewrite/redirect 不建模(唯一那条/docs/:path*.mdx落在更严格的/docs分支里,根本走不到这里);扫描面仍然只有content/docs——examples/**与根README.md按 PM 裁定留作后续单,不在本单扩。逐条处置表(18 条)
/docs/...页面有等价物的就指过去,没有的用 GitHub 绝对 URL(content/docs/plugins/*.mdx的 "Package README" 已有先例)。guide/data-source.md:202../../../packages/data-objectstack/README.md#cross-object-atomic-batch-batchtransactionhttps://github.com/.../blob/main/packages/data-objectstack/README.md#cross-object-atomic-batch-batchtransactionplugin-dashboard.mdx:222的 blob+锚点写法guide/component-registry.md:462/spec/component-package.md/docs/guide/plugin-developmentguide/component-registry.md:466/api/core.../tree/main/packages/coreguide/component-registry.md:467/api/react.../tree/main/packages/reactguide/component-registry.md:468/spec/component.md/docs/api/schema-referenceguide/expressions.md:639/protocol/overview/docs/guide/schema-overviewguide/expressions.md:643/api/core.../tree/main/packages/coreguide/expressions.md:644/protocol/form/docs/plugins/plugin-formguide/expressions.md:645/protocol/view/docs/plugins/plugin-viewguide/fields.md:69/protocolobjectstack/tree/main/packages/spec@objectstack/specguide/objectos-integration.mdx:662/examples/crm.../tree/main/examples/console-starterexamples/crm;console-starter 才是接 ObjectStack 后端、插件全开的那个例子guide/objectos-integration.mdx:663/examples/kitchen-sink/docs/guide/schema-catalogguide/plugins.md:515/spec/component-package.md/docs/guide/plugin-developmentguide/schema-rendering.md:414/protocol/overview/docs/guide/schema-overviewguide/schema-rendering.md:418/spec/schema-rendering/docs/core/schema-rendererguide/schema-rendering.md:419/spec/architecture/docs/guide/architectureguide/schema-rendering.md:420/api/core.../tree/main/packages/coreguide/schema-rendering.md:421/api/react.../tree/main/packages/react改标签的三处(#2/#3、#10、#11)是有意为之:链接文案写着 "CRM Application" 却指向 console-starter,本身就是另一个小谎。
同批的 3 条
/img/guide/dashboard-filters/*.png不动——它们本来就对,新检查把它们按public/静态资源判绿。验证(先预测方向,再跑)
预测:扩展后的门禁在未修改的 content 上应恰好报 18 条(17
site-route+ 1escapes-collection),且 3 条/img不得出现。 实跑一致:修完后
node scripts/check-doc-links.mjs→Docs links are valid.(exit 0)。反向验证。 预测方向为「红」:把两条豁免原样接回去,新增的拒绝类断言应全部转红,而直接对
collectSiteRoutes/siteUrlExists的单元测试不经过豁免、应保持绿。实跑与预测完全一致——6 failed | 28 passed,红的正是那 6 条拒绝类断言(3 条 site-route、1 条 public 缺失、1 条抛错、1 条 escapes-collection + reason 分类),路由表语义与真实apps/site那两个 describe 一条没红。其他:
pnpm exec vitest run scripts/Test Files 14 passed (14) / Tests 216 passed (216)(本文件 22 → 34)pnpm type-check:scriptspnpm exec eslint(改动的 mjs/ts)pnpm turbo run build --filter=@object-ui/siteTasks: 28 successful, 28 total— 文档照常编译node scripts/check-control-bytes.mjs[\x00-\x08\x0b\x0c\x0e-\x1f]自扫改动文件,无命中)两处需要 reviewer 注意的范围外沿
content/docs/guide/ci-cd-pipeline.md:该页第 248 行与第 290 行的表格格描述的正是本脚本的行为("resolved against the files actually on disk"、"Internal/docs/...routes"),被本次改动证伪。按 AGENTS.md Add automated testing infrastructure and CI/CD workflows #2(docs-driven)做了最小事实订正,没有做别的改动。check-doc-links.test.ts第 7 行的@ts-expect-error:[ci] scripts/ 在零 tsconfig 覆盖内:turbo type-check 从不检查 scripts/__tests__/*.ts——一批门禁 pin 测试自身无类型门 #3494 打开scripts/的allowJs推断后,fix(docs): check-doc-links 解析相对链接,并修掉它现在能看见的 16 个失效目标 (#3479) #3489 带进来的这条指令变成 unused,而 unused 本身就是 tsc 报错——main因此在pnpm type-check:scripts上已经是红的(与本 PR 无关,已由 PM 记为 main 的 Type Check job 全红:#3489 与 #3498 的语义冲突,check-doc-links.test.ts的@ts-expect-error在 allowJs 下变成 TS2578 #3504)。按 PM 协调只删这一行,不加替代注释,以便与热修 PR 无论谁先合都能干净合并。Generated by Claude Code