CI caught a follow-on bug from the previous commit. The component
files emitted by generate-superset-components.mjs are `.mdx`, but
my generator patch appended `.md` to the link suffix. Result: the
generated index pages (ui/index.mdx, design-system/index.mdx, and
the build-time-generated extension/index.mdx) reference
`./autocomplete.md`, `./dropdowncontainer.md`, etc. — all targets
that don't exist (the real files are `.mdx`). Docusaurus's
`onBrokenMarkdownLinks: 'throw'` correctly bombs the build.
Worth calling out: this is exactly the failure mode the previous
commit was trying to fix — bare relative links 404'd silently; now
that they go through the file resolver, the resolver catches the
extension mismatch instead. The system is working; my fix was just
wrong on this one detail.
Two corrections:
1. generate-superset-components.mjs now emits `.mdx` suffix (not
`.md`) on the component links it produces, matching the actual
page file format. Comment updated to make the intent explicit
for future maintainers.
2. The two committed auto-generated index files
(developer_docs/components/ui/index.mdx and
developer_docs/components/design-system/index.mdx) had 46 + 7 =
53 `.md` link suffixes from the previous commit. Bulk-corrected
to `.mdx` to match their actual targets. The third generated
file (components/extension/index.mdx) is produced at build time
and not committed; the generator fix above handles it.
Verified with a re-audit script: 92/92 markdown-link targets across
the PR's modified files now resolve to real `.md` / `.mdx` files on
disk. lint-docs-links still passes (it only fails on missing
extensions, not on this category of mismatch — that's `onBroken
MarkdownLinks`'s job, and it WAS doing its job here).
Copilot flagged two stragglers on editors.md where the previous
file-by-file conversion stopped halfway. Sweeping for the same
pattern across the active content tree found 76 bare relative
internal links total — 14 in this PR's already-modified files
(Copilot's two plus twelve more) and 62 in unchanged files.
Why the build doesn't catch this
─────────────────────────────────
`onBrokenLinks: 'throw'` (set in this PR) only validates *file-based*
markdown references — links whose URL ends in `.md` / `.mdx`. Those
go through Docusaurus's file resolver, which can prove the target
exists. Bare relative URL paths like `[Foo](../foo)` skip that
resolver entirely; Docusaurus emits them as raw hrefs. The browser
then resolves them against the *current* page URL, and for
trailing-slash routes that almost always lands in the wrong
directory. Page navigates client-side and 404s. The linkinator job
in CI *can* catch these, but it's `continue-on-error: true` so
findings are advisory.
What this commit does
──────────────────────
1. Fix all 76 bare relative internal links across the active docs
tree by appending `.md` to each one (preserving anchors / query
strings). All 76 targets resolved to real files; no link
targets changed, only the form of the reference.
2. Fix the component-page generator. 54 of the 76 bare links lived
in two auto-generated index files (`components/ui/index.mdx`
and `components/design-system/index.mdx`). The next regeneration
would have undone the manual fixes without this. The two
emission sites in `generate-superset-components.mjs` now emit
`.md`-suffixed links; comment at the call site explains why.
3. Add `docs/scripts/lint-docs-links.mjs` — fast source-level
linter that scans `.md`/`.mdx` files under the active content
trees (skipping `versioned_docs/` snapshots) and fails if it
finds any markdown link whose URL starts with `./` or `../` and
does not end in `.md`/`.mdx`. Excludes asset paths (.png,
.json, etc.) and ignores fenced code blocks. Wired up as
`yarn lint:docs-links`.
4. Add a `Lint docs links` step to `superset-docs-verify.yml`,
running before the build step so PRs that introduce the pattern
fail in seconds rather than at build-time / not at all. Blocking,
not advisory — exactly the gap linkinator's `continue-on-error`
leaves open.
Verified
────────
- `yarn lint:docs-links` exits 0 on the cleaned tree
- Re-introducing one bare link makes the linter report the exact
file:line with the offending URL, exit code 1
- All 76 originally-flagged targets resolved to real `.md` / `.mdx`
files; only the form of the reference changed