ua 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,720 @@
1
+ #--
2
+ # ERB::Compiler
3
+ class ERB
4
+ # = ERB::Compiler
5
+ #
6
+ # Compiles ERB templates into Ruby code; the compiled code produces the
7
+ # template result when evaluated. ERB::Compiler provides hooks to define how
8
+ # generated output is handled.
9
+ #
10
+ # Internally ERB does something like this to generate the code returned by
11
+ # ERB#src:
12
+ #
13
+ # compiler = ERB::Compiler.new('<>')
14
+ # compiler.pre_cmd = ["_erbout=''"]
15
+ # compiler.put_cmd = "_erbout.concat"
16
+ # compiler.insert_cmd = "_erbout.concat"
17
+ # compiler.post_cmd = ["_erbout"]
18
+ #
19
+ # code, enc = compiler.compile("Got <%= obj %>!\n")
20
+ # puts code
21
+ #
22
+ # <i>Generates</i>:
23
+ #
24
+ # #coding:UTF-8
25
+ # _erbout=''; _erbout.concat "Got "; _erbout.concat(( obj ).to_s); _erbout.concat "!\n"; _erbout
26
+ #
27
+ # By default the output is sent to the print method. For example:
28
+ #
29
+ # compiler = ERB::Compiler.new('<>')
30
+ # code, enc = compiler.compile("Got <%= obj %>!\n")
31
+ # puts code
32
+ #
33
+ # <i>Generates</i>:
34
+ #
35
+ # #coding:UTF-8
36
+ # print "Got "; print(( obj ).to_s); print "!\n"
37
+ #
38
+ # == Evaluation
39
+ #
40
+ # The compiled code can be used in any context where the names in the code
41
+ # correctly resolve. Using the last example, each of these print 'Got It!'
42
+ #
43
+ # Evaluate using a variable:
44
+ #
45
+ # obj = 'It'
46
+ # eval code
47
+ #
48
+ # Evaluate using an input:
49
+ #
50
+ # mod = Module.new
51
+ # mod.module_eval %{
52
+ # def get(obj)
53
+ # #{code}
54
+ # end
55
+ # }
56
+ # extend mod
57
+ # get('It')
58
+ #
59
+ # Evaluate using an accessor:
60
+ #
61
+ # klass = Class.new Object
62
+ # klass.class_eval %{
63
+ # attr_accessor :obj
64
+ # def initialize(obj)
65
+ # @obj = obj
66
+ # end
67
+ # def get_it
68
+ # #{code}
69
+ # end
70
+ # }
71
+ # klass.new('It').get_it
72
+ #
73
+ # Good! See also ERB#def_method, ERB#def_module, and ERB#def_class.
74
+ class Compiler # :nodoc:
75
+ class PercentLine # :nodoc:
76
+ def initialize(str)
77
+ @value = str
78
+ end
79
+ attr_reader :value
80
+ alias :to_s :value
81
+
82
+ def empty?
83
+ @value.empty?
84
+ end
85
+ end
86
+
87
+ class Scanner # :nodoc:
88
+ @scanner_map = {}
89
+ def self.regist_scanner(klass, trim_mode, percent)
90
+ @scanner_map[[trim_mode, percent]] = klass
91
+ end
92
+
93
+ def self.default_scanner=(klass)
94
+ @default_scanner = klass
95
+ end
96
+
97
+ def self.make_scanner(src, trim_mode, percent)
98
+ klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
99
+ klass.new(src, trim_mode, percent)
100
+ end
101
+
102
+ def initialize(src, trim_mode, percent)
103
+ @src = src
104
+ @stag = nil
105
+ end
106
+ attr_accessor :stag
107
+
108
+ def scan; end
109
+ end
110
+
111
+ class TrimScanner < Scanner # :nodoc:
112
+ def initialize(src, trim_mode, percent)
113
+ super
114
+ @trim_mode = trim_mode
115
+ @percent = percent
116
+ if @trim_mode == '>'
117
+ @scan_line = self.method(:trim_line1)
118
+ elsif @trim_mode == '<>'
119
+ @scan_line = self.method(:trim_line2)
120
+ elsif @trim_mode == '-'
121
+ @scan_line = self.method(:explicit_trim_line)
122
+ else
123
+ @scan_line = self.method(:scan_line)
124
+ end
125
+ end
126
+ attr_accessor :stag
127
+
128
+ def scan(&block)
129
+ @stag = nil
130
+ if @percent
131
+ @src.each_line do |line|
132
+ percent_line(line, &block)
133
+ end
134
+ else
135
+ @scan_line.call(@src, &block)
136
+ end
137
+ nil
138
+ end
139
+
140
+ def percent_line(line, &block)
141
+ if @stag || line[0] != ?%
142
+ return @scan_line.call(line, &block)
143
+ end
144
+
145
+ line[0] = ''
146
+ if line[0] == ?%
147
+ @scan_line.call(line, &block)
148
+ else
149
+ yield(PercentLine.new(line.chomp))
150
+ end
151
+ end
152
+
153
+ def scan_line(line)
154
+ line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens|
155
+ tokens.each do |token|
156
+ next if token.empty?
157
+ yield(token)
158
+ end
159
+ end
160
+ end
161
+
162
+ def trim_line1(line)
163
+ line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens|
164
+ tokens.each do |token|
165
+ next if token.empty?
166
+ if token == "%>\n"
167
+ yield('%>')
168
+ yield(:cr)
169
+ else
170
+ yield(token)
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ def trim_line2(line)
177
+ head = nil
178
+ line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens|
179
+ tokens.each do |token|
180
+ next if token.empty?
181
+ head = token unless head
182
+ if token == "%>\n"
183
+ yield('%>')
184
+ if is_erb_stag?(head)
185
+ yield(:cr)
186
+ else
187
+ yield("\n")
188
+ end
189
+ head = nil
190
+ else
191
+ yield(token)
192
+ head = nil if token == "\n"
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ def explicit_trim_line(line)
199
+ line.scan(/(.*?)(^[ \t]*<%\-|<%\-|<%%|%%>|<%=|<%#|<%|-%>\n|-%>|%>|\z)/m) do |tokens|
200
+ tokens.each do |token|
201
+ next if token.empty?
202
+ if @stag.nil? && /[ \t]*<%-/ =~ token
203
+ yield('<%')
204
+ elsif @stag && token == "-%>\n"
205
+ yield('%>')
206
+ yield(:cr)
207
+ elsif @stag && token == '-%>'
208
+ yield('%>')
209
+ else
210
+ yield(token)
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ ERB_STAG = %w(<%= <%# <%)
217
+ def is_erb_stag?(s)
218
+ ERB_STAG.member?(s)
219
+ end
220
+ end
221
+
222
+ Scanner.default_scanner = TrimScanner
223
+
224
+ class SimpleScanner < Scanner # :nodoc:
225
+ def scan
226
+ @src.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens|
227
+ tokens.each do |token|
228
+ next if token.empty?
229
+ yield(token)
230
+ end
231
+ end
232
+ end
233
+ end
234
+
235
+ Scanner.regist_scanner(SimpleScanner, nil, false)
236
+
237
+ begin
238
+ require 'strscan.rb'
239
+ class SimpleScanner2 < Scanner # :nodoc:
240
+ def scan
241
+ stag_reg = /(.*?)(<%%|<%=|<%#|<%|\z)/m
242
+ etag_reg = /(.*?)(%%>|%>|\z)/m
243
+ scanner = StringScanner.new(@src)
244
+ while ! scanner.eos?
245
+ scanner.scan(@stag ? etag_reg : stag_reg)
246
+ yield(scanner[1])
247
+ yield(scanner[2])
248
+ end
249
+ end
250
+ end
251
+ Scanner.regist_scanner(SimpleScanner2, nil, false)
252
+
253
+ class ExplicitScanner < Scanner # :nodoc:
254
+ def scan
255
+ stag_reg = /(.*?)(^[ \t]*<%-|<%%|<%=|<%#|<%-|<%|\z)/m
256
+ etag_reg = /(.*?)(%%>|-%>|%>|\z)/m
257
+ scanner = StringScanner.new(@src)
258
+ while ! scanner.eos?
259
+ scanner.scan(@stag ? etag_reg : stag_reg)
260
+ yield(scanner[1])
261
+
262
+ elem = scanner[2]
263
+ if /[ \t]*<%-/ =~ elem
264
+ yield('<%')
265
+ elsif elem == '-%>'
266
+ yield('%>')
267
+ yield(:cr) if scanner.scan(/(\n|\z)/)
268
+ else
269
+ yield(elem)
270
+ end
271
+ end
272
+ end
273
+ end
274
+ Scanner.regist_scanner(ExplicitScanner, '-', false)
275
+
276
+ rescue LoadError
277
+ end
278
+
279
+ class Buffer # :nodoc:
280
+ def initialize(compiler, enc=nil)
281
+ @compiler = compiler
282
+ @line = []
283
+ @script = enc ? "#coding:#{enc.to_s}\n" : ""
284
+ @compiler.pre_cmd.each do |x|
285
+ push(x)
286
+ end
287
+ end
288
+ attr_reader :script
289
+
290
+ def push(cmd)
291
+ @line << cmd
292
+ end
293
+
294
+ def cr
295
+ @script << (@line.join('; '))
296
+ @line = []
297
+ @script << "\n"
298
+ end
299
+
300
+ def close
301
+ return unless @line
302
+ @compiler.post_cmd.each do |x|
303
+ push(x)
304
+ end
305
+ @script << (@line.join('; '))
306
+ @line = nil
307
+ end
308
+ end
309
+
310
+ def content_dump(s) # :nodoc:
311
+ n = s.count("\n")
312
+ if n > 0
313
+ s.dump + "\n" * n
314
+ else
315
+ s.dump
316
+ end
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
+ out = Buffer.new(self)
323
+ content = ''
324
+ scanner = make_scanner(s)
325
+ scanner.scan do |token|
326
+ next if token.nil?
327
+ next if token == ''
328
+ if scanner.stag.nil?
329
+ case token
330
+ when PercentLine
331
+ out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
332
+ content = ''
333
+ out.push(token.to_s)
334
+ out.cr
335
+ when :cr
336
+ out.cr
337
+ when '<%', '<%=', '<%#'
338
+ scanner.stag = token
339
+ out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
340
+ content = ''
341
+ when "\n"
342
+ content << "\n"
343
+ out.push("#{@put_cmd} #{content_dump(content)}")
344
+ content = ''
345
+ when '<%%'
346
+ content << '<%'
347
+ else
348
+ content << token
349
+ end
350
+ else
351
+ case token
352
+ when '%>'
353
+ case scanner.stag
354
+ when '<%'
355
+ if content[-1] == ?\n
356
+ content.chop!
357
+ out.push(content)
358
+ out.cr
359
+ else
360
+ out.push(content)
361
+ end
362
+ when '<%='
363
+ out.push("#{@insert_cmd}((#{content}).to_s)")
364
+ when '<%#'
365
+ # out.push("# #{content_dump(content)}")
366
+ end
367
+ scanner.stag = nil
368
+ content = ''
369
+ when '%%>'
370
+ content << '%>'
371
+ else
372
+ content << token
373
+ end
374
+ end
375
+ end
376
+ out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
377
+ out.close
378
+ return out.script
379
+ end
380
+
381
+ def prepare_trim_mode(mode) # :nodoc:
382
+ case mode
383
+ when 1
384
+ return [false, '>']
385
+ when 2
386
+ return [false, '<>']
387
+ when 0
388
+ return [false, nil]
389
+ when String
390
+ perc = mode.include?('%')
391
+ if mode.include?('-')
392
+ return [perc, '-']
393
+ elsif mode.include?('<>')
394
+ return [perc, '<>']
395
+ elsif mode.include?('>')
396
+ return [perc, '>']
397
+ else
398
+ [perc, nil]
399
+ end
400
+ else
401
+ return [false, nil]
402
+ end
403
+ end
404
+
405
+ def make_scanner(src) # :nodoc:
406
+ Scanner.make_scanner(src, @trim_mode, @percent)
407
+ end
408
+
409
+ # Construct a new compiler using the trim_mode. See ERB#new for available
410
+ # trim modes.
411
+ def initialize(trim_mode)
412
+ @percent, @trim_mode = prepare_trim_mode(trim_mode)
413
+ @put_cmd = 'print'
414
+ @insert_cmd = @put_cmd
415
+ @pre_cmd = []
416
+ @post_cmd = []
417
+ end
418
+ attr_reader :percent, :trim_mode
419
+
420
+ # The command to handle text that ends with a newline
421
+ attr_accessor :put_cmd
422
+
423
+ # The command to handle text that is inserted prior to a newline
424
+ attr_accessor :insert_cmd
425
+
426
+ # An array of commands prepended to compiled code
427
+ attr_accessor :pre_cmd
428
+
429
+ # An array of commands appended to compiled code
430
+ attr_accessor :post_cmd
431
+
432
+ private
433
+ def detect_magic_comment(s)
434
+ if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s)
435
+ comment = $1
436
+ comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/]
437
+ if %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" =~ comment
438
+ enc = $1.sub(/-(?:mac|dos|unix)/i, '')
439
+ enc = Encoding.find(enc)
440
+ end
441
+ end
442
+ end
443
+ end
444
+ end
445
+
446
+ #--
447
+ # ERB
448
+ class ERB
449
+ #
450
+ # Constructs a new ERB object with the template specified in _str_.
451
+ #
452
+ # An ERB object works by building a chunk of Ruby code that will output
453
+ # the completed template when run. If _safe_level_ is set to a non-nil value,
454
+ # ERB code will be run in a separate thread with <b>$SAFE</b> set to the
455
+ # provided level.
456
+ #
457
+ # If _trim_mode_ is passed a String containing one or more of the following
458
+ # modifiers, ERB will adjust its code generation as listed:
459
+ #
460
+ # % enables Ruby code processing for lines beginning with %
461
+ # <> omit newline for lines starting with <% and ending in %>
462
+ # > omit newline for lines ending in %>
463
+ #
464
+ # _eoutvar_ can be used to set the name of the variable ERB will build up
465
+ # its output in. This is useful when you need to run multiple ERB
466
+ # templates through the same binding and/or when you want to control where
467
+ # output ends up. Pass the name of the variable to be used inside a String.
468
+ #
469
+ # === Example
470
+ #
471
+ # require "erb"
472
+ #
473
+ # # build data class
474
+ # class Listings
475
+ # PRODUCT = { :name => "Chicken Fried Steak",
476
+ # :desc => "A well messages pattie, breaded and fried.",
477
+ # :cost => 9.95 }
478
+ #
479
+ # attr_reader :product, :price
480
+ #
481
+ # def initialize( product = "", price = "" )
482
+ # @product = product
483
+ # @price = price
484
+ # end
485
+ #
486
+ # def build
487
+ # b = binding
488
+ # # create and run templates, filling member data variables
489
+ # ERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), 0, "", "@product").result b
490
+ # <%= PRODUCT[:name] %>
491
+ # <%= PRODUCT[:desc] %>
492
+ # END_PRODUCT
493
+ # ERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), 0, "", "@price").result b
494
+ # <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %>
495
+ # <%= PRODUCT[:desc] %>
496
+ # END_PRICE
497
+ # end
498
+ # end
499
+ #
500
+ # # setup template data
501
+ # listings = Listings.new
502
+ # listings.build
503
+ #
504
+ # puts listings.product + "\n" + listings.price
505
+ #
506
+ # _Generates_
507
+ #
508
+ # Chicken Fried Steak
509
+ # A well messages pattie, breaded and fried.
510
+ #
511
+ # Chicken Fried Steak -- 9.95
512
+ # A well messages pattie, breaded and fried.
513
+ #
514
+ def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
515
+ @safe_level = safe_level
516
+ compiler = ERB::Compiler.new(trim_mode)
517
+ set_eoutvar(compiler, eoutvar)
518
+ *@src = *compiler.compile(str)
519
+ @src.push(";" + eoutvar)
520
+ @src = @src.join
521
+ @filename = nil
522
+ end
523
+
524
+ # The Ruby code generated by ERB
525
+ attr_reader :src
526
+
527
+ # The optional _filename_ argument passed to Kernel#eval when the ERB code
528
+ # is run
529
+ attr_accessor :filename
530
+
531
+ #
532
+ # Can be used to set _eoutvar_ as described in ERB#new. It's probably easier
533
+ # to just use the constructor though, since calling this method requires the
534
+ # setup of an ERB _compiler_ object.
535
+ #
536
+ def set_eoutvar(compiler, eoutvar = '_erbout')
537
+ compiler.put_cmd = "#{eoutvar}.concat"
538
+ compiler.insert_cmd = "#{eoutvar}.concat"
539
+
540
+ cmd = []
541
+ cmd.push "#{eoutvar} = ''"
542
+
543
+ compiler.pre_cmd = cmd
544
+
545
+ cmd = []
546
+
547
+ compiler.post_cmd = cmd
548
+ end
549
+
550
+ # Generate results and print them. (see ERB#result)
551
+ def run(b=TOPLEVEL_BINDING)
552
+ print self.result(b)
553
+ end
554
+
555
+ #
556
+ # Executes the generated ERB code to produce a completed template, returning
557
+ # the results of that code. (See ERB#new for details on how this process can
558
+ # be affected by _safe_level_.)
559
+ #
560
+ # _b_ accepts a Binding or Proc object which is used to set the context of
561
+ # code evaluation.
562
+ #
563
+ def result(b=TOPLEVEL_BINDING)
564
+ if @safe_level
565
+ proc {
566
+ $SAFE = @safe_level
567
+ eval(@src, b, (@filename || '(erb)'), 0)
568
+ }.call
569
+ else
570
+ eval(@src, b, (@filename || '(erb)'), 0)
571
+ end
572
+ end
573
+
574
+ # Define _methodname_ as instance method of _mod_ from compiled ruby source.
575
+ #
576
+ # example:
577
+ # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
578
+ # erb = ERB.new(File.read(filename))
579
+ # erb.def_method(MyClass, 'render(arg1, arg2)', filename)
580
+ # print MyClass.new.render('foo', 123)
581
+ def def_method(mod, methodname, fname='(ERB)')
582
+ src = self.src
583
+ magic_comment = "#coding:#{@enc}\n"
584
+ mod.module_eval do
585
+ eval(magic_comment + "def #{methodname}\n" + src + "\nend\n", binding, fname, -2)
586
+ end
587
+ end
588
+
589
+ # Create unnamed module, define _methodname_ as instance method of it, and return it.
590
+ #
591
+ # example:
592
+ # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
593
+ # erb = ERB.new(File.read(filename))
594
+ # erb.filename = filename
595
+ # MyModule = erb.def_module('render(arg1, arg2)')
596
+ # class MyClass
597
+ # include MyModule
598
+ # end
599
+ def def_module(methodname='erb')
600
+ mod = Module.new
601
+ def_method(mod, methodname, @filename || '(ERB)')
602
+ mod
603
+ end
604
+
605
+ # Define unnamed class which has _methodname_ as instance method, and return it.
606
+ #
607
+ # example:
608
+ # class MyClass_
609
+ # def initialize(arg1, arg2)
610
+ # @arg1 = arg1; @arg2 = arg2
611
+ # end
612
+ # end
613
+ # filename = 'example.rhtml' # @arg1 and @arg2 are used in example.rhtml
614
+ # erb = ERB.new(File.read(filename))
615
+ # erb.filename = filename
616
+ # MyClass = erb.def_class(MyClass_, 'render()')
617
+ # print MyClass.new('foo', 123).render()
618
+ def def_class(superklass=Object, methodname='result')
619
+ cls = Class.new(superklass)
620
+ def_method(cls, methodname, @filename || '(ERB)')
621
+ cls
622
+ end
623
+ end
624
+
625
+ #--
626
+ # ERB::Util
627
+ class ERB
628
+ # A utility module for conversion routines, often handy in HTML generation.
629
+ module Util
630
+ public
631
+ #
632
+ # A utility method for escaping HTML tag characters in _s_.
633
+ #
634
+ # require "erb"
635
+ # include ERB::Util
636
+ #
637
+ # puts html_escape("is a > 0 & a < 10?")
638
+ #
639
+ # _Generates_
640
+ #
641
+ # is a &gt; 0 &amp; a &lt; 10?
642
+ #
643
+ def html_escape(s)
644
+ s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
645
+ end
646
+ alias h html_escape
647
+ module_function :h
648
+ module_function :html_escape
649
+
650
+ #
651
+ # A utility method for encoding the String _s_ as a URL.
652
+ #
653
+ # require "erb"
654
+ # include ERB::Util
655
+ #
656
+ # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
657
+ #
658
+ # _Generates_
659
+ #
660
+ # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
661
+ #
662
+ def url_encode(s)
663
+ s.to_s.dup.force_encoding("ASCII-8BIT").gsub(/[^a-zA-Z0-9_\-.]/n) {
664
+ sprintf("%%%02X", $&.unpack("C")[0])
665
+ }
666
+ end
667
+ alias u url_encode
668
+ module_function :u
669
+ module_function :url_encode
670
+ end
671
+ end
672
+
673
+ #--
674
+ # ERB::DefMethod
675
+ class ERB
676
+ # Utility module to define eRuby script as instance method.
677
+ #
678
+ # === Example
679
+ #
680
+ # example.rhtml:
681
+ # <% for item in @items %>
682
+ # <b><%= item %></b>
683
+ # <% end %>
684
+ #
685
+ # example.rb:
686
+ # require 'erb'
687
+ # class MyClass
688
+ # extend ERB::DefMethod
689
+ # def_erb_method('render()', 'example.rhtml')
690
+ # def initialize(items)
691
+ # @items = items
692
+ # end
693
+ # end
694
+ # print MyClass.new([10,20,30]).render()
695
+ #
696
+ # result:
697
+ #
698
+ # <b>10</b>
699
+ #
700
+ # <b>20</b>
701
+ #
702
+ # <b>30</b>
703
+ #
704
+ module DefMethod
705
+ public
706
+ # define _methodname_ as instance method of current module, using ERB
707
+ # object or eRuby file
708
+ def def_erb_method(methodname, erb_or_fname)
709
+ if erb_or_fname.kind_of? String
710
+ fname = erb_or_fname
711
+ erb = ERB.new(File.read(fname))
712
+ erb.def_method(self, methodname, fname)
713
+ else
714
+ erb = erb_or_fname
715
+ erb.def_method(self, methodname, erb.filename || '(ERB)')
716
+ end
717
+ end
718
+ module_function :def_erb_method
719
+ end
720
+ end