diff options
author | Jeremy Evans <code@jeremyevans.net> | 2017-01-20 15:02:34 -0800 |
---|---|---|
committer | Jeremy Daer <jeremydaer@gmail.com> | 2017-01-25 01:41:27 -0700 |
commit | 7da8d76206271bdf200ea201f7e5a49afb9bc9e7 (patch) | |
tree | bb8763b3790f6d841327e4435d5b3a6e4e296be0 /actionview/lib | |
parent | 72a869e626e2772733946483e21d65247864d856 (diff) | |
download | rails-7da8d76206271bdf200ea201f7e5a49afb9bc9e7.tar.gz rails-7da8d76206271bdf200ea201f7e5a49afb9bc9e7.tar.bz2 rails-7da8d76206271bdf200ea201f7e5a49afb9bc9e7.zip |
Change ActionView ERB Handler from Erubis to Erubi
Erubi offers the following advantages for Rails:
* Works with ruby's --enable-frozen-string-literal option
* Has 88% smaller memory footprint
* Does no freedom patching (Erubis adds a method to Kernel)
* Has simpler internals (1 file, <150 lines of code)
* Has an open development model (Erubis doesn't have a
public source control repository or bug tracker)
* Is not dead (Erubis hasn't been updated since 2011)
Erubi is a simplified fork of Erubis that contains just the
parts that are generally needed (which includes the parts
that Rails uses). The only intentional difference in
behavior is that it does not include support for <%=== tags
for debug output. That could be added to the ActionView ERB
handler if it is desired.
The Erubis template handler remains in a deprecated state
so that code that accesses it directly does not break. It
can be removed after Rails 5.1.
Diffstat (limited to 'actionview/lib')
-rw-r--r-- | actionview/lib/action_view/base.rb | 2 | ||||
-rw-r--r-- | actionview/lib/action_view/template/handlers/erb.rb | 77 | ||||
-rw-r--r-- | actionview/lib/action_view/template/handlers/erb/erubi.rb | 81 | ||||
-rw-r--r-- | actionview/lib/action_view/template/handlers/erb/erubis.rb | 80 |
4 files changed, 167 insertions, 73 deletions
diff --git a/actionview/lib/action_view/base.rb b/actionview/lib/action_view/base.rb index b7c05fdb88..5387174467 100644 --- a/actionview/lib/action_view/base.rb +++ b/actionview/lib/action_view/base.rb @@ -11,7 +11,7 @@ module ActionView #:nodoc: # = Action View Base # # Action View templates can be written in several ways. - # If the template file has a <tt>.erb</tt> extension, then it uses the erubis[https://rubygems.org/gems/erubis] + # If the template file has a <tt>.erb</tt> extension, then it uses the erubi[https://rubygems.org/gems/erubi] # template system which can embed Ruby into an HTML document. # If the template file has a <tt>.builder</tt> extension, then Jim Weirich's Builder::XmlMarkup library is used. # diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb index 5d047a6991..cee5408aa9 100644 --- a/actionview/lib/action_view/template/handlers/erb.rb +++ b/actionview/lib/action_view/template/handlers/erb.rb @@ -1,79 +1,12 @@ -require "erubis" - module ActionView class Template module Handlers - class Erubis < ::Erubis::Eruby - def add_preamble(src) - @newline_pending = 0 - src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;" - end - - def add_text(src, text) - return if text.empty? - - if text == "\n" - @newline_pending += 1 - else - src << "@output_buffer.safe_append='" - src << "\n" * @newline_pending if @newline_pending > 0 - src << escape_text(text) - src << "'.freeze;" - - @newline_pending = 0 - end - end - - # Erubis toggles <%= and <%== behavior when escaping is enabled. - # We override to always treat <%== as escaped. - def add_expr(src, code, indicator) - case indicator - when "==" - add_expr_escaped(src, code) - else - super - end - end - - BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/ - - def add_expr_literal(src, code) - flush_newline_if_pending(src) - if BLOCK_EXPR.match?(code) - src << "@output_buffer.append= " << code - else - src << "@output_buffer.append=(" << code << ");" - end - end - - def add_expr_escaped(src, code) - flush_newline_if_pending(src) - if BLOCK_EXPR.match?(code) - src << "@output_buffer.safe_expr_append= " << code - else - src << "@output_buffer.safe_expr_append=(" << code << ");" - end - end - - def add_stmt(src, code) - flush_newline_if_pending(src) - super - end - - def add_postamble(src) - flush_newline_if_pending(src) - src << "@output_buffer.to_s" - end - - def flush_newline_if_pending(src) - if @newline_pending > 0 - src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;" - @newline_pending = 0 - end - end - end + Erubis = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("Erubis", "ActionView::Template::Handlers::ERB::Erubis", message: "ActionView::Template::Handlers::Erubis is deprecated and will be removed from Rails 5.2. Switch to ActionView::Template::Handlers::ERB::Erubi instead.") class ERB + autoload :Erubi, "action_view/template/handlers/erb/erubi" + autoload :Erubis, "action_view/template/handlers/erb/erubis" + # Specify trim mode for the ERB compiler. Defaults to '-'. # See ERB documentation for suitable values. class_attribute :erb_trim_mode @@ -81,7 +14,7 @@ module ActionView # Default implementation used. class_attribute :erb_implementation - self.erb_implementation = Erubis + self.erb_implementation = Erubi # Do not escape templates of these mime types. class_attribute :escape_whitelist diff --git a/actionview/lib/action_view/template/handlers/erb/erubi.rb b/actionview/lib/action_view/template/handlers/erb/erubi.rb new file mode 100644 index 0000000000..755cc84015 --- /dev/null +++ b/actionview/lib/action_view/template/handlers/erb/erubi.rb @@ -0,0 +1,81 @@ +require "erubi" + +module ActionView + class Template + module Handlers + class ERB + class Erubi < ::Erubi::Engine + # :nodoc: all + def initialize(input, properties = {}) + @newline_pending = 0 + + # Dup properties so that we don't modify argument + properties = Hash[properties] + properties[:preamble] = "@output_buffer = output_buffer || ActionView::OutputBuffer.new;" + properties[:postamble] = "@output_buffer.to_s" + properties[:bufvar] = "@output_buffer" + properties[:escapefunc] = "" + + super + end + + def evaluate(action_view_erb_handler_context) + pr = eval("proc { #{@src} }", binding, @filename || "(erubi)") + action_view_erb_handler_context.instance_eval(&pr) + end + + private + def add_text(text) + return if text.empty? + + if text == "\n" + @newline_pending += 1 + else + src << "@output_buffer.safe_append='" + src << "\n" * @newline_pending if @newline_pending > 0 + src << text.gsub(/['\\]/, '\\\\\&') + src << "'.freeze;" + + @newline_pending = 0 + end + end + + BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/ + + def add_expression(indicator, code) + flush_newline_if_pending(src) + + if (indicator == "==") || @escape + src << "@output_buffer.safe_expr_append=" + else + src << "@output_buffer.append=" + end + + if BLOCK_EXPR.match?(code) + src << " " << code + else + src << "(" << code << ");" + end + end + + def add_code(code) + flush_newline_if_pending(src) + super + end + + def add_postamble(_) + flush_newline_if_pending(src) + super + end + + def flush_newline_if_pending(src) + if @newline_pending > 0 + src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;" + @newline_pending = 0 + end + end + end + end + end + end +end diff --git a/actionview/lib/action_view/template/handlers/erb/erubis.rb b/actionview/lib/action_view/template/handlers/erb/erubis.rb new file mode 100644 index 0000000000..bf316ceec5 --- /dev/null +++ b/actionview/lib/action_view/template/handlers/erb/erubis.rb @@ -0,0 +1,80 @@ +require "erubis" + +module ActionView + class Template + module Handlers + class ERB + class Erubis < ::Erubis::Eruby + # :nodoc: all + def add_preamble(src) + @newline_pending = 0 + src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;" + end + + def add_text(src, text) + return if text.empty? + + if text == "\n" + @newline_pending += 1 + else + src << "@output_buffer.safe_append='" + src << "\n" * @newline_pending if @newline_pending > 0 + src << escape_text(text) + src << "'.freeze;" + + @newline_pending = 0 + end + end + + # Erubis toggles <%= and <%== behavior when escaping is enabled. + # We override to always treat <%== as escaped. + def add_expr(src, code, indicator) + case indicator + when "==" + add_expr_escaped(src, code) + else + super + end + end + + BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/ + + def add_expr_literal(src, code) + flush_newline_if_pending(src) + if BLOCK_EXPR.match?(code) + src << "@output_buffer.append= " << code + else + src << "@output_buffer.append=(" << code << ");" + end + end + + def add_expr_escaped(src, code) + flush_newline_if_pending(src) + if BLOCK_EXPR.match?(code) + src << "@output_buffer.safe_expr_append= " << code + else + src << "@output_buffer.safe_expr_append=(" << code << ");" + end + end + + def add_stmt(src, code) + flush_newline_if_pending(src) + super + end + + def add_postamble(src) + flush_newline_if_pending(src) + src << "@output_buffer.to_s" + end + + def flush_newline_if_pending(src) + if @newline_pending > 0 + src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;" + @newline_pending = 0 + end + end + end + end + end + end +end |