Skip to content

Instantly share code, notes, and snippets.

@seak0503
Last active March 9, 2016 21:11
Show Gist options
  • Save seak0503/36eb74fe8cf32f3566af to your computer and use it in GitHub Desktop.
Save seak0503/36eb74fe8cf32f3566af to your computer and use it in GitHub Desktop.
NokogiriでHTMLを生成する時の注意ポイント

Nokogiriでは次の2パターンは同じ結果になるが、注意しなければいけない ポイントがある

パターン1 (ネストしないパターン)

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |doc|
  doc.div('これはテストです', class: 'notes')
end

puts root.to_html
<div class="notes">これはテストです</div>

パターン2 (ネストするパターン)

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |doc|
  doc.div(class: 'notes') do
    doc << 'これはテストです'
  end
end

puts root.to_html
<div class="notes">これはテストです</div>

上記の2パターンの場合は特に問題ないように見えるが、下記のように 本来はhtmlエスケープしなければならないケースの場合に違いが出てくる

パターン3 (ネストしないパターン)

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |doc|
  doc.div('<script type="text/javascript">alert("バカ")</script>', class: 'notes')
end

puts root.to_html
<div class="notes">&lt;script type="text/javascript"&gt;alert("バカ")&lt;/script&gt;</div>

パターン4 (ネストするパターン)

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |doc|
  doc.div(class: 'notes') do
    doc << '<script type="text/javascript">alert("バカ")</script>'
  end
end

puts root.to_html
<div class="notes"><script type="text/javascript">alert("バカ")</script></div>

パターン3はhtmlエスケープが行われるが、パターン4では行われていない。

パターン4のような場合にhtmlエスケープをするにはhtml_escapeを利用する必要がある。

パターン4 修正

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |doc|
  doc.div(class: 'notes') do
    doc << ERB::Util.html_escape('<script type="text/javascript">alert("バカ")</script>')
  end
end

puts root.to_html
<div class="notes">&lt;script type="text/javascript"&gt;alert("バカ")&lt;/script&gt;</div>

パターン4 修正の事例は、HTMLの表示が1行なのでネストしてわざわざhtml_escapeを行う メリットを感じないが、表示内容に改行が含まれる場合に改行を<br/>タグに変換して表示したい 場合などに重宝する。

パターン5

文字列中の改行コード\n<br />タグに変換しようとしているが、HTMLエスケープしたくない <br />&lt;br /&gt;にエスケープされてしまっている。

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |doc|
value = "javascriptのコード事例\n<script type='text/javascript'>\n  alert('アラート表示')\n</script>"
  doc.div(value.gsub(/\n/, '<br />'), class: 'notes')
end

puts root.to_html
<div class="notes">javascriptのコード事例&lt;br /&gt;&lt;script type='text/javascript'&gt;&lt;br /&gt;  alert('アラート表示')&lt;br /&gt;&lt;/script&gt;</div>

パターン6

自動的にhtmlエスケープされない仕様をうまく使い、エスケープすべきものとしないものを 表現している

root = Nokogiri::HTML::DocumentFragment.parse('')
Nokogiri::HTML::Builder.with(root) do |doc|
value = "javascriptのコード事例\n<script type='text/javascript'>\n  alert('アラート表示')\n</script>"
  doc.div(class: 'notes') do
    doc << ERB::Util.html_escape(value).gsub(/\n/, '<br />')
  end
end

puts root.to_html
<div class="notes">javascriptのコード事例<br>&lt;script type='text/javascript'&gt;<br>  alert('アラート表示')<br>&lt;/script&gt;</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment