diff options
-rw-r--r-- | actionpack/lib/action_view/helpers/tag_helper.rb | 2 | ||||
-rw-r--r-- | actionpack/test/template/erb_util_test.rb | 14 | ||||
-rw-r--r-- | activesupport/CHANGELOG.md | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/string/output_safety.rb | 19 |
4 files changed, 35 insertions, 2 deletions
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index d7a2651bad..ecd26891d6 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -118,7 +118,7 @@ module ActionView # escape_once("<< Accept & Checkout") # # => "<< Accept & Checkout" def escape_once(html) - html.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] } + ERB::Util.html_escape_once(html) end private diff --git a/actionpack/test/template/erb_util_test.rb b/actionpack/test/template/erb_util_test.rb index eba2ef64e0..ca2710e9b3 100644 --- a/actionpack/test/template/erb_util_test.rb +++ b/actionpack/test/template/erb_util_test.rb @@ -44,4 +44,18 @@ class ErbUtilTest < ActiveSupport::TestCase assert_equal chr, html_escape(chr) end end + + def test_html_escape_once + assert_equal '1 < 2 & 3', html_escape_once('1 < 2 & 3') + end + + def test_html_escape_once_returns_unsafe_strings_when_passed_unsafe_strings + value = html_escape_once('1 < 2 & 3') + assert !value.html_safe? + end + + def test_html_escape_once_returns_safe_strings_when_passed_safe_strings + value = html_escape_once('1 < 2 & 3'.html_safe) + assert value.html_safe? + end end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 5df3ec406f..ad9a12fc9b 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* Add html_escape_once to ERB::Util, and delegate escape_once tag helper to it. *Carlos Antonio da Silva* + * Remove ActiveSupport::TestCase#pending method, use `skip` instead. *Carlos Antonio da Silva* * Deprecates the compatibility method Module#local_constant_names, diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 73aa7dd89a..104ee251de 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -5,6 +5,8 @@ class ERB module Util HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' } JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' } + HTML_ESCAPE_ONCE_REGEXP = /[\"><]|&(?!([a-zA-Z]+|(#\d+));)/ + JSON_ESCAPE_REGEXP = /[&"><]/ # A utility method for escaping HTML tag characters. # This method is also aliased as <tt>h</tt>. @@ -33,6 +35,21 @@ class ERB singleton_class.send(:remove_method, :html_escape) module_function :html_escape + # Returns an escaped version of +html+ without affecting existing escaped entities. + # + # ==== Examples + # html_escape_once("1 < 2 & 3") + # # => "1 < 2 & 3" + # + # html_escape_once("<< Accept & Checkout") + # # => "<< Accept & Checkout" + def html_escape_once(s) + result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP) { |special| HTML_ESCAPE[special] } + s.html_safe? ? result.html_safe : result + end + + module_function :html_escape_once + # A utility method for escaping HTML entities in JSON strings # using \uXXXX JavaScript escape sequences for string literals: # @@ -51,7 +68,7 @@ class ERB # <%=j @person.to_json %> # def json_escape(s) - result = s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] } + result = s.to_s.gsub(JSON_ESCAPE_REGEXP) { |special| JSON_ESCAPE[special] } s.html_safe? ? result.html_safe : result end |