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"><script type="text/javascript">alert("バカ")</script></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"><script type="text/javascript">alert("バカ")</script></div>
パターン4 修正
の事例は、HTMLの表示が1行なのでネストしてわざわざhtml_escape
を行う
メリットを感じないが、表示内容に改行が含まれる場合に改行を<br/>
タグに変換して表示したい
場合などに重宝する。
パターン5
文字列中の改行コード\n
を<br />
タグに変換しようとしているが、HTMLエスケープしたくない
<br />
が<br />
にエスケープされてしまっている。
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のコード事例<br /><script type='text/javascript'><br /> alert('アラート表示')<br /></script></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><script type='text/javascript'><br> alert('アラート表示')<br></script></div>