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
 67 def initialize(input, properties={})
 68   @escape = escape = properties.fetch(:escape){properties.fetch(:escape_html, false)}
 69   trim       = properties[:trim] != false
 70   @filename  = properties[:filename]
 71   @bufvar = bufvar = properties[:bufvar] || properties[:outvar] || "_buf"
 72   bufval = properties[:bufval] || 'String.new'
 73   regexp = properties[:regexp] || /<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/m
 74   preamble   = properties[:preamble] || "#{bufvar} = #{bufval};"
 75   postamble  = properties[:postamble] || "#{bufvar}.to_s\n"
 76 
 77   @src = src = properties[:src] || String.new
 78   src << "# frozen_string_literal: true\n" if properties[:freeze]
 79   src << "begin; __original_outvar = #{bufvar} if defined?(#{bufvar}); " if properties[:ensure]
 80 
 81   unless @escapefunc = properties[:escapefunc]
 82     if escape
 83       @escapefunc = '__erubi.h'
 84       src << "__erubi = ::Erubi;"
 85     else
 86       @escapefunc = '::Erubi.h'
 87     end
 88   end
 89 
 90   src << preamble
 91 
 92   pos = 0
 93   is_bol = true
 94   input.scan(regexp) do |indicator, code, tailch, rspace|
 95     match = Regexp.last_match
 96     len  = match.begin(0) - pos
 97     text = input[pos, len]
 98     pos  = match.end(0)
 99     ch   = indicator ? indicator[RANGE_FIRST] : nil
100 
101     lspace = nil
102 
103     unless ch == '='
104       if text.empty?
105         lspace = "" if is_bol
106       elsif text[RANGE_LAST] == "\n"
107         lspace = ""
108       else
109         rindex = text.rindex("\n")
110         if rindex
111           range = rindex+1..-1
112           s = text[range]
113           if s =~ /\A[ \t]*\z/
114             lspace = s
115             text[range] = ''
116           end
117         else
118           if is_bol && text =~ /\A[ \t]*\z/
119             lspace = text.dup
120             text[RANGE_ALL] = ''
121           end
122         end
123       end
124     end
125 
126     is_bol = rspace ? true : false
127     add_text(text) if text && !text.empty?
128     case ch
129     when '='
130       rspace = nil if tailch && !tailch.empty?
131       add_text(lspace) if lspace
132       add_expression(indicator, code)
133       add_text(rspace) if rspace
134     when '#'
135       n = code.count("\n") + (rspace ? 1 : 0)
136       if trim
137         add_code("\n" * n)
138       else
139         add_text(lspace) if lspace
140         add_code("\n" * n)
141         add_text(rspace) if rspace
142       end
143     when '%'
144       add_text("#{lspace}#{prefix||='<%'}#{code}#{tailch}#{postfix||='%>'}#{rspace}")
145     when nil, '-'
146       if trim && lspace && rspace
147         add_code("#{lspace}#{code}#{rspace}")
148       else
149         add_text(lspace) if lspace
150         add_code(code)
151         add_text(rspace) if rspace
152       end
153     else
154       handle(indicator, code, tailch, rspace, lspace)
155     end
156   end
157   rest = pos == 0 ? input : input[pos..-1]
158   add_text(rest)
159 
160   src << "\n" unless src[RANGE_LAST] == "\n"
161   add_postamble(postamble)
162   src << "; ensure\n  #{bufvar} = __original_outvar\nend\n" if properties[:ensure]
163   src.freeze
164   freeze
165 end

Private Instance Methods

add_code(code) click to toggle source

Add ruby code to the template

    # File lib/erubi.rb
175 def add_code(code)
176   @src << code
177   @src << ';' unless code[RANGE_LAST] == "\n"
178 end
add_expression(indicator, code) click to toggle source

Add the given ruby expression result to the template, escaping it based on the indicator given and escape flag.

    # File lib/erubi.rb
182 def add_expression(indicator, code)
183   if ((indicator == '=') ^ @escape)
184     add_expression_result(code)
185   else
186     add_expression_result_escaped(code)
187   end
188 end
add_expression_result(code) click to toggle source

Add the result of Ruby expression to the template

    # File lib/erubi.rb
191 def add_expression_result(code)
192   @src << " #{@bufvar} << (" << code << ').to_s;'
193 end
add_expression_result_escaped(code) click to toggle source

Add the escaped result of Ruby expression to the template

    # File lib/erubi.rb
196 def add_expression_result_escaped(code)
197   @src << " #{@bufvar} << #{@escapefunc}((" << code << '));'
198 end
add_postamble(postamble) click to toggle source

Add the given postamble to the src. Can be overridden in subclasses to make additional changes to src that depend on the current state.

    # File lib/erubi.rb
202 def add_postamble(postamble)
203   src << postamble
204 end
add_text(text) click to toggle source

Add raw text to the template

    # File lib/erubi.rb
170 def add_text(text)
171   @src << " #{@bufvar} << '" << text.gsub(/['\\]/, '\\\\\&') << TEXT_END unless text.empty?
172 end
handle(indicator, code, tailch, rspace, lspace) click to toggle source

Raise an exception, as the base engine class does not support handling other indicators.

    # File lib/erubi.rb
207 def handle(indicator, code, tailch, rspace, lspace)
208   raise ArgumentError, "Invalid indicator: #{indicator}"
209 end