Markdown 処理系の比較

Markdown の基本文法は Markdown

PHP Markdown Extra にいくつか拡張文法が定義されている。PHP Markdown という名前だけど、他の Markdown 処理系でもこのうちのいくつかが実装されている。

拡張機能の比較

no intra emphasis
単語区切りのアンダースコアで斜体にしない
tables
PHP Markdown Extra 参照
fenced code blocks
GFM 参照
autolink
<> で囲まなくても URL を自動的にリンクにする。なくても必要なときに <> を囲むだけ
hard wrap
段落中の改行を <br> に変換する。なくても 2 つ以上のスペースで行を終わればいいだけ
definition lists
PHP Markdown Extra 参照
syntax highlighting
PygmentsCodeRay を用いる
extras \ library Sundown 系 Python-Markdown python-markdown2 cMarkdown
no intra emphasis YES YES (3) YES YES (3)
tables YES YES NO NO
fenced code blocks YES YES YES YES
autolink YES NO NO YES
hard wrap (1) YES NO YES
definition lists NO (2) YES NO NO
  • (1) Redcarpet と misaka は対応、Robotskirt は未対応
  • (2) 一応、対応検討中
  • (3) デフォルトで YES

Sundown

  • C で書かれた Markdown 処理系
  • 複数の言語のバインディングがある

    Redcarpet
    Ruby バインディング
    Robotskirt
    Node バインディング
    misaka
    Python バインディング

Python-Markdown

  • Pure Python

python-markdown2

  • Pure Python
  • Python-Markdown より速くて正確って作者は言ってる

cMarkdown

  • upskirt の Python バインディング
    • upskirt は Sundown の古いバージョン
  • Unicode 非対応
  • cMarkdown を選ぶなら misaka でいいと思う

ベンチマークによる比較

Python用のMarkdownを扱うモジュールを比較してみた参照。

python-markdown2 は Python-Markdown より確かに速いけど Sundown 系に比べるとずっと遅い。

コマンドラインサポート

すべてのライブラリで、コマンドラインで使うためのスクリプトが用意されている。でもカスタマイズ性に乏しい。

シンタックスハイライト

フラグでシンタックスハイライトを有効にできるのは Python-Markdown と python-markdown2 だけ。

Redcarpet

#!/usr/bin/env ruby
require 'redcarpet'
require 'pygments'

# from https://github.com/vmg/redcarpet
class HTMLwithPygments < Redcarpet::Render::HTML
  def block_code(code, language)
    Pygments.highlight(code, :lexer => language)
  end
end

parse_extensions = {
  :no_intra_emphasis => true,
  :tables => true,
  :fenced_code_blocks => true,
  :autolink => true
}

render_extensinos = {
  :hard_wrap => true
}

STDOUT.write Redcarpet::Markdown.new(HTMLwithPygments.new(render_extensinos),
                                     parse_extensions).render(ARGF.read)

<div class="highlight"><pre>...</pre></div> なコードブロックが生成される。

misaka

#!/usr/bin/env python
import codecs
import sys

import houdini as h
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
import misaka

# from http://misaka.61924.nl/manual/
class BleepRenderer(misaka.HtmlRenderer, misaka.SmartyPants):
    def block_code(self, text, lang):
        if not lang:
            return '\n<pre><code>%s</code></pre>\n' % \
                h.escape_html(text.strip())
        lexer = get_lexer_by_name(lang, stripall=True)
        formatter = HtmlFormatter()
        return highlight(text, lexer, formatter)

extensions = (misaka.EXT_NO_INTRA_EMPHASIS |
              misaka.EXT_TABLES |
              misaka.EXT_FENCED_CODE |
              misaka.EXT_AUTOLINK |
              misaka.HTML_HARD_WRAP)

if len(sys.argv) > 1:
    text = codecs.open(sys.argv[1], 'r', encoding='utf-8').read()
else:
    text = sys.stdin.read().decode(sys.stdin.encoding or 'utf-8')

sys.stdout.write(misaka.html(text, extensions=extensions)
                 .encode(sys.stdout.encoding or 'utf-8'))

<div class="highlight"><pre>...</pre></div> なコードブロックが生成される。lang 指定なしの場合は <pre><code>...</code></pre>(でもこれは BleepRenderer の定義次第)。

Python-Markdown

Pygments をインストールして codehilite を指定すればシンタックスハイライトされて、<div class="codehilite"><pre>...</pre></div> なコードブロックが生成される。

css クラス名を変更するにはコードを書く必要がある。

#!/usr/bin/env python
import codecs
import sys

import markdown

if len(sys.argv) > 1:
    text = codecs.open(sys.argv[1], 'r', encoding='utf-8').read()
else:
    text = sys.stdin.read().decode(sys.stdin.encoding or 'utf-8')

sys.stdout.write(
    markdown.markdown(
        text,
        extensions=['tables', 'fenced_code', 'codehilite', 'nl2br', 'def_list'],
        extension_configs={'codehilite': {'css_class': 'highlight'}})
    .encode(sys.stdout.encoding or 'utf-8'))

python-markdown2

Pygments がインストール済みで fenced-code-blocks を指定すれば自動的にシンタックスハイライトされて<div class="codehilite"><pre><code>...</code></pre></div> なコードブロックが生成される(<code> タグあり)。

css クラス名を変更するにはコードを書く必要がある。

#!/usr/bin/env python
import codecs
import sys

import markdown2

if len(sys.argv) > 1:
    text = codecs.open(sys.argv[1], 'r', encoding='utf-8').read()
else:
    text = sys.stdin.read().decode(sys.stdin.encoding or 'utf-8')

sys.stdout.write(
    markdown2.markdown(
        text,
        extras={'code-friendly': 1,
                'fenced-code-blocks': {'cssclass': 'highlight'}})
    .encode(sys.stdout.encoding or 'utf-8'))
  1. papaeye posted this