erubis-bmp 2.7.0.bmp

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES.txt +828 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.txt +10 -0
  5. data/benchmark/bench.rb +313 -0
  6. data/benchmark/bench_context.yaml +141 -0
  7. data/benchmark/mybench2.rb +266 -0
  8. data/benchmark/pibench.rb +163 -0
  9. data/benchmark/templates/_footer.html +4 -0
  10. data/benchmark/templates/_header.html +52 -0
  11. data/benchmark/templates/bench_erb.rhtml +29 -0
  12. data/benchmark/templates/bench_erubis.rhtml +29 -0
  13. data/benchmark/templates/bench_eruby.rhtml +29 -0
  14. data/bin/erubis +10 -0
  15. data/contrib/erubis-run.rb +132 -0
  16. data/doc/Rookbook.yaml +106 -0
  17. data/doc/docstyle.css +209 -0
  18. data/doc/users-guide.html +3551 -0
  19. data/doc/users-guide.txt +3631 -0
  20. data/examples/basic/Makefile +58 -0
  21. data/examples/basic/example.ec +42 -0
  22. data/examples/basic/example.ecpp +33 -0
  23. data/examples/basic/example.ejava +45 -0
  24. data/examples/basic/example.ejs +16 -0
  25. data/examples/basic/example.eperl +16 -0
  26. data/examples/basic/example.ephp +17 -0
  27. data/examples/basic/example.eruby +15 -0
  28. data/examples/basic/example.escheme +26 -0
  29. data/examples/pi-xhtml/ExamplePage.xhtml +80 -0
  30. data/examples/pi-xhtml/Makefile +17 -0
  31. data/examples/pi-xhtml/my/User.java +19 -0
  32. data/examples/pi-xhtml/my/Util.java +54 -0
  33. data/examples/pi/Makefile +54 -0
  34. data/examples/pi/example.ec +42 -0
  35. data/examples/pi/example.ejava +45 -0
  36. data/examples/pi/example.ejs +16 -0
  37. data/examples/pi/example.eperl +16 -0
  38. data/examples/pi/example.ephp +17 -0
  39. data/examples/pi/example.eruby +15 -0
  40. data/examples/pi/example.escheme +26 -0
  41. data/lib/erubis.rb +73 -0
  42. data/lib/erubis/context.rb +83 -0
  43. data/lib/erubis/converter.rb +357 -0
  44. data/lib/erubis/engine.rb +120 -0
  45. data/lib/erubis/engine/ec.rb +117 -0
  46. data/lib/erubis/engine/ecpp.rb +113 -0
  47. data/lib/erubis/engine/ejava.rb +110 -0
  48. data/lib/erubis/engine/ejavascript.rb +119 -0
  49. data/lib/erubis/engine/enhanced.rb +126 -0
  50. data/lib/erubis/engine/eperl.rb +95 -0
  51. data/lib/erubis/engine/ephp.rb +99 -0
  52. data/lib/erubis/engine/eruby.rb +125 -0
  53. data/lib/erubis/engine/escheme.rb +114 -0
  54. data/lib/erubis/engine/optimized.rb +127 -0
  55. data/lib/erubis/enhancer.rb +723 -0
  56. data/lib/erubis/error.rb +23 -0
  57. data/lib/erubis/evaluator.rb +88 -0
  58. data/lib/erubis/generator.rb +85 -0
  59. data/lib/erubis/helper.rb +47 -0
  60. data/lib/erubis/helpers/rails_form_helper.rb +197 -0
  61. data/lib/erubis/helpers/rails_helper.rb +353 -0
  62. data/lib/erubis/local-setting.rb +9 -0
  63. data/lib/erubis/main.rb +516 -0
  64. data/lib/erubis/preprocessing.rb +58 -0
  65. data/lib/erubis/tiny.rb +144 -0
  66. data/lib/erubis/util.rb +22 -0
  67. data/setup.rb +1331 -0
  68. data/test/Rookbook.yaml +42 -0
  69. data/test/assert-text-equal.rb +44 -0
  70. data/test/test-engines.rb +425 -0
  71. data/test/test-enhancers.rb +646 -0
  72. data/test/test-erubis.rb +887 -0
  73. data/test/test-index-cgi.rb +191 -0
  74. data/test/test-main.rb +752 -0
  75. data/test/test-users-guide.rb +73 -0
  76. data/test/test.rb +45 -0
  77. data/test/testutil.rb +111 -0
  78. metadata +121 -0
