lib/erubi.rb in erubi-1.0.0 vs lib/erubi.rb in erubi-1.1.0
- old
+ new
@@ -1,21 +1,25 @@
# frozen_string_literal: true
module Erubi
ESCAPE_TABLE = {'&' => '&'.freeze, '<' => '<'.freeze, '>' => '>'.freeze, '"' => '"'.freeze, "'" => '''.freeze}.freeze
- RANGE_FIRST = 0..0
RANGE_ALL = 0..-1
- RANGE_LAST = -1..-1
if RUBY_VERSION >= '1.9'
+ RANGE_FIRST = 0
+ RANGE_LAST = -1
+
# Escape the following characters with their HTML/XML
# equivalents.
def self.h(value)
value.to_s.gsub(/[&<>"']/, ESCAPE_TABLE)
end
else
# :nocov:
+ RANGE_FIRST = 0..0
+ RANGE_LAST = -1..-1
+
def self.h(value)
value.to_s.gsub(/[&<>"']/){|s| ESCAPE_TABLE[s]}
end
# :nocov:
end
@@ -29,30 +33,37 @@
# The variable name used for the buffer variable.
attr_reader :bufvar
# Initialize a new Erubi::Engine. Options:
+ # :bufval :: The value to use for the buffer variable, as a string.
# :bufvar :: The variable name to use for the buffer variable, as a string.
+ # :ensure :: Wrap the template in a begin/ensure block restoring the previous value of bufvar.
# :escapefunc :: The function to use for escaping, as a string (default: ::Erubi.h).
# :escape :: Whether to make <%= escape by default, and <%== not escape by default.
# :escape_html :: Same as :escape, with lower priority.
# :filename :: The filename for the template.
# :freeze :: Whether to enable frozen string literals in the resulting source code.
# :outvar :: Same as bufvar, with lower priority.
- # :postable :: the postamble for the template, by default returns the resulting source code.
+ # :postamble :: The postamble for the template, by default returns the resulting source code.
# :preamble :: The preamble for the template, by default initializes up the buffer variable.
+ # :regexp :: The regexp to use for scanning.
+ # :src :: The initial value to use for the source code
# :trim :: Whether to trim leading and trailing whitespace, true by default.
def initialize(input, properties={})
escape = properties.fetch(:escape){properties.fetch(:escape_html, false)}
trim = properties[:trim] != false
@filename = properties[:filename]
@bufvar = bufvar = properties[:bufvar] || properties[:outvar] || "_buf"
- preamble = properties[:preamble] || "#{bufvar} = String.new;"
+ bufval = properties[:bufval] || 'String.new'
+ regexp = properties[:regexp] || /<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/m
+ preamble = properties[:preamble] || "#{bufvar} = #{bufval};"
postamble = properties[:postamble] || "#{bufvar}.to_s\n"
- @src = src = String.new
+ @src = src = properties[:src] || String.new
src << "# frozen_string_literal: true\n" if properties[:freeze]
+ src << "begin; __original_outvar = #{bufvar} if defined?(#{bufvar}); " if properties[:ensure]
unless escapefunc = properties[:escapefunc]
if escape
escapefunc = '__erubi.h'
src << "__erubi = ::Erubi;"
@@ -63,16 +74,17 @@
src << preamble
pos = 0
is_bol = true
- input.scan(/<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/m) do |indicator, code, tailch, rspace|
+ input.scan(regexp) do |indicator, code, tailch, rspace|
match = Regexp.last_match
len = match.begin(0) - pos
text = input[pos, len]
pos = match.end(0)
ch = indicator ? indicator[RANGE_FIRST] : nil
+
lspace = nil
unless ch == '='
if text.empty?
lspace = "" if is_bol
@@ -96,45 +108,49 @@
end
end
is_bol = rspace ? true : false
add_text(text) if text && !text.empty?
- if ch == '='
+ case ch
+ when '='
rspace = nil if tailch && !tailch.empty?
add_text(lspace) if lspace
if ((indicator == '=') ^ escape)
src << " #{bufvar} << (" << code << ').to_s;'
else
src << " #{bufvar} << #{escapefunc}((" << code << '));'
end
add_text(rspace) if rspace
- elsif ch == '#'
+ when '#'
n = code.count("\n") + (rspace ? 1 : 0)
if trim
add_code("\n" * n)
else
add_text(lspace) if lspace
add_code("\n" * n)
add_text(rspace) if rspace
end
- elsif ch == '%'
+ when '%'
add_text("#{lspace}#{prefix||='<%'}#{code}#{tailch}#{postfix||='%>'}#{rspace}")
- else
+ when nil, '-'
if trim
add_code("#{lspace}#{code}#{rspace}")
else
add_text(lspace) if lspace
add_code(code)
add_text(rspace) if rspace
end
+ else
+ handle(indicator, code, tailch, rspace, lspace)
end
end
rest = pos == 0 ? input : input[pos..-1]
add_text(rest)
src << "\n" unless src[RANGE_LAST] == "\n"
src << postamble
+ src << "; ensure\n #{bufvar} = __original_outvar\nend\n" if properties[:ensure]
freeze
end
private
@@ -145,8 +161,13 @@
# Add ruby code to the template
def add_code(code)
@src << code
@src << ';' unless code[RANGE_LAST] == "\n"
+ end
+
+ # Raise an exception, as the base engine class does not support handling other indicators.
+ def handle(indicator, code, tailch, rspace, lspace)
+ raise ArgumentError, "Invalid indicator: #{indicator}"
end
end
end