はじめに
当ポートフォリオサイトの記事投稿画面では、長らくRails6から導入されたAction Textを使っていました(Action Textについては下記の記事をご覧ください)。
導入当初は便利な機能だと思って使っていたのですが、使い続けているうちにいくつか不満点が出てきました。最大の不満点は、コードのシンタックスハイライトができないことです。シンタックスハイライトとは、コード内のキーワードに基づいて色付けを行うことです。色付けを行うことにより、コードの可読性が格段に高まります。
今までの記事ではこんな感じで表示していました。
def sending
@contact = Contact.new(contact_params)
if @contact.valid?
ContactMailer.send_mail(@contact).deliver_now
redirect_to contact_done_path
else
render 'statics/index'
end
end
これにシンタックスハイライトを適用させるとこんな感じになります。
def sending
@contact = Contact.new(contact_params)
if @contact.valid?
ContactMailer.send_mail(@contact).deliver_now
redirect_to contact_done_path
else
render 'statics/index'
end
end
いかがしょうか? 明らかにシンタックスハイライトありのほうが読みやすいですね。
シンタックスハイライトを適用させるには、Markdownという決め事に則って文章を書く必要があります。今回はMarkdownで書いた文章をHTMLに変換してくれる「Redcarpet」と、コードのシンタックスハイライトを行ってくれる「Rouge」という2つのGemの導入・使用方法を解説します。
RedcarpetとRougeの導入
Gemfile
に以下を追記してbundle install
を行います。
Gemfile
gem 'redcarpet'
gem 'rouge'
Redcarpetの設定
まず、app/helpers/
配下にmarkdown_helper.rb
を作成し、以下のように記述します。
app/helpers/markdown_helper.rb
require 'rouge/plugins/redcarpet'
class CustomRenderHTML < Redcarpet::Render::HTML
include Rouge::Plugins::Redcarpet
end
module MarkdownHelper
def markdown(text)
options = {
no_styles: true,
with_toc_data: true,
hard_wrap: true,
}
extensions = {
no_intra_emphasis: true,
tables: true,
fenced_code_blocks: true,
autolink: true,
lax_spacing: true,
space_after_headers: true,
}
renderer = CustomRenderHTML.new(options)
markdown = Redcarpet::Markdown.new(renderer, extensions)
markdown.render(text).html_safe
end
def toc(text)
renderer = Redcarpet::Render::HTML_TOC.new(nesting_level: 3)
markdown = Redcarpet::Markdown.new(renderer)
markdown.render(text).html_safe
end
end
markdownメソッド
options
のパラメーターとその意味は以下の通り。
パラメーター | 意味 |
---|---|
no_images | <img> タグを生成しない |
no_styles | <style> タグを生成しない |
with_toc_data | 見出しにアンカーを付ける |
hard_wrap | 改行を<br> タグに変換 |
extensions
のパラメーターとその意味は以下の通り。
パラメーター | 意味 |
---|---|
no_intra_emphasis | 単語内の強調を解析しない |
tables | テーブルを有効化 |
fenced_code_blocks | 複数行のコードを有効化 |
autolink | http https ftp で始まる文字列を自動リンク |
lax_spacing | 複数行のコードの前後に空行が不要 |
space_after_headers | 見出しは#の後にスペースを空ける |
Rougeによるシンタックスハイライトを有効にするため、Rougeのプラグインをincludeしたカスタムクラスのインスタンスとしてレンダラーを作成します。
tocメソッド
TOCとはTable Of Contentsのことで、目次を意味します。markdown
メソッド内でwith_toc_data
を有効にしている必要があります。
toc_option
のパラメーターとその意味は以下の通り。
パラメーター | 意味 |
---|---|
nesting_level | 見出しのネストレベル(整数) |
Markdownドキュメントの表示
Markdownを表示したいビューで以下のようにヘルパーを呼び出せば、Markdownドキュメントが表示されます。
<%= toc(@article.content) %>
<%= markdown(@article.content) %>
Markdownからプレーンテキストに変換
Markdownで書いた文章を、ある場所ではプレーンテキスト(Markdownキーワードを含まない)で表示したい場合があります。当ブログの場合、記事一覧ページの各記事の本文がそれにあたります。Redcarpetには、Markdownで書いた文章をプレーンテキストに変換するRedcarpet::Render::StripDown
というAPIが用意されています。
Markdownをプレーンテキストに変換するヘルパーメソッドを作成します。
app/helpers/markdown_helper.rb
require 'redcarpet'
require 'redcarpet/render_strip'
module MarkdownHelper
def plaintext(text)
markdown = Redcarpet::Markdown.new(Redcarpet::Render::StripDown)
markdown.render(text)
end
end
あとはプレーンテキストを表示させたい場所でplaintext
メソッドを呼び出すだけです。
<%= plaintext(@article.content) %>
Rougeの設定
app/assets/stylesheets/
配下に_rouge.scss.erb
を作り、rougeのカラーテーマを読み込みます。
app/assets/stylesheets/_rouge.scss.erb
<%= Rouge::Themes::Base16.render(:scope => '.highlight') %>
最後に、assets/stylesheetsapplication.scss
に以下を追記してrougeをインポートします。
assets/stylesheetsapplication.scss
@import 'rouge';
以上でMarkdownを表示する準備ができました。
カラーテーマの変更
Rougeにはシンタックスハイライトのカラーテーマがいくつか用意されています。使用できるカラーテーマの一覧と使用方法について詳しくは以下の記事を参照してください。
まとめ
Markdownで記事を書くには、まずMarkdown記法というものを覚えなければなりません。
しかし、MarkdownはGitHubやStack Overflowなどでも標準的に使われている記法です。エンジニアの方なら一度はこれらのサイトを利用したことがあるはずです。
Markdownを知らなかったという人はこの機会にMarkdownを覚え、Railsアプリにも導入してはいかがでしょうか。