おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

Redcarpet2のざっくりまとめ

githubで使われているMarkdown用ライブラリRedcarpet後方互換性のない version 2 になるみたいです。現時点のバージョンは 2.0.0b3 で、まだ本リリースではないようですが、これから使うなら2の方を勉強しておくべきだと思うのでまとめます。

基本的にいつものようなREADMEの意訳です。

基本情報

  • Redcapet は Redcloth の代換として使われてきたけど、バージョン2からは独自のAPIを持つようになる。
  • Redcarpet は Sundown という名前の Markdown をパースする拡張ライブラリを利用している。詳しくはこちら

インストール

下記のようにインストールする(ただし、現在は普通にインストールすると1系が入ります)。native extensionsがビルドされるけど、スタンドアロンなので他のライブラリをインストールしておく必要は無い。

gem install redcarpet

ソースはgithubから。

git clone git://github.com/tanoku/redcarpet.git

使い方

RedcarpetのコアはRedcarpet::Markdownクラス。それぞれのインスタンスにはRendererオブジェクトが付いてくる。Markdownクラスはドキュメントをパースして、rendererを使って出力する。


Markdownオブジェクトは必要な設定と共に一度生成されて、パースするたびに再利用される。

Markdown.new(renderer, extensions={})

rendererはRedcarpet::Render::Baseを継承している描画用のオブジェクト。もし与えられたオブジェクトがインスタンス化されていなかったら、ライブラリはデフォルトの引数でインスタンス化する。

Markdown#renderでMarkdownを描画する。RedCloth API とは異なり、Markdownインスタンスに描画したいテキストを引数として渡す。これによりインスタンスの再利用が出来る。

以下からextensionsで使えるオプションの説明に入ります。

no_intra_emphasis

単語中では強調をパースしない。

Redcarpet::Markdown.new(Redcarpet::Render::HTML).render('hoge_fuga_foo')
# => "<p>hoge<em>fuga</em>foo</p>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :no_intra_emphasis => true).render('hoge_fuga_foo')
# => "<p>hoge_fuga_foo</p>\n"

tables

PHP-Markdownスタイルでtableをパースするらしい

string =<<EOF
First Header  | Second Header
------------- | -------------
Content Cell  | Content Cell
Content Cell  | Content Cel
EOF

Redcarpet::Markdown.new(Redcarpet::Render::HTML).render(string)
# => "<p>First Header  | Second Header\n------------- | -------------\nContent Cell  | Content Cell\nContent Cell  | Content Cel</p>\n"

Redcarpet::Markdown.new(Redcarpet::Render::HTML, :tables => true).render(string)
# => "<table><thead>\n<tr>\n<td>First Header</td>\n<td>Second Header</td>\n</tr>\n</thead><tbody>\n<tr>\n<td>Content Cell</td>\n<td>Content Cell</td>\n</tr>\n<tr>\n<td>Content Cell</td>\n<td>Content Cel</td>\n</tr>\n</tbody></table>\n"

fenced_code_blocks

