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.
- data/ChangeLog +45 -18
- data/README.txt +80 -0
- data/benchmark/erubybench-lib.rb +189 -0
- data/benchmark/erubybench.rb +364 -0
- data/benchmark/erubybench.rhtml +61 -0
- data/benchmark/erubybench.yaml +61 -0
- data/bin/erubis +4 -180
- data/contrib/erubis +2297 -0
- data/contrib/inline-require +151 -0
- data/doc-api/classes/Erubis.html +236 -0
- data/doc-api/classes/Erubis/ArrayBufferEnhancer.html +175 -0
- data/doc-api/classes/Erubis/ArrayBufferEruby.html +120 -0
- data/doc-api/classes/Erubis/ArrayEnhancer.html +174 -0
- data/doc-api/classes/Erubis/ArrayEruby.html +120 -0
- data/doc-api/classes/Erubis/BiPatternEnhancer.html +212 -0
- data/doc-api/classes/Erubis/BiPatternEruby.html +120 -0
- data/doc-api/classes/Erubis/CommandOptionError.html +113 -0
- data/doc-api/classes/Erubis/Context.html +249 -0
- data/doc-api/classes/Erubis/Ec.html +399 -0
- data/doc-api/classes/Erubis/Ejava.html +366 -0
- data/doc-api/classes/Erubis/Ejavascript.html +390 -0
- data/doc-api/classes/Erubis/Engine.html +711 -0
- data/doc-api/classes/Erubis/Eperl.html +350 -0
- data/doc-api/classes/Erubis/Ephp.html +308 -0
- data/doc-api/classes/Erubis/ErubisError.html +117 -0
- data/doc-api/classes/Erubis/Eruby.html +310 -0
- data/doc-api/classes/Erubis/EscapeEnhancer.html +167 -0
- data/doc-api/classes/Erubis/EscapedEc.html +120 -0
- data/doc-api/classes/Erubis/EscapedEjava.html +120 -0
- data/doc-api/classes/Erubis/EscapedEjavascript.html +120 -0
- data/doc-api/classes/Erubis/EscapedEperl.html +120 -0
- data/doc-api/classes/Erubis/EscapedEphp.html +120 -0
- data/doc-api/classes/Erubis/EscapedEruby.html +127 -0
- data/doc-api/classes/Erubis/EscapedEscheme.html +120 -0
- data/doc-api/classes/Erubis/Escheme.html +389 -0
- data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +264 -0
- data/doc-api/classes/Erubis/HeaderFooterEruby.html +120 -0
- data/doc-api/classes/Erubis/Main.html +318 -0
- data/doc-api/classes/Erubis/NoTextEnhancer.html +159 -0
- data/doc-api/classes/Erubis/NoTextEruby.html +120 -0
- data/doc-api/classes/Erubis/OptimizedEruby.html +445 -0
- data/doc-api/classes/Erubis/OptimizedXmlEruby.html +163 -0
- data/doc-api/classes/Erubis/PercentLineEnhancer.html +174 -0
- data/doc-api/classes/Erubis/PercentLineEruby.html +120 -0
- data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +212 -0
- data/doc-api/classes/Erubis/PrintEnabledEruby.html +120 -0
- data/doc-api/classes/Erubis/PrintOutEnhancer.html +244 -0
- data/doc-api/classes/Erubis/PrintOutEruby.html +120 -0
- data/doc-api/classes/Erubis/PrintOutSimplifiedEruby.html +121 -0
- data/doc-api/classes/Erubis/SimplifiedEruby.html +120 -0
- data/doc-api/classes/Erubis/SimplifyEnhancer.html +185 -0
- data/doc-api/classes/Erubis/StdoutEnhancer.html +173 -0
- data/doc-api/classes/Erubis/StdoutEruby.html +120 -0
- data/doc-api/classes/Erubis/StdoutSimplifiedEruby.html +121 -0
- data/doc-api/classes/Erubis/StringBufferEnhancer.html +174 -0
- data/doc-api/classes/Erubis/StringBufferEruby.html +120 -0
- data/doc-api/classes/Erubis/StringIOEruby.html +120 -0
- data/doc-api/classes/Erubis/TinyEruby.html +305 -0
- data/doc-api/classes/Erubis/XmlEruby.html +130 -0
- data/doc-api/classes/Erubis/XmlHelper.html +193 -0
- data/doc-api/created.rid +1 -0
- data/doc-api/files/__/README_txt.html +214 -0
- data/doc-api/files/erubis/engine/ec_rb.html +115 -0
- data/doc-api/files/erubis/engine/ejava_rb.html +115 -0
- data/doc-api/files/erubis/engine/ejavascript_rb.html +115 -0
- data/doc-api/files/erubis/engine/enhanced_rb.html +115 -0
- data/doc-api/files/erubis/engine/eperl_rb.html +115 -0
- data/doc-api/files/erubis/engine/ephp_rb.html +115 -0
- data/doc-api/files/erubis/engine/eruby_rb.html +115 -0
- data/doc-api/files/erubis/engine/escheme_rb.html +115 -0
- data/doc-api/files/erubis/engine/optimized_rb.html +114 -0
- data/doc-api/files/erubis/engine_rb.html +114 -0
- data/doc-api/files/erubis/enhancer_rb.html +114 -0
- data/doc-api/files/erubis/helper_rb.html +107 -0
- data/doc-api/files/erubis/local-setting_rb.html +107 -0
- data/doc-api/files/erubis/main_rb.html +125 -0
- data/doc-api/files/erubis/tiny_rb.html +107 -0
- data/doc-api/files/erubis_rb.html +118 -0
- data/doc-api/fr_class_index.html +77 -0
- data/doc-api/fr_file_index.html +43 -0
- data/doc-api/fr_method_index.html +157 -0
- data/doc-api/index.html +24 -0
- data/doc-api/rdoc-style.css +208 -0
- data/doc/users-guide.html +1507 -375
- data/examples/Makefile +53 -0
- data/examples/example.ec +24 -0
- data/examples/example.ejava +41 -0
- data/examples/example.ejavascript +16 -0
- data/examples/example.eperl +16 -0
- data/examples/example.ephp +17 -0
- data/examples/example.eruby +15 -0
- data/examples/example.escheme +26 -0
- data/lib/erubis.rb +37 -269
- data/lib/erubis/engine.rb +260 -0
- data/lib/erubis/engine/ec.rb +106 -0
- data/lib/erubis/engine/ejava.rb +101 -0
- data/lib/erubis/engine/ejavascript.rb +104 -0
- data/lib/erubis/engine/enhanced.rb +102 -0
- data/lib/erubis/engine/eperl.rb +83 -0
- data/lib/erubis/engine/ephp.rb +84 -0
- data/lib/erubis/engine/eruby.rb +91 -0
- data/lib/erubis/engine/escheme.rb +96 -0
- data/lib/erubis/engine/optimized.rb +114 -0
- data/lib/erubis/enhancer.rb +487 -0
- data/lib/erubis/helper.rb +53 -0
- data/lib/erubis/local-setting.rb +10 -0
- data/lib/erubis/main.rb +368 -0
- data/lib/erubis/tiny.rb +65 -0
- data/test/assert-text-equal.rb +45 -0
- data/test/test-bin.rb +222 -45
- data/test/test-engines.rb +343 -0
- data/test/test-erubis.rb +836 -501
- data/test/test.rb +27 -0
- data/test/testutil.rb +86 -0
- metadata +131 -8
- data/README +0 -50
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
2
|
+
"http://www.w3.org/TR/html4/loose.dtd">
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<title>benchmark example</title>
|
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
7
|
+
<style type="text/css">
|
|
8
|
+
<!--
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
color: #333333;
|
|
12
|
+
line-height: 150%;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
thead {
|
|
16
|
+
font-weight: bold;
|
|
17
|
+
background-color: #CCCCCC;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.odd {
|
|
21
|
+
background-color: #FFCCCC;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.even {
|
|
25
|
+
background-color: #CCCCFF;
|
|
26
|
+
}
|
|
27
|
+
-->
|
|
28
|
+
</style>
|
|
29
|
+
|
|
30
|
+
</head>
|
|
31
|
+
|
|
32
|
+
<body>
|
|
33
|
+
|
|
34
|
+
<h1>Companies</h1>
|
|
35
|
+
|
|
36
|
+
<table>
|
|
37
|
+
<thead>
|
|
38
|
+
<tr>
|
|
39
|
+
<th>index</th><th>code</th><th>name</th>
|
|
40
|
+
</tr>
|
|
41
|
+
</thead>
|
|
42
|
+
<tbody>
|
|
43
|
+
<% data.each_with_index do |h, i| %>
|
|
44
|
+
<% n = i + 1 %>
|
|
45
|
+
<tr class="<%= n % 2 == 0 ? 'even' : 'odd' %>">
|
|
46
|
+
<td style="text-align: center">
|
|
47
|
+
<span><%= n %></span>
|
|
48
|
+
</td>
|
|
49
|
+
<td>
|
|
50
|
+
<a href="/stock/<%= h[:code] %>"><%= h[:code] %></a>
|
|
51
|
+
</td>
|
|
52
|
+
<td>
|
|
53
|
+
<a href="<%= h[:url] %>"><%= h[:name] %></a>
|
|
54
|
+
</td>
|
|
55
|
+
</tr>
|
|
56
|
+
<% end %>
|
|
57
|
+
</tbody>
|
|
58
|
+
</table>
|
|
59
|
+
|
|
60
|
+
</body>
|
|
61
|
+
</html>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
data:
|
|
2
|
+
- name: Apple Computer Inc.
|
|
3
|
+
url: http://www.apple.com
|
|
4
|
+
code: AAPL
|
|
5
|
+
- name: Amazon.com Inc
|
|
6
|
+
url: http://www.amazon.com
|
|
7
|
+
code: AMZN
|
|
8
|
+
- name: Sun Microsystems Inc.
|
|
9
|
+
url: http://www.sun.com
|
|
10
|
+
code: SUNW
|
|
11
|
+
- name: Microsoft Corp
|
|
12
|
+
url: http://www.microsoft.com
|
|
13
|
+
code: MSFT
|
|
14
|
+
- name: Adobe Systems Inc.
|
|
15
|
+
url: http://www.adobe.com
|
|
16
|
+
code: ADBE
|
|
17
|
+
- name: Intel Corp.
|
|
18
|
+
url: http://www.intel.com
|
|
19
|
+
code: INTC
|
|
20
|
+
- name: Oracle Corp.
|
|
21
|
+
url: http://www.oracle.com
|
|
22
|
+
code: ORCL
|
|
23
|
+
- name: International Business Machines Corp.
|
|
24
|
+
url: http://www.ibm.com
|
|
25
|
+
code: IBM
|
|
26
|
+
- name: BEA Systems Inc.
|
|
27
|
+
url: http://www.bea.com
|
|
28
|
+
code: BEAS
|
|
29
|
+
- name: eBay Inc.
|
|
30
|
+
url: http://www.ebay.com
|
|
31
|
+
code: EBAY
|
|
32
|
+
- name: Yahoo! Inc.
|
|
33
|
+
url: http://www.yahoo.com
|
|
34
|
+
code: YHOO
|
|
35
|
+
- name: Google Inc.
|
|
36
|
+
url: http://www.google.com
|
|
37
|
+
code: GOOG
|
|
38
|
+
- name: Hewlett-Packard Co.
|
|
39
|
+
url: http://www.hp.com
|
|
40
|
+
code: HPQ
|
|
41
|
+
- name: SAP AG
|
|
42
|
+
url: http://www.sap.com
|
|
43
|
+
code: SAP
|
|
44
|
+
- name: Cisco Systems Inc.
|
|
45
|
+
url: http://www.cisco.com
|
|
46
|
+
code: CSCO
|
|
47
|
+
- name: Juniper Networks, Inc
|
|
48
|
+
url: http://www.juniper.net/
|
|
49
|
+
code: JNPR
|
|
50
|
+
- name: Advanced Micro Devices Inc.
|
|
51
|
+
url: http://www.amd.com
|
|
52
|
+
code: AMD
|
|
53
|
+
- name: Red Hat Inc.
|
|
54
|
+
url: http://www.redhat.com
|
|
55
|
+
code: RHAT
|
|
56
|
+
- name: CA, Inc.
|
|
57
|
+
url: http://www.ca.com
|
|
58
|
+
code: CA
|
|
59
|
+
- name: Seagate Technology
|
|
60
|
+
url: http://www.seagate.com/
|
|
61
|
+
code: STX
|
data/bin/erubis
CHANGED
|
@@ -1,187 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/ruby
|
|
2
2
|
|
|
3
3
|
###
|
|
4
|
-
### $Rev:
|
|
5
|
-
### $Release:
|
|
4
|
+
### $Rev: 10 $
|
|
5
|
+
### $Release: 2.0.0 $
|
|
6
6
|
### copyright(c) 2006 kuwata-lab all rights reserved.
|
|
7
7
|
###
|
|
8
8
|
|
|
9
|
-
require '
|
|
10
|
-
require 'erubis'
|
|
9
|
+
require 'erubis/main'
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
class CommandOptionError < StandardError
|
|
14
|
-
def initialize(message)
|
|
15
|
-
super(message)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class Main
|
|
21
|
-
|
|
22
|
-
def execute(argv=ARGV)
|
|
23
|
-
## parse command-line options
|
|
24
|
-
options, context = parse_argv(argv, "hvsT", "pcrfKI")
|
|
25
|
-
filenames = argv
|
|
26
|
-
options[?h] = true if context[:help]
|
|
27
|
-
|
|
28
|
-
## help, version
|
|
29
|
-
if options[?h] || options[?v]
|
|
30
|
-
puts version() if options[?v]
|
|
31
|
-
puts usage() if options[?h]
|
|
32
|
-
return
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
## include path
|
|
36
|
-
options[?I].split(/,/).each do |path|
|
|
37
|
-
$: << path
|
|
38
|
-
end if options[?I]
|
|
39
|
-
|
|
40
|
-
## require library
|
|
41
|
-
options[?r].split(/,/).each do |library|
|
|
42
|
-
require library
|
|
43
|
-
end if options[?r]
|
|
44
|
-
|
|
45
|
-
## class name of Eruby
|
|
46
|
-
classname = options[?c] || 'Eruby'
|
|
47
|
-
begin
|
|
48
|
-
klass = Erubis.const_get(classname)
|
|
49
|
-
rescue NameError
|
|
50
|
-
klass = nil
|
|
51
|
-
end
|
|
52
|
-
unless klass && classname =~ /Eruby\z/
|
|
53
|
-
raise CommandOptionError.new("-c #{classname}: invalid class name.")
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
## kanji code
|
|
57
|
-
$KCODE = options[?K] if options[?K]
|
|
58
|
-
|
|
59
|
-
## read context values from yaml file
|
|
60
|
-
yamlfiles = options[?f]
|
|
61
|
-
if yamlfiles
|
|
62
|
-
hash = {}
|
|
63
|
-
yamlfiles.split(/,/).each do |yamlfile|
|
|
64
|
-
ydoc = yamlfile == '-' ? YAML.load($stdin.read()) : YAML.load_file(yamlfile)
|
|
65
|
-
unless ydoc.is_a?(Hash)
|
|
66
|
-
raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
|
|
67
|
-
end
|
|
68
|
-
hash.update(ydoc)
|
|
69
|
-
end
|
|
70
|
-
hash.update(context)
|
|
71
|
-
context = hash
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
## options for Eruby
|
|
75
|
-
eruby_options = {}
|
|
76
|
-
eruby_options[:pattern] = options[?p] if options[?p]
|
|
77
|
-
eruby_options[:trim] = false if options[?T]
|
|
78
|
-
|
|
79
|
-
## execute Eruby
|
|
80
|
-
flag_src = options[?s]
|
|
81
|
-
if filenames && !filenames.empty?
|
|
82
|
-
filenames.each do |filename|
|
|
83
|
-
eruby = klass.load_file(filename, eruby_options)
|
|
84
|
-
print flag_src ? eruby.src : eruby.evaluate(context)
|
|
85
|
-
end
|
|
86
|
-
else
|
|
87
|
-
input = ARGF.read()
|
|
88
|
-
eruby = klass.new(input, eruby_options)
|
|
89
|
-
print flag_src ? eruby.src : eruby.evaluate(context)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
private
|
|
95
|
-
|
|
96
|
-
def usage
|
|
97
|
-
command = File.basename($0)
|
|
98
|
-
s = <<END
|
|
99
|
-
Usage: #{command} [..options..] [file ...]
|
|
100
|
-
-h, --help : help
|
|
101
|
-
-v : version
|
|
102
|
-
-s : script source
|
|
103
|
-
-T : no trimming
|
|
104
|
-
-p pattern : embedded pattern (default '<% %>')
|
|
105
|
-
-c class : class name (Eruby, XmlEruby, FastEruby, ...) (default Eruby)
|
|
106
|
-
-I path : library include path
|
|
107
|
-
-K kanji : kanji code (euc, sjis, utf8, none) (default none)
|
|
108
|
-
-f file.yaml : YAML file for context values (read stdin if filename is '-')
|
|
109
|
-
--name=value : context name and value
|
|
110
|
-
END
|
|
111
|
-
# -r library : require library
|
|
112
|
-
return s
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def version
|
|
116
|
-
release = ('$Release: 1.1.0 $' =~ /([.\d]+)/) && $1
|
|
117
|
-
return release
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def parse_argv(argv, arg_none='', arg_required='', arg_optional='')
|
|
121
|
-
options = {}
|
|
122
|
-
context = {}
|
|
123
|
-
while argv[0] && argv[0][0] == ?-
|
|
124
|
-
optstr = argv.shift
|
|
125
|
-
optstr = optstr[1, optstr.length-1]
|
|
126
|
-
#
|
|
127
|
-
if optstr[0] == ?- # context
|
|
128
|
-
unless optstr =~ /\A\-([-\w]+)(?:=(.*))?/
|
|
129
|
-
raise CommandOptionError.new("-#{optstr}: invalid context value.")
|
|
130
|
-
end
|
|
131
|
-
name = $1; value = $2
|
|
132
|
-
name = name.gsub(/-/, '_').intern
|
|
133
|
-
value = value == nil ? true : to_value(value)
|
|
134
|
-
context[name] = value
|
|
135
|
-
#
|
|
136
|
-
else # options
|
|
137
|
-
while optstr && !optstr.empty?
|
|
138
|
-
optchar = optstr[0]
|
|
139
|
-
optstr[0,1] = ""
|
|
140
|
-
if arg_none.include?(optchar)
|
|
141
|
-
options[optchar] = true
|
|
142
|
-
elsif arg_required.include?(optchar)
|
|
143
|
-
arg = optstr.empty? ? argv.shift : optstr
|
|
144
|
-
raise CommandOptionError.new("-#{optchar.chr}: argument required.") unless arg
|
|
145
|
-
options[optchar] = arg
|
|
146
|
-
optstr = nil
|
|
147
|
-
elsif arg_optional.include?(optchar)
|
|
148
|
-
arg = optstr.empty? ? true : optstr
|
|
149
|
-
options[optchar] = arg
|
|
150
|
-
optstr = nil
|
|
151
|
-
else
|
|
152
|
-
raise CommandOptionError.new("-#{optchar.chr}: unknown option.")
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
#
|
|
157
|
-
end # end of while
|
|
158
|
-
|
|
159
|
-
return options, context
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def to_value(str)
|
|
163
|
-
case str
|
|
164
|
-
when nil, "null", "nil" ; return nil
|
|
165
|
-
when "true", "yes" ; return true
|
|
166
|
-
when "false", "no" ; return false
|
|
167
|
-
when /\A\d+\z/ ; return str.to_i
|
|
168
|
-
when /\A\d+\.\d+\z/ ; return str.to_f
|
|
169
|
-
when /\/(.*)\// ; return Regexp.new($1)
|
|
170
|
-
when /\A'.*'\z/, /\A".*"\z/ ; return eval(str)
|
|
171
|
-
else ; return str
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
#if __FILE__ == $0
|
|
179
|
-
status = 0
|
|
180
|
-
begin
|
|
181
|
-
Main.new.execute(ARGV)
|
|
182
|
-
rescue CommandOptionError => ex
|
|
183
|
-
$stderr.puts ex.message
|
|
184
|
-
status = 1
|
|
185
|
-
end
|
|
186
|
-
exit(status)
|
|
187
|
-
#end
|
|
11
|
+
Erubis::Main.main(ARGV)
|
data/contrib/erubis
ADDED
|
@@ -0,0 +1,2297 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
|
|
3
|
+
###
|
|
4
|
+
### $Rev: 10 $
|
|
5
|
+
### $Release: 2.0.0 $
|
|
6
|
+
### copyright(c) 2006 kuwata-lab all rights reserved.
|
|
7
|
+
###
|
|
8
|
+
|
|
9
|
+
#--begin of require 'erubis/main'
|
|
10
|
+
###
|
|
11
|
+
### $Rev: 21 $
|
|
12
|
+
### $Release: 2.0.0 $
|
|
13
|
+
### copyright(c) 2006 kuwata-lab all rights reserved.
|
|
14
|
+
###
|
|
15
|
+
|
|
16
|
+
require 'yaml'
|
|
17
|
+
#--begin of require 'erubis'
|
|
18
|
+
##
|
|
19
|
+
## $Rev: 21 $
|
|
20
|
+
## $Release: 2.0.0 $
|
|
21
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
22
|
+
##
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
## an implementation of eRuby
|
|
26
|
+
##
|
|
27
|
+
## * class Eruby - normal eRuby class
|
|
28
|
+
## * class XmlEruby - eRuby class which escape '&<>"' into '&<>"'
|
|
29
|
+
## * module StdoutEnhancer - use $stdout instead of String as output
|
|
30
|
+
## * module PrintEnhancer - enable to write print statement in <% ... %>
|
|
31
|
+
## * class OptimizedEruby - optimized Eruby class faster than FastEruby
|
|
32
|
+
## * class OptimizedXmlEruby - optimized XmlEruby class faster than FastXmlEruby
|
|
33
|
+
##
|
|
34
|
+
## example:
|
|
35
|
+
## input = <<'END'
|
|
36
|
+
## <ul>
|
|
37
|
+
## <% for item in @list %>
|
|
38
|
+
## <li><%= item %>
|
|
39
|
+
## <%== item %></li>
|
|
40
|
+
## <% end %>
|
|
41
|
+
## </ul>
|
|
42
|
+
## END
|
|
43
|
+
## list = ['<aaa>', 'b&b', '"ccc"']
|
|
44
|
+
## eruby = Erubis::Eruby.new(input)
|
|
45
|
+
## puts "--- source ---"
|
|
46
|
+
## puts eruby.src
|
|
47
|
+
## puts "--- result ---"
|
|
48
|
+
## puts eruby.evaluate(:list=>list)
|
|
49
|
+
## # or puts eruby.result(binding())
|
|
50
|
+
##
|
|
51
|
+
## result:
|
|
52
|
+
## --- source ---
|
|
53
|
+
## _buf = ""; _buf << " <ul>\n"
|
|
54
|
+
## for item in list
|
|
55
|
+
## _buf << " <li>"; _buf << ( item ).to_s; _buf << "\n"
|
|
56
|
+
## _buf << " "; _buf << Erubis::XmlEruby.escape( item ); _buf << "</li>\n"
|
|
57
|
+
## end
|
|
58
|
+
## _buf << " </ul>\n"
|
|
59
|
+
## _buf
|
|
60
|
+
## --- result ---
|
|
61
|
+
## <ul>
|
|
62
|
+
## <li><aaa>
|
|
63
|
+
## <aaa></li>
|
|
64
|
+
## <li>b&b
|
|
65
|
+
## b&b</li>
|
|
66
|
+
## <li>"ccc"
|
|
67
|
+
## "ccc"</li>
|
|
68
|
+
## </ul>
|
|
69
|
+
##
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
#--begin of require 'erubis/engine'
|
|
73
|
+
##
|
|
74
|
+
## $Rev: 21 $
|
|
75
|
+
## $Release: 2.0.0 $
|
|
76
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
77
|
+
##
|
|
78
|
+
|
|
79
|
+
#--begin of require 'abstract'
|
|
80
|
+
##
|
|
81
|
+
## $Rev: 1 $
|
|
82
|
+
## $Release$
|
|
83
|
+
## $Copyright$
|
|
84
|
+
##
|
|
85
|
+
##
|
|
86
|
+
## helper to define abstract method in Ruby.
|
|
87
|
+
##
|
|
88
|
+
##
|
|
89
|
+
## example1. (shorter notation)
|
|
90
|
+
##
|
|
91
|
+
## require 'abstract'
|
|
92
|
+
## class Foo
|
|
93
|
+
## abstract_method 'arg1, arg2=""', :method1, :method2, :method3
|
|
94
|
+
## end
|
|
95
|
+
##
|
|
96
|
+
##
|
|
97
|
+
## example2. (RDoc friendly notation)
|
|
98
|
+
##
|
|
99
|
+
## require 'abstract'
|
|
100
|
+
## class Bar
|
|
101
|
+
## # ... method1 description ...
|
|
102
|
+
## def method1(arg1, arg2="")
|
|
103
|
+
## not_implemented
|
|
104
|
+
## end
|
|
105
|
+
##
|
|
106
|
+
## # ... method2 description ...
|
|
107
|
+
## def method2(arg1, arg2="")
|
|
108
|
+
## not_implemented
|
|
109
|
+
## end
|
|
110
|
+
## end
|
|
111
|
+
##
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
##
|
|
115
|
+
class Module
|
|
116
|
+
|
|
117
|
+
##
|
|
118
|
+
## define abstract methods
|
|
119
|
+
##
|
|
120
|
+
def abstract_method args_str, *method_names
|
|
121
|
+
method_names.each do |name|
|
|
122
|
+
module_eval <<-END
|
|
123
|
+
def #{name}(#{args_str})
|
|
124
|
+
mesg = "class \#{self.class.name} must implement abstract method `#{self.name}##{name}()'."
|
|
125
|
+
#mesg = "\#{self.class.name}##{name}() is not implemented."
|
|
126
|
+
err = NotImplementedError.new mesg
|
|
127
|
+
err.set_backtrace caller()
|
|
128
|
+
raise err
|
|
129
|
+
end
|
|
130
|
+
END
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
##
|
|
138
|
+
module Kernel
|
|
139
|
+
|
|
140
|
+
##
|
|
141
|
+
## raise NotImplementedError
|
|
142
|
+
##
|
|
143
|
+
def not_implemented #:doc:
|
|
144
|
+
backtrace = caller()
|
|
145
|
+
method_name = (backtrace.shift =~ /`(\w+)'$/) && $1
|
|
146
|
+
mesg = "class #{self.class.name} must implement abstract method '#{method_name}()'."
|
|
147
|
+
#mesg = "#{self.class.name}##{method_name}() is not implemented."
|
|
148
|
+
err = NotImplementedError.new mesg
|
|
149
|
+
err.set_backtrace backtrace
|
|
150
|
+
raise err
|
|
151
|
+
end
|
|
152
|
+
private :not_implemented
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
#--end of require 'abstract'
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
module Erubis
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
##
|
|
162
|
+
## base error class
|
|
163
|
+
##
|
|
164
|
+
class ErubisError < StandardError
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
##
|
|
169
|
+
## .[abstract] context object for Engine#evaluate
|
|
170
|
+
##
|
|
171
|
+
## ex.
|
|
172
|
+
## template = <<'END'
|
|
173
|
+
## Hello <%= @user %>!
|
|
174
|
+
## <% for item in @list %>
|
|
175
|
+
## - <%= item %>
|
|
176
|
+
## <% end %>
|
|
177
|
+
## END
|
|
178
|
+
##
|
|
179
|
+
## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
|
|
180
|
+
## # or
|
|
181
|
+
## # context = Erubis::Context.new
|
|
182
|
+
## # context[:user] = 'World'
|
|
183
|
+
## # context[:list] = ['a', 'b', 'c']
|
|
184
|
+
##
|
|
185
|
+
## eruby = Erubis::Eruby.new(template)
|
|
186
|
+
## print eruby.evaluate(context)
|
|
187
|
+
##
|
|
188
|
+
class Context
|
|
189
|
+
|
|
190
|
+
def initialize(hash=nil)
|
|
191
|
+
hash.each do |name, value|
|
|
192
|
+
self[name] = value
|
|
193
|
+
end if hash
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def [](key)
|
|
197
|
+
return instance_variable_get("@#{key}")
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def []=(key, value)
|
|
201
|
+
return instance_variable_set("@#{key}", value)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def keys
|
|
205
|
+
return instance_variables.collect { |name| name[1,name.length-1] }
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
##
|
|
212
|
+
## [abstract] base engine class
|
|
213
|
+
##
|
|
214
|
+
class Engine
|
|
215
|
+
|
|
216
|
+
def self.supported_properties # :nodoc:
|
|
217
|
+
return [
|
|
218
|
+
[:pattern, '<% %>', "embed pattern"],
|
|
219
|
+
#[:filename, nil, "filename"],
|
|
220
|
+
[:trim, true, "trim spaces around <% ... %>"],
|
|
221
|
+
[:preamble, nil, "preamble (no preamble when false)"],
|
|
222
|
+
[:postamble, nil, "postamble (no postamble when false)"],
|
|
223
|
+
[:escape, nil, "escape function name"],
|
|
224
|
+
]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def initialize(input, properties={})
|
|
228
|
+
#@input = input
|
|
229
|
+
@pattern = properties[:pattern] || '<% %>'
|
|
230
|
+
@filename = properties[:filename]
|
|
231
|
+
@trim = properties[:trim] != false
|
|
232
|
+
@preamble = properties[:preamble]
|
|
233
|
+
@postamble = properties[:postamble]
|
|
234
|
+
@escape = properties[:escape]
|
|
235
|
+
@src = compile(input) if input
|
|
236
|
+
end
|
|
237
|
+
attr_reader :src
|
|
238
|
+
attr_accessor :filename
|
|
239
|
+
|
|
240
|
+
## load file and create engine object
|
|
241
|
+
def self.load_file(filename, properties={})
|
|
242
|
+
input = File.open(filename, 'rb') { |f| f.read }
|
|
243
|
+
input.untaint # is it ok?
|
|
244
|
+
properties[:filename] = filename
|
|
245
|
+
engine = self.new(input, properties)
|
|
246
|
+
return engine
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
## eval(@src) with binding
|
|
250
|
+
def result(_binding_or_hash=TOPLEVEL_BINDING)
|
|
251
|
+
_arg = _binding_or_hash
|
|
252
|
+
if _arg.is_a?(Hash)
|
|
253
|
+
## load _context data as local variables by eval
|
|
254
|
+
eval _arg.keys.inject("") { |s, k| s << "#{k.to_s} = _arg[#{k.inspect}];" }
|
|
255
|
+
_arg = binding()
|
|
256
|
+
end
|
|
257
|
+
return eval(@src, _arg, (@filename || '(erubis)'))
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
## call context.instance_eval(@src)
|
|
261
|
+
def evaluate(context=Context.new)
|
|
262
|
+
context = Context.new(context) if context.is_a?(Hash)
|
|
263
|
+
return context.instance_eval(@src, (@filename || '(erubis)'))
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
|
|
267
|
+
|
|
268
|
+
## return regexp of pattern to parse eRuby script
|
|
269
|
+
def pattern_regexp(pattern=@pattern)
|
|
270
|
+
if pattern == '<% %>'
|
|
271
|
+
return DEFAULT_REGEXP
|
|
272
|
+
else
|
|
273
|
+
prefix, postfix = pattern.split()
|
|
274
|
+
return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
protected :pattern_regexp
|
|
278
|
+
|
|
279
|
+
## compile input string into target language
|
|
280
|
+
def compile(input)
|
|
281
|
+
src = ""
|
|
282
|
+
@preamble.nil? ? add_preamble(src) : (@preamble && (src << @preamble))
|
|
283
|
+
regexp = pattern_regexp(@pattern)
|
|
284
|
+
input.scan(regexp) do |text, lspace, indicator, code, rspace|
|
|
285
|
+
add_text(src, text)
|
|
286
|
+
## * when '<%= %>', do nothing
|
|
287
|
+
## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
|
|
288
|
+
if !indicator # <% %>
|
|
289
|
+
if @trim && lspace && rspace
|
|
290
|
+
add_stmt(src, "#{lspace}#{code}#{rspace}")
|
|
291
|
+
else
|
|
292
|
+
add_text(src, lspace) if lspace
|
|
293
|
+
add_stmt(src, code)
|
|
294
|
+
add_text(src, rspace) if rspace
|
|
295
|
+
end
|
|
296
|
+
elsif indicator[0] == ?\# # <%# %>
|
|
297
|
+
n = code.count("\n") + (rspace ? 1 : 0)
|
|
298
|
+
if @trim && lspace && rspace
|
|
299
|
+
add_stmt(src, "\n" * n)
|
|
300
|
+
else
|
|
301
|
+
add_text(src, lspace) if lspace
|
|
302
|
+
add_stmt(src, "\n" * n)
|
|
303
|
+
add_text(src, rspace) if lspace
|
|
304
|
+
end
|
|
305
|
+
#flag_trim = @trim && lspace && rspace
|
|
306
|
+
#add_text(src, lspace) if !flag_trim && lspace
|
|
307
|
+
#n = code.count("\n") + (rspace ? 1 : 0)
|
|
308
|
+
#add_stmt(src, "\n" * n)
|
|
309
|
+
#add_text(src, rspace) if !flag_trim && rspace
|
|
310
|
+
else # <%= %>
|
|
311
|
+
add_text(src, lspace) if lspace
|
|
312
|
+
add_expr(src, code, indicator)
|
|
313
|
+
add_text(src, rspace) if rspace
|
|
314
|
+
end
|
|
315
|
+
#if indicator && indicator[0] == ?=
|
|
316
|
+
# flag_trim = false
|
|
317
|
+
#else
|
|
318
|
+
# flag_trim = @trim && lspace && rspace
|
|
319
|
+
#end
|
|
320
|
+
##flag_trim = @trim && !(indicator && indicator[0]==?=) && lspace && rspace
|
|
321
|
+
#add_text(src, text)
|
|
322
|
+
#add_text(src, lspace) if !flag_trim && lspace
|
|
323
|
+
#if !indicator # <% %>
|
|
324
|
+
# code = "#{lspace}#{code}#{rspace}" if flag_trim
|
|
325
|
+
# add_stmt(src, code)
|
|
326
|
+
#elsif indicator[0] == ?\# # <%# %>
|
|
327
|
+
# n = code.count("\n") + (rspace ? 1 : 0)
|
|
328
|
+
# add_stmt(src, "\n" * n)
|
|
329
|
+
#else # <%= %>
|
|
330
|
+
# add_expr(src, code, indicator)
|
|
331
|
+
#end
|
|
332
|
+
#add_text(src, rspace) if !flag_trim && rspace
|
|
333
|
+
end
|
|
334
|
+
rest = $' || input # add input when no matched
|
|
335
|
+
add_text(src, rest)
|
|
336
|
+
@postamble.nil? ? add_postamble(src) : (@postamble && (src << @postamble))
|
|
337
|
+
return src
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
## compile input string and set it to @src
|
|
341
|
+
def compile!(input)
|
|
342
|
+
@src = compile(input)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
protected
|
|
346
|
+
|
|
347
|
+
## escape text string
|
|
348
|
+
def escape_text(text)
|
|
349
|
+
return text
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
## return escaped expression code
|
|
353
|
+
def escaped_expr(code)
|
|
354
|
+
@escape ||= 'escape'
|
|
355
|
+
return "#{@escape}(#{code.strip})"
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
## .[empty] add @preamble to src
|
|
359
|
+
def add_preamble(src)
|
|
360
|
+
# empty
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
## .[abstract] add text string to src
|
|
364
|
+
def add_text(src, text)
|
|
365
|
+
not_implemented
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
## .[abstract] add statement code to src
|
|
369
|
+
def add_stmt(src, code)
|
|
370
|
+
not_implemented
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
## add expression code to src
|
|
374
|
+
def add_expr(src, code, indicator)
|
|
375
|
+
case indicator
|
|
376
|
+
when '='
|
|
377
|
+
add_expr_literal(src, code)
|
|
378
|
+
when '=='
|
|
379
|
+
add_expr_escaped(src, code)
|
|
380
|
+
when '==='
|
|
381
|
+
add_expr_debug(src, code)
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
## .[abstract] add expression literal code to src. this is called by add_expr().
|
|
386
|
+
def add_expr_literal(src, code)
|
|
387
|
+
not_implemented
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
## .[abstract] add escaped expression code to src. this is called by add_expr().
|
|
391
|
+
def add_expr_escaped(src, code)
|
|
392
|
+
not_implemented
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
## .[empty] add expression code to src for debug. this is called by add_expr().
|
|
396
|
+
def add_expr_debug(src, code)
|
|
397
|
+
# empty
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
## .[empty] add @postamble to src
|
|
401
|
+
def add_postamble(src)
|
|
402
|
+
# empty
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
end # end of class Engine
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
end
|
|
409
|
+
#--end of require 'erubis/engine'
|
|
410
|
+
#--begin of require 'erubis/helper'
|
|
411
|
+
##
|
|
412
|
+
## $Rev: 21 $
|
|
413
|
+
## $Release: 2.0.0 $
|
|
414
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
415
|
+
##
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
module Erubis
|
|
419
|
+
|
|
420
|
+
##
|
|
421
|
+
## helper for xml
|
|
422
|
+
##
|
|
423
|
+
module XmlHelper
|
|
424
|
+
|
|
425
|
+
module_function
|
|
426
|
+
|
|
427
|
+
ESCAPE_TABLE = {
|
|
428
|
+
'&' => '&',
|
|
429
|
+
'<' => '<',
|
|
430
|
+
'>' => '>',
|
|
431
|
+
'"' => '"',
|
|
432
|
+
"'" => ''',
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
def escape_xml(obj)
|
|
436
|
+
#table = ESCAPE_TABLE
|
|
437
|
+
#obj.to_s.gsub(/[&<>"]/) { |s| table[s] } # or /[&<>"']/
|
|
438
|
+
obj.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] } # or /[&<>"']/
|
|
439
|
+
#obj.to_s.gsub(SCAN_REGEXP) { |s| ESCAPE_TABLE[s] }
|
|
440
|
+
#obj.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
#--
|
|
444
|
+
#def escape_xml(obj)
|
|
445
|
+
# str = obj.to_s.dup
|
|
446
|
+
# #str = obj.to_s
|
|
447
|
+
# #str = str.dup if obj.__id__ == str.__id__
|
|
448
|
+
# str.gsub!(/&/, '&')
|
|
449
|
+
# str.gsub!(/</, '<')
|
|
450
|
+
# str.gsub!(/>/, '>')
|
|
451
|
+
# str.gsub!(/"/, '"')
|
|
452
|
+
# str.gsub!(/'/, ''')
|
|
453
|
+
# return str
|
|
454
|
+
#end
|
|
455
|
+
#++
|
|
456
|
+
|
|
457
|
+
alias h escape_xml
|
|
458
|
+
alias html_escape escape_xml
|
|
459
|
+
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
end
|
|
464
|
+
#--end of require 'erubis/helper'
|
|
465
|
+
#--begin of require 'erubis/enhancer'
|
|
466
|
+
##
|
|
467
|
+
## $Rev: 21 $
|
|
468
|
+
## $Release: 2.0.0 $
|
|
469
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
470
|
+
##
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
#--already included require 'erubis/engine'
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
module Erubis
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
##
|
|
480
|
+
## switch '<%= ... %>' to escaped and '<%== ... %>' to unescaped
|
|
481
|
+
##
|
|
482
|
+
## ex.
|
|
483
|
+
## class XmlEruby < Eruby
|
|
484
|
+
## include EscapeEnhancer
|
|
485
|
+
## end
|
|
486
|
+
##
|
|
487
|
+
## this is language-indenedent.
|
|
488
|
+
##
|
|
489
|
+
module EscapeEnhancer
|
|
490
|
+
|
|
491
|
+
def self.desc # :nodoc:
|
|
492
|
+
"switch '<%= %>' to escaped and '<%== %>' to unescaped"
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
#--
|
|
496
|
+
#def self.included(klass)
|
|
497
|
+
# klass.class_eval <<-END
|
|
498
|
+
# alias _add_expr_literal add_expr_literal
|
|
499
|
+
# alias _add_expr_escaped add_expr_escaped
|
|
500
|
+
# alias add_expr_literal _add_expr_escaped
|
|
501
|
+
# alias add_expr_escaped _add_expr_literal
|
|
502
|
+
# END
|
|
503
|
+
#end
|
|
504
|
+
#++
|
|
505
|
+
|
|
506
|
+
def add_expr(src, code, indicator)
|
|
507
|
+
case indicator
|
|
508
|
+
when '='
|
|
509
|
+
add_expr_escaped(src, code)
|
|
510
|
+
#add_expr_literal(src, code)
|
|
511
|
+
when '=='
|
|
512
|
+
add_expr_literal(src, code)
|
|
513
|
+
#add_expr_escaped(src, code)
|
|
514
|
+
when '==='
|
|
515
|
+
add_expr_debug(src, code)
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
#--
|
|
523
|
+
## (obsolete)
|
|
524
|
+
#module FastEnhancer
|
|
525
|
+
#end
|
|
526
|
+
#++
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
##
|
|
530
|
+
## use $stdout instead of string
|
|
531
|
+
##
|
|
532
|
+
## this is only for Eruby.
|
|
533
|
+
##
|
|
534
|
+
module StdoutEnhancer
|
|
535
|
+
|
|
536
|
+
def self.desc # :nodoc:
|
|
537
|
+
"use $stdout instead of array buffer or string buffer"
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def add_preamble(src)
|
|
541
|
+
src << "_buf = $stdout;"
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
def add_postamble(src)
|
|
545
|
+
src << "\n''\n"
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
##
|
|
552
|
+
## use print statement instead of '_buf << ...'
|
|
553
|
+
##
|
|
554
|
+
## this is only for Eruby.
|
|
555
|
+
##
|
|
556
|
+
module PrintOutEnhancer
|
|
557
|
+
|
|
558
|
+
def self.desc # :nodoc:
|
|
559
|
+
"use print statement instead of '_buf << ...'"
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def add_preamble(src)
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def add_text(src, text)
|
|
566
|
+
src << " print '" << escape_text(text) << "';" unless text.empty?
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def add_expr_literal(src, code)
|
|
570
|
+
src << ' print((' << code << ').to_s);'
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def add_expr_escaped(src, code)
|
|
574
|
+
src << ' print ' << escaped_expr(code) << ';'
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
def add_postamble(src)
|
|
578
|
+
src << "\n" unless src[-1] == ?\n
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
##
|
|
585
|
+
## enable print function
|
|
586
|
+
##
|
|
587
|
+
## Notice: use Eruby#evaluate() and don't use Eruby#result()
|
|
588
|
+
## to be enable print function.
|
|
589
|
+
##
|
|
590
|
+
## this is only for Eruby.
|
|
591
|
+
##
|
|
592
|
+
module PrintEnabledEnhancer
|
|
593
|
+
|
|
594
|
+
def self.desc # :nodoc:
|
|
595
|
+
"enable to use print function in '<% %>'"
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
def add_preamble(src)
|
|
599
|
+
src << "@_buf = "
|
|
600
|
+
super
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def print(*args)
|
|
604
|
+
args.each do |arg|
|
|
605
|
+
@_buf << arg.to_s
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
def evaluate(context=Context.new)
|
|
610
|
+
_src = @src
|
|
611
|
+
if context.is_a?(Hash)
|
|
612
|
+
context.each do |key, val| instance_variable_set("@#{key}", val) end
|
|
613
|
+
else
|
|
614
|
+
context.instance_variables.each do |name|
|
|
615
|
+
instance_variable_set(name, context.instance_variable_get(name))
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
return instance_eval(_src, (@filename || '(erubis)'))
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
##
|
|
625
|
+
## return array instead of string
|
|
626
|
+
##
|
|
627
|
+
## this is only for Eruby.
|
|
628
|
+
##
|
|
629
|
+
module ArrayEnhancer
|
|
630
|
+
|
|
631
|
+
def self.desc # :nodoc:
|
|
632
|
+
"return array instead of string"
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
def add_preamble(src)
|
|
636
|
+
src << "_buf = [];"
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
def add_postamble(src)
|
|
640
|
+
src << "\n" unless src[-1] == ?\n
|
|
641
|
+
src << "_buf\n"
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
##
|
|
648
|
+
## use an Array object as buffer (included in Eruby by default)
|
|
649
|
+
##
|
|
650
|
+
## this is only for Eruby.
|
|
651
|
+
##
|
|
652
|
+
module ArrayBufferEnhancer
|
|
653
|
+
|
|
654
|
+
def self.desc # :nodoc:
|
|
655
|
+
"use an Array object for buffering (included in Eruby class)"
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
def add_preamble(src)
|
|
659
|
+
src << "_buf = [];"
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
def add_postamble(src)
|
|
663
|
+
src << "\n" unless src[-1] == ?\n
|
|
664
|
+
src << "_buf.join\n"
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
##
|
|
671
|
+
## use String class for buffering
|
|
672
|
+
##
|
|
673
|
+
## this is only for Eruby.
|
|
674
|
+
##
|
|
675
|
+
module StringBufferEnhancer
|
|
676
|
+
|
|
677
|
+
def self.desc # :nodoc:
|
|
678
|
+
"use a String object for buffering"
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
def add_preamble(src)
|
|
682
|
+
src << "_buf = '';"
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
def add_postamble(src)
|
|
686
|
+
src << "\n" unless src[-1] == ?\n
|
|
687
|
+
src << "_buf\n"
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
##
|
|
694
|
+
## use StringIO class for buffering
|
|
695
|
+
##
|
|
696
|
+
## this is only for Eruby.
|
|
697
|
+
##
|
|
698
|
+
module StringIOEnhancer # :nodoc:
|
|
699
|
+
|
|
700
|
+
def self.desc # :nodoc:
|
|
701
|
+
"use a StringIO object for buffering"
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
def add_preamble(src)
|
|
705
|
+
src << "_buf = StringIO.new;"
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
def add_postamble(src)
|
|
709
|
+
src << "\n" unless src[-1] == ?\n
|
|
710
|
+
src << "_buf.string\n"
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
##
|
|
717
|
+
## remove text and leave code, especially useful when debugging.
|
|
718
|
+
##
|
|
719
|
+
## ex.
|
|
720
|
+
## $ erubis -s -e NoText file.eruby | more
|
|
721
|
+
##
|
|
722
|
+
## this is language independent.
|
|
723
|
+
##
|
|
724
|
+
module NoTextEnhancer
|
|
725
|
+
|
|
726
|
+
def self.desc # :nodoc:
|
|
727
|
+
"remove text and leave code (useful when debugging)"
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
def add_text(src, text)
|
|
731
|
+
src << ("\n" * text.count("\n"))
|
|
732
|
+
if text[-1] != ?\n
|
|
733
|
+
text =~ /^(.*?)\z/
|
|
734
|
+
src << (' ' * $1.length)
|
|
735
|
+
end
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
##
|
|
742
|
+
## get compile faster, but spaces around '<%...%>' are not trimmed.
|
|
743
|
+
##
|
|
744
|
+
## this is language-independent.
|
|
745
|
+
##
|
|
746
|
+
module SimplifyEnhancer
|
|
747
|
+
|
|
748
|
+
def self.desc # :nodoc:
|
|
749
|
+
"get compile faster but leave spaces around '<% %>'"
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
#DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
|
|
753
|
+
SIMPLE_REGEXP = /(.*?)<%(=+|\#)?(.*?)-?%>/m
|
|
754
|
+
|
|
755
|
+
def compile(input)
|
|
756
|
+
src = ""
|
|
757
|
+
add_preamble(src)
|
|
758
|
+
#regexp = pattern_regexp(@pattern)
|
|
759
|
+
input.scan(SIMPLE_REGEXP) do |text, indicator, code|
|
|
760
|
+
add_text(src, text)
|
|
761
|
+
if !indicator # <% %>
|
|
762
|
+
add_stmt(src, code)
|
|
763
|
+
elsif indicator[0] == ?\# # <%# %>
|
|
764
|
+
n = code.count("\n")
|
|
765
|
+
add_stmt(src, "\n" * n)
|
|
766
|
+
else # <%= %>
|
|
767
|
+
add_expr(src, code, indicator)
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
rest = $' || input
|
|
771
|
+
add_text(src, rest)
|
|
772
|
+
add_postamble(src)
|
|
773
|
+
return src
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
##
|
|
780
|
+
## enable to use other embedded expression pattern (default is '\[= =\]').
|
|
781
|
+
##
|
|
782
|
+
## notice! this is an experimental. spec may change in the future.
|
|
783
|
+
##
|
|
784
|
+
## ex.
|
|
785
|
+
## input = <<END
|
|
786
|
+
## <% for item in list %>
|
|
787
|
+
## <%= item %> : <%== item %>
|
|
788
|
+
## [= item =] : [== item =]
|
|
789
|
+
## <% end %>
|
|
790
|
+
## END
|
|
791
|
+
##
|
|
792
|
+
## class BiPatternEruby
|
|
793
|
+
## include BiPatternEnhancer
|
|
794
|
+
## end
|
|
795
|
+
## eruby = BiPatternEruby.new(input, :bipattern=>'\[= =\]')
|
|
796
|
+
## list = ['<a>', 'b&b', '"c"']
|
|
797
|
+
## print eruby.result(binding())
|
|
798
|
+
##
|
|
799
|
+
## ## output
|
|
800
|
+
## <a> : <a>
|
|
801
|
+
## <a> : <a>
|
|
802
|
+
## b&b : b&b
|
|
803
|
+
## b&b : b&b
|
|
804
|
+
## "c" : "c"
|
|
805
|
+
## "c" : "c"
|
|
806
|
+
##
|
|
807
|
+
## this is language independent.
|
|
808
|
+
##
|
|
809
|
+
module BiPatternEnhancer
|
|
810
|
+
|
|
811
|
+
def self.desc # :nodoc:
|
|
812
|
+
"another embedded expression pattern (default '\[= =\]')."
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
def initialize(input, properties={})
|
|
816
|
+
self.bipattern = properties[:bipattern] # or '\$\{ \}'
|
|
817
|
+
super
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
## when pat is nil then '\[= =\]' is used
|
|
821
|
+
def bipattern=(pat) # :nodoc:
|
|
822
|
+
@bipattern = pat || '\[= =\]'
|
|
823
|
+
pre, post = @bipattern.split()
|
|
824
|
+
@bipattern_regexp = /(.*?)#{pre}(=*)(.*?)#{post}/m
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
def add_text(src, text)
|
|
828
|
+
return unless text
|
|
829
|
+
text.scan(@bipattern_regexp) do |txt, indicator, code|
|
|
830
|
+
super(src, txt)
|
|
831
|
+
add_expr(src, code, '=' + indicator)
|
|
832
|
+
end
|
|
833
|
+
rest = $' || text
|
|
834
|
+
super(src, rest)
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
##
|
|
841
|
+
## regards lines starting with '%' as program code
|
|
842
|
+
##
|
|
843
|
+
## this is for compatibility to eruby and ERB.
|
|
844
|
+
##
|
|
845
|
+
## this is language-independent.
|
|
846
|
+
##
|
|
847
|
+
module PercentLineEnhancer
|
|
848
|
+
|
|
849
|
+
def self.desc # :nodoc:
|
|
850
|
+
"regard lines starting with '%' as program code"
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
PERCENT_LINE_PATTERN = /(.*?)^\%(.*?\r?\n)/m
|
|
854
|
+
|
|
855
|
+
def add_text(src, text)
|
|
856
|
+
text.scan(PERCENT_LINE_PATTERN) do |txt, line|
|
|
857
|
+
super(src, txt)
|
|
858
|
+
if line[0] == ?%
|
|
859
|
+
super(src, line)
|
|
860
|
+
else
|
|
861
|
+
add_stmt(src, line)
|
|
862
|
+
end
|
|
863
|
+
end
|
|
864
|
+
rest = $' || text
|
|
865
|
+
super(src, rest)
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
##
|
|
872
|
+
## [experimental] allow header and footer in eRuby script
|
|
873
|
+
##
|
|
874
|
+
## ex.
|
|
875
|
+
## ====================
|
|
876
|
+
## ## without header and footer
|
|
877
|
+
## $ cat ex1.eruby
|
|
878
|
+
## <% def list_items(list) %>
|
|
879
|
+
## <% for item in list %>
|
|
880
|
+
## <li><%= item %></li>
|
|
881
|
+
## <% end %>
|
|
882
|
+
## <% end %>
|
|
883
|
+
##
|
|
884
|
+
## $ erubis -s ex1.eruby
|
|
885
|
+
## _buf = []; def list_items(list)
|
|
886
|
+
## ; for item in list
|
|
887
|
+
## ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
|
|
888
|
+
## '; end
|
|
889
|
+
## ; end
|
|
890
|
+
## ;
|
|
891
|
+
## _buf.join
|
|
892
|
+
##
|
|
893
|
+
## ## with header and footer
|
|
894
|
+
## $ cat ex2.eruby
|
|
895
|
+
## <!--#header:
|
|
896
|
+
## def list_items(list)
|
|
897
|
+
## #-->
|
|
898
|
+
## <% for item in list %>
|
|
899
|
+
## <li><%= item %></li>
|
|
900
|
+
## <% end %>
|
|
901
|
+
## <!--#footer:
|
|
902
|
+
## end
|
|
903
|
+
## #-->
|
|
904
|
+
##
|
|
905
|
+
## $ erubis -s -c HeaderFooterEruby ex4.eruby
|
|
906
|
+
##
|
|
907
|
+
## def list_items(list)
|
|
908
|
+
## _buf = []; _buf << '
|
|
909
|
+
## '; for item in list
|
|
910
|
+
## ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
|
|
911
|
+
## '; end
|
|
912
|
+
## ; _buf << '
|
|
913
|
+
## ';
|
|
914
|
+
## _buf.join
|
|
915
|
+
## end
|
|
916
|
+
##
|
|
917
|
+
## ====================
|
|
918
|
+
##
|
|
919
|
+
## this is language-independent.
|
|
920
|
+
##
|
|
921
|
+
module HeaderFooterEnhancer
|
|
922
|
+
|
|
923
|
+
def self.desc # :nodoc:
|
|
924
|
+
"allow header/footer in document (ex. '<!--#header: #-->')"
|
|
925
|
+
end
|
|
926
|
+
|
|
927
|
+
HEADER_FOOTER_PATTERN = /(.*?)(^[ \t]*)?<!--\#(\w+):(.*?)\#-->([ \t]*\r?\n)?/m
|
|
928
|
+
|
|
929
|
+
def add_text(src, text)
|
|
930
|
+
text.scan(HEADER_FOOTER_PATTERN) do |txt, lspace, word, content, rspace|
|
|
931
|
+
flag_trim = @trim && lspace && rspace
|
|
932
|
+
super(src, txt)
|
|
933
|
+
content = "#{lspace}#{content}#{rspace}" if flag_trim
|
|
934
|
+
super(src, lspace) if !flag_trim && lspace
|
|
935
|
+
instance_variable_set("@#{word}", content)
|
|
936
|
+
super(src, rspace) if !flag_trim && rspace
|
|
937
|
+
end
|
|
938
|
+
rest = $' || text
|
|
939
|
+
super(src, rest)
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
attr_accessor :header, :footer
|
|
943
|
+
|
|
944
|
+
def compile(input)
|
|
945
|
+
source = super
|
|
946
|
+
return @src = "#{@header}#{source}#{@footer}"
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
end
|
|
953
|
+
#--end of require 'erubis/enhancer'
|
|
954
|
+
#require 'erubis/tiny'
|
|
955
|
+
#--begin of require 'erubis/engine/eruby'
|
|
956
|
+
##
|
|
957
|
+
## $Rev: 21 $
|
|
958
|
+
## $Release: 2.0.0 $
|
|
959
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
960
|
+
##
|
|
961
|
+
|
|
962
|
+
#--already included require 'erubis/engine'
|
|
963
|
+
#--already included require 'erubis/enhancer'
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
module Erubis
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
##
|
|
970
|
+
## engine for Ruby
|
|
971
|
+
##
|
|
972
|
+
class Eruby < Engine
|
|
973
|
+
#include StringBufferEnhancer
|
|
974
|
+
include ArrayBufferEnhancer
|
|
975
|
+
|
|
976
|
+
def self.supported_properties() # :nodoc:
|
|
977
|
+
return super
|
|
978
|
+
end
|
|
979
|
+
|
|
980
|
+
def escape_text(text)
|
|
981
|
+
text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\'
|
|
982
|
+
end
|
|
983
|
+
|
|
984
|
+
def escaped_expr(code)
|
|
985
|
+
@escape ||= "Erubis::XmlHelper.escape_xml"
|
|
986
|
+
return "#{@escape}(#{code})"
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
#--
|
|
990
|
+
#def add_preamble(src)
|
|
991
|
+
# src << "_buf = [];"
|
|
992
|
+
#end
|
|
993
|
+
#++
|
|
994
|
+
|
|
995
|
+
def add_text(src, text)
|
|
996
|
+
src << " _buf << '" << escape_text(text) << "';" unless text.empty?
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
def add_stmt(src, code)
|
|
1000
|
+
#src << code << ';'
|
|
1001
|
+
src << code
|
|
1002
|
+
src << ';' unless code[-1] == ?\n
|
|
1003
|
+
end
|
|
1004
|
+
|
|
1005
|
+
def add_expr_literal(src, code)
|
|
1006
|
+
src << ' _buf << (' << code << ').to_s;'
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
def add_expr_escaped(src, code)
|
|
1010
|
+
src << ' _buf << ' << escaped_expr(code) << ';'
|
|
1011
|
+
end
|
|
1012
|
+
|
|
1013
|
+
def add_expr_debug(src, code)
|
|
1014
|
+
code.strip!
|
|
1015
|
+
s = (code.dump =~ /\A"(.*)"\z/) && $1
|
|
1016
|
+
src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
|
|
1017
|
+
end
|
|
1018
|
+
|
|
1019
|
+
#--
|
|
1020
|
+
#def add_postamble(src)
|
|
1021
|
+
# src << "\n_buf.join\n"
|
|
1022
|
+
#end
|
|
1023
|
+
#++
|
|
1024
|
+
|
|
1025
|
+
end
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
##
|
|
1029
|
+
## swtich '<%= %>' to escaped and '<%== %>' to not escaped
|
|
1030
|
+
##
|
|
1031
|
+
class EscapedEruby < Eruby
|
|
1032
|
+
include EscapeEnhancer
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
##
|
|
1037
|
+
## sanitize expression (<%= ... %>) by default
|
|
1038
|
+
##
|
|
1039
|
+
## this is equivalent to EscapedEruby and is prepared only for compatibility.
|
|
1040
|
+
##
|
|
1041
|
+
class XmlEruby < Eruby
|
|
1042
|
+
include EscapeEnhancer
|
|
1043
|
+
end
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
end
|
|
1047
|
+
#--end of require 'erubis/engine/eruby'
|
|
1048
|
+
#require 'erubis/engine/enhanced' # enhanced eruby engines
|
|
1049
|
+
#require 'erubis/engine/optimized' # generates optimized ruby code
|
|
1050
|
+
#require 'erubis/engine/ephp'
|
|
1051
|
+
#require 'erubis/engine/ec'
|
|
1052
|
+
#require 'erubis/engine/ejava'
|
|
1053
|
+
#require 'erubis/engine/escheme'
|
|
1054
|
+
#require 'erubis/engine/eperl'
|
|
1055
|
+
#require 'erubis/engine/ejavascript'
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
#--begin of require 'erubis/local-setting'
|
|
1059
|
+
##
|
|
1060
|
+
## $Rev: 13 $
|
|
1061
|
+
## $Release: 2.0.0 $
|
|
1062
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1063
|
+
##
|
|
1064
|
+
|
|
1065
|
+
##
|
|
1066
|
+
## you can add site-local settings here.
|
|
1067
|
+
## this files is 'require'd by erubis.rb
|
|
1068
|
+
##
|
|
1069
|
+
#--end of require 'erubis/local-setting'
|
|
1070
|
+
#--end of require 'erubis'
|
|
1071
|
+
#--begin of require 'erubis/tiny'
|
|
1072
|
+
##
|
|
1073
|
+
## $Rev: 21 $
|
|
1074
|
+
## $Release: 2.0.0 $
|
|
1075
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1076
|
+
##
|
|
1077
|
+
|
|
1078
|
+
module Erubis
|
|
1079
|
+
|
|
1080
|
+
##
|
|
1081
|
+
## tiny and the simplest implementation of eRuby
|
|
1082
|
+
##
|
|
1083
|
+
## ex.
|
|
1084
|
+
## eruby = TinyEruby.new(File.read('example.rhtml'))
|
|
1085
|
+
## print eruby.src # print ruby code
|
|
1086
|
+
## print eruby.result(binding()) # eval ruby code with Binding object
|
|
1087
|
+
## print eruby.evalute(context) # eval ruby code with context object
|
|
1088
|
+
##
|
|
1089
|
+
class TinyEruby
|
|
1090
|
+
|
|
1091
|
+
def initialize(input)
|
|
1092
|
+
@src = compile(input)
|
|
1093
|
+
end
|
|
1094
|
+
attr_reader :src
|
|
1095
|
+
|
|
1096
|
+
EMBEDDED_PATTERN = /(.*?)<%(=+|\#)?(.*?)-?%>/m
|
|
1097
|
+
|
|
1098
|
+
def compile(input)
|
|
1099
|
+
src = "_buf = [];" # preamble
|
|
1100
|
+
input.scan(EMBEDDED_PATTERN) do |text, indicator, code|
|
|
1101
|
+
src << " _buf << '" << escape_text(text) << "';"
|
|
1102
|
+
if !indicator # <% %>
|
|
1103
|
+
src << code << ";"
|
|
1104
|
+
elsif indicator[0] == ?\# # <%# %>
|
|
1105
|
+
n = code.count("\n")
|
|
1106
|
+
add_stmt(src, "\n" * n)
|
|
1107
|
+
else # <%= %>
|
|
1108
|
+
src << " _buf << (" << code << ").to_s;"
|
|
1109
|
+
end
|
|
1110
|
+
end
|
|
1111
|
+
rest = $' || input
|
|
1112
|
+
src << " _buf << '" << escape_text(rest) << "';"
|
|
1113
|
+
src << "\n_buf.join\n" # postamble
|
|
1114
|
+
return src
|
|
1115
|
+
end
|
|
1116
|
+
|
|
1117
|
+
def escape_text(text)
|
|
1118
|
+
return text.gsub!(/['\\]/, '\\\\\&') || text
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1121
|
+
def result(binding=TOPLEVEL_BINDING)
|
|
1122
|
+
eval @src, binding
|
|
1123
|
+
end
|
|
1124
|
+
|
|
1125
|
+
def evaluate(context=Object.new)
|
|
1126
|
+
if context.is_a?(Hash)
|
|
1127
|
+
obj = Object.new
|
|
1128
|
+
context.each do |k, v| obj.instance_variable_set("@#{k}", v) end
|
|
1129
|
+
context = obj
|
|
1130
|
+
end
|
|
1131
|
+
context.instance_eval @src
|
|
1132
|
+
end
|
|
1133
|
+
|
|
1134
|
+
end
|
|
1135
|
+
|
|
1136
|
+
end
|
|
1137
|
+
#--end of require 'erubis/tiny'
|
|
1138
|
+
#--begin of require 'erubis/engine/enhanced'
|
|
1139
|
+
##
|
|
1140
|
+
## $Rev: 19 $
|
|
1141
|
+
## $Release: 2.0.0 $
|
|
1142
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1143
|
+
##
|
|
1144
|
+
|
|
1145
|
+
#--already included require 'erubis/enhancer'
|
|
1146
|
+
#--already included require 'erubis/engine/eruby'
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
module Erubis
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
#--
|
|
1153
|
+
## moved to engine/ruby.rb
|
|
1154
|
+
#class EscapedEruby < Eruby
|
|
1155
|
+
# include EscapeEnhancer
|
|
1156
|
+
#end
|
|
1157
|
+
#++
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
#--
|
|
1161
|
+
### (obsolete)
|
|
1162
|
+
#class FastEruby < Eruby
|
|
1163
|
+
# include FastEnhancer
|
|
1164
|
+
#end
|
|
1165
|
+
#++
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
class StdoutEruby < Eruby
|
|
1169
|
+
include StdoutEnhancer
|
|
1170
|
+
end
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
class PrintOutEruby < Eruby
|
|
1174
|
+
include PrintOutEnhancer
|
|
1175
|
+
end
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
class PrintEnabledEruby < Eruby
|
|
1179
|
+
include PrintEnabledEnhancer
|
|
1180
|
+
end
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
class ArrayEruby < Eruby
|
|
1184
|
+
include ArrayEnhancer
|
|
1185
|
+
end
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
class ArrayBufferEruby < Eruby
|
|
1189
|
+
include ArrayBufferEnhancer
|
|
1190
|
+
end
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
class StringBufferEruby < Eruby
|
|
1194
|
+
include StringBufferEnhancer
|
|
1195
|
+
end
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
class StringIOEruby < Eruby
|
|
1199
|
+
include StringIOEnhancer
|
|
1200
|
+
end
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
class NoTextEruby < Eruby
|
|
1204
|
+
include NoTextEnhancer
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
class SimplifiedEruby < Eruby
|
|
1209
|
+
include SimplifyEnhancer
|
|
1210
|
+
end
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
class StdoutSimplifiedEruby < Eruby
|
|
1214
|
+
include StdoutEnhancer
|
|
1215
|
+
include SimplifyEnhancer
|
|
1216
|
+
end
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
class PrintOutSimplifiedEruby < Eruby
|
|
1220
|
+
include PrintOutEnhancer
|
|
1221
|
+
include SimplifyEnhancer
|
|
1222
|
+
end
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
class BiPatternEruby < Eruby
|
|
1226
|
+
include BiPatternEnhancer
|
|
1227
|
+
end
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
class PercentLineEruby < Eruby
|
|
1231
|
+
include PercentLineEnhancer
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
class HeaderFooterEruby < Eruby
|
|
1236
|
+
include HeaderFooterEnhancer
|
|
1237
|
+
end
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
end
|
|
1241
|
+
#--end of require 'erubis/engine/enhanced'
|
|
1242
|
+
#--begin of require 'erubis/engine/optimized'
|
|
1243
|
+
##
|
|
1244
|
+
## $Rev: 21 $
|
|
1245
|
+
## $Release: 2.0.0 $
|
|
1246
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1247
|
+
##
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
#--already included require 'erubis/engine/eruby'
|
|
1251
|
+
|
|
1252
|
+
|
|
1253
|
+
module Erubis
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
##
|
|
1257
|
+
## Eruby class which generates optimized ruby code
|
|
1258
|
+
##
|
|
1259
|
+
class OptimizedEruby < Engine # Eruby
|
|
1260
|
+
|
|
1261
|
+
def self.supported_properties() # :nodoc:
|
|
1262
|
+
return super
|
|
1263
|
+
end
|
|
1264
|
+
|
|
1265
|
+
def initialize(input, properties={})
|
|
1266
|
+
@initialized = false
|
|
1267
|
+
@prev_is_expr = false
|
|
1268
|
+
super
|
|
1269
|
+
end
|
|
1270
|
+
|
|
1271
|
+
protected
|
|
1272
|
+
|
|
1273
|
+
def escape_text(text)
|
|
1274
|
+
text.gsub(/['\\]/, '\\\\\&') # "'" => "\\'", '\\' => '\\\\'
|
|
1275
|
+
end
|
|
1276
|
+
|
|
1277
|
+
def escaped_expr(code)
|
|
1278
|
+
@escape ||= 'Erubis::XmlHelper.escape_xml'
|
|
1279
|
+
return "#{@escape}(#{code})"
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1282
|
+
def switch_to_expr(src)
|
|
1283
|
+
return if @prev_is_expr
|
|
1284
|
+
@prev_is_expr = true
|
|
1285
|
+
src << ' _buf'
|
|
1286
|
+
end
|
|
1287
|
+
|
|
1288
|
+
def switch_to_stmt(src)
|
|
1289
|
+
return unless @prev_is_expr
|
|
1290
|
+
@prev_is_expr = false
|
|
1291
|
+
src << ';'
|
|
1292
|
+
end
|
|
1293
|
+
|
|
1294
|
+
def add_preamble(src)
|
|
1295
|
+
#@initialized = false
|
|
1296
|
+
#@prev_is_expr = false
|
|
1297
|
+
end
|
|
1298
|
+
|
|
1299
|
+
def add_text(src, text)
|
|
1300
|
+
return if text.empty?
|
|
1301
|
+
if @initialized
|
|
1302
|
+
switch_to_expr(src)
|
|
1303
|
+
src << " << '" << escape_text(text) << "'"
|
|
1304
|
+
else
|
|
1305
|
+
src << "_buf = '" << escape_text(text) << "';"
|
|
1306
|
+
@initialized = true
|
|
1307
|
+
end
|
|
1308
|
+
end
|
|
1309
|
+
|
|
1310
|
+
def add_stmt(src, code)
|
|
1311
|
+
switch_to_stmt(src) if @initialized
|
|
1312
|
+
#super
|
|
1313
|
+
src << code
|
|
1314
|
+
src << ';' unless code[-1] == ?\n
|
|
1315
|
+
end
|
|
1316
|
+
|
|
1317
|
+
def add_expr_literal(src, code)
|
|
1318
|
+
unless @initialized; src << "_buf = ''"; @initialized = true; end
|
|
1319
|
+
switch_to_expr(src)
|
|
1320
|
+
src << " << (" << code << ").to_s"
|
|
1321
|
+
end
|
|
1322
|
+
|
|
1323
|
+
def add_expr_escaped(src, code)
|
|
1324
|
+
unless @initialized; src << "_buf = ''"; @initialized = true; end
|
|
1325
|
+
switch_to_expr(src)
|
|
1326
|
+
src << " << " << escaped_expr(code)
|
|
1327
|
+
end
|
|
1328
|
+
|
|
1329
|
+
def add_expr_debug(src, code)
|
|
1330
|
+
code.strip!
|
|
1331
|
+
s = (code.dump =~ /\A"(.*)"\z/) && $1
|
|
1332
|
+
src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
|
|
1333
|
+
end
|
|
1334
|
+
|
|
1335
|
+
def add_postamble(src)
|
|
1336
|
+
#super if @initialized
|
|
1337
|
+
src << "\n_buf\n" if @initialized
|
|
1338
|
+
end
|
|
1339
|
+
|
|
1340
|
+
end # end of class OptimizedEruby
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
##
|
|
1344
|
+
## XmlEruby class which generates optimized ruby code
|
|
1345
|
+
##
|
|
1346
|
+
class OptimizedXmlEruby < OptimizedEruby
|
|
1347
|
+
include EscapeEnhancer
|
|
1348
|
+
|
|
1349
|
+
def add_expr_debug(src, code)
|
|
1350
|
+
switch_to_stmt(src) if indicator == '===' && !@initialized
|
|
1351
|
+
super
|
|
1352
|
+
end
|
|
1353
|
+
|
|
1354
|
+
end # end of class OptimizedXmlEruby
|
|
1355
|
+
|
|
1356
|
+
end
|
|
1357
|
+
#--end of require 'erubis/engine/optimized'
|
|
1358
|
+
#--already included require 'erubis/engine/eruby'
|
|
1359
|
+
#--begin of require 'erubis/engine/ephp'
|
|
1360
|
+
##
|
|
1361
|
+
## $Rev: 19 $
|
|
1362
|
+
## $Release: 2.0.0 $
|
|
1363
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1364
|
+
##
|
|
1365
|
+
|
|
1366
|
+
#--already included require 'erubis/engine'
|
|
1367
|
+
#--already included require 'erubis/enhancer'
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
module Erubis
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
##
|
|
1374
|
+
## engine for PHP
|
|
1375
|
+
##
|
|
1376
|
+
class Ephp < Engine
|
|
1377
|
+
|
|
1378
|
+
def self.supported_properties() # :nodoc:
|
|
1379
|
+
return super
|
|
1380
|
+
end
|
|
1381
|
+
|
|
1382
|
+
#--
|
|
1383
|
+
#def add_preamble(src)
|
|
1384
|
+
#end
|
|
1385
|
+
#++
|
|
1386
|
+
|
|
1387
|
+
def escape_text(text)
|
|
1388
|
+
return text.gsub!(/<\?xml\b/, '<<?php ?>?xml') || text
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
def add_text(src, text)
|
|
1392
|
+
src << escape_text(text)
|
|
1393
|
+
end
|
|
1394
|
+
|
|
1395
|
+
def escaped_expr(code)
|
|
1396
|
+
@escape ||= 'htmlspecialchars'
|
|
1397
|
+
return "#{@escape}(#{code.strip})"
|
|
1398
|
+
end
|
|
1399
|
+
|
|
1400
|
+
def add_expr_literal(src, code)
|
|
1401
|
+
src << "<?php echo #{code.strip}; ?>"
|
|
1402
|
+
end
|
|
1403
|
+
|
|
1404
|
+
def add_expr_escaped(src, code)
|
|
1405
|
+
src << "<?php echo #{escaped_expr(code)}; ?>"
|
|
1406
|
+
end
|
|
1407
|
+
|
|
1408
|
+
def add_expr_debug(src, code)
|
|
1409
|
+
code.strip!
|
|
1410
|
+
s = code.gsub(/\'/, "\\'")
|
|
1411
|
+
src << "<?php error_log('*** debug: #{s}='.(#{code}), 0); ?>"
|
|
1412
|
+
end
|
|
1413
|
+
|
|
1414
|
+
def add_stmt(src, code)
|
|
1415
|
+
src << "<?php"
|
|
1416
|
+
src << " " if code[0] != ?\ #
|
|
1417
|
+
if code[-1] == ?\n
|
|
1418
|
+
code.chomp!
|
|
1419
|
+
src << code << "?>\n"
|
|
1420
|
+
else
|
|
1421
|
+
src << code << "?>"
|
|
1422
|
+
end
|
|
1423
|
+
end
|
|
1424
|
+
|
|
1425
|
+
#--
|
|
1426
|
+
#def add_postamble(src)
|
|
1427
|
+
#end
|
|
1428
|
+
#++
|
|
1429
|
+
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
class EscapedEphp < Ephp
|
|
1434
|
+
include EscapeEnhancer
|
|
1435
|
+
end
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
#class XmlEphp < Ephp
|
|
1439
|
+
# include EscapeEnhancer
|
|
1440
|
+
#end
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
end
|
|
1444
|
+
#--end of require 'erubis/engine/ephp'
|
|
1445
|
+
#--begin of require 'erubis/engine/ec'
|
|
1446
|
+
##
|
|
1447
|
+
## $Rev: 21 $
|
|
1448
|
+
## $Release: 2.0.0 $
|
|
1449
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1450
|
+
##
|
|
1451
|
+
|
|
1452
|
+
#--already included require 'erubis/engine'
|
|
1453
|
+
#--already included require 'erubis/enhancer'
|
|
1454
|
+
|
|
1455
|
+
|
|
1456
|
+
module Erubis
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
##
|
|
1460
|
+
## engine for C
|
|
1461
|
+
##
|
|
1462
|
+
class Ec < Engine
|
|
1463
|
+
|
|
1464
|
+
def self.supported_properties() # :nodoc:
|
|
1465
|
+
list = super
|
|
1466
|
+
list << [:indent, '', "indent spaces (ex. ' ')"]
|
|
1467
|
+
list << [:out, 'stdout', "output file pointer name"]
|
|
1468
|
+
return list
|
|
1469
|
+
end
|
|
1470
|
+
|
|
1471
|
+
def initialize(input, properties={})
|
|
1472
|
+
@indent = properties[:indent] || ''
|
|
1473
|
+
@out = properties[:out] || 'stdout'
|
|
1474
|
+
super
|
|
1475
|
+
end
|
|
1476
|
+
|
|
1477
|
+
def add_preamble(src)
|
|
1478
|
+
src << "#line 1 \"#{self.filename}\"\n" if self.filename
|
|
1479
|
+
end
|
|
1480
|
+
|
|
1481
|
+
def escape_text(text)
|
|
1482
|
+
@@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
|
|
1483
|
+
text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] }
|
|
1484
|
+
return text
|
|
1485
|
+
end
|
|
1486
|
+
|
|
1487
|
+
def escaped_expr(code)
|
|
1488
|
+
@escape ||= "escape"
|
|
1489
|
+
code.strip!
|
|
1490
|
+
if code =~ /\A(\".*?\")\s*,\s*(.*)/
|
|
1491
|
+
return "#{$1}, #{@escape}(#{$2})"
|
|
1492
|
+
else
|
|
1493
|
+
return "#{@escape}(#{code})"
|
|
1494
|
+
end
|
|
1495
|
+
end
|
|
1496
|
+
|
|
1497
|
+
def add_text(src, text)
|
|
1498
|
+
return if text.empty?
|
|
1499
|
+
src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
|
|
1500
|
+
src << "fputs("
|
|
1501
|
+
i = 0
|
|
1502
|
+
text.each_line do |line|
|
|
1503
|
+
src << "\n" << @indent << ' ' if i > 0
|
|
1504
|
+
i += 1
|
|
1505
|
+
src << '"' << escape_text(line) << '"'
|
|
1506
|
+
end
|
|
1507
|
+
src << ", #{@out});" #<< (text[-1] == ?\n ? "\n" : "")
|
|
1508
|
+
src << "\n" if text[-1] == ?\n
|
|
1509
|
+
end
|
|
1510
|
+
|
|
1511
|
+
def add_stmt(src, code)
|
|
1512
|
+
src << code
|
|
1513
|
+
end
|
|
1514
|
+
|
|
1515
|
+
def add_expr_literal(src, code)
|
|
1516
|
+
src << @indent if src.empty? || src[-1] == ?\n
|
|
1517
|
+
src << " fprintf(#{@out}, " << code.strip << ');'
|
|
1518
|
+
end
|
|
1519
|
+
|
|
1520
|
+
def add_expr_escaped(src, code)
|
|
1521
|
+
src << @indent if src.empty? || src[-1] == ?\n
|
|
1522
|
+
src << " fprintf(#{@out}, " << escaped_expr(code) << ');'
|
|
1523
|
+
end
|
|
1524
|
+
|
|
1525
|
+
def add_expr_debug(src, code)
|
|
1526
|
+
code.strip!
|
|
1527
|
+
s = nil
|
|
1528
|
+
if code =~ /\A\".*?\"\s*,\s*(.*)/
|
|
1529
|
+
s = $1.gsub(/[%"]/, '\\\1') + '='
|
|
1530
|
+
end
|
|
1531
|
+
src << @indent if src.empty? || src[-1] == ?\n
|
|
1532
|
+
src << " fprintf(stderr, \"*** debug: #{s}\" #{code});"
|
|
1533
|
+
end
|
|
1534
|
+
|
|
1535
|
+
def add_postamble(src)
|
|
1536
|
+
end
|
|
1537
|
+
|
|
1538
|
+
end
|
|
1539
|
+
|
|
1540
|
+
|
|
1541
|
+
class EscapedEc < Ec
|
|
1542
|
+
include EscapeEnhancer
|
|
1543
|
+
end
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
#class XmlEc < Ec
|
|
1547
|
+
# include EscapeEnhancer
|
|
1548
|
+
#end
|
|
1549
|
+
|
|
1550
|
+
|
|
1551
|
+
end
|
|
1552
|
+
#--end of require 'erubis/engine/ec'
|
|
1553
|
+
#--begin of require 'erubis/engine/ejava'
|
|
1554
|
+
##
|
|
1555
|
+
## $Rev: 21 $
|
|
1556
|
+
## $Release: 2.0.0 $
|
|
1557
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1558
|
+
##
|
|
1559
|
+
|
|
1560
|
+
#--already included require 'erubis/engine'
|
|
1561
|
+
#--already included require 'erubis/enhancer'
|
|
1562
|
+
|
|
1563
|
+
|
|
1564
|
+
module Erubis
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
##
|
|
1568
|
+
## engine for Java
|
|
1569
|
+
##
|
|
1570
|
+
class Ejava < Engine
|
|
1571
|
+
|
|
1572
|
+
def self.supported_properties() # :nodoc:
|
|
1573
|
+
list = super
|
|
1574
|
+
list << [:indent, '', "indent spaces (ex. ' ')"]
|
|
1575
|
+
list << [:buf, '_buf', "output buffer name"]
|
|
1576
|
+
list << [:bufclass, 'StringBuffer', "output buffer class (ex. 'StringBuilder')"]
|
|
1577
|
+
return list
|
|
1578
|
+
end
|
|
1579
|
+
|
|
1580
|
+
def initialize(input, properties={})
|
|
1581
|
+
@indent = properties[:indent] || ''
|
|
1582
|
+
@buf = properties[:buf] || '_buf'
|
|
1583
|
+
@bufclass = properties[:bufclass] || 'StringBuffer'
|
|
1584
|
+
super
|
|
1585
|
+
end
|
|
1586
|
+
|
|
1587
|
+
def add_preamble(src)
|
|
1588
|
+
src << "#{@indent}#{@bufclass} #{@buf} = new #{@bufclass}();"
|
|
1589
|
+
end
|
|
1590
|
+
|
|
1591
|
+
def escape_text(text)
|
|
1592
|
+
@@table_ ||= { "\r"=>"\\r", "\n"=>"\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
|
|
1593
|
+
return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
|
|
1594
|
+
end
|
|
1595
|
+
|
|
1596
|
+
#--
|
|
1597
|
+
#def escaped_expr(code)
|
|
1598
|
+
# @escape ||= 'escape'
|
|
1599
|
+
# return "#{@escape}(#{code.strip})"
|
|
1600
|
+
#end
|
|
1601
|
+
#++
|
|
1602
|
+
|
|
1603
|
+
def add_text(src, text)
|
|
1604
|
+
return if text.empty?
|
|
1605
|
+
src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
|
|
1606
|
+
src << @buf << ".append("
|
|
1607
|
+
i = 0
|
|
1608
|
+
text.each_line do |line|
|
|
1609
|
+
src << "\n" << @indent << ' + ' if i > 0
|
|
1610
|
+
i += 1
|
|
1611
|
+
src << '"' << escape_text(line) << '"'
|
|
1612
|
+
end
|
|
1613
|
+
src << ");" << (text[-1] == ?\n ? "\n" : "")
|
|
1614
|
+
end
|
|
1615
|
+
|
|
1616
|
+
def add_stmt(src, code)
|
|
1617
|
+
src << code
|
|
1618
|
+
end
|
|
1619
|
+
|
|
1620
|
+
def add_expr_literal(src, code)
|
|
1621
|
+
src << @indent if src.empty? || src[-1] == ?\n
|
|
1622
|
+
src << ' ' << @buf << '.append(' << code.strip << ');'
|
|
1623
|
+
end
|
|
1624
|
+
|
|
1625
|
+
def add_expr_escaped(src, code)
|
|
1626
|
+
src << @indent if src.empty? || src[-1] == ?\n
|
|
1627
|
+
src << ' ' << @buf << '.append(' << escaped_expr(code) << ');'
|
|
1628
|
+
end
|
|
1629
|
+
|
|
1630
|
+
def add_expr_debug(src, code)
|
|
1631
|
+
code.strip!
|
|
1632
|
+
src << @indent if src.empty? || src[-1] == ?\n
|
|
1633
|
+
src << " System.err.println(\"*** debug: #{code}=\"+(#{code}));"
|
|
1634
|
+
end
|
|
1635
|
+
|
|
1636
|
+
def add_postamble(src)
|
|
1637
|
+
src << "\n" if src[-1] == ?;
|
|
1638
|
+
src << @indent << "return " << @buf << ".toString();\n"
|
|
1639
|
+
end
|
|
1640
|
+
|
|
1641
|
+
end
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
class EscapedEjava < Ejava
|
|
1645
|
+
include EscapeEnhancer
|
|
1646
|
+
end
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
#class XmlEjava < Ejava
|
|
1650
|
+
# include EscapeEnhancer
|
|
1651
|
+
#end
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
end
|
|
1655
|
+
#--end of require 'erubis/engine/ejava'
|
|
1656
|
+
#--begin of require 'erubis/engine/escheme'
|
|
1657
|
+
##
|
|
1658
|
+
## $Rev: 21 $
|
|
1659
|
+
## $Release: 2.0.0 $
|
|
1660
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1661
|
+
##
|
|
1662
|
+
|
|
1663
|
+
#--already included require 'erubis/engine'
|
|
1664
|
+
#--already included require 'erubis/enhancer'
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
module Erubis
|
|
1668
|
+
|
|
1669
|
+
|
|
1670
|
+
##
|
|
1671
|
+
## engine for Scheme
|
|
1672
|
+
##
|
|
1673
|
+
class Escheme < Engine
|
|
1674
|
+
|
|
1675
|
+
def self.supported_properties() # :nodoc:
|
|
1676
|
+
list = super
|
|
1677
|
+
list << [:func, '_add', "function name (ex. 'display')"]
|
|
1678
|
+
return list
|
|
1679
|
+
end
|
|
1680
|
+
|
|
1681
|
+
def initialize(input, properties={})
|
|
1682
|
+
@func = properties[:func] || '_add' # or 'display'
|
|
1683
|
+
super
|
|
1684
|
+
end
|
|
1685
|
+
|
|
1686
|
+
def add_preamble(src)
|
|
1687
|
+
return unless @func == '_add'
|
|
1688
|
+
src << "(let ((_buf '())) " + \
|
|
1689
|
+
"(define (_add x) (set! _buf (cons x _buf))) "
|
|
1690
|
+
#src << "(let* ((_buf '())" + \
|
|
1691
|
+
# " (_add (lambda (x) (set! _buf (cons x _buf))))) "
|
|
1692
|
+
end
|
|
1693
|
+
|
|
1694
|
+
def escape_text(text)
|
|
1695
|
+
@table_ ||= { '"'=>'\\"', '\\'=>'\\\\' }
|
|
1696
|
+
text.gsub!(/["\\]/) { |m| @table_[m] }
|
|
1697
|
+
return text
|
|
1698
|
+
end
|
|
1699
|
+
|
|
1700
|
+
def escaped_expr(code)
|
|
1701
|
+
@escape ||= 'escape'
|
|
1702
|
+
return "(#{@escape} #{code.strip})"
|
|
1703
|
+
end
|
|
1704
|
+
|
|
1705
|
+
def add_text(src, text)
|
|
1706
|
+
return if text.empty?
|
|
1707
|
+
t = escape_text(text)
|
|
1708
|
+
if t[-1] == ?\n
|
|
1709
|
+
t[-1, 1] = ''
|
|
1710
|
+
src << "(#{@func} \"" << t << "\\n\")\n"
|
|
1711
|
+
else
|
|
1712
|
+
src << "(#{@func} \"" << t << '")'
|
|
1713
|
+
end
|
|
1714
|
+
end
|
|
1715
|
+
|
|
1716
|
+
def add_stmt(src, code)
|
|
1717
|
+
src << code
|
|
1718
|
+
end
|
|
1719
|
+
|
|
1720
|
+
def add_expr_literal(src, code)
|
|
1721
|
+
src << "(#{@func} " << code.strip << ')'
|
|
1722
|
+
end
|
|
1723
|
+
|
|
1724
|
+
def add_expr_escaped(src, code)
|
|
1725
|
+
src << "(#{@func} " << escaped_expr(code) << ')'
|
|
1726
|
+
end
|
|
1727
|
+
|
|
1728
|
+
def add_expr_debug(src, code)
|
|
1729
|
+
s = (code.strip! || code).gsub(/\"/, '\\"')
|
|
1730
|
+
src << "(display \"*** debug: #{s}=\")(display #{code.strip})(display \"\\n\")"
|
|
1731
|
+
end
|
|
1732
|
+
|
|
1733
|
+
def add_postamble(src)
|
|
1734
|
+
return unless @func == '_add'
|
|
1735
|
+
src << "\n" unless src[-1] == ?\n
|
|
1736
|
+
src << " (reverse _buf))\n"
|
|
1737
|
+
end
|
|
1738
|
+
|
|
1739
|
+
end
|
|
1740
|
+
|
|
1741
|
+
|
|
1742
|
+
class EscapedEscheme < Escheme
|
|
1743
|
+
include EscapeEnhancer
|
|
1744
|
+
end
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
#class XmlEscheme < Escheme
|
|
1748
|
+
# include EscapeEnhancer
|
|
1749
|
+
#end
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
end
|
|
1753
|
+
#--end of require 'erubis/engine/escheme'
|
|
1754
|
+
#--begin of require 'erubis/engine/eperl'
|
|
1755
|
+
##
|
|
1756
|
+
## $Rev: 19 $
|
|
1757
|
+
## $Release: 2.0.0 $
|
|
1758
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1759
|
+
##
|
|
1760
|
+
|
|
1761
|
+
#--already included require 'erubis/engine'
|
|
1762
|
+
#--already included require 'erubis/enhancer'
|
|
1763
|
+
|
|
1764
|
+
|
|
1765
|
+
module Erubis
|
|
1766
|
+
|
|
1767
|
+
|
|
1768
|
+
##
|
|
1769
|
+
## engine for Perl
|
|
1770
|
+
##
|
|
1771
|
+
class Eperl < Engine
|
|
1772
|
+
|
|
1773
|
+
def self.supported_properties() # :nodoc:
|
|
1774
|
+
list = super
|
|
1775
|
+
list << [:func, 'print', "function name"]
|
|
1776
|
+
return list
|
|
1777
|
+
end
|
|
1778
|
+
|
|
1779
|
+
def initialize(input, properties={})
|
|
1780
|
+
@func = properties[:func] || 'print'
|
|
1781
|
+
super
|
|
1782
|
+
end
|
|
1783
|
+
|
|
1784
|
+
def add_preamble(src)
|
|
1785
|
+
end
|
|
1786
|
+
|
|
1787
|
+
def escape_text(text)
|
|
1788
|
+
return text.gsub!(/['\\]/, '\\\\\&') || text
|
|
1789
|
+
end
|
|
1790
|
+
|
|
1791
|
+
def add_text(src, text)
|
|
1792
|
+
src << @func << "('" << escape_text(text) << "'); " unless text.empty?
|
|
1793
|
+
end
|
|
1794
|
+
|
|
1795
|
+
#--
|
|
1796
|
+
#def escaped_expr(code)
|
|
1797
|
+
# @escape ||= 'escape'
|
|
1798
|
+
# return "escape(#{code.strip})"
|
|
1799
|
+
#end
|
|
1800
|
+
#++
|
|
1801
|
+
|
|
1802
|
+
def add_expr_literal(src, code)
|
|
1803
|
+
src << @func << "(" << code.strip << "); "
|
|
1804
|
+
end
|
|
1805
|
+
|
|
1806
|
+
def add_expr_escaped(src, code)
|
|
1807
|
+
src << @func << "(" << escaped_expr(code) << "); "
|
|
1808
|
+
end
|
|
1809
|
+
|
|
1810
|
+
def add_expr_debug(src, code)
|
|
1811
|
+
code.strip!
|
|
1812
|
+
s = code.gsub(/\'/, "\\'")
|
|
1813
|
+
src << @func << "('*** debug: #{code}=', #{code}, \"\\n\");"
|
|
1814
|
+
end
|
|
1815
|
+
|
|
1816
|
+
def add_stmt(src, code)
|
|
1817
|
+
src << code
|
|
1818
|
+
end
|
|
1819
|
+
|
|
1820
|
+
def add_postamble(src)
|
|
1821
|
+
src << "\n" unless src[-1] == ?\n
|
|
1822
|
+
end
|
|
1823
|
+
|
|
1824
|
+
end
|
|
1825
|
+
|
|
1826
|
+
|
|
1827
|
+
class EscapedEperl < Eperl
|
|
1828
|
+
include EscapeEnhancer
|
|
1829
|
+
end
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
#class XmlEperl < Eperl
|
|
1833
|
+
# include EscapeEnhancer
|
|
1834
|
+
#end
|
|
1835
|
+
|
|
1836
|
+
|
|
1837
|
+
end
|
|
1838
|
+
#--end of require 'erubis/engine/eperl'
|
|
1839
|
+
#--begin of require 'erubis/engine/ejavascript'
|
|
1840
|
+
##
|
|
1841
|
+
## $Rev: 21 $
|
|
1842
|
+
## $Release: 2.0.0 $
|
|
1843
|
+
## copyright(c) 2006 kuwata-lab all rights reserved.
|
|
1844
|
+
##
|
|
1845
|
+
|
|
1846
|
+
#--already included require 'erubis/engine'
|
|
1847
|
+
#--already included require 'erubis/enhancer'
|
|
1848
|
+
|
|
1849
|
+
|
|
1850
|
+
module Erubis
|
|
1851
|
+
|
|
1852
|
+
|
|
1853
|
+
##
|
|
1854
|
+
## engine for JavaScript
|
|
1855
|
+
##
|
|
1856
|
+
class Ejavascript < Engine
|
|
1857
|
+
|
|
1858
|
+
def self.supported_properties() # :nodoc:
|
|
1859
|
+
list = super
|
|
1860
|
+
#list << [:indent, '', "indent spaces (ex. ' ')"]
|
|
1861
|
+
#list << [:buf, '_buf', "output buffer name"]
|
|
1862
|
+
return list
|
|
1863
|
+
end
|
|
1864
|
+
|
|
1865
|
+
def initialize(input, properties={})
|
|
1866
|
+
@indent = properties[:indent] || ''
|
|
1867
|
+
@buf = properties[:out] || '_buf'
|
|
1868
|
+
#@bufclass = properties[:outclass] || 'StringBuffer'
|
|
1869
|
+
super
|
|
1870
|
+
end
|
|
1871
|
+
|
|
1872
|
+
def add_preamble(src)
|
|
1873
|
+
src << "#{@indent}var #{@buf} = [];"
|
|
1874
|
+
end
|
|
1875
|
+
|
|
1876
|
+
def escape_text(text)
|
|
1877
|
+
@@table_ ||= { "\r"=>"\\r", "\n"=>"\\n\\\n", "\t"=>"\\t", '"'=>'\\"', "\\"=>"\\\\" }
|
|
1878
|
+
return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
|
|
1879
|
+
end
|
|
1880
|
+
|
|
1881
|
+
#--
|
|
1882
|
+
#def escaped_expr(code)
|
|
1883
|
+
# @escape ||= 'escape'
|
|
1884
|
+
# return "#{@escape}(#{code.strip})"
|
|
1885
|
+
#end
|
|
1886
|
+
#++
|
|
1887
|
+
|
|
1888
|
+
def add_indent(src, indent)
|
|
1889
|
+
src << (src.empty? || src[-1] == ?\n ? indent : ' ')
|
|
1890
|
+
end
|
|
1891
|
+
|
|
1892
|
+
def add_text(src, text)
|
|
1893
|
+
return if text.empty?
|
|
1894
|
+
add_indent(src, @indent)
|
|
1895
|
+
src << @buf << '.push("'
|
|
1896
|
+
s = escape_text(text)
|
|
1897
|
+
if s[-1] == ?\n
|
|
1898
|
+
s[-2, 2] = ''
|
|
1899
|
+
src << s << "\");\n"
|
|
1900
|
+
else
|
|
1901
|
+
src << s << "\");"
|
|
1902
|
+
end
|
|
1903
|
+
end
|
|
1904
|
+
|
|
1905
|
+
def add_stmt(src, code)
|
|
1906
|
+
src << code
|
|
1907
|
+
end
|
|
1908
|
+
|
|
1909
|
+
def add_expr_literal(src, code)
|
|
1910
|
+
add_indent(src, @indent)
|
|
1911
|
+
src << @buf << '.push(' << code.strip << ');'
|
|
1912
|
+
end
|
|
1913
|
+
|
|
1914
|
+
def add_expr_escaped(src, code)
|
|
1915
|
+
add_indent(src, @indent)
|
|
1916
|
+
src << @buf << '.push(' << escaped_expr(code) << ');'
|
|
1917
|
+
end
|
|
1918
|
+
|
|
1919
|
+
def add_expr_debug(src, code)
|
|
1920
|
+
add_indent(src, @indent)
|
|
1921
|
+
code.strip!
|
|
1922
|
+
src << "alert(\"*** debug: #{code}=\"+(#{code}));"
|
|
1923
|
+
end
|
|
1924
|
+
|
|
1925
|
+
def add_postamble(src)
|
|
1926
|
+
src << "\n" if src[-1] == ?;
|
|
1927
|
+
src << @indent << 'document.write(' << @buf << ".join(\"\"));\n"
|
|
1928
|
+
end
|
|
1929
|
+
|
|
1930
|
+
end
|
|
1931
|
+
|
|
1932
|
+
|
|
1933
|
+
class EscapedEjavascript < Ejavascript
|
|
1934
|
+
include EscapeEnhancer
|
|
1935
|
+
end
|
|
1936
|
+
|
|
1937
|
+
|
|
1938
|
+
#class XmlEjavascript < Ejavascript
|
|
1939
|
+
# include EscapeEnhancer
|
|
1940
|
+
#end
|
|
1941
|
+
|
|
1942
|
+
|
|
1943
|
+
end
|
|
1944
|
+
#--end of require 'erubis/engine/ejavascript'
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
module Erubis
|
|
1948
|
+
|
|
1949
|
+
|
|
1950
|
+
Ejs = Ejavascript
|
|
1951
|
+
EscapedEjs = EscapedEjavascript
|
|
1952
|
+
|
|
1953
|
+
|
|
1954
|
+
class CommandOptionError < ErubisError
|
|
1955
|
+
end
|
|
1956
|
+
|
|
1957
|
+
|
|
1958
|
+
##
|
|
1959
|
+
## main class of command
|
|
1960
|
+
##
|
|
1961
|
+
## ex.
|
|
1962
|
+
## Main.main(ARGV)
|
|
1963
|
+
##
|
|
1964
|
+
class Main
|
|
1965
|
+
|
|
1966
|
+
def self.main(argv=ARGV)
|
|
1967
|
+
status = 0
|
|
1968
|
+
begin
|
|
1969
|
+
Main.new.execute(ARGV)
|
|
1970
|
+
rescue CommandOptionError => ex
|
|
1971
|
+
$stderr.puts ex.message
|
|
1972
|
+
status = 1
|
|
1973
|
+
end
|
|
1974
|
+
exit(status)
|
|
1975
|
+
end
|
|
1976
|
+
|
|
1977
|
+
def initialize
|
|
1978
|
+
@single_options = "hvxTtSbeB"
|
|
1979
|
+
@arg_options = "pcrfKIlaE"
|
|
1980
|
+
@option_names = {
|
|
1981
|
+
?h => :help,
|
|
1982
|
+
?v => :version,
|
|
1983
|
+
?x => :source,
|
|
1984
|
+
?T => :notrim,
|
|
1985
|
+
?t => :untabify,
|
|
1986
|
+
?S => :intern,
|
|
1987
|
+
?b => :bodyonly,
|
|
1988
|
+
?B => :binding,
|
|
1989
|
+
?p => :pattern,
|
|
1990
|
+
?c => :class,
|
|
1991
|
+
?e => :escape,
|
|
1992
|
+
?r => :requires,
|
|
1993
|
+
?f => :yamlfiles,
|
|
1994
|
+
?K => :kanji,
|
|
1995
|
+
?I => :includes,
|
|
1996
|
+
?l => :lang,
|
|
1997
|
+
?a => :action,
|
|
1998
|
+
?E => :enhancers,
|
|
1999
|
+
}
|
|
2000
|
+
assert unless @single_options.length + @arg_options.length == @option_names.length
|
|
2001
|
+
(@single_options + @arg_options).each_byte do |ch|
|
|
2002
|
+
assert unless @option_names.key?(ch)
|
|
2003
|
+
end
|
|
2004
|
+
end
|
|
2005
|
+
|
|
2006
|
+
|
|
2007
|
+
def execute(argv=ARGV)
|
|
2008
|
+
## parse command-line options
|
|
2009
|
+
options, properties = parse_argv(argv, @single_options, @arg_options)
|
|
2010
|
+
filenames = argv
|
|
2011
|
+
options[?h] = true if properties[:help]
|
|
2012
|
+
opts = Object.new
|
|
2013
|
+
arr = @option_names.collect { |ch, name| "def #{name}; @#{name}; end\n" }
|
|
2014
|
+
opts.instance_eval arr.join
|
|
2015
|
+
options.each do |ch, val|
|
|
2016
|
+
name = @option_names[ch]
|
|
2017
|
+
opts.instance_variable_set("@#{name}", val)
|
|
2018
|
+
end
|
|
2019
|
+
|
|
2020
|
+
## help, version, enhancer list
|
|
2021
|
+
if opts.help || opts.version
|
|
2022
|
+
puts version() if opts.version
|
|
2023
|
+
puts usage() if opts.help
|
|
2024
|
+
puts show_properties() if opts.help
|
|
2025
|
+
puts show_enhancers() if opts.help
|
|
2026
|
+
return
|
|
2027
|
+
end
|
|
2028
|
+
|
|
2029
|
+
## include path
|
|
2030
|
+
opts.includes.split(/,/).each do |path|
|
|
2031
|
+
$: << path
|
|
2032
|
+
end if opts.includes
|
|
2033
|
+
|
|
2034
|
+
## require library
|
|
2035
|
+
opts.requires.split(/,/).each do |library|
|
|
2036
|
+
require library
|
|
2037
|
+
end if opts.requires
|
|
2038
|
+
|
|
2039
|
+
## action
|
|
2040
|
+
action = opts.action
|
|
2041
|
+
action ||= 'compile' if opts.source
|
|
2042
|
+
|
|
2043
|
+
## lang
|
|
2044
|
+
lang = opts.lang || 'ruby'
|
|
2045
|
+
action ||= 'compile' if opts.lang
|
|
2046
|
+
|
|
2047
|
+
## class name of Eruby
|
|
2048
|
+
classname = opts.class
|
|
2049
|
+
klass = get_classobj(classname, lang)
|
|
2050
|
+
|
|
2051
|
+
## kanji code
|
|
2052
|
+
$KCODE = opts.kanji if opts.kanji
|
|
2053
|
+
|
|
2054
|
+
## read context values from yaml file
|
|
2055
|
+
yamlfiles = opts.yamlfiles
|
|
2056
|
+
context = load_yamlfiles(yamlfiles, opts)
|
|
2057
|
+
|
|
2058
|
+
## properties for engine
|
|
2059
|
+
properties[:pattern] = opts.pattern if opts.pattern
|
|
2060
|
+
properties[:trim] = false if opts.notrim
|
|
2061
|
+
properties[:preamble] = properties[:postamble] = false if opts.bodyonly
|
|
2062
|
+
|
|
2063
|
+
## create engine and extend enhancers
|
|
2064
|
+
engine = klass.new(nil, properties)
|
|
2065
|
+
enhancers = get_enhancers(opts.enhancers)
|
|
2066
|
+
enhancers.push(Erubis::EscapeEnhancer) if opts.escape
|
|
2067
|
+
enhancers.each do |enhancer|
|
|
2068
|
+
engine.extend(enhancer)
|
|
2069
|
+
engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
|
|
2070
|
+
end
|
|
2071
|
+
|
|
2072
|
+
## compile and execute
|
|
2073
|
+
val = nil
|
|
2074
|
+
if filenames && !filenames.empty?
|
|
2075
|
+
filenames.each do |filename|
|
|
2076
|
+
test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
|
|
2077
|
+
engine.filename = filename
|
|
2078
|
+
engine.compile!(File.read(filename))
|
|
2079
|
+
print val if val = do_action(action, engine, context, opts)
|
|
2080
|
+
end
|
|
2081
|
+
else
|
|
2082
|
+
engine.filename = '(stdin)'
|
|
2083
|
+
engine.compile!($stdin.read())
|
|
2084
|
+
print val if val = do_action(action, engine, context, opts)
|
|
2085
|
+
end
|
|
2086
|
+
|
|
2087
|
+
end
|
|
2088
|
+
|
|
2089
|
+
private
|
|
2090
|
+
|
|
2091
|
+
def do_action(action, engine, context, opts)
|
|
2092
|
+
case action
|
|
2093
|
+
when 'compile'
|
|
2094
|
+
s = engine.src
|
|
2095
|
+
when nil, 'exec', 'execute'
|
|
2096
|
+
s = opts.binding ? engine.result(context) : engine.evaluate(context)
|
|
2097
|
+
else
|
|
2098
|
+
raise "*** internal error"
|
|
2099
|
+
end
|
|
2100
|
+
return s
|
|
2101
|
+
end
|
|
2102
|
+
|
|
2103
|
+
def usage
|
|
2104
|
+
command = File.basename($0)
|
|
2105
|
+
s = <<'END'
|
|
2106
|
+
erubis - embedded program compiler for multi-language
|
|
2107
|
+
Usage: #{command} [..options..] [file ...]
|
|
2108
|
+
-h, --help : help
|
|
2109
|
+
-v : version
|
|
2110
|
+
-x : compiled code
|
|
2111
|
+
-T : don't trim spaces around '<% %>'
|
|
2112
|
+
-b : body only (no preamble nor postamble)
|
|
2113
|
+
-e : escape (equal to '--E Escape')
|
|
2114
|
+
-p pattern : embedded pattern (default '<% %>')
|
|
2115
|
+
-l lang : compile but no execute (ruby/php/c/java/scheme/perl/js)
|
|
2116
|
+
-E enhancer,... : enhancer name (Escape, PercentLine, BiPattern, ...)
|
|
2117
|
+
-I path : library include path
|
|
2118
|
+
-K kanji : kanji code (euc/sjis/utf8) (default none)
|
|
2119
|
+
-f file.yaml : YAML file for context values (read stdin if filename is '-')
|
|
2120
|
+
-t : expand tab character in YAML file
|
|
2121
|
+
-S : convert mapping key from string to symbol in YAML file
|
|
2122
|
+
-B : invoke 'result(binding)' instead of 'evaluate(context)'
|
|
2123
|
+
|
|
2124
|
+
END
|
|
2125
|
+
# -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
|
|
2126
|
+
# -r library : require library
|
|
2127
|
+
# -a : action (compile/execute)
|
|
2128
|
+
return s
|
|
2129
|
+
end
|
|
2130
|
+
|
|
2131
|
+
def show_properties
|
|
2132
|
+
s = "supported properties:\n"
|
|
2133
|
+
%w[(common) ruby php c java scheme perl javascript].each do |lang|
|
|
2134
|
+
list = Erubis::Engine.supported_properties
|
|
2135
|
+
if lang != '(common)'
|
|
2136
|
+
klass = Erubis.const_get("E#{lang}")
|
|
2137
|
+
list = klass.supported_properties - list
|
|
2138
|
+
end
|
|
2139
|
+
s << " * #{lang}\n"
|
|
2140
|
+
list.each do |name, default_val, desc|
|
|
2141
|
+
s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc])
|
|
2142
|
+
end
|
|
2143
|
+
end
|
|
2144
|
+
s << "\n"
|
|
2145
|
+
return s
|
|
2146
|
+
end
|
|
2147
|
+
|
|
2148
|
+
def show_enhancers
|
|
2149
|
+
s = "enhancers:\n"
|
|
2150
|
+
list = []
|
|
2151
|
+
ObjectSpace.each_object(Module) do |m| list << m end
|
|
2152
|
+
list.sort_by { |m| m.name }.each do |m|
|
|
2153
|
+
next unless m.name =~ /\AErubis::(.*)Enhancer\z/
|
|
2154
|
+
name = $1
|
|
2155
|
+
desc = m.desc
|
|
2156
|
+
s << (" %-13s : %s\n" % [name, desc])
|
|
2157
|
+
end
|
|
2158
|
+
return s
|
|
2159
|
+
end
|
|
2160
|
+
|
|
2161
|
+
def version
|
|
2162
|
+
release = ('$Release: 2.0.0 $' =~ /([.\d]+)/) && $1
|
|
2163
|
+
return release
|
|
2164
|
+
end
|
|
2165
|
+
|
|
2166
|
+
def parse_argv(argv, arg_none='', arg_required='', arg_optional='')
|
|
2167
|
+
options = {}
|
|
2168
|
+
context = {}
|
|
2169
|
+
while argv[0] && argv[0][0] == ?-
|
|
2170
|
+
optstr = argv.shift
|
|
2171
|
+
optstr = optstr[1, optstr.length-1]
|
|
2172
|
+
#
|
|
2173
|
+
if optstr[0] == ?- # context
|
|
2174
|
+
unless optstr =~ /\A\-([-\w]+)(?:=(.*))?/
|
|
2175
|
+
raise CommandOptionError.new("-#{optstr}: invalid context value.")
|
|
2176
|
+
end
|
|
2177
|
+
name = $1; value = $2
|
|
2178
|
+
name = name.gsub(/-/, '_').intern
|
|
2179
|
+
#value = value.nil? ? true : YAML.load(value) # error, why?
|
|
2180
|
+
value = value.nil? ? true : YAML.load("---\n#{value}\n")
|
|
2181
|
+
context[name] = value
|
|
2182
|
+
#
|
|
2183
|
+
else # options
|
|
2184
|
+
while optstr && !optstr.empty?
|
|
2185
|
+
optchar = optstr[0]
|
|
2186
|
+
optstr[0,1] = ""
|
|
2187
|
+
if arg_none.include?(optchar)
|
|
2188
|
+
options[optchar] = true
|
|
2189
|
+
elsif arg_required.include?(optchar)
|
|
2190
|
+
arg = optstr.empty? ? argv.shift : optstr
|
|
2191
|
+
unless arg
|
|
2192
|
+
mesg = "-#{optchar.chr}: #{@option_args[optchar]} required."
|
|
2193
|
+
raise CommandOptionError.new(mesg)
|
|
2194
|
+
end
|
|
2195
|
+
options[optchar] = arg
|
|
2196
|
+
optstr = nil
|
|
2197
|
+
elsif arg_optional.include?(optchar)
|
|
2198
|
+
arg = optstr.empty? ? true : optstr
|
|
2199
|
+
options[optchar] = arg
|
|
2200
|
+
optstr = nil
|
|
2201
|
+
else
|
|
2202
|
+
raise CommandOptionError.new("-#{optchar.chr}: unknown option.")
|
|
2203
|
+
end
|
|
2204
|
+
end
|
|
2205
|
+
end
|
|
2206
|
+
#
|
|
2207
|
+
end # end of while
|
|
2208
|
+
|
|
2209
|
+
return options, context
|
|
2210
|
+
end
|
|
2211
|
+
|
|
2212
|
+
def untabify(text, width=8)
|
|
2213
|
+
sb = ''
|
|
2214
|
+
text.scan(/(.*?)\t/m) do |s, |
|
|
2215
|
+
len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
|
|
2216
|
+
sb << s << (" " * (width - len % width))
|
|
2217
|
+
end
|
|
2218
|
+
return $' ? (sb << $') : text
|
|
2219
|
+
end
|
|
2220
|
+
|
|
2221
|
+
def get_classobj(classname, lang)
|
|
2222
|
+
unless classname
|
|
2223
|
+
classname = lang =~ /\Axml(.*)/ ? "EscapedE#{$1}" : "E#{lang}"
|
|
2224
|
+
end
|
|
2225
|
+
begin
|
|
2226
|
+
klass = Erubis.const_get(classname)
|
|
2227
|
+
rescue NameError
|
|
2228
|
+
klass = nil
|
|
2229
|
+
end
|
|
2230
|
+
unless klass
|
|
2231
|
+
if lang
|
|
2232
|
+
msg = "-l #{lang}: invalid language name (class Erubis::#{classname} not found)."
|
|
2233
|
+
else
|
|
2234
|
+
msg = "-c #{classname}: invalid class name."
|
|
2235
|
+
end
|
|
2236
|
+
raise CommandOptionError.new(msg)
|
|
2237
|
+
end
|
|
2238
|
+
return klass
|
|
2239
|
+
end
|
|
2240
|
+
|
|
2241
|
+
def get_enhancers(enhancer_names)
|
|
2242
|
+
return [] unless enhancer_names
|
|
2243
|
+
enhancers = []
|
|
2244
|
+
shortname = nil
|
|
2245
|
+
begin
|
|
2246
|
+
enhancer_names.split(/,/).each do |shortname|
|
|
2247
|
+
enhancers << Erubis.const_get("#{shortname}Enhancer")
|
|
2248
|
+
end
|
|
2249
|
+
rescue NameError
|
|
2250
|
+
raise CommandOptionError.new("#{shortname}: no such Enhancer (try '-E' to show all enhancers).")
|
|
2251
|
+
end
|
|
2252
|
+
return enhancers
|
|
2253
|
+
end
|
|
2254
|
+
|
|
2255
|
+
def load_yamlfiles(yamlfiles, opts)
|
|
2256
|
+
hash = {}
|
|
2257
|
+
return hash unless yamlfiles
|
|
2258
|
+
yamlfiles.split(/,/).each do |yamlfile|
|
|
2259
|
+
if yamlfile == '-'
|
|
2260
|
+
str = $stdin.read()
|
|
2261
|
+
else
|
|
2262
|
+
test(?f, yamlfile) or raise CommandOptionError.new("#{yamlfile}: file not found.")
|
|
2263
|
+
str = File.read(yamlfile)
|
|
2264
|
+
end
|
|
2265
|
+
str = yamlfile == '-' ? $stdin.read() : File.read(yamlfile)
|
|
2266
|
+
str = untabify(str) if opts.untabify
|
|
2267
|
+
ydoc = YAML.load(str)
|
|
2268
|
+
unless ydoc.is_a?(Hash)
|
|
2269
|
+
raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
|
|
2270
|
+
end
|
|
2271
|
+
convert_mapping_key_from_string_to_symbol(ydoc) if opts.intern
|
|
2272
|
+
hash.update(ydoc)
|
|
2273
|
+
end
|
|
2274
|
+
context = hash
|
|
2275
|
+
return context
|
|
2276
|
+
end
|
|
2277
|
+
|
|
2278
|
+
def convert_mapping_key_from_string_to_symbol(ydoc)
|
|
2279
|
+
if ydoc.is_a?(Hash)
|
|
2280
|
+
ydoc.each do |key, val|
|
|
2281
|
+
ydoc[key.intern] = ydoc.delete(key) if key.is_a?(String)
|
|
2282
|
+
convert_mapping_key_from_string_to_symbol(val)
|
|
2283
|
+
end
|
|
2284
|
+
elsif ydoc.is_a?(Array)
|
|
2285
|
+
ydoc.each do |val|
|
|
2286
|
+
convert_mapping_key_from_string_to_symbol(val)
|
|
2287
|
+
end
|
|
2288
|
+
end
|
|
2289
|
+
return ydoc
|
|
2290
|
+
end
|
|
2291
|
+
|
|
2292
|
+
end
|
|
2293
|
+
|
|
2294
|
+
end
|
|
2295
|
+
#--end of require 'erubis/main'
|
|
2296
|
+
|
|
2297
|
+
Erubis::Main.main(ARGV)
|