erubis 2.0.1 → 2.1.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.
- data/ChangeLog +150 -2
- data/LGPL +504 -0
- data/README.txt +14 -8
- data/benchmark/erubybench.rb +1 -1
- data/benchmark/erubybench.rhtml +3 -3
- data/bin/erubis +1 -1
- data/bin/notext +154 -0
- data/contrib/erubis +1036 -374
- data/contrib/inline-require +5 -3
- data/doc-api/classes/Erubis.html +43 -1
- data/doc-api/classes/Erubis/ArrayBufferEnhancer.html +14 -14
- data/doc-api/classes/Erubis/ArrayEnhancer.html +14 -14
- data/doc-api/classes/Erubis/Basic.html +112 -0
- data/doc-api/classes/Erubis/Basic/Converter.html +318 -0
- data/doc-api/classes/Erubis/Basic/Engine.html +130 -0
- data/doc-api/classes/Erubis/BiPatternEnhancer.html +14 -14
- data/doc-api/classes/Erubis/CGenerator.html +386 -0
- data/doc-api/classes/Erubis/Context.html +31 -32
- data/doc-api/classes/Erubis/Converter.html +231 -0
- data/doc-api/classes/Erubis/Ec.html +9 -283
- data/doc-api/classes/Erubis/Ejava.html +9 -274
- data/doc-api/classes/Erubis/Ejavascript.html +9 -298
- data/doc-api/classes/Erubis/Engine.html +68 -508
- data/doc-api/classes/Erubis/Eperl.html +9 -259
- data/doc-api/classes/Erubis/Ephp.html +9 -239
- data/doc-api/classes/Erubis/ErubisError.html +2 -2
- data/doc-api/classes/Erubis/Eruby.html +4 -187
- data/doc-api/classes/Erubis/EscapeEnhancer.html +9 -11
- data/doc-api/classes/Erubis/Escheme.html +9 -272
- data/doc-api/classes/Erubis/Evaluator.html +212 -0
- data/doc-api/classes/Erubis/Generator.html +410 -0
- data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +16 -16
- data/doc-api/classes/Erubis/Helper.html +112 -0
- data/doc-api/classes/Erubis/Helper/CachedRailsTemplate.html +198 -0
- data/doc-api/classes/Erubis/Helper/RailsTemplate.html +366 -0
- data/doc-api/classes/Erubis/JavaGenerator.html +359 -0
- data/doc-api/classes/Erubis/JavascriptGenerator.html +381 -0
- data/doc-api/classes/Erubis/Main.html +27 -25
- data/doc-api/classes/Erubis/NoCodeEnhancer.html +249 -0
- data/doc-api/classes/Erubis/NoCodeEruby.html +120 -0
- data/doc-api/classes/Erubis/NoTextEnhancer.html +8 -8
- data/doc-api/classes/Erubis/NotSupportedError.html +119 -0
- data/doc-api/classes/Erubis/OptimizedEruby.html +22 -304
- data/doc-api/classes/Erubis/OptimizedGenerator.html +439 -0
- data/doc-api/classes/Erubis/OptimizedXmlEruby.html +7 -7
- data/doc-api/classes/Erubis/PI.html +124 -0
- data/doc-api/classes/Erubis/PI/Converter.html +318 -0
- data/doc-api/classes/Erubis/PI/Ec.html +166 -0
- data/doc-api/classes/Erubis/PI/Ejava.html +166 -0
- data/doc-api/classes/Erubis/PI/Ejavascript.html +166 -0
- data/doc-api/classes/Erubis/PI/Engine.html +122 -0
- data/doc-api/classes/Erubis/PI/Eperl.html +166 -0
- data/doc-api/classes/Erubis/PI/Ephp.html +166 -0
- data/doc-api/classes/Erubis/PI/Eruby.html +155 -0
- data/doc-api/classes/Erubis/PI/Escheme.html +166 -0
- data/doc-api/classes/Erubis/PI/TinyEruby.html +305 -0
- data/doc-api/classes/Erubis/PercentLineEnhancer.html +7 -7
- data/doc-api/classes/Erubis/PerlGenerator.html +344 -0
- data/doc-api/classes/Erubis/PhpGenerator.html +350 -0
- data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +24 -24
- data/doc-api/classes/Erubis/PrintOutEnhancer.html +35 -35
- data/doc-api/classes/Erubis/RubyEvaluator.html +190 -0
- data/doc-api/classes/Erubis/RubyGenerator.html +327 -0
- data/doc-api/classes/Erubis/SchemeGenerator.html +382 -0
- data/doc-api/classes/Erubis/SimplifyEnhancer.html +17 -13
- data/doc-api/classes/Erubis/StdoutEnhancer.html +14 -14
- data/doc-api/classes/Erubis/StringBufferEnhancer.html +14 -14
- data/doc-api/classes/Erubis/TinyEruby.html +45 -40
- data/doc-api/classes/Erubis/XmlHelper.html +14 -14
- data/doc-api/created.rid +1 -1
- data/doc-api/files/__/README_txt.html +27 -9
- data/doc-api/files/erubis/context_rb.html +107 -0
- data/doc-api/files/erubis/converter_rb.html +114 -0
- data/doc-api/files/erubis/engine/ec_rb.html +2 -2
- data/doc-api/files/erubis/engine/ejava_rb.html +2 -2
- data/doc-api/files/erubis/engine/ejavascript_rb.html +2 -2
- data/doc-api/files/erubis/engine/enhanced_rb.html +2 -2
- data/doc-api/files/erubis/engine/eperl_rb.html +2 -2
- data/doc-api/files/erubis/engine/ephp_rb.html +2 -2
- data/doc-api/files/erubis/engine/eruby_rb.html +3 -2
- data/doc-api/files/erubis/engine/escheme_rb.html +2 -2
- data/doc-api/files/erubis/engine/optimized_rb.html +2 -2
- data/doc-api/files/erubis/engine_rb.html +6 -3
- data/doc-api/files/erubis/enhancer_rb.html +2 -9
- data/doc-api/files/erubis/error_rb.html +107 -0
- data/doc-api/files/erubis/evaluator_rb.html +115 -0
- data/doc-api/files/erubis/generator_rb.html +114 -0
- data/doc-api/files/erubis/helper/rails_rb.html +140 -0
- data/doc-api/files/erubis/helper_rb.html +1 -1
- data/doc-api/files/erubis/local-setting_rb.html +1 -1
- data/doc-api/files/erubis/main_rb.html +2 -2
- data/doc-api/files/erubis/tiny_rb.html +2 -2
- data/doc-api/files/erubis_rb.html +2 -2
- data/doc-api/fr_class_index.html +32 -0
- data/doc-api/fr_file_index.html +6 -0
- data/doc-api/fr_method_index.html +178 -136
- data/doc/users-guide.html +538 -199
- data/examples/{Makefile → basic/Makefile} +11 -11
- data/examples/basic/example.ec +42 -0
- data/examples/{example.ejava → basic/example.ejava} +5 -1
- data/examples/{example.ejavascript → basic/example.ejs} +0 -0
- data/examples/{example.eperl → basic/example.eperl} +2 -2
- data/examples/{example.ephp → basic/example.ephp} +0 -0
- data/examples/{example.eruby → basic/example.eruby} +0 -0
- data/examples/{example.escheme → basic/example.escheme} +0 -0
- data/examples/pi/Makefile +54 -0
- data/examples/pi/example.ec +42 -0
- data/examples/pi/example.ejava +45 -0
- data/examples/pi/example.ejs +16 -0
- data/examples/pi/example.eperl +16 -0
- data/examples/pi/example.ephp +17 -0
- data/examples/pi/example.eruby +15 -0
- data/examples/pi/example.escheme +26 -0
- data/lib/erubis.rb +15 -8
- data/lib/erubis/context.rb +54 -0
- data/lib/erubis/converter.rb +307 -0
- data/lib/erubis/engine.rb +57 -227
- data/lib/erubis/engine/ec.rb +31 -20
- data/lib/erubis/engine/ejava.rb +33 -21
- data/lib/erubis/engine/ejavascript.rb +30 -18
- data/lib/erubis/engine/enhanced.rb +7 -2
- data/lib/erubis/engine/eperl.rb +33 -19
- data/lib/erubis/engine/ephp.rb +32 -14
- data/lib/erubis/engine/eruby.rb +34 -7
- data/lib/erubis/engine/escheme.rb +34 -15
- data/lib/erubis/engine/optimized.rb +25 -11
- data/lib/erubis/enhancer.rb +53 -19
- data/lib/erubis/error.rb +24 -0
- data/lib/erubis/evaluator.rb +71 -0
- data/lib/erubis/generator.rb +83 -0
- data/lib/erubis/helper.rb +1 -1
- data/lib/erubis/helper/rails.rb +159 -0
- data/lib/erubis/local-setting.rb +1 -1
- data/lib/erubis/main.rb +87 -46
- data/lib/erubis/tiny.rb +81 -7
- data/test/assert-text-equal.rb +1 -1
- data/test/test-engines.rb +8 -9
- data/test/test-erubis.rb +196 -18
- data/test/{test-bin.rb → test-main.rb} +123 -21
- data/test/test-notext.rb +27 -0
- data/test/test.rb +5 -3
- data/test/testutil.rb +25 -36
- metadata +75 -13
- data/COPYING +0 -340
- data/examples/example.ec +0 -24
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
##
|
|
2
|
+
## $Rev: 37 $
|
|
3
|
+
## $Release: 2.1.0 $
|
|
4
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
require 'abstract'
|
|
8
|
+
|
|
9
|
+
module Erubis
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
## convert
|
|
14
|
+
##
|
|
15
|
+
module Converter
|
|
16
|
+
|
|
17
|
+
attr_accessor :preamble, :postamble, :escape
|
|
18
|
+
|
|
19
|
+
def self.supported_properties # :nodoc:
|
|
20
|
+
return [
|
|
21
|
+
[:preamble, nil, "preamble (no preamble when false)"],
|
|
22
|
+
[:postamble, nil, "postamble (no postamble when false)"],
|
|
23
|
+
[:escape, nil, "escape expression or not in default"],
|
|
24
|
+
]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def init_converter(properties={})
|
|
28
|
+
@preamble = properties[:preamble]
|
|
29
|
+
@postamble = properties[:postamble]
|
|
30
|
+
@escape = properties[:escape]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
## convert input string into target language
|
|
34
|
+
def convert(input)
|
|
35
|
+
codebuf = "" # or []
|
|
36
|
+
@preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble))
|
|
37
|
+
convert_input(codebuf, input)
|
|
38
|
+
@postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble))
|
|
39
|
+
return codebuf # or codebuf.join()
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
protected
|
|
43
|
+
|
|
44
|
+
##
|
|
45
|
+
## (abstract) convert input to code
|
|
46
|
+
##
|
|
47
|
+
def convert_input(codebuf, input)
|
|
48
|
+
not_implemented
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
module Basic
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
## basic converter which supports '<% ... %>' notation.
|
|
60
|
+
##
|
|
61
|
+
module Basic::Converter
|
|
62
|
+
include Erubis::Converter
|
|
63
|
+
|
|
64
|
+
def self.supported_properties # :nodoc:
|
|
65
|
+
return [
|
|
66
|
+
[:pattern, '<% %>', "embed pattern"],
|
|
67
|
+
[:trim, true, "trim spaces around <% ... %>"],
|
|
68
|
+
]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
attr_accessor :pattern, :trim
|
|
72
|
+
|
|
73
|
+
def init_converter(properties={})
|
|
74
|
+
super(properties)
|
|
75
|
+
@pattern = properties[:pattern]
|
|
76
|
+
@trim = properties[:trim] != false
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
#DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
|
|
80
|
+
DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
|
|
81
|
+
|
|
82
|
+
## return regexp of pattern to parse eRuby script
|
|
83
|
+
def pattern_regexp(pattern=@pattern)
|
|
84
|
+
if pattern.nil? || pattern == '<% %>'
|
|
85
|
+
return DEFAULT_REGEXP
|
|
86
|
+
else
|
|
87
|
+
prefix, postfix = pattern.split()
|
|
88
|
+
#return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
|
|
89
|
+
return /(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
protected :pattern_regexp
|
|
93
|
+
|
|
94
|
+
def convert_input(src, input)
|
|
95
|
+
regexp = pattern_regexp(@pattern)
|
|
96
|
+
pos = 0
|
|
97
|
+
input.scan(regexp) do |lspace, indicator, code, rspace|
|
|
98
|
+
match = Regexp.last_match()
|
|
99
|
+
index = match.begin(0)
|
|
100
|
+
text = input[pos, index - pos]
|
|
101
|
+
pos = match.end(0)
|
|
102
|
+
add_text(src, text)
|
|
103
|
+
## * when '<%= %>', do nothing
|
|
104
|
+
## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
|
|
105
|
+
if !indicator # <% %>
|
|
106
|
+
if @trim && lspace && rspace
|
|
107
|
+
add_stmt(src, "#{lspace}#{code}#{rspace}")
|
|
108
|
+
else
|
|
109
|
+
add_text(src, lspace) if lspace
|
|
110
|
+
add_stmt(src, code)
|
|
111
|
+
add_text(src, rspace) if rspace
|
|
112
|
+
end
|
|
113
|
+
elsif indicator[0] == ?\# # <%# %>
|
|
114
|
+
n = code.count("\n") + (rspace ? 1 : 0)
|
|
115
|
+
if @trim && lspace && rspace
|
|
116
|
+
add_stmt(src, "\n" * n)
|
|
117
|
+
else
|
|
118
|
+
add_text(src, lspace) if lspace
|
|
119
|
+
add_stmt(src, "\n" * n)
|
|
120
|
+
add_text(src, rspace) if rspace
|
|
121
|
+
end
|
|
122
|
+
else # <%= %>
|
|
123
|
+
add_text(src, lspace) if lspace
|
|
124
|
+
add_expr(src, code, indicator)
|
|
125
|
+
add_text(src, rspace) if rspace
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
rest = $' || input # add input when no matched
|
|
129
|
+
add_text(src, rest)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
## add expression code to src
|
|
133
|
+
def add_expr(src, code, indicator)
|
|
134
|
+
case indicator
|
|
135
|
+
when '='
|
|
136
|
+
@escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
|
|
137
|
+
when '=='
|
|
138
|
+
@escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
|
|
139
|
+
when '==='
|
|
140
|
+
add_expr_debug(src, code)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
module PI
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
##
|
|
151
|
+
## Processing Instructions (PI) converter for XML.
|
|
152
|
+
## this class converts '<?rb ... ?>' and '${...}' notation.
|
|
153
|
+
##
|
|
154
|
+
module PI::Converter
|
|
155
|
+
include Erubis::Converter
|
|
156
|
+
|
|
157
|
+
def self.desc # :nodoc:
|
|
158
|
+
"use processing instructions (PI) instead of '<% %>'"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def self.supported_properties # :nodoc:
|
|
162
|
+
return [
|
|
163
|
+
[:trim, true, "trim spaces around <% ... %>"],
|
|
164
|
+
[:pi, 'rb', "PI (Processing Instrunctions) name"],
|
|
165
|
+
[:embchar, '@', "char for embedded expression pattern('@{...}@')"],
|
|
166
|
+
[:pattern, '<% %>', "embed pattern"],
|
|
167
|
+
]
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
attr_accessor :pi, :prefix
|
|
171
|
+
|
|
172
|
+
def init_converter(properties={})
|
|
173
|
+
super(properties)
|
|
174
|
+
@trim = !(properties[:trim] == false)
|
|
175
|
+
@pi = properties[:pi] if properties[:pi]
|
|
176
|
+
@embchar = properties[:embchar] || '@'
|
|
177
|
+
@pattern = properties[:pattern]
|
|
178
|
+
@pattern = '<% %>' if @pattern.nil? #|| @pattern == true
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def convert(input)
|
|
182
|
+
code = super(input)
|
|
183
|
+
return @header || @footer ? "#{@header}#{code}#{@footer}" : code
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
protected
|
|
187
|
+
|
|
188
|
+
def convert_input(codebuf, input)
|
|
189
|
+
parse_stmts(codebuf, input)
|
|
190
|
+
#parse_stmts2(codebuf, input)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def parse_stmts(codebuf, input)
|
|
194
|
+
#regexp = pattern_regexp(@pattern)
|
|
195
|
+
@pi ||= 'e'
|
|
196
|
+
@stmt_pattern ||= /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m
|
|
197
|
+
pos = 0
|
|
198
|
+
input.scan(@stmt_pattern) do |lspace, pi_arg, code, rspace|
|
|
199
|
+
match = Regexp.last_match
|
|
200
|
+
index = match.begin(0)
|
|
201
|
+
text = input[pos, index - pos]
|
|
202
|
+
pos = match.end(0)
|
|
203
|
+
parse_exprs(codebuf, text) # unless text.empty?
|
|
204
|
+
if @trim && lspace && rspace
|
|
205
|
+
add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
|
|
206
|
+
else
|
|
207
|
+
add_text(codebuf, lspace)
|
|
208
|
+
add_pi_stmt(codebuf, code, pi_arg)
|
|
209
|
+
add_text(codebuf, rspace)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
rest = $' || input
|
|
213
|
+
parse_exprs(codebuf, rest)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def parse_exprs(codebuf, input)
|
|
217
|
+
unless @expr_pattern
|
|
218
|
+
ch = Regexp.escape(@embchar)
|
|
219
|
+
if @pattern
|
|
220
|
+
left, right = @pattern.split(' ')
|
|
221
|
+
@expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/
|
|
222
|
+
else
|
|
223
|
+
@expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
pos = 0
|
|
227
|
+
input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2|
|
|
228
|
+
indicator = indicator1 || indicator2
|
|
229
|
+
code = code1 || code2
|
|
230
|
+
match = Regexp.last_match
|
|
231
|
+
index = match.begin(0)
|
|
232
|
+
text = input[pos, index - pos]
|
|
233
|
+
pos = match.end(0)
|
|
234
|
+
add_text(codebuf, text) # unless text.empty?
|
|
235
|
+
add_pi_expr(codebuf, code, indicator)
|
|
236
|
+
end
|
|
237
|
+
rest = $' || input
|
|
238
|
+
add_text(codebuf, rest)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def add_pi_stmt(codebuf, code, pi_arg) # :nodoc:
|
|
242
|
+
case pi_arg
|
|
243
|
+
when 'header' ; @header = code
|
|
244
|
+
when 'footer' ; @footer = code
|
|
245
|
+
when 'comment'; add_stmt(codebuf, "\n" * code.count("\n"))
|
|
246
|
+
when 'value' ; add_expr_literal(codebuf, code)
|
|
247
|
+
else ; add_stmt(codebuf, code)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def add_pi_expr(codebuf, code, indicator) # :nodoc:
|
|
252
|
+
case indicator
|
|
253
|
+
when nil, '', '==' # @{...}@ or <%== ... %>
|
|
254
|
+
@escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code)
|
|
255
|
+
when '!', '=' # @!{...}@ or <%= ... %>
|
|
256
|
+
@escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code)
|
|
257
|
+
when '!!', '===' # @!!{...}@ or <%=== ... %>
|
|
258
|
+
add_expr_debug(codebuf, code)
|
|
259
|
+
else
|
|
260
|
+
# ignore
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
## (obsolete) equivarent to parse_stmts(), but a little slower than it.
|
|
265
|
+
def parse_stmts2(codebuf, input) # :nodoc:
|
|
266
|
+
#regexp = pattern_regexp(@pattern)
|
|
267
|
+
@pi ||= 'e'
|
|
268
|
+
unless @embedded_pattern
|
|
269
|
+
ch = Regexp.escape(@embchar)
|
|
270
|
+
if @pattern
|
|
271
|
+
left, right = @pattern.split(' ')
|
|
272
|
+
@embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
|
|
273
|
+
else
|
|
274
|
+
@embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
pos = 0
|
|
278
|
+
input.scan(@embedded_pattern) do |lspace, pi_arg, stmt, rspace,
|
|
279
|
+
indicator1, expr1, indicator2, expr2|
|
|
280
|
+
match = Regexp.last_match
|
|
281
|
+
index = match.begin(0)
|
|
282
|
+
text = input[pos, index - pos]
|
|
283
|
+
pos = match.end(0)
|
|
284
|
+
add_text(codebuf, text) # unless text.empty?
|
|
285
|
+
if stmt
|
|
286
|
+
code = stmt
|
|
287
|
+
if @trim && lspace && rspace
|
|
288
|
+
add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
|
|
289
|
+
else
|
|
290
|
+
add_text(codebuf, lspace)
|
|
291
|
+
add_pi_stmt(codebuf, code, pi_arg)
|
|
292
|
+
add_text(codebuf, rspace)
|
|
293
|
+
end
|
|
294
|
+
else
|
|
295
|
+
code = expr1 || expr2
|
|
296
|
+
indicator = indicator1 || indicator2
|
|
297
|
+
add_pi_expr(codebuf, code, indicator)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
rest = $' || input
|
|
301
|
+
add_text(codebuf, rest)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
end
|
data/lib/erubis/engine.rb
CHANGED
|
@@ -1,93 +1,40 @@
|
|
|
1
1
|
##
|
|
2
|
-
## $Rev:
|
|
3
|
-
## $Release: 2.0
|
|
2
|
+
## $Rev: 32 $
|
|
3
|
+
## $Release: 2.1.0 $
|
|
4
4
|
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
5
5
|
##
|
|
6
6
|
|
|
7
|
-
require 'abstract'
|
|
8
7
|
|
|
8
|
+
require 'erubis/generator'
|
|
9
|
+
require 'erubis/converter'
|
|
10
|
+
require 'erubis/evaluator'
|
|
11
|
+
require 'erubis/context'
|
|
9
12
|
|
|
10
|
-
module Erubis
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
##
|
|
14
|
-
## base error class
|
|
15
|
-
##
|
|
16
|
-
class ErubisError < StandardError
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
##
|
|
21
|
-
## .[abstract] context object for Engine#evaluate
|
|
22
|
-
##
|
|
23
|
-
## ex.
|
|
24
|
-
## template = <<'END'
|
|
25
|
-
## Hello <%= @user %>!
|
|
26
|
-
## <% for item in @list %>
|
|
27
|
-
## - <%= item %>
|
|
28
|
-
## <% end %>
|
|
29
|
-
## END
|
|
30
|
-
##
|
|
31
|
-
## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
|
|
32
|
-
## # or
|
|
33
|
-
## # context = Erubis::Context.new
|
|
34
|
-
## # context[:user] = 'World'
|
|
35
|
-
## # context[:list] = ['a', 'b', 'c']
|
|
36
|
-
##
|
|
37
|
-
## eruby = Erubis::Eruby.new(template)
|
|
38
|
-
## print eruby.evaluate(context)
|
|
39
|
-
##
|
|
40
|
-
class Context
|
|
41
|
-
|
|
42
|
-
def initialize(hash=nil)
|
|
43
|
-
hash.each do |name, value|
|
|
44
|
-
self[name] = value
|
|
45
|
-
end if hash
|
|
46
|
-
end
|
|
47
13
|
|
|
48
|
-
|
|
49
|
-
return instance_variable_get("@#{key}")
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def []=(key, value)
|
|
53
|
-
return instance_variable_set("@#{key}", value)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def keys
|
|
57
|
-
return instance_variables.collect { |name| name[1,name.length-1] }
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
end
|
|
14
|
+
module Erubis
|
|
61
15
|
|
|
62
16
|
|
|
63
17
|
##
|
|
64
|
-
##
|
|
18
|
+
## (abstract) abstract engine class.
|
|
19
|
+
## subclass must include evaluator and converter module.
|
|
65
20
|
##
|
|
66
21
|
class Engine
|
|
22
|
+
#include Evaluator
|
|
23
|
+
#include Converter
|
|
24
|
+
#include Generator
|
|
67
25
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
#[:filename, nil, "filename"],
|
|
72
|
-
[:trim, true, "trim spaces around <% ... %>"],
|
|
73
|
-
[:preamble, nil, "preamble (no preamble when false)"],
|
|
74
|
-
[:postamble, nil, "postamble (no postamble when false)"],
|
|
75
|
-
[:escape, nil, "escape function name"],
|
|
76
|
-
]
|
|
26
|
+
# convert input string and set it to @src
|
|
27
|
+
def convert!(input)
|
|
28
|
+
@src = convert(input)
|
|
77
29
|
end
|
|
78
30
|
|
|
79
|
-
def initialize(input, properties={})
|
|
80
|
-
#@input
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
@
|
|
85
|
-
@postamble = properties[:postamble]
|
|
86
|
-
@escape = properties[:escape]
|
|
87
|
-
@src = compile(input) if input
|
|
31
|
+
def initialize(input=nil, properties={})
|
|
32
|
+
#@input = input
|
|
33
|
+
init_generator(properties)
|
|
34
|
+
init_converter(properties)
|
|
35
|
+
init_evaluator(properties)
|
|
36
|
+
@src = convert(input) if input
|
|
88
37
|
end
|
|
89
|
-
attr_reader :src
|
|
90
|
-
attr_accessor :filename
|
|
91
38
|
|
|
92
39
|
## load file and create engine object
|
|
93
40
|
def self.load_file(filename, properties={})
|
|
@@ -98,174 +45,57 @@ module Erubis
|
|
|
98
45
|
return engine
|
|
99
46
|
end
|
|
100
47
|
|
|
101
|
-
## eval(@src) with binding object
|
|
102
|
-
def result(_binding_or_hash=TOPLEVEL_BINDING)
|
|
103
|
-
_arg = _binding_or_hash
|
|
104
|
-
if _arg.is_a?(Hash)
|
|
105
|
-
## load _context data as local variables by eval
|
|
106
|
-
eval _arg.keys.inject("") { |s, k| s << "#{k.to_s} = _arg[#{k.inspect}];" }
|
|
107
|
-
_arg = binding()
|
|
108
|
-
end
|
|
109
|
-
return eval(@src, _arg, (@filename || '(erubis)'))
|
|
110
|
-
end
|
|
111
48
|
|
|
112
|
-
##
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def pattern_regexp(pattern=@pattern)
|
|
122
|
-
if pattern.nil? || pattern == '<% %>'
|
|
123
|
-
return DEFAULT_REGEXP
|
|
49
|
+
##
|
|
50
|
+
## helper method to convert and evaluate input text with context object.
|
|
51
|
+
## context may be Binding, Hash, or Object.
|
|
52
|
+
##
|
|
53
|
+
def process(input, context=nil, filename=nil)
|
|
54
|
+
code = convert(input)
|
|
55
|
+
filename ||= '(erubis)'
|
|
56
|
+
if context.is_a?(Binding)
|
|
57
|
+
return eval(code, context, filename)
|
|
124
58
|
else
|
|
125
|
-
|
|
126
|
-
return
|
|
59
|
+
context = Context.new(context) if context.is_a?(Hash)
|
|
60
|
+
return context.instance_eval(code, filename)
|
|
127
61
|
end
|
|
128
62
|
end
|
|
129
|
-
protected :pattern_regexp
|
|
130
63
|
|
|
131
|
-
## compile input string into target language
|
|
132
|
-
def compile(input)
|
|
133
|
-
src = ""
|
|
134
|
-
@preamble.nil? ? add_preamble(src) : (@preamble && (src << @preamble))
|
|
135
|
-
regexp = pattern_regexp(@pattern)
|
|
136
|
-
input.scan(regexp) do |text, lspace, indicator, code, rspace|
|
|
137
|
-
add_text(src, text)
|
|
138
|
-
## * when '<%= %>', do nothing
|
|
139
|
-
## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
|
|
140
|
-
if !indicator # <% %>
|
|
141
|
-
if @trim && lspace && rspace
|
|
142
|
-
add_stmt(src, "#{lspace}#{code}#{rspace}")
|
|
143
|
-
else
|
|
144
|
-
add_text(src, lspace) if lspace
|
|
145
|
-
add_stmt(src, code)
|
|
146
|
-
add_text(src, rspace) if rspace
|
|
147
|
-
end
|
|
148
|
-
elsif indicator[0] == ?\# # <%# %>
|
|
149
|
-
n = code.count("\n") + (rspace ? 1 : 0)
|
|
150
|
-
if @trim && lspace && rspace
|
|
151
|
-
add_stmt(src, "\n" * n)
|
|
152
|
-
else
|
|
153
|
-
add_text(src, lspace) if lspace
|
|
154
|
-
add_stmt(src, "\n" * n)
|
|
155
|
-
add_text(src, rspace) if rspace
|
|
156
|
-
end
|
|
157
|
-
#flag_trim = @trim && lspace && rspace
|
|
158
|
-
#add_text(src, lspace) if !flag_trim && lspace
|
|
159
|
-
#n = code.count("\n") + (rspace ? 1 : 0)
|
|
160
|
-
#add_stmt(src, "\n" * n)
|
|
161
|
-
#add_text(src, rspace) if !flag_trim && rspace
|
|
162
|
-
else # <%= %>
|
|
163
|
-
add_text(src, lspace) if lspace
|
|
164
|
-
add_expr(src, code, indicator)
|
|
165
|
-
add_text(src, rspace) if rspace
|
|
166
|
-
end
|
|
167
|
-
#if indicator && indicator[0] == ?=
|
|
168
|
-
# flag_trim = false
|
|
169
|
-
#else
|
|
170
|
-
# flag_trim = @trim && lspace && rspace
|
|
171
|
-
#end
|
|
172
|
-
##flag_trim = @trim && !(indicator && indicator[0]==?=) && lspace && rspace
|
|
173
|
-
#add_text(src, text)
|
|
174
|
-
#add_text(src, lspace) if !flag_trim && lspace
|
|
175
|
-
#if !indicator # <% %>
|
|
176
|
-
# code = "#{lspace}#{code}#{rspace}" if flag_trim
|
|
177
|
-
# add_stmt(src, code)
|
|
178
|
-
#elsif indicator[0] == ?\# # <%# %>
|
|
179
|
-
# n = code.count("\n") + (rspace ? 1 : 0)
|
|
180
|
-
# add_stmt(src, "\n" * n)
|
|
181
|
-
#else # <%= %>
|
|
182
|
-
# add_expr(src, code, indicator)
|
|
183
|
-
#end
|
|
184
|
-
#add_text(src, rspace) if !flag_trim && rspace
|
|
185
|
-
end
|
|
186
|
-
rest = $' || input # add input when no matched
|
|
187
|
-
add_text(src, rest)
|
|
188
|
-
@postamble.nil? ? add_postamble(src) : (@postamble && (src << @postamble))
|
|
189
|
-
return src
|
|
190
|
-
end
|
|
191
64
|
|
|
192
|
-
## compile input string and set it to @src
|
|
193
|
-
def compile!(input)
|
|
194
|
-
@src = compile(input)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
protected
|
|
198
|
-
|
|
199
|
-
## .[abstract] escape text string
|
|
200
65
|
##
|
|
201
|
-
##
|
|
202
|
-
##
|
|
203
|
-
## return text.dump
|
|
204
|
-
## # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'"
|
|
205
|
-
## end
|
|
206
|
-
def escape_text(text)
|
|
207
|
-
not_implemented
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
## .[abstract] return escaped expression code
|
|
66
|
+
## helper method evaluate Proc object iwth contect object.
|
|
67
|
+
## context may be Binding, Hash, or Object.
|
|
211
68
|
##
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
## .[abstract] add @preamble to src
|
|
222
|
-
def add_preamble(src)
|
|
223
|
-
not_implemented
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
## .[abstract] add text string to src
|
|
227
|
-
def add_text(src, text)
|
|
228
|
-
not_implemented
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
## .[abstract] add statement code to src
|
|
232
|
-
def add_stmt(src, code)
|
|
233
|
-
not_implemented
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
## add expression code to src
|
|
237
|
-
def add_expr(src, code, indicator)
|
|
238
|
-
case indicator
|
|
239
|
-
when '='
|
|
240
|
-
add_expr_literal(src, code)
|
|
241
|
-
when '=='
|
|
242
|
-
add_expr_escaped(src, code)
|
|
243
|
-
when '==='
|
|
244
|
-
add_expr_debug(src, code)
|
|
69
|
+
def process_proc(proc_obj, context=nil, filename=nil)
|
|
70
|
+
if context.is_a?(Binding)
|
|
71
|
+
filename ||= '(erubis)'
|
|
72
|
+
return eval(proc_obj, context, filename)
|
|
73
|
+
else
|
|
74
|
+
context = Context.new(context) if context.is_a?(Hash)
|
|
75
|
+
return context.instance_eval(&proc_obj)
|
|
245
76
|
end
|
|
246
77
|
end
|
|
247
78
|
|
|
248
|
-
## .[abstract] add expression literal code to src. this is called by add_expr().
|
|
249
|
-
def add_expr_literal(src, code)
|
|
250
|
-
not_implemented
|
|
251
|
-
end
|
|
252
79
|
|
|
253
|
-
|
|
254
|
-
def add_expr_escaped(src, code)
|
|
255
|
-
not_implemented
|
|
256
|
-
end
|
|
80
|
+
end # end of class Engine
|
|
257
81
|
|
|
258
|
-
## .[abstract] add expression code to src for debug. this is called by add_expr().
|
|
259
|
-
def add_expr_debug(src, code)
|
|
260
|
-
not_implemented
|
|
261
|
-
end
|
|
262
82
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
83
|
+
##
|
|
84
|
+
## (abstract) base engine class for Eruby, Eperl, Ejava, and so on.
|
|
85
|
+
## subclass must include generator.
|
|
86
|
+
##
|
|
87
|
+
class Basic::Engine < Engine
|
|
88
|
+
include Evaluator
|
|
89
|
+
include Basic::Converter
|
|
90
|
+
include Generator
|
|
91
|
+
end
|
|
267
92
|
|
|
268
|
-
|
|
93
|
+
|
|
94
|
+
class PI::Engine < Engine
|
|
95
|
+
include Evaluator
|
|
96
|
+
include PI::Converter
|
|
97
|
+
include Generator
|
|
98
|
+
end
|
|
269
99
|
|
|
270
100
|
|
|
271
101
|
end
|