PHP-Markdownスタイルでfence code blocksをパースする。~~~ または ``` とするとコードと識別される。インデントは必要ない。オプションとして言語の名前を ~~~ruby のように付けることが出来る。

string =<<EOF
```ruby
puts 'hello world'
```
EOF
Redcarpet::Markdown.new(Redcarpet::Render::HTML).render(string)
# => "<p><code>ruby\nputs 'hello world'\n</code></p>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true).render(string)
# => "<pre><code class=\"ruby\">puts 'hello world'\n</code></pre>\n"

autolink

http, https, ftp やメールアドレスを自動でリンクにする。httpで始まってなくても 'www.' で始まっていたらリンクにする。

Redcarpet::Markdown.new(Redcarpet::Render::HTML).render('http://d.hatena.ne.jp/willnet')
# => "<p>http://d.hatena.ne.jp/willnet</p>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true).render('http://d.hatena.ne.jp/willnet')
# => "<p><a href=\"http://d.hatena.ne.jp/willnet\">http://d.hatena.ne.jp/willnet</a></p>\n"

strikethrough

PHP-Markdownスタイル。'~~'で囲んだ箇所をdelタグで囲む。

Redcarpet::Markdown.new(Redcarpet::Render::HTML).render('this is ~~good~~ bad')
# => "<p>this is ~~good~~ bad</p>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :strikethrough => true).render('this is ~~good~~ bad')
# => "<p>this is <del>good</del> bad</p>\n"

lax_html_blocks

Markdown標準のように、HTMLブロックが空行で囲まれる必要がなくなる。

例とするコードをどのように書いたらいいかよくわからないので省略。

space_after_headers

ヘッダのハッシュの後にスペースを必須にする

Redcarpet::Markdown.new(Redcarpet::Render::HTML).render("#hoge")
# => "<h1>hoge</h1>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :space_after_headers => true).render("#hoge")
# => "<p>#hoge</p>\n"

superscript

'^'の後のsuperscriptsをパースする。ネストすることが出来る。()で囲んで指定することも出来る

Redcarpet::Markdown.new(Redcarpet::Render::HTML, :superscript => true).render("hoge fuga")
# => "<p>hoge fuga</p>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :superscript => true).render("2^(nd)")
# => "<p>2<sup>nd</sup></p>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :superscript => true).render("hoge ^fuga")
# => "<p>hoge <sup>fuga</sup></p>\n"
Redcarpet::Markdown.new(Redcarpet::Render::HTML, :superscript => true).render("hoge ^fu^ga")
# => "<p>hoge <sup>fu<sup>ga</sup></sup></p>\n"

renderer

ビルトインのrendererは二つ。

  • Redcarpet::Render::HTML
  • Redcarpet::Render::XHTML

それぞれHTMLとXHTMLを出力する。これらのrendererはcで実装されていて、他のRubyで実装されたMarkdown系のライブラリよりもパフォーマンスが高い。

HTMLの出力関連で、前のバージョンで適用されてきたフラグはRedcarpet::HTMLに移動した。rendererをインスタンス化する時に使える。

Render::HTML.new(render_options={})

rendererを初期化する。

rndr = Redcarpet::Render::HTML.new(:no_links => true, :hard_wrap => true)

HTMLのrendererには代替版があって、Redcarpet::Render::HTML_TOCを使うと目次も一緒に出力してくれる。

render_optionには下記のフラグが使える。

filter_html
ユーザが入力したHTMLを出力しないようにする
no_images
imgタグを出力しないようにする
no_links
aタグを出力しないようにする
no_styles
styleタグを出力しないようにする
safe_links_only
安全と思われるプロトコルのリンクだけ出力する(httpsだけってことかな?)
with_toc_data
出力したh1とかのタグにアンカを付ける
hard_wrap
パラグラフ内に改行があればbrタグを出力する(デフォルトでは出力しない)
xhtml
xhtmlのタグを出力する。Render::XHTMLでは常に有効。

独自のパーサを作る

既にあるrendererを継承することで、独自のrendererを作ることが出来る。ビルトインのrendererであるHTMLとXHTMLは下記のようにして拡張する。

# コードのハイライトをする独自のrendererを作る
class HTMLwithAlbino < Redcarpet::Render::HTML
  def block_code(code, language)
    Albino.safe_colorize(code, language)
  end
end

markdown = Redcarpet::Markdown.new(HTMLwithAlbino, :fenced_code_blocks => true)

スクラッチで新しいrendererを作ることが出来る。lib/redcarpet/render_man.rbが実装の参考になる。

class ManPage < Redcarpet::Render::Base
    # you get the drill -- keep going from here
end

rendererに実装できるメソッド

省略。詳しくは原文みてください。

SmartyPants

Redcarpet2ではSmartyPants(`とか…を文字参照に変換するライブラリ)の実装が同梱されている。これはもともとの実装と互換性があるけど、格段にこっちの方が早い。

SamrtyPantsパーサはRedcarpet::Render::SmartyPantsでモジュールとして定義されていて、単体で使うことも出来るしmixinして使うことも出来る。

# Mixin
class HTMLWithPants < Redcarpet::Render::HTML
  include Redcarpet::Render::SmartyPants
end

# Standalone
Redcarpet::Render::SmartyPants.render("<p>Oh SmartyPants, you're so crazy...</p>")

Renderクラスにmixinした場合、描画が終わった後に実行されるpostprocesメソッドをオーバライドする。

SmartyPantsは既に描画されたHTMLに作用して、HTMLタグの中身やcodeやpreタグの中身は無視する。