markdown-it vs showdown vs remarkable
前端 Markdown 解析器选型对比
markdown-itshowdownremarkable类似的npm包:

前端 Markdown 解析器选型对比

markdown-itremarkableshowdown 都是用于将 Markdown 文本转换为 HTML 的 JavaScript 库,适用于在浏览器或 Node.js 环境中渲染用户输入的 Markdown 内容。它们都支持标准 CommonMark 语法,并提供扩展机制以支持自定义功能(如任务列表、脚注、高亮等)。这些库广泛用于博客系统、文档站点、富文本编辑器预览和内容管理系统中,核心目标是在保证安全性和性能的前提下,提供灵活、可配置的 Markdown 渲染能力。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
markdown-it19,129,85721,116768 kB5824 天前MIT
showdown1,440,93814,836801 kB233-MIT
remarkable1,193,7055,824-1326 年前MIT

Markdown 解析器深度对比:markdown-it vs remarkable vs showdown

在前端开发中,将用户输入的 Markdown 安全高效地渲染为 HTML 是常见需求。markdown-itremarkableshowdown 是三个主流选择,但它们在架构、扩展性和维护状态上差异显著。本文从工程实践角度,对比三者的核心能力。

⚙️ 架构与扩展机制:插件化 vs 选项配置 vs 固定功能

markdown-it 采用基于插件的模块化架构,所有核心功能(包括链接、图片)都可通过插件启用或替换。它暴露完整的解析器(parser)、渲染器(renderer)和规则链(rules),允许深度干预解析过程。

// markdown-it: 插件扩展
import MarkdownIt from 'markdown-it';
import markdownItTaskLists from 'markdown-it-task-lists';

const md = new MarkdownIt()
  .use(markdownItTaskLists); // 启用任务列表插件

const html = md.render('- [x] done');

remarkable 提供有限的内置扩展(如 breakslinkify),但不支持第三方插件。其扩展需通过直接修改内部规则实现,灵活性较低。

// remarkable: 内置选项配置
import Remarkable from 'remarkable';

const md = new Remarkable({
  breaks: true,        // 转换 \n 为 <br>
  linkify: true        // 自动识别 URL
});

const html = md.render('Visit https://example.com');

showdown 使用选项(options)和扩展(extensions)两种方式。扩展需通过全局注册或实例方法添加,但 API 较为冗长。

// showdown: 扩展注册
import showdown from 'showdown';

showdown.extension('myext', function() {
  return [
    {
      type: 'output',
      filter: function(text) {
        return text.replace(/@\w+/g, '<code>$&</code>');
      }
    }
  ];
});

const converter = new showdown.Converter({ extensions: ['myext'] });
const html = converter.makeHtml('Mention @user');

💡 关键区别markdown-it 的插件机制最灵活,适合复杂定制;showdown 的扩展需手动编写过滤器;remarkable 几乎无法扩展新语法。

🛡️ 安全性:XSS 防护能力

三者默认均不自动转义 HTML 标签,这意味着如果用户输入包含 <script>,会直接输出到 HTML 中,造成 XSS 风险。开发者必须显式启用转义或使用 sanitize 库。

markdown-it 推荐通过 html: false 禁用原生 HTML,并配合 markdown-it-sanitizer 等插件处理。

// markdown-it: 禁用 HTML + 安全插件
const md = new MarkdownIt({ html: false })
  .use(require('markdown-it-sanitizer'));

remarkable 同样需设置 html: false,但无官方安全插件。

// remarkable: 禁用 HTML
const md = new Remarkable({ html: false });

showdown 通过 noHeaderIdghCompatibleHeaderId 等选项间接提升安全,但核心仍需依赖 sanitize-html 等外部库。

// showdown: 配合 sanitize-html
import sanitizeHtml from 'sanitize-html';
const dirty = converter.makeHtml(userInput);
const clean = sanitizeHtml(dirty);

⚠️ 重要提醒:无论选择哪个库,都必须额外处理 XSS 防护。不要依赖解析器默认行为。

🧪 语法兼容性与标准遵循

  • markdown-it 严格遵循 CommonMark 0.30 规范,并通过官方测试套件验证。对 GFM(GitHub Flavored Markdown)的支持通过插件(如 markdown-it-gfm)实现。
  • remarkable 基于早期 CommonMark 草案,部分边缘情况(如嵌套列表、引用块)与标准存在差异。
  • showdown 兼容 CommonMark,但默认行为更接近传统 Markdown(如不支持表格),需开启 tables: true 等选项。
