erubi 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cefbc9c1251647b1876b855e13cde7e22fe0877b
4
+ data.tar.gz: b237d3a6ad613c5f48a1fafa65aa01675fcfb59a
5
+ SHA512:
6
+ metadata.gz: 18e593606c5c1b881bd52f20a5b9800b5dd058264cc38f609c8251e3be220d8d1a3540066dc7dfffe9143ebfdacc5af6dab7c21e22aaea9ea945dc9ecaaa0b62
7
+ data.tar.gz: 13a3fa3d9d49edc442a32f4d4ee41d1262e471dd524b6693af392019d04d4563ff632a3e55c8e01d37fca1650b42ce07335e0abc8dbda243dd17f9d3437bd339
@@ -0,0 +1,3 @@
1
+ === 1.0.0 (2016-11-10)
2
+
3
+ * Initial Public Release
@@ -0,0 +1,21 @@
1
+ copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
2
+ copyright(c) 2016 Jeremy Evans
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ = Erubi
2
+
3
+ Erubi is a ERB template engine for ruby. It is a simplified fork of Erubis, with
4
+ the following differences:
5
+
6
+ * Handles postfix conditionals when using escaping (e.g. <tt><%= foo if bar %><tt>)
7
+ * Supports frozen_string_literal: true in templates via :freeze option
8
+ * Works with ruby's --enable-frozen-string-literal option
9
+ * Escapes ' (apostrophe) when escaping for better XSS protection
10
+ * Has 90% smaller memory footprint
11
+ * Does no monkey patching (Erubis adds a method to Kernel)
12
+ * Uses an immutable design (all options passed to the constructor, which returns a frozen object)
13
+ * Has simpler internals (1 file, <100 lines of code)
14
+ * Has an open development model (Erubis doesn't have a public source control repository or bug tracker)
15
+ * Is not dead (Erubis hasn't been updated since 2011)
16
+
17
+ It is not designed with Erubis API compatibility in mind, though most Erubis
18
+ ERB syntax works, with the following exceptions:
19
+
20
+ * No support for <tt><%===</tt> for debug output
21
+ * No support for custom patterns
22
+
23
+ = Installation
24
+
25
+ gem install erubi
26
+
27
+ = Source Code
28
+
29
+ Source code is available on GitHub at https://github.com/jeremyevans/erubi
30
+
31
+ = Usage
32
+
33
+ The expected usage is via tilt, and erubi ships with tilt integration:
34
+
35
+ require 'tilt/erubi'
36
+ Tilt.new("filename.erb").render
37
+
38
+ Requiring +tilt/erubi+ sets erubi as the default erb/rhtml template processor
39
+ for tilt. In most cases, you can use Erubi as a replacement for Erubis if
40
+ you are using tilt.
41
+
42
+ You can use the library manually, but it's only useful to get the generated
43
+ source:
44
+
45
+ require 'erubi'
46
+ eval(Erubi::Engine.new(File.read('filename.erb')).src)
47
+
48
+ = Reporting Bugs
49
+
50
+ The bug tracker is located at https://github.com/jeremyevans/erubi/issues
51
+
52
+ = License
53
+
54
+ MIT
55
+
56
+ = Authors
57
+
58
+ Jeremy Evans <code@jeremyevans.net>
59
+ kuwata-lab.com
@@ -0,0 +1,78 @@
1
+ require "rake"
2
+ require "rake/clean"
3
+
4
+ NAME = 'erubi'
5
+ CLEAN.include ["#{NAME}-*.gem", "rdoc", "coverage"]
6
+
7
+ # Gem Packaging and Release
8
+
9
+ desc "Packages #{NAME}"
10
+ task :package=>[:clean] do |p|
11
+ sh %{gem build #{NAME}.gemspec}
12
+ end
13
+
14
+ ### RDoc
15
+
16
+ RDOC_DEFAULT_OPTS = ["--line-numbers", "--inline-source", '--title', 'Erubi: Small ERB Implementation']
17
+
18
+ begin
19
+ gem 'hanna-nouveau'
20
+ RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
21
+ rescue Gem::LoadError
22
+ end
23
+
24
+ rdoc_task_class = begin
25
+ require "rdoc/task"
26
+ RDoc::Task
27
+ rescue LoadError
28
+ require "rake/rdoctask"
29
+ Rake::RDocTask
30
+ end
31
+
32
+ RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
33
+ RDOC_FILES = %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb"
34
+
35
+ rdoc_task_class.new do |rdoc|
36
+ rdoc.rdoc_dir = "rdoc"
37
+ rdoc.options += RDOC_OPTS
38
+ rdoc.rdoc_files.add RDOC_FILES
39
+ end
40
+
41
+ ### Specs
42
+
43
+ spec = proc do |env|
44
+ env.each{|k,v| ENV[k] = v}
45
+ sh "#{FileUtils::RUBY} test/test.rb"
46
+ env.each{|k,v| ENV.delete(k)}
47
+ end
48
+
49
+ desc "Run specs"
50
+ task "spec" do
51
+ spec.call({})
52
+ end
53
+
54
+ task :default=>:spec
55
+
56
+ desc "Run specs with coverage"
57
+ task "spec_cov" do
58
+ spec.call('COVERAGE'=>'1')
59
+ end
60
+
61
+ desc "Run specs with -w, some warnings filtered"
62
+ task "spec_w" do
63
+ ENV['RUBYOPT'] ? (ENV['RUBYOPT'] += " -w") : (ENV['RUBYOPT'] = '-w')
64
+ rake = ENV['RAKE'] || "#{FileUtils::RUBY} -S rake"
65
+ sh %{#{rake} 2>&1 | egrep -v \": warning: instance variable @.* not initialized|: warning: method redefined; discarding old|: warning: previous definition of|: warning: statement not reached"}
66
+ end
67
+
68
+ ### Other
69
+
70
+ desc "Start an IRB shell using the extension"
71
+ task :irb do
72
+ require 'rbconfig'
73
+ ruby = ENV['RUBY'] || File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
74
+ irb = ENV['IRB'] || File.join(RbConfig::CONFIG['bindir'], File.basename(ruby).sub('ruby', 'irb'))
75
+ sh %{#{irb} -I lib -r #{NAME}}
76
+ end
77
+
78
+
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Erubi
4
+ ESCAPE_TABLE = {'&' => '&amp;'.freeze, '<' => '&lt;'.freeze, '>' => '&gt;'.freeze, '"' => '&quot;'.freeze, "'" => '&#039;'.freeze}.freeze
5
+ RANGE_FIRST = 0..0
6
+ RANGE_ALL = 0..-1
7
+ RANGE_LAST = -1..-1
8
+
9
+ if RUBY_VERSION >= '1.9'
10
+ # Escape the following characters with their HTML/XML
11
+ # equivalents.
12
+ def self.h(value)
13
+ value.to_s.gsub(/[&<>"']/, ESCAPE_TABLE)
14
+ end
15
+ else
16
+ # :nocov:
17
+ def self.h(value)
18
+ value.to_s.gsub(/[&<>"']/){|s| ESCAPE_TABLE[s]}
19
+ end
20
+ # :nocov:
21
+ end
22
+
23
+ class Engine
24
+ # The ruby source code generated from the template, which can be evaled.
25
+ attr_reader :src
26
+
27
+ # The filename of the template, if one was given.
28
+ attr_reader :filename
29
+
30
+ # The variable name used for the buffer variable.
31
+ attr_reader :bufvar
32
+
33
+ # Initialize a new Erubi::Engine. Options:
34
+ # :bufvar :: The variable name to use for the buffer variable, as a string.
35
+ # :escapefunc :: The function to use for escaping, as a string (default: ::Erubi.h).
36
+ # :escape :: Whether to make <%= escape by default, and <%== not escape by default.
37
+ # :escape_html :: Same as :escape, with lower priority.
38
+ # :filename :: The filename for the template.
39
+ # :freeze :: Whether to enable frozen string literals in the resulting source code.
40
+ # :outvar :: Same as bufvar, with lower priority.
41
+ # :postable :: the postamble for the template, by default returns the resulting source code.
42
+ # :preamble :: The preamble for the template, by default initializes up the buffer variable.
43
+ # :trim :: Whether to trim leading and trailing whitespace, true by default.
44
+ def initialize(input, properties={})
45
+ escape = properties.fetch(:escape){properties.fetch(:escape_html, false)}
46
+ trim = properties[:trim] != false
47
+ @filename = properties[:filename]
48
+ @bufvar = bufvar = properties[:bufvar] || properties[:outvar] || "_buf"
49
+ preamble = properties[:preamble] || "#{bufvar} = String.new;"
50
+ postamble = properties[:postamble] || "#{bufvar}.to_s\n"
51
+
52
+ @src = src = String.new
53
+ src << "# frozen_string_literal: true\n" if properties[:freeze]
54
+
55
+ unless escapefunc = properties[:escapefunc]
56
+ if escape
57
+ escapefunc = '__erubi.h'
58
+ src << "__erubi = ::Erubi;"
59
+ else
60
+ escapefunc = '::Erubi.h'
61
+ end
62
+ end
63
+
64
+ src << preamble
65
+
66
+ pos = 0
67
+ is_bol = true
68
+ input.scan(/<%(={1,2}|-|\#|%)?(.*?)([-=])?%>([ \t]*\r?\n)?/m) do |indicator, code, tailch, rspace|
69
+ match = Regexp.last_match
70
+ len = match.begin(0) - pos
71
+ text = input[pos, len]
72
+ pos = match.end(0)
73
+ ch = indicator ? indicator[RANGE_FIRST] : nil
74
+ lspace = nil
75
+
76
+ unless ch == '='
77
+ if text.empty?
78
+ lspace = "" if is_bol
79
+ elsif text[RANGE_LAST] == "\n"
80
+ lspace = ""
81
+ else
82
+ rindex = text.rindex("\n")
83
+ if rindex
84
+ range = rindex+1..-1
85
+ s = text[range]
86
+ if s =~ /\A[ \t]*\z/
87
+ lspace = s
88
+ text[range] = ''
89
+ end
90
+ else
91
+ if is_bol && text =~ /\A[ \t]*\z/
92
+ lspace = text.dup
93
+ text[RANGE_ALL] = ''
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ is_bol = rspace ? true : false
100
+ add_text(text) if text && !text.empty?
101
+ if ch == '='
102
+ rspace = nil if tailch && !tailch.empty?
103
+ add_text(lspace) if lspace
104
+ if ((indicator == '=') ^ escape)
105
+ src << " #{bufvar} << (" << code << ').to_s;'
106
+ else
107
+ src << " #{bufvar} << #{escapefunc}((" << code << '));'
108
+ end
109
+ add_text(rspace) if rspace
110
+ elsif ch == '#'
111
+ n = code.count("\n") + (rspace ? 1 : 0)
112
+ if trim
113
+ add_code("\n" * n)
114
+ else
115
+ add_text(lspace) if lspace
116
+ add_code("\n" * n)
117
+ add_text(rspace) if rspace
118
+ end
119
+ elsif ch == '%'
120
+ add_text("#{lspace}#{prefix||='<%'}#{code}#{tailch}#{postfix||='%>'}#{rspace}")
121
+ else
122
+ if trim
123
+ add_code("#{lspace}#{code}#{rspace}")
124
+ else
125
+ add_text(lspace) if lspace
126
+ add_code(code)
127
+ add_text(rspace) if rspace
128
+ end
129
+ end
130
+ end
131
+ rest = pos == 0 ? input : input[pos..-1]
132
+ add_text(rest)
133
+
134
+ src << "\n" unless src[RANGE_LAST] == "\n"
135
+ src << postamble
136
+ freeze
137
+ end
138
+
139
+ private
140
+
141
+ # Add raw text to the template
142
+ def add_text(text)
143
+ @src << " #{@bufvar} << '" << text.gsub(/['\\]/, '\\\\\&') << "';" unless text.empty?
144
+ end
145
+
146
+ # Add ruby code to the template
147
+ def add_code(code)
148
+ @src << code
149
+ @src << ';' unless code[RANGE_LAST] == "\n"
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,34 @@
1
+ require 'tilt'
2
+ require 'tilt/erb'
3
+ require 'erubi'
4
+
5
+ module Tilt
6
+ # Erubi (a simplified version of Erubis) template implementation
7
+ class ErubiTemplate < ERBTemplate
8
+ def prepare
9
+ @options.merge!(:preamble => false, :postamble => false)
10
+ @engine = Erubi::Engine.new(data, @options)
11
+ @outvar = @engine.bufvar
12
+ @engine
13
+ end
14
+
15
+ def precompiled_preamble(locals)
16
+ [super, "#{@outvar} = _buf = String.new"].join("\n")
17
+ end
18
+
19
+ def precompiled_postamble(locals)
20
+ [@outvar, super].join("\n")
21
+ end
22
+
23
+ # Erubi doesn't have ERB's line-off-by-one under 1.9 problem.
24
+ # Override and adjust back.
25
+ if RUBY_VERSION >= '1.9.0'
26
+ def precompiled(locals)
27
+ source, offset = super
28
+ [source, offset - 1]
29
+ end
30
+ end
31
+
32
+ Tilt.register self, 'erb', 'rhtml', 'erubi'
33
+ end
34
+ end
@@ -0,0 +1,370 @@
1
+ require 'rubygems'
2
+
3
+ unless defined?(TESTDIR)
4
+ TESTDIR = File.dirname(__FILE__)
5
+ LIBDIR = TESTDIR == '.' ? '../lib' : File.dirname(TESTDIR) + '/lib'
6
+ $: << TESTDIR
7
+ $: << LIBDIR
8
+ end
9
+
10
+ if ENV['COVERAGE']
11
+ require 'coverage'
12
+ require 'simplecov'
13
+
14
+ ENV.delete('COVERAGE')
15
+ SimpleCov.instance_eval do
16
+ start do
17
+ add_filter "/test/"
18
+ add_group('Missing'){|src| src.covered_percent < 100}
19
+ add_group('Covered'){|src| src.covered_percent == 100}
20
+ end
21
+ end
22
+ end
23
+
24
+ require 'erubi'
25
+ require 'minitest/spec'
26
+ require 'minitest/autorun'
27
+
28
+ describe Erubi::Engine do
29
+ before do
30
+ @options = {}
31
+ end
32
+
33
+ def check_output(input, src, result, &block)
34
+ t = Erubi::Engine.new(input, @options)
35
+ t.src.must_equal src
36
+ eval(t.src, block.binding).must_equal result
37
+ end
38
+
39
+ it "should handle no options" do
40
+ list = ['&\'<>"2']
41
+ check_output(<<END1, <<END2, <<END3){}
42
+ <table>
43
+ <tbody>
44
+ <% i = 0
45
+ list.each_with_index do |item, i| %>
46
+ <tr>
47
+ <td><%= i+1 %></td>
48
+ <td><%== item %></td>
49
+ </tr>
50
+ <% end %>
51
+ </tbody>
52
+ </table>
53
+ <%== i+1 %>
54
+ END1
55
+ _buf = String.new; _buf << '<table>
56
+ <tbody>
57
+ '; i = 0
58
+ list.each_with_index do |item, i|
59
+ _buf << ' <tr>
60
+ <td>'; _buf << ( i+1 ).to_s; _buf << '</td>
61
+ <td>'; _buf << ::Erubi.h(( item )); _buf << '</td>
62
+ </tr>
63
+ '; end
64
+ _buf << ' </tbody>
65
+ </table>
66
+ '; _buf << ::Erubi.h(( i+1 )); _buf << '
67
+ ';
68
+ _buf.to_s
69
+ END2
70
+ <table>
71
+ <tbody>
72
+ <tr>
73
+ <td>1</td>
74
+ <td>&amp;&#039;&lt;&gt;&quot;2</td>
75
+ </tr>
76
+ </tbody>
77
+ </table>
78
+ 1
79
+ END3
80
+ end
81
+
82
+ [:outvar, :bufvar].each do |var|
83
+ it "should handle :#{var} and :freeze options" do
84
+ @options[var] = "@_out_buf"
85
+ @options[:freeze] = true
86
+ @items = [2]
87
+ i = 0
88
+ check_output(<<END1, <<END2, <<END3){}
89
+ <table>
90
+ <% for item in @items %>
91
+ <tr>
92
+ <td><%= i+1 %></td>
93
+ <td><%== item %></td>
94
+ </tr>
95
+ <% end %>
96
+ </table>
97
+ END1
98
+ # frozen_string_literal: true
99
+ @_out_buf = String.new; @_out_buf << '<table>
100
+ '; for item in @items
101
+ @_out_buf << ' <tr>
102
+ <td>'; @_out_buf << ( i+1 ).to_s; @_out_buf << '</td>
103
+ <td>'; @_out_buf << ::Erubi.h(( item )); @_out_buf << '</td>
104
+ </tr>
105
+ '; end
106
+ @_out_buf << '</table>
107
+ ';
108
+ @_out_buf.to_s
109
+ END2
110
+ <table>
111
+ <tr>
112
+ <td>1</td>
113
+ <td>2</td>
114
+ </tr>
115
+ </table>
116
+ END3
117
+ end
118
+ end
119
+
120
+ it "should handle <%% and <%# syntax" do
121
+ @items = [2]
122
+ i = 0
123
+ check_output(<<END1, <<END2, <<END3){}
124
+ <table>
125
+ <%% for item in @items %>
126
+ <tr>
127
+ <td><%# i+1 %></td>
128
+ <td><%# item %></td>
129
+ </tr>
130
+ <%% end %>
131
+ </table>
132
+ END1
133
+ _buf = String.new; _buf << '<table>
134
+ '; _buf << '<% for item in @items %>
135
+ '; _buf << ' <tr>
136
+ <td>';; _buf << '</td>
137
+ <td>';; _buf << '</td>
138
+ </tr>
139
+ '; _buf << ' <% end %>
140
+ '; _buf << '</table>
141
+ ';
142
+ _buf.to_s
143
+ END2
144
+ <table>
145
+ <% for item in @items %>
146
+ <tr>
147
+ <td></td>
148
+ <td></td>
149
+ </tr>
150
+ <% end %>
151
+ </table>
152
+ END3
153
+ end
154
+
155
+ it "should handle :trim => false option" do
156
+ @options[:trim] = false
157
+ @items = [2]
158
+ i = 0
159
+ check_output(<<END1, <<END2, <<END3){}
160
+ <table>
161
+ <% for item in @items %>
162
+ <tr>
163
+ <td><%#
164
+ i+1
165
+ %></td>
166
+ <td><%== item %></td>
167
+ </tr>
168
+ <% end %><%#%>
169
+ <% i %>a
170
+ <% i %>
171
+ </table>
172
+ END1
173
+ _buf = String.new; _buf << '<table>
174
+ '; _buf << ' '; for item in @items ; _buf << '
175
+ '; _buf << ' <tr>
176
+ <td>';
177
+
178
+ _buf << '</td>
179
+ <td>'; _buf << ::Erubi.h(( item )); _buf << '</td>
180
+ </tr>
181
+ '; _buf << ' '; end ;
182
+ _buf << '
183
+ '; _buf << ' '; i ; _buf << 'a
184
+ '; _buf << ' '; i ; _buf << '
185
+ '; _buf << '</table>
186
+ ';
187
+ _buf.to_s
188
+ END2
189
+ <table>
190
+
191
+ <tr>
192
+ <td></td>
193
+ <td>2</td>
194
+ </tr>
195
+
196
+ a
197
+
198
+ </table>
199
+ END3
200
+ end
201
+
202
+ [:escape, :escape_html].each do |opt|
203
+ it "should handle :#{opt} and :escapefunc options" do
204
+ @options[opt] = true
205
+ @options[:escapefunc] = 'h.call'
206
+ h = proc{|s| s.to_s*2}
207
+ list = ['2']
208
+ check_output(<<END1, <<END2, <<END3){}
209
+ <table>
210
+ <tbody>
211
+ <% i = 0
212
+ list.each_with_index do |item, i| %>
213
+ <tr>
214
+ <td><%= i+1 %></td>
215
+ <td><%== item %></td>
216
+ </tr>
217
+ <% end %>
218
+ </tbody>
219
+ </table>
220
+ <%== i+1 %>
221
+ END1
222
+ _buf = String.new; _buf << '<table>
223
+ <tbody>
224
+ '; i = 0
225
+ list.each_with_index do |item, i|
226
+ _buf << ' <tr>
227
+ <td>'; _buf << h.call(( i+1 )); _buf << '</td>
228
+ <td>'; _buf << ( item ).to_s; _buf << '</td>
229
+ </tr>
230
+ '; end
231
+ _buf << ' </tbody>
232
+ </table>
233
+ '; _buf << ( i+1 ).to_s; _buf << '
234
+ ';
235
+ _buf.to_s
236
+ END2
237
+ <table>
238
+ <tbody>
239
+ <tr>
240
+ <td>11</td>
241
+ <td>2</td>
242
+ </tr>
243
+ </tbody>
244
+ </table>
245
+ 1
246
+ END3
247
+ end
248
+ end
249
+
250
+ it "should handle :escape option without :escapefunc option" do
251
+ @options[:escape] = true
252
+ list = ['&\'<>"2']
253
+ check_output(<<END1, <<END2, <<END3){}
254
+ <table>
255
+ <tbody>
256
+ <% i = 0
257
+ list.each_with_index do |item, i| %>
258
+ <tr>
259
+ <td><%== i+1 %></td>
260
+ <td><%= item %></td>
261
+ </tr>
262
+ <% end %>
263
+ </tbody>
264
+ </table>
265
+ END1
266
+ __erubi = ::Erubi;_buf = String.new; _buf << '<table>
267
+ <tbody>
268
+ '; i = 0
269
+ list.each_with_index do |item, i|
270
+ _buf << ' <tr>
271
+ <td>'; _buf << ( i+1 ).to_s; _buf << '</td>
272
+ <td>'; _buf << __erubi.h(( item )); _buf << '</td>
273
+ </tr>
274
+ '; end
275
+ _buf << ' </tbody>
276
+ </table>
277
+ ';
278
+ _buf.to_s
279
+ END2
280
+ <table>
281
+ <tbody>
282
+ <tr>
283
+ <td>1</td>
284
+ <td>&amp;&#039;&lt;&gt;&quot;2</td>
285
+ </tr>
286
+ </tbody>
287
+ </table>
288
+ END3
289
+ end
290
+
291
+ it "should handle :preamble and :postamble options" do
292
+ @options[:preamble] = '_buf = String.new("1");'
293
+ @options[:postamble] = "_buf[0...18]\n"
294
+ list = ['2']
295
+ check_output(<<END1, <<END2, <<END3){}
296
+ <table>
297
+ <tbody>
298
+ <% i = 0
299
+ list.each_with_index do |item, i| %>
300
+ <tr>
301
+ <td><%= i+1 %></td>
302
+ <td><%== item %></td>
303
+ </tr>
304
+ <% end %>
305
+ </tbody>
306
+ </table>
307
+ <%== i+1 %>
308
+ END1
309
+ _buf = String.new("1"); _buf << '<table>
310
+ <tbody>
311
+ '; i = 0
312
+ list.each_with_index do |item, i|
313
+ _buf << ' <tr>
314
+ <td>'; _buf << ( i+1 ).to_s; _buf << '</td>
315
+ <td>'; _buf << ::Erubi.h(( item )); _buf << '</td>
316
+ </tr>
317
+ '; end
318
+ _buf << ' </tbody>
319
+ </table>
320
+ '; _buf << ::Erubi.h(( i+1 )); _buf << '
321
+ ';
322
+ _buf[0...18]
323
+ END2
324
+ 1<table>
325
+ <tbody>
326
+ END3
327
+ end
328
+
329
+ it "should have working filename accessor" do
330
+ Erubi::Engine.new('', :filename=>'foo.rb').filename.must_equal 'foo.rb'
331
+ end
332
+
333
+ it "should have working bufvar accessor" do
334
+ Erubi::Engine.new('', :bufvar=>'foo').bufvar.must_equal 'foo'
335
+ Erubi::Engine.new('', :outvar=>'foo').bufvar.must_equal 'foo'
336
+ end
337
+
338
+ it "should return frozen object" do
339
+ Erubi::Engine.new('').frozen?.must_equal true
340
+ end
341
+
342
+ it "should have working tilt support" do
343
+ require 'tilt/erubi'
344
+ @list = ['&\'<>"2']
345
+ Tilt::ErubiTemplate.new{<<END1}.render(self).must_equal(<<END2)
346
+ <table>
347
+ <tbody>
348
+ <% i = 0
349
+ @list.each_with_index do |item, i| %>
350
+ <tr>
351
+ <td><%= i+1 %></td>
352
+ <td><%== item %></td>
353
+ </tr>
354
+ <% end %>
355
+ </tbody>
356
+ </table>
357
+ <%== i+1 %>
358
+ END1
359
+ <table>
360
+ <tbody>
361
+ <tr>
362
+ <td>1</td>
363
+ <td>&amp;&#039;&lt;&gt;&quot;2</td>
364
+ </tr>
365
+ </tbody>
366
+ </table>
367
+ 1
368
+ END2
369
+ end
370
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: erubi
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Evans
8
+ - kuwata-lab.com
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-11-10 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Erubi is a ERB template engine for ruby. It is a simplified fork of Erubis
15
+ email: code@jeremyevans.net
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - README.rdoc
20
+ - CHANGELOG
21
+ - MIT-LICENSE
22
+ files:
23
+ - CHANGELOG
24
+ - MIT-LICENSE
25
+ - README.rdoc
26
+ - Rakefile
27
+ - lib/erubi.rb
28
+ - lib/tilt/erubi.rb
29
+ - test/test.rb
30
+ homepage: https://github.com/jeremyevans/erubi
31
+ licenses:
32
+ - MIT
33
+ metadata: {}
34
+ post_install_message:
35
+ rdoc_options:
36
+ - "--quiet"
37
+ - "--line-numbers"
38
+ - "--inline-source"
39
+ - "--title"
40
+ - 'Erubi: Small ERB Implementation'
41
+ - "--main"
42
+ - README.rdoc
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.6.6
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Small ERB Implementation
61
+ test_files: []