diff --git a/actionview/test/template/erb_util_test.rb b/actionview/test/template/erb_util_test.rb index c6983000a0..4d85539720 100644 --- a/actionview/test/template/erb_util_test.rb +++ b/actionview/test/template/erb_util_test.rb @@ -103,9 +103,9 @@ def test_html_escape_once assert_equal " ' ' λ λ " ' < > ", html_escape_once(" ' ' λ λ \" ' < > ") end - def test_html_escape_once_returns_unsafe_strings_when_passed_unsafe_strings + def test_html_escape_once_returns_safe_strings_when_passed_unsafe_strings value = html_escape_once("1 < 2 & 3") - assert_not_predicate value, :html_safe? + assert_predicate value, :html_safe? end def test_html_escape_once_returns_safe_strings_when_passed_safe_strings diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 8191570a96..1f38a08a80 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,31 @@ +* `ERB::Util.html_escape_once` always returns an `html_safe` string. + + This method previously maintained the `html_safe?` property of a string on the return + value. Because this string has been escaped, however, not marking it as `html_safe` causes + entities to be double-escaped. + + As an example, take this view snippet: + + ```html +

<%= html_escape_once("this & that & the other") %>

+ ``` + + Before this change, that would be double-escaped and render as: + + ```html +

this &amp; that &amp; the other

+ ``` + + After this change, it renders correctly as: + + ```html +

this & that & the other

+ ``` + + Fixes #48256 + + *Mike Dalessio* + * Deprecate `SafeBuffer#clone_empty`. This method has not been used internally since Rails 4.2.0. diff --git a/activesupport/lib/active_support/core_ext/erb/util.rb b/activesupport/lib/active_support/core_ext/erb/util.rb index e4857619e5..3ce848374c 100644 --- a/activesupport/lib/active_support/core_ext/erb/util.rb +++ b/activesupport/lib/active_support/core_ext/erb/util.rb @@ -63,8 +63,7 @@ module Util # html_escape_once('<< Accept & Checkout') # # => "<< Accept & Checkout" def html_escape_once(s) - result = ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE) - s.html_safe? ? result.html_safe : result + ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE).html_safe end module_function :html_escape_once