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.

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 http or https) are skipped entirely and remain unchanged in the output.
  • Internal paths (typically starting with /) are rewritten according to the active mode.

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:

  1. Strip the leading slash from the path (/history becomes history)
  2. Prefix with a hash symbol (#)
  3. Result: href becomes #history

This allows navigation between sections in the aggregated Markdown output using standard anchor links like [History](#history).

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:

  1. Strip the leading slash from the path (/api/reference becomes api/reference)
  2. Append the .md extension
  3. Result: href becomes api/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.ts is 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 default page (converting links to relative Markdown files like section.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

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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →