How Turndown Service Converts HTML to Markdown While Preserving Formatting in WeChat Article Exporter
The WeChat Article Exporter utilizes the Turndown library to parse HTML content into a DOM tree and apply rule-based transformations that convert specific tags into equivalent Markdown syntax, ensuring the original formatting and visual hierarchy remain intact.
The wechat-article/wechat-article-exporter project leverages Turndown Service to transform raw WeChat public account article HTML into structured Markdown documents. This conversion process systematically traverses the HTML document object model and maps elements to their Markdown counterparts while normalizing whitespace and maintaining nested structures.
Where HTML-to-Markdown Conversion Occurs
The codebase implements Turndown conversion in two primary locations to ensure consistent Markdown output across both file exports and API responses.
Single Article Export in Exporter.ts
In utils/download/Exporter.ts, the core export logic instantiates a new TurndownService and invokes the turndown method on the raw HTML content. Lines 411-419 handle this conversion when exporting individual articles, processing the contentHtml property through the service to generate the final Markdown string.
Public API Endpoint in download.get.ts
The server-side API endpoint defined in server/api/public/v1/download.get.ts performs the same transformation at line 66. This allows direct HTTP requests to retrieve articles in Markdown format, using an identical Turndown configuration to ensure output consistency across the application.
How Turndown Preserves Formatting During Conversion
Turndown operates through a rule-based system that traverses the parsed HTML DOM tree and applies specific conversion logic to each node type. This approach ensures that semantic meaning and visual structure translate accurately from HTML to Markdown.
Default HTML-to-Markdown Mappings
The library ships with comprehensive default rules that handle standard WeChat article elements. The conversion preserves the following mappings:
- Headings:
<h1>through<h6>convert to#through###### - Paragraphs:
<p>tags become text blocks separated by blank lines - Emphasis:
<strong>and<b>transform to**text**, while<em>and<i>become*text* - Lists:
<ul>items convert to-prefixed lines and<ol>items to1.numbered lists, with indentation preserved for nested structures - Links:
<a>elements render as[text](url)format - Images:
<img>tags convert tosyntax - Code:
<code>becomes inline backticks and<pre>transforms to fenced code blocks - Blockquotes:
<blockquote>prefixes lines with> - Horizontal Rules:
<hr>converts to---
During processing, the library normalizes excessive whitespace, removes empty nodes, and collapses consecutive line breaks. This normalization ensures the resulting Markdown mirrors the original article layout without carrying over HTML-specific formatting artifacts.
Handling Custom and Non-Standard Tags
While the WeChat Article Exporter currently relies on Turndown's default configuration, the library supports custom rules for specialized conversion needs. Developers can extend the service to handle custom tags or preserve specific inline styles that fall outside standard Markdown specifications using the addRule method.
Implementation Examples
The following code patterns demonstrate how the exporter implements Turndown conversion and how developers can extend the functionality.
Basic Conversion Pattern
This is the core implementation used in both Exporter.ts and download.get.ts:
import TurndownService from 'turndown';
// content represents the raw HTML string from the WeChat article
const turndownService = new TurndownService();
const markdown = turndownService.turndown(content);
Adding Custom Conversion Rules
For articles containing non-standard HTML elements, extend the service with custom filters:
import TurndownService from 'turndown';
const service = new TurndownService();
// Convert custom section tags to level-2 headings
service.addRule('section', {
filter: 'section',
replacement: function (content) {
return '\n## ' + content + '\n';
}
});
const markdown = service.turndown(html);
Using the Exporter Class Directly
The project provides a wrapper method for streamlined conversion:
import Exporter from '@/utils/download/Exporter';
// article object contains the contentHtml property
const exporter = new Exporter();
const markdown = exporter.exportToMarkdown(article);
Internally, exportToMarkdown instantiates the Turndown service and applies the standard conversion rules shown in the basic pattern above.
Summary
- Turndown Service parses HTML into a traversable DOM structure before applying conversion rules that map HTML elements to Markdown syntax.
- The conversion logic resides primarily in
utils/download/Exporter.ts(lines 411-419) andserver/api/public/v1/download.get.ts(line 66), ensuring consistent output across export methods and API endpoints. - Default rules handle standard WeChat article components including headings, lists, links, images, code blocks, and blockquotes while normalizing whitespace.
- The library supports custom rule definitions for handling proprietary HTML tags or specialized formatting requirements beyond the default Markdown specification.
Frequently Asked Questions
What HTML elements does Turndown convert to Markdown by default?
Turndown converts standard semantic HTML elements including headings (<h1>-<h6>), paragraphs (<p>), emphasis tags (<strong>, <em>), lists (<ul>, <ol>), links (<a>), images (<img>), code elements (<code>, <pre>), blockquotes (<blockquote>), and horizontal rules (<hr>). Each element maps to its GitHub-flavored Markdown equivalent while preserving nesting structures and content hierarchy.
Can I customize how specific HTML tags convert to Markdown in the exporter?
Yes, Turndown provides an addRule method that accepts a filter criteria and replacement function. You can target specific tag names, CSS classes, or attribute patterns and define custom Markdown output strings. This allows handling of WeChat-specific HTML elements that might not exist in the default rule set without modifying the core library.
How does the WeChat Article Exporter handle code blocks during conversion?
The exporter relies on Turndown's default handling of <pre> and <code> elements. Inline code within <code> tags converts to single backtick wrapping (`code`), while <pre> blocks become fenced code blocks using triple backticks. The conversion preserves the literal code content while stripping HTML tags, ensuring syntax remains intact for technical articles.
Where is the Turndown conversion configured in the source code?
The primary conversion occurs in utils/download/Exporter.ts at lines 411-419 within the single-article export method, and in server/api/public/v1/download.get.ts at line 66 for the public API endpoint. Both locations instantiate TurndownService with default configuration and call the turndown method on the article's HTML content string.
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 →