class Erubi::Engine
Attributes
The variable name used for the buffer variable.
The filename of the template, if one was given.
The frozen ruby source code generated from the template, which can be evaled.
Public Class Methods
Initialize a new Erubi::Engine
. Options:
:bufval
-
The value to use for the buffer variable, as a string (default
'::String.new'
). :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.
:literal_prefix
-
The prefix to output when using escaped tag delimiters (default
'<%'
). :literal_postfix
-
The postfix to output when using escaped tag delimiters (default
'%>'
). :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 the buffer variable.
:regexp
-
The regexp to use for scanning.
:src
-
The initial value to use for the source code, an empty string by default.
:trim
-
Whether to trim leading and trailing whitespace, true by default.
# File lib/erubi.rb 74 def initialize(input, properties={}) 75 @escape = escape = properties.fetch(:escape){properties.fetch(:escape_html, false)} 76 trim = properties[:trim] != false 77 @filename = properties[:filename] 78 @bufvar = bufvar = properties[:bufvar] || properties[:outvar] || "_buf" 79 bufval = properties[:bufval] || '::String.new' 80 regexp = properties[:regexp] || /<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/m 81 literal_prefix = properties[:literal_prefix] || '<%' 82 literal_postfix = properties[:literal_postfix] || '%>' 83 preamble = properties[:preamble] || "#{bufvar} = #{bufval};" 84 postamble = properties[:postamble] || "#{bufvar}.to_s\n" 85 86 @src = src = properties[:src] || String.new 87 src << "# frozen_string_literal: true\n" if properties[:freeze] 88 src << "begin; __original_outvar = #{bufvar} if defined?(#{bufvar}); " if properties[:ensure] 89 90 unless @escapefunc = properties[:escapefunc] 91 if escape 92 @escapefunc = '__erubi.h' 93 src << "__erubi = ::Erubi;" 94 else 95 @escapefunc = '::Erubi.h' 96 end 97 end 98 99 src << preamble 100 101 pos = 0 102 is_bol = true 103 input.scan(regexp) do |indicator, code, tailch, rspace| 104 match = Regexp.last_match 105 len = match.begin(0) - pos 106 text = input[pos, len] 107 pos = match.end(0) 108 ch = indicator ? indicator[RANGE_FIRST] : nil 109 110 lspace = nil 111 112 unless ch == '=' 113 if text.empty? 114 lspace = "" if is_bol 115 elsif text[RANGE_LAST] == "\n" 116 lspace = "" 117 else 118 rindex = text.rindex("\n") 119 if rindex 120 range = rindex+1..-1 121 s = text[range] 122 if /\A[ \t]*\z/.send(MATCH_METHOD, s) 123 lspace = s 124 text[range] = '' 125 end 126 else 127 if is_bol && /\A[ \t]*\z/.send(MATCH_METHOD, text) 128 lspace = text 129 text = '' 130 end 131 end 132 end 133 end 134 135 is_bol = rspace 136 add_text(text) 137 case ch 138 when '=' 139 rspace = nil if tailch && !tailch.empty? 140 add_expression(indicator, code) 141 add_text(rspace) if rspace 142 when nil, '-' 143 if trim && lspace && rspace 144 add_code("#{lspace}#{code}#{rspace}") 145 else 146 add_text(lspace) if lspace 147 add_code(code) 148 add_text(rspace) if rspace 149 end 150 when '#' 151 n = code.count("\n") + (rspace ? 1 : 0) 152 if trim && lspace && rspace 153 add_code("\n" * n) 154 else 155 add_text(lspace) if lspace 156 add_code("\n" * n) 157 add_text(rspace) if rspace 158 end 159 when '%' 160 add_text("#{lspace}#{literal_prefix}#{code}#{tailch}#{literal_postfix}#{rspace}") 161 else 162 handle(indicator, code, tailch, rspace, lspace) 163 end 164 end 165 rest = pos == 0 ? input : input[pos..-1] 166 add_text(rest) 167 168 src << "\n" unless src[RANGE_LAST] == "\n" 169 add_postamble(postamble) 170 src << "; ensure\n " << bufvar << " = __original_outvar\nend\n" if properties[:ensure] 171 src.freeze 172 freeze 173 end
Private Instance Methods
Add ruby code to the template
# File lib/erubi.rb 191 def add_code(code) 192 @src << code 193 @src << ';' unless code[RANGE_LAST] == "\n" 194 end
Add the given ruby expression result to the template, escaping it based on the indicator given and escape flag.
# File lib/erubi.rb 198 def add_expression(indicator, code) 199 if ((indicator == '=') ^ @escape) 200 add_expression_result(code) 201 else 202 add_expression_result_escaped(code) 203 end 204 end
Add the result of Ruby expression to the template
# File lib/erubi.rb 207 def add_expression_result(code) 208 @src << ' ' << @bufvar << ' << (' << code << ').to_s;' 209 end
Add the escaped result of Ruby expression to the template
# File lib/erubi.rb 212 def add_expression_result_escaped(code) 213 @src << ' ' << @bufvar << ' << ' << @escapefunc << '((' << code << '));' 214 end
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 218 def add_postamble(postamble) 219 src << postamble 220 end
Add raw text to the template. Modifies argument if argument is mutable as a memory optimization. Must be called with a string, cannot be called with nil (Rails’s subclass depends on it).
# File lib/erubi.rb 179 def add_text(text) 180 return if text.empty? 181 182 if text.frozen? 183 text = text.gsub(/['\\]/, '\\\\\&') 184 else 185 text.gsub!(/['\\]/, '\\\\\&') 186 end 187 @src << " " << @bufvar << " << '" << text << TEXT_END 188 end
Raise an exception, as the base engine class does not support handling other indicators.
# File lib/erubi.rb 223 def handle(indicator, code, tailch, rspace, lspace) 224 raise ArgumentError, "Invalid indicator: #{indicator}" 225 end