erubi 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f504eb8d1ae0f89e098de29336a69d0251cd8659a1b6fe1ab86c7f23ed44d67
4
- data.tar.gz: e54396a6eb2cf0c193089c9b2c3d5fa0f92daf5cf4f462fe09d0aea6dca49419
3
+ metadata.gz: 0424c43d37611204a83153f9cffb1e259027a0f1a1edd16b3b5cfef09ec7b137
4
+ data.tar.gz: 796b2b90f46c80297fdf05b3070f9bad10fc9199946878c0bfbfe7435ce5466c
5
5
  SHA512:
6
- metadata.gz: 0a789b8a528548760ac4898867588477e03c3f1410bd930538c849e167c68a346202f8c168a2a71107485c961bb41a91d549f687a4d24ebf3614821bc15b4e73
7
- data.tar.gz: 14e74f5fb8c452c0cbc15afbe51b8a86be572d8d585416f09f07d9227e06ad8d8c14d8681424dc53f9b7eaba1a1297ed72e8e7dc0c36afe6e2da1926bec742d0
6
+ metadata.gz: 8833bc8ec00db215ef73c71271c97e668861f920c339de7df658f1cf464761b62b2811845a062b681bb30966b7797beec708674929aa9400159e1bfdce3c31dd
7
+ data.tar.gz: 74fa7a9107f056dbcb3bb2efedb858a7f120d8c36d378da1eb425783c75e2a398ffd4b301c1e300cc684b98155d9b67abb07d1589f1be9786282756a0140449b
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ === 1.11.0 (2022-08-02)
2
+
3
+ * Support :freeze_template_literals option for configuring whether to add .freeze to template literal strings (casperisfine) (#33)
4
+
5
+ * Support :chain_appends option for chaining appends to the buffer variable (casperisfine, jeremyevans) (#32)
6
+
7
+ * Avoid unnecessary defined? usage on Ruby 3+ when using the :ensure option (jeremyevans)
8
+
1
9
  === 1.10.0 (2020-11-13)
2
10
 
3
11
  * Improve template parsing, mostly by reducing allocations (jeremyevans)
data/MIT-LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
2
- copyright(c) 2016-2020 Jeremy Evans
2
+ copyright(c) 2016-2021 Jeremy Evans
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -42,7 +42,7 @@ end
42
42
 
43
43
  spec = proc do |env|
44
44
  env.each{|k,v| ENV[k] = v}
45
- sh "#{FileUtils::RUBY} test/test.rb"
45
+ sh "#{FileUtils::RUBY} #{'-w' if RUBY_VERSION >= '3'} test/test.rb"
46
46
  env.each{|k,v| ENV.delete(k)}
47
47
  end
48
48
 
@@ -57,11 +57,6 @@ desc "Run specs with coverage"
57
57
  task "spec_cov" do
58
58
  spec.call('COVERAGE'=>'1')
59
59
  end
60
-
61
- desc "Run specs with -w, some warnings filtered"
62
- task "spec_w" do
63
- sh "#{FileUtils::RUBY} test/test_w.rb"
64
- end
65
60
 
66
61
  ### Other
67
62
 
@@ -36,13 +36,19 @@ module Erubi
36
36
  rspace = nil if tailch && !tailch.empty?
37
37
  add_text(lspace) if lspace
38
38
  escape_capture = !((indicator == '|=') ^ @escape_capture)
39
- src << "begin; (#{@bufstack} ||= []) << #{@bufvar}; #{@bufvar} = #{@bufval}; #{@bufstack}.last << #{@escapefunc if escape_capture}((" << code
39
+ terminate_expression
40
+ @src << "begin; (#{@bufstack} ||= []) << #{@bufvar}; #{@bufvar} = #{@bufval}; #{@bufstack}.last << #{@escapefunc if escape_capture}((" << code
41
+ @buffer_on_stack = false
40
42
  add_text(rspace) if rspace
41
43
  when '|'
42
44
  rspace = nil if tailch && !tailch.empty?
43
45
  add_text(lspace) if lspace
44
- result = @yield_returns_buffer ? " #{@bufvar}; " : ""
45
- src << result << code << ")).to_s; ensure; #{@bufvar} = #{@bufstack}.pop; end;"
46
+ if @yield_returns_buffer
47
+ terminate_expression
48
+ @src << " #{@bufvar}; "
49
+ end
50
+ @src << code << ")).to_s; ensure; #{@bufvar} = #{@bufstack}.pop; end;"
51
+ @buffer_on_stack = false
46
52
  add_text(rspace) if rspace
47
53
  else
48
54
  super
data/lib/erubi.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Erubi
4
- VERSION = '1.10.0'
5
- RANGE_ALL = 0..-1
4
+ VERSION = '1.11.0'
6
5
 
7
6
  # :nocov:
8
7
  if RUBY_VERSION >= '1.9'
@@ -13,8 +12,8 @@ module Erubi
13
12
  RANGE_LAST = -1..-1
14
13
  end
15
14
 
16
- TEXT_END = RUBY_VERSION >= '2.1' ? "'.freeze;" : "';"
17
15
  MATCH_METHOD = RUBY_VERSION >= '2.4' ? :match? : :match
16
+ SKIP_DEFINED_FOR_INSTANCE_VARIABLE = RUBY_VERSION > '3'
18
17
  # :nocov:
19
18
 
20
19
  begin
@@ -45,6 +44,9 @@ module Erubi
45
44
  end
46
45
 
47
46
  class Engine
47
+ # The default regular expression used for scanning.
48
+ DEFAULT_REGEXP = /<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/m
49
+
48
50
  # The frozen ruby source code generated from the template, which can be evaled.
49
51
  attr_reader :src
50
52
 
@@ -57,12 +59,22 @@ module Erubi
57
59
  # Initialize a new Erubi::Engine. Options:
58
60
  # +:bufval+ :: The value to use for the buffer variable, as a string (default <tt>'::String.new'</tt>).
59
61
  # +:bufvar+ :: The variable name to use for the buffer variable, as a string.
62
+ # +:chain_appends+ :: Whether to chain <tt><<</t> calls to the buffer variable. Offers better
63
+ # performance, but can cause issues when the buffer variable is reassigned during
64
+ # template rendering (default +false+).
60
65
  # +:ensure+ :: Wrap the template in a begin/ensure block restoring the previous value of bufvar.
61
66
  # +:escapefunc+ :: The function to use for escaping, as a string (default: <tt>'::Erubi.h'</tt>).
62
67
  # +:escape+ :: Whether to make <tt><%=</tt> escape by default, and <tt><%==</tt> not escape by default.
63
68
  # +:escape_html+ :: Same as +:escape+, with lower priority.
64
69
  # +:filename+ :: The filename for the template.
65
- # +:freeze+ :: Whether to enable frozen string literals in the resulting source code.
70
+ # +:freeze+ :: Whether to enable add a <tt>frozen_string_literal: true</tt> magic comment at the top of
71
+ # the resulting source code. Note this may cause problems if you are wrapping the resulting
72
+ # source code in other code, because the magic comment only has an effect at the beginning of
73
+ # the file, and having the magic comment later in the file can trigger warnings.
74
+ # +:freeze_template_literals+ :: Whether to suffix all literal strings for template code with <tt>.freeze</tt>
75
+ # (default: +true+ on Ruby 2.1+, +false+ on Ruby 2.0 and older).
76
+ # Can be set to +false+ on Ruby 2.3+ when frozen string literals are enabled
77
+ # in order to improve performance.
66
78
  # +:literal_prefix+ :: The prefix to output when using escaped tag delimiters (default <tt>'<%'</tt>).
67
79
  # +:literal_postfix+ :: The postfix to output when using escaped tag delimiters (default <tt>'%>'</tt>).
68
80
  # +:outvar+ :: Same as +:bufvar+, with lower priority.
@@ -77,20 +89,34 @@ module Erubi
77
89
  @filename = properties[:filename]
78
90
  @bufvar = bufvar = properties[:bufvar] || properties[:outvar] || "_buf"
79
91
  bufval = properties[:bufval] || '::String.new'
80
- regexp = properties[:regexp] || /<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/m
92
+ regexp = properties[:regexp] || DEFAULT_REGEXP
81
93
  literal_prefix = properties[:literal_prefix] || '<%'
82
94
  literal_postfix = properties[:literal_postfix] || '%>'
83
95
  preamble = properties[:preamble] || "#{bufvar} = #{bufval};"
84
96
  postamble = properties[:postamble] || "#{bufvar}.to_s\n"
97
+ @chain_appends = properties[:chain_appends]
98
+ @text_end = if properties.fetch(:freeze_template_literals, RUBY_VERSION >= '2.1')
99
+ "'.freeze"
100
+ else
101
+ "'"
102
+ end
85
103
 
104
+ @buffer_on_stack = false
86
105
  @src = src = properties[:src] || String.new
87
106
  src << "# frozen_string_literal: true\n" if properties[:freeze]
88
- src << "begin; __original_outvar = #{bufvar} if defined?(#{bufvar}); " if properties[:ensure]
107
+ if properties[:ensure]
108
+ src << "begin; __original_outvar = #{bufvar}"
109
+ if SKIP_DEFINED_FOR_INSTANCE_VARIABLE && /\A@[^@]/ =~ bufvar
110
+ src << "; "
111
+ else
112
+ src << " if defined?(#{bufvar}); "
113
+ end
114
+ end
89
115
 
90
116
  unless @escapefunc = properties[:escapefunc]
91
117
  if escape
92
118
  @escapefunc = '__erubi.h'
93
- src << "__erubi = ::Erubi;"
119
+ src << "__erubi = ::Erubi; "
94
120
  else
95
121
  @escapefunc = '::Erubi.h'
96
122
  end
@@ -184,13 +210,16 @@ module Erubi
184
210
  else
185
211
  text.gsub!(/['\\]/, '\\\\\&')
186
212
  end
187
- @src << " " << @bufvar << " << '" << text << TEXT_END
213
+
214
+ with_buffer{@src << " << '" << text << @text_end}
188
215
  end
189
216
 
190
217
  # Add ruby code to the template
191
218
  def add_code(code)
219
+ terminate_expression
192
220
  @src << code
193
221
  @src << ';' unless code[RANGE_LAST] == "\n"
222
+ @buffer_on_stack = false
194
223
  end
195
224
 
196
225
  # Add the given ruby expression result to the template,
@@ -205,23 +234,52 @@ module Erubi
205
234
 
206
235
  # Add the result of Ruby expression to the template
207
236
  def add_expression_result(code)
208
- @src << ' ' << @bufvar << ' << (' << code << ').to_s;'
237
+ with_buffer{@src << ' << (' << code << ').to_s'}
209
238
  end
210
239
 
211
240
  # Add the escaped result of Ruby expression to the template
212
241
  def add_expression_result_escaped(code)
213
- @src << ' ' << @bufvar << ' << ' << @escapefunc << '((' << code << '));'
242
+ with_buffer{@src << ' << ' << @escapefunc << '((' << code << '))'}
214
243
  end
215
244
 
216
245
  # Add the given postamble to the src. Can be overridden in subclasses
217
246
  # to make additional changes to src that depend on the current state.
218
247
  def add_postamble(postamble)
219
- src << postamble
248
+ terminate_expression
249
+ @src << postamble
220
250
  end
221
251
 
222
252
  # Raise an exception, as the base engine class does not support handling other indicators.
223
253
  def handle(indicator, code, tailch, rspace, lspace)
224
254
  raise ArgumentError, "Invalid indicator: #{indicator}"
225
255
  end
256
+
257
+ # Make sure the buffer variable is the target of the next append
258
+ # before yielding to the block. Mark that the buffer is the target
259
+ # of the next append after the block executes.
260
+ #
261
+ # This method should only be called if the block will result in
262
+ # code where << will append to the bufvar.
263
+ def with_buffer
264
+ if @chain_appends
265
+ unless @buffer_on_stack
266
+ @src << '; ' << @bufvar
267
+ end
268
+ yield
269
+ @buffer_on_stack = true
270
+ else
271
+ @src << ' ' << @bufvar
272
+ yield
273
+ @src << ';'
274
+ end
275
+ end
276
+
277
+ # Make sure that any current expression has been terminated.
278
+ # The default is to terminate all expressions, but when
279
+ # the chain_appends option is used, expressions may not be
280
+ # terminated.
281
+ def terminate_expression
282
+ @src << '; ' if @chain_appends
283
+ end
226
284
  end
227
285
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erubi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-11-13 00:00:00.000000000 Z
12
+ date: 2022-08-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  - !ruby/object:Gem::Version
84
84
  version: '0'
85
85
  requirements: []
86
- rubygems_version: 3.1.4
86
+ rubygems_version: 3.3.7
87
87
  signing_key:
88
88
  specification_version: 4
89
89
  summary: Small ERB Implementation