LoginSignup
0
1

More than 5 years have passed since last update.

[html-pipeline]テキストデータを加工して、HTMLで安全に出力する方法

Last updated at Posted at 2017-01-29

概要

先日、html-pipelineのgemを使う機会があったので、備忘録も兼ねて、
本gemの使い方について、書いていきたいと思います。(´ε`)
使い方は簡単なんですが、日本語の解説ページがあんまり無かったので、掲載(^o^)/

Webフォーム等から入力されたテキストデータをサニタイズ(タグのエスケープや削除とか)し、
ちょっと加工して、HTMLとして表示させたい場合があると思います。
- CMS的なサイトでフォームでコンテンツを入力させて、Webページとして表示させたい
- http://〜〜のリンクがあったらハイパーリンクで表示したい
- タグ等は文字として表示させたい
- Youtubeとかのリンクがあったら、埋め込みのような形で表示したい

こんなことをやってくれるのがgem html-pipeline です。
https://github.com/jch/html-pipeline

環境

Rails 5.0.1
Ruby 2.3.1

html-pipelineで何ができるのさ?

冒頭にも書きましたが、html-pipelineを使うことで、
テキストデータを加工して、html出力することができます。

html-pipelineには「フィルター」という概念があり、例えば、
「http://〜をリンクとして表示したいな」と思ったら、そのフィルターを設定することで、
テキストデータの中から文字列を見つけて、aタグで囲んでくれたりします。

フィルターの種類はgithubのページに記載されていますが、例として以下のようなフィルターがあります。
リンク作ったり、マークダウンをhtmlにしたり、youtubeの埋め込みタグ作ったりです。
例えば、httpはリンクにして、youtubeへのリンクは埋め込んで表示させたいなら、フィルターを2つを指定します。

(gitbubのページから一部抜粋) 
MentionFilter - replace @user mentions with links
AutolinkFilter - auto_linking urls in HTML
EmojiFilter - everyone loves emoji!
MarkdownFilter - convert markdown to html
PlainTextInputFilter - html escape text and wrap the result in a div
html-pipeline-nico_link - An HTML::Pipeline filter for niconico description links
html-pipeline-youtube - An HTML::Pipeline filter for YouTube links

使い方

1.ベースとなるhtml-pipelineのインストール
githubのinstallationに書いてあります。
Genfileに
gem 'html-pipeline'
を入れて、
$ bundle install

2.フィルターの選定
どのフィルターを使うか選びましょう。
Githubの「Filters」または「3rd Party Extensions」からチョイスします。

3.依存関係のあるgemのインストール
まず、Filtersの中からフィルターを選択したあなた!
あなたが選択したフィルターを動作させるためには別途gemが必要かもしれません。

依存関係のあるgemは、「Dependencies」の章に書いてあります。
例えば、httpをリンクして表示したいなら、「AutolinkFilter」が必要で、
これを動作させるためには「rinku」というgemが別途必要です。
こんな感じで書いてありますね。
AutolinkFilter - rinku

また、依存関係のgemにはバージョンが指定されているものがあります!
以下のリンク先をチェックして、gemをインストールしましょう。
Note: See Gemfile :test block for version requirements.

そして、3rd Party Extensionsからフィルターを選択したあなた!
別途gemを入れる必要があります。リンク先に飛んでgemを入れましょう!
例えば、「html-pipeline-youtube」を選択した場合、
html-pipeline-youtube
というgemをインストールします。

4.では使いましょう
使い方は簡単です。
1)html-pipelineのインスタンス生成
2)生成したインスタンスの引数にテキストを与える
  3)テキストが出力されるのでhtml_safeとかしてviewで表示
以上!w

少し詳しく書いていきます。
1.html-pipelineのインスタンス生成
HTML:Pipeline.newでインスタンスを生成しますが、その際に引数を2つ(a,b)与えます。
  a:配列で適用するフィルターを記載
  b:フィルターが必要なオプションをハッシュで指定

実際のコードはこんな感じ↓です。以下の例では2つのフィルターを定義しています。
bの引数は、AutolinkFilterのオプションです。
必要/設定可能なオプションは、「/lib/html/pipeline/」以下の[フィルター名.rb]に書かれています。

HtmlSanitizationPipeline = 
  HTML::Pipeline.new [
    HTML::Pipeline::YoutubeFilter,  # aの適用フィルター
    HTML::Pipeline::AutolinkFilter
  ], {autolink: true, link_attr: 'target="_blank"'} # bのフィルターオプション

2.生成したインスタンスの引数にテキストを与える
以下のような感じでcallメソッドの引数としてテキストデータを与えます。
返り値のハッシュのoutputに結果が入りますので、それを出力すればOKです。
これらをヘルパーメソッドにして、viewから呼んであげれば色々使いまわせます。

result = HtmlSanitizationPipeline.call(テキストデータ)
result[:output].html_safe

html-pipeline + 別メソッドで要件にあったものを

基本的な使い方は以上ですが、上記の例ではタグなどに囲まれた文字は、
文字として出力されず削除されてしまうと思います。
文字として出力するための(文字エスケープ)フィルターとしてhtml-pipelineには、
PlainTextInputFilter - html escape text and wrap the result in a div
が用意されていますが、今回これは使いませんでした。(微妙に出力結果が要件に合わず)

先日html-pipelineを使った際には、pipelineに渡す前にrailsのhtml_escapeメソッドで
タグ等をエスケープ処理した上で、pipelineにデータを渡す方法を選択しました。

result = HtmlSanitizationPipeline.call(html_escape(テキストデータ))
result[:output].html_safe

要件によってはresultに対してさらに加工が必要なこともありますが、その場合は、
split_paragraphsで行単位で処理するとか、railsのメソッドと組合せるとお手軽にできるかもです。

ではでは〜〜\(^o^)/

0
1
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
0
1