// 表格支持对比
const tableMd = '| a | b |\n|---|---|\n| 1 | 2 |';

// markdown-it: 需插件
md.use(require('markdown-it-tables'));

// showdown: 需选项
new showdown.Converter({ tables: true });

// remarkable: 不支持表格(需手动 hack)

🚫 维护状态:是否适合新项目?

  • remarkable已停止维护。其 GitHub 仓库 README 明确写道:“此项目不再积极开发。推荐使用 markdown-it。” 新项目应避免选用。
  • markdown-itshowdown 均处于活跃维护状态,定期发布更新并修复安全问题。

🔧 实际工程场景推荐

场景 1:构建文档站点(如 Docusaurus 替代方案)

  • 需求:支持 GFM、代码高亮、自定义容器(如 :::tip)、SEO 友好。
  • 推荐markdown-it
  • 理由:丰富的插件生态(markdown-it-highlightjsmarkdown-it-container)可快速实现所需功能,且 AST 支持便于静态分析。
// markdown-it 示例:自定义容器
md.use(require('markdown-it-container'), 'tip', {
  validate: params => params.trim().match(/^tip\s+(.*)$/),
  render: (tokens, idx) => {
    if (tokens[idx].nesting === 1) {
      return '<div class="tip">';
    } else {
      return '</div>';
    }
  }
});

场景 2:用户评论系统(简单 Markdown 支持)

  • 需求:基础语法(粗体、链接、列表)、自动转义、轻量级。
  • 推荐showdown
  • 理由:配置简单,无需复杂插件,配合 sanitize-html 即可满足安全需求。
// showdown 示例:基础配置
const converter = new showdown.Converter({
  simpleLineBreaks: true,
  strikethrough: true
});

场景 3:遗留系统维护

  • 现状:已有 remarkable 集成,功能稳定无扩展需求。
  • 建议:继续使用,但不要在新模块中引入。规划迁移至 markdown-it

📊 总结:核心差异速查表

特性markdown-itremarkableshowdown
扩展机制插件系统(高度灵活)内置选项(不可扩展)扩展 + 选项
CommonMark 兼容✅ 严格遵循⚠️ 部分兼容✅(需配置)
维护状态✅ 活跃❌ 已停止✅ 活跃
XSS 防护需手动配置 + 插件需手动配置需手动配置 + 外部库
适用场景复杂定制、文档平台遗留系统快速集成、简单需求

💡 最终建议

  • 新项目首选 markdown-it:它的插件生态和标准兼容性为未来扩展留足空间。
  • 避免 remarkable:除非维护旧代码,否则不要引入已废弃的依赖。
  • showdown 作为轻量备选:当项目简单、团队熟悉其 API 时可考虑,但需自行处理安全和高级功能。

无论选择哪个库,请始终记住:Markdown 解析只是第一步,安全渲染才是关键

如何选择: markdown-it vs showdown vs remarkable

  • markdown-it:

    选择 markdown-it 如果你需要高度可扩展的解析器,支持插件生态、细粒度的 AST 操作,以及对 CommonMark 标准的严格遵循。它适合构建需要深度定制(如自定义语法、安全过滤、语法高亮集成)的复杂应用,例如文档平台或开发者工具。

  • showdown:

    选择 showdown 如果你需要一个简单易用、开箱即用的解析器,且偏好基于选项(options)而非插件的配置方式。它适合快速集成到中小型项目中(如评论系统、静态站点生成器),尤其当你不需要复杂的 AST 操作或高性能要求时。

  • remarkable:

    选择 remarkable 如果你追求极致的解析速度和简洁的 API,且不需要频繁扩展功能。但需注意:该库已不再积极维护,官方 GitHub 仓库明确建议新项目使用 markdown-it。因此,仅在遗留系统维护或对性能有极端要求且功能固定的场景下考虑。

markdown-it的README

markdown-it

CI NPM version Coverage Status Gitter

Markdown parser done right. Fast and easy to extend.

Live demo

  • Follows the CommonMark spec + adds syntax extensions & sugar (URL autolinking, typographer).
  • Configurable syntax! You can add new rules and even replace existing ones.
  • High speed.
  • Safe by default.
  • Community-written plugins and other packages on npm.

Table of content

Install

node.js:

npm install markdown-it

browser (CDN):

Usage examples

See also:

Simple

// node.js
// can use `require('markdown-it')` for CJS
import markdownit from 'markdown-it'
const md = markdownit()
const result = md.render('# markdown-it rulezz!');

