Turndown.js: 优雅地将 HTML 转换为 Markdown
在 web 开发中,我们经常需要在富文本编辑器(HTML)和 Markdown 格式之间进行转换。无论是为了存储用户输入、生成静态网站内容,还是简单地进行格式迁移,一个强大而灵活的 HTML-to-Markdown 转换工具都至关重要。今天,我们将介绍一个非常出色的 JavaScript 库:Turndown.js。
Turndown 是一个用 JavaScript 编写的、功能强大且高度可扩展的库,旨在将 HTML 内容无缝转换为干净、可读的 Markdown。
核心功能
- CommonMark 兼容: 生成标准的、兼容 CommonMark 的 Markdown。
- 可扩展性强: 可以通过添加自定义规则来处理特定的 HTML 标签。
- GFM (GitHub Flavored Markdown) 支持: 通过插件支持表格、删除线等 GFM 特性。
- 环境通用: 同时支持在 Node.js 服务端和浏览器环境中使用。
- 智能过滤: 可以选择性地保留或移除某些 HTML 元素。
基本用法
上手 Turndown 非常简单。
1. 安装
首先,根据你的项目环境安装 Turndown。
Node.js 环境:
使用 npm 或 yarn 安装:
npm install turndown
浏览器环境:
直接通过 script 标签引入:
<script src="https://unpkg.com/turndown/dist/turndown.js"></script>
2. 转换 HTML
使用 Turndown 非常直观。首先实例化一个 TurndownService
,然后调用它的 turndown
方法。
在 Node.js 中:
const TurndownService = require('turndown');
const turndownService = new TurndownService();
// 从 HTML 字符串转换
const htmlString = '<h1>你好,世界!</h1><p>这是一个 <em>重要</em> 的段落。</p>';
const markdown = turndownService.turndown(htmlString);
console.log(markdown);
// 输出:
// # 你好,世界!
//
// 这是一个 *重要* 的段落。
在浏览器中:
Turndown 也可以直接处理 DOM 节点。
<div id="content">
<h1>文章标题</h1>
<p>这是一个从 <b>DOM</b> 元素转换的例子。</p>
</div>
<script src="https://unpkg.com/turndown/dist/turndown.js"></script>
<script>
const turndownService = new TurndownService();
const markdown = turndownService.turndown(document.getElementById('content'));
console.log(markdown);
// 输出:
// # 文章标题
//
// 这是一个从 **DOM** 元素转换的例子。
</script>
3. 配置选项
在实例化 TurndownService
时,可以传入一个配置对象来自定义转换行为。
例如,你可以改变标题的样式或列表标记:
const turndownService = new TurndownService({
headingStyle: 'atx', // or 'setext'
hr: '---',
bulletListMarker: '-', // or '*', '+'
codeBlockStyle: 'fenced', // or 'indented'
emDelimiter: '_', // or '*'
});
注意事项和进阶用法
Turndown 的强大之处在于其灵活性。以下是一些使用时需要注意的关键点。
1. 字符转义 (Escaping)
这是一个非常重要的特性。为了防止 HTML 内容中的特殊字符被错误地解析为 Markdown 语法,Turndown 会对其进行转义。
例如,HTML <h3>1. 第一项</h3>
会被转换为 ### 1\. 第一项
。注意 1.
后面的反斜杠 \
,它确保了这行文本被正确地渲染为标题,而不是一个有序列表的开始。
需要注意: Turndown 的转义规则可能比较"激进"。如果你对转义行为有特殊需求,可以覆盖 TurndownService.prototype.escape
方法来实现自定义的转义逻辑。
2. 自定义规则 (Custom Rules)
这是 Turndown 最强大的功能之一。你可以添加自己的规则来定义如何转换特定的 HTML 元素。一个规则包含 filter
和 replacement
两个部分。
filter
: 用于选择要应用此规则的元素(可以是标签名、标签名数组或一个返回布尔值的函数)。replacement
: 一个函数,定义了如何将匹配到的元素转换为 Markdown。
示例:添加删除线规则
默认情况下,Turndown 不会处理 <s>
或 <del>
标签。我们可以轻松添加一个规则来支持它们:
turndownService.addRule('strikethrough', {
filter: ['del', 's', 'strike'],
replacement: function (content) {
return '~' + content + '~';
}
});
const markdown = turndownService.turndown('<p>这是一个<s>已删除</s>的文本。</p>');
console.log(markdown); // 输出: 这是一个~已删除~的文本。
3. 保留或移除特定标签
有时候,你可能不希望转换某些 HTML 标签,而是想在 Markdown 中保留它们的原样。keep()
方法可以实现这一点。
// 保留 <del> 和 <ins> 标签
turndownService.keep(['del', 'ins']);
const markdown = turndownService.turndown('<p>Hello <del>world</del><ins>World</ins></p>');
console.log(markdown); // 'Hello <del>world</del><ins>World</ins>'
与之相对,remove()
方法可以彻底移除某些标签及其内容。
// 移除 <del> 标签
turndownService.remove('del');
const markdown = turndownService.turndown('<p>Hello <del>world</del></p>');
console.log(markdown); // 'Hello '
4. 使用插件 (Plugins)
为了方便地扩展功能,Turndown 支持插件系统。最常用的插件是 turndown-plugin-gfm
,它增加了对 GitHub Flavored Markdown 的支持(如表格、任务列表等)。
// 需要先安装插件: npm install turndown-plugin-gfm
const turndownPluginGfm = require('turndown-plugin-gfm');
const gfm = turndownPluginGfm.gfm;
// 使用 GFM 插件
turndownService.use(gfm);
// 现在可以转换包含表格的 HTML 了
const tableHtml = '<table><tr><th>Name</th><th>Email</th></tr><tr><td>John</td><td>john@example.com</td></tr></table>';
const markdownTable = turndownService.turndown(tableHtml);
console.log(markdownTable);
总结
Turndown.js 是一个功能全面、设计精良的 HTML 到 Markdown 转换库。无论你是需要一个简单的转换器,还是一个能够处理复杂、自定义场景的强大工具,Turndown 都能满足你的需求。其清晰的 API、强大的规则引擎和插件系统,使其成为任何处理 Markdown 和 HTML 互转项目的首选。