Skip to content

Commit 6857415

Browse files
committed
Merge pull request rails#15654 from pdg137/master
In tag helper, honor html_safe on arrays; also make safe_join more similar to Array.join
2 parents 4e009ee + bcab3f2 commit 6857415

File tree

5 files changed

+51
-7
lines changed

5 files changed

+51
-7
lines changed

actionview/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
* Flatten the array parameter in `safe_join`, so it behaves consistently with
2+
`Array#join`.
3+
4+
*Paul Grayson*
5+
6+
* Honor `html_safe` on array elements in tag values, as we do for plain string
7+
values.
8+
9+
*Paul Grayson*
10+
111
* Add `ActionView::Template::Handler.unregister_template_handler`.
212

313
It performs the opposite of `ActionView::Template::Handler.register_template_handler`.

actionview/lib/action_view/helpers/output_safety_helper.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ def raw(stringish)
1818
end
1919

2020
# This method returns a html safe string similar to what <tt>Array#join</tt>
21-
# would return. All items in the array, including the supplied separator, are
22-
# html escaped unless they are html safe, and the returned string is marked
23-
# as html safe.
21+
# would return. The array is flattened, and all items, including
22+
# the supplied separator, are html escaped unless they are html
23+
# safe, and the returned string is marked as html safe.
2424
#
2525
# safe_join(["<p>foo</p>".html_safe, "<p>bar</p>"], "<br />")
2626
# # => "<p>foo</p>&lt;br /&gt;&lt;p&gt;bar&lt;/p&gt;"
@@ -31,7 +31,7 @@ def raw(stringish)
3131
def safe_join(array, sep=$,)
3232
sep = ERB::Util.unwrapped_html_escape(sep)
3333

34-
array.map { |i| ERB::Util.unwrapped_html_escape(i) }.join(sep).html_safe
34+
array.flatten.map! { |i| ERB::Util.unwrapped_html_escape(i) }.join(sep).html_safe
3535
end
3636
end
3737
end

actionview/lib/action_view/helpers/tag_helper.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,11 @@ def boolean_tag_option(key)
173173
end
174174

175175
def tag_option(key, value, escape)
176-
value = value.join(" ") if value.is_a?(Array)
177-
value = ERB::Util.unwrapped_html_escape(value) if escape
176+
if value.is_a?(Array)
177+
value = escape ? safe_join(value, " ") : value.join(" ")
178+
else
179+
value = escape ? ERB::Util.unwrapped_html_escape(value) : value
180+
end
178181
%(#{key}="#{value}")
179182
end
180183
end

actionview/test/template/output_safety_helper_test.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,11 @@ def setup
2525
assert_equal "<p>foo</p><br /><p>bar</p>", joined
2626
end
2727

28-
end
28+
test "safe_join should work recursively similarly to Array.join" do
29+
joined = safe_join(['a',['b','c']], ':')
30+
assert_equal 'a:b:c', joined
31+
32+
joined = safe_join(['"a"',['<b>','<c>']], ' <br/> ')
33+
assert_equal '&quot;a&quot; &lt;br/&gt; &lt;b&gt; &lt;br/&gt; &lt;c&gt;', joined
34+
end
35+
end

actionview/test/template/tag_helper_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,27 @@ def test_content_tag_with_escaped_array_class
8080

8181
str = content_tag('p', "limelight", :class => ["song", "play"])
8282
assert_equal "<p class=\"song play\">limelight</p>", str
83+
84+
str = content_tag('p', "limelight", :class => ["song", ["play"]])
85+
assert_equal "<p class=\"song play\">limelight</p>", str
8386
end
8487

8588
def test_content_tag_with_unescaped_array_class
8689
str = content_tag('p', "limelight", {:class => ["song", "play>"]}, false)
8790
assert_equal "<p class=\"song play>\">limelight</p>", str
91+
92+
str = content_tag('p', "limelight", {:class => ["song", ["play>"]]}, false)
93+
assert_equal "<p class=\"song play>\">limelight</p>", str
94+
end
95+
96+
def test_content_tag_with_empty_array_class
97+
str = content_tag('p', 'limelight', {:class => []})
98+
assert_equal '<p class="">limelight</p>', str
99+
end
100+
101+
def test_content_tag_with_unescaped_empty_array_class
102+
str = content_tag('p', 'limelight', {:class => []}, false)
103+
assert_equal '<p class="">limelight</p>', str
88104
end
89105

90106
def test_content_tag_with_data_attributes
@@ -115,6 +131,14 @@ def test_tag_honors_html_safe_for_param_values
115131
end
116132
end
117133

134+
def test_tag_honors_html_safe_with_escaped_array_class
135+
str = tag('p', :class => ['song>', 'play>'.html_safe])
136+
assert_equal '<p class="song&gt; play>" />', str
137+
138+
str = tag('p', :class => ['song>'.html_safe, 'play>'])
139+
assert_equal '<p class="song> play&gt;" />', str
140+
end
141+
118142
def test_skip_invalid_escaped_attributes
119143
['&1;', '&#1dfa3;', '& #123;'].each do |escaped|
120144
assert_equal %(<a href="#{escaped.gsub(/&/, '&amp;')}" />), tag('a', :href => escaped)

0 commit comments

Comments
 (0)