diff options
-rw-r--r-- | actionpack/lib/action_view/helpers.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/capture_helper.rb | 14 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/deprecated_block_helpers.rb | 35 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/javascript_helper.rb | 8 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/tag_helper.rb | 26 | ||||
-rw-r--r-- | actionpack/lib/action_view/template/handlers/erb.rb | 46 | ||||
-rw-r--r-- | actionpack/test/template/erb/tag_helper_test.rb | 60 | ||||
-rw-r--r-- | actionpack/test/template/javascript_helper_test.rb | 12 | ||||
-rw-r--r-- | actionpack/test/template/tag_helper_test.rb | 16 |
9 files changed, 154 insertions, 64 deletions
diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb index b4f649385a..e359b0bdac 100644 --- a/actionpack/lib/action_view/helpers.rb +++ b/actionpack/lib/action_view/helpers.rb @@ -10,6 +10,7 @@ module ActionView #:nodoc: autoload :CsrfHelper, 'action_view/helpers/csrf_helper' autoload :DateHelper, 'action_view/helpers/date_helper' autoload :DebugHelper, 'action_view/helpers/debug_helper' + autoload :DeprecatedBlockHelpers, 'action_view/helpers/deprecated_block_helpers' autoload :FormHelper, 'action_view/helpers/form_helper' autoload :FormOptionsHelper, 'action_view/helpers/form_options_helper' autoload :FormTagHelper, 'action_view/helpers/form_tag_helper' diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index 8c48300ed3..75fc2fddeb 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -30,14 +30,10 @@ module ActionView # <b><%= @greeting %></b> # </body></html> # - def capture(*args, &block) - # Return captured buffer in erb. - if block_called_from_erb?(block) - with_output_buffer { block.call(*args) } - else - # Return block result otherwise, but protect buffer also. - with_output_buffer { return block.call(*args) } - end + def capture(*args) + value = nil + buffer = with_output_buffer { value = yield *args } + buffer.presence || value end # Calling content_for stores a block of markup in an identifier for later use. @@ -143,7 +139,7 @@ module ActionView # Defaults to a new empty string. def with_output_buffer(buf = nil) #:nodoc: unless buf - buf = ActiveSupport::SafeBuffer.new + buf = ActionView::OutputBuffer.new buf.force_encoding(output_buffer.encoding) if buf.respond_to?(:force_encoding) end self.output_buffer, old_buffer = buf, output_buffer diff --git a/actionpack/lib/action_view/helpers/deprecated_block_helpers.rb b/actionpack/lib/action_view/helpers/deprecated_block_helpers.rb new file mode 100644 index 0000000000..ffbffbf25e --- /dev/null +++ b/actionpack/lib/action_view/helpers/deprecated_block_helpers.rb @@ -0,0 +1,35 @@ +module ActionView + module Helpers + module DeprecatedBlockHelpers + extend ActiveSupport::Concern + + include ActionView::Helpers::TagHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::JavaScriptHelper + + def content_tag(*, &block) + block_called_from_erb?(block) ? safe_concat(super) : super + end + + def javascript_tag(*, &block) + block_called_from_erb?(block) ? safe_concat(super) : super + end + + BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template' + + if RUBY_VERSION < '1.9.0' + # Check whether we're called from an erb template. + # We'd return a string in any other case, but erb <%= ... %> + # can't take an <% end %> later on, so we have to use <% ... %> + # and implicitly concat. + def block_called_from_erb?(block) + block && eval(BLOCK_CALLED_FROM_ERB, block) + end + else + def block_called_from_erb?(block) + block && eval(BLOCK_CALLED_FROM_ERB, block.binding) + end + end + end + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 2c73ff88f7..8dab3094dd 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -83,13 +83,7 @@ module ActionView content_or_options_with_block end - tag = content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS)) - - if block_called_from_erb?(block) - safe_concat(tag) - else - tag - end + content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS)) end def javascript_cdata_section(content) #:nodoc: diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 513d72880c..d9d2588a2a 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -7,6 +7,9 @@ module ActionView module TagHelper include ERB::Util + extend ActiveSupport::Concern + include CaptureHelper + BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer autoplay controls loop selected hidden scoped async defer reversed ismap seemless muted required @@ -69,13 +72,7 @@ module ActionView def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block) if block_given? options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash) - content_tag = content_tag_string(name, capture(&block), options, escape) - - if block_called_from_erb?(block) - safe_concat(content_tag) - else - content_tag - end + content_tag_string(name, capture(&block), options, escape) else content_tag_string(name, content_or_options_with_block, options, escape) end @@ -109,21 +106,6 @@ module ActionView end private - BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template' - - if RUBY_VERSION < '1.9.0' - # Check whether we're called from an erb template. - # We'd return a string in any other case, but erb <%= ... %> - # can't take an <% end %> later on, so we have to use <% ... %> - # and implicitly concat. - def block_called_from_erb?(block) - block && eval(BLOCK_CALLED_FROM_ERB, block) - end - else - def block_called_from_erb?(block) - block && eval(BLOCK_CALLED_FROM_ERB, block.binding) - end - end def content_tag_string(name, content, options, escape = true) tag_options = tag_options(options, escape) if options diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 4b7cec50f3..3fcae167ff 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -3,10 +3,46 @@ require 'active_support/core_ext/string/output_safety' require 'erubis' module ActionView + class OutputBuffer + def initialize + @buffer = ActiveSupport::SafeBuffer.new + end + + def safe_concat(value) + @buffer.safe_concat(value) + end + + def <<(value) + @buffer << value.to_s + end + + def length + @buffer.length + end + + def [](*args) + @buffer[*args] + end + + def to_s + @buffer.to_s + end + + def empty? + @buffer.empty? + end + + if "".respond_to?(:force_encoding) + def force_encoding(encoding) + @buffer.force_encoding(encoding) + end + end + end + module Template::Handlers class Erubis < ::Erubis::Eruby def add_preamble(src) - src << "@output_buffer = ActiveSupport::SafeBuffer.new;" + src << "@output_buffer = ActionView::OutputBuffer.new;" end def add_text(src, text) @@ -15,10 +51,10 @@ module ActionView end def add_expr_literal(src, code) - if code =~ /\s*raw\s+(.*)/ - src << "@output_buffer.safe_concat((" << $1 << ").to_s);" + if code =~ /(do|\{)(\s*\|[^|]*\|)?\s*\Z/ + src << '@output_buffer << ' << code else - src << '@output_buffer << ((' << code << ').to_s);' + src << '@output_buffer << (' << code << ');' end end @@ -42,7 +78,7 @@ module ActionView self.erb_trim_mode = '-' self.default_format = Mime::HTML - + cattr_accessor :erb_implementation self.erb_implementation = Erubis diff --git a/actionpack/test/template/erb/tag_helper_test.rb b/actionpack/test/template/erb/tag_helper_test.rb new file mode 100644 index 0000000000..d9ca828b43 --- /dev/null +++ b/actionpack/test/template/erb/tag_helper_test.rb @@ -0,0 +1,60 @@ +require "abstract_unit" + +module ERBTest + module SharedTagHelpers + extend ActiveSupport::Testing::Declarative + + def render_content(start, inside) + template = block_helper(start, inside) + ActionView::Template::Handlers::Erubis.new(template).evaluate(context.new) + end + + test "percent equals works for content_tag" do + assert_equal "<div>Hello world</div>", render_content("content_tag(:div)", "Hello world") + end + + test "percent equals works for javascript_tag" do + expected_output = "<script type=\"text/javascript\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" + assert_equal expected_output, render_content("javascript_tag", "alert('Hello')") + end + + test "percent equals works for javascript_tag with options" do + expected_output = "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" + assert_equal expected_output, render_content("javascript_tag(:id => 'the_js_tag')", "alert('Hello')") + end + end + + class TagHelperTest < ActiveSupport::TestCase + def context + Class.new do + include ActionView::Helpers::TagHelper + include ActionView::Helpers::JavaScriptHelper + + attr_accessor :output_buffer + end + end + + def block_helper(str, rest) + "<%= #{str} do %>#{rest}<% end %>" + end + + include SharedTagHelpers + end + + class DeprecatedTagHelperTest < ActiveSupport::TestCase + def context + Class.new do + include ActionView::Helpers::TagHelper + include ActionView::Helpers::JavaScriptHelper + include ActionView::Helpers::DeprecatedBlockHelpers + attr_accessor :output_buffer + end + end + + def block_helper(str, rest) + "<% __in_erb_template=true %><% #{str} do %>#{rest}<% end %>" + end + + include SharedTagHelpers + end +end
\ No newline at end of file diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index 6604f1c095..f49b763881 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -74,18 +74,6 @@ class JavaScriptHelperTest < ActionView::TestCase javascript_tag("alert('hello')", :id => "the_js_tag") end - def test_javascript_tag_with_block_in_erb - __in_erb_template = '' - javascript_tag { concat "alert('hello')" } - assert_dom_equal "<script type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", output_buffer - end - - def test_javascript_tag_with_block_and_options_in_erb - __in_erb_template = '' - javascript_tag(:id => "the_js_tag") { concat "alert('hello')" } - assert_dom_equal "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", output_buffer - end - def test_javascript_cdata_section assert_dom_equal "\n//<![CDATA[\nalert('hello')\n//]]>\n", javascript_cdata_section("alert('hello')") end diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb index 3858ffde40..256d9bdcde 100644 --- a/actionpack/test/template/tag_helper_test.rb +++ b/actionpack/test/template/tag_helper_test.rb @@ -42,15 +42,13 @@ class TagHelperTest < ActionView::TestCase end def test_content_tag_with_block_in_erb - __in_erb_template = '' - content_tag(:div) { concat "Hello world!" } - assert_dom_equal "<div>Hello world!</div>", output_buffer + buffer = content_tag(:div) { concat "Hello world!" } + assert_dom_equal "<div>Hello world!</div>", buffer end def test_content_tag_with_block_and_options_in_erb - __in_erb_template = '' - content_tag(:div, :class => "green") { concat "Hello world!" } - assert_dom_equal %(<div class="green">Hello world!</div>), output_buffer + buffer = content_tag(:div, :class => "green") { concat "Hello world!" } + assert_dom_equal %(<div class="green">Hello world!</div>), buffer end def test_content_tag_with_block_and_options_out_of_erb @@ -68,10 +66,10 @@ class TagHelperTest < ActionView::TestCase output_buffer end + # TAG TODO: Move this into a real template def test_content_tag_nested_in_content_tag_in_erb - __in_erb_template = true - content_tag("p") { concat content_tag("b", "Hello") } - assert_equal '<p><b>Hello</b></p>', output_buffer + buffer = content_tag("p") { concat content_tag("b", "Hello") } + assert_equal '<p><b>Hello</b></p>', buffer end def test_content_tag_with_escaped_array_class |