// browser with UMD build, added to "window" on script load
// Note, there is no dash in "markdownit".
const md = window.markdownit();
const result = md.render('# markdown-it rulezz!');

Single line rendering, without paragraph wrap:

import markdownit from 'markdown-it'
const md = markdownit()
const result = md.renderInline('__markdown-it__ rulezz!');

Init with presets and options

(*) presets define combinations of active rules and options. Can be "commonmark", "zero" or "default" (if skipped). See API docs for more details.

import markdownit from 'markdown-it'

// commonmark mode
const md = markdownit('commonmark')

// default mode
const md = markdownit()

// enable everything
const md = markdownit({
  html: true,
  linkify: true,
  typographer: true
})

// full options list (defaults)
const md = markdownit({
  // Enable HTML tags in source
  html:         false,

  // Use '/' to close single tags (<br />).
  // This is only for full CommonMark compatibility.
  xhtmlOut:     false,

  // Convert '\n' in paragraphs into <br>
  breaks:       false,

  // CSS language prefix for fenced blocks. Can be
  // useful for external highlighters.
  langPrefix:   'language-',

  // Autoconvert URL-like text to links
  linkify:      false,

  // Enable some language-neutral replacement + quotes beautification
  // For the full list of replacements, see https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.mjs
  typographer:  false,

  // Double + single quotes replacement pairs, when typographer enabled,
  // and smartquotes on. Could be either a String or an Array.
  //
  // For example, you can use '«»„“' for Russian, '„“‚‘' for German,
  // and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
  quotes: '“”‘’',

  // Highlighter function. Should return escaped HTML,
  // or '' if the source string is not changed and should be escaped externally.
  // If result starts with <pre... internal wrapper is skipped.
  highlight: function (/*str, lang*/) { return ''; }
});

Plugins load

import markdownit from 'markdown-it'

const md = markdownit
  .use(plugin1)
  .use(plugin2, opts, ...)
  .use(plugin3);

Syntax highlighting

Apply syntax highlighting to fenced code blocks with the highlight option:

import markdownit from 'markdown-it'
import hljs from 'highlight.js' // https://highlightjs.org

// Actual default values
const md = markdownit({
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(str, { language: lang }).value;
      } catch (__) {}
    }

    return ''; // use external default escaping
  }
});

Or with full wrapper override (if you need assign class to <pre> or <code>):

import markdownit from 'markdown-it'
import hljs from 'highlight.js' // https://highlightjs.org

// Actual default values
const md = markdownit({
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return '<pre><code class="hljs">' +
               hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
               '</code></pre>';
      } catch (__) {}
    }

    return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
  }
});

Linkify

linkify: true uses linkify-it. To configure linkify-it, access the linkify instance through md.linkify:

md.linkify.set({ fuzzyEmail: false });  // disables converting email to link

API

API documentation

If you are going to write plugins, please take a look at Development info.

Syntax extensions

Embedded (enabled by default):

Via plugins:

Manage rules

By default all rules are enabled, but can be restricted by options. On plugin load all its rules are enabled automatically.

import markdownit from 'markdown-it'

// Activate/deactivate rules, with currying
const md = markdownit()
  .disable(['link', 'image'])
  .enable(['link'])
  .enable('image');

// Enable everything
const md = markdownit({
  html: true,
  linkify: true,
  typographer: true,
});

You can find all rules in sources:

Benchmark

Here is the result of readme parse at MB Pro Retina 2013 (2.4 GHz):

npm run benchmark-deps
benchmark/benchmark.mjs readme

Selected samples: (1 of 28)
 > README

Sample: README.md (7774 bytes)
 > commonmark-reference x 1,222 ops/sec ±0.96% (97 runs sampled)
 > current x 743 ops/sec ±0.84% (97 runs sampled)
 > current-commonmark x 1,568 ops/sec ±0.84% (98 runs sampled)
 > marked x 1,587 ops/sec ±4.31% (93 runs sampled)

Note. CommonMark version runs with simplified link normalizers for more "honest" compare. Difference is ≈1.5×.

As you can see, markdown-it doesn't pay with speed for its flexibility. Slowdown of "full" version caused by additional features not available in other implementations.

markdown-it for enterprise

Available as part of the Tidelift Subscription.

The maintainers of markdown-it and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

Authors

markdown-it is the result of the decision of the authors who contributed to 99% of the Remarkable code to move to a project with the same authorship but new leadership (Vitaly and Alex). It's not a fork.

References / Thanks

Big thanks to John MacFarlane for his work on the CommonMark spec and reference implementations. His work saved us a lot of time during this project's development.

Related Links:

Ports