markdown-it vs showdown vs remarkable
Markdownパーサーの選定:markdown-it、remarkable、showdownを比較
markdown-itshowdownremarkable類似パッケージ:

Markdownパーサーの選定:markdown-it、remarkable、showdownを比較

markdown-itremarkableshowdown はいずれもJavaScriptでMarkdownをHTMLに変換するためのライブラリです。これらは共通してCommonMark準拠や拡張性を重視しつつ、それぞれ異なる設計哲学とAPIスタイルを持っています。markdown-itはプラグインによる柔軟な拡張を特徴とし、remarkableは高速かつ安全な出力を目指して開発されましたが、現在は非推奨となっています。showdownは長年にわたり安定した実績を持ち、シンプルなAPIと豊富なオプション設定が特徴です。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
markdown-it19,129,85721,116768 kB5824日前MIT
showdown1,440,93814,836801 kB233-MIT
remarkable1,193,7055,824-1326年前MIT

Markdownパーサーの選定:markdown-it、remarkable、showdownを比較

フロントエンド開発でMarkdownをHTMLに変換する必要があるとき、markdown-itremarkableshowdownはよく検討される選択肢です。しかし、それぞれの設計思想、拡張性、メンテナンス状況には大きな違いがあります。この記事では、実際のコード例を交えながら、技術的な観点から深く比較します。

⚠️ メンテナンス状況:非推奨パッケージに注意

まず重要なのは、remarkableは非推奨であることです。npmページおよびGitHubリポジトリには明確に「DEPRECATED」と記載されており、2017年以降の更新はありません。新規プロジェクトでの使用は避けてください。

一方、markdown-itshowdownはともにアクティブにメンテナンスされており、TypeScript定義や最新のセキュリティ対応も整っています。

🧩 拡張性:プラグイン機構の違い

markdown-it: プラグインファースト設計

markdown-itは、コア機能を最小限に抑え、ほぼすべての機能をプラグインで提供します。たとえば、テーブルや脚注を有効にするには別途プラグインをインストール・登録する必要があります。

// markdown-it: プラグインで機能を追加
import MarkdownIt from 'markdown-it';
import markdownItTable from 'markdown-it-table';

const md = new MarkdownIt().use(markdownItTable);

const html = md.render('| A | B |\n|---|---|\n| 1 | 2 |');
// 出力: <table>...</table>

この設計により、不要な機能を含めずに軽量に保てます。また、独自のルール(トークン)を追加することも容易です。

showdown: ビルトインオプションと拡張ポイント

showdownは多くの機能をオプションとして内蔵しています。たとえば、GitHub風のコードブロックやテーブルはフラグを立てるだけで有効になります。

// showdown: オプションで機能を有効化
import showdown from 'showdown';

const converter = new showdown.Converter({
  tables: true,
  ghCodeBlocks: true
});

const html = converter.makeHtml('| A | B |\n|---|---|\n| 1 | 2 |');
// 出力: <table>...</table>

さらに、addExtensionメソッドでカスタム拡張も可能です。

// showdown: カスタム拡張
showdown.extension('myExt', function() {
  return [
    {
      type: 'output',
      regex: /MY_TOKEN/g,
      replace: '<span class="my-token">MY_TOKEN</span>'
    }
  ];
});

const converter = new showdown.Converter({ extensions: ['myExt'] });

remarkable: 非推奨のため拡張性は考慮不要

remarkableもかつては拡張可能でしたが、現在はメンテナンスされていないため、新規開発での採用は推奨されません。

// remarkable: 非推奨のため使用しない
// const Remarkable = require('remarkable');
// const md = new Remarkable();

🛡️ セキュリティ:XSS対策の有無

MarkdownはHTMLに変換されるため、悪意ある入力からXSSを防ぐ必要があります。

  • markdown-it: コアではサニタイズを行いませんが、markdown-it-sanitizerなどのサードパーティプラグインで対応可能です。
// markdown-it + サニタイズプラグイン
import MarkdownIt from 'markdown-it';
import sanitizer from 'markdown-it-sanitizer';

