class Erubi::Engine
Constants
- DEFAULT_REGEXP
-
The default regular expression used for scanning.
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
Source
# File lib/erubi.rb 94 def initialize(input, properties={}) 95 @escape = escape = properties.fetch(:escape){properties.fetch(:escape_html, false)} 96 trim = properties[:trim] != false 97 @filename = properties[:filename] 98 @bufvar = bufvar = properties[:bufvar] || properties[:outvar] || "_buf" 99 bufval = properties[:bufval] || '::String.new' 100 regexp = properties[:regexp] || DEFAULT_REGEXP 101 literal_prefix = properties[:literal_prefix] || '<%' 102 literal_postfix = properties[:literal_postfix] || '%>' 103 preamble = properties[:preamble] || "#{bufvar} = #{bufval};" 104 postamble = properties[:postamble] || "#{bufvar}.to_s\n" 105 @chain_appends = properties[:chain_appends] 106 @text_end = if properties.fetch(:freeze_template_literals, FREEZE_TEMPLATE_LITERALS) 107 "'.freeze" 108 else 109 "'" 110 end 111 112 @buffer_on_stack = false 113 @src = src = properties[:src] || String.new 114 src << "# frozen_string_literal: true\n" if properties[:freeze] 115 if properties[:ensure] 116 src << "begin; __original_outvar = #{bufvar}" 117 if SKIP_DEFINED_FOR_INSTANCE_VARIABLE && /\A@[^@]/ =~ bufvar 118 src << "; " 119 else 120 src << " if defined?(#{bufvar}); " 121 end 122 end 123 124 unless @escapefunc = properties[:escapefunc] 125 if escape 126 @escapefunc = '__erubi.h' 127 src << "__erubi = ::Erubi; " 128 else 129 @escapefunc = '::Erubi.h' 130 end 131 end 132 133 src << preamble 134 135 pos = 0 136 is_bol = true 137 input.scan(regexp) do |indicator, code, tailch, rspace| 138 match = Regexp.last_match 139 len = match.begin(0) - pos 140 text = input[pos, len] 141 pos = match.end(0) 142 ch = indicator ? indicator[RANGE_FIRST] : nil 143 144 lspace = nil 145 146 unless ch == '=' 147 if text.empty? 148 lspace = "" if is_bol 149 elsif text[RANGE_LAST] == "\n" 150 lspace = "" 151 else 152 rindex = text.rindex("\n") 153 if rindex 154 range = rindex+1..-1 155 s = text[range] 156 if /\A[ \t]*\z/.send(MATCH_METHOD, s) 157 lspace = s 158 text[range] = '' 159 end 160 else 161 if is_bol && /\A[ \t]*\z/.send(MATCH_METHOD, text) 162 lspace = text 163 text = '' 164 end 165 end 166 end 167 end 168 169 is_bol = rspace 170 add_text(text) 171 case ch 172 when '=' 173 rspace = nil if tailch && !tailch.empty? 174 add_expression(indicator, code) 175 add_text(rspace) if rspace 176 when nil, '-' 177 if trim && lspace && rspace 178 add_code("#{lspace}#{code}#{rspace}") 179 else 180 add_text(lspace) if lspace 181 add_code(code) 182 add_text(rspace) if rspace 183 end 184 when '#' 185 n = code.count("\n") + (rspace ? 1 : 0) 186 if trim && lspace && rspace 187 add_code("\n" * n) 188 else 189 add_text(lspace) if lspace 190 add_code("\n" * n) 191 add_text(rspace) if rspace 192 end 193 when '%' 194 add_text("#{lspace}#{literal_prefix}#{code}#{tailch}#{literal_postfix}#{rspace}") 195 else 196 handle(indicator, code, tailch, rspace, lspace) 197 end 198 end 199 rest = pos == 0 ? input : input[pos..-1] 200 add_text(rest) 201 202 src << "\n" unless src[RANGE_LAST] == "\n" 203 add_postamble(postamble) 204 src << "; ensure\n " << bufvar << " = __original_outvar\nend\n" if properties[:ensure] 205 src.freeze 206 freeze 207 end
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.
:chain_appends
-
Whether to chain <tt><<</t> calls to the buffer variable. Offers better performance, but can cause issues when the buffer variable is reassigned during template rendering (default
false
). :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 add a
frozen_string_literal: true
magic comment at the top of the resulting source code. Note this may cause problems if you are wrapping the resulting source code in other code, because the magic comment only has an effect at the beginning of the file, and having the magic comment later in the file can trigger warnings. :freeze_template_literals
-
Whether to suffix all literal strings for template code with
.freeze
(default:true
on Ruby 2.1+,false
on Ruby 2.0 and older). Can be set tofalse
on Ruby 2.3+ when frozen string literals are enabled in order to improve performance. :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.
Private Instance Methods
Source
# File lib/erubi.rb 226 def add_code(code) 227 terminate_expression 228 @src << code 229 @src << ';' unless code[RANGE_LAST] == "\n" 230 @buffer_on_stack = false 231 end
Add ruby code to the template
Source
# File lib/erubi.rb 235 def add_expression(indicator, code) 236 if ((indicator == '=') ^ @escape) 237 add_expression_result(code) 238 else 239 add_expression_result_escaped(code) 240 end 241 end
Add the given ruby expression result to the template, escaping it based on the indicator given and escape flag.
Source
# File lib/erubi.rb 244 def add_expression_result(code) 245 with_buffer{@src << ' << (' << code << ').to_s'} 246 end
Add the result of Ruby expression to the template
Source
# File lib/erubi.rb 249 def add_expression_result_escaped(code) 250 with_buffer{@src << ' << ' << @escapefunc << '((' << code << '))'} 251 end
Add the escaped result of Ruby expression to the template
Source
# File lib/erubi.rb 255 def add_postamble(postamble) 256 terminate_expression 257 @src << postamble 258 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.
Source
# File lib/erubi.rb 213 def add_text(text) 214 return if text.empty? 215 216 if text.frozen? 217 text = text.gsub(/['\\]/, '\\\\\&') 218 else 219 text.gsub!(/['\\]/, '\\\\\&') 220 end 221 222 with_buffer{@src << " << '" << text << @text_end} 223 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).
Source
# File lib/erubi.rb 261 def handle(indicator, code, tailch, rspace, lspace) 262 raise ArgumentError, "Invalid indicator: #{indicator}" 263 end
Raise an exception, as the base engine class does not support handling other indicators.
Source
# File lib/erubi.rb 289 def terminate_expression 290 @src << '; ' if @chain_appends 291 end
Make sure that any current expression has been terminated. The default is to terminate all expressions, but when the chain_appends option is used, expressions may not be terminated.
Source
# File lib/erubi.rb 271 def with_buffer 272 if @chain_appends 273 unless @buffer_on_stack 274 @src << '; ' << @bufvar 275 end 276 yield 277 @buffer_on_stack = true 278 else 279 @src << ' ' << @bufvar 280 yield 281 @src << ';' 282 end 283 end
Make sure the buffer variable is the target of the next append before yielding to the block. Mark that the buffer is the target of the next append after the block executes.
This method should only be called if the block will result in code where << will append to the bufvar.