erb 2.2.3 → 4.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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +21 -14
- data/.gitignore +3 -0
- data/Gemfile +5 -2
- data/NEWS.md +25 -4
- data/README.md +1 -1
- data/Rakefile +13 -0
- data/erb.gemspec +10 -3
- data/ext/erb/escape/escape.c +95 -0
- data/ext/erb/escape/extconf.rb +2 -0
- data/lib/erb/compiler.rb +471 -0
- data/lib/erb/def_method.rb +46 -0
- data/lib/erb/util.rb +59 -0
- data/lib/erb/version.rb +1 -1
- data/lib/erb.rb +4 -577
- data/libexec/erb +1 -11
- metadata +18 -10
data/lib/erb.rb
CHANGED
@@ -14,6 +14,9 @@
|
|
14
14
|
|
15
15
|
require 'cgi/util'
|
16
16
|
require 'erb/version'
|
17
|
+
require 'erb/compiler'
|
18
|
+
require 'erb/def_method'
|
19
|
+
require 'erb/util'
|
17
20
|
|
18
21
|
#
|
19
22
|
# = ERB -- Ruby Templating
|
@@ -46,7 +49,7 @@ require 'erb/version'
|
|
46
49
|
#
|
47
50
|
# <% Ruby code -- inline with output %>
|
48
51
|
# <%= Ruby expression -- replace with result %>
|
49
|
-
# <%# comment -- ignored -- useful in testing %>
|
52
|
+
# <%# comment -- ignored -- useful in testing %> (`<% #` doesn't work. Don't use Ruby comments.)
|
50
53
|
# % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
|
51
54
|
# %% replaced with % if first thing on a line and % processing is used
|
52
55
|
# <%% or %%> -- replace with <% or %> respectively
|
@@ -264,486 +267,7 @@ class ERB
|
|
264
267
|
def self.version
|
265
268
|
VERSION
|
266
269
|
end
|
267
|
-
end
|
268
270
|
|
269
|
-
#--
|
270
|
-
# ERB::Compiler
|
271
|
-
class ERB
|
272
|
-
# = ERB::Compiler
|
273
|
-
#
|
274
|
-
# Compiles ERB templates into Ruby code; the compiled code produces the
|
275
|
-
# template result when evaluated. ERB::Compiler provides hooks to define how
|
276
|
-
# generated output is handled.
|
277
|
-
#
|
278
|
-
# Internally ERB does something like this to generate the code returned by
|
279
|
-
# ERB#src:
|
280
|
-
#
|
281
|
-
# compiler = ERB::Compiler.new('<>')
|
282
|
-
# compiler.pre_cmd = ["_erbout=+''"]
|
283
|
-
# compiler.put_cmd = "_erbout.<<"
|
284
|
-
# compiler.insert_cmd = "_erbout.<<"
|
285
|
-
# compiler.post_cmd = ["_erbout"]
|
286
|
-
#
|
287
|
-
# code, enc = compiler.compile("Got <%= obj %>!\n")
|
288
|
-
# puts code
|
289
|
-
#
|
290
|
-
# <i>Generates</i>:
|
291
|
-
#
|
292
|
-
# #coding:UTF-8
|
293
|
-
# _erbout=+''; _erbout.<< "Got ".freeze; _erbout.<<(( obj ).to_s); _erbout.<< "!\n".freeze; _erbout
|
294
|
-
#
|
295
|
-
# By default the output is sent to the print method. For example:
|
296
|
-
#
|
297
|
-
# compiler = ERB::Compiler.new('<>')
|
298
|
-
# code, enc = compiler.compile("Got <%= obj %>!\n")
|
299
|
-
# puts code
|
300
|
-
#
|
301
|
-
# <i>Generates</i>:
|
302
|
-
#
|
303
|
-
# #coding:UTF-8
|
304
|
-
# print "Got ".freeze; print(( obj ).to_s); print "!\n".freeze
|
305
|
-
#
|
306
|
-
# == Evaluation
|
307
|
-
#
|
308
|
-
# The compiled code can be used in any context where the names in the code
|
309
|
-
# correctly resolve. Using the last example, each of these print 'Got It!'
|
310
|
-
#
|
311
|
-
# Evaluate using a variable:
|
312
|
-
#
|
313
|
-
# obj = 'It'
|
314
|
-
# eval code
|
315
|
-
#
|
316
|
-
# Evaluate using an input:
|
317
|
-
#
|
318
|
-
# mod = Module.new
|
319
|
-
# mod.module_eval %{
|
320
|
-
# def get(obj)
|
321
|
-
# #{code}
|
322
|
-
# end
|
323
|
-
# }
|
324
|
-
# extend mod
|
325
|
-
# get('It')
|
326
|
-
#
|
327
|
-
# Evaluate using an accessor:
|
328
|
-
#
|
329
|
-
# klass = Class.new Object
|
330
|
-
# klass.class_eval %{
|
331
|
-
# attr_accessor :obj
|
332
|
-
# def initialize(obj)
|
333
|
-
# @obj = obj
|
334
|
-
# end
|
335
|
-
# def get_it
|
336
|
-
# #{code}
|
337
|
-
# end
|
338
|
-
# }
|
339
|
-
# klass.new('It').get_it
|
340
|
-
#
|
341
|
-
# Good! See also ERB#def_method, ERB#def_module, and ERB#def_class.
|
342
|
-
class Compiler # :nodoc:
|
343
|
-
class PercentLine # :nodoc:
|
344
|
-
def initialize(str)
|
345
|
-
@value = str
|
346
|
-
end
|
347
|
-
attr_reader :value
|
348
|
-
alias :to_s :value
|
349
|
-
end
|
350
|
-
|
351
|
-
class Scanner # :nodoc:
|
352
|
-
@scanner_map = {}
|
353
|
-
class << self
|
354
|
-
def register_scanner(klass, trim_mode, percent)
|
355
|
-
@scanner_map[[trim_mode, percent]] = klass
|
356
|
-
end
|
357
|
-
alias :regist_scanner :register_scanner
|
358
|
-
end
|
359
|
-
|
360
|
-
def self.default_scanner=(klass)
|
361
|
-
@default_scanner = klass
|
362
|
-
end
|
363
|
-
|
364
|
-
def self.make_scanner(src, trim_mode, percent)
|
365
|
-
klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
|
366
|
-
klass.new(src, trim_mode, percent)
|
367
|
-
end
|
368
|
-
|
369
|
-
DEFAULT_STAGS = %w(<%% <%= <%# <%).freeze
|
370
|
-
DEFAULT_ETAGS = %w(%%> %>).freeze
|
371
|
-
def initialize(src, trim_mode, percent)
|
372
|
-
@src = src
|
373
|
-
@stag = nil
|
374
|
-
@stags = DEFAULT_STAGS
|
375
|
-
@etags = DEFAULT_ETAGS
|
376
|
-
end
|
377
|
-
attr_accessor :stag
|
378
|
-
attr_reader :stags, :etags
|
379
|
-
|
380
|
-
def scan; end
|
381
|
-
end
|
382
|
-
|
383
|
-
class TrimScanner < Scanner # :nodoc:
|
384
|
-
def initialize(src, trim_mode, percent)
|
385
|
-
super
|
386
|
-
@trim_mode = trim_mode
|
387
|
-
@percent = percent
|
388
|
-
if @trim_mode == '>'
|
389
|
-
@scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
|
390
|
-
@scan_line = self.method(:trim_line1)
|
391
|
-
elsif @trim_mode == '<>'
|
392
|
-
@scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
|
393
|
-
@scan_line = self.method(:trim_line2)
|
394
|
-
elsif @trim_mode == '-'
|
395
|
-
@scan_reg = /(.*?)(^[ \t]*<%\-|<%\-|-%>\r?\n|-%>|#{(stags + etags).join('|')}|\z)/m
|
396
|
-
@scan_line = self.method(:explicit_trim_line)
|
397
|
-
else
|
398
|
-
@scan_reg = /(.*?)(#{(stags + etags).join('|')}|\n|\z)/m
|
399
|
-
@scan_line = self.method(:scan_line)
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
def scan(&block)
|
404
|
-
@stag = nil
|
405
|
-
if @percent
|
406
|
-
@src.each_line do |line|
|
407
|
-
percent_line(line, &block)
|
408
|
-
end
|
409
|
-
else
|
410
|
-
@scan_line.call(@src, &block)
|
411
|
-
end
|
412
|
-
nil
|
413
|
-
end
|
414
|
-
|
415
|
-
def percent_line(line, &block)
|
416
|
-
if @stag || line[0] != ?%
|
417
|
-
return @scan_line.call(line, &block)
|
418
|
-
end
|
419
|
-
|
420
|
-
line[0] = ''
|
421
|
-
if line[0] == ?%
|
422
|
-
@scan_line.call(line, &block)
|
423
|
-
else
|
424
|
-
yield(PercentLine.new(line.chomp))
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
def scan_line(line)
|
429
|
-
line.scan(@scan_reg) do |tokens|
|
430
|
-
tokens.each do |token|
|
431
|
-
next if token.empty?
|
432
|
-
yield(token)
|
433
|
-
end
|
434
|
-
end
|
435
|
-
end
|
436
|
-
|
437
|
-
def trim_line1(line)
|
438
|
-
line.scan(@scan_reg) do |tokens|
|
439
|
-
tokens.each do |token|
|
440
|
-
next if token.empty?
|
441
|
-
if token == "%>\n" || token == "%>\r\n"
|
442
|
-
yield('%>')
|
443
|
-
yield(:cr)
|
444
|
-
else
|
445
|
-
yield(token)
|
446
|
-
end
|
447
|
-
end
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
def trim_line2(line)
|
452
|
-
head = nil
|
453
|
-
line.scan(@scan_reg) do |tokens|
|
454
|
-
tokens.each do |token|
|
455
|
-
next if token.empty?
|
456
|
-
head = token unless head
|
457
|
-
if token == "%>\n" || token == "%>\r\n"
|
458
|
-
yield('%>')
|
459
|
-
if is_erb_stag?(head)
|
460
|
-
yield(:cr)
|
461
|
-
else
|
462
|
-
yield("\n")
|
463
|
-
end
|
464
|
-
head = nil
|
465
|
-
else
|
466
|
-
yield(token)
|
467
|
-
head = nil if token == "\n"
|
468
|
-
end
|
469
|
-
end
|
470
|
-
end
|
471
|
-
end
|
472
|
-
|
473
|
-
def explicit_trim_line(line)
|
474
|
-
line.scan(@scan_reg) do |tokens|
|
475
|
-
tokens.each do |token|
|
476
|
-
next if token.empty?
|
477
|
-
if @stag.nil? && /[ \t]*<%-/ =~ token
|
478
|
-
yield('<%')
|
479
|
-
elsif @stag && (token == "-%>\n" || token == "-%>\r\n")
|
480
|
-
yield('%>')
|
481
|
-
yield(:cr)
|
482
|
-
elsif @stag && token == '-%>'
|
483
|
-
yield('%>')
|
484
|
-
else
|
485
|
-
yield(token)
|
486
|
-
end
|
487
|
-
end
|
488
|
-
end
|
489
|
-
end
|
490
|
-
|
491
|
-
ERB_STAG = %w(<%= <%# <%)
|
492
|
-
def is_erb_stag?(s)
|
493
|
-
ERB_STAG.member?(s)
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
Scanner.default_scanner = TrimScanner
|
498
|
-
|
499
|
-
begin
|
500
|
-
require 'strscan'
|
501
|
-
rescue LoadError
|
502
|
-
else
|
503
|
-
class SimpleScanner < Scanner # :nodoc:
|
504
|
-
def scan
|
505
|
-
stag_reg = (stags == DEFAULT_STAGS) ? /(.*?)(<%[%=#]?|\z)/m : /(.*?)(#{stags.join('|')}|\z)/m
|
506
|
-
etag_reg = (etags == DEFAULT_ETAGS) ? /(.*?)(%%?>|\z)/m : /(.*?)(#{etags.join('|')}|\z)/m
|
507
|
-
scanner = StringScanner.new(@src)
|
508
|
-
while ! scanner.eos?
|
509
|
-
scanner.scan(@stag ? etag_reg : stag_reg)
|
510
|
-
yield(scanner[1])
|
511
|
-
yield(scanner[2])
|
512
|
-
end
|
513
|
-
end
|
514
|
-
end
|
515
|
-
Scanner.register_scanner(SimpleScanner, nil, false)
|
516
|
-
|
517
|
-
class ExplicitScanner < Scanner # :nodoc:
|
518
|
-
def scan
|
519
|
-
stag_reg = /(.*?)(^[ \t]*<%-|<%-|#{stags.join('|')}|\z)/m
|
520
|
-
etag_reg = /(.*?)(-%>|#{etags.join('|')}|\z)/m
|
521
|
-
scanner = StringScanner.new(@src)
|
522
|
-
while ! scanner.eos?
|
523
|
-
scanner.scan(@stag ? etag_reg : stag_reg)
|
524
|
-
yield(scanner[1])
|
525
|
-
|
526
|
-
elem = scanner[2]
|
527
|
-
if /[ \t]*<%-/ =~ elem
|
528
|
-
yield('<%')
|
529
|
-
elsif elem == '-%>'
|
530
|
-
yield('%>')
|
531
|
-
yield(:cr) if scanner.scan(/(\r?\n|\z)/)
|
532
|
-
else
|
533
|
-
yield(elem)
|
534
|
-
end
|
535
|
-
end
|
536
|
-
end
|
537
|
-
end
|
538
|
-
Scanner.register_scanner(ExplicitScanner, '-', false)
|
539
|
-
end
|
540
|
-
|
541
|
-
class Buffer # :nodoc:
|
542
|
-
def initialize(compiler, enc=nil, frozen=nil)
|
543
|
-
@compiler = compiler
|
544
|
-
@line = []
|
545
|
-
@script = +''
|
546
|
-
@script << "#coding:#{enc}\n" if enc
|
547
|
-
@script << "#frozen-string-literal:#{frozen}\n" unless frozen.nil?
|
548
|
-
@compiler.pre_cmd.each do |x|
|
549
|
-
push(x)
|
550
|
-
end
|
551
|
-
end
|
552
|
-
attr_reader :script
|
553
|
-
|
554
|
-
def push(cmd)
|
555
|
-
@line << cmd
|
556
|
-
end
|
557
|
-
|
558
|
-
def cr
|
559
|
-
@script << (@line.join('; '))
|
560
|
-
@line = []
|
561
|
-
@script << "\n"
|
562
|
-
end
|
563
|
-
|
564
|
-
def close
|
565
|
-
return unless @line
|
566
|
-
@compiler.post_cmd.each do |x|
|
567
|
-
push(x)
|
568
|
-
end
|
569
|
-
@script << (@line.join('; '))
|
570
|
-
@line = nil
|
571
|
-
end
|
572
|
-
end
|
573
|
-
|
574
|
-
def add_put_cmd(out, content)
|
575
|
-
out.push("#{@put_cmd} #{content.dump}.freeze#{"\n" * content.count("\n")}")
|
576
|
-
end
|
577
|
-
|
578
|
-
def add_insert_cmd(out, content)
|
579
|
-
out.push("#{@insert_cmd}((#{content}).to_s)")
|
580
|
-
end
|
581
|
-
|
582
|
-
# Compiles an ERB template into Ruby code. Returns an array of the code
|
583
|
-
# and encoding like ["code", Encoding].
|
584
|
-
def compile(s)
|
585
|
-
enc = s.encoding
|
586
|
-
raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
|
587
|
-
s = s.b # see String#b
|
588
|
-
magic_comment = detect_magic_comment(s, enc)
|
589
|
-
out = Buffer.new(self, *magic_comment)
|
590
|
-
|
591
|
-
self.content = +''
|
592
|
-
scanner = make_scanner(s)
|
593
|
-
scanner.scan do |token|
|
594
|
-
next if token.nil?
|
595
|
-
next if token == ''
|
596
|
-
if scanner.stag.nil?
|
597
|
-
compile_stag(token, out, scanner)
|
598
|
-
else
|
599
|
-
compile_etag(token, out, scanner)
|
600
|
-
end
|
601
|
-
end
|
602
|
-
add_put_cmd(out, content) if content.size > 0
|
603
|
-
out.close
|
604
|
-
return out.script, *magic_comment
|
605
|
-
end
|
606
|
-
|
607
|
-
def compile_stag(stag, out, scanner)
|
608
|
-
case stag
|
609
|
-
when PercentLine
|
610
|
-
add_put_cmd(out, content) if content.size > 0
|
611
|
-
self.content = +''
|
612
|
-
out.push(stag.to_s)
|
613
|
-
out.cr
|
614
|
-
when :cr
|
615
|
-
out.cr
|
616
|
-
when '<%', '<%=', '<%#'
|
617
|
-
scanner.stag = stag
|
618
|
-
add_put_cmd(out, content) if content.size > 0
|
619
|
-
self.content = +''
|
620
|
-
when "\n"
|
621
|
-
content << "\n"
|
622
|
-
add_put_cmd(out, content)
|
623
|
-
self.content = +''
|
624
|
-
when '<%%'
|
625
|
-
content << '<%'
|
626
|
-
else
|
627
|
-
content << stag
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
|
-
def compile_etag(etag, out, scanner)
|
632
|
-
case etag
|
633
|
-
when '%>'
|
634
|
-
compile_content(scanner.stag, out)
|
635
|
-
scanner.stag = nil
|
636
|
-
self.content = +''
|
637
|
-
when '%%>'
|
638
|
-
content << '%>'
|
639
|
-
else
|
640
|
-
content << etag
|
641
|
-
end
|
642
|
-
end
|
643
|
-
|
644
|
-
def compile_content(stag, out)
|
645
|
-
case stag
|
646
|
-
when '<%'
|
647
|
-
if content[-1] == ?\n
|
648
|
-
content.chop!
|
649
|
-
out.push(content)
|
650
|
-
out.cr
|
651
|
-
else
|
652
|
-
out.push(content)
|
653
|
-
end
|
654
|
-
when '<%='
|
655
|
-
add_insert_cmd(out, content)
|
656
|
-
when '<%#'
|
657
|
-
# commented out
|
658
|
-
end
|
659
|
-
end
|
660
|
-
|
661
|
-
def prepare_trim_mode(mode) # :nodoc:
|
662
|
-
case mode
|
663
|
-
when 1
|
664
|
-
return [false, '>']
|
665
|
-
when 2
|
666
|
-
return [false, '<>']
|
667
|
-
when 0, nil
|
668
|
-
return [false, nil]
|
669
|
-
when String
|
670
|
-
unless mode.match?(/\A(%|-|>|<>){1,2}\z/)
|
671
|
-
warn_invalid_trim_mode(mode, uplevel: 5)
|
672
|
-
end
|
673
|
-
|
674
|
-
perc = mode.include?('%')
|
675
|
-
if mode.include?('-')
|
676
|
-
return [perc, '-']
|
677
|
-
elsif mode.include?('<>')
|
678
|
-
return [perc, '<>']
|
679
|
-
elsif mode.include?('>')
|
680
|
-
return [perc, '>']
|
681
|
-
else
|
682
|
-
[perc, nil]
|
683
|
-
end
|
684
|
-
else
|
685
|
-
warn_invalid_trim_mode(mode, uplevel: 5)
|
686
|
-
return [false, nil]
|
687
|
-
end
|
688
|
-
end
|
689
|
-
|
690
|
-
def make_scanner(src) # :nodoc:
|
691
|
-
Scanner.make_scanner(src, @trim_mode, @percent)
|
692
|
-
end
|
693
|
-
|
694
|
-
# Construct a new compiler using the trim_mode. See ERB::new for available
|
695
|
-
# trim modes.
|
696
|
-
def initialize(trim_mode)
|
697
|
-
@percent, @trim_mode = prepare_trim_mode(trim_mode)
|
698
|
-
@put_cmd = 'print'
|
699
|
-
@insert_cmd = @put_cmd
|
700
|
-
@pre_cmd = []
|
701
|
-
@post_cmd = []
|
702
|
-
end
|
703
|
-
attr_reader :percent, :trim_mode
|
704
|
-
|
705
|
-
# The command to handle text that ends with a newline
|
706
|
-
attr_accessor :put_cmd
|
707
|
-
|
708
|
-
# The command to handle text that is inserted prior to a newline
|
709
|
-
attr_accessor :insert_cmd
|
710
|
-
|
711
|
-
# An array of commands prepended to compiled code
|
712
|
-
attr_accessor :pre_cmd
|
713
|
-
|
714
|
-
# An array of commands appended to compiled code
|
715
|
-
attr_accessor :post_cmd
|
716
|
-
|
717
|
-
private
|
718
|
-
|
719
|
-
# A buffered text in #compile
|
720
|
-
attr_accessor :content
|
721
|
-
|
722
|
-
def detect_magic_comment(s, enc = nil)
|
723
|
-
re = @percent ? /\G(?:<%#(.*)%>|%#(.*)\n)/ : /\G<%#(.*)%>/
|
724
|
-
frozen = nil
|
725
|
-
s.scan(re) do
|
726
|
-
comment = $+
|
727
|
-
comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/]
|
728
|
-
case comment
|
729
|
-
when %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
|
730
|
-
enc = Encoding.find($1.sub(/-(?:mac|dos|unix)/i, ''))
|
731
|
-
when %r"frozen[-_]string[-_]literal\s*:\s*([[:alnum:]]+)"
|
732
|
-
frozen = $1
|
733
|
-
end
|
734
|
-
end
|
735
|
-
return enc, frozen
|
736
|
-
end
|
737
|
-
|
738
|
-
def warn_invalid_trim_mode(mode, uplevel:)
|
739
|
-
warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1
|
740
|
-
end
|
741
|
-
end
|
742
|
-
end
|
743
|
-
|
744
|
-
#--
|
745
|
-
# ERB
|
746
|
-
class ERB
|
747
271
|
#
|
748
272
|
# Constructs a new ERB object with the template specified in _str_.
|
749
273
|
#
|
@@ -980,100 +504,3 @@ class ERB
|
|
980
504
|
cls
|
981
505
|
end
|
982
506
|
end
|
983
|
-
|
984
|
-
#--
|
985
|
-
# ERB::Util
|
986
|
-
class ERB
|
987
|
-
# A utility module for conversion routines, often handy in HTML generation.
|
988
|
-
module Util
|
989
|
-
public
|
990
|
-
#
|
991
|
-
# A utility method for escaping HTML tag characters in _s_.
|
992
|
-
#
|
993
|
-
# require "erb"
|
994
|
-
# include ERB::Util
|
995
|
-
#
|
996
|
-
# puts html_escape("is a > 0 & a < 10?")
|
997
|
-
#
|
998
|
-
# _Generates_
|
999
|
-
#
|
1000
|
-
# is a > 0 & a < 10?
|
1001
|
-
#
|
1002
|
-
def html_escape(s)
|
1003
|
-
CGI.escapeHTML(s.to_s)
|
1004
|
-
end
|
1005
|
-
alias h html_escape
|
1006
|
-
module_function :h
|
1007
|
-
module_function :html_escape
|
1008
|
-
|
1009
|
-
#
|
1010
|
-
# A utility method for encoding the String _s_ as a URL.
|
1011
|
-
#
|
1012
|
-
# require "erb"
|
1013
|
-
# include ERB::Util
|
1014
|
-
#
|
1015
|
-
# puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
|
1016
|
-
#
|
1017
|
-
# _Generates_
|
1018
|
-
#
|
1019
|
-
# Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
|
1020
|
-
#
|
1021
|
-
def url_encode(s)
|
1022
|
-
s.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) { |m|
|
1023
|
-
sprintf("%%%02X", m.unpack1("C"))
|
1024
|
-
}
|
1025
|
-
end
|
1026
|
-
alias u url_encode
|
1027
|
-
module_function :u
|
1028
|
-
module_function :url_encode
|
1029
|
-
end
|
1030
|
-
end
|
1031
|
-
|
1032
|
-
#--
|
1033
|
-
# ERB::DefMethod
|
1034
|
-
class ERB
|
1035
|
-
# Utility module to define eRuby script as instance method.
|
1036
|
-
#
|
1037
|
-
# === Example
|
1038
|
-
#
|
1039
|
-
# example.rhtml:
|
1040
|
-
# <% for item in @items %>
|
1041
|
-
# <b><%= item %></b>
|
1042
|
-
# <% end %>
|
1043
|
-
#
|
1044
|
-
# example.rb:
|
1045
|
-
# require 'erb'
|
1046
|
-
# class MyClass
|
1047
|
-
# extend ERB::DefMethod
|
1048
|
-
# def_erb_method('render()', 'example.rhtml')
|
1049
|
-
# def initialize(items)
|
1050
|
-
# @items = items
|
1051
|
-
# end
|
1052
|
-
# end
|
1053
|
-
# print MyClass.new([10,20,30]).render()
|
1054
|
-
#
|
1055
|
-
# result:
|
1056
|
-
#
|
1057
|
-
# <b>10</b>
|
1058
|
-
#
|
1059
|
-
# <b>20</b>
|
1060
|
-
#
|
1061
|
-
# <b>30</b>
|
1062
|
-
#
|
1063
|
-
module DefMethod
|
1064
|
-
public
|
1065
|
-
# define _methodname_ as instance method of current module, using ERB
|
1066
|
-
# object or eRuby file
|
1067
|
-
def def_erb_method(methodname, erb_or_fname)
|
1068
|
-
if erb_or_fname.kind_of? String
|
1069
|
-
fname = erb_or_fname
|
1070
|
-
erb = ERB.new(File.read(fname))
|
1071
|
-
erb.def_method(self, methodname, fname)
|
1072
|
-
else
|
1073
|
-
erb = erb_or_fname
|
1074
|
-
erb.def_method(self, methodname, erb.filename || '(ERB)')
|
1075
|
-
end
|
1076
|
-
end
|
1077
|
-
module_function :def_erb_method
|
1078
|
-
end
|
1079
|
-
end
|
data/libexec/erb
CHANGED
@@ -74,11 +74,6 @@ class ERB
|
|
74
74
|
$DEBUG = true
|
75
75
|
when '-r' # require
|
76
76
|
require ARGV.req_arg
|
77
|
-
when '-S' # security level
|
78
|
-
warn 'warning: -S option of erb command is deprecated. Please do not use this.'
|
79
|
-
arg = ARGV.req_arg
|
80
|
-
raise "invalid safe_level #{arg.dump}" unless arg =~ /\A[0-1]\z/
|
81
|
-
safe_level = arg.to_i
|
82
77
|
when '-T' # trim mode
|
83
78
|
arg = ARGV.req_arg
|
84
79
|
if arg == '-'
|
@@ -127,12 +122,7 @@ EOU
|
|
127
122
|
filename = $FILENAME
|
128
123
|
exit 2 unless src
|
129
124
|
trim = trim_mode_opt(trim_mode, disable_percent)
|
130
|
-
|
131
|
-
erb = factory.new(src, trim_mode: trim)
|
132
|
-
else
|
133
|
-
# [deprecated] This will be removed at Ruby 2.7.
|
134
|
-
erb = factory.new(src, safe_level, trim_mode: trim)
|
135
|
-
end
|
125
|
+
erb = factory.new(src, trim_mode: trim)
|
136
126
|
erb.filename = filename
|
137
127
|
if output
|
138
128
|
if number
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: erb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masatoshi SEKI
|
8
|
-
|
8
|
+
- Takashi Kokubun
|
9
|
+
autorequire:
|
9
10
|
bindir: libexec
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2022-11-26 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: cgi
|
@@ -16,20 +17,22 @@ dependencies:
|
|
16
17
|
requirements:
|
17
18
|
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
+
version: 0.3.3
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
25
|
- - ">="
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
+
version: 0.3.3
|
27
28
|
description: An easy to use but powerful templating system for Ruby.
|
28
29
|
email:
|
29
30
|
- seki@ruby-lang.org
|
31
|
+
- takashikkbn@gmail.com
|
30
32
|
executables:
|
31
33
|
- erb
|
32
|
-
extensions:
|
34
|
+
extensions:
|
35
|
+
- ext/erb/escape/extconf.rb
|
33
36
|
extra_rdoc_files: []
|
34
37
|
files:
|
35
38
|
- ".github/workflows/test.yml"
|
@@ -42,7 +45,12 @@ files:
|
|
42
45
|
- bin/console
|
43
46
|
- bin/setup
|
44
47
|
- erb.gemspec
|
48
|
+
- ext/erb/escape/escape.c
|
49
|
+
- ext/erb/escape/extconf.rb
|
45
50
|
- lib/erb.rb
|
51
|
+
- lib/erb/compiler.rb
|
52
|
+
- lib/erb/def_method.rb
|
53
|
+
- lib/erb/util.rb
|
46
54
|
- lib/erb/version.rb
|
47
55
|
- libexec/erb
|
48
56
|
homepage: https://github.com/ruby/erb
|
@@ -52,7 +60,7 @@ licenses:
|
|
52
60
|
metadata:
|
53
61
|
homepage_uri: https://github.com/ruby/erb
|
54
62
|
source_code_uri: https://github.com/ruby/erb
|
55
|
-
post_install_message:
|
63
|
+
post_install_message:
|
56
64
|
rdoc_options: []
|
57
65
|
require_paths:
|
58
66
|
- lib
|
@@ -60,15 +68,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
68
|
requirements:
|
61
69
|
- - ">="
|
62
70
|
- !ruby/object:Gem::Version
|
63
|
-
version: 2.
|
71
|
+
version: 2.7.0
|
64
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
73
|
requirements:
|
66
74
|
- - ">="
|
67
75
|
- !ruby/object:Gem::Version
|
68
76
|
version: '0'
|
69
77
|
requirements: []
|
70
|
-
rubygems_version: 3.
|
71
|
-
signing_key:
|
78
|
+
rubygems_version: 3.3.7
|
79
|
+
signing_key:
|
72
80
|
specification_version: 4
|
73
81
|
summary: An easy to use but powerful templating system for Ruby.
|
74
82
|
test_files: []
|