aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
authorRafael França <rafaelmfranca@gmail.com>2016-04-20 01:19:51 -0300
committerRafael França <rafaelmfranca@gmail.com>2016-04-20 01:19:51 -0300
commit2201eef7f6cd2a3430bce9d9b0b56cc14373f68c (patch)
treeb019b248cca5c02678decb2dd91761958a950421 /actionview
parent9918118a97c91742d94a0e677603f2e3301eebdc (diff)
parent9baedc8a963e5efc92911f32a84bc8b74a15a2e9 (diff)
downloadrails-2201eef7f6cd2a3430bce9d9b0b56cc14373f68c.tar.gz
rails-2201eef7f6cd2a3430bce9d9b0b56cc14373f68c.tar.bz2
rails-2201eef7f6cd2a3430bce9d9b0b56cc14373f68c.zip
Merge pull request #23869 from oreoshake/to-sentence-html-safety
Add html_safe support to ActionView Array#OutputSafetyHelper
Diffstat (limited to 'actionview')
-rw-r--r--actionview/lib/action_view/helpers/output_safety_helper.rb30
-rw-r--r--actionview/test/template/output_safety_helper_test.rb55
2 files changed, 85 insertions, 0 deletions
diff --git a/actionview/lib/action_view/helpers/output_safety_helper.rb b/actionview/lib/action_view/helpers/output_safety_helper.rb
index c0fc3b820f..d4b55423a8 100644
--- a/actionview/lib/action_view/helpers/output_safety_helper.rb
+++ b/actionview/lib/action_view/helpers/output_safety_helper.rb
@@ -33,6 +33,36 @@ module ActionView #:nodoc:
array.flatten.map! { |i| ERB::Util.unwrapped_html_escape(i) }.join(sep).html_safe
end
+
+ # Converts the array to a comma-separated sentence where the last element is
+ # joined by the connector word. This is the html_safe-aware version of
+ # ActiveSupport's {Array#to_sentence}[http://api.rubyonrails.org/classes/Array.html#method-i-to_sentence].
+ #
+ def to_sentence(array, options = {})
+ options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
+
+ default_connectors = {
+ :words_connector => ', ',
+ :two_words_connector => ' and ',
+ :last_word_connector => ', and '
+ }
+ if defined?(I18n)
+ i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
+ default_connectors.merge!(i18n_connectors)
+ end
+ options = default_connectors.merge!(options)
+
+ case array.length
+ when 0
+ ''.html_safe
+ when 1
+ ERB::Util.html_escape(array[0])
+ when 2
+ safe_join([array[0], array[1]], options[:two_words_connector])
+ else
+ safe_join([safe_join(array[0...-1], options[:words_connector]), options[:last_word_connector], array[-1]])
+ end
+ end
end
end
end
diff --git a/actionview/test/template/output_safety_helper_test.rb b/actionview/test/template/output_safety_helper_test.rb
index 8de0ae2f6f..b940c9dd36 100644
--- a/actionview/test/template/output_safety_helper_test.rb
+++ b/actionview/test/template/output_safety_helper_test.rb
@@ -32,4 +32,59 @@ class OutputSafetyHelperTest < ActionView::TestCase
joined = safe_join(['"a"',['<b>','<c>']], ' <br/> ')
assert_equal '&quot;a&quot; &lt;br/&gt; &lt;b&gt; &lt;br/&gt; &lt;c&gt;', joined
end
+
+ test "to_sentence should escape non-html_safe values" do
+ actual = to_sentence(%w(< > & ' "))
+ assert actual.html_safe?
+ assert_equal("&lt;, &gt;, &amp;, &#39;, and &quot;", actual)
+
+ actual = to_sentence(%w(<script>))
+ assert actual.html_safe?
+ assert_equal("&lt;script&gt;", actual)
+ end
+
+ test "to_sentence does not double escape if single value is html_safe" do
+ assert_equal("&lt;script&gt;", to_sentence([ERB::Util.html_escape("<script>")]))
+ assert_equal("&lt;script&gt;", to_sentence(["&lt;script&gt;".html_safe]))
+ assert_equal("&amp;lt;script&amp;gt;", to_sentence(["&lt;script&gt;"]))
+ end
+
+ test "to_sentence connector words are checked for html safety" do
+ assert_equal "one & two, and three", to_sentence(['one', 'two', 'three'], words_connector: ' & '.html_safe)
+ assert_equal "one & two", to_sentence(['one', 'two'], two_words_connector: ' & '.html_safe)
+ assert_equal "one, two &lt;script&gt;alert(1)&lt;/script&gt; three", to_sentence(['one', 'two', 'three'], last_word_connector: ' <script>alert(1)</script> ')
+ end
+
+ test "to_sentence should not escape html_safe values" do
+ ptag = content_tag("p") do
+ safe_join(["<marquee>shady stuff</marquee>", tag("br")])
+ end
+ url = "https://example.com"
+ expected = %(<a href="#{url}">#{url}</a> and <p>&lt;marquee&gt;shady stuff&lt;/marquee&gt;<br /></p>)
+ actual = to_sentence([link_to(url, url), ptag])
+ assert actual.html_safe?
+ assert_equal(expected, actual)
+ end
+
+ test "to_sentence handles blank strings" do
+ actual = to_sentence(['', 'two', 'three'])
+ assert actual.html_safe?
+ assert_equal ", two, and three", actual
+ end
+
+ test "to_sentence handles nil values" do
+ actual = to_sentence([nil, 'two', 'three'])
+ assert actual.html_safe?
+ assert_equal ", two, and three", actual
+ end
+
+ test "to_sentence still supports ActiveSupports Array#to_sentence arguments" do
+ assert_equal "one two, and three", to_sentence(['one', 'two', 'three'], words_connector: ' ')
+ assert_equal "one & two, and three", to_sentence(['one', 'two', 'three'], words_connector: ' & '.html_safe)
+ assert_equal "onetwo, and three", to_sentence(['one', 'two', 'three'], words_connector: nil)
+ assert_equal "one, two, and also three", to_sentence(['one', 'two', 'three'], last_word_connector: ', and also ')
+ assert_equal "one, twothree", to_sentence(['one', 'two', 'three'], last_word_connector: nil)
+ assert_equal "one, two three", to_sentence(['one', 'two', 'three'], last_word_connector: ' ')
+ assert_equal "one, two and three", to_sentence(['one', 'two', 'three'], last_word_connector: ' and ')
+ end
end