字节笔记本

2026年2月22日

Turndown:HTML 转 Markdown 的 JavaScript 利器

本文介绍 Turndown,一个用于将 HTML 转换为 Markdown 的 JavaScript 库。Turndown 提供了灵活的配置选项和扩展机制,支持自定义转换规则,是处理富文本内容转换的实用工具。

项目简介

Turndown 是一个开源的 HTML 转 Markdown 转换器,由 mixmark-io 组织开发维护。截至目前,该项目在 GitHub 上已获得超过 10.8k stars 和 962 个 fork,是 JavaScript 生态中最流行的 HTML 转 Markdown 解决方案之一。

该项目最初名为 to-markdown,后更名为 Turndown。它可以将任意 HTML 内容转换为符合 CommonMark 规范的 Markdown 格式,支持浏览器和 Node.js 环境。

核心特性

  • 标准兼容:生成符合 CommonMark 规范的 Markdown
  • 灵活配置:提供丰富的选项自定义输出格式
  • 规则扩展:支持添加自定义转换规则
  • 插件系统:可通过插件扩展功能(如 GitHub Flavored Markdown)
  • 多环境支持:同时支持浏览器和 Node.js
  • DOM 友好:可直接处理 DOM 节点,无需字符串操作

技术栈

  • JavaScript:纯 JavaScript 实现,无外部依赖
  • CommonMark:遵循 CommonMark 规范
  • UMD 模块:支持 CommonJS、AMD 和全局变量

安装指南

Node.js 环境

bash
npm install turndown

浏览器环境

html
<script src="https://unpkg.com/turndown/dist/turndown.js"></script>

RequireJS 使用

UMD 版本位于:

  • lib/turndown.umd.js(Node.js)
  • lib/turndown.browser.umd.js(浏览器)

如需手动构建,克隆仓库后运行:

bash
npm run build

快速开始

Node.js 基础用法

javascript
var TurndownService = require('turndown')
var turndownService = new TurndownService()
var markdown = turndownService.turndown('<h1>Hello world!</h1>')

浏览器基础用法

javascript
var turndownService = new TurndownService()
var markdown = turndownService.turndown('<h1>Hello world!</h1>')

转换 DOM 元素

Turndown 也接受 DOM 节点作为输入(元素节点、文档节点或文档片段节点):

javascript
var markdown = turndownService.turndown(document.getElementById('content'))

配置选项

Turndown 提供丰富的配置选项,可在实例化时传入:

javascript
var turndownService = new TurndownService({
  headingStyle: 'atx',
  bulletListMarker: '-',
  codeBlockStyle: 'fenced'
})

主要选项

选项有效值默认值说明
headingStylesetextatxsetext标题样式
hr任意主题分隔符* * *水平线样式
bulletListMarker-, +, 或 **无序列表标记
codeBlockStyleindentedfencedindented代码块样式
fence\``~~~`\```代码围栏样式
emDelimiter_*_斜体分隔符
strongDelimiter**__**粗体分隔符
linkStyleinlinedreferencedinlined链接样式
linkReferenceStylefull, collapsed, 或 shortcutfull链接引用样式

使用示例

场景 1:基础 HTML 转换

javascript
const TurndownService = require('turndown')
const turndownService = new TurndownService()

const html = `
<h1>文章标题</h1>
<p>这是一段<strong>加粗</strong>和<em>斜体</em>的文本。</p>
<ul>
  <li>列表项 1</li>
  <li>列表项 2</li>
</ul>
`

const markdown = turndownService.turndown(html)
console.log(markdown)

输出:

markdown
文章标题
========

这是一段**加粗**和_斜体_的文本。

*   列表项 1
*   列表项 2

场景 2:自定义规则 - 处理删除线

javascript
turndownService.addRule('strikethrough', {
  filter: ['del', 's', 'strike'],
  replacement: function (content) {
    return '~~' + content + '~~'
  }
})

const html = '<p>Hello <del>world</del>World</p>'
const markdown = turndownService.turndown(html)
// 输出: Hello ~~world~~World

场景 3:保留特定 HTML 标签

javascript
turndownService.keep(['del', 'ins'])

const html = '<p>Hello <del>world</del><ins>World</ins></p>'
const markdown = turndownService.turndown(html)
// 输出: Hello <del>world</del><ins>World</ins>

场景 4:使用 GFM 插件

javascript
const TurndownService = require('turndown')
const turndownPluginGfm = require('turndown-plugin-gfm')

const turndownService = new TurndownService()
const gfm = turndownPluginGfm.gfm

// 使用 GFM 插件(支持表格、删除线等)
turndownService.use(gfm)

const html = `
<table>
  <tr><th>名称</th><th>值</th></tr>
  <tr><td>A</td><td>1</td></tr>
</table>
`

const markdown = turndownService.turndown(html)

API 参考

实例方法

turndown(html)

将 HTML 字符串或 DOM 节点转换为 Markdown。

addRule(key, rule)

添加自定义转换规则。

javascript
turndownService.addRule('customRule', {
  filter: 'div',
  replacement: function (content) {
    return '\n\n' + content + '\n\n'
  }
})

keep(filter)

指定哪些元素应保持为 HTML 格式而不转换。

javascript
turndownService.keep(['del', 'ins', 'mark'])

remove(filter)

指定哪些元素应被完全移除。

javascript
turndownService.remove('script')

use(plugin|array)

使用插件或插件数组。

javascript
turndownService.use(plugin)
turndownService.use([plugin1, plugin2])

规则结构

规则是一个包含 filterreplacement 属性的对象:

javascript
{
  filter: 'p',  // 字符串、数组或函数
  replacement: function (content, node, options) {
    return '\n\n' + content + '\n\n'
  }
}

Filter 类型

  • 字符串:匹配标签名(如 'p'
  • 数组:匹配多个标签(如 ['em', 'i']
  • 函数:自定义匹配逻辑
javascript
filter: function (node, options) {
  return node.nodeName === 'A' && node.getAttribute('href')
}

规则优先级

Turndown 按以下顺序匹配规则:

  1. 空白规则(Blank rule)
  2. 自定义规则(通过 addRule 添加)
  3. CommonMark 规则
  4. 保留规则(Keep rules)
  5. 移除规则(Remove rules)
  6. 默认规则(Default rule)

注意事项

  1. 转义处理:Turndown 使用反斜杠转义 Markdown 特殊字符,确保输出可被正确解析回 HTML
  2. 性能考虑:转义规则使用正则表达式,在某些场景下可能较为激进
  3. 空白处理:默认会折叠空白字符,如需保留原始格式可使用 preformattedCode 选项
  4. 插件依赖:GFM 插件需要单独安装 turndown-plugin-gfm

项目链接

许可证

Turndown 采用 MIT 许可证开源。

分享: