erubis 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. data/ChangeLog +45 -18
  2. data/README.txt +80 -0
  3. data/benchmark/erubybench-lib.rb +189 -0
  4. data/benchmark/erubybench.rb +364 -0
  5. data/benchmark/erubybench.rhtml +61 -0
  6. data/benchmark/erubybench.yaml +61 -0
  7. data/bin/erubis +4 -180
  8. data/contrib/erubis +2297 -0
  9. data/contrib/inline-require +151 -0
  10. data/doc-api/classes/Erubis.html +236 -0
  11. data/doc-api/classes/Erubis/ArrayBufferEnhancer.html +175 -0
  12. data/doc-api/classes/Erubis/ArrayBufferEruby.html +120 -0
  13. data/doc-api/classes/Erubis/ArrayEnhancer.html +174 -0
  14. data/doc-api/classes/Erubis/ArrayEruby.html +120 -0
  15. data/doc-api/classes/Erubis/BiPatternEnhancer.html +212 -0
  16. data/doc-api/classes/Erubis/BiPatternEruby.html +120 -0
  17. data/doc-api/classes/Erubis/CommandOptionError.html +113 -0
  18. data/doc-api/classes/Erubis/Context.html +249 -0
  19. data/doc-api/classes/Erubis/Ec.html +399 -0
  20. data/doc-api/classes/Erubis/Ejava.html +366 -0
  21. data/doc-api/classes/Erubis/Ejavascript.html +390 -0
  22. data/doc-api/classes/Erubis/Engine.html +711 -0
  23. data/doc-api/classes/Erubis/Eperl.html +350 -0
  24. data/doc-api/classes/Erubis/Ephp.html +308 -0
  25. data/doc-api/classes/Erubis/ErubisError.html +117 -0
  26. data/doc-api/classes/Erubis/Eruby.html +310 -0
  27. data/doc-api/classes/Erubis/EscapeEnhancer.html +167 -0
  28. data/doc-api/classes/Erubis/EscapedEc.html +120 -0
  29. data/doc-api/classes/Erubis/EscapedEjava.html +120 -0
  30. data/doc-api/classes/Erubis/EscapedEjavascript.html +120 -0
  31. data/doc-api/classes/Erubis/EscapedEperl.html +120 -0
  32. data/doc-api/classes/Erubis/EscapedEphp.html +120 -0
  33. data/doc-api/classes/Erubis/EscapedEruby.html +127 -0
  34. data/doc-api/classes/Erubis/EscapedEscheme.html +120 -0
  35. data/doc-api/classes/Erubis/Escheme.html +389 -0
  36. data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +264 -0
  37. data/doc-api/classes/Erubis/HeaderFooterEruby.html +120 -0
  38. data/doc-api/classes/Erubis/Main.html +318 -0
  39. data/doc-api/classes/Erubis/NoTextEnhancer.html +159 -0
  40. data/doc-api/classes/Erubis/NoTextEruby.html +120 -0
  41. data/doc-api/classes/Erubis/OptimizedEruby.html +445 -0
  42. data/doc-api/classes/Erubis/OptimizedXmlEruby.html +163 -0
  43. data/doc-api/classes/Erubis/PercentLineEnhancer.html +174 -0
  44. data/doc-api/classes/Erubis/PercentLineEruby.html +120 -0
  45. data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +212 -0
  46. data/doc-api/classes/Erubis/PrintEnabledEruby.html +120 -0
  47. data/doc-api/classes/Erubis/PrintOutEnhancer.html +244 -0
  48. data/doc-api/classes/Erubis/PrintOutEruby.html +120 -0
  49. data/doc-api/classes/Erubis/PrintOutSimplifiedEruby.html +121 -0
  50. data/doc-api/classes/Erubis/SimplifiedEruby.html +120 -0
  51. data/doc-api/classes/Erubis/SimplifyEnhancer.html +185 -0
  52. data/doc-api/classes/Erubis/StdoutEnhancer.html +173 -0
  53. data/doc-api/classes/Erubis/StdoutEruby.html +120 -0
  54. data/doc-api/classes/Erubis/StdoutSimplifiedEruby.html +121 -0
  55. data/doc-api/classes/Erubis/StringBufferEnhancer.html +174 -0
  56. data/doc-api/classes/Erubis/StringBufferEruby.html +120 -0
  57. data/doc-api/classes/Erubis/StringIOEruby.html +120 -0
  58. data/doc-api/classes/Erubis/TinyEruby.html +305 -0
  59. data/doc-api/classes/Erubis/XmlEruby.html +130 -0
  60. data/doc-api/classes/Erubis/XmlHelper.html +193 -0
  61. data/doc-api/created.rid +1 -0
  62. data/doc-api/files/__/README_txt.html +214 -0
  63. data/doc-api/files/erubis/engine/ec_rb.html +115 -0
  64. data/doc-api/files/erubis/engine/ejava_rb.html +115 -0
  65. data/doc-api/files/erubis/engine/ejavascript_rb.html +115 -0
  66. data/doc-api/files/erubis/engine/enhanced_rb.html +115 -0
  67. data/doc-api/files/erubis/engine/eperl_rb.html +115 -0
  68. data/doc-api/files/erubis/engine/ephp_rb.html +115 -0
  69. data/doc-api/files/erubis/engine/eruby_rb.html +115 -0
  70. data/doc-api/files/erubis/engine/escheme_rb.html +115 -0
  71. data/doc-api/files/erubis/engine/optimized_rb.html +114 -0
  72. data/doc-api/files/erubis/engine_rb.html +114 -0
  73. data/doc-api/files/erubis/enhancer_rb.html +114 -0
  74. data/doc-api/files/erubis/helper_rb.html +107 -0
  75. data/doc-api/files/erubis/local-setting_rb.html +107 -0
  76. data/doc-api/files/erubis/main_rb.html +125 -0
  77. data/doc-api/files/erubis/tiny_rb.html +107 -0
  78. data/doc-api/files/erubis_rb.html +118 -0
  79. data/doc-api/fr_class_index.html +77 -0
  80. data/doc-api/fr_file_index.html +43 -0
  81. data/doc-api/fr_method_index.html +157 -0
  82. data/doc-api/index.html +24 -0
  83. data/doc-api/rdoc-style.css +208 -0
  84. data/doc/users-guide.html +1507 -375
  85. data/examples/Makefile +53 -0
  86. data/examples/example.ec +24 -0
  87. data/examples/example.ejava +41 -0
  88. data/examples/example.ejavascript +16 -0
  89. data/examples/example.eperl +16 -0
  90. data/examples/example.ephp +17 -0
  91. data/examples/example.eruby +15 -0
  92. data/examples/example.escheme +26 -0
  93. data/lib/erubis.rb +37 -269
  94. data/lib/erubis/engine.rb +260 -0
  95. data/lib/erubis/engine/ec.rb +106 -0
  96. data/lib/erubis/engine/ejava.rb +101 -0
  97. data/lib/erubis/engine/ejavascript.rb +104 -0
  98. data/lib/erubis/engine/enhanced.rb +102 -0
  99. data/lib/erubis/engine/eperl.rb +83 -0
  100. data/lib/erubis/engine/ephp.rb +84 -0
  101. data/lib/erubis/engine/eruby.rb +91 -0
  102. data/lib/erubis/engine/escheme.rb +96 -0
  103. data/lib/erubis/engine/optimized.rb +114 -0
  104. data/lib/erubis/enhancer.rb +487 -0
  105. data/lib/erubis/helper.rb +53 -0
  106. data/lib/erubis/local-setting.rb +10 -0
  107. data/lib/erubis/main.rb +368 -0
  108. data/lib/erubis/tiny.rb +65 -0
  109. data/test/assert-text-equal.rb +45 -0
  110. data/test/test-bin.rb +222 -45
  111. data/test/test-engines.rb +343 -0
  112. data/test/test-erubis.rb +836 -501
  113. data/test/test.rb +27 -0
  114. data/test/testutil.rb +86 -0
  115. metadata +131 -8
  116. data/README +0 -50