@@ -0,0 +1,114 @@
1
+ ##
2
+ ## $Release:$
3
+ ## $Copyright$
4
+ ##
5
+
6
+ require 'erubis/engine'
7
+ require 'erubis/enhancer'
8
+
9
+
10
+ module Erubis
11
+
12
+
13
+ module SchemeGenerator
14
+ include Generator
15
+
16
+ def self.supported_properties() # :nodoc:
17
+ return [
18
+ [:func, '_add', "function name (ex. 'display')"],
19
+ ]
20
+ end
21
+
22
+ def init_generator(properties={})
23
+ super
24
+ @escapefunc ||= 'escape'
25
+ @func = properties[:func] || '_add' # or 'display'
26
+ end
27
+
28
+ def add_preamble(src)
29
+ return unless @func == '_add'
30
+ src << "(let ((_buf '())) " + \
31
+ "(define (_add x) (set! _buf (cons x _buf))) "
32
+ #src << "(let* ((_buf '())" + \
33
+ # " (_add (lambda (x) (set! _buf (cons x _buf))))) "
34
+ end
35
+
36
+ def escape_text(text)
37
+ @table_ ||= { '"'=>'\\"', '\\'=>'\\\\' }
38
+ text.gsub!(/["\\]/) { |m| @table_[m] }
39
+ return text
40
+ end
41
+
42
+ def escaped_expr(code)
43
+ code.strip!
44
+ return "(#{@escapefunc} #{code})"
45
+ end
46
+
47
+ def add_text(src, text)
48
+ return if text.empty?
49
+ t = escape_text(text)
50
+ if t[-1] == ?\n
51
+ t[-1, 1] = ''
52
+ src << "(#{@func} \"" << t << "\\n\")\n"
53
+ else
54
+ src << "(#{@func} \"" << t << '")'
55
+ end
56
+ end
57
+
58
+ def add_stmt(src, code)
59
+ src << code
60
+ end
61
+
62
+ def add_expr_literal(src, code)
63
+ code.strip!
64
+ src << "(#{@func} #{code})"
65
+ end
66
+
67
+ def add_expr_escaped(src, code)
68
+ add_expr_literal(src, escaped_expr(code))
69
+ end
70
+
71
+ def add_expr_debug(src, code)
72
+ s = (code.strip! || code).gsub(/\"/, '\\"')
73
+ src << "(display \"*** debug: #{s}=\")(display #{code.strip})(display \"\\n\")"
74
+ end
75
+
76
+ def add_postamble(src)
77
+ return unless @func == '_add'
78
+ src << "\n" unless src[-1] == ?\n
79
+ src << " (reverse _buf))\n"
80
+ end
81
+
82
+ end
83
+
84
+
85
+ ##
86
+ ## engine for Scheme
87
+ ##
88
+ class Escheme < Basic::Engine
89
+ include SchemeGenerator
90
+ end
91
+
92
+
93
+ class EscapedEscheme < Escheme
94
+ include EscapeEnhancer
95
+ end
96
+
97
+
98
+ #class XmlEscheme < Escheme
99
+ # include EscapeEnhancer
100
+ #end
101
+
102
+
103
+ class PI::Escheme < PI::Engine
104
+ include SchemeGenerator
105
+
106
+ def init_converter(properties={})
107
+ @pi = 'scheme'
108
+ super(properties)
109
+ end
110
+
111
+ end
112
+
113
+
114
+ end
@@ -0,0 +1,127 @@
1
+ ##
2
+ ## $Release:$
3
+ ## $Copyright$
4
+ ##
5
+
6
+
7
+ require 'erubis/engine/eruby'
8
+
9
+
10
+ module Erubis
11
+
12
+
13
+ module OptimizedGenerator
14
+ include Generator
15
+
16
+ def self.supported_properties() # :nodoc:
17
+ return []
18
+ end
19
+
20
+ def init_generator(properties={})
21
+ super
22
+ @escapefunc ||= "Erubis::XmlHelper.escape_xml"
23
+ @initialized = false
24
+ @prev_is_expr = false
25
+ end
26
+
27
+ protected
28
+
29
+ def escape_text(text)
30
+ text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\'
31
+ end
32
+
33
+ def escaped_expr(code)
34
+ @escapefunc ||= 'Erubis::XmlHelper.escape_xml'
35
+ return "#{@escapefunc}(#{code})"
36
+ end
37
+
38
+ def switch_to_expr(src)
39
+ return if @prev_is_expr
40
+ @prev_is_expr = true
41
+ src << ' _buf'
42
+ end
43
+
44
+ def switch_to_stmt(src)
45
+ return unless @prev_is_expr
46
+ @prev_is_expr = false
47
+ src << ';'
48
+ end
49
+
50
+ def add_preamble(src)
51
+ #@initialized = false
52
+ #@prev_is_expr = false
53
+ end
54
+
55
+ def add_text(src, text)
56
+ return if text.empty?
57
+ if @initialized
58
+ switch_to_expr(src)
59
+ src << " << '" << escape_text(text) << "'"
60
+ else
61
+ src << "_buf = '" << escape_text(text) << "';"
62
+ @initialized = true
63
+ end
64
+ end
65
+
66
+ def add_stmt(src, code)
67
+ switch_to_stmt(src) if @initialized
68
+ #super
69
+ src << code
70
+ src << ';' unless code[-1] == ?\n
71
+ end
72
+
73
+ def add_expr_literal(src, code)
74
+ unless @initialized; src << "_buf = ''"; @initialized = true; end
75
+ switch_to_expr(src)
76
+ src << " << (" << code << ").to_s"
77
+ end
78
+
79
+ def add_expr_escaped(src, code)
80
+ unless @initialized; src << "_buf = ''"; @initialized = true; end
81
+ switch_to_expr(src)
82
+ src << " << " << escaped_expr(code)
83
+ end
84
+
85
+ def add_expr_debug(src, code)
86
+ code.strip!
87
+ s = (code.dump =~ /\A"(.*)"\z/) && $1
88
+ src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
89
+ end
90
+
91
+ def add_postamble(src)
92
+ #super if @initialized
93
+ src << "\n_buf\n" if @initialized
94
+ end
95
+
96
+ end # end of class OptimizedEruby
97
+
98
+
99
+ ##
100
+ ## Eruby class which generates optimized ruby code
101
+ ##
102
+ class OptimizedEruby < Basic::Engine # Eruby
103
+ include RubyEvaluator
104
+ include OptimizedGenerator
105
+
106
+ def init_converter(properties={})
107
+ @pi = 'rb'
108
+ super(properties)
109
+ end
110
+
111
+ end
112
+
113
+
114
+ ##
115
+ ## XmlEruby class which generates optimized ruby code
116
+ ##
117
+ class OptimizedXmlEruby < OptimizedEruby
118
+ include EscapeEnhancer
119
+
120
+ def add_expr_debug(src, code)
121
+ switch_to_stmt(src) if indicator == '===' && !@initialized
122
+ super
123
+ end
124
+
125
+ end # end of class OptimizedXmlEruby
126
+
127
+ end
@@ -0,0 +1,723 @@
1
+ ##
2
+ ## $Release:$
3
+ ## $Copyright$
4
+ ##
5
+
6
+
7
+ module Erubis
8
+
9
+
10
+ ##
11
+ ## switch '<%= ... %>' to escaped and '<%== ... %>' to unescaped
12
+ ##
13
+ ## ex.
14
+ ## class XmlEruby < Eruby
15
+ ## include EscapeEnhancer
16
+ ## end
17
+ ##
18
+ ## this is language-indenedent.
19
+ ##
20
+ module EscapeEnhancer
21
+
22
+ def self.desc # :nodoc:
23
+ "switch '<%= %>' to escaped and '<%== %>' to unescaped"
24
+ end
25
+
26
+ #--
27
+ #def self.included(klass)
28
+ # klass.class_eval <<-END
29
+ # alias _add_expr_literal add_expr_literal
30
+ # alias _add_expr_escaped add_expr_escaped
31
+ # alias add_expr_literal _add_expr_escaped
32
+ # alias add_expr_escaped _add_expr_literal
33
+ # END
34
+ #end
35
+ #++
36
+
37
+ def add_expr(src, code, indicator)
38
+ case indicator
39
+ when '='
40
+ @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
41
+ when '=='
42
+ @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
43
+ when '==='
44
+ add_expr_debug(src, code)
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+
51
+ #--
52
+ ## (obsolete)
53
+ #module FastEnhancer
54
+ #end
55
+ #++
56
+
57
+
58
+ ##
59
+ ## use $stdout instead of string
60
+ ##
61
+ ## this is only for Eruby.
62
+ ##
63
+ module StdoutEnhancer
64
+
65
+ def self.desc # :nodoc:
66
+ "use $stdout instead of array buffer or string buffer"
67
+ end
68
+
69
+ def add_preamble(src)
70
+ src << "#{@bufvar} = $stdout;"
71
+ end
72
+
73
+ def add_postamble(src)
74
+ src << "\n''\n"
75
+ end
76
+
77
+ end
78
+
79
+
80
+ ##
81
+ ## use print statement instead of '_buf << ...'
82
+ ##
83
+ ## this is only for Eruby.
84
+ ##
85
+ module PrintOutEnhancer
86
+
87
+ def self.desc # :nodoc:
88
+ "use print statement instead of '_buf << ...'"
89
+ end
90
+
91
+ def add_preamble(src)
92
+ end
93
+
94
+ def add_text(src, text)
95
+ src << " print '#{escape_text(text)}';" unless text.empty?
96
+ end
97
+
98
+ def add_expr_literal(src, code)
99
+ src << " print((#{code}).to_s);"
100
+ end
101
+
102
+ def add_expr_escaped(src, code)
103
+ src << " print #{escaped_expr(code)};"
104
+ end
105
+
106
+ def add_postamble(src)
107
+ src << "\n" unless src[-1] == ?\n
108
+ end
109
+
110
+ end
111
+
112
+
113
+ ##
114
+ ## enable print function
115
+ ##
116
+ ## Notice: use Eruby#evaluate() and don't use Eruby#result()
117
+ ## to be enable print function.
118
+ ##
119
+ ## this is only for Eruby.
120
+ ##
121
+ module PrintEnabledEnhancer
122
+
123
+ def self.desc # :nodoc:
124
+ "enable to use print function in '<% %>'"
125
+ end
126
+
127
+ def add_preamble(src)
128
+ src << "@_buf = "
129
+ super
130
+ end
131
+
132
+ def print(*args)
133
+ args.each do |arg|
134
+ @_buf << arg.to_s
135
+ end
136
+ end
137
+
138
+ def evaluate(context=nil)
139
+ _src = @src
140
+ if context.is_a?(Hash)
141
+ context.each do |key, val| instance_variable_set("@#{key}", val) end
142
+ elsif context
143
+ context.instance_variables.each do |name|
144
+ instance_variable_set(name, context.instance_variable_get(name))
145
+ end
146
+ end
147
+ return instance_eval(_src, (@filename || '(erubis)'))
148
+ end
149
+
150
+ end
151
+
152
+
153
+ ##
154
+ ## return array instead of string
155
+ ##
156
+ ## this is only for Eruby.
157
+ ##
158
+ module ArrayEnhancer
159
+
160
+ def self.desc # :nodoc:
161
+ "return array instead of string"
162
+ end
163
+
164
+ def add_preamble(src)
165
+ src << "#{@bufvar} = [];"
166
+ end
167
+
168
+ def add_postamble(src)
169
+ src << "\n" unless src[-1] == ?\n
170
+ src << "#{@bufvar}\n"
171
+ end
172
+
173
+ end
174
+
175
+
176
+ ##
177
+ ## use an Array object as buffer (included in Eruby by default)
178
+ ##
179
+ ## this is only for Eruby.
180
+ ##
181
+ module ArrayBufferEnhancer
182
+
183
+ def self.desc # :nodoc:
184
+ "use an Array object for buffering (included in Eruby class)"
185
+ end
186
+
187
+ def add_preamble(src)
188
+ src << "_buf = [];"
189
+ end
190
+
191
+ def add_postamble(src)
192
+ src << "\n" unless src[-1] == ?\n
193
+ src << "_buf.join\n"
194
+ end
195
+
196
+ end
197
+
198
+
199
+ ##
200
+ ## use String class for buffering
201
+ ##
202
+ ## this is only for Eruby.
203
+ ##
204
+ module StringBufferEnhancer
205
+
206
+ def self.desc # :nodoc:
207
+ "use a String object for buffering"
208
+ end
209
+
210
+ def add_preamble(src)
211
+ src << "#{@bufvar} = '';"
212
+ end
213
+
214
+ def add_postamble(src)
215
+ src << "\n" unless src[-1] == ?\n
216
+ src << "#{@bufvar}.to_s\n"
217
+ end
218
+
219
+ end
220
+
221
+
222
+ ##
223
+ ## use StringIO class for buffering
224
+ ##
225
+ ## this is only for Eruby.
226
+ ##
227
+ module StringIOEnhancer # :nodoc:
228
+
229
+ def self.desc # :nodoc:
230
+ "use a StringIO object for buffering"
231
+ end
232
+
233
+ def add_preamble(src)
234
+ src << "#{@bufvar} = StringIO.new;"
235
+ end
236
+
237
+ def add_postamble(src)
238
+ src << "\n" unless src[-1] == ?\n
239
+ src << "#{@bufvar}.string\n"
240
+ end
241
+
242
+ end
243
+
244
+
245
+ ##
246
+ ## set buffer variable name to '_erbout' as well as '_buf'
247
+ ##
248
+ ## this is only for Eruby.
249
+ ##
250
+ module ErboutEnhancer
251
+
252
+ def self.desc # :nodoc:
253
+ "set '_erbout = _buf = \"\";' to be compatible with ERB."
254
+ end
255
+
256
+ def add_preamble(src)
257
+ src << "_erbout = #{@bufvar} = '';"
258
+ end
259
+
260
+ def add_postamble(src)
261
+ src << "\n" unless src[-1] == ?\n
262
+ src << "#{@bufvar}.to_s\n"
263
+ end
264
+
265
+ end
266
+
267
+
268
+ ##
269
+ ## remove text and leave code, especially useful when debugging.
270
+ ##
271
+ ## ex.
272
+ ## $ erubis -s -E NoText file.eruby | more
273
+ ##
274
+ ## this is language independent.
275
+ ##
276
+ module NoTextEnhancer
277
+
278
+ def self.desc # :nodoc:
279
+ "remove text and leave code (useful when debugging)"
280
+ end
281
+
282
+ def add_text(src, text)
283
+ src << ("\n" * text.count("\n"))
284
+ if text[-1] != ?\n
285
+ text =~ /^(.*?)\z/
286
+ src << (' ' * $1.length)
287
+ end
288
+ end
289
+
290
+ end
291
+
292
+
293
+ ##
294
+ ## remove code and leave text, especially useful when validating HTML tags.
295
+ ##
296
+ ## ex.
297
+ ## $ erubis -s -E NoCode file.eruby | tidy -errors
298
+ ##
299
+ ## this is language independent.
300
+ ##
301
+ module NoCodeEnhancer
302
+
303
+ def self.desc # :nodoc:
304
+ "remove code and leave text (useful when validating HTML)"
305
+ end
306
+
307
+ def add_preamble(src)
308
+ end
309
+
310
+ def add_postamble(src)
311
+ end
312
+
313
+ def add_text(src, text)
314
+ src << text
315
+ end
316
+
317
+ def add_expr(src, code, indicator)
318
+ src << "\n" * code.count("\n")
319
+ end
320
+
321
+ def add_stmt(src, code)
322
+ src << "\n" * code.count("\n")
323
+ end
324
+
325
+ end
326
+
327
+
328
+ ##
329
+ ## get convert faster, but spaces around '<%...%>' are not trimmed.
330
+ ##
331
+ ## this is language-independent.
332
+ ##
333
+ module SimplifyEnhancer
334
+
335
+ def self.desc # :nodoc:
336
+ "get convert faster but leave spaces around '<% %>'"
337
+ end
338
+
339
+ #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
340
+ SIMPLE_REGEXP = /<%(=+|\#)?(.*?)-?%>/m
341
+
342
+ def convert(input)
343
+ src = ""
344
+ add_preamble(src)
345
+ #regexp = pattern_regexp(@pattern)
346
+ pos = 0
347
+ input.scan(SIMPLE_REGEXP) do |indicator, code|
348
+ match = Regexp.last_match
349
+ index = match.begin(0)
350
+ text = input[pos, index - pos]
351
+ pos = match.end(0)
352
+ add_text(src, text)
353
+ if !indicator # <% %>
354
+ add_stmt(src, code)
355
+ elsif indicator[0] == ?\# # <%# %>
356
+ n = code.count("\n")
357
+ add_stmt(src, "\n" * n)
358
+ else # <%= %>
359
+ add_expr(src, code, indicator)
360
+ end
361
+ end
362
+ #rest = $' || input # ruby1.8
363
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
364
+ add_text(src, rest)
365
+ add_postamble(src)
366
+ return src
367
+ end
368
+
369
+ end
370
+
371
+
372
+ ##
373
+ ## enable to use other embedded expression pattern (default is '\[= =\]').
374
+ ##
375
+ ## notice! this is an experimental. spec may change in the future.
376
+ ##
377
+ ## ex.
378
+ ## input = <<END
379
+ ## <% for item in list %>
380
+ ## <%= item %> : <%== item %>
381
+ ## [= item =] : [== item =]
382
+ ## <% end %>
383
+ ## END
384
+ ##
385
+ ## class BiPatternEruby
386
+ ## include BiPatternEnhancer
387
+ ## end
388
+ ## eruby = BiPatternEruby.new(input, :bipattern=>'\[= =\]')
389
+ ## list = ['<a>', 'b&b', '"c"']
390
+ ## print eruby.result(binding())
391
+ ##
392
+ ## ## output
393
+ ## <a> : &lt;a&gt;
394
+ ## <a> : &lt;a&gt;
395
+ ## b&b : b&amp;b
396
+ ## b&b : b&amp;b
397
+ ## "c" : &quot;c&quot;
398
+ ## "c" : &quot;c&quot;
399
+ ##
400
+ ## this is language independent.
401
+ ##
402
+ module BiPatternEnhancer
403
+
404
+ def self.desc # :nodoc:
405
+ "another embedded expression pattern (default '\[= =\]')."
406
+ end
407
+
408
+ def initialize(input, properties={})
409
+ self.bipattern = properties[:bipattern] # or '\$\{ \}'
410
+ super
411
+ end
412
+
413
+ ## when pat is nil then '\[= =\]' is used
414
+ def bipattern=(pat) # :nodoc:
415
+ @bipattern = pat || '\[= =\]'
416
+ pre, post = @bipattern.split()
417
+ @bipattern_regexp = /(.*?)#{pre}(=*)(.*?)#{post}/m
418
+ end
419
+
420
+ def add_text(src, text)
421
+ return unless text
422
+ m = nil
423
+ text.scan(@bipattern_regexp) do |txt, indicator, code|
424
+ m = Regexp.last_match
425
+ super(src, txt)
426
+ add_expr(src, code, '=' + indicator)
427
+ end
428
+ #rest = $' || text # ruby1.8
429
+ rest = m ? text[m.end(0)..-1] : text # ruby1.9
430
+ super(src, rest)
431
+ end
432
+
433
+ end
434
+
435
+
436
+ ##
437
+ ## regards lines starting with '^[ \t]*%' as program code
438
+ ##
439
+ ## in addition you can specify prefix character (default '%')
440
+ ##
441
+ ## this is language-independent.
442
+ ##
443
+ module PrefixedLineEnhancer
444
+
445
+ def self.desc # :nodoc:
446
+ "regard lines matched to '^[ \t]*%' as program code"
447
+ end
448
+
449
+ def init_generator(properties={})
450
+ super
451
+ @prefixchar = properties[:prefixchar]
452
+ end
453
+
454
+ def add_text(src, text)
455
+ unless @prefixrexp
456
+ @prefixchar ||= '%'
457
+ @prefixrexp = Regexp.compile("^([ \\t]*)\\#{@prefixchar}(.*?\\r?\\n)")
458
+ end
459
+ pos = 0
460
+ text2 = ''
461
+ text.scan(@prefixrexp) do
462
+ space = $1
463
+ line = $2
464
+ space, line = '', $1 unless $2
465
+ match = Regexp.last_match
466
+ len = match.begin(0) - pos
467
+ str = text[pos, len]
468
+ pos = match.end(0)
469
+ if text2.empty?
470
+ text2 = str
471
+ else
472
+ text2 << str
473
+ end
474
+ if line[0, 1] == @prefixchar
475
+ text2 << space << line
476
+ else
477
+ super(src, text2)
478
+ text2 = ''
479
+ add_stmt(src, space + line)
480
+ end
481
+ end
482
+ #rest = pos == 0 ? text : $' # ruby1.8
483
+ rest = pos == 0 ? text : text[pos..-1] # ruby1.9
484
+ unless text2.empty?
485
+ text2 << rest if rest
486
+ rest = text2
487
+ end
488
+ super(src, rest)
489
+ end
490
+
491
+ end
492
+
493
+
494
+ ##
495
+ ## regards lines starting with '%' as program code
496
+ ##
497
+ ## this is for compatibility to eruby and ERB.
498
+ ##
499
+ ## this is language-independent.
500
+ ##
501
+ module PercentLineEnhancer
502
+ include PrefixedLineEnhancer
503
+
504
+ def self.desc # :nodoc:
505
+ "regard lines starting with '%' as program code"
506
+ end
507
+
508
+ #--
509
+ #def init_generator(properties={})
510
+ # super
511
+ # @prefixchar = '%'
512
+ # @prefixrexp = /^\%(.*?\r?\n)/
513
+ #end
514
+ #++
515
+
516
+ def add_text(src, text)
517
+ unless @prefixrexp
518
+ @prefixchar = '%'
519
+ @prefixrexp = /^\%(.*?\r?\n)/
520
+ end
521
+ super(src, text)
522
+ end
523
+
524
+ end
525
+
526
+
527
+ ##
528
+ ## [experimental] allow header and footer in eRuby script
529
+ ##
530
+ ## ex.
531
+ ## ====================
532
+ ## ## without header and footer
533
+ ## $ cat ex1.eruby
534
+ ## <% def list_items(list) %>
535
+ ## <% for item in list %>
536
+ ## <li><%= item %></li>
537
+ ## <% end %>
538
+ ## <% end %>
539
+ ##
540
+ ## $ erubis -s ex1.eruby
541
+ ## _buf = []; def list_items(list)
542
+ ## ; for item in list
543
+ ## ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
544
+ ## '; end
545
+ ## ; end
546
+ ## ;
547
+ ## _buf.join
548
+ ##
549
+ ## ## with header and footer
550
+ ## $ cat ex2.eruby
551
+ ## <!--#header:
552
+ ## def list_items(list)
553
+ ## #-->
554
+ ## <% for item in list %>
555
+ ## <li><%= item %></li>
556
+ ## <% end %>
557
+ ## <!--#footer:
558
+ ## end
559
+ ## #-->
560
+ ##
561
+ ## $ erubis -s -c HeaderFooterEruby ex4.eruby
562
+ ##
563
+ ## def list_items(list)
564
+ ## _buf = []; _buf << '
565
+ ## '; for item in list
566
+ ## ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
567
+ ## '; end
568
+ ## ; _buf << '
569
+ ## ';
570
+ ## _buf.join
571
+ ## end
572
+ ##
573
+ ## ====================
574
+ ##
575
+ ## this is language-independent.
576
+ ##
577
+ module HeaderFooterEnhancer
578
+
579
+ def self.desc # :nodoc:
580
+ "allow header/footer in document (ex. '<!--#header: #-->')"
581
+ end
582
+
583
+ HEADER_FOOTER_PATTERN = /(.*?)(^[ \t]*)?<!--\#(\w+):(.*?)\#-->([ \t]*\r?\n)?/m
584
+
585
+ def add_text(src, text)
586
+ m = nil
587
+ text.scan(HEADER_FOOTER_PATTERN) do |txt, lspace, word, content, rspace|
588
+ m = Regexp.last_match
589
+ flag_trim = @trim && lspace && rspace
590
+ super(src, txt)
591
+ content = "#{lspace}#{content}#{rspace}" if flag_trim
592
+ super(src, lspace) if !flag_trim && lspace
593
+ instance_variable_set("@#{word}", content)
594
+ super(src, rspace) if !flag_trim && rspace
595
+ end
596
+ #rest = $' || text # ruby1.8
597
+ rest = m ? text[m.end(0)..-1] : text # ruby1.9
598
+ super(src, rest)
599
+ end
600
+
601
+ attr_accessor :header, :footer
602
+
603
+ def convert(input)
604
+ source = super
605
+ return @src = "#{@header}#{source}#{@footer}"
606
+ end
607
+
608
+ end
609
+
610
+
611
+ ##
612
+ ## delete indentation of HTML.
613
+ ##
614
+ ## this is language-independent.
615
+ ##
616
+ module DeleteIndentEnhancer
617
+
618
+ def self.desc # :nodoc:
619
+ "delete indentation of HTML."
620
+ end
621
+
622
+ def convert_input(src, input)
623
+ input = input.gsub(/^[ \t]+</, '<')
624
+ super(src, input)
625
+ end
626
+
627
+ end
628
+
629
+
630
+ ##
631
+ ## convert "<h1><%=title%></h1>" into "_buf << %Q`<h1>#{title}</h1>`"
632
+ ##
633
+ ## this is only for Eruby.
634
+ ##
635
+ module InterpolationEnhancer
636
+
637
+ def self.desc # :nodoc:
638
+ "convert '<p><%=text%></p>' into '_buf << %Q`<p>\#{text}</p>`'"
639
+ end
640
+
641
+ def convert_input(src, input)
642
+ pat = @pattern
643
+ regexp = pat.nil? || pat == '<% %>' ? Basic::Converter::DEFAULT_REGEXP : pattern_regexp(pat)
644
+ pos = 0
645
+ is_bol = true # is beginning of line
646
+ str = ''
647
+ input.scan(regexp) do |indicator, code, tailch, rspace|
648
+ match = Regexp.last_match()
649
+ len = match.begin(0) - pos
650
+ text = input[pos, len]
651
+ pos = match.end(0)
652
+ ch = indicator ? indicator[0] : nil
653
+ lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
654
+ is_bol = rspace ? true : false
655
+ _add_text_to_str(str, text)
656
+ ## * when '<%= %>', do nothing
657
+ ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
658
+ if ch == ?= # <%= %>
659
+ rspace = nil if tailch && !tailch.empty?
660
+ str << lspace if lspace
661
+ add_expr(str, code, indicator)
662
+ str << rspace if rspace
663
+ elsif ch == ?\# # <%# %>
664
+ n = code.count("\n") + (rspace ? 1 : 0)
665
+ if @trim && lspace && rspace
666
+ add_text(src, str)
667
+ str = ''
668
+ add_stmt(src, "\n" * n)
669
+ else
670
+ str << lspace if lspace
671
+ add_text(src, str)
672
+ str = ''
673
+ add_stmt(src, "\n" * n)
674
+ str << rspace if rspace
675
+ end
676
+ else # <% %>
677
+ if @trim && lspace && rspace
678
+ add_text(src, str)
679
+ str = ''
680
+ add_stmt(src, "#{lspace}#{code}#{rspace}")
681
+ else
682
+ str << lspace if lspace
683
+ add_text(src, str)
684
+ str = ''
685
+ add_stmt(src, code)
686
+ str << rspace if rspace
687
+ end
688
+ end
689
+ end
690
+ #rest = $' || input # ruby1.8
691
+ rest = pos == 0 ? input : input[pos..-1] # ruby1.9
692
+ _add_text_to_str(str, rest)
693
+ add_text(src, str)
694
+ end
695
+
696
+ def add_text(src, text)
697
+ return if !text || text.empty?
698
+ #src << " _buf << %Q`" << text << "`;"
699
+ if text[-1] == ?\n
700
+ text[-1] = "\\n"
701
+ src << " #{@bufvar} << %Q`#{text}`\n"
702
+ else
703
+ src << " #{@bufvar} << %Q`#{text}`;"
704
+ end
705
+ end
706
+
707
+ def _add_text_to_str(str, text)
708
+ return if !text || text.empty?
709
+ str << text.gsub(/[`\#\\]/, '\\\\\&')
710
+ end
711
+
712
+ def add_expr_escaped(str, code)
713
+ str << "\#{#{escaped_expr(code)}}"
714
+ end
715
+
716
+ def add_expr_literal(str, code)
717
+ str << "\#{#{code}}"
718
+ end
719
+
720
+ end
721
+
722
+
723
+ end