fix(docs): finish bare-relative link conversion + add lint guardrail

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
This commit is contained in:
Evan Rusackas
2026-05-13 19:27:57 -07:00
parent 04451766e7
commit 10f71bdcd5
20 changed files with 270 additions and 78 deletions

View File

@@ -29,10 +29,10 @@ sidebar_position: 1
## Components
- [DropdownContainer](./dropdowncontainer)
- [Flex](./flex)
- [Grid](./grid)
- [Layout](./layout)
- [MetadataBar](./metadatabar)
- [Space](./space)
- [Table](./table)
- [DropdownContainer](./dropdowncontainer.md)
- [Flex](./flex.md)
- [Grid](./grid.md)
- [Layout](./layout.md)
- [MetadataBar](./metadatabar.md)
- [Space](./space.md)
- [Table](./table.md)

View File

@@ -62,7 +62,7 @@ This documentation is auto-generated from Storybook stories. To add or update co
4. Run `yarn generate:superset-components` in the `docs/` directory
:::info Work in Progress
This component library is actively being documented. See the [Components TODO](./TODO) page for a list of components awaiting documentation.
This component library is actively being documented. See the [Components TODO](./TODO.md) page for a list of components awaiting documentation.
:::
---

View File

@@ -29,49 +29,49 @@ sidebar_position: 1
## Components
- [AutoComplete](./autocomplete)
- [Avatar](./avatar)
- [Badge](./badge)
- [Breadcrumb](./breadcrumb)
- [Button](./button)
- [ButtonGroup](./buttongroup)
- [CachedLabel](./cachedlabel)
- [Card](./card)
- [Checkbox](./checkbox)
- [Collapse](./collapse)
- [DatePicker](./datepicker)
- [Divider](./divider)
- [EditableTitle](./editabletitle)
- [EmptyState](./emptystate)
- [FaveStar](./favestar)
- [IconButton](./iconbutton)
- [Icons](./icons)
- [IconTooltip](./icontooltip)
- [InfoTooltip](./infotooltip)
- [Input](./input)
- [Label](./label)
- [List](./list)
- [ListViewCard](./listviewcard)
- [Loading](./loading)
- [Menu](./menu)
- [Modal](./modal)
- [ModalTrigger](./modaltrigger)
- [Popover](./popover)
- [ProgressBar](./progressbar)
- [Radio](./radio)
- [SafeMarkdown](./safemarkdown)
- [Select](./select)
- [Skeleton](./skeleton)
- [Slider](./slider)
- [Steps](./steps)
- [Switch](./switch)
- [TableCollection](./tablecollection)
- [TableView](./tableview)
- [Tabs](./tabs)
- [Timer](./timer)
- [Tooltip](./tooltip)
- [Tree](./tree)
- [TreeSelect](./treeselect)
- [Typography](./typography)
- [UnsavedChangesModal](./unsavedchangesmodal)
- [Upload](./upload)
- [AutoComplete](./autocomplete.md)
- [Avatar](./avatar.md)
- [Badge](./badge.md)
- [Breadcrumb](./breadcrumb.md)
- [Button](./button.md)
- [ButtonGroup](./buttongroup.md)
- [CachedLabel](./cachedlabel.md)
- [Card](./card.md)
- [Checkbox](./checkbox.md)
- [Collapse](./collapse.md)
- [DatePicker](./datepicker.md)
- [Divider](./divider.md)
- [EditableTitle](./editabletitle.md)
- [EmptyState](./emptystate.md)
- [FaveStar](./favestar.md)
- [IconButton](./iconbutton.md)
- [Icons](./icons.md)
- [IconTooltip](./icontooltip.md)
- [InfoTooltip](./infotooltip.md)
- [Input](./input.md)
- [Label](./label.md)
- [List](./list.md)
- [ListViewCard](./listviewcard.md)
- [Loading](./loading.md)
- [Menu](./menu.md)
- [Modal](./modal.md)
- [ModalTrigger](./modaltrigger.md)
- [Popover](./popover.md)
- [ProgressBar](./progressbar.md)
- [Radio](./radio.md)
- [SafeMarkdown](./safemarkdown.md)
- [Select](./select.md)
- [Skeleton](./skeleton.md)
- [Slider](./slider.md)
- [Steps](./steps.md)
- [Switch](./switch.md)
- [TableCollection](./tablecollection.md)
- [TableView](./tableview.md)
- [Tabs](./tabs.md)
- [Timer](./timer.md)
- [Tooltip](./tooltip.md)
- [Tree](./tree.md)
- [TreeSelect](./treeselect.md)
- [Typography](./typography.md)
- [UnsavedChangesModal](./unsavedchangesmodal.md)
- [Upload](./upload.md)

