概要
先日、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^)/