const md = new MarkdownIt().use(sanitizer);
  • showdown: sanitizeオプションをtrueにすることで、基本的なXSS対策が有効になります。
// showdown: 組み込みサニタイズ
const converter = new showdown.Converter({ sanitize: true });
const html = converter.makeHtml('![img](javascript:alert(1))');
// 出力: <p>![img]()</p> (危険な部分が除去される)
  • remarkable: サニタイズ機能はありますが、非推奨のため信頼性に欠けます。

🧪 AST(抽象構文木)へのアクセス

高度な処理(例:静的解析、カスタムレンダリング)を行う場合、ASTへのアクセスが重要です。

  • markdown-it: parseメソッドでトークン配列(AST相当)を取得できます。
// markdown-it: AST取得
const tokens = md.parse('# Hello', {});
console.log(tokens);
// [{ type: 'heading_open', ... }, { type: 'inline', ... }, ...]
  • showdown: 標準ではASTを公開していません。内部のparsertokenizerは非公開APIのため、直接操作は推奨されません。

  • remarkable: parseメソッドでASTを取得可能でしたが、非推奨のため使用できません。

📦 利用シーン別の推奨

エディタやリアルタイムプレビューが必要な場合

markdown-itが最適です。ASTへのアクセスと細かいイベントフックにより、カーソル位置に応じたプレビュー表示や構文強調が容易に実装できます。

シンプルなブログやCMSでの静的変換

showdownが手軽です。オプション一発でテーブルやコードブロックが有効になり、サニタイズも組み込みで対応できます。

既存のremarkable利用プロジェクト

早急にmarkdown-itまたはshowdownへの移行を検討してください。非推奨ライブラリのまま運用を続けると、セキュリティリスクや依存関係の断絶が発生します。

📌 まとめ:技術的トレードオフ

観点markdown-itshowdownremarkable
メンテナンス✅ アクティブ✅ アクティブ❌ 非推奨
拡張性⭐⭐⭐ プラグイン中心⭐⭐ オプション+拡張⭐(非推奨)
セキュリティプラグイン依存組み込みサニタイズ古い実装
ASTアクセス✅ 公式API❌ 非公開✅(非推奨)
学習コスト中〜高低〜中低(非推奨)

💡 最終的なアドバイス

  • 新規プロジェクトでは、remarkableを絶対に使わないでください。
  • 柔軟性と将来性を求めるなら → markdown-it
  • シンプルさと即時性を求めるなら → showdown

どちらを選ぶにせよ、ユーザー入力からのXSSリスクを常に意識し、適切なサニタイズを実装することが必須です。

選び方: markdown-it vs showdown vs remarkable

  • markdown-it:

    markdown-itは、高度なカスタマイズや拡張が必要なプロジェクトに最適です。公式およびコミュニティ製の多数のプラグインがあり、構文ハイライト、テーブル、脚注など、幅広い機能を簡単に追加できます。AST(抽象構文木)へのアクセスも可能で、静的解析や変換処理にも対応します。大規模アプリやエディタ統合など、柔軟性が求められる場面で選ぶべきです。

  • showdown:

    showdownはシンプルで安定したMarkdown変換を必要とするプロジェクトに向いています。多くのオプション設定(例:ghCodeBlockstables)をビルトインで提供し、プラグイン機構も備えています。TypeScriptサポートも整っており、ドキュメントも充実しています。ただし、拡張性やパフォーマンス面ではmarkdown-itに劣る場合があるため、中規模以下の用途や既存システムとの互換性を重視する場合に適しています。

  • remarkable:

    remarkableは2017年以降更新が停止されており、npmおよびGitHub上で非推奨(deprecated)と明記されています。新規プロジェクトでは使用しないでください。既存プロジェクトで利用している場合は、markdown-itshowdownへの移行を検討すべきです。過去には高速かつ安全な出力が評価されていましたが、現在はメンテナンスされていないため脆弱性リスクがあります。

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