View File

@@ -327,9 +327,9 @@ stats.sort_stats('cumulative').print_stats(10)
## Resources
### Internal
- [Coding Guidelines](../guidelines/design-guidelines)
- [Testing Guide](../testing/overview)
- [Extension Architecture](../extensions/architecture)
- [Coding Guidelines](../guidelines/design-guidelines.md)
- [Testing Guide](../testing/overview.md)
- [Extension Architecture](../extensions/architecture.md)
### External
- [Google's Code Review Guide](https://google.github.io/eng-practices/review/)

View File

@@ -668,7 +668,7 @@ A series of checks will now run when you make a git commit.
## Linting
See [how tos](./howtos#linting)
See [how tos](./howtos.md#linting)
## GitHub Actions and `act`

View File

@@ -77,7 +77,7 @@ Finally, never submit a PR that will put master branch in broken state. If the P
in `requirements.txt` pinned to a specific version which ensures that the application
build is deterministic.
- For TypeScript/JavaScript, include new libraries in `package.json`
- **Tests:** The pull request should include tests, either as doctests, unit tests, or both. Make sure to resolve all errors and test failures. See [Testing](./howtos#testing) for how to run tests.
- **Tests:** The pull request should include tests, either as doctests, unit tests, or both. Make sure to resolve all errors and test failures. See [Testing](./howtos.md#testing) for how to run tests.
- **Documentation:** If the pull request adds functionality, the docs should be updated as part of the same PR.
- **CI:** Reviewers will not review the code until all CI tests are passed. Sometimes there can be flaky tests. You can close and open PR to re-run CI test. Please report if the issue persists. After the CI fix has been deployed to `master`, please rebase your PR.
- **Code coverage:** Please ensure that code coverage does not decrease.

View File

@@ -282,7 +282,7 @@ You can now launch your VSCode debugger with the same config as above. VSCode wi
### Storybook
See the dedicated [Storybook documentation](../testing/storybook) for information on running Storybook locally and adding new stories.
See the dedicated [Storybook documentation](../testing/storybook.md) for information on running Storybook locally and adding new stories.
## Contributing Translations

View File

@@ -94,7 +94,7 @@ Look through the GitHub issues. Issues tagged with
Superset could always use better documentation,
whether as part of the official Superset docs,
in docstrings, `docs/*.rst` or even on the web as blog posts or
articles. See [Documentation](./howtos#contributing-to-documentation) for more details.
articles. See [Documentation](./howtos.md#contributing-to-documentation) for more details.
### Add Translations
@@ -103,7 +103,7 @@ text strings from Superset's UI. You can jump into the existing
language dictionaries at
`superset/translations/<language_code>/LC_MESSAGES/messages.po`, or
even create a dictionary for a new language altogether.
See [Translating](./howtos#contributing-translations) for more details.
See [Translating](./howtos.md#contributing-translations) for more details.
### Ask Questions

View File

@@ -35,7 +35,7 @@ Learn how to create and submit high-quality pull requests to Apache Superset.
- [ ] You've found or created an issue to work on
### PR Readiness Checklist
- [ ] Code follows [coding guidelines](../guidelines/design-guidelines)
- [ ] Code follows [coding guidelines](../guidelines/design-guidelines.md)
- [ ] Tests are passing locally
- [ ] Linting passes (`pre-commit run --all-files`)
- [ ] Documentation is updated if needed

View File

@@ -110,7 +110,7 @@ editors.registerEditor(
);
```
See [Editors Extension Point](./extension-points/editors) for implementation details.
See [Editors Extension Point](./extension-points/editors.md) for implementation details.
## Backend

View File

@@ -218,5 +218,5 @@ const disposable = handle.registerCompletionProvider(provider);
## Next Steps
- **[SQL Lab Extension Points](./sqllab.md)** - Learn about other SQL Lab customizations
- **[Contribution Types](../contribution-types)** - Explore other contribution types
- **[Development](../development)** - Set up your development environment
- **[Contribution Types](../contribution-types.md)** - Explore other contribution types
- **[Development](../development.md)** - Set up your development environment

View File

@@ -157,6 +157,6 @@ menus.registerMenuItem(
## Next Steps
- **[Contribution Types](../contribution-types)** - Learn about other contribution types (commands, menus)
- **[Development](../development)** - Set up your development environment
- **[Quick Start](../quick-start)** - Build a complete extension
- **[Contribution Types](../contribution-types.md)** - Learn about other contribution types (commands, menus)
- **[Development](../development.md)** - Set up your development environment
- **[Quick Start](../quick-start.md)** - Build a complete extension

View File

@@ -225,7 +225,7 @@ The `@apache-superset/core` package must be listed in both `peerDependencies` (t
The webpack configuration requires specific settings for Module Federation. Key settings include `externalsType: "window"` and `externals` to map `@apache-superset/core` to `window.superset` at runtime, `import: false` for shared modules to use the host's React instead of bundling a separate copy, and `remoteEntry.[contenthash].js` for cache busting.
**Convention**: Superset always loads extensions by requesting the `./index` module from the Module Federation container. The `exposes` entry must be exactly `'./index': './src/index.tsx'` — do not rename or add additional entries. All API registrations must be reachable from that file. See [Architecture](./architecture#module-federation) for a full explanation.
**Convention**: Superset always loads extensions by requesting the `./index` module from the Module Federation container. The `exposes` entry must be exactly `'./index': './src/index.tsx'` — do not rename or add additional entries. All API registrations must be reachable from that file. See [Architecture](./architecture.md#module-federation) for a full explanation.
```javascript
const path = require('path');

View File

@@ -114,7 +114,7 @@ class CreateDashboardCommand(BaseCommand):
### Data Access Objects (DAOs)
See: [DAO Style Guidelines and Best Practices](./backend/dao-style-guidelines)
See: [DAO Style Guidelines and Best Practices](./backend/dao-style-guidelines.md)
## Testing

View File

@@ -29,16 +29,16 @@ This is a list of statements that describe how we do frontend development in Sup
- We develop using TypeScript.
- See: [SIP-36](https://github.com/apache/superset/issues/9101)
- We use React for building components, and Redux to manage app/global state.
- See: [Component Style Guidelines and Best Practices](./frontend/component-style-guidelines)
- See: [Component Style Guidelines and Best Practices](./frontend/component-style-guidelines.md)
- We prefer functional components to class components and use hooks for local component state.
- We use [Ant Design](https://ant.design/) components from our component library whenever possible, only building our own custom components when it's required.
- See: [SIP-48](https://github.com/apache/superset/issues/11283)
- We use [@emotion](https://emotion.sh/docs/introduction) to provide styling for our components, co-locating styling within component files.
- See: [SIP-37](https://github.com/apache/superset/issues/9145)
- See: [Emotion Styling Guidelines and Best Practices](./frontend/emotion-styling-guidelines)
- See: [Emotion Styling Guidelines and Best Practices](./frontend/emotion-styling-guidelines.md)
- We use Jest for unit tests, React Testing Library for component tests, and Cypress for end-to-end tests.
- See: [SIP-56](https://github.com/apache/superset/issues/11830)
- See: [Testing Guidelines and Best Practices](../testing/testing-guidelines)
- See: [Testing Guidelines and Best Practices](../testing/testing-guidelines.md)
- We add tests for every new component or file added to the frontend.
- We organize our repo so similar files live near each other, and tests are co-located with the files they test.
- See: [SIP-61](https://github.com/apache/superset/issues/12098)
@@ -46,6 +46,6 @@ This is a list of statements that describe how we do frontend development in Sup
- We use OXC (oxlint) and Prettier to automatically fix lint errors and format the code.
- We do not debate code formatting style in PRs, instead relying on automated tooling to enforce it.
- If there's not a linting rule, we don't have a rule!
- See: [Linting How-Tos](../contributing/howtos#typescript--javascript)
- See: [Linting How-Tos](../contributing/howtos.md#typescript--javascript)
- We use [React Storybook](https://storybook.js.org/) to help preview/test and stabilize our components
- A public Storybook with components from the `master` branch is available [here](https://apache-superset.github.io/superset-ui/?path=/story/*)

View File

@@ -53,7 +53,7 @@ superset-frontend/src/components
**Storybook:** Components should come with a storybook file whenever applicable, with the following naming convention `\{ComponentName\}.stories.tsx`. More details about Storybook below
**Unit and end-to-end tests:** All components should come with unit tests using Jest and React Testing Library. The file name should follow this naming convention `\{ComponentName\}.test.tsx`. Read the [Testing Guidelines and Best Practices](../../testing/testing-guidelines) for more details
**Unit and end-to-end tests:** All components should come with unit tests using Jest and React Testing Library. The file name should follow this naming convention `\{ComponentName\}.test.tsx`. Read the [Testing Guidelines and Best Practices](../../testing/testing-guidelines.md) for more details
**Reference naming:** Use `PascalCase` for React components and `camelCase` for component instances