Skip to content

feat(core): resolve Markdown file links across plugins (AI-assisted) - #12431

Open
gauranshahuja wants to merge 1 commit into
facebook:mainfrom
gauranshahuja:9117/cross-plugin-markdown-links
Open

gauranshahuja wants to merge 1 commit into
facebook:mainfrom
gauranshahuja:9117/cross-plugin-markdown-links

Conversation

@gauranshahuja

Copy link
Copy Markdown

Closes #9117

This PR was written with AI assistance (AI-assisted).

Motivation

Markdown file references such as [link](../blog/post.md) could only be resolved
against the Markdown files of the plugin instance owning the source file. Linking a
doc to a blog post, or a page to a doc, was impossible — the docs even documented the
limitation.

Building on @slorber's "core maintains a file path → URL path mapping" suggestion in
the issue.

Implementation

  • Core builds a site-wide Markdown files registry from the route metadata
    (sourceFilePath, available on every content route since refactor(mdx-loader): read metadata from memory (loaded content) instead of fs #10457). No new plugin
    lifecycle is needed, and multi-instance / versioned / localized content works out of
    the box. Third-party content plugins join automatically as soon as they set
    sourceFilePath on their routes.
  • The registry is exposed on LoadContext (siteMarkdownLinks) and handed over to the
    MDX loader by the docs/blog/pages plugins through a new optional
    resolveSiteMarkdownLink option.
  • The resolveMarkdownLinks remark plugin tries the plugin's own resolver first and
    only falls back to the site-wide registry. Existing links therefore keep resolving
    exactly as before; only links that are broken today start resolving.
  • The registry object identity is stable and its content is refreshed in place, because
    the bundler config (and thus the MDX loader options) is only created once, while
    reloadSite() creates a brand new LoadContext on every dev reload.

Relative, site-absolute (/docs/intro.md) and @site/-aliased links are all supported.

Test Plan

  • New unit tests for the registry (siteMarkdownLinks.test.ts) including the
    refresh-in-place invariant used by dev reloads.
  • New remark plugin tests for the fallback: plugin resolves / site-wide fallback
    resolves / neither resolves.
  • Dogfooding: cross-plugin links added to the docs, pages and blog test instances
    (docs → blog + pages + site docs, pages → docs + blog, and a new blog post → docs +
    pages). Since onBrokenMarkdownLinks defaults to throw, the website build itself
    asserts they all resolve.
  • pnpm test, pnpm lint:js, pnpm lint:style, pnpm lint:spelling,
    pnpm build:packages and pnpm build:website:fast all pass.

Docs updated: markdown-features-links.mdx now has a "Cross-plugin links" section
replacing the warning that said this wasn't possible.

Markdown file references such as [link](../blog/post.md) could only be
resolved against the Markdown files of the plugin instance owning the
source file. Linking a doc to a blog post or to a standalone page was
therefore impossible.

The core now builds a site-wide Markdown files registry from the route
metadata (`sourceFilePath`), and hands it over to the MDX loader through
a new `resolveSiteMarkdownLink` option. Plugins keep resolving their own
links in priority, and the site-wide registry is only used as a
fallback, so versioned/localized docs keep resolving to the right file.

The registry object identity is stable and its content is refreshed in
place on site reloads, because the bundler config (and therefore the MDX
loader options) is only created once.

Closes facebook#9117
@meta-cla

meta-cla Bot commented Sep 10, 2026

Copy link
Copy Markdown

Hi @gauranshahuja!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@netlify

netlify Bot commented Sep 10, 2026

Copy link
Copy Markdown

[V2]

Built without sensitive environment variables

Name Link
🔨 Latest commit a4cec65
🔍 Latest deploy log https://app.netlify.com/projects/docusaurus-2/deploys/6aa25203941c3f00089e242d
😎 Deploy Preview https://deploy-preview-12431--docusaurus-2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@gauranshahuja

Copy link
Copy Markdown
Author

I have signed the CLA!

@meta-cla

meta-cla Bot commented Sep 10, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Signed Facebook CLA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relative markdown links between blog and docs does not work

1 participant