class Erubi::Engine

Attributes

bufvar[R]

The variable name used for the buffer variable.

filename[R]

The filename of the template, if one was given.

src[R]

The frozen ruby source code generated from the template, which can be evaled.

Public Class Methods

new(input, properties={}) click to toggle source

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.

: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.

# File lib/erubi.rb, line 67
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] || /<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/
  preamble   = properties[:preamble] || "#{bufvar} = #{bufval};"
  postamble  = properties[:postamble] || "#{bufvar}.to_s\n"

  @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;"
    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 s =~ /\A[ \t]*\z/
            lspace = s
            text[range] = ''
          end
        else
          if is_bol && text =~ /\A[ \t]*\z/
            lspace = text.dup
            text[RANGE_ALL] = ''
          end
        end
      end
    end

    is_bol = rspace ? true : false
    add_text(text) if text && !text.empty?
    case ch
    when '='
      rspace = nil if tailch && !tailch.empty?
      add_text(lspace) if lspace
      add_expression(indicator, code)
      add_text(rspace) if rspace
    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
    when '%'
      add_text("#{lspace}#{prefix||='<%'}#{code}#{tailch}#{postfix||='%>'}#{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
    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