How the linkRewrite Module Converts HTML Links to Markdown in DeepWiki MCP
The linkRewrite module is a Rehype plugin that transforms internal HTML anchor tags into Markdown-compatible links, supporting both section anchors for aggregated documents and relative file paths for multi-page outputs.
DeepWiki MCP relies on the linkRewrite module to ensure that internal navigation links remain functional when converting raw HTML documentation into Markdown format. Located in src/lib/linkRewrite.ts, this plugin integrates directly into the unified processing pipeline defined in src/converter/htmlToMarkdown.ts, where it selectively rewrites <a> tags based on the configured output mode.
What Is the linkRewrite Module?
The linkRewrite module exports a factory function called rehypeRewriteLinks that creates a Rehype plugin for transforming link nodes in the HTML abstract syntax tree (AST). Unlike generic HTML-to-Markdown converters, this module specifically handles internal wiki links—those pointing to other pages or sections within the same documentation set—while preserving external URLs unchanged.
The plugin accepts an options object containing the processing mode (defined in src/schemas/deepwiki.ts as ModeEnum), which determines whether the output should target a single aggregated document or multiple separate pages.
How linkRewrite Transforms Internal Links
When processing the HTML tree using unist-util-visit, the plugin inspects every element node with tagName === 'a'. It extracts the href property and applies the following logic:
- External URLs (those starting with
httporhttps) are skipped entirely and remain unchanged in the output. - Internal paths (typically starting with
/) are rewritten according to the active mode.
Aggregate Mode: Converting Links to Section Anchors
In aggregate mode, the linkRewrite module prepares links for a single-page Markdown document where all content is merged. Internal links are converted to hash anchors pointing to specific sections within the same file.
The transformation follows this pattern:
- Strip the leading slash from the path (
/historybecomeshistory) - Prefix with a hash symbol (
#) - Result:
hrefbecomes#history
This allows navigation between sections in the aggregated Markdown output using standard anchor links like [History](#history).
Default Mode: Converting Links to Markdown File References
In the default page mode, the module generates links suitable for multi-file documentation structures. Each internal link is converted to a relative Markdown file reference.
The transformation follows this pattern:
- Strip the leading slash from the path (
/api/referencebecomesapi/reference) - Append the
.mdextension - Result:
hrefbecomesapi/reference.md
This produces valid Markdown links like [API Reference](api/reference.md) that resolve correctly when the documentation is split across multiple files.
The HTML-to-Markdown Pipeline Integration
The linkRewrite module does not operate in isolation; it is embedded within a unified processing chain defined in src/converter/htmlToMarkdown.ts. The pipeline orchestrates the complete transformation from raw HTML to sanitized Markdown:
const file = await unified()
.use(rehypeParse, { fragment: true }) // Parse raw HTML
.use(rehypeSanitize, sanitizeSchema) // Strip unsafe nodes
.use(rehypeRewriteLinks, { mode }) // ← linkRewrite module
.use(rehypeRemark) // Convert to remark tree
.use(remarkGfm) // GitHub-flavored markdown
.use(remarkStringify, { fences: true }) // Serialize to Markdown
.process(html);
The sanitizeSchema imported from src/lib/sanitizeSchema.ts runs before link rewriting to ensure that only safe HTML elements enter the transformation pipeline. The mode parameter—passed from the calling context and validated against ModeEnum—determines which rewriting strategy the linkRewrite module applies to internal anchors.
Code Implementation Details
The core logic resides in src/lib/linkRewrite.ts, where the rehypeRewriteLinks function creates a transformer that traverses the HTML syntax tree:
// src/lib/linkRewrite.ts (simplified)
export function rehypeRewriteLinks({ mode }) {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName !== 'a') return;
const href = node.properties?.href;
if (!href || href.startsWith('http')) return;
// Rewrite based on mode
node.properties.href =
mode === 'aggregate'
? `#${href.replace(/^\//, '')}`
: `${href.replace(/^\//, '')}.md`;
});
};
}
This implementation uses the visit utility from unist-util-visit to efficiently traverse only element nodes, minimizing overhead. The regular expression /^\// ensures that leading slashes are removed regardless of the path depth, creating consistent relative references whether the original link points to /history or /api/v2/endpoints.
Summary
- The linkRewrite module in
src/lib/linkRewrite.tsis a specialized Rehype plugin that transforms internal HTML links during the HTML-to-Markdown conversion process. - It operates in two distinct modes:
aggregate(converting links to section anchors like#section) and defaultpage(converting links to relative Markdown files likesection.md). - The module integrates into the unified processing pipeline in
src/converter/htmlToMarkdown.ts, running after sanitization but before the HTML-to-remark conversion. - External URLs are preserved unchanged, while internal paths are normalized by stripping leading slashes and appending appropriate suffixes based on the output mode.
Frequently Asked Questions
How does the linkRewrite module handle external versus internal links?
The module inspects the href property of every anchor tag. If the value starts with http or https, the link is considered external and is skipped entirely, preserving the original URL. All other links—typically internal paths starting with /—are processed according to the active mode, with leading slashes removed and either .md extensions or # anchors appended.
What is the difference between aggregate mode and page mode in linkRewrite?
In aggregate mode, the module prepares links for a single consolidated Markdown document by converting internal paths to hash anchors (e.g., /history becomes #history). In page mode (the default), the module generates relative file references for multi-page documentation by appending .md to the path (e.g., /history becomes history.md). The mode is specified via the ModeEnum type defined in src/schemas/deepwiki.ts.
Where does the linkRewrite module fit in the HTML-to-Markdown conversion pipeline?
The plugin is inserted into the unified processor chain in src/converter/htmlToMarkdown.ts immediately after the rehypeSanitize step and before rehypeRemark. This positioning ensures that HTML is first parsed and sanitized, then internal links are rewritten according to the selected mode, and finally the modified tree is converted to a remark AST for Markdown serialization.
Can the linkRewrite module be customized to support additional link formats?
Yes, the module is designed as a standalone Rehype plugin in src/lib/linkRewrite.ts, making it straightforward to extend. Developers can modify the visit callback logic to handle additional URL patterns, change the regular expressions used for path normalization, or introduce new modes beyond aggregate and page by extending the ModeEnum schema in src/schemas/deepwiki.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →