ed-precompiled_erb 5.0.3-x86_64-linux

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.
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/erb.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ begin
2
+ require_relative 'lib/erb/version'
3
+ rescue LoadError
4
+ # for Ruby core repository
5
+ require_relative 'version'
6
+ end
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'ed-precompiled_erb'
10
+ spec.version = ERB.const_get(:VERSION, false)
11
+ spec.authors = ['Masatoshi SEKI', 'Takashi Kokubun']
12
+ spec.email = ['seki@ruby-lang.org', 'k0kubun@ruby-lang.org']
13
+
14
+ spec.summary = %q{An easy to use but powerful templating system for Ruby.}
15
+ spec.description = %q{An easy to use but powerful templating system for Ruby.}
16
+ spec.homepage = 'https://github.com/ruby/erb'
17
+ spec.licenses = ['Ruby', 'BSD-2-Clause']
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = spec.homepage
21
+
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = 'libexec'
26
+ spec.executables = ['erb']
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.required_ruby_version = '>= 3.2.0'
30
+
31
+ if RUBY_ENGINE == 'jruby'
32
+ spec.platform = 'java'
33
+ else
34
+ spec.extensions = ['ext/erb/escape/extconf.rb']
35
+ end
36
+ end
@@ -0,0 +1,102 @@
1
+ #include "ruby.h"
2
+ #include "ruby/encoding.h"
3
+
4
+ static VALUE rb_cERB, rb_mEscape, rb_cCGI;
5
+ static ID id_escapeHTML;
6
+
7
+ #define HTML_ESCAPE_MAX_LEN 6
8
+
9
+ static const struct {
10
+ uint8_t len;
11
+ char str[HTML_ESCAPE_MAX_LEN+1];
12
+ } html_escape_table[UCHAR_MAX+1] = {
13
+ #define HTML_ESCAPE(c, str) [c] = {rb_strlen_lit(str), str}
14
+ HTML_ESCAPE('\'', "'"),
15
+ HTML_ESCAPE('&', "&"),
16
+ HTML_ESCAPE('"', """),
17
+ HTML_ESCAPE('<', "&lt;"),
18
+ HTML_ESCAPE('>', "&gt;"),
19
+ #undef HTML_ESCAPE
20
+ };
21
+
22
+ static inline void
23
+ preserve_original_state(VALUE orig, VALUE dest)
24
+ {
25
+ rb_enc_associate(dest, rb_enc_get(orig));
26
+ }
27
+
28
+ static inline long
29
+ escaped_length(VALUE str)
30
+ {
31
+ const long len = RSTRING_LEN(str);
32
+ if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
33
+ ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
34
+ }
35
+ return len * HTML_ESCAPE_MAX_LEN;
36
+ }
37
+
38
+ static VALUE
39
+ optimized_escape_html(VALUE str)
40
+ {
41
+ VALUE vbuf;
42
+ char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
43
+ const char *cstr = RSTRING_PTR(str);
44
+ const char *end = cstr + RSTRING_LEN(str);
45
+
46
+ char *dest = buf;
47
+ while (cstr < end) {
48
+ const unsigned char c = *cstr++;
49
+ uint8_t len = html_escape_table[c].len;
50
+ if (len) {
51
+ memcpy(dest, html_escape_table[c].str, len);
52
+ dest += len;
53
+ }
54
+ else {
55
+ *dest++ = c;
56
+ }
57
+ }
58
+
59
+ VALUE escaped = str;
60
+ if (RSTRING_LEN(str) < (dest - buf)) {
61
+ escaped = rb_str_new(buf, dest - buf);
62
+ preserve_original_state(str, escaped);
63
+ }
64
+ ALLOCV_END(vbuf);
65
+ return escaped;
66
+ }
67
+
68
+ /*
69
+ * ERB::Util.html_escape is similar to CGI.escapeHTML but different in the following two parts:
70
+ *
71
+ * * ERB::Util.html_escape converts an argument with #to_s first (only if it's not T_STRING)
72
+ * * ERB::Util.html_escape does not allocate a new string when nothing needs to be escaped
73
+ */
74
+ static VALUE
75
+ erb_escape_html(VALUE self, VALUE str)
76
+ {
77
+ if (!RB_TYPE_P(str, T_STRING)) {
78
+ str = rb_convert_type(str, T_STRING, "String", "to_s");
79
+ }
80
+
81
+ if (rb_enc_str_asciicompat_p(str)) {
82
+ return optimized_escape_html(str);
83
+ }
84
+ else {
85
+ return rb_funcall(rb_cCGI, id_escapeHTML, 1, str);
86
+ }
87
+ }
88
+
89
+ void
90
+ Init_escape(void)
91
+ {
92
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
93
+ rb_ext_ractor_safe(true);
94
+ #endif
95
+
96
+ rb_cERB = rb_define_class("ERB", rb_cObject);
97
+ rb_mEscape = rb_define_module_under(rb_cERB, "Escape");
98
+ rb_define_module_function(rb_mEscape, "html_escape", erb_escape_html, 1);
99
+
100
+ rb_cCGI = rb_define_class("CGI", rb_cObject);
101
+ id_escapeHTML = rb_intern("escapeHTML");
102
+ }
@@ -0,0 +1,9 @@
1
+ require 'mkmf'
2
+
3
+ case RUBY_ENGINE
4
+ when 'jruby', 'truffleruby'
5
+ File.write('Makefile', dummy_makefile($srcdir).join)
6
+ else
7
+ have_func("rb_ext_ractor_safe", "ruby.h")
8
+ create_makefile 'erb/escape'
9
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,488 @@
1
+ # frozen_string_literal: true
2
+ #--
3
+ # ERB::Compiler
4
+ #
5
+ # Compiles ERB templates into Ruby code; the compiled code produces the
6
+ # template result when evaluated. ERB::Compiler provides hooks to define how
7
+ # generated output is handled.
8
+ #
9
+ # Internally ERB does something like this to generate the code returned by
10
+ # ERB#src:
11
+ #
12
+ # compiler = ERB::Compiler.new('<>')
13
+ # compiler.pre_cmd = ["_erbout=+''"]
14
+ # compiler.put_cmd = "_erbout.<<"
15
+ # compiler.insert_cmd = "_erbout.<<"
16
+ # compiler.post_cmd = ["_erbout"]
17
+ #
18
+ # code, enc = compiler.compile("Got <%= obj %>!\n")
19
+ # puts code
20
+ #
21
+ # <i>Generates</i>:
22
+ #
23
+ # #coding:UTF-8
24
+ # _erbout=+''; _erbout.<< "Got ".freeze; _erbout.<<(( obj ).to_s); _erbout.<< "!\n".freeze; _erbout
25
+ #
26
+ # By default the output is sent to the print method. For example:
27
+ #
28
+ # compiler = ERB::Compiler.new('<>')
29
+ # code, enc = compiler.compile("Got <%= obj %>!\n")
30
+ # puts code
31
+ #
32
+ # <i>Generates</i>:
33
+ #
34
+ # #coding:UTF-8
35
+ # print "Got ".freeze; print(( obj ).to_s); print "!\n".freeze
36
+ #
37
+ # == Evaluation
38
+ #
39
+ # The compiled code can be used in any context where the names in the code
40
+ # correctly resolve. Using the last example, each of these print 'Got It!'
41
+ #
42
+ # Evaluate using a variable:
43
+ #
44
+ # obj = 'It'
45
+ # eval code
46
+ #
47
+ # Evaluate using an input:
48
+ #
49
+ # mod = Module.new
50
+ # mod.module_eval %{
51
+ # def get(obj)
52
+ # #{code}
53
+ # end
54
+ # }
55
+ # extend mod
56
+ # get('It')
57
+ #
58
+ # Evaluate using an accessor:
59
+ #
60
+ # klass = Class.new Object
61
+ # klass.class_eval %{
62
+ # attr_accessor :obj
63
+ # def initialize(obj)
64
+ # @obj = obj
65
+ # end
66
+ # def get_it
67
+ # #{code}
68
+ # end
69
+ # }
70
+ # klass.new('It').get_it
71
+ #
72
+ # Good! See also ERB#def_method, ERB#def_module, and ERB#def_class.
73
+ class ERB::Compiler # :nodoc:
74
+ class PercentLine # :nodoc:
75
+ def initialize(str)
76
+ @value = str
77
+ end
78
+ attr_reader :value
79
+ alias :to_s :value
80
+ end
81
+
82
+ class Scanner # :nodoc:
83
+ @scanner_map = defined?(Ractor) ? Ractor.make_shareable({}) : {}
84
+ class << self
85
+ if defined?(Ractor)
86
+ def register_scanner(klass, trim_mode, percent)
87
+ @scanner_map = Ractor.make_shareable({ **@scanner_map, [trim_mode, percent] => klass })
88
+ end
89
+ else
90
+ def register_scanner(klass, trim_mode, percent)
91
+ @scanner_map[[trim_mode, percent]] = klass
92
+ end
93
+ end
94
+ alias :regist_scanner :register_scanner
95
+ end
96
+
97
+ def self.default_scanner=(klass)
98
+ @default_scanner = klass
99
+ end
100
+
101
+ def self.make_scanner(src, trim_mode, percent)
102
+ klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
103
+ klass.new(src, trim_mode, percent)
104
+ end
105
+
106
+ DEFAULT_STAGS = %w(<%% <%= <%# <%).freeze
107
+ DEFAULT_ETAGS = %w(%%> %>).freeze
108
+ def initialize(src, trim_mode, percent)
109
+ @src = src
110
+ @stag = nil
111
+ @stags = DEFAULT_STAGS
112
+ @etags = DEFAULT_ETAGS
113
+ end
114
+ attr_accessor :stag
115
+ attr_reader :stags, :etags
116
+
117
+ def scan; end
118
+ end
119
+
120
+ class TrimScanner < Scanner # :nodoc:
121
+ def initialize(src, trim_mode, percent)
122
+ super
123
+ @trim_mode = trim_mode
124
+ @percent = percent
125
+ if @trim_mode == '>'
126
+ @scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
127
+ @scan_line = self.method(:trim_line1)
128
+ elsif @trim_mode == '<>'
129
+ @scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
130
+ @scan_line = self.method(:trim_line2)
131
+ elsif @trim_mode == '-'
132
+ @scan_reg = /(.*?)(^[ \t]*<%\-|<%\-|-%>\r?\n|-%>|#{(stags + etags).join('|')}|\z)/m
133
+ @scan_line = self.method(:explicit_trim_line)
134
+ else
135
+ @scan_reg = /(.*?)(#{(stags + etags).join('|')}|\n|\z)/m
136
+ @scan_line = self.method(:scan_line)
137
+ end
138
+ end
139
+
140
+ def scan(&block)
141
+ @stag = nil
142
+ if @percent
143
+ @src.each_line do |line|
144
+ percent_line(line, &block)
145
+ end
146
+ else
147
+ @scan_line.call(@src, &block)
148
+ end
149
+ nil
150
+ end
151
+
152
+ def percent_line(line, &block)
153
+ if @stag || line[0] != ?%
154
+ return @scan_line.call(line, &block)
155
+ end
156
+
157
+ line[0] = ''
158
+ if line[0] == ?%
159
+ @scan_line.call(line, &block)
160
+ else
161
+ yield(PercentLine.new(line.chomp))
162
+ end
163
+ end
164
+
165
+ def scan_line(line)
166
+ line.scan(@scan_reg) do |tokens|
167
+ tokens.each do |token|
168
+ next if token.empty?
169
+ yield(token)
170
+ end
171
+ end
172
+ end
173
+
174
+ def trim_line1(line)
175
+ line.scan(@scan_reg) do |tokens|
176
+ tokens.each do |token|
177
+ next if token.empty?
178
+ if token == "%>\n" || token == "%>\r\n"
179
+ yield('%>')
180
+ yield(:cr)
181
+ else
182
+ yield(token)
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ def trim_line2(line)
189
+ head = nil
190
+ line.scan(@scan_reg) do |tokens|
191
+ tokens.each do |token|
192
+ next if token.empty?
193
+ head = token unless head
194
+ if token == "%>\n" || token == "%>\r\n"
195
+ yield('%>')
196
+ if is_erb_stag?(head)
197
+ yield(:cr)
198
+ else
199
+ yield("\n")
200
+ end
201
+ head = nil
202
+ else
203
+ yield(token)
204
+ head = nil if token == "\n"
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ def explicit_trim_line(line)
211
+ line.scan(@scan_reg) do |tokens|
212
+ tokens.each do |token|
213
+ next if token.empty?
214
+ if @stag.nil? && /[ \t]*<%-/ =~ token
215
+ yield('<%')
216
+ elsif @stag && (token == "-%>\n" || token == "-%>\r\n")
217
+ yield('%>')
218
+ yield(:cr)
219
+ elsif @stag && token == '-%>'
220
+ yield('%>')
221
+ else
222
+ yield(token)
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ ERB_STAG = %w(<%= <%# <%)
229
+ def is_erb_stag?(s)
230
+ ERB_STAG.member?(s)
231
+ end
232
+ end
233
+
234
+ Scanner.default_scanner = TrimScanner
235
+
236
+ begin
237
+ require 'strscan'
238
+ rescue LoadError
239
+ else
240
+ class SimpleScanner < Scanner # :nodoc:
241
+ def scan
242
+ stag_reg = (stags == DEFAULT_STAGS) ? /(.*?)(<%[%=#]?|\z)/m : /(.*?)(#{stags.join('|')}|\z)/m
243
+ etag_reg = (etags == DEFAULT_ETAGS) ? /(.*?)(%%?>|\z)/m : /(.*?)(#{etags.join('|')}|\z)/m
244
+ scanner = StringScanner.new(@src)
245
+ while ! scanner.eos?
246
+ scanner.scan(@stag ? etag_reg : stag_reg)
247
+ yield(scanner[1])
248
+ yield(scanner[2])
249
+ end
250
+ end
251
+ end
252
+ Scanner.register_scanner(SimpleScanner, nil, false)
253
+
254
+ class ExplicitScanner < Scanner # :nodoc:
255
+ def scan
256
+ stag_reg = /(.*?)(^[ \t]*<%-|<%-|#{stags.join('|')}|\z)/m
257
+ etag_reg = /(.*?)(-%>|#{etags.join('|')}|\z)/m
258
+ scanner = StringScanner.new(@src)
259
+ while ! scanner.eos?
260
+ scanner.scan(@stag ? etag_reg : stag_reg)
261
+ yield(scanner[1])
262
+
263
+ elem = scanner[2]
264
+ if /[ \t]*<%-/ =~ elem
265
+ yield('<%')
266
+ elsif elem == '-%>'
267
+ yield('%>')
268
+ yield(:cr) if scanner.scan(/(\r?\n|\z)/)
269
+ else
270
+ yield(elem)
271
+ end
272
+ end
273
+ end
274
+ end
275
+ Scanner.register_scanner(ExplicitScanner, '-', false)
276
+ end
277
+
278
+ class Buffer # :nodoc:
279
+ def initialize(compiler, enc=nil, frozen=nil)
280
+ @compiler = compiler
281
+ @line = []
282
+ @script = +''
283
+ @script << "#coding:#{enc}\n" if enc
284
+ @script << "#frozen-string-literal:#{frozen}\n" unless frozen.nil?
285
+ @compiler.pre_cmd.each do |x|
286
+ push(x)
287
+ end
288
+ end
289
+ attr_reader :script
290
+
291
+ def push(cmd)
292
+ @line << cmd
293
+ end
294
+
295
+ def cr
296
+ @script << (@line.join('; '))
297
+ @line = []
298
+ @script << "\n"
299
+ end
300
+
301
+ def close
302
+ return unless @line
303
+ @compiler.post_cmd.each do |x|
304
+ push(x)
305
+ end
306
+ @script << (@line.join('; '))
307
+ @line = nil
308
+ end
309
+ end
310
+
311
+ def add_put_cmd(out, content)
312
+ out.push("#{@put_cmd} #{content.dump}.freeze#{"\n" * content.count("\n")}")
313
+ end
314
+
315
+ def add_insert_cmd(out, content)
316
+ out.push("#{@insert_cmd}((#{content}).to_s)")
317
+ end
318
+
319
+ # Compiles an ERB template into Ruby code. Returns an array of the code
320
+ # and encoding like ["code", Encoding].
321
+ def compile(s)
322
+ enc = s.encoding
323
+ raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
324
+ s = s.b # see String#b
325
+ magic_comment = detect_magic_comment(s, enc)
326
+ out = Buffer.new(self, *magic_comment)
327
+
328
+ self.content = +''
329
+ scanner = make_scanner(s)
330
+ scanner.scan do |token|
331
+ next if token.nil?
332
+ next if token == ''
333
+ if scanner.stag.nil?
334
+ compile_stag(token, out, scanner)
335
+ else
336
+ compile_etag(token, out, scanner)
337
+ end
338
+ end
339
+ add_put_cmd(out, content) if content.size > 0
340
+ out.close
341
+ return out.script, *magic_comment
342
+ end
343
+
344
+ def compile_stag(stag, out, scanner)
345
+ case stag
346
+ when PercentLine
347
+ add_put_cmd(out, content) if content.size > 0
348
+ self.content = +''
349
+ out.push(stag.to_s)
350
+ out.cr
351
+ when :cr
352
+ out.cr
353
+ when '<%', '<%=', '<%#'
354
+ scanner.stag = stag
355
+ add_put_cmd(out, content) if content.size > 0
356
+ self.content = +''
357
+ when "\n"
358
+ content << "\n"
359
+ add_put_cmd(out, content)
360
+ self.content = +''
361
+ when '<%%'
362
+ content << '<%'
363
+ else
364
+ content << stag
365
+ end
366
+ end
367
+
368
+ def compile_etag(etag, out, scanner)
369
+ case etag
370
+ when '%>'
371
+ compile_content(scanner.stag, out)
372
+ scanner.stag = nil
373
+ self.content = +''
374
+ when '%%>'
375
+ content << '%>'
376
+ else
377
+ content << etag
378
+ end
379
+ end
380
+
381
+ def compile_content(stag, out)
382
+ case stag
383
+ when '<%'
384
+ if content[-1] == ?\n
385
+ content.chop!
386
+ out.push(content)
387
+ out.cr
388
+ else
389
+ out.push(content)
390
+ end
391
+ when '<%='
392
+ add_insert_cmd(out, content)
393
+ when '<%#'
394
+ out.push("\n" * content.count("\n")) # only adjust lineno
395
+ end
396
+ end
397
+
398
+ def prepare_trim_mode(mode) # :nodoc:
399
+ case mode
400
+ when 1
401
+ return [false, '>']
402
+ when 2
403
+ return [false, '<>']
404
+ when 0, nil
405
+ return [false, nil]
406
+ when String
407
+ unless mode.match?(/\A(%|-|>|<>){1,2}\z/)
408
+ warn_invalid_trim_mode(mode, uplevel: 5)
409
+ end
410
+
411
+ perc = mode.include?('%')
412
+ if mode.include?('-')
413
+ return [perc, '-']
414
+ elsif mode.include?('<>')
415
+ return [perc, '<>']
416
+ elsif mode.include?('>')
417
+ return [perc, '>']
418
+ else
419
+ [perc, nil]
420
+ end
421
+ else
422
+ warn_invalid_trim_mode(mode, uplevel: 5)
423
+ return [false, nil]
424
+ end
425
+ end
426
+
427
+ def make_scanner(src) # :nodoc:
428
+ Scanner.make_scanner(src, @trim_mode, @percent)
429
+ end
430
+
431
+ # Construct a new compiler using the trim_mode. See ERB::new for available
432
+ # trim modes.
433
+ def initialize(trim_mode)
434
+ @percent, @trim_mode = prepare_trim_mode(trim_mode)
435
+ @put_cmd = 'print'
436
+ @insert_cmd = @put_cmd
437
+ @pre_cmd = []
438
+ @post_cmd = []
439
+ end
440
+ attr_reader :percent, :trim_mode
441
+
442
+ # The command to handle text that ends with a newline
443
+ attr_accessor :put_cmd
444
+
445
+ # The command to handle text that is inserted prior to a newline
446
+ attr_accessor :insert_cmd
447
+
448
+ # An array of commands prepended to compiled code
449
+ attr_accessor :pre_cmd
450
+
451
+ # An array of commands appended to compiled code
452
+ attr_accessor :post_cmd
453
+
454
+ private
455
+
456
+ # A buffered text in #compile
457
+ attr_accessor :content
458
+
459
+ def detect_magic_comment(s, enc = nil)
460
+ re = @percent ? /\G(?:<%#(.*)%>|%#(.*)\n)/ : /\G<%#(.*)%>/
461
+ frozen = nil
462
+ s.scan(re) do
463
+ comment = $+
464
+ comment = $1 if comment[/-\*-\s*([^\s].*?)\s*-\*-$/]
465
+ case comment
466
+ when %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
467
+ enc = Encoding.find($1.sub(/-(?:mac|dos|unix)/i, ''))
468
+ when %r"frozen[-_]string[-_]literal\s*:\s*([[:alnum:]]+)"
469
+ frozen = $1
470
+ end
471
+ end
472
+ return enc, frozen
473
+ end
474
+
475
+ # :stopdoc:
476
+ WARNING_UPLEVEL = Class.new {
477
+ attr_reader :c
478
+ def initialize from
479
+ @c = caller.length - from.length
480
+ end
481
+ }.new(caller(0)).c
482
+ private_constant :WARNING_UPLEVEL
483
+ # :startdoc:
484
+
485
+ def warn_invalid_trim_mode(mode, uplevel:)
486
+ warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + WARNING_UPLEVEL
487
+ end
488
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ERB::DefMethod
4
+ #
5
+ # Utility module to define eRuby script as instance method.
6
+ #
7
+ # === Example
8
+ #
9
+ # example.rhtml:
10
+ # <% for item in @items %>
11
+ # <b><%= item %></b>
12
+ # <% end %>
13
+ #
14
+ # example.rb:
15
+ # require 'erb'
16
+ # class MyClass
17
+ # extend ERB::DefMethod
18
+ # def_erb_method('render()', 'example.rhtml')
19
+ # def initialize(items)
20
+ # @items = items
21
+ # end
22
+ # end
23
+ # print MyClass.new([10,20,30]).render()
24
+ #
25
+ # result:
26
+ #
27
+ # <b>10</b>
28
+ #
29
+ # <b>20</b>
30
+ #
31
+ # <b>30</b>
32
+ #
33
+ module ERB::DefMethod
34
+ # define _methodname_ as instance method of current module, using ERB
35
+ # object or eRuby file
36
+ def def_erb_method(methodname, erb_or_fname)
37
+ if erb_or_fname.kind_of? String
38
+ fname = erb_or_fname
39
+ erb = ERB.new(File.read(fname))
40
+ erb.def_method(self, methodname, fname)
41
+ else
42
+ erb = erb_or_fname
43
+ erb.def_method(self, methodname, erb.filename || '(ERB)')
44
+ end
45
+ end
46
+ module_function :def_erb_method
47
+ end
data/lib/erb/escape.so ADDED
Binary file