@@ -0,0 +1,53 @@
1
+ ##
2
+ ## $Rev: 21 $
3
+ ## $Release: 2.0.0 $
4
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ##
6
+
7
+
8
+ module Erubis
9
+
10
+ ##
11
+ ## helper for xml
12
+ ##
13
+ module XmlHelper
14
+
15
+ module_function
16
+
17
+ ESCAPE_TABLE = {
18
+ '&' => '&',
19
+ '<' => '&lt;',
20
+ '>' => '&gt;',
21
+ '"' => '&quot;',
22
+ "'" => '&#039;',
23
+ }
24
+
25
+ def escape_xml(obj)
26
+ #table = ESCAPE_TABLE
27
+ #obj.to_s.gsub(/[&<>"]/) { |s| table[s] } # or /[&<>"']/
28
+ obj.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/
29
+ #obj.to_s.gsub(SCAN_REGEXP) { |s| ESCAPE_TABLE[s] }
30
+ #obj.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
31
+ end
32
+
33
+ #--
34
+ #def escape_xml(obj)
35
+ # str = obj.to_s.dup
36
+ # #str = obj.to_s
37
+ # #str = str.dup if obj.__id__ == str.__id__
38
+ # str.gsub!(/&/, '&amp;')
39
+ # str.gsub!(/</, '&lt;')
40
+ # str.gsub!(/>/, '&gt;')
41
+ # str.gsub!(/"/, '&quot;')
42
+ # str.gsub!(/'/, '&#039;')
43
+ # return str
44
+ #end
45
+ #++
46
+
47
+ alias h escape_xml
48
+ alias html_escape escape_xml
49
+
50
+ end
51
+
52
+
53
+ end
@@ -0,0 +1,10 @@
1
+ ##
2
+ ## $Rev: 13 $
3
+ ## $Release: 2.0.0 $
4
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ##
6
+
7
+ ##
8
+ ## you can add site-local settings here.
9
+ ## this files is 'require'd by erubis.rb
10
+ ##
@@ -0,0 +1,368 @@
1
+ ###
2
+ ### $Rev: 21 $
3
+ ### $Release: 2.0.0 $
4
+ ### copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ require 'yaml'
8
+ require 'erubis'
9
+ require 'erubis/tiny'
10
+ require 'erubis/engine/enhanced'
11
+ require 'erubis/engine/optimized'
12
+ require 'erubis/engine/eruby'
13
+ require 'erubis/engine/ephp'
14
+ require 'erubis/engine/ec'
15
+ require 'erubis/engine/ejava'
16
+ require 'erubis/engine/escheme'
17
+ require 'erubis/engine/eperl'
18
+ require 'erubis/engine/ejavascript'
19
+
20
+
21
+ module Erubis
22
+
23
+
24
+ Ejs = Ejavascript
25
+ EscapedEjs = EscapedEjavascript
26
+
27
+
28
+ class CommandOptionError < ErubisError
29
+ end
30
+
31
+
32
+ ##
33
+ ## main class of command
34
+ ##
35
+ ## ex.
36
+ ## Main.main(ARGV)
37
+ ##
38
+ class Main
39
+
40
+ def self.main(argv=ARGV)
41
+ status = 0
42
+ begin
43
+ Main.new.execute(ARGV)
44
+ rescue CommandOptionError => ex
45
+ $stderr.puts ex.message
46
+ status = 1
47
+ end
48
+ exit(status)
49
+ end
50
+
51
+ def initialize
52
+ @single_options = "hvxTtSbeB"
53
+ @arg_options = "pcrfKIlaE"
54
+ @option_names = {
55
+ ?h => :help,
56
+ ?v => :version,
57
+ ?x => :source,
58
+ ?T => :notrim,
59
+ ?t => :untabify,
60
+ ?S => :intern,
61
+ ?b => :bodyonly,
62
+ ?B => :binding,
63
+ ?p => :pattern,
64
+ ?c => :class,
65
+ ?e => :escape,
66
+ ?r => :requires,
67
+ ?f => :yamlfiles,
68
+ ?K => :kanji,
69
+ ?I => :includes,
70
+ ?l => :lang,
71
+ ?a => :action,
72
+ ?E => :enhancers,
73
+ }
74
+ assert unless @single_options.length + @arg_options.length == @option_names.length
75
+ (@single_options + @arg_options).each_byte do |ch|
76
+ assert unless @option_names.key?(ch)
77
+ end
78
+ end
79
+
80
+
81
+ def execute(argv=ARGV)
82
+ ## parse command-line options
83
+ options, properties = parse_argv(argv, @single_options, @arg_options)
84
+ filenames = argv
85
+ options[?h] = true if properties[:help]
86
+ opts = Object.new
87
+ arr = @option_names.collect { |ch, name| "def #{name}; @#{name}; end\n" }
88
+ opts.instance_eval arr.join
89
+ options.each do |ch, val|
90
+ name = @option_names[ch]
91
+ opts.instance_variable_set("@#{name}", val)
92
+ end
93
+
94
+ ## help, version, enhancer list
95
+ if opts.help || opts.version
96
+ puts version() if opts.version
97
+ puts usage() if opts.help
98
+ puts show_properties() if opts.help
99
+ puts show_enhancers() if opts.help
100
+ return
101
+ end
102
+
103
+ ## include path
104
+ opts.includes.split(/,/).each do |path|
105
+ $: << path
106
+ end if opts.includes
107
+
108
+ ## require library
109
+ opts.requires.split(/,/).each do |library|
110
+ require library
111
+ end if opts.requires
112
+
113
+ ## action
114
+ action = opts.action
115
+ action ||= 'compile' if opts.source
116
+
117
+ ## lang
118
+ lang = opts.lang || 'ruby'
119
+ action ||= 'compile' if opts.lang
120
+
121
+ ## class name of Eruby
122
+ classname = opts.class
123
+ klass = get_classobj(classname, lang)
124
+
125
+ ## kanji code
126
+ $KCODE = opts.kanji if opts.kanji
127
+
128
+ ## read context values from yaml file
129
+ yamlfiles = opts.yamlfiles
130
+ context = load_yamlfiles(yamlfiles, opts)
131
+
132
+ ## properties for engine
133
+ properties[:pattern] = opts.pattern if opts.pattern
134
+ properties[:trim] = false if opts.notrim
135
+ properties[:preamble] = properties[:postamble] = false if opts.bodyonly
136
+
137
+ ## create engine and extend enhancers
138
+ engine = klass.new(nil, properties)
139
+ enhancers = get_enhancers(opts.enhancers)
140
+ enhancers.push(Erubis::EscapeEnhancer) if opts.escape
141
+ enhancers.each do |enhancer|
142
+ engine.extend(enhancer)
143
+ engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
144
+ end
145
+
146
+ ## compile and execute
147
+ val = nil
148
+ if filenames && !filenames.empty?
149
+ filenames.each do |filename|
150
+ test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
151
+ engine.filename = filename
152
+ engine.compile!(File.read(filename))
153
+ print val if val = do_action(action, engine, context, opts)
154
+ end
155
+ else
156
+ engine.filename = '(stdin)'
157
+ engine.compile!($stdin.read())
158
+ print val if val = do_action(action, engine, context, opts)
159
+ end
160
+
161
+ end
162
+
163
+ private
164
+
165
+ def do_action(action, engine, context, opts)
166
+ case action
167
+ when 'compile'
168
+ s = engine.src
169
+ when nil, 'exec', 'execute'
170
+ s = opts.binding ? engine.result(context) : engine.evaluate(context)
171
+ else
172
+ raise "*** internal error"
173
+ end
174
+ return s
175
+ end
176
+
177
+ def usage
178
+ command = File.basename($0)
179
+ s = <<'END'
180
+ erubis - embedded program compiler for multi-language
181
+ Usage: #{command} [..options..] [file ...]
182
+ -h, --help : help
183
+ -v : version
184
+ -x : compiled code
185
+ -T : don't trim spaces around '<% %>'
186
+ -b : body only (no preamble nor postamble)
187
+ -e : escape (equal to '--E Escape')
188
+ -p pattern : embedded pattern (default '<% %>')
189
+ -l lang : compile but no execute (ruby/php/c/java/scheme/perl/js)
190
+ -E enhancer,... : enhancer name (Escape, PercentLine, BiPattern, ...)
191
+ -I path : library include path
192
+ -K kanji : kanji code (euc/sjis/utf8) (default none)
193
+ -f file.yaml : YAML file for context values (read stdin if filename is '-')
194
+ -t : expand tab character in YAML file
195
+ -S : convert mapping key from string to symbol in YAML file
196
+ -B : invoke 'result(binding)' instead of 'evaluate(context)'
197
+
198
+ END
199
+ # -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
200
+ # -r library : require library
201
+ # -a : action (compile/execute)
202
+ return s
203
+ end
204
+
205
+ def show_properties
206
+ s = "supported properties:\n"
207
+ %w[(common) ruby php c java scheme perl javascript].each do |lang|
208
+ list = Erubis::Engine.supported_properties
209
+ if lang != '(common)'
210
+ klass = Erubis.const_get("E#{lang}")
211
+ list = klass.supported_properties - list
212
+ end
213
+ s << " * #{lang}\n"
214
+ list.each do |name, default_val, desc|
215
+ s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc])
216
+ end
217
+ end
218
+ s << "\n"
219
+ return s
220
+ end
221
+
222
+ def show_enhancers
223
+ s = "enhancers:\n"
224
+ list = []
225
+ ObjectSpace.each_object(Module) do |m| list << m end
226
+ list.sort_by { |m| m.name }.each do |m|
227
+ next unless m.name =~ /\AErubis::(.*)Enhancer\z/
228
+ name = $1
229
+ desc = m.desc
230
+ s << (" %-13s : %s\n" % [name, desc])
231
+ end
232
+ return s
233
+ end
234
+
235
+ def version
236
+ release = ('$Release: 2.0.0 $' =~ /([.\d]+)/) && $1
237
+ return release
238
+ end
239
+
240
+ def parse_argv(argv, arg_none='', arg_required='', arg_optional='')
241
+ options = {}
242
+ context = {}
243
+ while argv[0] && argv[0][0] == ?-
244
+ optstr = argv.shift
245
+ optstr = optstr[1, optstr.length-1]
246
+ #
247
+ if optstr[0] == ?- # context
248
+ unless optstr =~ /\A\-([-\w]+)(?:=(.*))?/
249
+ raise CommandOptionError.new("-#{optstr}: invalid context value.")
250
+ end
251
+ name = $1; value = $2
252
+ name = name.gsub(/-/, '_').intern
253
+ #value = value.nil? ? true : YAML.load(value) # error, why?
254
+ value = value.nil? ? true : YAML.load("---\n#{value}\n")
255
+ context[name] = value
256
+ #
257
+ else # options
258
+ while optstr && !optstr.empty?
259
+ optchar = optstr[0]
260
+ optstr[0,1] = ""
261
+ if arg_none.include?(optchar)
262
+ options[optchar] = true
263
+ elsif arg_required.include?(optchar)
264
+ arg = optstr.empty? ? argv.shift : optstr
265
+ unless arg
266
+ mesg = "-#{optchar.chr}: #{@option_args[optchar]} required."
267
+ raise CommandOptionError.new(mesg)
268
+ end
269
+ options[optchar] = arg
270
+ optstr = nil
271
+ elsif arg_optional.include?(optchar)
272
+ arg = optstr.empty? ? true : optstr
273
+ options[optchar] = arg
274
+ optstr = nil
275
+ else
276
+ raise CommandOptionError.new("-#{optchar.chr}: unknown option.")
277
+ end
278
+ end
279
+ end
280
+ #
281
+ end # end of while
282
+
283
+ return options, context
284
+ end
285
+
286
+ def untabify(text, width=8)
287
+ sb = ''
288
+ text.scan(/(.*?)\t/m) do |s, |
289
+ len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
290
+ sb << s << (" " * (width - len % width))
291
+ end
292
+ return $' ? (sb << $') : text
293
+ end
294
+
295
+ def get_classobj(classname, lang)
296
+ unless classname
297
+ classname = lang =~ /\Axml(.*)/ ? "EscapedE#{$1}" : "E#{lang}"
298
+ end
299
+ begin
300
+ klass = Erubis.const_get(classname)
301
+ rescue NameError
302
+ klass = nil
303
+ end
304
+ unless klass
305
+ if lang
306
+ msg = "-l #{lang}: invalid language name (class Erubis::#{classname} not found)."
307
+ else
308
+ msg = "-c #{classname}: invalid class name."
309
+ end
310
+ raise CommandOptionError.new(msg)
311
+ end
312
+ return klass
313
+ end
314
+
315
+ def get_enhancers(enhancer_names)
316
+ return [] unless enhancer_names
317
+ enhancers = []
318
+ shortname = nil
319
+ begin
320
+ enhancer_names.split(/,/).each do |shortname|
321
+ enhancers << Erubis.const_get("#{shortname}Enhancer")
322
+ end
323
+ rescue NameError
324
+ raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-E' to show all enhancers).")
325
+ end
326
+ return enhancers
327
+ end
328
+
329
+ def load_yamlfiles(yamlfiles, opts)
330
+ hash = {}
331
+ return hash unless yamlfiles
332
+ yamlfiles.split(/,/).each do |yamlfile|
333
+ if yamlfile == '-'
334
+ str = $stdin.read()
335
+ else
336
+ test(?f, yamlfile) or raise CommandOptionError.new("#{yamlfile}: file not found.")
337
+ str = File.read(yamlfile)
338
+ end
339
+ str = yamlfile == '-' ? $stdin.read() : File.read(yamlfile)
340
+ str = untabify(str) if opts.untabify
341
+ ydoc = YAML.load(str)
342
+ unless ydoc.is_a?(Hash)
343
+ raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
344
+ end
345
+ convert_mapping_key_from_string_to_symbol(ydoc) if opts.intern
346
+ hash.update(ydoc)
347
+ end
348
+ context = hash
349
+ return context
350
+ end
351
+
352
+ def convert_mapping_key_from_string_to_symbol(ydoc)
353
+ if ydoc.is_a?(Hash)
354
+ ydoc.each do |key, val|
355
+ ydoc[key.intern] = ydoc.delete(key) if key.is_a?(String)
356
+ convert_mapping_key_from_string_to_symbol(val)
357
+ end
358
+ elsif ydoc.is_a?(Array)
359
+ ydoc.each do |val|
360
+ convert_mapping_key_from_string_to_symbol(val)
361
+ end
362
+ end
363
+ return ydoc
364
+ end
365
+
366
+ end
367
+
368
+ end
@@ -0,0 +1,65 @@
1
+ ##
2
+ ## $Rev: 21 $
3
+ ## $Release: 2.0.0 $
4
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
5
+ ##
6
+
7
+ module Erubis
8
+
9
+ ##
10
+ ## tiny and the simplest implementation of eRuby
11
+ ##
12
+ ## ex.
13
+ ## eruby = TinyEruby.new(File.read('example.rhtml'))
14
+ ## print eruby.src # print ruby code
15
+ ## print eruby.result(binding()) # eval ruby code with Binding object
16
+ ## print eruby.evalute(context) # eval ruby code with context object
17
+ ##
18
+ class TinyEruby
19
+
20
+ def initialize(input)
21
+ @src = compile(input)
22
+ end
23
+ attr_reader :src
24
+
25
+ EMBEDDED_PATTERN = /(.*?)<%(=+|\#)?(.*?)-?%>/m
26
+
27
+ def compile(input)
28
+ src = "_buf = [];" # preamble
29
+ input.scan(EMBEDDED_PATTERN) do |text, indicator, code|
30
+ src << " _buf << '" << escape_text(text) << "';"
31
+ if !indicator # <% %>
32
+ src << code << ";"
33
+ elsif indicator[0] == ?\# # <%# %>
34
+ n = code.count("\n")
35
+ add_stmt(src, "\n" * n)
36
+ else # <%= %>
37
+ src << " _buf << (" << code << ").to_s;"
38
+ end
39
+ end
40
+ rest = $' || input
41
+ src << " _buf << '" << escape_text(rest) << "';"
42
+ src << "\n_buf.join\n" # postamble
43
+ return src
44
+ end
45
+
46
+ def escape_text(text)
47
+ return text.gsub!(/['\\]/, '\\\\\&') || text
48
+ end
49
+
50
+ def result(binding=TOPLEVEL_BINDING)
51
+ eval @src, binding
52
+ end
53
+
54
+ def evaluate(context=Object.new)
55
+ if context.is_a?(Hash)
56
+ obj = Object.new
57
+ context.each do |k, v| obj.instance_variable_set("@#{k}", v) end
58
+ context = obj
59
+ end
60
+ context.instance_eval @src
61
+ end
62
+
63
+ end
64
+
65
+ end