railsにmarkdownを実装したよ

markdown 機能実装

記事を書くのにいちいちHTMLで書くのは面倒。

だから使い慣れているmarkdownを導入することにした。

今回欲しかった機能は以下の通り

  • markdown
  • リアルタイムプレビュー
  • toc(目次)機能

順番に説明していく。

実装工程

markdown

今回使うgemはこれ

gem 'redcarpet'
gem 'rouge'

そしておなじみのやつを打ち込んで

sudo bundle install

以下のファイルを作ってコードをぶち込む

app/helper/markdown_helper.rb

module MarkdownHelper
  def markdown(text)
    options = {
      filter_html:     true,
      hard_wrap:       true,
      space_after_headers: true,
      with_toc_data: true
    }

    extensions = {
      autolink:           true,
      no_intra_emphasis:  true,
      fenced_code_blocks: true,
      tables:             true
    }

    renderer = Redcarpet::Render::HTML.new(options)
    markdown = Redcarpet::Markdown.new(renderer, extensions)
    markdown.render(text).html_safe
  end

end

optionsとextentionsの中身(filter_htmlとか)は参考サイトを参照してほしい。もっと丁寧に書いてあって参考になるはず。

これができたらあとは、適当なviewにこれをかく。()の中身は各自対応させる。

app/views/articles/show.html.slim

  = markdown(@article.content)

これだけで@article.contentがmarkdownで表示される。

すげええ。

参考

redcarpetでrailsにシンプルにMarkdownを適用する

Railsでカスタムmarkdownを実装する - k0kubun's blog

Ruby On Railsでredcarpetを利用し、シンタックスハイライトに対応したブログ機能を実装する - Ruby_on_Rails | ゼロイチ | 独学者・初心者向けプログラミング・SEO入門サイト

リアルタイムプレビュー

vue.jsとmarked.jsをheadに追加する

/app/views/layout/application.html.slim

doctype html
html
  head
    title
      | hoge
    link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
    script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"
    script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
    /! Realtime preview 始まり
    script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.10/vue.js"
    script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.js"
   /! Realtime preview 終わり

    = csrf_meta_tags
    = csp_meta_tag
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
  body
    /! 以下略

ほんで、フォームの部分に、投稿部分とプレビュー部分を並べる。

JSも書き忘れないように。

app/views/articles/_form.html.slim

= form_for @article do |f|
  /! 中略
  .field
    #editor
      textarea.form-control debounce="50" name="article[content]" rows="20" v-model="input"
      div v-html=("input | marked")
  .actions = f.submit "保存"

  javascript:
    window.onload = function() {
      new Vue({
        el: '#editor',
        data: {
          input: '#{j @article.content}',
        },
        filters: {
          marked: marked,
        },
      });
    };

f:id:kapiba-ra:20180609181025p:plain

参考

Railsにマークダウンのリアルタイムプレビューを実装する

html.erbファイルでjs直書きでその中にrubyのコードを埋め込んでいる状態のものをslimに置き換えるときの書き方

toc(目次)機能

先ほど作成したヘルパーに追記していく。

toc用のものを作成した。markdownを参考にしたら簡単にできた。

app/helper/markdown_helper.rb

module MarkdownHelper
  def markdown(text)
    options = {
      filter_html:     true,
      hard_wrap:       true,
      space_after_headers: true,
      with_toc_data: true
    }

    extensions = {
      autolink:           true,
      no_intra_emphasis:  true,
      fenced_code_blocks: true,
      tables:             true
    }

    renderer = Redcarpet::Render::HTML.new(options)
    markdown = Redcarpet::Markdown.new(renderer, extensions)
    markdown.render(text).html_safe
  end

  /!以下追加
  def toc(text)
    toc_option = {
      nesting_level: 2
    }

    toc_renderer = Redcarpet::Render::HTML_TOC.new
    toc = Redcarpet::Markdown.new(toc_renderer, toc_option)
    toc.render(text).html_safe
  end
  /! 以上追加

end

あとは、markdownを実装したとき同様こうやると完成。

app/views/articles/show.html.slim

  = markdown(@article.content)

f:id:kapiba-ra:20180609181044p:plain

参考

RedcarpetでTOC表示 | | Scimpr Blog