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.
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 &gt; 0 &amp; a &lt; 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
- if safe_level.nil?
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: 2.2.3
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masatoshi SEKI
8
- autorequire:
8
+ - Takashi Kokubun
9
+ autorequire:
9
10
  bindir: libexec
10
11
  cert_chain: []
11
- date: 2021-03-26 00:00:00.000000000 Z
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: '0'
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: '0'
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.5.0
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.2.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: []