# How the linkRewrite Module Converts HTML Links to Markdown in DeepWiki MCP

> Discover how the linkRewrite module converts HTML links to Markdown. This Rehype plugin supports section anchors and relative file paths for DeepWiki MCP.

- Repository: [Kevin Kern/deepwiki-mcp](https://github.com/regenrek/deepwiki-mcp)
- Tags: internals
- Published: 2026-02-16

---

**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`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/lib/linkRewrite.ts), this plugin integrates directly into the unified processing pipeline defined in [`src/converter/htmlToMarkdown.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/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 `http` or `https`) 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:
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)`.

### 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:
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`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/converter/htmlToMarkdown.ts). The pipeline orchestrates the complete transformation from raw HTML to sanitized Markdown:

```typescript
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`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/lib/linkRewrite.ts), where the `rehypeRewriteLinks` function creates a transformer that traverses the HTML syntax tree:

```typescript
// 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`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/section.md)).
- The module integrates into the unified processing pipeline in [`src/converter/htmlToMarkdown.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/history.md)). The mode is specified via the `ModeEnum` type defined in [`src/schemas/deepwiki.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/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`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/schemas/deepwiki.ts).