erbse 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES.txt +828 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +51 -0
  5. data/benchmark/Makefile +6 -0
  6. data/benchmark/bench.rb +313 -0
  7. data/benchmark/bench_context.yaml +141 -0
  8. data/benchmark/templates/_footer.html +4 -0
  9. data/benchmark/templates/_header.html +52 -0
  10. data/benchmark/templates/bench_erb.rhtml +29 -0
  11. data/benchmark/templates/bench_erubis.rhtml +29 -0
  12. data/benchmark/templates/bench_eruby.rhtml +29 -0
  13. data/bin/erubis +10 -0
  14. data/erbse.gemspec +24 -0
  15. data/lib/erbse.rb +52 -0
  16. data/lib/erbse/context.rb +83 -0
  17. data/lib/erbse/converter.rb +357 -0
  18. data/lib/erbse/engine.rb +114 -0
  19. data/lib/erbse/engine/ec.rb +117 -0
  20. data/lib/erbse/engine/ecpp.rb +113 -0
  21. data/lib/erbse/engine/ejava.rb +110 -0
  22. data/lib/erbse/engine/ejavascript.rb +119 -0
  23. data/lib/erbse/engine/enhanced.rb +126 -0
  24. data/lib/erbse/engine/eperl.rb +95 -0
  25. data/lib/erbse/engine/ephp.rb +99 -0
  26. data/lib/erbse/engine/eruby.rb +119 -0
  27. data/lib/erbse/engine/escheme.rb +114 -0
  28. data/lib/erbse/engine/optimized.rb +127 -0
  29. data/lib/erbse/enhancer.rb +723 -0
  30. data/lib/erbse/error.rb +23 -0
  31. data/lib/erbse/evaluator.rb +88 -0
  32. data/lib/erbse/generator.rb +85 -0
  33. data/lib/erbse/helper.rb +47 -0
  34. data/lib/erbse/helpers/rails_form_helper.rb +197 -0
  35. data/lib/erbse/helpers/rails_helper.rb +353 -0
  36. data/lib/erbse/main.rb +516 -0
  37. data/lib/erbse/preprocessing.rb +58 -0
  38. data/lib/erbse/tiny.rb +144 -0
  39. data/lib/erbse/util.rb +22 -0
  40. data/lib/erbse/version.rb +3 -0
  41. data/test/assert-text-equal.rb +44 -0
  42. data/test/data/users-guide/Example.ejava +55 -0
  43. data/test/data/users-guide/array_example.result +9 -0
  44. data/test/data/users-guide/arraybuffer_example.result +9 -0
  45. data/test/data/users-guide/bipattern-example.rhtml +4 -0
  46. data/test/data/users-guide/bipattern_example.result +6 -0
  47. data/test/data/users-guide/bufvar-example.rb +10 -0
  48. data/test/data/users-guide/bufvar-example.result +17 -0
  49. data/test/data/users-guide/context.rb +6 -0
  50. data/test/data/users-guide/context.yaml +8 -0
  51. data/test/data/users-guide/def_method.rb +14 -0
  52. data/test/data/users-guide/def_method.result +3 -0
  53. data/test/data/users-guide/escape_example.result +9 -0
  54. data/test/data/users-guide/example.ec +27 -0
  55. data/test/data/users-guide/example.ecpp +30 -0
  56. data/test/data/users-guide/example.ejs +20 -0
  57. data/test/data/users-guide/example.eperl +18 -0
  58. data/test/data/users-guide/example.ephp +18 -0
  59. data/test/data/users-guide/example.eruby +6 -0
  60. data/test/data/users-guide/example.escheme +28 -0
  61. data/test/data/users-guide/example1.eruby +6 -0
  62. data/test/data/users-guide/example1.rb +17 -0
  63. data/test/data/users-guide/example1.result +16 -0
  64. data/test/data/users-guide/example10.rb +4 -0
  65. data/test/data/users-guide/example10.result +17 -0
  66. data/test/data/users-guide/example10.xhtml +14 -0
  67. data/test/data/users-guide/example10_x.result +17 -0
  68. data/test/data/users-guide/example11.php +20 -0
  69. data/test/data/users-guide/example11.result +23 -0
  70. data/test/data/users-guide/example11.rhtml +21 -0
  71. data/test/data/users-guide/example11_C.result +10 -0
  72. data/test/data/users-guide/example11_N.result +16 -0
  73. data/test/data/users-guide/example11_U.result +16 -0
  74. data/test/data/users-guide/example11_php.result +15 -0
  75. data/test/data/users-guide/example1_x.result +9 -0
  76. data/test/data/users-guide/example2.eruby +7 -0
  77. data/test/data/users-guide/example2.rb +10 -0
  78. data/test/data/users-guide/example2.result +27 -0
  79. data/test/data/users-guide/example2_trim.result +10 -0
  80. data/test/data/users-guide/example2_x.result +10 -0
  81. data/test/data/users-guide/example3.eruby +6 -0
  82. data/test/data/users-guide/example3.rb +10 -0
  83. data/test/data/users-guide/example31.result +22 -0
  84. data/test/data/users-guide/example32.result +4 -0
  85. data/test/data/users-guide/example3_e.result +8 -0
  86. data/test/data/users-guide/example4.eruby +3 -0
  87. data/test/data/users-guide/example4.rb +11 -0
  88. data/test/data/users-guide/example4.result +10 -0
  89. data/test/data/users-guide/example4_x.result +5 -0
  90. data/test/data/users-guide/example5.eruby +6 -0
  91. data/test/data/users-guide/example5.rb +16 -0
  92. data/test/data/users-guide/example5.result +7 -0
  93. data/test/data/users-guide/example6.rb +12 -0
  94. data/test/data/users-guide/example6.result +7 -0
  95. data/test/data/users-guide/example7.eruby +8 -0
  96. data/test/data/users-guide/example71.result +13 -0
  97. data/test/data/users-guide/example72.result +13 -0
  98. data/test/data/users-guide/example8.eruby +6 -0
  99. data/test/data/users-guide/example8_ruby.result +7 -0
  100. data/test/data/users-guide/example8_yaml.result +7 -0
  101. data/test/data/users-guide/example9.eruby +3 -0
  102. data/test/data/users-guide/example9.rb +8 -0
  103. data/test/data/users-guide/example9.result +9 -0
  104. data/test/data/users-guide/example91.result +5 -0
  105. data/test/data/users-guide/example92.result +4 -0
  106. data/test/data/users-guide/example_c.result +32 -0
  107. data/test/data/users-guide/example_java.result +56 -0
  108. data/test/data/users-guide/example_js.result +22 -0
  109. data/test/data/users-guide/example_perl.result +20 -0
  110. data/test/data/users-guide/example_php.result +19 -0
  111. data/test/data/users-guide/example_scheme.result +30 -0
  112. data/test/data/users-guide/example_scheme_display.result +29 -0
  113. data/test/data/users-guide/fasteruby-example.rb +8 -0
  114. data/test/data/users-guide/fasteruby-example.result +18 -0
  115. data/test/data/users-guide/fasteruby.rb +11 -0
  116. data/test/data/users-guide/fasteruby.result +38 -0
  117. data/test/data/users-guide/fasteruby.rhtml +15 -0
  118. data/test/data/users-guide/headerfooter-example.eruby +9 -0
  119. data/test/data/users-guide/headerfooter-example2.rb +8 -0
  120. data/test/data/users-guide/headerfooter-example2.rhtml +10 -0
  121. data/test/data/users-guide/headerfooter_example.result +11 -0
  122. data/test/data/users-guide/headerfooter_example2.result +13 -0
  123. data/test/data/users-guide/interpolation_example.result +9 -0
  124. data/test/data/users-guide/main_program1.rb +8 -0
  125. data/test/data/users-guide/main_program1.result +6 -0
  126. data/test/data/users-guide/main_program2.rb +8 -0
  127. data/test/data/users-guide/main_program2.result +6 -0
  128. data/test/data/users-guide/nocode-example.eruby +14 -0
  129. data/test/data/users-guide/nocode-php.result +20 -0
  130. data/test/data/users-guide/nocode_example.result +15 -0
  131. data/test/data/users-guide/normal-eruby-test.eruby +9 -0
  132. data/test/data/users-guide/normal_eruby_test.result +11 -0
  133. data/test/data/users-guide/notext-example.eruby +14 -0
  134. data/test/data/users-guide/notext-example.php +19 -0
  135. data/test/data/users-guide/notext-php.result +20 -0
  136. data/test/data/users-guide/notext_example.result +16 -0
  137. data/test/data/users-guide/percentline-example.rhtml +6 -0
  138. data/test/data/users-guide/percentline_example.result +9 -0
  139. data/test/data/users-guide/prefixedline-example.rb +9 -0
  140. data/test/data/users-guide/prefixedline-example.rhtml +6 -0
  141. data/test/data/users-guide/prefixedline_example.result +9 -0
  142. data/test/data/users-guide/printenable_example.result +4 -0
  143. data/test/data/users-guide/printenabled-example.eruby +3 -0
  144. data/test/data/users-guide/printenabled-example.rb +8 -0
  145. data/test/data/users-guide/printstatement_example.result +8 -0
  146. data/test/data/users-guide/simplify_example.result +9 -0
  147. data/test/data/users-guide/stderr.log +3 -0
  148. data/test/data/users-guide/stdout_exmple.result +9 -0
  149. data/test/data/users-guide/stringbuffer_example.result +9 -0
  150. data/test/data/users-guide/tail_260.result +4 -0
  151. data/test/data/users-guide/tailnewline.rhtml +3 -0
  152. data/test/data/users-guide/template1.rhtml +4 -0
  153. data/test/data/users-guide/template2.rhtml +4 -0
  154. data/test/test-engines.rb +425 -0
  155. data/test/test-enhancers.rb +646 -0
  156. data/test/test-erubis.rb +887 -0
  157. data/test/test-index-cgi.rb +191 -0
  158. data/test/test-main.rb +752 -0
  159. data/test/test-users-guide.rb +73 -0
  160. data/test/test.rb +45 -0
  161. data/test/testutil.rb +111 -0
  162. metadata +233 -0
@@ -0,0 +1,114 @@
1
+ ##
2
+ ## $Release: 2.7.0 $
3
+ ## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
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: 2.7.0 $
3
+ ## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
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: 2.7.0 $
3
+ ## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
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