ua 0.0.1

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,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