class Erubi::Engine

def initialize(input, properties={})

+:trim+ :: Whether to trim leading and trailing whitespace, true by default.
+:src+ :: The initial value to use for the source code, an empty string by default.
+:regexp+ :: The regexp to use for scanning.
+:preamble+ :: The preamble for the template, by default initializes the buffer variable.
+:postamble+ :: The postamble for the template, by default returns the resulting source code.
+:outvar+ :: Same as +:bufvar+, with lower priority.
+:literal_postfix+ :: The postfix to output when using escaped tag delimiters (default '%>').
+:literal_prefix+ :: The prefix to output when using escaped tag delimiters (default '<%').
in order to improve performance.
Can be set to +false+ on Ruby 2.3+ when frozen string literals are enabled
(default: +true+ on Ruby 2.1+, +false+ on Ruby 2.0 and older).
+:freeze_template_literals+ :: Whether to suffix all literal strings for template code with .freeze
the file, and having the magic comment later in the file can trigger warnings.
source code in other code, because the magic comment only has an effect at the beginning of
the resulting source code. Note this may cause problems if you are wrapping the resulting
+:freeze+ :: Whether to enable add a frozen_string_literal: true magic comment at the top of
+:filename+ :: The filename for the template.
+:escape_html+ :: Same as +:escape+, with lower priority.
+:escape+ :: Whether to make <%= escape by default, and <%== not escape by default.
+:escapefunc+ :: The function to use for escaping, as a string (default: '::Erubi.h').
+:ensure+ :: Wrap the template in a begin/ensure block restoring the previous value of bufvar.
template rendering (default +false+).
performance, but can cause issues when the buffer variable is reassigned during
+:chain_appends+ :: Whether to chain << calls to the buffer variable. Offers better
+:bufvar+ :: The variable name to use for the buffer variable, as a string.
+:bufval+ :: The value to use for the buffer variable, as a string (default '::String.new').
Initialize a new Erubi::Engine. Options:
def initialize(input, properties={})
  @escape = escape = properties.fetch(:escape){properties.fetch(:escape_html, false)}
  trim       = properties[:trim] != false
  @filename  = properties[:filename]
  @bufvar = bufvar = properties[:bufvar] || properties[:outvar] || "_buf"
  bufval = properties[:bufval] || '::String.new'
  regexp = properties[:regexp] || DEFAULT_REGEXP
  literal_prefix = properties[:literal_prefix] || '<%'
  literal_postfix = properties[:literal_postfix] || '%>'
  preamble   = properties[:preamble] || "#{bufvar} = #{bufval};"
  postamble  = properties[:postamble] || "#{bufvar}.to_s\n"
  @chain_appends = properties[:chain_appends]
  @text_end = if properties.fetch(:freeze_template_literals, FREEZE_TEMPLATE_LITERALS)
    "'.freeze"
  else
    "'"
  end
  @buffer_on_stack = false
  @src = src = properties[:src] || String.new
  src << "# frozen_string_literal: true\n" if properties[:freeze]
  if properties[:ensure]
    src << "begin; __original_outvar = #{bufvar}"
    if SKIP_DEFINED_FOR_INSTANCE_VARIABLE && /\A@[^@]/ =~ bufvar
      src << "; "
    else
      src << " if defined?(#{bufvar}); "
    end
  end
  unless @escapefunc = properties[:escapefunc]
    if escape
      @escapefunc = '__erubi.h'
      src << "__erubi = ::Erubi; "
    else
      @escapefunc = '::Erubi.h'
    end
  end
  src << preamble
  pos = 0
  is_bol = true
  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
      elsif text[RANGE_LAST] == "\n"
        lspace = ""
      else
        rindex = text.rindex("\n")
        if rindex
          range = rindex+1..-1
          s = text[range]
          if /\A[ \t]*\z/.send(MATCH_METHOD, s)
            lspace = s
            text[range] = ''
          end
        else
          if is_bol && /\A[ \t]*\z/.send(MATCH_METHOD, text)
            lspace = text
            text = ''
          end
        end
      end
    end
    is_bol = rspace
    add_text(text)
    case ch
    when '='
      rspace = nil if tailch && !tailch.empty?
      add_expression(indicator, code)
      add_text(rspace) if rspace
    when nil, '-'
      if trim && lspace && rspace
        add_code("#{lspace}#{code}#{rspace}")
      else
        add_text(lspace) if lspace
        add_code(code)
        add_text(rspace) if rspace
      end
    when '#'
      n = code.count("\n") + (rspace ? 1 : 0)
      if trim && lspace && rspace
        add_code("\n" * n)
      else
        add_text(lspace) if lspace
        add_code("\n" * n)
        add_text(rspace) if rspace
      end
    when '%'
      add_text("#{lspace}#{literal_prefix}#{code}#{tailch}#{literal_postfix}#{rspace}")
    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"
  add_postamble(postamble)
  src << "; ensure\n  " << bufvar << " = __original_outvar\nend\n" if properties[:ensure]
  src.freeze
  freeze
end