aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib/action_view/template/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'actionview/lib/action_view/template/handlers')
-rw-r--r--actionview/lib/action_view/template/handlers/builder.rb25
-rw-r--r--actionview/lib/action_view/template/handlers/erb.rb77
-rw-r--r--actionview/lib/action_view/template/handlers/erb/deprecated_erubis.rb11
-rw-r--r--actionview/lib/action_view/template/handlers/erb/erubi.rb83
-rw-r--r--actionview/lib/action_view/template/handlers/erb/erubis.rb83
-rw-r--r--actionview/lib/action_view/template/handlers/html.rb11
-rw-r--r--actionview/lib/action_view/template/handlers/raw.rb11
7 files changed, 301 insertions, 0 deletions
diff --git a/actionview/lib/action_view/template/handlers/builder.rb b/actionview/lib/action_view/template/handlers/builder.rb
new file mode 100644
index 0000000000..61492ce448
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/builder.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module ActionView
+ module Template::Handlers
+ class Builder
+ class_attribute :default_format, default: :xml
+
+ def call(template)
+ require_engine
+ "xml = ::Builder::XmlMarkup.new(:indent => 2);" \
+ "self.output_buffer = xml.target!;" +
+ template.source +
+ ";xml.target!;"
+ end
+
+ private
+ def require_engine # :doc:
+ @required ||= begin
+ require "builder"
+ true
+ end
+ end
+ end
+ end
+end
diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb
new file mode 100644
index 0000000000..c41de62e52
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/erb.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module ActionView
+ class Template
+ module Handlers
+ autoload :Erubis, "action_view/template/handlers/erb/deprecated_erubis"
+
+ 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, default: "-"
+
+ # Default implementation used.
+ class_attribute :erb_implementation, default: Erubi
+
+ # Do not escape templates of these mime types.
+ class_attribute :escape_whitelist, default: ["text/plain"]
+
+ ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
+
+ def self.call(template)
+ new.call(template)
+ end
+
+ def supports_streaming?
+ true
+ end
+
+ def handles_encoding?
+ true
+ end
+
+ def call(template)
+ # First, convert to BINARY, so in case the encoding is
+ # wrong, we can still find an encoding tag
+ # (<%# encoding %>) inside the String using a regular
+ # expression
+ template_source = template.source.dup.force_encoding(Encoding::ASCII_8BIT)
+
+ erb = template_source.gsub(ENCODING_TAG, "")
+ encoding = $2
+
+ erb.force_encoding valid_encoding(template.source.dup, encoding)
+
+ # Always make sure we return a String in the default_internal
+ erb.encode!
+
+ self.class.erb_implementation.new(
+ erb,
+ escape: (self.class.escape_whitelist.include? template.type),
+ trim: (self.class.erb_trim_mode == "-")
+ ).src
+ end
+
+ private
+
+ def valid_encoding(string, encoding)
+ # If a magic encoding comment was found, tag the
+ # String with this encoding. This is for a case
+ # where the original String was assumed to be,
+ # for instance, UTF-8, but a magic comment
+ # proved otherwise
+ string.force_encoding(encoding) if encoding
+
+ # If the String is valid, return the encoding we found
+ return string.encoding if string.valid_encoding?
+
+ # Otherwise, raise an exception
+ raise WrongEncodingError.new(string, string.encoding)
+ end
+ end
+ end
+ end
+end
diff --git a/actionview/lib/action_view/template/handlers/erb/deprecated_erubis.rb b/actionview/lib/action_view/template/handlers/erb/deprecated_erubis.rb
new file mode 100644
index 0000000000..00c7d7cc7d
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/erb/deprecated_erubis.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+::ActiveSupport::Deprecation.warn("ActionView::Template::Handlers::Erubis is deprecated and will be removed from Rails 5.2. Switch to ActionView::Template::Handlers::ERB::Erubi instead.")
+
+module ActionView
+ class Template
+ module Handlers
+ Erubis = ERB::Erubis
+ end
+ end
+end
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..db75f028ed
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/erb/erubi.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+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..dc3bf1ff27
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/erb/erubis.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+gem "erubis"
+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
diff --git a/actionview/lib/action_view/template/handlers/html.rb b/actionview/lib/action_view/template/handlers/html.rb
new file mode 100644
index 0000000000..27004a318c
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/html.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module ActionView
+ module Template::Handlers
+ class Html < Raw
+ def call(template)
+ "ActionView::OutputBuffer.new #{super}"
+ end
+ end
+ end
+end
diff --git a/actionview/lib/action_view/template/handlers/raw.rb b/actionview/lib/action_view/template/handlers/raw.rb
new file mode 100644
index 0000000000..5cd23a0060
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/raw.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module ActionView
+ module Template::Handlers
+ class Raw
+ def call(template)
+ "#{template.source.inspect}.html_safe;"
+ end
+ end
+ end
+end