Webサービスに絵文字を導入する際、候補としてEmojiOneNoto Emojiなど、いろんな絵文字セットがあります。 SomemojiはRuby製のライブラリで、これら絵文字セットをラップして汎用的に使うことができるようになります。

今回は、SomemojiでRuby on Railsアプリケーション内のMarkdown表示部分に絵文字を表示してみたいと思います。

要件

今回は、元々Redcarpetを利用していたというケースを想定し、RedcarpetでMarkdownを表示していた部分に対し、カスタムレンダラを適用することで絵文字を表示します。

Markdownのレンダラをカスタマイズする代表的な方法としては、HTML::Pipelineがあります。 この場合の対応方法はREADMEに例がありますので、そちらをご確認ください。

また、codepreといったタグ内の絵文字コードは変換したくないので、これらをスキップさせる処理も追加します。

動作環境

今回利用するライブラリの各バージョンは次のようになっています。

  • Somemoji v0.6.1
  • Redcarpet v3.3.4

1. 絵文字変換モジュールを実装する

RedcarpetのカスタムレンダラでHTML内の絵文字コードを絵文字に変換しますが、まずその変換部分をモジュールとして実装します。

Somemojiはいろいろなプロバイダに対応しており、「ユーザの設定に応じて絵文字セットを切り替える」などの柔軟な対応も可能です。 ここではとりあえず表示を確認したいので、CDNからの配信に対応しているEmojiOneで表示してみています。

module EmojiRenderer
  IGNORED_PARENT_NAMES = %w(code pre)

  def emojify(document)
    doc = Nokogiri::HTML::DocumentFragment.parse(document)
    doc.search('.//text()').each do |node|
      if node.parent.name.in?(IGNORED_PARENT_NAMES)
        next
      end
      node.replace(node_with_emoji(node.content))
    end
    doc.to_html
  end

  private

  def node_with_emoji(content)
    Somemoji.emoji_one_emoji_collection.replace_code(content) do |emoji|
      %(<img src="https://cdnjs.cloudflare.com/ajax/libs/emojione/2.2.6/assets/png/#{emoji.code_points.join('-')}.png">)
    end
  end
end

2. カスタムレンダラを定義する

Redcarpetに渡すカスタムレンダラを定義します。 Redcarpetは、最終的に#postprocessで返されるHTMLを出力するので、これを上記モジュールで絵文字化します。

class CustomRenderer < Redcarpet::Render::HTML
  include EmojiRenderer

  def postprocess(document)
    emojify(document)
  end
end

3. ヘルパーを実装する

あとはビューから参照できるヘルパーで、HTML化を行なうメソッドを定義します。

module ApplicationHelper
  def markdown(text)
    markdown = Redcarpet::Markdown.new(CustomRenderer, { autolink: true, ... })
    markdown.render(text).html_safe
  end
end

参考記事

おわりに

実際の運用では、自分のサーバからCDNをとおして配信したりすると思います。 Somemojiは画像を準備するためのコマンドラインツールもあるので、簡単に実現できます。

複数の絵文字セットを扱う機会がなくても、他のライブラリよりシンプルに使えて便利だと思うので、覚えておくといいかもしれません。