概要
RailsでMakdown形式の文章を保存して、それを元にHTMLを生成したいということがありました。
そこで、私はredcarpetというGemを使ってMarkdownの読み書きを実現したので、どのようにしてMarkdownを読み書きできるようにしたのかをここに書いておきます。
さらに今回、コードの記述などに色を付けるシンタックスハイライトについても設定をしたので、その設定も含めてここに書きます。
Gemのインストール
Markdownの読み書きには、redcarpetというGemを使います。
シンタックスハイライトには、rougeというGemを使います。
Gemfileに次の2行を追記します。
gem 'redcarpet'
gem 'rouge'
追記したら、bundle installでGemのインストールをします。
使い方
redcarpetの使い方として、Markdownの文章をredcarpetのインスタンスに流し込むとHTMLが生成されます。
そして、Markdownと言っても、記述の仕方などオプションがあるため、インスタンスの作成の際には、そのオプションについても設定する必要があります。
実際に使う場合、インスタンスの生成はhelper内にメソッドで記述します。私の場合、app/helper/application_helper.rb内に記述しました。
module ApplicationHelper
def markdown(text)
render_options = {
filter_html: true,
hard_wrap: true
}
extensions = {
autolink: true,
fenced_code_blocks: true,
lax_spacing: true,
no_intra_emphasis: true,
strikethrough: true,
superscript: true,
tables: true
}
renderer = RougeConfig::RougeRender.new(render_options)
Redcarpet::Markdown.new(renderer, extensions).render(text)
end
end
render_optionsとextensionsは、redcarpetで生成するHTMLの設定の記述です。
それらの設定を元に、Redcarpet::Markdown.new(renderer, extensions).render(text)のようにして、HTMLを生成します。
生成の前に、RougeRenderというクラスのインスタンスを作成していますが、これはシンタックスハイライトのための設定で、あとで詳しく説明します。
設定
render_optionsで設定している内容は次のものです。
| 設定名 | 意味 |
|---|---|
| filter_html | 入力されたHTMLをエスケープする |
| hard_wrap | Markdown内の改行をHTMLの改行にする |
extensionsで設定している内容は次のものです。
| 設定名 | 意味 |
|---|---|
| autolink | URLの記述をリンクとして表示する |
| fenced_code_blocks | フェンス・コードブロックの記述を可能にする |
| lax_spacing | HTMLブロックはMarkdown標準のように空行で囲む必要はない |
| no_intra_emphasis | foo_bar_bazのような文字列の時に強調しない |
| strikethrough | 2つの~で囲まれたものを取り消し線とする |
| superscript | 文字列の後に^を使って上付き文字を記述できるようにする |
| tables | テーブルを記述できるようにする |
ここで紹介しているもの以外にも設定はあり、それらはGitHubのredcarpetのリポジトリのREADME.mdで説明されているので、そちらを見てください。
シンタックスハイライト
シンタックスハイライトのために、rougeというGemを使っています。
rougeは、redcarpetのインスタンスの作成の際にレンダラーとして組み込む必要があり、それはrenderer = RougeConfig::RougeRender.new(render_options)という部分でレンダラーを作成しています。
このランダラーのためのクラスは、Redcarpet::Render::HTMLを継承した自作のクラスで、継承したクラス内でRouge::Plugins::Redcarpetをインクルードする必要があります。
このクラスの記述は、libディレクトリ内に作成してそこから読み込みます。
なので、lib/rouge_configという場所にrouge_render.rbという名前でクラスを記述します。
require 'redcarpet'
require 'rouge'
require 'rouge/plugins/redcarpet'
module RougeConfig
class RougeRender < Redcarpet::Render::HTML
include Rouge::Plugins::Redcarpet
end
end
そして、このファイルを読み込むようにconfig/application.rbのApplicationクラス内に次の1行を追記します。
config.autoload_paths += %W(#{config.root}/lib/)
Railsの設定を変更したので、サーバを立ち上げている場合は、再起動する必要があります。
rougeでシンタックスハイライトができる言語は、次のサイトから確認できます。
スタイル
シンタックスハイライトのためには、対応するテーマを追加する必要があります。
テーマはapp/assets/stylesheets内にrouge.css.erbのような名前でファイルを作成し、そのファイル内で次のように記述します。
<%= Rouge::Themes::Monokai.render(:scope => '.highlight') %>
ここでは、Monokaiというテーマで色を付けています。
rougeには、あらかじめいくつかのテーマが用意されており、そのテーマは次で確認できます。
HTMLに変換
実際に、Markdwonの文章をHTMLに変換するには、Viewファイルなどで、次のようにhelper内のメソッドを呼び出します。
<%= sanitize markdown(text) %>
textには、Markdown形式で書かれた文章が代入されているとします。
このように、helper内のメソッドを呼び出すとHTMLが戻り値となるので、それをsanitizeメソッドでHTMLがエスケープされないようにします。
もしsanitizeメソッドを使わないと、せっかくredcarpetでHTMLが生成されたのに、それが全てエスケープされてしまい正しく表示されなくなります。
まとめ
やってみるとかなり簡単にできると思います。
redcarpetには設定できる項目がたくさんあるので、状況に応じて使い分けましょう。