Skip to content

Commit bcab3f2

Browse files
author
Paul Grayson
committed
In tag helper, honor html_safe on array parameters; also make safe_join more similar to Array.join by first calling flatten.
1 parent 80b4fe2 commit bcab3f2

File tree

4 files changed

+51
-8
lines changed

4 files changed

+51
-8
lines changed

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: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,21 @@ 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
178-
%(#{key}="#{value}")
176+
escaped_value = case value
177+
when Array
178+
if escape
179+
safe_join(value, " ")
180+
else
181+
value.join(" ")
182+
end
183+
else
184+
if escape
185+
ERB::Util.unwrapped_html_escape(value)
186+
else
187+
value
188+
end
189+
end
190+
%(#{key}="#{escaped_value}")
179191
end
180192
end
181193
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)