LoginSignup
6
6

More than 5 years have passed since last update.

RailsでHTML-pipelineを使ったテキスト整形

Last updated at Posted at 2016-01-11

はじめに

Webアプリに限らず様々な場面で「HTMLタグを無毒化して、URLを<a>タグで囲んで...」という共通した処理をする必要があるかと思います。sanitizegsub でもいいですけど、emojiを使ったり@user#hashtagにもリンクを貼ったりすると、コードが煩雑化するのが目に見えています。

この問題を解決できるhtml-pipelineというGemがあります。html-pipelineはこれらのフィルタ処理をパイプラインで処理します。またデフォルトで多くのフィルタを使うことができ、独自のフィルタも定義できます。

この記事では、元のテキストを以下の手順でフィルタする方法を紹介します。

  1. &"<> を実体参照に置換
  2. URLを<a>タグのリンクで置換

インストール

Gemfileにhtml-pipelineを記述します。今回使うフィルタの依存gemもインストールします。

# Gemfile

gem 'html-pipeline'
gem 'rinku'
gem 'escape_utils'

Railsアプリに組み込む

Railsアプリでhtml-pipelineを使うときは、ヘルパーメソッドでラップするとviewからも呼び出せて便利です。ここでは ApplicationHelper にヘルパーメソッドを追加します。

# app/helpers/application_helper.rb

module ApplicationHelper
  def html_pipeline(source)
    pipeline = HTML::Pipeline.new [
      HTML::Pipeline::PlainTextInputFilter,
      HTML::Pipeline::AutolinkFilter
    ]
    pipeline.call(source)[:output]
  end
end

HTML::Pipelineのnewに、フィルタクラスをArrayで渡します。call を呼び出すと、戻り地のハッシュの :output に結果が格納されます。

また次のコードは、ヘルパメソッドのテストとなります。

# spec/helpers/application_helper_spec.rb

require 'rails_helper'

RSpec.describe ApplicationHelper, type: :helper do
  describe "#html_pipeline" do
    context "when the text contains HTML tags" do
      subject { html_pipeline("Hello <b>world</b>") }
      it { should match /&lt;b&gt;/ }
    end

    context "when the text contains urls" do
      subject { html_pipeline("Google on https://google.com/") }
      it { should match /href/ }
    end
  end
end

おわりに

ヘルパーメソッド呼び出し時に毎回インスタンスが作られてたくない人は、initializersでインスタンスを作れば良いと思います。またhtml-pipelineはRailsアプリに限らず、いろいろなアプリケーションに使えるので、Middlemanやjekyllでも使ってみたいですね。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6