From 9d3cfb2718a5787df684af73038546d4be8ec961 Mon Sep 17 00:00:00 2001 From: jackchuka Date: Tue, 25 Aug 2026 12:31:44 +0900 Subject: [PATCH] fix(docs): repair broken links in app-shell migrations The PR Checks workflow has been failing on main, and so on every open dependency PR: - `lint`: the VitePress build failed on two dead links to ../packages/core/CHANGELOG. That path is correct inside the app-shell repo, but docs-sync copies the file to app-shell/changelog.md, so the original path resolves to nothing here. - `schema-check`: two anchors in docs/app-shell/migrations.md were written with GitHub's slugger, which emits a hyphen per separator character, so " / " and " -> " produced a doubled hyphen. mdschema collapses runs of hyphens and saw both links as broken. docs/app-shell is regenerated wholesale by the nightly docs-sync run, so fixing the file alone would revert within a day. Both rewrites are added to the sync post-processing, and the changelog rewrite is derived from the `extraCopies` list rather than hardcoding the path, so the copy rule and the link rule cannot drift apart. Running `pnpm sync:app-shell` reproduces the committed file exactly. A third slug dialect is left alone deliberately: VitePress renders `## 1.12.0: ...` as `id="_1-12-0-..."`, so the 9 anchors in the migrations table scroll nowhere on the site. The build does not check fragments, so nothing catches it. Emitting VitePress's dialect and moving the anchor check out of mdschema was tried and reverted as more machinery than the problem warrants; the reasoning is recorded next to collapseAnchorHyphens. --- docs/app-shell/migrations.md | 8 ++++---- scripts/docs-sync/main.ts | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/docs/app-shell/migrations.md b/docs/app-shell/migrations.md index 3fbbd3a..0b8dcdc 100644 --- a/docs/app-shell/migrations.md +++ b/docs/app-shell/migrations.md @@ -7,17 +7,17 @@ description: Breaking changes and required migration steps for AppShell upgrades Every change that requires you to edit your application before or after upgrading, newest first. -This page is deliberately narrow. It is **not** a changelog — see [`packages/core/CHANGELOG.md`](../packages/core/CHANGELOG) for the full release history including features and fixes. A change belongs here only if an app that does nothing will break, misbehave, or silently drift. +This page is deliberately narrow. It is **not** a changelog — see [`packages/core/CHANGELOG.md`](./changelog) for the full release history including features and fixes. A change belongs here only if an app that does nothing will break, misbehave, or silently drift. Each entry states which versions are affected, what breaks, how to detect it, and what to change. Entries stay here permanently; they are not pruned when they get old, because apps upgrade across arbitrary version gaps. | Version | Change | | ------------- | ---------------------------------------------------------------------------------------------------------------------------- | -| 1.12.0 | [`DateField` / `DatePicker` field chrome moved to `Field.Root`](#1120-datefield--datepicker-field-chrome-moved-to-fieldroot) | +| 1.12.0 | [`DateField` / `DatePicker` field chrome moved to `Field.Root`](#1120-datefield-datepicker-field-chrome-moved-to-fieldroot) | | 1.11.0 | [React 19.2.7 and React Router v8 required](#1110-react-1927-and-react-router-v8-are-now-required) | | 1.11.0 | [Non-modal `Sheet` renders no backdrop](#1110-non-modal-sheet-no-longer-renders-a-backdrop) | | 1.8.0 | [`stream` removed from `useAIChat()`](#180-stream-removed-from-useaichat) | -| 1.5.0 → 1.7.0 | [Remove the theme bridge workaround](#150--170-remove-the-theme-bridge-workaround) | +| 1.5.0 → 1.7.0 | [Remove the theme bridge workaround](#150-170-remove-the-theme-bridge-workaround) | | 1.5.0 | [`loader` removed from file-based pages](#150-loader-removed-from-file-based-page-definitions) | | 1.3.0 | [Column inference and badge defaults changed](#130-column-inference-and-badge-defaults-changed) | | 1.0.2 | [`Toaster` no longer accepts `richColors`](#102-toaster-no-longer-accepts-richcolors) | @@ -158,7 +158,7 @@ The prop is removed, and toasts no longer colour-code the success, error, warnin Pre-1.0 releases changed the public API often, mostly around authentication and routing. If you are upgrading from a 0.x version, work through these in order — several supersede each other, so applying them out of sequence will not land you in the right place. -Each is summarised here; [`packages/core/CHANGELOG.md`](../packages/core/CHANGELOG) carries the full before/after code for every one. +Each is summarised here; [`packages/core/CHANGELOG.md`](./changelog) carries the full before/after code for every one. | Version | Change | | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/scripts/docs-sync/main.ts b/scripts/docs-sync/main.ts index 2912c23..0877ace 100644 --- a/scripts/docs-sync/main.ts +++ b/scripts/docs-sync/main.ts @@ -116,6 +116,42 @@ function stripNonAllowedLinks(content: string): string { }); } +// Upstream links to the files in `extraCopies` by their path in the source +// repo. Those files land here under a different name, so the original path +// resolves to nothing and fails the VitePress dead-link check. Derive the +// rewrite from the copy list itself so the two cannot drift apart. +function rewriteExtraCopyLinks(content: string, config: SyncConfig): string { + const repoRoot = path.dirname(config.src); + for (const [src, dst] of config.extraCopies ?? []) { + const from = path.relative(repoRoot, src).replace(/\.md$/, ""); + const to = path.basename(dst, ".md"); + const pattern = new RegExp( + `\\]\\((?:\\.\\./)*${from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?:\\.md)?\\)`, + "g", + ); + content = content.replace(pattern, `](./${to})`); + } + return content; +} + +// Upstream anchors are written with GitHub's slugger, which keeps a hyphen per +// separator character, so " / " and " \u2192 " yield a doubled hyphen. mdschema +// collapses runs of hyphens and reports those links as broken. +// +// This only settles the disagreement with mdschema. VitePress slugs headings a +// third way (`## 1.12.0: ...` renders as `id="_1-12-0-..."`), so anchors onto +// headings that contain `.`, `/` or an arrow still scroll nowhere on the site +// — 9 of them in app-shell/migrations.md today. The build does not check +// fragments, so nothing catches that. Fixing it means emitting VitePress's +// dialect here and moving the anchor check out of mdschema, which was judged +// more machinery than the problem currently warrants. +function collapseAnchorHyphens(content: string): string { + return content.replace( + /\]\((#[^)]+)\)/g, + (_, anchor: string) => `](${anchor.replace(/-{2,}/g, "-")})`, + ); +} + // 1. Backup index.md const indexBackupPath = path.join(config.dst, "index.md"); const indexBackup = fs.existsSync(indexBackupPath) @@ -167,6 +203,8 @@ walk(config.dst) content = content.replace(/\.md\)/g, ")"); content = fixHeadingLevels(content); content = stripNonAllowedLinks(content); + content = rewriteExtraCopyLinks(content, config); + content = collapseAnchorHyphens(content); fs.writeFileSync(f, content); });