diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c247a0a6a9..69ef7cea29 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -48,6 +48,22 @@ jobs: run: npm run typecheck - name: 🔤 Spell Check run: npm run spellcheck + # Docusaurus derives a heading's anchor from its text, so renaming a + # heading moves the anchor and breaks every inbound link. An explicit id + # survives the rename, and lets a translation keep the English anchor + # after the heading text is translated. + # + # Nothing in Docusaurus enforces this: a page whose headings are all + # unpinned builds clean. So run its own generator and fail if it had + # anything to add. + - name: 🔗 Heading IDs + run: | + npm run heading-ids + if ! git diff --quiet -- docs; then + echo "::error::Headings are missing explicit ids. Run \`npm run heading-ids\` and commit the result." + git diff -- docs + exit 1 + fi - uses: ./.github/workflows/actions/check-translations cross-platform: diff --git a/docusaurus.config.js b/docusaurus.config.js index f020c84229..05cf7cc5b0 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -45,7 +45,16 @@ module.exports = { ja: { label: '日本語' }, }, }, - onBrokenLinks: 'warn', + /** + * A broken link or anchor fails the build instead of warning, so a stale + * cross-reference cannot reach production unnoticed. + * + * `build:preview` passes `--locale en`, so a pull request preview only + * ever checks English. A regression in a translated locale surfaces in + * the production build, which builds every locale. + */ + onBrokenLinks: 'throw', + onBrokenAnchors: 'throw', future: { v4: { /** diff --git a/package.json b/package.json index afec9cf311..fded68b474 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "deploy": "docusaurus deploy", "docusaurus": "docusaurus", "generate-markdown": "node scripts/native.mjs && node scripts/cli.mjs && node scripts/release-notes.mjs", + "heading-ids": "docusaurus write-heading-ids . \"docs/**/*.mdx\" \"!docs/native/**\" \"!docs/cli/commands/**\" --syntax mdx-comment", "lint": "npm run prettier -- --write", "serve": "docusaurus serve", "playground:new": "hygen playground new",