Skip to content

fix: absolutize relative doc links and fix $ orphan in version interpolations#593

Merged
LakshanSS merged 1 commit into
openchoreo:mainfrom
rashadism:main
May 11, 2026
Merged

fix: absolutize relative doc links and fix $ orphan in version interpolations#593
LakshanSS merged 1 commit into
openchoreo:mainfrom
rashadism:main

Conversation

@rashadism

Copy link
Copy Markdown
Contributor

Summary

  • Relative doc links (./foo, ../foo, .mdx) in exported .md files were left relative, so consumers fetching a single .md had no base URL to resolve against. Now rewritten to absolute https://<site>/docs/<...>.md URLs against the doc's own location.
  • replaceVersionInterpolations matched {versions.X} but not the $ of ${versions.X}, leaving a stray $ in the output (e.g. tree/$main/samples). Regex now optionally consumes the leading $.

Sample

Before:

- [Deploy and Explore](../deploy-and-explore.md)
- [sample applications](https://github.com/openchoreo/openchoreo/tree/$main/samples)

After:

- [Deploy and Explore](https://openchoreo.dev/docs/getting-started/deploy-and-explore.md)
- [sample applications](https://github.com/openchoreo/openchoreo/tree/main/samples)

Test plan

  • npm run build produces .md files with absolute URLs for relative doc links.
  • .mdx references in source render as .md in the export.
  • External URLs, anchor-only links, and asset paths are untouched.
  • Code fences and inline code are not touched.
  • ${versions.githubRef} in <Link to={...}> resolves cleanly with no leftover $.

… `$` in version interpolations

Two bugs in the exported `.md` output that hurt LLM consumption:

1. Relative links (`./foo`, `../foo`, `.mdx` references) stayed relative
   in the exported file. An LLM fetching `/docs/<page>.md` standalone
   has no base URL to resolve them against, so the links are dead.
   Now resolved against the current doc's URL path and rewritten to
   absolute `https://<site>/docs/<...>.md` URLs. `.mdx` references are
   also normalized to `.md`. External, anchor-only, and asset links
   are left untouched, and rewriting skips fenced code blocks and
   inline code spans.

2. `replaceVersionInterpolations` matched `{versions.X}` but not the
   `$` of `${versions.X}`. JSX template-literal usages like
   `<Link to={`.../${versions.githubRef}/...`}>` survived the earlier
   `<Link>` extraction with the `{...}` portion already replaced and
   the `$` left behind, producing URLs like `tree/$main/samples`.
   Regex now optionally consumes the leading `$`.

Signed-off-by: Rashad Sirajudeen <rashad@wso2.com>
@coderabbitai

coderabbitai Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed relative links in exported markdown files to generate correct absolute URLs
    • Improved document URL path computation using site configuration
  • Enhancements

    • Enhanced version template interpolation to support additional syntax formats
    • Better preservation of link anchors and query strings during export

Walkthrough

The plugin now extracts site configuration (siteUrl, baseUrl) upfront and computes per-file docUrlPath values. It passes these as link context into processMarkdownFile, which rewrites relative markdown links to absolute .md URLs while preserving anchors, skipping code blocks, and normalizing file extensions. Version placeholder replacement also now supports optional $ prefixes.

Changes

Markdown Link URL Rewriting

Layer / File(s) Summary
URL Configuration Setup
plugins/docusaurus-plugin-markdown-export/index.js
Plugin extracts siteUrl and baseUrl from site config during initialization. siteUrl is normalized by trimming trailing slash; baseUrl defaults to '/' when unset.
Processor Function Signature
plugins/docusaurus-plugin-markdown-export/mdxProcessor.js
processMarkdownFile signature updated to accept linkContext parameter. New link rewriting processing step inserted before artifact cleanup, invoking rewriteRelativeDocLinks.
Link Rewriting Implementation
plugins/docusaurus-plugin-markdown-export/mdxProcessor.js
rewriteRelativeDocLinks utility and helpers convert relative markdown links to absolute site URLs, normalizing .mdx to .md, preserving #anchor and ?query, skipping code blocks/spans, and leaving external, schemed, and image links unchanged.
Version Placeholder Enhancement
plugins/docusaurus-plugin-markdown-export/mdxProcessor.js
Version interpolation replacement tolerates optional leading $, supporting both {versions.*} and ${versions.*} placeholder styles without orphan delimiters.
Export Path Integration
plugins/docusaurus-plugin-markdown-export/index.js
Both exportSingleFile and exportAllVersions compute per-file docUrlPath and pass it with siteUrl as linkContext into updated processMarkdownFile calls.

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: absolutizing relative doc links and fixing the $ orphan in version interpolations, which directly align with the changeset.
Description check ✅ Passed The PR description includes a clear summary of changes, sample outputs, and a comprehensive test plan, though it lacks the 'Related Issues' section and checklist items from the template.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@rashadism rashadism changed the title fix(markdown-export): absolutize relative doc links and fix $ orphan in version interpolations fix: absolutize relative doc links and fix $ orphan in version interpolations May 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/docusaurus-plugin-markdown-export/mdxProcessor.js (1)

83-84: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update step number to maintain sequential numbering.

Line 83 should say "Step 12" instead of "Step 11" now that a new Step 10 was added above.

📝 Proposed fix
-  // Step 11: Clean up excessive whitespace
+  // Step 12: Clean up excessive whitespace
   result = cleanupWhitespace(result);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/docusaurus-plugin-markdown-export/mdxProcessor.js` around lines 83 -
84, Update the inline comment before the cleanupWhitespace call to reflect the
new sequence number: change "Step 11: Clean up excessive whitespace" to "Step
12: Clean up excessive whitespace" in mdxProcessor.js so comments remain
sequential; the affected line is the comment immediately above the statement
"result = cleanupWhitespace(result);" which you should update.
🧹 Nitpick comments (1)
plugins/docusaurus-plugin-markdown-export/mdxProcessor.js (1)

318-335: 💤 Low value

Consider documenting the absolute-path assumption.

The resolvePath function works correctly for its current use case where paths are always absolute (e.g., /docs/foo/../bar), but it doesn't handle standalone relative paths correctly (e.g., foo/../bar would become foo/bar instead of bar). Since the function is always called with absolute paths (line 312 prepends baseDir + '/'), this is not a bug, but future maintainers might find the behavior surprising.

💡 Optional: Add a JSDoc comment
+/**
+ * Normalize an absolute path by collapsing '.', '..', and '//' segments.
+ * Note: This function expects absolute paths (starting with '/').
+ */
 function resolvePath(p) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/docusaurus-plugin-markdown-export/mdxProcessor.js` around lines 318 -
335, The resolvePath function assumes POSIX-style absolute paths and can produce
surprising results for standalone relative inputs; add a JSDoc comment above the
resolvePath function that clearly states the function expects an absolute POSIX
path (e.g., "/docs/foo/../bar"), describes how it collapses ".", "..", and
duplicate slashes, shows a short example of expected input/output, and documents
the return value (normalized absolute path or "/"). Also mention that callers
(e.g., where baseDir + '/' is prepended) must ensure paths are absolute so
future maintainers know the precondition.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@plugins/docusaurus-plugin-markdown-export/mdxProcessor.js`:
- Around line 83-84: Update the inline comment before the cleanupWhitespace call
to reflect the new sequence number: change "Step 11: Clean up excessive
whitespace" to "Step 12: Clean up excessive whitespace" in mdxProcessor.js so
comments remain sequential; the affected line is the comment immediately above
the statement "result = cleanupWhitespace(result);" which you should update.

---

Nitpick comments:
In `@plugins/docusaurus-plugin-markdown-export/mdxProcessor.js`:
- Around line 318-335: The resolvePath function assumes POSIX-style absolute
paths and can produce surprising results for standalone relative inputs; add a
JSDoc comment above the resolvePath function that clearly states the function
expects an absolute POSIX path (e.g., "/docs/foo/../bar"), describes how it
collapses ".", "..", and duplicate slashes, shows a short example of expected
input/output, and documents the return value (normalized absolute path or "/").
Also mention that callers (e.g., where baseDir + '/' is prepended) must ensure
paths are absolute so future maintainers know the precondition.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b93614ff-129c-45f1-a804-f77218b1307f

📥 Commits

Reviewing files that changed from the base of the PR and between 7b0ae88 and 22dcd06.

📒 Files selected for processing (2)
  • plugins/docusaurus-plugin-markdown-export/index.js
  • plugins/docusaurus-plugin-markdown-export/mdxProcessor.js

@LakshanSS
LakshanSS merged commit d0ad4a8 into openchoreo:main May 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants