erubis 2.6.2 → 2.6.3

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.
Files changed (117) hide show
  1. data/CHANGES.txt +16 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.txt +2 -2
  4. data/benchmark/bench.rb +2 -2
  5. data/bin/erubis +4 -4
  6. data/contrib/erubis +3349 -5
  7. data/contrib/inline-require +2 -2
  8. data/doc-api/classes/Erubis.html +1 -1
  9. data/doc-api/classes/Erubis/ArrayEnhancer.html +12 -12
  10. data/doc-api/classes/Erubis/Basic/Converter.html +24 -24
  11. data/doc-api/classes/Erubis/BiPatternEnhancer.html +12 -12
  12. data/doc-api/classes/Erubis/CGenerator.html +60 -60
  13. data/doc-api/classes/Erubis/Converter.html +27 -27
  14. data/doc-api/classes/Erubis/DeleteIndentEnhancer.html +6 -6
  15. data/doc-api/classes/Erubis/ErboutEnhancer.html +12 -12
  16. data/doc-api/classes/Erubis/EscapeEnhancer.html +6 -6
  17. data/doc-api/classes/Erubis/Evaluator.html +19 -19
  18. data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +12 -12
  19. data/doc-api/classes/Erubis/Helpers/RailsFormHelper.html +150 -150
  20. data/doc-api/classes/Erubis/Helpers/RailsHelper.html +49 -49
  21. data/doc-api/classes/Erubis/Helpers/RailsHelper/TemplateConverter.html +12 -12
  22. data/doc-api/classes/Erubis/InterpolationEnhancer.html +30 -30
  23. data/doc-api/classes/Erubis/JavaGenerator.html +54 -54
  24. data/doc-api/classes/Erubis/JavascriptGenerator.html +60 -60
  25. data/doc-api/classes/Erubis/NoTextEnhancer.html +6 -6
  26. data/doc-api/classes/Erubis/OptimizedGenerator.html +72 -72
  27. data/doc-api/classes/Erubis/PI/Ec.html +6 -6
  28. data/doc-api/classes/Erubis/PI/Ejavascript.html +6 -6
  29. data/doc-api/classes/Erubis/PI/Eperl.html +6 -6
  30. data/doc-api/classes/Erubis/PI/Ephp.html +6 -6
  31. data/doc-api/classes/Erubis/PI/Eruby.html +6 -6
  32. data/doc-api/classes/Erubis/PI/Escheme.html +6 -6
  33. data/doc-api/classes/Erubis/PI/TinyEruby.html +24 -24
  34. data/doc-api/classes/Erubis/PercentLineEnhancer.html +6 -6
  35. data/doc-api/classes/Erubis/PerlGenerator.html +54 -54
  36. data/doc-api/classes/Erubis/PhpGenerator.html +54 -54
  37. data/doc-api/classes/Erubis/PreprocessingEruby.html +12 -12
  38. data/doc-api/classes/Erubis/PreprocessingHelper.html +22 -22
  39. data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +20 -20
  40. data/doc-api/classes/Erubis/PrintOutEnhancer.html +30 -30
  41. data/doc-api/classes/Erubis/RubyEvaluator.html +18 -18
  42. data/doc-api/classes/Erubis/RubyGenerator.html +48 -48
  43. data/doc-api/classes/Erubis/SchemeGenerator.html +60 -60
  44. data/doc-api/classes/Erubis/SimplifyEnhancer.html +7 -7
  45. data/doc-api/classes/Erubis/StdoutEnhancer.html +12 -12
  46. data/doc-api/classes/Erubis/StringBufferEnhancer.html +12 -12
  47. data/doc-api/classes/Erubis/TinyEruby.html +24 -24
  48. data/doc-api/classes/Erubis/XmlHelper.html +30 -30
  49. data/doc-api/created.rid +1 -1
  50. data/doc-api/files/README_txt.html +3 -3
  51. data/doc-api/files/erubis/context_rb.html +1 -1
  52. data/doc-api/files/erubis/converter_rb.html +1 -1
  53. data/doc-api/files/erubis/engine/ec_rb.html +1 -1
  54. data/doc-api/files/erubis/engine/ejava_rb.html +1 -1
  55. data/doc-api/files/erubis/engine/ejavascript_rb.html +1 -1
  56. data/doc-api/files/erubis/engine/enhanced_rb.html +1 -1
  57. data/doc-api/files/erubis/engine/eperl_rb.html +1 -1
  58. data/doc-api/files/erubis/engine/ephp_rb.html +1 -1
  59. data/doc-api/files/erubis/engine/eruby_rb.html +1 -1
  60. data/doc-api/files/erubis/engine/escheme_rb.html +1 -1
  61. data/doc-api/files/erubis/engine/optimized_rb.html +1 -1
  62. data/doc-api/files/erubis/engine_rb.html +1 -1
  63. data/doc-api/files/erubis/enhancer_rb.html +1 -1
  64. data/doc-api/files/erubis/error_rb.html +1 -1
  65. data/doc-api/files/erubis/evaluator_rb.html +1 -1
  66. data/doc-api/files/erubis/generator_rb.html +1 -1
  67. data/doc-api/files/erubis/helper_rb.html +1 -1
  68. data/doc-api/files/erubis/helpers/rails_form_helper_rb.html +1 -1
  69. data/doc-api/files/erubis/helpers/rails_helper_rb.html +1 -1
  70. data/doc-api/files/erubis/local-setting_rb.html +1 -1
  71. data/doc-api/files/erubis/main_rb.html +2 -2
  72. data/doc-api/files/erubis/preprocessing_rb.html +1 -1
  73. data/doc-api/files/erubis/tiny_rb.html +1 -1
  74. data/doc-api/files/erubis_rb.html +1 -1
  75. data/doc-api/fr_method_index.html +188 -188
  76. data/doc/users-guide.html +5 -5
  77. data/lib/erubis.rb +3 -3
  78. data/lib/erubis/context.rb +2 -2
  79. data/lib/erubis/converter.rb +2 -2
  80. data/lib/erubis/engine.rb +2 -2
  81. data/lib/erubis/engine/ec.rb +2 -2
  82. data/lib/erubis/engine/ejava.rb +2 -2
  83. data/lib/erubis/engine/ejavascript.rb +2 -2
  84. data/lib/erubis/engine/enhanced.rb +2 -2
  85. data/lib/erubis/engine/eperl.rb +2 -2
  86. data/lib/erubis/engine/ephp.rb +2 -2
  87. data/lib/erubis/engine/eruby.rb +2 -2
  88. data/lib/erubis/engine/escheme.rb +2 -2
  89. data/lib/erubis/engine/optimized.rb +2 -2
  90. data/lib/erubis/enhancer.rb +2 -2
  91. data/lib/erubis/error.rb +2 -2
  92. data/lib/erubis/evaluator.rb +2 -2
  93. data/lib/erubis/generator.rb +2 -2
  94. data/lib/erubis/helper.rb +2 -2
  95. data/lib/erubis/helpers/rails_form_helper.rb +2 -2
  96. data/lib/erubis/helpers/rails_helper.rb +2 -2
  97. data/lib/erubis/local-setting.rb +2 -2
  98. data/lib/erubis/main.rb +8 -7
  99. data/lib/erubis/preprocessing.rb +2 -2
  100. data/lib/erubis/tiny.rb +2 -2
  101. data/test/assert-text-equal.rb +2 -2
  102. data/test/data/users-guide/stderr.log +3 -0
  103. data/test/test-engines.rb +2 -2
  104. data/test/test-enhancers.rb +2 -2
  105. data/test/test-erubis.rb +2 -2
  106. data/test/test-main.rb +43 -16
  107. data/test/test-users-guide.rb +2 -2
  108. data/test/test.rb +2 -2
  109. data/test/testutil.rb +2 -2
  110. metadata +5 -10
  111. data/test/assert-text-equal.rbc +0 -0
  112. data/test/hoge.rb +0 -5
  113. data/test/test-engines.rbc +0 -0
  114. data/test/test-erubis.rbc +0 -0
  115. data/test/test-users-guide.rbc +0 -0
  116. data/test/test.rbc +0 -0
  117. data/test/testutil.rbc +0 -0
@@ -1,7 +1,19 @@
1
1
  # -*- coding: utf-8 -*-
2
- # $Rev: 118 $
3
- # $Release: 2.6.2 $
4
- # copyright(c) 2006-2008 kuwata-lab.com all rights reserved.
2
+ # $Rev: 123 $
3
+ # $Release: 2.6.3 $
4
+ # copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
5
+
6
+
7
+ - release: 2.6.3
8
+ date: 2009-02-07
9
+ bugfixes:
10
+
11
+ - Enhancer name was not displayed in Ruby 1.9.1 when it was missing.
12
+
13
+ - Command option argument name was not displayed correctly as a part of error message.
14
+
15
+ - MethoNotFound error was raised when invalid option was specified.
16
+
5
17
 
6
18
  - release: 2.6.2
7
19
  date: 2008-06-12
@@ -13,8 +25,7 @@
13
25
  bugfixes:
14
26
 
15
27
  - |
16
- Fixed a bug that it is not able to install Erubis on windows
17
- (Thanks to Tim Morgan and Allen).
28
+ Fixed installation problem on Windows (Thanks to Tim Morgan and Allen).
18
29
 
19
30
 
20
31
  - release: 2.6.1
@@ -1,4 +1,4 @@
1
- copyright(c) 2006-2008 kuwata-lab.com all rights reserved.
1
+ copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  = README
2
2
 
3
- release:: 2.6.2
4
- copyright:: copyright(c) 2006-2008 kuwata-lab.com all rights reserved.
3
+ release:: 2.6.3
4
+ copyright:: copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
5
5
 
6
6
 
7
7
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  ###
4
4
  ### $Rev: 101 $
5
- ### $Release: 2.6.2 $
6
- ### copyright(c) 2006-2008 kuwata-lab.com all rights reserved.
5
+ ### $Release: 2.6.3 $
6
+ ### copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
7
7
  ###
8
8
 
9
9
  require 'erb'
data/bin/erubis CHANGED
@@ -1,9 +1,9 @@
1
- #!/usr/bin/ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  ###
4
- ### $Rev: 77 $
5
- ### $Release: 2.6.2 $
6
- ### copyright(c) 2006-2008 kuwata-lab.com all rights reserved.
4
+ ### $Rev: 121 $
5
+ ### $Release: 2.6.3 $
6
+ ### copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
7
7
  ###
8
8
 
9
9
  require 'erubis/main'
@@ -1,11 +1,3355 @@
1
- #!/usr/bin/ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  ###
4
- ### $Rev: 77 $
5
- ### $Release: 2.6.2 $
6
- ### copyright(c) 2006-2008 kuwata-lab.com all rights reserved.
4
+ ### $Rev: 121 $
5
+ ### $Release: 2.6.3 $
6
+ ### copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
7
7
  ###
8
8
 
9
- require 'erubis/main'
9
+ #--begin of require 'erubis/main'
10
+ ###
11
+ ### $Rev: 122 $
12
+ ### $Release: 2.6.3 $
13
+ ### copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
14
+ ###
15
+
16
+ require 'yaml'
17
+ #--begin of require 'erubis'
18
+ ##
19
+ ## $Rev: 99 $
20
+ ## $Release: 2.6.3 $
21
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
22
+ ##
23
+
24
+ ##
25
+ ## an implementation of eRuby
26
+ ##
27
+ ## ex.
28
+ ## input = <<'END'
29
+ ## <ul>
30
+ ## <% for item in @list %>
31
+ ## <li><%= item %>
32
+ ## <%== item %></li>
33
+ ## <% end %>
34
+ ## </ul>
35
+ ## END
36
+ ## list = ['<aaa>', 'b&b', '"ccc"']
37
+ ## eruby = Erubis::Eruby.new(input)
38
+ ## puts "--- code ---"
39
+ ## puts eruby.src
40
+ ## puts "--- result ---"
41
+ ## context = Erubis::Context.new() # or new(:list=>list)
42
+ ## context[:list] = list
43
+ ## puts eruby.evaluate(context)
44
+ ##
45
+ ## result:
46
+ ## --- source ---
47
+ ## _buf = ''; _buf << '<ul>
48
+ ## '; for item in @list
49
+ ## _buf << ' <li>'; _buf << ( item ).to_s; _buf << '
50
+ ## '; _buf << ' '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</li>
51
+ ## '; end
52
+ ## _buf << '</ul>
53
+ ## ';
54
+ ## _buf.to_s
55
+ ## --- result ---
56
+ ## <ul>
57
+ ## <li><aaa>
58
+ ## &lt;aaa&gt;</li>
59
+ ## <li>b&b
60
+ ## b&amp;b</li>
61
+ ## <li>"ccc"
62
+ ## &quot;ccc&quot;</li>
63
+ ## </ul>
64
+ ##
65
+
66
+
67
+ module Erubis
68
+ VERSION = ('$Release: 2.6.3 $' =~ /([.\d]+)/) && $1
69
+ end
70
+
71
+ #--begin of require 'erubis/engine'
72
+ ##
73
+ ## $Rev: 104 $
74
+ ## $Release: 2.6.3 $
75
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
76
+ ##
77
+
78
+
79
+ #--begin of require 'erubis/generator'
80
+ ##
81
+ ## $Rev: 77 $
82
+ ## $Release: 2.6.3 $
83
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
84
+ ##
85
+
86
+ #--begin of require 'abstract'
87
+ ##
88
+ ## $Rev: 1 $
89
+ ## $Release: 0.1.0 $
90
+ ## copyright(c) 2006 kuwata-lab.com all rights reserved.
91
+ ##
92
+ ##
93
+ ## helper to define abstract method in Ruby.
94
+ ##
95
+ ##
96
+ ## example1. (shorter notation)
97
+ ##
98
+ ## require 'abstract'
99
+ ## class Foo
100
+ ## abstract_method 'arg1, arg2=""', :method1, :method2, :method3
101
+ ## end
102
+ ##
103
+ ##
104
+ ## example2. (RDoc friendly notation)
105
+ ##
106
+ ## require 'abstract'
107
+ ## class Bar
108
+ ## # ... method1 description ...
109
+ ## def method1(arg1, arg2="")
110
+ ## not_implemented
111
+ ## end
112
+ ##
113
+ ## # ... method2 description ...
114
+ ## def method2(arg1, arg2="")
115
+ ## not_implemented
116
+ ## end
117
+ ## end
118
+ ##
119
+
120
+
121
+ ##
122
+ class Module
123
+
124
+ ##
125
+ ## define abstract methods
126
+ ##
127
+ def abstract_method args_str, *method_names
128
+ method_names.each do |name|
129
+ module_eval <<-END
130
+ def #{name}(#{args_str})
131
+ mesg = "class \#{self.class.name} must implement abstract method `#{self.name}##{name}()'."
132
+ #mesg = "\#{self.class.name}##{name}() is not implemented."
133
+ err = NotImplementedError.new mesg
134
+ err.set_backtrace caller()
135
+ raise err
136
+ end
137
+ END
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+
144
+ ##
145
+ module Kernel
146
+
147
+ ##
148
+ ## raise NotImplementedError
149
+ ##
150
+ def not_implemented #:doc:
151
+ backtrace = caller()
152
+ method_name = (backtrace.shift =~ /`(\w+)'$/) && $1
153
+ mesg = "class #{self.class.name} must implement abstract method '#{method_name}()'."
154
+ #mesg = "#{self.class.name}##{method_name}() is not implemented."
155
+ err = NotImplementedError.new mesg
156
+ err.set_backtrace backtrace
157
+ raise err
158
+ end
159
+ private :not_implemented
160
+
161
+ end
162
+ #--end of require 'abstract'
163
+
164
+ module Erubis
165
+
166
+
167
+ ##
168
+ ## code generator, called by Converter module
169
+ ##
170
+ module Generator
171
+
172
+ def self.supported_properties() # :nodoc:
173
+ return [
174
+ [:escapefunc, nil, "escape function name"],
175
+ ]
176
+ end
177
+
178
+ attr_accessor :escapefunc
179
+
180
+ def init_generator(properties={})
181
+ @escapefunc = properties[:escapefunc]
182
+ end
183
+
184
+
185
+ ## (abstract) escape text string
186
+ ##
187
+ ## ex.
188
+ ## def escape_text(text)
189
+ ## return text.dump
190
+ ## # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'"
191
+ ## end
192
+ def escape_text(text)
193
+ not_implemented
194
+ end
195
+
196
+ ## return escaped expression code (ex. 'h(...)' or 'htmlspecialchars(...)')
197
+ def escaped_expr(code)
198
+ code.strip!
199
+ return "#{@escapefunc}(#{code})"
200
+ end
201
+
202
+ ## (abstract) add @preamble to src
203
+ def add_preamble(src)
204
+ not_implemented
205
+ end
206
+
207
+ ## (abstract) add text string to src
208
+ def add_text(src, text)
209
+ not_implemented
210
+ end
211
+
212
+ ## (abstract) add statement code to src
213
+ def add_stmt(src, code)
214
+ not_implemented
215
+ end
216
+
217
+ ## (abstract) add expression literal code to src. this is called by add_expr().
218
+ def add_expr_literal(src, code)
219
+ not_implemented
220
+ end
221
+
222
+ ## (abstract) add escaped expression code to src. this is called by add_expr().
223
+ def add_expr_escaped(src, code)
224
+ not_implemented
225
+ end
226
+
227
+ ## (abstract) add expression code to src for debug. this is called by add_expr().
228
+ def add_expr_debug(src, code)
229
+ not_implemented
230
+ end
231
+
232
+ ## (abstract) add @postamble to src
233
+ def add_postamble(src)
234
+ not_implemented
235
+ end
236
+
237
+
238
+ end
239
+
240
+
241
+ end
242
+ #--end of require 'erubis/generator'
243
+ #--begin of require 'erubis/converter'
244
+ ##
245
+ ## $Rev: 115 $
246
+ ## $Release: 2.6.3 $
247
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
248
+ ##
249
+
250
+ #--already included require 'abstract'
251
+
252
+ module Erubis
253
+
254
+
255
+ ##
256
+ ## convert
257
+ ##
258
+ module Converter
259
+
260
+ attr_accessor :preamble, :postamble, :escape
261
+
262
+ def self.supported_properties # :nodoc:
263
+ return [
264
+ [:preamble, nil, "preamble (no preamble when false)"],
265
+ [:postamble, nil, "postamble (no postamble when false)"],
266
+ [:escape, nil, "escape expression or not in default"],
267
+ ]
268
+ end
269
+
270
+ def init_converter(properties={})
271
+ @preamble = properties[:preamble]
272
+ @postamble = properties[:postamble]
273
+ @escape = properties[:escape]
274
+ end
275
+
276
+ ## convert input string into target language
277
+ def convert(input)
278
+ codebuf = "" # or []
279
+ @preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble))
280
+ convert_input(codebuf, input)
281
+ @postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble))
282
+ @_proc = nil # clear cached proc object
283
+ return codebuf # or codebuf.join()
284
+ end
285
+
286
+ protected
287
+
288
+ ##
289
+ ## detect spaces at beginning of line
290
+ ##
291
+ def detect_spaces_at_bol(text, is_bol)
292
+ lspace = nil
293
+ if text.empty?
294
+ lspace = "" if is_bol
295
+ elsif text[-1] == ?\n
296
+ lspace = ""
297
+ else
298
+ rindex = text.rindex(?\n)
299
+ if rindex
300
+ s = text[rindex+1..-1]
301
+ if s =~ /\A[ \t]*\z/
302
+ lspace = s
303
+ #text = text[0..rindex]
304
+ text[rindex+1..-1] = ''
305
+ end
306
+ else
307
+ if is_bol && text =~ /\A[ \t]*\z/
308
+ #lspace = text
309
+ #text = nil
310
+ lspace = text.dup
311
+ text[0..-1] = ''
312
+ end
313
+ end
314
+ end
315
+ return lspace
316
+ end
317
+
318
+ ##
319
+ ## (abstract) convert input to code
320
+ ##
321
+ def convert_input(codebuf, input)
322
+ not_implemented
323
+ end
324
+
325
+ end
326
+
327
+
328
+ module Basic
329
+ end
330
+
331
+
332
+ ##
333
+ ## basic converter which supports '<% ... %>' notation.
334
+ ##
335
+ module Basic::Converter
336
+ include Erubis::Converter
337
+
338
+ def self.supported_properties # :nodoc:
339
+ return [
340
+ [:pattern, '<% %>', "embed pattern"],
341
+ [:trim, true, "trim spaces around <% ... %>"],
342
+ ]
343
+ end
344
+
345
+ attr_accessor :pattern, :trim
346
+
347
+ def init_converter(properties={})
348
+ super(properties)
349
+ @pattern = properties[:pattern]
350
+ @trim = properties[:trim] != false
351
+ end
352
+
353
+ protected
354
+
355
+ ## return regexp of pattern to parse eRuby script
356
+ def pattern_regexp(pattern)
357
+ @prefix, @postfix = pattern.split() # '<% %>' => '<%', '%>'
358
+ #return /(.*?)(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m
359
+ #return /(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m
360
+ return /#{@prefix}(=+|-|\#|%)?(.*?)([-=])?#{@postfix}([ \t]*\r?\n)?/m
361
+ end
362
+ module_function :pattern_regexp
363
+
364
+ #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
365
+ #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
366
+ #DEFAULT_REGEXP = /<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
367
+ DEFAULT_REGEXP = pattern_regexp('<% %>')
368
+
369
+ public
370
+
371
+ def convert_input(src, input)
372
+ pat = @pattern
373
+ regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat)
374
+ pos = 0
375
+ is_bol = true # is beginning of line
376
+ input.scan(regexp) do |indicator, code, tailch, rspace|
377
+ match = Regexp.last_match()
378
+ len = match.begin(0) - pos
379
+ text = input[pos, len]
380
+ pos = match.end(0)
381
+ ch = indicator ? indicator[0] : nil
382
+ lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
383
+ is_bol = rspace ? true : false
384
+ add_text(src, text) if text && !text.empty?
385
+ ## * when '<%= %>', do nothing
386
+ ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
387
+ if ch == ?= # <%= %>
388
+ rspace = nil if tailch && !tailch.empty?
389
+ add_text(src, lspace) if lspace
390
+ add_expr(src, code, indicator)
391
+ add_text(src, rspace) if rspace
392
+ elsif ch == ?\# # <%# %>
393
+ n = code.count("\n") + (rspace ? 1 : 0)
394
+ if @trim && lspace && rspace
395
+ add_stmt(src, "\n" * n)
396
+ else
397
+ add_text(src, lspace) if lspace
398
+ add_stmt(src, "\n" * n)
399
+ add_text(src, rspace) if rspace
400
+ end
401
+ elsif ch == ?% # <%% %>
402
+ s = "#{lspace}#{@prefix||='<%'}#{code}#{tailch}#{@postfix||='%>'}#{rspace}"
403
+ add_text(src, s)
404
+ else # <% %>
405
+ if @trim && lspace && rspace
406
+ add_stmt(src, "#{lspace}#{code}#{rspace}")
407
+ else
408
+ add_text(src, lspace) if lspace
409
+ add_stmt(src, code)
410
+ add_text(src, rspace) if rspace
411
+ end
412
+ end
413
+ end
414
+ #rest = $' || input # ruby1.8
415
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
416
+ add_text(src, rest)
417
+ end
418
+
419
+ ## add expression code to src
420
+ def add_expr(src, code, indicator)
421
+ case indicator
422
+ when '='
423
+ @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
424
+ when '=='
425
+ @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
426
+ when '==='
427
+ add_expr_debug(src, code)
428
+ end
429
+ end
430
+
431
+ end
432
+
433
+
434
+ module PI
435
+ end
436
+
437
+ ##
438
+ ## Processing Instructions (PI) converter for XML.
439
+ ## this class converts '<?rb ... ?>' and '${...}' notation.
440
+ ##
441
+ module PI::Converter
442
+ include Erubis::Converter
443
+
444
+ def self.desc # :nodoc:
445
+ "use processing instructions (PI) instead of '<% %>'"
446
+ end
447
+
448
+ def self.supported_properties # :nodoc:
449
+ return [
450
+ [:trim, true, "trim spaces around <% ... %>"],
451
+ [:pi, 'rb', "PI (Processing Instrunctions) name"],
452
+ [:embchar, '@', "char for embedded expression pattern('@{...}@')"],
453
+ [:pattern, '<% %>', "embed pattern"],
454
+ ]
455
+ end
456
+
457
+ attr_accessor :pi, :prefix
458
+
459
+ def init_converter(properties={})
460
+ super(properties)
461
+ @trim = properties.fetch(:trim, true)
462
+ @pi = properties[:pi] if properties[:pi]
463
+ @embchar = properties[:embchar] || '@'
464
+ @pattern = properties[:pattern]
465
+ @pattern = '<% %>' if @pattern.nil? #|| @pattern == true
466
+ end
467
+
468
+ def convert(input)
469
+ code = super(input)
470
+ return @header || @footer ? "#{@header}#{code}#{@footer}" : code
471
+ end
472
+
473
+ protected
474
+
475
+ def convert_input(codebuf, input)
476
+ unless @regexp
477
+ @pi ||= 'e'
478
+ ch = Regexp.escape(@embchar)
479
+ if @pattern
480
+ left, right = @pattern.split(' ')
481
+ @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
482
+ else
483
+ @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
484
+ end
485
+ end
486
+ #
487
+ is_bol = true
488
+ pos = 0
489
+ input.scan(@regexp) do |pi_arg, stmt, rspace,
490
+ indicator1, expr1, indicator2, expr2|
491
+ match = Regexp.last_match
492
+ len = match.begin(0) - pos
493
+ text = input[pos, len]
494
+ pos = match.end(0)
495
+ lspace = stmt ? detect_spaces_at_bol(text, is_bol) : nil
496
+ is_bol = stmt && rspace ? true : false
497
+ add_text(codebuf, text) # unless text.empty?
498
+ #
499
+ if stmt
500
+ if @trim && lspace && rspace
501
+ add_pi_stmt(codebuf, "#{lspace}#{stmt}#{rspace}", pi_arg)
502
+ else
503
+ add_text(codebuf, lspace) if lspace
504
+ add_pi_stmt(codebuf, stmt, pi_arg)
505
+ add_text(codebuf, rspace) if rspace
506
+ end
507
+ else
508
+ add_pi_expr(codebuf, expr1 || expr2, indicator1 || indicator2)
509
+ end
510
+ end
511
+ #rest = $' || input # ruby1.8
512
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
513
+ add_text(codebuf, rest)
514
+ end
515
+
516
+ #--
517
+ #def convert_input(codebuf, input)
518
+ # parse_stmts(codebuf, input)
519
+ # #parse_stmts2(codebuf, input)
520
+ #end
521
+ #
522
+ #def parse_stmts(codebuf, input)
523
+ # #regexp = pattern_regexp(@pattern)
524
+ # @pi ||= 'e'
525
+ # @stmt_pattern ||= /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m
526
+ # is_bol = true
527
+ # pos = 0
528
+ # input.scan(@stmt_pattern) do |pi_arg, code, rspace|
529
+ # match = Regexp.last_match
530
+ # len = match.begin(0) - pos
531
+ # text = input[pos, len]
532
+ # pos = match.end(0)
533
+ # lspace = detect_spaces_at_bol(text, is_bol)
534
+ # is_bol = rspace ? true : false
535
+ # parse_exprs(codebuf, text) # unless text.empty?
536
+ # if @trim && lspace && rspace
537
+ # add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
538
+ # else
539
+ # add_text(codebuf, lspace)
540
+ # add_pi_stmt(codebuf, code, pi_arg)
541
+ # add_text(codebuf, rspace)
542
+ # end
543
+ # end
544
+ # rest = $' || input
545
+ # parse_exprs(codebuf, rest)
546
+ #end
547
+ #
548
+ #def parse_exprs(codebuf, input)
549
+ # unless @expr_pattern
550
+ # ch = Regexp.escape(@embchar)
551
+ # if @pattern
552
+ # left, right = @pattern.split(' ')
553
+ # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/
554
+ # else
555
+ # @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/
556
+ # end
557
+ # end
558
+ # pos = 0
559
+ # input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2|
560
+ # indicator = indicator1 || indicator2
561
+ # code = code1 || code2
562
+ # match = Regexp.last_match
563
+ # len = match.begin(0) - pos
564
+ # text = input[pos, len]
565
+ # pos = match.end(0)
566
+ # add_text(codebuf, text) # unless text.empty?
567
+ # add_pi_expr(codebuf, code, indicator)
568
+ # end
569
+ # rest = $' || input
570
+ # add_text(codebuf, rest)
571
+ #end
572
+ #++
573
+
574
+ def add_pi_stmt(codebuf, code, pi_arg) # :nodoc:
575
+ case pi_arg
576
+ when nil ; add_stmt(codebuf, code)
577
+ when 'header' ; @header = code
578
+ when 'footer' ; @footer = code
579
+ when 'comment'; add_stmt(codebuf, "\n" * code.count("\n"))
580
+ when 'value' ; add_expr_literal(codebuf, code)
581
+ else ; add_stmt(codebuf, code)
582
+ end
583
+ end
584
+
585
+ def add_pi_expr(codebuf, code, indicator) # :nodoc:
586
+ case indicator
587
+ when nil, '', '==' # @{...}@ or <%== ... %>
588
+ @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code)
589
+ when '!', '=' # @!{...}@ or <%= ... %>
590
+ @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code)
591
+ when '!!', '===' # @!!{...}@ or <%=== ... %>
592
+ add_expr_debug(codebuf, code)
593
+ else
594
+ # ignore
595
+ end
596
+ end
597
+
598
+ end
599
+
600
+
601
+ end
602
+ #--end of require 'erubis/converter'
603
+ #--begin of require 'erubis/evaluator'
604
+ ##
605
+ ## $Rev: 115 $
606
+ ## $Release: 2.6.3 $
607
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
608
+ ##
609
+
610
+ #--begin of require 'erubis/error'
611
+ ##
612
+ ## $Rev: 77 $
613
+ ## $Release: 2.6.3 $
614
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
615
+ ##
616
+
617
+ module Erubis
618
+
619
+
620
+ ##
621
+ ## base error class
622
+ ##
623
+ class ErubisError < StandardError
624
+ end
625
+
626
+
627
+ ##
628
+ ## raised when method or function is not supported
629
+ ##
630
+ class NotSupportedError < ErubisError
631
+ end
632
+
633
+
634
+ end
635
+ #--end of require 'erubis/error'
636
+ #--begin of require 'erubis/context'
637
+ ##
638
+ ## $Rev: 77 $
639
+ ## $Release: 2.6.3 $
640
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
641
+ ##
642
+
643
+
644
+ module Erubis
645
+
646
+
647
+ ##
648
+ ## context object for Engine#evaluate
649
+ ##
650
+ ## ex.
651
+ ## template = <<'END'
652
+ ## Hello <%= @user %>!
653
+ ## <% for item in @list %>
654
+ ## - <%= item %>
655
+ ## <% end %>
656
+ ## END
657
+ ##
658
+ ## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
659
+ ## # or
660
+ ## # context = Erubis::Context.new
661
+ ## # context[:user] = 'World'
662
+ ## # context[:list] = ['a', 'b', 'c']
663
+ ##
664
+ ## eruby = Erubis::Eruby.new(template)
665
+ ## print eruby.evaluate(context)
666
+ ##
667
+ class Context
668
+ include Enumerable
669
+
670
+ def initialize(hash=nil)
671
+ hash.each do |name, value|
672
+ self[name] = value
673
+ end if hash
674
+ end
675
+
676
+ def [](key)
677
+ return instance_variable_get("@#{key}")
678
+ end
679
+
680
+ def []=(key, value)
681
+ return instance_variable_set("@#{key}", value)
682
+ end
683
+
684
+ def keys
685
+ return instance_variables.collect { |name| name[1..-1] }
686
+ end
687
+
688
+ def each
689
+ instance_variables.each do |name|
690
+ key = name[1..-1]
691
+ value = instance_variable_get(name)
692
+ yield(key, value)
693
+ end
694
+ end
695
+
696
+ def to_hash
697
+ hash = {}
698
+ self.keys.each { |key| hash[key] = self[key] }
699
+ return hash
700
+ end
701
+
702
+ def update(context_or_hash)
703
+ arg = context_or_hash
704
+ if arg.is_a?(Hash)
705
+ arg.each do |key, val|
706
+ self[key] = val
707
+ end
708
+ else
709
+ arg.instance_variables.each do |varname|
710
+ key = varname[1..-1]
711
+ val = arg.instance_variable_get(varname)
712
+ self[key] = val
713
+ end
714
+ end
715
+ end
716
+
717
+ end
718
+
719
+
720
+ end
721
+ #--end of require 'erubis/context'
722
+
723
+
724
+ module Erubis
725
+
726
+ EMPTY_BINDING = binding()
727
+
728
+
729
+ ##
730
+ ## evaluate code
731
+ ##
732
+ module Evaluator
733
+
734
+ def self.supported_properties # :nodoc:
735
+ return []
736
+ end
737
+
738
+ attr_accessor :src, :filename
739
+
740
+ def init_evaluator(properties)
741
+ @filename = properties[:filename]
742
+ end
743
+
744
+ def result(*args)
745
+ raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
746
+ end
747
+
748
+ def evaluate(*args)
749
+ raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
750
+ end
751
+
752
+ end
753
+
754
+
755
+ ##
756
+ ## evaluator for Ruby
757
+ ##
758
+ module RubyEvaluator
759
+ include Evaluator
760
+
761
+ def self.supported_properties # :nodoc:
762
+ list = Evaluator.supported_properties
763
+ return list
764
+ end
765
+
766
+ ## eval(@src) with binding object
767
+ def result(_binding_or_hash=TOPLEVEL_BINDING)
768
+ _arg = _binding_or_hash
769
+ if _arg.is_a?(Hash)
770
+ _b = binding()
771
+ eval _arg.collect{|k,v| "#{k} = _arg[#{k.inspect}]; "}.join, _b
772
+ elsif _arg.is_a?(Binding)
773
+ _b = _arg
774
+ elsif _arg.nil?
775
+ _b = binding()
776
+ else
777
+ raise ArgumentError.new("#{self.class.name}#result(): argument should be Binding or Hash but passed #{_arg.class.name} object.")
778
+ end
779
+ return eval(@src, _b, (@filename || '(erubis'))
780
+ end
781
+
782
+ ## invoke context.instance_eval(@src)
783
+ def evaluate(_context=Context.new)
784
+ _context = Context.new(_context) if _context.is_a?(Hash)
785
+ #return _context.instance_eval(@src, @filename || '(erubis)')
786
+ #@_proc ||= eval("proc { #{@src} }", Erubis::EMPTY_BINDING, @filename || '(erubis)')
787
+ @_proc ||= eval("proc { #{@src} }", binding(), @filename || '(erubis)')
788
+ return _context.instance_eval(&@_proc)
789
+ end
790
+
791
+ ## if object is an Class or Module then define instance method to it,
792
+ ## else define singleton method to it.
793
+ def def_method(object, method_name, filename=nil)
794
+ m = object.is_a?(Module) ? :module_eval : :instance_eval
795
+ object.__send__(m, "def #{method_name}; #{@src}; end", filename || @filename || '(erubis)')
796
+ end
797
+
798
+
799
+ end
800
+
801
+
802
+ end
803
+ #--end of require 'erubis/evaluator'
804
+ #--already included require 'erubis/context'
805
+
806
+
807
+ module Erubis
808
+
809
+
810
+ ##
811
+ ## (abstract) abstract engine class.
812
+ ## subclass must include evaluator and converter module.
813
+ ##
814
+ class Engine
815
+ #include Evaluator
816
+ #include Converter
817
+ #include Generator
818
+
819
+ def initialize(input=nil, properties={})
820
+ #@input = input
821
+ init_generator(properties)
822
+ init_converter(properties)
823
+ init_evaluator(properties)
824
+ @src = convert(input) if input
825
+ end
826
+
827
+
828
+ ##
829
+ ## convert input string and set it to @src
830
+ ##
831
+ def convert!(input)
832
+ @src = convert(input)
833
+ end
834
+
835
+
836
+ ##
837
+ ## load file, write cache file, and return engine object.
838
+ ## this method create code cache file automatically.
839
+ ## cachefile name can be specified with properties[:cachename],
840
+ ## or filname + 'cache' is used as default.
841
+ ##
842
+ def self.load_file(filename, properties={})
843
+ cachename = properties[:cachename] || (filename + '.cache')
844
+ properties[:filename] = filename
845
+ if test(?f, cachename) && File.mtime(filename) <= File.mtime(cachename)
846
+ engine = self.new(nil, properties)
847
+ engine.src = File.read(cachename)
848
+ else
849
+ input = File.open(filename, 'rb') {|f| f.read }
850
+ engine = self.new(input, properties)
851
+ File.open(cachename, 'wb') do |f|
852
+ f.flock(File::LOCK_EX)
853
+ f.write(engine.src)
854
+ f.flush()
855
+ end
856
+ end
857
+ engine.src.untaint # ok?
858
+ return engine
859
+ end
860
+
861
+
862
+ ##
863
+ ## helper method to convert and evaluate input text with context object.
864
+ ## context may be Binding, Hash, or Object.
865
+ ##
866
+ def process(input, context=nil, filename=nil)
867
+ code = convert(input)
868
+ filename ||= '(erubis)'
869
+ if context.is_a?(Binding)
870
+ return eval(code, context, filename)
871
+ else
872
+ context = Context.new(context) if context.is_a?(Hash)
873
+ return context.instance_eval(code, filename)
874
+ end
875
+ end
876
+
877
+
878
+ ##
879
+ ## helper method evaluate Proc object with contect object.
880
+ ## context may be Binding, Hash, or Object.
881
+ ##
882
+ def process_proc(proc_obj, context=nil, filename=nil)
883
+ if context.is_a?(Binding)
884
+ filename ||= '(erubis)'
885
+ return eval(proc_obj, context, filename)
886
+ else
887
+ context = Context.new(context) if context.is_a?(Hash)
888
+ return context.instance_eval(&proc_obj)
889
+ end
890
+ end
891
+
892
+
893
+ end # end of class Engine
894
+
895
+
896
+ ##
897
+ ## (abstract) base engine class for Eruby, Eperl, Ejava, and so on.
898
+ ## subclass must include generator.
899
+ ##
900
+ class Basic::Engine < Engine
901
+ include Evaluator
902
+ include Basic::Converter
903
+ include Generator
904
+ end
905
+
906
+
907
+ class PI::Engine < Engine
908
+ include Evaluator
909
+ include PI::Converter
910
+ include Generator
911
+ end
912
+
913
+
914
+ end
915
+ #--end of require 'erubis/engine'
916
+ #require 'erubis/generator'
917
+ #require 'erubis/converter'
918
+ #require 'erubis/evaluator'
919
+ #require 'erubis/error'
920
+ #require 'erubis/context'
921
+ #--begin of require 'erubis/helper'
922
+ ##
923
+ ## $Rev: 89 $
924
+ ## $Release: 2.6.3 $
925
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
926
+ ##
927
+
928
+
929
+ module Erubis
930
+
931
+ ##
932
+ ## helper for xml
933
+ ##
934
+ module XmlHelper
935
+
936
+ module_function
937
+
938
+ ESCAPE_TABLE = {
939
+ '&' => '&amp;',
940
+ '<' => '&lt;',
941
+ '>' => '&gt;',
942
+ '"' => '&quot;',
943
+ "'" => '&#039;',
944
+ }
945
+
946
+ def escape_xml(value)
947
+ value.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/
948
+ #value.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
949
+ end
950
+
951
+ def escape_xml2(value)
952
+ return value.to_s.gsub(/\&/,'&amp;').gsub(/</,'&lt;').gsub(/>/,'&gt;').gsub(/"/,'&quot;')
953
+ end
954
+
955
+ alias h escape_xml
956
+ alias html_escape escape_xml
957
+
958
+ def url_encode(str)
959
+ return str.gsub(/[^-_.a-zA-Z0-9]+/) { |s|
960
+ s.unpack('C*').collect { |i| "%%%02X" % i }.join
961
+ }
962
+ end
963
+
964
+ alias u url_encode
965
+
966
+ end
967
+
968
+
969
+ end
970
+ #--end of require 'erubis/helper'
971
+ #--begin of require 'erubis/enhancer'
972
+ ##
973
+ ## $Rev: 115 $
974
+ ## $Release: 2.6.3 $
975
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
976
+ ##
977
+
978
+
979
+ module Erubis
980
+
981
+
982
+ ##
983
+ ## switch '<%= ... %>' to escaped and '<%== ... %>' to unescaped
984
+ ##
985
+ ## ex.
986
+ ## class XmlEruby < Eruby
987
+ ## include EscapeEnhancer
988
+ ## end
989
+ ##
990
+ ## this is language-indenedent.
991
+ ##
992
+ module EscapeEnhancer
993
+
994
+ def self.desc # :nodoc:
995
+ "switch '<%= %>' to escaped and '<%== %>' to unescaped"
996
+ end
997
+
998
+ #--
999
+ #def self.included(klass)
1000
+ # klass.class_eval <<-END
1001
+ # alias _add_expr_literal add_expr_literal
1002
+ # alias _add_expr_escaped add_expr_escaped
1003
+ # alias add_expr_literal _add_expr_escaped
1004
+ # alias add_expr_escaped _add_expr_literal
1005
+ # END
1006
+ #end
1007
+ #++
1008
+
1009
+ def add_expr(src, code, indicator)
1010
+ case indicator
1011
+ when '='
1012
+ @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
1013
+ when '=='
1014
+ @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
1015
+ when '==='
1016
+ add_expr_debug(src, code)
1017
+ end
1018
+ end
1019
+
1020
+ end
1021
+
1022
+
1023
+ #--
1024
+ ## (obsolete)
1025
+ #module FastEnhancer
1026
+ #end
1027
+ #++
1028
+
1029
+
1030
+ ##
1031
+ ## use $stdout instead of string
1032
+ ##
1033
+ ## this is only for Eruby.
1034
+ ##
1035
+ module StdoutEnhancer
1036
+
1037
+ def self.desc # :nodoc:
1038
+ "use $stdout instead of array buffer or string buffer"
1039
+ end
1040
+
1041
+ def add_preamble(src)
1042
+ src << "_buf = $stdout;"
1043
+ end
1044
+
1045
+ def add_postamble(src)
1046
+ src << "\n''\n"
1047
+ end
1048
+
1049
+ end
1050
+
1051
+
1052
+ ##
1053
+ ## use print statement instead of '_buf << ...'
1054
+ ##
1055
+ ## this is only for Eruby.
1056
+ ##
1057
+ module PrintOutEnhancer
1058
+
1059
+ def self.desc # :nodoc:
1060
+ "use print statement instead of '_buf << ...'"
1061
+ end
1062
+
1063
+ def add_preamble(src)
1064
+ end
1065
+
1066
+ def add_text(src, text)
1067
+ src << " print '" << escape_text(text) << "';" unless text.empty?
1068
+ end
1069
+
1070
+ def add_expr_literal(src, code)
1071
+ src << ' print((' << code << ').to_s);'
1072
+ end
1073
+
1074
+ def add_expr_escaped(src, code)
1075
+ src << ' print ' << escaped_expr(code) << ';'
1076
+ end
1077
+
1078
+ def add_postamble(src)
1079
+ src << "\n" unless src[-1] == ?\n
1080
+ end
1081
+
1082
+ end
1083
+
1084
+
1085
+ ##
1086
+ ## enable print function
1087
+ ##
1088
+ ## Notice: use Eruby#evaluate() and don't use Eruby#result()
1089
+ ## to be enable print function.
1090
+ ##
1091
+ ## this is only for Eruby.
1092
+ ##
1093
+ module PrintEnabledEnhancer
1094
+
1095
+ def self.desc # :nodoc:
1096
+ "enable to use print function in '<% %>'"
1097
+ end
1098
+
1099
+ def add_preamble(src)
1100
+ src << "@_buf = "
1101
+ super
1102
+ end
1103
+
1104
+ def print(*args)
1105
+ args.each do |arg|
1106
+ @_buf << arg.to_s
1107
+ end
1108
+ end
1109
+
1110
+ def evaluate(context=nil)
1111
+ _src = @src
1112
+ if context.is_a?(Hash)
1113
+ context.each do |key, val| instance_variable_set("@#{key}", val) end
1114
+ elsif context
1115
+ context.instance_variables.each do |name|
1116
+ instance_variable_set(name, context.instance_variable_get(name))
1117
+ end
1118
+ end
1119
+ return instance_eval(_src, (@filename || '(erubis)'))
1120
+ end
1121
+
1122
+ end
1123
+
1124
+
1125
+ ##
1126
+ ## return array instead of string
1127
+ ##
1128
+ ## this is only for Eruby.
1129
+ ##
1130
+ module ArrayEnhancer
1131
+
1132
+ def self.desc # :nodoc:
1133
+ "return array instead of string"
1134
+ end
1135
+
1136
+ def add_preamble(src)
1137
+ src << "_buf = [];"
1138
+ end
1139
+
1140
+ def add_postamble(src)
1141
+ src << "\n" unless src[-1] == ?\n
1142
+ src << "_buf\n"
1143
+ end
1144
+
1145
+ end
1146
+
1147
+
1148
+ ##
1149
+ ## use an Array object as buffer (included in Eruby by default)
1150
+ ##
1151
+ ## this is only for Eruby.
1152
+ ##
1153
+ module ArrayBufferEnhancer
1154
+
1155
+ def self.desc # :nodoc:
1156
+ "use an Array object for buffering (included in Eruby class)"
1157
+ end
1158
+
1159
+ def add_preamble(src)
1160
+ src << "_buf = [];"
1161
+ end
1162
+
1163
+ def add_postamble(src)
1164
+ src << "\n" unless src[-1] == ?\n
1165
+ src << "_buf.join\n"
1166
+ end
1167
+
1168
+ end
1169
+
1170
+
1171
+ ##
1172
+ ## use String class for buffering
1173
+ ##
1174
+ ## this is only for Eruby.
1175
+ ##
1176
+ module StringBufferEnhancer
1177
+
1178
+ def self.desc # :nodoc:
1179
+ "use a String object for buffering"
1180
+ end
1181
+
1182
+ def add_preamble(src)
1183
+ src << "_buf = '';"
1184
+ end
1185
+
1186
+ def add_postamble(src)
1187
+ src << "\n" unless src[-1] == ?\n
1188
+ src << "_buf.to_s\n"
1189
+ end
1190
+
1191
+ end
1192
+
1193
+
1194
+ ##
1195
+ ## use StringIO class for buffering
1196
+ ##
1197
+ ## this is only for Eruby.
1198
+ ##
1199
+ module StringIOEnhancer # :nodoc:
1200
+
1201
+ def self.desc # :nodoc:
1202
+ "use a StringIO object for buffering"
1203
+ end
1204
+
1205
+ def add_preamble(src)
1206
+ src << "_buf = StringIO.new;"
1207
+ end
1208
+
1209
+ def add_postamble(src)
1210
+ src << "\n" unless src[-1] == ?\n
1211
+ src << "_buf.string\n"
1212
+ end
1213
+
1214
+ end
1215
+
1216
+
1217
+ ##
1218
+ ## set buffer variable name to '_erbout' as well as '_buf'
1219
+ ##
1220
+ ## this is only for Eruby.
1221
+ ##
1222
+ module ErboutEnhancer
1223
+
1224
+ def self.desc # :nodoc:
1225
+ "set '_erbout = _buf = \"\";' to be compatible with ERB."
1226
+ end
1227
+
1228
+ def add_preamble(src)
1229
+ src << "_erbout = _buf = '';"
1230
+ end
1231
+
1232
+ def add_postamble(src)
1233
+ src << "\n" unless src[-1] == ?\n
1234
+ src << "_buf.to_s\n"
1235
+ end
1236
+
1237
+ end
1238
+
1239
+
1240
+ ##
1241
+ ## remove text and leave code, especially useful when debugging.
1242
+ ##
1243
+ ## ex.
1244
+ ## $ erubis -s -E NoText file.eruby | more
1245
+ ##
1246
+ ## this is language independent.
1247
+ ##
1248
+ module NoTextEnhancer
1249
+
1250
+ def self.desc # :nodoc:
1251
+ "remove text and leave code (useful when debugging)"
1252
+ end
1253
+
1254
+ def add_text(src, text)
1255
+ src << ("\n" * text.count("\n"))
1256
+ if text[-1] != ?\n
1257
+ text =~ /^(.*?)\z/
1258
+ src << (' ' * $1.length)
1259
+ end
1260
+ end
1261
+
1262
+ end
1263
+
1264
+
1265
+ ##
1266
+ ## remove code and leave text, especially useful when validating HTML tags.
1267
+ ##
1268
+ ## ex.
1269
+ ## $ erubis -s -E NoCode file.eruby | tidy -errors
1270
+ ##
1271
+ ## this is language independent.
1272
+ ##
1273
+ module NoCodeEnhancer
1274
+
1275
+ def self.desc # :nodoc:
1276
+ "remove code and leave text (useful when validating HTML)"
1277
+ end
1278
+
1279
+ def add_preamble(src)
1280
+ end
1281
+
1282
+ def add_postamble(src)
1283
+ end
1284
+
1285
+ def add_text(src, text)
1286
+ src << text
1287
+ end
1288
+
1289
+ def add_expr(src, code, indicator)
1290
+ src << "\n" * code.count("\n")
1291
+ end
1292
+
1293
+ def add_stmt(src, code)
1294
+ src << "\n" * code.count("\n")
1295
+ end
1296
+
1297
+ end
1298
+
1299
+
1300
+ ##
1301
+ ## get convert faster, but spaces around '<%...%>' are not trimmed.
1302
+ ##
1303
+ ## this is language-independent.
1304
+ ##
1305
+ module SimplifyEnhancer
1306
+
1307
+ def self.desc # :nodoc:
1308
+ "get convert faster but leave spaces around '<% %>'"
1309
+ end
1310
+
1311
+ #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
1312
+ SIMPLE_REGEXP = /<%(=+|\#)?(.*?)-?%>/m
1313
+
1314
+ def convert(input)
1315
+ src = ""
1316
+ add_preamble(src)
1317
+ #regexp = pattern_regexp(@pattern)
1318
+ pos = 0
1319
+ input.scan(SIMPLE_REGEXP) do |indicator, code|
1320
+ match = Regexp.last_match
1321
+ index = match.begin(0)
1322
+ text = input[pos, index - pos]
1323
+ pos = match.end(0)
1324
+ add_text(src, text)
1325
+ if !indicator # <% %>
1326
+ add_stmt(src, code)
1327
+ elsif indicator[0] == ?\# # <%# %>
1328
+ n = code.count("\n")
1329
+ add_stmt(src, "\n" * n)
1330
+ else # <%= %>
1331
+ add_expr(src, code, indicator)
1332
+ end
1333
+ end
1334
+ #rest = $' || input # ruby1.8
1335
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
1336
+ add_text(src, rest)
1337
+ add_postamble(src)
1338
+ return src
1339
+ end
1340
+
1341
+ end
1342
+
1343
+
1344
+ ##
1345
+ ## enable to use other embedded expression pattern (default is '\[= =\]').
1346
+ ##
1347
+ ## notice! this is an experimental. spec may change in the future.
1348
+ ##
1349
+ ## ex.
1350
+ ## input = <<END
1351
+ ## <% for item in list %>
1352
+ ## <%= item %> : <%== item %>
1353
+ ## [= item =] : [== item =]
1354
+ ## <% end %>
1355
+ ## END
1356
+ ##
1357
+ ## class BiPatternEruby
1358
+ ## include BiPatternEnhancer
1359
+ ## end
1360
+ ## eruby = BiPatternEruby.new(input, :bipattern=>'\[= =\]')
1361
+ ## list = ['<a>', 'b&b', '"c"']
1362
+ ## print eruby.result(binding())
1363
+ ##
1364
+ ## ## output
1365
+ ## <a> : &lt;a&gt;
1366
+ ## <a> : &lt;a&gt;
1367
+ ## b&b : b&amp;b
1368
+ ## b&b : b&amp;b
1369
+ ## "c" : &quot;c&quot;
1370
+ ## "c" : &quot;c&quot;
1371
+ ##
1372
+ ## this is language independent.
1373
+ ##
1374
+ module BiPatternEnhancer
1375
+
1376
+ def self.desc # :nodoc:
1377
+ "another embedded expression pattern (default '\[= =\]')."
1378
+ end
1379
+
1380
+ def initialize(input, properties={})
1381
+ self.bipattern = properties[:bipattern] # or '\$\{ \}'
1382
+ super
1383
+ end
1384
+
1385
+ ## when pat is nil then '\[= =\]' is used
1386
+ def bipattern=(pat) # :nodoc:
1387
+ @bipattern = pat || '\[= =\]'
1388
+ pre, post = @bipattern.split()
1389
+ @bipattern_regexp = /(.*?)#{pre}(=*)(.*?)#{post}/m
1390
+ end
1391
+
1392
+ def add_text(src, text)
1393
+ return unless text
1394
+ m = nil
1395
+ text.scan(@bipattern_regexp) do |txt, indicator, code|
1396
+ m = Regexp.last_match
1397
+ super(src, txt)
1398
+ add_expr(src, code, '=' + indicator)
1399
+ end
1400
+ #rest = $' || text # ruby1.8
1401
+ rest = m ? text[m.end(0)..-1] : text # ruby1.9
1402
+ super(src, rest)
1403
+ end
1404
+
1405
+ end
1406
+
1407
+
1408
+ ##
1409
+ ## regards lines starting with '%' as program code
1410
+ ##
1411
+ ## this is for compatibility to eruby and ERB.
1412
+ ##
1413
+ ## this is language-independent.
1414
+ ##
1415
+ module PercentLineEnhancer
1416
+
1417
+ def self.desc # :nodoc:
1418
+ "regard lines starting with '%' as program code"
1419
+ end
1420
+
1421
+ def add_text(src, text)
1422
+ pos = 0
1423
+ text2 = ''
1424
+ text.scan(/^\%(.*?\r?\n)/) do
1425
+ line = $1
1426
+ match = Regexp.last_match
1427
+ len = match.begin(0) - pos
1428
+ str = text[pos, len]
1429
+ pos = match.end(0)
1430
+ if text2.empty?
1431
+ text2 = str
1432
+ else
1433
+ text2 << str
1434
+ end
1435
+ if line[0] == ?%
1436
+ text2 << line
1437
+ else
1438
+ super(src, text2)
1439
+ text2 = ''
1440
+ add_stmt(src, line)
1441
+ end
1442
+ end
1443
+ #rest = pos == 0 ? text : $' # ruby1.8
1444
+ rest = pos == 0 ? text : text[pos..-1] # ruby1.9
1445
+ unless text2.empty?
1446
+ text2 << rest if rest
1447
+ rest = text2
1448
+ end
1449
+ super(src, rest)
1450
+ end
1451
+
1452
+ end
1453
+
1454
+
1455
+ ##
1456
+ ## [experimental] allow header and footer in eRuby script
1457
+ ##
1458
+ ## ex.
1459
+ ## ====================
1460
+ ## ## without header and footer
1461
+ ## $ cat ex1.eruby
1462
+ ## <% def list_items(list) %>
1463
+ ## <% for item in list %>
1464
+ ## <li><%= item %></li>
1465
+ ## <% end %>
1466
+ ## <% end %>
1467
+ ##
1468
+ ## $ erubis -s ex1.eruby
1469
+ ## _buf = []; def list_items(list)
1470
+ ## ; for item in list
1471
+ ## ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
1472
+ ## '; end
1473
+ ## ; end
1474
+ ## ;
1475
+ ## _buf.join
1476
+ ##
1477
+ ## ## with header and footer
1478
+ ## $ cat ex2.eruby
1479
+ ## <!--#header:
1480
+ ## def list_items(list)
1481
+ ## #-->
1482
+ ## <% for item in list %>
1483
+ ## <li><%= item %></li>
1484
+ ## <% end %>
1485
+ ## <!--#footer:
1486
+ ## end
1487
+ ## #-->
1488
+ ##
1489
+ ## $ erubis -s -c HeaderFooterEruby ex4.eruby
1490
+ ##
1491
+ ## def list_items(list)
1492
+ ## _buf = []; _buf << '
1493
+ ## '; for item in list
1494
+ ## ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
1495
+ ## '; end
1496
+ ## ; _buf << '
1497
+ ## ';
1498
+ ## _buf.join
1499
+ ## end
1500
+ ##
1501
+ ## ====================
1502
+ ##
1503
+ ## this is language-independent.
1504
+ ##
1505
+ module HeaderFooterEnhancer
1506
+
1507
+ def self.desc # :nodoc:
1508
+ "allow header/footer in document (ex. '<!--#header: #-->')"
1509
+ end
1510
+
1511
+ HEADER_FOOTER_PATTERN = /(.*?)(^[ \t]*)?<!--\#(\w+):(.*?)\#-->([ \t]*\r?\n)?/m
1512
+
1513
+ def add_text(src, text)
1514
+ m = nil
1515
+ text.scan(HEADER_FOOTER_PATTERN) do |txt, lspace, word, content, rspace|
1516
+ m = Regexp.last_match
1517
+ flag_trim = @trim && lspace && rspace
1518
+ super(src, txt)
1519
+ content = "#{lspace}#{content}#{rspace}" if flag_trim
1520
+ super(src, lspace) if !flag_trim && lspace
1521
+ instance_variable_set("@#{word}", content)
1522
+ super(src, rspace) if !flag_trim && rspace
1523
+ end
1524
+ #rest = $' || text # ruby1.8
1525
+ rest = m ? text[m.end(0)..-1] : text # ruby1.9
1526
+ super(src, rest)
1527
+ end
1528
+
1529
+ attr_accessor :header, :footer
1530
+
1531
+ def convert(input)
1532
+ source = super
1533
+ return @src = "#{@header}#{source}#{@footer}"
1534
+ end
1535
+
1536
+ end
1537
+
1538
+
1539
+ ##
1540
+ ## delete indentation of HTML.
1541
+ ##
1542
+ ## this is language-independent.
1543
+ ##
1544
+ module DeleteIndentEnhancer
1545
+
1546
+ def self.desc # :nodoc:
1547
+ "delete indentation of HTML."
1548
+ end
1549
+
1550
+ def convert_input(src, input)
1551
+ input = input.gsub(/^[ \t]+</, '<')
1552
+ super(src, input)
1553
+ end
1554
+
1555
+ end
1556
+
1557
+
1558
+ ##
1559
+ ## convert "<h1><%=title%></h1>" into "_buf << %Q`<h1>#{title}</h1>`"
1560
+ ##
1561
+ ## this is only for Eruby.
1562
+ ##
1563
+ module InterpolationEnhancer
1564
+
1565
+ def self.desc # :nodoc:
1566
+ "convert '<p><%=text%></p>' into '_buf << %Q`<p>\#{text}</p>`'"
1567
+ end
1568
+
1569
+ def convert_input(src, input)
1570
+ pat = @pattern
1571
+ regexp = pat.nil? || pat == '<% %>' ? Basic::Converter::DEFAULT_REGEXP : pattern_regexp(pat)
1572
+ pos = 0
1573
+ is_bol = true # is beginning of line
1574
+ str = ''
1575
+ input.scan(regexp) do |indicator, code, tailch, rspace|
1576
+ match = Regexp.last_match()
1577
+ len = match.begin(0) - pos
1578
+ text = input[pos, len]
1579
+ pos = match.end(0)
1580
+ ch = indicator ? indicator[0] : nil
1581
+ lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
1582
+ is_bol = rspace ? true : false
1583
+ _add_text_to_str(str, text)
1584
+ ## * when '<%= %>', do nothing
1585
+ ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
1586
+ if ch == ?= # <%= %>
1587
+ rspace = nil if tailch && !tailch.empty?
1588
+ str << lspace if lspace
1589
+ add_expr(str, code, indicator)
1590
+ str << rspace if rspace
1591
+ elsif ch == ?\# # <%# %>
1592
+ n = code.count("\n") + (rspace ? 1 : 0)
1593
+ if @trim && lspace && rspace
1594
+ add_text(src, str)
1595
+ str = ''
1596
+ add_stmt(src, "\n" * n)
1597
+ else
1598
+ str << lspace if lspace
1599
+ add_text(src, str)
1600
+ str = ''
1601
+ add_stmt(src, "\n" * n)
1602
+ str << rspace if rspace
1603
+ end
1604
+ else # <% %>
1605
+ if @trim && lspace && rspace
1606
+ add_text(src, str)
1607
+ str = ''
1608
+ add_stmt(src, "#{lspace}#{code}#{rspace}")
1609
+ else
1610
+ str << lspace if lspace
1611
+ add_text(src, str)
1612
+ str = ''
1613
+ add_stmt(src, code)
1614
+ str << rspace if rspace
1615
+ end
1616
+ end
1617
+ end
1618
+ #rest = $' || input # ruby1.8
1619
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
1620
+ _add_text_to_str(str, rest)
1621
+ add_text(src, str)
1622
+ end
1623
+
1624
+ def add_text(src, text)
1625
+ return if !text || text.empty?
1626
+ #src << " _buf << %Q`" << text << "`;"
1627
+ if text[-1] == ?\n
1628
+ text[-1] = "\\n"
1629
+ src << " _buf << %Q`" << text << "`\n"
1630
+ else
1631
+ src << " _buf << %Q`" << text << "`;"
1632
+ end
1633
+ end
1634
+
1635
+ def _add_text_to_str(str, text)
1636
+ return if !text || text.empty?
1637
+ text.gsub!(/['\#\\]/, '\\\\\&')
1638
+ str << text
1639
+ end
1640
+
1641
+ def add_expr_escaped(str, code)
1642
+ str << "\#{#{escaped_expr(code)}}"
1643
+ end
1644
+
1645
+ def add_expr_literal(str, code)
1646
+ str << "\#{#{code}}"
1647
+ end
1648
+
1649
+ end
1650
+
1651
+
1652
+ end
1653
+ #--end of require 'erubis/enhancer'
1654
+ #require 'erubis/tiny'
1655
+ #--begin of require 'erubis/engine/eruby'
1656
+ ##
1657
+ ## $Rev: 77 $
1658
+ ## $Release: 2.6.3 $
1659
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
1660
+ ##
1661
+
1662
+ #--already included require 'erubis/engine'
1663
+ #--already included require 'erubis/enhancer'
1664
+
1665
+
1666
+ module Erubis
1667
+
1668
+
1669
+ ##
1670
+ ## code generator for Ruby
1671
+ ##
1672
+ module RubyGenerator
1673
+ include Generator
1674
+ #include ArrayBufferEnhancer
1675
+ include StringBufferEnhancer
1676
+
1677
+ def init_generator(properties={})
1678
+ super
1679
+ @escapefunc ||= "Erubis::XmlHelper.escape_xml"
1680
+ end
1681
+
1682
+ def self.supported_properties() # :nodoc:
1683
+ return []
1684
+ end
1685
+
1686
+ def escape_text(text)
1687
+ text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\'
1688
+ end
1689
+
1690
+ def escaped_expr(code)
1691
+ return "#{@escapefunc}(#{code})"
1692
+ end
1693
+
1694
+ #--
1695
+ #def add_preamble(src)
1696
+ # src << "_buf = [];"
1697
+ #end
1698
+ #++
1699
+
1700
+ def add_text(src, text)
1701
+ src << " _buf << '" << escape_text(text) << "';" unless text.empty?
1702
+ end
1703
+
1704
+ def add_stmt(src, code)
1705
+ #src << code << ';'
1706
+ src << code
1707
+ src << ';' unless code[-1] == ?\n
1708
+ end
1709
+
1710
+ def add_expr_literal(src, code)
1711
+ src << ' _buf << (' << code << ').to_s;'
1712
+ end
1713
+
1714
+ def add_expr_escaped(src, code)
1715
+ src << ' _buf << ' << escaped_expr(code) << ';'
1716
+ end
1717
+
1718
+ def add_expr_debug(src, code)
1719
+ code.strip!
1720
+ s = (code.dump =~ /\A"(.*)"\z/) && $1
1721
+ src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
1722
+ end
1723
+
1724
+ #--
1725
+ #def add_postamble(src)
1726
+ # src << "\n_buf.join\n"
1727
+ #end
1728
+ #++
1729
+
1730
+ end
1731
+
1732
+
1733
+ ##
1734
+ ## engine for Ruby
1735
+ ##
1736
+ class Eruby < Basic::Engine
1737
+ include RubyEvaluator
1738
+ include RubyGenerator
1739
+ end
1740
+
1741
+
1742
+ ##
1743
+ ## fast engine for Ruby
1744
+ ##
1745
+ class FastEruby < Eruby
1746
+ include InterpolationEnhancer
1747
+ end
1748
+
1749
+
1750
+ ##
1751
+ ## swtich '<%= %>' to escaped and '<%== %>' to not escaped
1752
+ ##
1753
+ class EscapedEruby < Eruby
1754
+ include EscapeEnhancer
1755
+ end
1756
+
1757
+
1758
+ ##
1759
+ ## sanitize expression (<%= ... %>) by default
1760
+ ##
1761
+ ## this is equivalent to EscapedEruby and is prepared only for compatibility.
1762
+ ##
1763
+ class XmlEruby < Eruby
1764
+ include EscapeEnhancer
1765
+ end
1766
+
1767
+
1768
+ class PI::Eruby < PI::Engine
1769
+ include RubyEvaluator
1770
+ include RubyGenerator
1771
+
1772
+ def init_converter(properties={})
1773
+ @pi = 'rb'
1774
+ super(properties)
1775
+ end
1776
+
1777
+ end
1778
+
1779
+
1780
+ end
1781
+ #--end of require 'erubis/engine/eruby'
1782
+ #require 'erubis/engine/enhanced' # enhanced eruby engines
1783
+ #require 'erubis/engine/optimized' # generates optimized ruby code
1784
+ #require 'erubis/engine/ephp'
1785
+ #require 'erubis/engine/ec'
1786
+ #require 'erubis/engine/ejava'
1787
+ #require 'erubis/engine/escheme'
1788
+ #require 'erubis/engine/eperl'
1789
+ #require 'erubis/engine/ejavascript'
1790
+
1791
+ #--begin of require 'erubis/local-setting'
1792
+ ##
1793
+ ## $Rev: 77 $
1794
+ ## $Release: 2.6.3 $
1795
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
1796
+ ##
1797
+
1798
+ ##
1799
+ ## you can add site-local settings here.
1800
+ ## this files is required by erubis.rb
1801
+ ##
1802
+ #--end of require 'erubis/local-setting'
1803
+ #--end of require 'erubis'
1804
+ #--begin of require 'erubis/tiny'
1805
+ ##
1806
+ ## $Rev: 115 $
1807
+ ## $Release: 2.6.3 $
1808
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
1809
+ ##
1810
+
1811
+ module Erubis
1812
+
1813
+ ##
1814
+ ## tiny and the simplest implementation of eRuby
1815
+ ##
1816
+ ## ex.
1817
+ ## eruby = TinyEruby.new(File.read('example.rhtml'))
1818
+ ## print eruby.src # print ruby code
1819
+ ## print eruby.result(binding()) # eval ruby code with Binding object
1820
+ ## print eruby.evalute(context) # eval ruby code with context object
1821
+ ##
1822
+ class TinyEruby
1823
+
1824
+ def initialize(input=nil)
1825
+ @src = convert(input) if input
1826
+ end
1827
+ attr_reader :src
1828
+
1829
+ EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m
1830
+
1831
+ def convert(input)
1832
+ src = "_buf = '';" # preamble
1833
+ pos = 0
1834
+ input.scan(EMBEDDED_PATTERN) do |indicator, code|
1835
+ match = Regexp.last_match
1836
+ len = match.begin(0) - pos
1837
+ text = input[pos, len]
1838
+ pos = match.end(0)
1839
+ #src << " _buf << '" << escape_text(text) << "';"
1840
+ text.gsub!(/['\\]/, '\\\\\&')
1841
+ src << " _buf << '" << text << "';" unless text.empty?
1842
+ if !indicator # <% %>
1843
+ src << code << ";"
1844
+ elsif indicator == '#' # <%# %>
1845
+ src << ("\n" * code.count("\n"))
1846
+ else # <%= %>
1847
+ src << " _buf << (" << code << ").to_s;"
1848
+ end
1849
+ end
1850
+ #rest = $' || input # ruby1.8
1851
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
1852
+ #src << " _buf << '" << escape_text(rest) << "';"
1853
+ rest.gsub!(/['\\]/, '\\\\\&')
1854
+ src << " _buf << '" << rest << "';" unless rest.empty?
1855
+ src << "\n_buf.to_s\n" # postamble
1856
+ return src
1857
+ end
1858
+
1859
+ #def escape_text(text)
1860
+ # return text.gsub!(/['\\]/, '\\\\\&') || text
1861
+ #end
1862
+
1863
+ def result(_binding=TOPLEVEL_BINDING)
1864
+ eval @src, _binding
1865
+ end
1866
+
1867
+ def evaluate(_context=Object.new)
1868
+ if _context.is_a?(Hash)
1869
+ _obj = Object.new
1870
+ _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
1871
+ _context = _obj
1872
+ end
1873
+ _context.instance_eval @src
1874
+ end
1875
+
1876
+ end
1877
+
1878
+
1879
+
1880
+ module PI
1881
+ end
1882
+
1883
+ class PI::TinyEruby
1884
+
1885
+ def initialize(input=nil, options={})
1886
+ @escape = options[:escape] || 'Erubis::XmlHelper.escape_xml'
1887
+ @src = convert(input) if input
1888
+ end
1889
+
1890
+ attr_reader :src
1891
+
1892
+ EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m
1893
+
1894
+ def convert(input)
1895
+ src = "_buf = '';" # preamble
1896
+ pos = 0
1897
+ input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr|
1898
+ match = Regexp.last_match
1899
+ len = match.begin(0) - pos
1900
+ text = input[pos, len]
1901
+ pos = match.end(0)
1902
+ #src << " _buf << '" << escape_text(text) << "';"
1903
+ text.gsub!(/['\\]/, '\\\\\&')
1904
+ src << " _buf << '" << text << "';" unless text.empty?
1905
+ if stmt # <?rb ... ?>
1906
+ if lspace && rspace
1907
+ src << "#{lspace}#{stmt}#{rspace}"
1908
+ else
1909
+ src << " _buf << '" << lspace << "';" if lspace
1910
+ src << stmt << ";"
1911
+ src << " _buf << '" << rspace << "';" if rspace
1912
+ end
1913
+ else # ${...}, $!{...}
1914
+ if !indicator
1915
+ src << " _buf << " << @escape << "(" << expr << ");"
1916
+ elsif indicator == '!'
1917
+ src << " _buf << (" << expr << ").to_s;"
1918
+ end
1919
+ end
1920
+ end
1921
+ #rest = $' || input # ruby1.8
1922
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
1923
+ #src << " _buf << '" << escape_text(rest) << "';"
1924
+ rest.gsub!(/['\\]/, '\\\\\&')
1925
+ src << " _buf << '" << rest << "';" unless rest.empty?
1926
+ src << "\n_buf.to_s\n" # postamble
1927
+ return src
1928
+ end
1929
+
1930
+ #def escape_text(text)
1931
+ # return text.gsub!(/['\\]/, '\\\\\&') || text
1932
+ #end
1933
+
1934
+ def result(_binding=TOPLEVEL_BINDING)
1935
+ eval @src, _binding
1936
+ end
1937
+
1938
+ def evaluate(_context=Object.new)
1939
+ if _context.is_a?(Hash)
1940
+ _obj = Object.new
1941
+ _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
1942
+ _context = _obj
1943
+ end
1944
+ _context.instance_eval @src
1945
+ end
1946
+
1947
+ end
1948
+
1949
+
1950
+ end
1951
+ #--end of require 'erubis/tiny'
1952
+ #--begin of require 'erubis/engine/enhanced'
1953
+ ##
1954
+ ## $Rev: 77 $
1955
+ ## $Release: 2.6.3 $
1956
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
1957
+ ##
1958
+
1959
+ #--already included require 'erubis/enhancer'
1960
+ #--already included require 'erubis/engine/eruby'
1961
+
1962
+
1963
+ module Erubis
1964
+
1965
+
1966
+ #--
1967
+ ## moved to engine/ruby.rb
1968
+ #class EscapedEruby < Eruby
1969
+ # include EscapeEnhancer
1970
+ #end
1971
+ #++
1972
+
1973
+
1974
+ #--
1975
+ ### (obsolete)
1976
+ #class FastEruby < Eruby
1977
+ # include FastEnhancer
1978
+ #end
1979
+ #++
1980
+
1981
+
1982
+ class StdoutEruby < Eruby
1983
+ include StdoutEnhancer
1984
+ end
1985
+
1986
+
1987
+ class PrintOutEruby < Eruby
1988
+ include PrintOutEnhancer
1989
+ end
1990
+
1991
+
1992
+ class PrintEnabledEruby < Eruby
1993
+ include PrintEnabledEnhancer
1994
+ end
1995
+
1996
+
1997
+ class ArrayEruby < Eruby
1998
+ include ArrayEnhancer
1999
+ end
2000
+
2001
+
2002
+ class ArrayBufferEruby < Eruby
2003
+ include ArrayBufferEnhancer
2004
+ end
2005
+
2006
+
2007
+ class StringBufferEruby < Eruby
2008
+ include StringBufferEnhancer
2009
+ end
2010
+
2011
+
2012
+ class StringIOEruby < Eruby
2013
+ include StringIOEnhancer
2014
+ end
2015
+
2016
+
2017
+ class ErboutEruby < Eruby
2018
+ include ErboutEnhancer
2019
+ end
2020
+
2021
+
2022
+ class NoTextEruby < Eruby
2023
+ include NoTextEnhancer
2024
+ end
2025
+
2026
+
2027
+ class NoCodeEruby < Eruby
2028
+ include NoCodeEnhancer
2029
+ end
2030
+
2031
+
2032
+ class SimplifiedEruby < Eruby
2033
+ include SimplifyEnhancer
2034
+ end
2035
+
2036
+
2037
+ class StdoutSimplifiedEruby < Eruby
2038
+ include StdoutEnhancer
2039
+ include SimplifyEnhancer
2040
+ end
2041
+
2042
+
2043
+ class PrintOutSimplifiedEruby < Eruby
2044
+ include PrintOutEnhancer
2045
+ include SimplifyEnhancer
2046
+ end
2047
+
2048
+
2049
+ class BiPatternEruby < Eruby
2050
+ include BiPatternEnhancer
2051
+ end
2052
+
2053
+
2054
+ class PercentLineEruby < Eruby
2055
+ include PercentLineEnhancer
2056
+ end
2057
+
2058
+
2059
+ class HeaderFooterEruby < Eruby
2060
+ include HeaderFooterEnhancer
2061
+ end
2062
+
2063
+
2064
+ class DeleteIndentEruby < Eruby
2065
+ include DeleteIndentEnhancer
2066
+ end
2067
+
2068
+
2069
+ class InterpolationEruby < Eruby
2070
+ include InterpolationEnhancer
2071
+ end
2072
+
2073
+
2074
+ end
2075
+ #--end of require 'erubis/engine/enhanced'
2076
+ #--begin of require 'erubis/engine/optimized'
2077
+ ##
2078
+ ## $Rev: 77 $
2079
+ ## $Release: 2.6.3 $
2080
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2081
+ ##
2082
+
2083
+
2084
+ #--already included require 'erubis/engine/eruby'
2085
+
2086
+
2087
+ module Erubis
2088
+
2089
+
2090
+ module OptimizedGenerator
2091
+ include Generator
2092
+
2093
+ def self.supported_properties() # :nodoc:
2094
+ return []
2095
+ end
2096
+
2097
+ def init_generator(properties={})
2098
+ super
2099
+ @escapefunc ||= "Erubis::XmlHelper.escape_xml"
2100
+ @initialized = false
2101
+ @prev_is_expr = false
2102
+ end
2103
+
2104
+ protected
2105
+
2106
+ def escape_text(text)
2107
+ text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\'
2108
+ end
2109
+
2110
+ def escaped_expr(code)
2111
+ @escapefunc ||= 'Erubis::XmlHelper.escape_xml'
2112
+ return "#{@escapefunc}(#{code})"
2113
+ end
2114
+
2115
+ def switch_to_expr(src)
2116
+ return if @prev_is_expr
2117
+ @prev_is_expr = true
2118
+ src << ' _buf'
2119
+ end
2120
+
2121
+ def switch_to_stmt(src)
2122
+ return unless @prev_is_expr
2123
+ @prev_is_expr = false
2124
+ src << ';'
2125
+ end
2126
+
2127
+ def add_preamble(src)
2128
+ #@initialized = false
2129
+ #@prev_is_expr = false
2130
+ end
2131
+
2132
+ def add_text(src, text)
2133
+ return if text.empty?
2134
+ if @initialized
2135
+ switch_to_expr(src)
2136
+ src << " << '" << escape_text(text) << "'"
2137
+ else
2138
+ src << "_buf = '" << escape_text(text) << "';"
2139
+ @initialized = true
2140
+ end
2141
+ end
2142
+
2143
+ def add_stmt(src, code)
2144
+ switch_to_stmt(src) if @initialized
2145
+ #super
2146
+ src << code
2147
+ src << ';' unless code[-1] == ?\n
2148
+ end
2149
+
2150
+ def add_expr_literal(src, code)
2151
+ unless @initialized; src << "_buf = ''"; @initialized = true; end
2152
+ switch_to_expr(src)
2153
+ src << " << (" << code << ").to_s"
2154
+ end
2155
+
2156
+ def add_expr_escaped(src, code)
2157
+ unless @initialized; src << "_buf = ''"; @initialized = true; end
2158
+ switch_to_expr(src)
2159
+ src << " << " << escaped_expr(code)
2160
+ end
2161
+
2162
+ def add_expr_debug(src, code)
2163
+ code.strip!
2164
+ s = (code.dump =~ /\A"(.*)"\z/) && $1
2165
+ src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
2166
+ end
2167
+
2168
+ def add_postamble(src)
2169
+ #super if @initialized
2170
+ src << "\n_buf\n" if @initialized
2171
+ end
2172
+
2173
+ end # end of class OptimizedEruby
2174
+
2175
+
2176
+ ##
2177
+ ## Eruby class which generates optimized ruby code
2178
+ ##
2179
+ class OptimizedEruby < Basic::Engine # Eruby
2180
+ include RubyEvaluator
2181
+ include OptimizedGenerator
2182
+
2183
+ def init_converter(properties={})
2184
+ @pi = 'rb'
2185
+ super(properties)
2186
+ end
2187
+
2188
+ end
2189
+
2190
+
2191
+ ##
2192
+ ## XmlEruby class which generates optimized ruby code
2193
+ ##
2194
+ class OptimizedXmlEruby < OptimizedEruby
2195
+ include EscapeEnhancer
2196
+
2197
+ def add_expr_debug(src, code)
2198
+ switch_to_stmt(src) if indicator == '===' && !@initialized
2199
+ super
2200
+ end
2201
+
2202
+ end # end of class OptimizedXmlEruby
2203
+
2204
+ end
2205
+ #--end of require 'erubis/engine/optimized'
2206
+ #--already included require 'erubis/engine/eruby'
2207
+ #--begin of require 'erubis/engine/ephp'
2208
+ ##
2209
+ ## $Rev: 77 $
2210
+ ## $Release: 2.6.3 $
2211
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2212
+ ##
2213
+
2214
+ #--already included require 'erubis/engine'
2215
+ #--already included require 'erubis/enhancer'
2216
+
2217
+
2218
+ module Erubis
2219
+
2220
+
2221
+ module PhpGenerator
2222
+ include Generator
2223
+
2224
+ def self.supported_properties() # :nodoc:
2225
+ return []
2226
+ end
2227
+
2228
+ def init_generator(properties={})
2229
+ super
2230
+ @escapefunc ||= 'htmlspecialchars'
2231
+ end
2232
+
2233
+ def add_preamble(src)
2234
+ # empty
2235
+ end
2236
+
2237
+ def escape_text(text)
2238
+ return text.gsub!(/<\?xml\b/, '<<?php ?>?xml') || text
2239
+ end
2240
+
2241
+ def add_text(src, text)
2242
+ src << escape_text(text)
2243
+ end
2244
+
2245
+ def add_expr_literal(src, code)
2246
+ code.strip!
2247
+ src << "<?php echo #{code}; ?>"
2248
+ end
2249
+
2250
+ def add_expr_escaped(src, code)
2251
+ add_expr_literal(src, escaped_expr(code))
2252
+ end
2253
+
2254
+ def add_expr_debug(src, code)
2255
+ code.strip!
2256
+ s = code.gsub(/\'/, "\\'")
2257
+ src << "<?php error_log('*** debug: #{s}='.(#{code}), 0); ?>"
2258
+ end
2259
+
2260
+ def add_stmt(src, code)
2261
+ src << "<?php"
2262
+ src << " " if code[0] != ?\ #
2263
+ if code[-1] == ?\n
2264
+ code.chomp!
2265
+ src << code << "?>\n"
2266
+ else
2267
+ src << code << "?>"
2268
+ end
2269
+ end
2270
+
2271
+ def add_postamble(src)
2272
+ # empty
2273
+ end
2274
+
2275
+ end
2276
+
2277
+
2278
+ ##
2279
+ ## engine for PHP
2280
+ ##
2281
+ class Ephp < Basic::Engine
2282
+ include PhpGenerator
2283
+ end
2284
+
2285
+
2286
+ class EscapedEphp < Ephp
2287
+ include EscapeEnhancer
2288
+ end
2289
+
2290
+
2291
+ #class XmlEphp < Ephp
2292
+ # include EscapeEnhancer
2293
+ #end
2294
+
2295
+
2296
+ class PI::Ephp < PI::Engine
2297
+ include PhpGenerator
2298
+
2299
+ def init_converter(properties={})
2300
+ @pi = 'php'
2301
+ super(properties)
2302
+ end
2303
+
2304
+ end
2305
+
2306
+
2307
+ end
2308
+ #--end of require 'erubis/engine/ephp'
2309
+ #--begin of require 'erubis/engine/ec'
2310
+ ##
2311
+ ## $Rev: 77 $
2312
+ ## $Release: 2.6.3 $
2313
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2314
+ ##
2315
+
2316
+ #--already included require 'erubis/engine'
2317
+ #--already included require 'erubis/enhancer'
2318
+
2319
+
2320
+ module Erubis
2321
+
2322
+
2323
+ module CGenerator
2324
+ include Generator
2325
+
2326
+ def self.supported_properties() # :nodoc:
2327
+ return [
2328
+ [:indent, '', "indent spaces (ex. ' ')"],
2329
+ [:out, 'stdout', "output file pointer name"],
2330
+ ]
2331
+ end
2332
+
2333
+ def init_generator(properties={})
2334
+ super
2335
+ @escapefunc ||= "escape"
2336
+ @indent = properties[:indent] || ''
2337
+ @out = properties[:out] || 'stdout'
2338
+ end
2339
+
2340
+ def add_preamble(src)
2341
+ src << "#line 1 \"#{self.filename}\"\n" if self.filename
2342
+ end
2343
+
2344
+ def escape_text(text)
2345
+ @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
2346
+ text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] }
2347
+ return text
2348
+ end
2349
+
2350
+ def escaped_expr(code)
2351
+ return "#{@escapefunc}(#{code.strip}, #{@out})"
2352
+ end
2353
+
2354
+ def add_text(src, text)
2355
+ return if text.empty?
2356
+ src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
2357
+ src << "fputs("
2358
+ i = 0
2359
+ text.each_line do |line|
2360
+ src << "\n" << @indent << ' ' if i > 0
2361
+ i += 1
2362
+ src << '"' << escape_text(line) << '"'
2363
+ end
2364
+ src << ", #{@out});" #<< (text[-1] == ?\n ? "\n" : "")
2365
+ src << "\n" if text[-1] == ?\n
2366
+ end
2367
+
2368
+ def add_stmt(src, code)
2369
+ src << code
2370
+ end
2371
+
2372
+ def add_expr_literal(src, code)
2373
+ src << @indent if src.empty? || src[-1] == ?\n
2374
+ src << " fprintf(#{@out}, " << code.strip << ');'
2375
+ end
2376
+
2377
+ def add_expr_escaped(src, code)
2378
+ src << @indent if src.empty? || src[-1] == ?\n
2379
+ src << ' ' << escaped_expr(code) << ';'
2380
+ end
2381
+
2382
+ def add_expr_debug(src, code)
2383
+ code.strip!
2384
+ s = nil
2385
+ if code =~ /\A\".*?\"\s*,\s*(.*)/
2386
+ s = $1.gsub(/[%"]/, '\\\1') + '='
2387
+ end
2388
+ src << @indent if src.empty? || src[-1] == ?\n
2389
+ src << " fprintf(stderr, \"*** debug: #{s}\" #{code});"
2390
+ end
2391
+
2392
+ def add_postamble(src)
2393
+ # empty
2394
+ end
2395
+
2396
+ end
2397
+
2398
+
2399
+ ##
2400
+ ## engine for C
2401
+ ##
2402
+ class Ec < Basic::Engine
2403
+ include CGenerator
2404
+ end
2405
+
2406
+
2407
+ class EscapedEc < Ec
2408
+ include EscapeEnhancer
2409
+ end
2410
+
2411
+
2412
+ #class XmlEc < Ec
2413
+ # include EscapeEnhancer
2414
+ #end
2415
+
2416
+ class PI::Ec < PI::Engine
2417
+ include CGenerator
2418
+
2419
+ def init_converter(properties={})
2420
+ @pi = 'c'
2421
+ super(properties)
2422
+ end
2423
+
2424
+ end
2425
+
2426
+
2427
+ end
2428
+ #--end of require 'erubis/engine/ec'
2429
+ #--begin of require 'erubis/engine/ejava'
2430
+ ##
2431
+ ## $Rev: 77 $
2432
+ ## $Release: 2.6.3 $
2433
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2434
+ ##
2435
+
2436
+ #--already included require 'erubis/engine'
2437
+ #--already included require 'erubis/enhancer'
2438
+
2439
+
2440
+ module Erubis
2441
+
2442
+
2443
+ module JavaGenerator
2444
+ include Generator
2445
+
2446
+ def self.supported_properties() # :nodoc:
2447
+ return [
2448
+ [:indent, '', "indent spaces (ex. ' ')"],
2449
+ [:buf, '_buf', "output buffer name"],
2450
+ [:bufclass, 'StringBuffer', "output buffer class (ex. 'StringBuilder')"],
2451
+ ]
2452
+ end
2453
+
2454
+ def init_generator(properties={})
2455
+ super
2456
+ @escapefunc ||= 'escape'
2457
+ @indent = properties[:indent] || ''
2458
+ @buf = properties[:buf] || '_buf'
2459
+ @bufclass = properties[:bufclass] || 'StringBuffer'
2460
+ end
2461
+
2462
+ def add_preamble(src)
2463
+ src << "#{@indent}#{@bufclass} #{@buf} = new #{@bufclass}();"
2464
+ end
2465
+
2466
+ def escape_text(text)
2467
+ @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
2468
+ return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
2469
+ end
2470
+
2471
+ def add_text(src, text)
2472
+ return if text.empty?
2473
+ src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
2474
+ src << @buf << ".append("
2475
+ i = 0
2476
+ text.each_line do |line|
2477
+ src << "\n" << @indent << ' + ' if i > 0
2478
+ i += 1
2479
+ src << '"' << escape_text(line) << '"'
2480
+ end
2481
+ src << ");" << (text[-1] == ?\n ? "\n" : "")
2482
+ end
2483
+
2484
+ def add_stmt(src, code)
2485
+ src << code
2486
+ end
2487
+
2488
+ def add_expr_literal(src, code)
2489
+ src << @indent if src.empty? || src[-1] == ?\n
2490
+ code.strip!
2491
+ src << " #{@buf}.append(#{code});"
2492
+ end
2493
+
2494
+ def add_expr_escaped(src, code)
2495
+ add_expr_literal(src, escaped_expr(code))
2496
+ end
2497
+
2498
+ def add_expr_debug(src, code)
2499
+ code.strip!
2500
+ src << @indent if src.empty? || src[-1] == ?\n
2501
+ src << " System.err.println(\"*** debug: #{code}=\"+(#{code}));"
2502
+ end
2503
+
2504
+ def add_postamble(src)
2505
+ src << "\n" if src[-1] == ?;
2506
+ src << @indent << "return " << @buf << ".toString();\n"
2507
+ #src << @indent << "System.out.print(" << @buf << ".toString());\n"
2508
+ end
2509
+
2510
+ end
2511
+
2512
+
2513
+ ##
2514
+ ## engine for Java
2515
+ ##
2516
+ class Ejava < Basic::Engine
2517
+ include JavaGenerator
2518
+ end
2519
+
2520
+
2521
+ class EscapedEjava < Ejava
2522
+ include EscapeEnhancer
2523
+ end
2524
+
2525
+
2526
+ #class XmlEjava < Ejava
2527
+ # include EscapeEnhancer
2528
+ #end
2529
+
2530
+ class PI::Ejava < PI::Engine
2531
+ include JavaGenerator
2532
+
2533
+ def init_converter(properties={})
2534
+ @pi = 'java'
2535
+ super(properties)
2536
+ end
2537
+
2538
+ end
2539
+
2540
+ end
2541
+ #--end of require 'erubis/engine/ejava'
2542
+ #--begin of require 'erubis/engine/escheme'
2543
+ ##
2544
+ ## $Rev: 77 $
2545
+ ## $Release: 2.6.3 $
2546
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2547
+ ##
2548
+
2549
+ #--already included require 'erubis/engine'
2550
+ #--already included require 'erubis/enhancer'
2551
+
2552
+
2553
+ module Erubis
2554
+
2555
+
2556
+ module SchemeGenerator
2557
+ include Generator
2558
+
2559
+ def self.supported_properties() # :nodoc:
2560
+ return [
2561
+ [:func, '_add', "function name (ex. 'display')"],
2562
+ ]
2563
+ end
2564
+
2565
+ def init_generator(properties={})
2566
+ super
2567
+ @escapefunc ||= 'escape'
2568
+ @func = properties[:func] || '_add' # or 'display'
2569
+ end
2570
+
2571
+ def add_preamble(src)
2572
+ return unless @func == '_add'
2573
+ src << "(let ((_buf '())) " + \
2574
+ "(define (_add x) (set! _buf (cons x _buf))) "
2575
+ #src << "(let* ((_buf '())" + \
2576
+ # " (_add (lambda (x) (set! _buf (cons x _buf))))) "
2577
+ end
2578
+
2579
+ def escape_text(text)
2580
+ @table_ ||= { '"'=>'\\"', '\\'=>'\\\\' }
2581
+ text.gsub!(/["\\]/) { |m| @table_[m] }
2582
+ return text
2583
+ end
2584
+
2585
+ def escaped_expr(code)
2586
+ code.strip!
2587
+ return "(#{@escapefunc} #{code})"
2588
+ end
2589
+
2590
+ def add_text(src, text)
2591
+ return if text.empty?
2592
+ t = escape_text(text)
2593
+ if t[-1] == ?\n
2594
+ t[-1, 1] = ''
2595
+ src << "(#{@func} \"" << t << "\\n\")\n"
2596
+ else
2597
+ src << "(#{@func} \"" << t << '")'
2598
+ end
2599
+ end
2600
+
2601
+ def add_stmt(src, code)
2602
+ src << code
2603
+ end
2604
+
2605
+ def add_expr_literal(src, code)
2606
+ code.strip!
2607
+ src << "(#{@func} #{code})"
2608
+ end
2609
+
2610
+ def add_expr_escaped(src, code)
2611
+ add_expr_literal(src, escaped_expr(code))
2612
+ end
2613
+
2614
+ def add_expr_debug(src, code)
2615
+ s = (code.strip! || code).gsub(/\"/, '\\"')
2616
+ src << "(display \"*** debug: #{s}=\")(display #{code.strip})(display \"\\n\")"
2617
+ end
2618
+
2619
+ def add_postamble(src)
2620
+ return unless @func == '_add'
2621
+ src << "\n" unless src[-1] == ?\n
2622
+ src << " (reverse _buf))\n"
2623
+ end
2624
+
2625
+ end
2626
+
2627
+
2628
+ ##
2629
+ ## engine for Scheme
2630
+ ##
2631
+ class Escheme < Basic::Engine
2632
+ include SchemeGenerator
2633
+ end
2634
+
2635
+
2636
+ class EscapedEscheme < Escheme
2637
+ include EscapeEnhancer
2638
+ end
2639
+
2640
+
2641
+ #class XmlEscheme < Escheme
2642
+ # include EscapeEnhancer
2643
+ #end
2644
+
2645
+
2646
+ class PI::Escheme < PI::Engine
2647
+ include SchemeGenerator
2648
+
2649
+ def init_converter(properties={})
2650
+ @pi = 'scheme'
2651
+ super(properties)
2652
+ end
2653
+
2654
+ end
2655
+
2656
+
2657
+ end
2658
+ #--end of require 'erubis/engine/escheme'
2659
+ #--begin of require 'erubis/engine/eperl'
2660
+ ##
2661
+ ## $Rev: 77 $
2662
+ ## $Release: 2.6.3 $
2663
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2664
+ ##
2665
+
2666
+ #--already included require 'erubis/engine'
2667
+ #--already included require 'erubis/enhancer'
2668
+
2669
+
2670
+ module Erubis
2671
+
2672
+
2673
+ module PerlGenerator
2674
+ include Generator
2675
+
2676
+ def self.supported_properties() # :nodoc:
2677
+ return [
2678
+ [:func, 'print', "function name"],
2679
+ ]
2680
+ end
2681
+
2682
+ def init_generator(properties={})
2683
+ super
2684
+ @escapefunc ||= 'encode_entities'
2685
+ @func = properties[:func] || 'print'
2686
+ end
2687
+
2688
+ def add_preamble(src)
2689
+ src << "use HTML::Entities; ";
2690
+ end
2691
+
2692
+ def escape_text(text)
2693
+ return text.gsub!(/['\\]/, '\\\\\&') || text
2694
+ end
2695
+
2696
+ def add_text(src, text)
2697
+ src << @func << "('" << escape_text(text) << "'); " unless text.empty?
2698
+ end
2699
+
2700
+ def add_expr_literal(src, code)
2701
+ code.strip!
2702
+ src << @func << "(" << code << "); "
2703
+ end
2704
+
2705
+ def add_expr_escaped(src, code)
2706
+ add_expr_literal(src, escaped_expr(code))
2707
+ end
2708
+
2709
+ def add_expr_debug(src, code)
2710
+ code.strip!
2711
+ s = code.gsub(/\'/, "\\'")
2712
+ src << @func << "('*** debug: #{code}=', #{code}, \"\\n\");"
2713
+ end
2714
+
2715
+ def add_stmt(src, code)
2716
+ src << code
2717
+ end
2718
+
2719
+ def add_postamble(src)
2720
+ src << "\n" unless src[-1] == ?\n
2721
+ end
2722
+
2723
+ end
2724
+
2725
+
2726
+ ##
2727
+ ## engine for Perl
2728
+ ##
2729
+ class Eperl < Basic::Engine
2730
+ include PerlGenerator
2731
+ end
2732
+
2733
+
2734
+ class EscapedEperl < Eperl
2735
+ include EscapeEnhancer
2736
+ end
2737
+
2738
+
2739
+ #class XmlEperl < Eperl
2740
+ # include EscapeEnhancer
2741
+ #end
2742
+
2743
+
2744
+ class PI::Eperl < PI::Engine
2745
+ include PerlGenerator
2746
+
2747
+ def init_converter(properties={})
2748
+ @pi = 'perl'
2749
+ super(properties)
2750
+ end
2751
+
2752
+ end
2753
+
2754
+
2755
+ end
2756
+ #--end of require 'erubis/engine/eperl'
2757
+ #--begin of require 'erubis/engine/ejavascript'
2758
+ ##
2759
+ ## $Rev: 95 $
2760
+ ## $Release: 2.6.3 $
2761
+ ## copyright(c) 2006-2009 kuwata-lab.com all rights reserved.
2762
+ ##
2763
+
2764
+ #--already included require 'erubis/engine'
2765
+ #--already included require 'erubis/enhancer'
2766
+
2767
+
2768
+ module Erubis
2769
+
2770
+
2771
+ module JavascriptGenerator
2772
+ include Generator
2773
+
2774
+ def self.supported_properties() # :nodoc:
2775
+ list = []
2776
+ #list << [:indent, '', "indent spaces (ex. ' ')"]
2777
+ #list << [:buf, '_buf', "output buffer name"]
2778
+ list << [:docwrite, true, "use 'document.write()' when true"]
2779
+ return list
2780
+ end
2781
+
2782
+ def init_generator(properties={})
2783
+ super
2784
+ @escapefunc ||= 'escape'
2785
+ @indent = properties[:indent] || ''
2786
+ @buf = properties[:out] || '_buf'
2787
+ @docwrite = properties[:docwrite] != false # '!= false' will be removed in the next release
2788
+ end
2789
+
2790
+ def add_preamble(src)
2791
+ src << "#{@indent}var #{@buf} = [];"
2792
+ end
2793
+
2794
+ def escape_text(text)
2795
+ @@table_ ||= { "\r"=>"\\r", "\n"=>"\\n\\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
2796
+ return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
2797
+ end
2798
+
2799
+ def add_indent(src, indent)
2800
+ src << (src.empty? || src[-1] == ?\n ? indent : ' ')
2801
+ end
2802
+
2803
+ def add_text(src, text)
2804
+ return if text.empty?
2805
+ add_indent(src, @indent)
2806
+ src << @buf << '.push("'
2807
+ s = escape_text(text)
2808
+ if s[-1] == ?\n
2809
+ s[-2, 2] = ''
2810
+ src << s << "\");\n"
2811
+ else
2812
+ src << s << "\");"
2813
+ end
2814
+ end
2815
+
2816
+ def add_stmt(src, code)
2817
+ src << code
2818
+ end
2819
+
2820
+ def add_expr_literal(src, code)
2821
+ add_indent(src, @indent)
2822
+ code.strip!
2823
+ src << "#{@buf}.push(#{code});"
2824
+ end
2825
+
2826
+ def add_expr_escaped(src, code)
2827
+ add_expr_literal(src, escaped_expr(code))
2828
+ end
2829
+
2830
+ def add_expr_debug(src, code)
2831
+ add_indent(src, @indent)
2832
+ code.strip!
2833
+ src << "alert(\"*** debug: #{code}=\"+(#{code}));"
2834
+ end
2835
+
2836
+ def add_postamble(src)
2837
+ src << "\n" if src[-1] == ?;
2838
+ if @docwrite
2839
+ src << @indent << 'document.write(' << @buf << ".join(\"\"));\n"
2840
+ else
2841
+ src << @indent << @buf << ".join(\"\");\n"
2842
+ end
2843
+ end
2844
+
2845
+ end
2846
+
2847
+
2848
+ ##
2849
+ ## engine for JavaScript
2850
+ ##
2851
+ class Ejavascript < Basic::Engine
2852
+ include JavascriptGenerator
2853
+ end
2854
+
2855
+
2856
+ class EscapedEjavascript < Ejavascript
2857
+ include EscapeEnhancer
2858
+ end
2859
+
2860
+
2861
+ #class XmlEjavascript < Ejavascript
2862
+ # include EscapeEnhancer
2863
+ #end
2864
+
2865
+
2866
+ class PI::Ejavascript < PI::Engine
2867
+ include JavascriptGenerator
2868
+
2869
+ def init_converter(properties={})
2870
+ @pi = 'js'
2871
+ super(properties)
2872
+ end
2873
+
2874
+ end
2875
+
2876
+
2877
+ end
2878
+ #--end of require 'erubis/engine/ejavascript'
2879
+
2880
+
2881
+ module Erubis
2882
+
2883
+
2884
+ Ejs = Ejavascript
2885
+ EscapedEjs = EscapedEjavascript
2886
+
2887
+
2888
+ class CommandOptionError < ErubisError
2889
+ end
2890
+
2891
+
2892
+ ##
2893
+ ## main class of command
2894
+ ##
2895
+ ## ex.
2896
+ ## Main.main(ARGV)
2897
+ ##
2898
+ class Main
2899
+
2900
+ def self.main(argv=ARGV)
2901
+ status = 0
2902
+ begin
2903
+ Main.new.execute(ARGV)
2904
+ rescue CommandOptionError => ex
2905
+ $stderr.puts ex.message
2906
+ status = 1
2907
+ end
2908
+ exit(status)
2909
+ end
2910
+
2911
+ def initialize
2912
+ @single_options = "hvxztTSbeBXNUC"
2913
+ @arg_options = "pcrfKIlaE" #C
2914
+ @option_names = {
2915
+ 'h' => :help,
2916
+ 'v' => :version,
2917
+ 'x' => :source,
2918
+ 'z' => :syntax,
2919
+ 'T' => :unexpand,
2920
+ 't' => :untabify, # obsolete
2921
+ 'S' => :intern,
2922
+ 'b' => :bodyonly,
2923
+ 'B' => :binding,
2924
+ 'p' => :pattern,
2925
+ 'c' => :context,
2926
+ #'C' => :class,
2927
+ 'e' => :escape,
2928
+ 'r' => :requires,
2929
+ 'f' => :datafiles,
2930
+ 'K' => :kanji,
2931
+ 'I' => :includes,
2932
+ 'l' => :lang,
2933
+ 'a' => :action,
2934
+ 'E' => :enhancers,
2935
+ 'X' => :notext,
2936
+ 'N' => :linenum,
2937
+ 'U' => :unique,
2938
+ 'C' => :compact,
2939
+ }
2940
+ assert unless @single_options.length + @arg_options.length == @option_names.length
2941
+ (@single_options + @arg_options).each_byte do |ch|
2942
+ assert unless @option_names.key?(ch.chr)
2943
+ end
2944
+ end
2945
+
2946
+
2947
+ def execute(argv=ARGV)
2948
+ ## parse command-line options
2949
+ options, properties = parse_argv(argv, @single_options, @arg_options)
2950
+ filenames = argv
2951
+ options['h'] = true if properties[:help]
2952
+ opts = Object.new
2953
+ arr = @option_names.collect { |ch, name| "def #{name}; @#{name}; end\n" }
2954
+ opts.instance_eval arr.join
2955
+ options.each do |ch, val|
2956
+ name = @option_names[ch]
2957
+ opts.instance_variable_set("@#{name}", val)
2958
+ end
2959
+
2960
+ ## help, version, enhancer list
2961
+ if opts.help || opts.version
2962
+ puts version() if opts.version
2963
+ puts usage() if opts.help
2964
+ puts show_properties() if opts.help
2965
+ puts show_enhancers() if opts.help
2966
+ return
2967
+ end
2968
+
2969
+ ## include path
2970
+ opts.includes.split(/,/).each do |path|
2971
+ $: << path
2972
+ end if opts.includes
2973
+
2974
+ ## require library
2975
+ opts.requires.split(/,/).each do |library|
2976
+ require library
2977
+ end if opts.requires
2978
+
2979
+ ## action
2980
+ action = opts.action
2981
+ action ||= 'syntax' if opts.syntax
2982
+ action ||= 'convert' if opts.source || opts.notext
2983
+
2984
+ ## lang
2985
+ lang = opts.lang || 'ruby'
2986
+ action ||= 'convert' if opts.lang
2987
+
2988
+ ## class name of Eruby
2989
+ #classname = opts.class
2990
+ classname = nil
2991
+ klass = get_classobj(classname, lang, properties[:pi])
2992
+
2993
+ ## kanji code
2994
+ $KCODE = opts.kanji if opts.kanji
2995
+
2996
+ ## read context values from yaml file
2997
+ datafiles = opts.datafiles
2998
+ context = load_datafiles(datafiles, opts)
2999
+
3000
+ ## parse context data
3001
+ if opts.context
3002
+ context = parse_context_data(opts.context, opts)
3003
+ end
3004
+
3005
+ ## properties for engine
3006
+ properties[:escape] = true if opts.escape && !properties.key?(:escape)
3007
+ properties[:pattern] = opts.pattern if opts.pattern
3008
+ #properties[:trim] = false if opts.notrim
3009
+ properties[:preamble] = properties[:postamble] = false if opts.bodyonly
3010
+ properties[:pi] = nil if properties[:pi] == true
3011
+
3012
+ ## create engine and extend enhancers
3013
+ engine = klass.new(nil, properties)
3014
+ enhancers = get_enhancers(opts.enhancers)
3015
+ #enhancers.push(Erubis::EscapeEnhancer) if opts.escape
3016
+ enhancers.each do |enhancer|
3017
+ engine.extend(enhancer)
3018
+ engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
3019
+ end
3020
+
3021
+ ## no-text
3022
+ engine.extend(Erubis::NoTextEnhancer) if opts.notext
3023
+
3024
+ ## convert and execute
3025
+ val = nil
3026
+ msg = "Syntax OK\n"
3027
+ if filenames && !filenames.empty?
3028
+ filenames.each do |filename|
3029
+ test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
3030
+ engine.filename = filename
3031
+ engine.convert!(File.read(filename))
3032
+ val = do_action(action, engine, context, filename, opts)
3033
+ msg = nil if val
3034
+ end
3035
+ else
3036
+ engine.filename = filename = '(stdin)'
3037
+ engine.convert!($stdin.read())
3038
+ val = do_action(action, engine, context, filename, opts)
3039
+ msg = nil if val
3040
+ end
3041
+ print msg if action == 'syntax' && msg
3042
+
3043
+ end
3044
+
3045
+ private
3046
+
3047
+ def do_action(action, engine, context, filename, opts)
3048
+ case action
3049
+ when 'convert'
3050
+ s = manipulate_src(engine.src, opts)
3051
+ when nil, 'exec', 'execute'
3052
+ s = opts.binding ? engine.result(context.to_hash) : engine.evaluate(context)
3053
+ when 'syntax'
3054
+ s = check_syntax(filename, engine.src)
3055
+ else
3056
+ raise "*** internal error"
3057
+ end
3058
+ print s if s
3059
+ return s
3060
+ end
3061
+
3062
+ def manipulate_src(source, opts)
3063
+ flag_linenum = opts.linenum
3064
+ flag_unique = opts.unique
3065
+ flag_compact = opts.compact
3066
+ if flag_linenum
3067
+ n = 0
3068
+ source.gsub!(/^/) { n += 1; "%5d: " % n }
3069
+ source.gsub!(/^ *\d+:\s+?\n/, '') if flag_compact
3070
+ source.gsub!(/(^ *\d+:\s+?\n)+/, "\n") if flag_unique
3071
+ else
3072
+ source.gsub!(/^\s*?\n/, '') if flag_compact
3073
+ source.gsub!(/(^\s*?\n)+/, "\n") if flag_unique
3074
+ end
3075
+ return source
3076
+ end
3077
+
3078
+ def usage(command=nil)
3079
+ command ||= File.basename($0)
3080
+ buf = []
3081
+ buf << "erubis - embedded program converter for multi-language"
3082
+ buf << "Usage: #{command} [..options..] [file ...]"
3083
+ buf << " -h, --help : help"
3084
+ buf << " -v : version"
3085
+ buf << " -x : show converted code"
3086
+ buf << " -X : show converted code, only ruby code and no text part"
3087
+ buf << " -N : numbering: add line numbers (for '-x/-X')"
3088
+ buf << " -U : unique: compress empty lines to a line (for '-x/-X')"
3089
+ buf << " -C : compact: remove empty lines (for '-x/-X')"
3090
+ buf << " -b : body only: no preamble nor postamble (for '-x/-X')"
3091
+ buf << " -z : syntax checking"
3092
+ buf << " -e : escape (equal to '--E Escape')"
3093
+ buf << " -p pattern : embedded pattern (default '<% %>')"
3094
+ buf << " -l lang : convert but no execute (ruby/php/c/java/scheme/perl/js)"
3095
+ buf << " -E e1,e2,... : enhancer names (Escape, PercentLine, BiPattern, ...)"
3096
+ buf << " -I path : library include path"
3097
+ buf << " -K kanji : kanji code (euc/sjis/utf8) (default none)"
3098
+ buf << " -c context : context data string (yaml inline style or ruby code)"
3099
+ buf << " -f datafile : context data file ('*.yaml', '*.yml', or '*.rb')"
3100
+ #buf << " -t : expand tab characters in YAML file"
3101
+ buf << " -T : don't expand tab characters in YAML file"
3102
+ buf << " -S : convert mapping key from string to symbol in YAML file"
3103
+ buf << " -B : invoke 'result(binding)' instead of 'evaluate(context)'"
3104
+ buf << " --pi=name : parse '<?name ... ?>' instead of '<% ... %>'"
3105
+ #'
3106
+ # -T : don't trim spaces around '<% %>'
3107
+ # -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
3108
+ # -r library : require library
3109
+ # -a : action (convert/execute)
3110
+ return buf.join("\n")
3111
+ end
3112
+
3113
+ def collect_supported_properties(erubis_klass)
3114
+ list = []
3115
+ erubis_klass.ancestors.each do |klass|
3116
+ if klass.respond_to?(:supported_properties)
3117
+ list.concat(klass.supported_properties)
3118
+ end
3119
+ end
3120
+ return list
3121
+ end
3122
+
3123
+ def show_properties
3124
+ s = "supported properties:\n"
3125
+ basic_props = collect_supported_properties(Erubis::Basic::Engine)
3126
+ pi_props = collect_supported_properties(Erubis::PI::Engine)
3127
+ list = []
3128
+ common_props = basic_props & pi_props
3129
+ list << ['(common)', common_props]
3130
+ list << ['(basic)', basic_props - common_props]
3131
+ list << ['(pi)', pi_props - common_props]
3132
+ %w[ruby php c java scheme perl javascript].each do |lang|
3133
+ klass = Erubis.const_get("E#{lang}")
3134
+ list << [lang, collect_supported_properties(klass) - basic_props]
3135
+ end
3136
+ list.each do |lang, props|
3137
+ s << " * #{lang}\n"
3138
+ props.each do |name, default_val, desc|
3139
+ s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc])
3140
+ end
3141
+ end
3142
+ s << "\n"
3143
+ return s
3144
+ end
3145
+
3146
+ def show_enhancers
3147
+ s = "enhancers:\n"
3148
+ list = []
3149
+ ObjectSpace.each_object(Module) do |m| list << m end
3150
+ list.sort_by { |m| m.name.to_s }.each do |m|
3151
+ next unless m.name =~ /\AErubis::(.*)Enhancer\z/
3152
+ name = $1
3153
+ desc = m.desc
3154
+ s << (" %-13s : %s\n" % [name, desc])
3155
+ end
3156
+ return s
3157
+ end
3158
+
3159
+ def version
3160
+ return Erubis::VERSION
3161
+ end
3162
+
3163
+ def parse_argv(argv, arg_none='', arg_required='', arg_optional='')
3164
+ options = {}
3165
+ context = {}
3166
+ while argv[0] && argv[0][0] == ?-
3167
+ optstr = argv.shift
3168
+ optstr = optstr[1, optstr.length-1]
3169
+ #
3170
+ if optstr[0] == ?- # context
3171
+ unless optstr =~ /\A\-([-\w]+)(?:=(.*))?/
3172
+ raise CommandOptionError.new("-#{optstr}: invalid context value.")
3173
+ end
3174
+ name = $1; value = $2
3175
+ name = name.gsub(/-/, '_').intern
3176
+ #value = value.nil? ? true : YAML.load(value) # error, why?
3177
+ value = value.nil? ? true : YAML.load("---\n#{value}\n")
3178
+ context[name] = value
3179
+ #
3180
+ else # options
3181
+ while optstr && !optstr.empty?
3182
+ optchar = optstr[0].chr
3183
+ optstr[0,1] = ""
3184
+ if arg_none.include?(optchar)
3185
+ options[optchar] = true
3186
+ elsif arg_required.include?(optchar)
3187
+ arg = optstr.empty? ? argv.shift : optstr
3188
+ unless arg
3189
+ mesg = "-#{optchar}: #{@option_names[optchar]} required."
3190
+ raise CommandOptionError.new(mesg)
3191
+ end
3192
+ options[optchar] = arg
3193
+ optstr = nil
3194
+ elsif arg_optional.include?(optchar)
3195
+ arg = optstr.empty? ? true : optstr
3196
+ options[optchar] = arg
3197
+ optstr = nil
3198
+ else
3199
+ raise CommandOptionError.new("-#{optchar}: unknown option.")
3200
+ end
3201
+ end
3202
+ end
3203
+ #
3204
+ end # end of while
3205
+
3206
+ return options, context
3207
+ end
3208
+
3209
+
3210
+ def untabify(str, width=8)
3211
+ list = str.split(/\t/)
3212
+ last = list.pop
3213
+ sb = ''
3214
+ list.each do |s|
3215
+ column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
3216
+ n = width - (column % width)
3217
+ sb << s << (' ' * n)
3218
+ end
3219
+ sb << last
3220
+ return sb
3221
+ end
3222
+ #--
3223
+ #def untabify(str, width=8)
3224
+ # sb = ''
3225
+ # str.scan(/(.*?)\t/m) do |s, |
3226
+ # len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
3227
+ # sb << s << (" " * (width - len % width))
3228
+ # end
3229
+ # return $' ? (sb << $') : str
3230
+ #end
3231
+ #++
3232
+
3233
+
3234
+ def get_classobj(classname, lang, pi)
3235
+ classname ||= "E#{lang}"
3236
+ base_module = pi ? Erubis::PI : Erubis
3237
+ begin
3238
+ klass = base_module.const_get(classname)
3239
+ rescue NameError
3240
+ klass = nil
3241
+ end
3242
+ unless klass
3243
+ if lang
3244
+ msg = "-l #{lang}: invalid language name (class #{base_module.name}::#{classname} not found)."
3245
+ else
3246
+ msg = "-c #{classname}: invalid class name."
3247
+ end
3248
+ raise CommandOptionError.new(msg)
3249
+ end
3250
+ return klass
3251
+ end
3252
+
3253
+ def get_enhancers(enhancer_names)
3254
+ return [] unless enhancer_names
3255
+ enhancers = []
3256
+ shortname = nil
3257
+ begin
3258
+ enhancer_names.split(/,/).each do |name|
3259
+ shortname = name
3260
+ enhancers << Erubis.const_get("#{shortname}Enhancer")
3261
+ end
3262
+ rescue NameError
3263
+ raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-h' to show all enhancers).")
3264
+ end
3265
+ return enhancers
3266
+ end
3267
+
3268
+ def load_datafiles(filenames, opts)
3269
+ context = Erubis::Context.new
3270
+ return context unless filenames
3271
+ filenames.split(/,/).each do |filename|
3272
+ filename.strip!
3273
+ test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
3274
+ if filename =~ /\.ya?ml$/
3275
+ if opts.unexpand
3276
+ ydoc = YAML.load_file(filename)
3277
+ else
3278
+ ydoc = YAML.load(untabify(File.read(filename)))
3279
+ end
3280
+ ydoc.is_a?(Hash) or raise CommandOptionError.new("#{filename}: root object is not a mapping.")
3281
+ intern_hash_keys(ydoc) if opts.intern
3282
+ context.update(ydoc)
3283
+ elsif filename =~ /\.rb$/
3284
+ str = File.read(filename)
3285
+ context2 = Erubis::Context.new
3286
+ _instance_eval(context2, str)
3287
+ context.update(context2)
3288
+ else
3289
+ CommandOptionError.new("#{filename}: '*.yaml', '*.yml', or '*.rb' required.")
3290
+ end
3291
+ end
3292
+ return context
3293
+ end
3294
+
3295
+ def _instance_eval(_context, _str)
3296
+ _context.instance_eval(_str)
3297
+ end
3298
+
3299
+ def parse_context_data(context_str, opts)
3300
+ if context_str[0] == ?{
3301
+ require 'yaml'
3302
+ ydoc = YAML.load(context_str)
3303
+ unless ydoc.is_a?(Hash)
3304
+ raise CommandOptionError.new("-c: root object is not a mapping.")
3305
+ end
3306
+ intern_hash_keys(ydoc) if opts.intern
3307
+ return ydoc
3308
+ else
3309
+ context = Erubis::Context.new
3310
+ context.instance_eval(context_str, '-c')
3311
+ return context
3312
+ end
3313
+ end
3314
+
3315
+ def intern_hash_keys(obj, done={})
3316
+ return if done.key?(obj.__id__)
3317
+ case obj
3318
+ when Hash
3319
+ done[obj.__id__] = obj
3320
+ obj.keys.each do |key|
3321
+ obj[key.intern] = obj.delete(key) if key.is_a?(String)
3322
+ end
3323
+ obj.values.each do |val|
3324
+ intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
3325
+ end
3326
+ when Array
3327
+ done[obj.__id__] = obj
3328
+ obj.each do |val|
3329
+ intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
3330
+ end
3331
+ end
3332
+ end
3333
+
3334
+ def check_syntax(filename, src)
3335
+ require 'open3'
3336
+ command = (ENV['_'] || 'ruby') + ' -wc' # ENV['_'] stores command name
3337
+ stdin, stdout, stderr = Open3.popen3(command)
3338
+ stdin.write(src)
3339
+ stdin.close
3340
+ result = stdout.read()
3341
+ stdout.close()
3342
+ errmsg = stderr.read()
3343
+ stderr.close()
3344
+ return nil unless errmsg && !errmsg.empty?
3345
+ errmsg =~ /\A-:(\d+): /
3346
+ linenum, message = $1, $'
3347
+ return "#{filename}:#{linenum}: #{message}"
3348
+ end
3349
+
3350
+ end
3351
+
3352
+ end
3353
+ #--end of require 'erubis/main'
10
3354
 
11
3355
  Erubis::Main.main(ARGV)
OSZAR »