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.
Files changed (145) hide show
  1. data/ChangeLog +150 -2
  2. data/LGPL +504 -0
  3. data/README.txt +14 -8
  4. data/benchmark/erubybench.rb +1 -1
  5. data/benchmark/erubybench.rhtml +3 -3
  6. data/bin/erubis +1 -1
  7. data/bin/notext +154 -0
  8. data/contrib/erubis +1036 -374
  9. data/contrib/inline-require +5 -3
  10. data/doc-api/classes/Erubis.html +43 -1
  11. data/doc-api/classes/Erubis/ArrayBufferEnhancer.html +14 -14
  12. data/doc-api/classes/Erubis/ArrayEnhancer.html +14 -14
  13. data/doc-api/classes/Erubis/Basic.html +112 -0
  14. data/doc-api/classes/Erubis/Basic/Converter.html +318 -0
  15. data/doc-api/classes/Erubis/Basic/Engine.html +130 -0
  16. data/doc-api/classes/Erubis/BiPatternEnhancer.html +14 -14
  17. data/doc-api/classes/Erubis/CGenerator.html +386 -0
  18. data/doc-api/classes/Erubis/Context.html +31 -32
  19. data/doc-api/classes/Erubis/Converter.html +231 -0
  20. data/doc-api/classes/Erubis/Ec.html +9 -283
  21. data/doc-api/classes/Erubis/Ejava.html +9 -274
  22. data/doc-api/classes/Erubis/Ejavascript.html +9 -298
  23. data/doc-api/classes/Erubis/Engine.html +68 -508
  24. data/doc-api/classes/Erubis/Eperl.html +9 -259
  25. data/doc-api/classes/Erubis/Ephp.html +9 -239
  26. data/doc-api/classes/Erubis/ErubisError.html +2 -2
  27. data/doc-api/classes/Erubis/Eruby.html +4 -187
  28. data/doc-api/classes/Erubis/EscapeEnhancer.html +9 -11
  29. data/doc-api/classes/Erubis/Escheme.html +9 -272
  30. data/doc-api/classes/Erubis/Evaluator.html +212 -0
  31. data/doc-api/classes/Erubis/Generator.html +410 -0
  32. data/doc-api/classes/Erubis/HeaderFooterEnhancer.html +16 -16
  33. data/doc-api/classes/Erubis/Helper.html +112 -0
  34. data/doc-api/classes/Erubis/Helper/CachedRailsTemplate.html +198 -0
  35. data/doc-api/classes/Erubis/Helper/RailsTemplate.html +366 -0
  36. data/doc-api/classes/Erubis/JavaGenerator.html +359 -0
  37. data/doc-api/classes/Erubis/JavascriptGenerator.html +381 -0
  38. data/doc-api/classes/Erubis/Main.html +27 -25
  39. data/doc-api/classes/Erubis/NoCodeEnhancer.html +249 -0
  40. data/doc-api/classes/Erubis/NoCodeEruby.html +120 -0
  41. data/doc-api/classes/Erubis/NoTextEnhancer.html +8 -8
  42. data/doc-api/classes/Erubis/NotSupportedError.html +119 -0
  43. data/doc-api/classes/Erubis/OptimizedEruby.html +22 -304
  44. data/doc-api/classes/Erubis/OptimizedGenerator.html +439 -0
  45. data/doc-api/classes/Erubis/OptimizedXmlEruby.html +7 -7
  46. data/doc-api/classes/Erubis/PI.html +124 -0
  47. data/doc-api/classes/Erubis/PI/Converter.html +318 -0
  48. data/doc-api/classes/Erubis/PI/Ec.html +166 -0
  49. data/doc-api/classes/Erubis/PI/Ejava.html +166 -0
  50. data/doc-api/classes/Erubis/PI/Ejavascript.html +166 -0
  51. data/doc-api/classes/Erubis/PI/Engine.html +122 -0
  52. data/doc-api/classes/Erubis/PI/Eperl.html +166 -0
  53. data/doc-api/classes/Erubis/PI/Ephp.html +166 -0
  54. data/doc-api/classes/Erubis/PI/Eruby.html +155 -0
  55. data/doc-api/classes/Erubis/PI/Escheme.html +166 -0
  56. data/doc-api/classes/Erubis/PI/TinyEruby.html +305 -0
  57. data/doc-api/classes/Erubis/PercentLineEnhancer.html +7 -7
  58. data/doc-api/classes/Erubis/PerlGenerator.html +344 -0
  59. data/doc-api/classes/Erubis/PhpGenerator.html +350 -0
  60. data/doc-api/classes/Erubis/PrintEnabledEnhancer.html +24 -24
  61. data/doc-api/classes/Erubis/PrintOutEnhancer.html +35 -35
  62. data/doc-api/classes/Erubis/RubyEvaluator.html +190 -0
  63. data/doc-api/classes/Erubis/RubyGenerator.html +327 -0
  64. data/doc-api/classes/Erubis/SchemeGenerator.html +382 -0
  65. data/doc-api/classes/Erubis/SimplifyEnhancer.html +17 -13
  66. data/doc-api/classes/Erubis/StdoutEnhancer.html +14 -14
  67. data/doc-api/classes/Erubis/StringBufferEnhancer.html +14 -14
  68. data/doc-api/classes/Erubis/TinyEruby.html +45 -40
  69. data/doc-api/classes/Erubis/XmlHelper.html +14 -14
  70. data/doc-api/created.rid +1 -1
  71. data/doc-api/files/__/README_txt.html +27 -9
  72. data/doc-api/files/erubis/context_rb.html +107 -0
  73. data/doc-api/files/erubis/converter_rb.html +114 -0
  74. data/doc-api/files/erubis/engine/ec_rb.html +2 -2
  75. data/doc-api/files/erubis/engine/ejava_rb.html +2 -2
  76. data/doc-api/files/erubis/engine/ejavascript_rb.html +2 -2
  77. data/doc-api/files/erubis/engine/enhanced_rb.html +2 -2
  78. data/doc-api/files/erubis/engine/eperl_rb.html +2 -2
  79. data/doc-api/files/erubis/engine/ephp_rb.html +2 -2
  80. data/doc-api/files/erubis/engine/eruby_rb.html +3 -2
  81. data/doc-api/files/erubis/engine/escheme_rb.html +2 -2
  82. data/doc-api/files/erubis/engine/optimized_rb.html +2 -2
  83. data/doc-api/files/erubis/engine_rb.html +6 -3
  84. data/doc-api/files/erubis/enhancer_rb.html +2 -9
  85. data/doc-api/files/erubis/error_rb.html +107 -0
  86. data/doc-api/files/erubis/evaluator_rb.html +115 -0
  87. data/doc-api/files/erubis/generator_rb.html +114 -0
  88. data/doc-api/files/erubis/helper/rails_rb.html +140 -0
  89. data/doc-api/files/erubis/helper_rb.html +1 -1
  90. data/doc-api/files/erubis/local-setting_rb.html +1 -1
  91. data/doc-api/files/erubis/main_rb.html +2 -2
  92. data/doc-api/files/erubis/tiny_rb.html +2 -2
  93. data/doc-api/files/erubis_rb.html +2 -2
  94. data/doc-api/fr_class_index.html +32 -0
  95. data/doc-api/fr_file_index.html +6 -0
  96. data/doc-api/fr_method_index.html +178 -136
  97. data/doc/users-guide.html +538 -199
  98. data/examples/{Makefile → basic/Makefile} +11 -11
  99. data/examples/basic/example.ec +42 -0
  100. data/examples/{example.ejava → basic/example.ejava} +5 -1
  101. data/examples/{example.ejavascript → basic/example.ejs} +0 -0
  102. data/examples/{example.eperl → basic/example.eperl} +2 -2
  103. data/examples/{example.ephp → basic/example.ephp} +0 -0
  104. data/examples/{example.eruby → basic/example.eruby} +0 -0
  105. data/examples/{example.escheme → basic/example.escheme} +0 -0
  106. data/examples/pi/Makefile +54 -0
  107. data/examples/pi/example.ec +42 -0
  108. data/examples/pi/example.ejava +45 -0
  109. data/examples/pi/example.ejs +16 -0
  110. data/examples/pi/example.eperl +16 -0
  111. data/examples/pi/example.ephp +17 -0
  112. data/examples/pi/example.eruby +15 -0
  113. data/examples/pi/example.escheme +26 -0
  114. data/lib/erubis.rb +15 -8
  115. data/lib/erubis/context.rb +54 -0
  116. data/lib/erubis/converter.rb +307 -0
  117. data/lib/erubis/engine.rb +57 -227
  118. data/lib/erubis/engine/ec.rb +31 -20
  119. data/lib/erubis/engine/ejava.rb +33 -21
  120. data/lib/erubis/engine/ejavascript.rb +30 -18
  121. data/lib/erubis/engine/enhanced.rb +7 -2
  122. data/lib/erubis/engine/eperl.rb +33 -19
  123. data/lib/erubis/engine/ephp.rb +32 -14
  124. data/lib/erubis/engine/eruby.rb +34 -7
  125. data/lib/erubis/engine/escheme.rb +34 -15
  126. data/lib/erubis/engine/optimized.rb +25 -11
  127. data/lib/erubis/enhancer.rb +53 -19
  128. data/lib/erubis/error.rb +24 -0
  129. data/lib/erubis/evaluator.rb +71 -0
  130. data/lib/erubis/generator.rb +83 -0
  131. data/lib/erubis/helper.rb +1 -1
  132. data/lib/erubis/helper/rails.rb +159 -0
  133. data/lib/erubis/local-setting.rb +1 -1
  134. data/lib/erubis/main.rb +87 -46
  135. data/lib/erubis/tiny.rb +81 -7
  136. data/test/assert-text-equal.rb +1 -1
  137. data/test/test-engines.rb +8 -9
  138. data/test/test-erubis.rb +196 -18
  139. data/test/{test-bin.rb → test-main.rb} +123 -21
  140. data/test/test-notext.rb +27 -0
  141. data/test/test.rb +5 -3
  142. data/test/testutil.rb +25 -36
  143. metadata +75 -13
  144. data/COPYING +0 -340
  145. data/examples/example.ec +0 -24
data/README.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  = README
2
2
 
3
- release:: $Release: 2.0.1 $
3
+ release:: $Release: 2.1.0 $
4
4
  copyright:: copyright(c) 2006 kuwata-lab all rights reserved.
5
5
 
6
6
 
@@ -8,13 +8,16 @@ copyright:: copyright(c) 2006 kuwata-lab all rights reserved.
8
8
  == About Erubis
9
9
 
10
10
  Erubis is an implementation of eRuby. It has the following features.
11
- * Very fast (about three times faster than ERB and almost as fast as eruby)
12
- * Auto trimming spaces around '<% %>'
13
- * Auto escape (sanitizing)
14
- * Changeable embedded pattern (default '<% %>')
15
- * Context object available
16
- * Easy to expand and customize in subclass
11
+ * Very fast, almost three times faster than ERB and even faster than eruby
17
12
  * Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript)
13
+ * Auto escaping support
14
+ * Auto trimming spaces around '<% %>'
15
+ * Embedded pattern changeable (default '<% %>')
16
+ * Enable to handle Processing Instructions (PI) as embedded pattern (ex. '<?rb ... ?>')
17
+ * Context object available and easy to combine eRuby template with YAML datafile
18
+ * Print statement available
19
+ * Easy to extend and customize in subclass
20
+ * Ruby on Rails support
18
21
 
19
22
  Erubis is implemented in pure Ruby. It requires Ruby 1.8 or higher.
20
23
 
@@ -59,6 +62,8 @@ If you are exploring Eruby, see the following class at first.
59
62
  base class of Eruby, Ephp, Ejava, and so on.
60
63
  * Erubis::Eruby (erubis/engine/eruby.rb) --
61
64
  engine class for eRuby.
65
+ * Erubis::Converter (erubis/converter.rb) --
66
+ convert eRuby script into Ruby code.
62
67
 
63
68
 
64
69
 
@@ -71,8 +76,9 @@ Try 'ruby erubybenchmark.rb' in benchmark directory.
71
76
 
72
77
  == License
73
78
 
74
- GPL ver.2
79
+ LGPL version 2.1
75
80
 
81
+ If you need looser license, please suggest me.
76
82
 
77
83
 
78
84
  == Author
@@ -1,6 +1,6 @@
1
1
  ##
2
2
  ## $Rev: 21 $
3
- ## $Release: 2.0.1 $
3
+ ## $Release: 2.1.0 $
4
4
  ## copyright(c) 2006 kuwata-lab all rights reserved.
5
5
  ##
6
6
 
@@ -40,17 +40,17 @@ thead {
40
40
  </tr>
41
41
  </thead>
42
42
  <tbody>
43
- <% data.each_with_index do |h, i| %>
43
+ <% data.each_with_index do |hash, i| %>
44
44
  <% n = i + 1 %>
45
45
  <tr class="<%= n % 2 == 0 ? 'even' : 'odd' %>">
46
46
  <td style="text-align: center">
47
47
  <span><%= n %></span>
48
48
  </td>
49
49
  <td>
50
- <a href="/stock/<%= h[:code] %>"><%= h[:code] %></a>
50
+ <a href="/stock/<%= hash[:code] %>"><%= hash[:code] %></a>
51
51
  </td>
52
52
  <td>
53
- <a href="<%= h[:url] %>"><%= h[:name] %></a>
53
+ <a href="<%= hash[:url] %>"><%= hash[:name] %></a>
54
54
  </td>
55
55
  </tr>
56
56
  <% end %>
data/bin/erubis CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ###
4
4
  ### $Rev: 10 $
5
- ### $Release: 2.0.1 $
5
+ ### $Release: 2.1.0 $
6
6
  ### copyright(c) 2006 kuwata-lab all rights reserved.
7
7
  ###
8
8
 
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ###
4
+ ### notext - retrieve embedded code from eRuby, PHP, and so on
5
+ ###
6
+ ### $Rev$
7
+ ### $Release: 2.1.0 $
8
+ ### copyright(c) 2006 kuwata-lab all rights reserved.
9
+ ###
10
+
11
+ require 'erubis'
12
+ require 'erubis/engine/eruby'
13
+ require 'erubis/engine/ephp'
14
+ require 'erubis/engine/ec'
15
+ require 'erubis/engine/ejava'
16
+ require 'erubis/engine/escheme'
17
+ require 'erubis/engine/eperl'
18
+ require 'erubis/engine/ejavascript'
19
+
20
+
21
+ def help()
22
+ command = File.basename($0)
23
+ s = <<END
24
+ #{command} - retrieve embedded code from eRuby, PHP, and so on.
25
+ Usage: #{command} [-hvncu] [-l lang] [-p pattern] file.php ...
26
+ -h : help
27
+ -v : version
28
+ -n : show line number
29
+ -c : compact mode (delete empty lines)
30
+ -u : uniq mode (compress repeated empty lines to a line)
31
+ -l lang : ruby/php/perl/c/java/scheme/javascript
32
+ -p pattern : embedded pattern (default '<% %>' or '<\\?(?:php|=|\\s) \\?>')
33
+ END
34
+ return s
35
+ end
36
+
37
+
38
+ ## Engine classes which include NoTextEnhancer
39
+ klass_table = {}
40
+ lang_list = %w[ruby php c java scheme perl javascript]
41
+ lang_list.each do |lang|
42
+ eval <<-END
43
+ class NoTextE#{lang} < Erubis::E#{lang}
44
+ include Erubis::NoTextEnhancer
45
+ end
46
+ END
47
+ klass_table[lang] = Object.const_get("NoTextE#{lang}")
48
+ end
49
+
50
+
51
+ ## parse command-line options
52
+ options = {}
53
+ properties = {}
54
+ while !ARGV.empty? && ARGV[0][0] == ?-
55
+ optstr = ARGV.shift
56
+ optstr = optstr.sub(/^-/, '')
57
+ while !optstr.empty?
58
+ optch = optstr[0]
59
+ optstr = optstr[1, optstr.length-1]
60
+ case optch
61
+ when ?h, ?v, ?n, ?c, ?u # help, version, linenum, compact, uniq
62
+ options[optch] = true
63
+ when ?l, ?p # lang, pattern
64
+ arg = !optstr.empty? ? optstr : ARGV.shift
65
+ unless arg
66
+ argnames = { ?l => 'lang name', ?p => 'pattern' }
67
+ $stderr.puts "-#{optch.chr}: #{argnames[optch]} required."
68
+ exit(1)
69
+ end
70
+ options[optch] = arg
71
+ else
72
+ $stderr.puts "-#{optch.chr}: unknown option."
73
+ exit(1)
74
+ end
75
+ end
76
+ end
77
+
78
+ opt_help = options[?h]
79
+ opt_version = options[?v]
80
+ opt_linenum = options[?n]
81
+ opt_compact = options[?c]
82
+ opt_unique = options[?u]
83
+ opt_pattern = options[?p]
84
+ opt_lang = options[?l]
85
+
86
+ if opt_lang
87
+ unless lang_list.include?(opt_lang)
88
+ $stderr.puts "-l #{opt_lang}: not supported."
89
+ exit(1)
90
+ end
91
+ end
92
+
93
+
94
+ ## help message
95
+ if opt_help || opt_version
96
+ version = ('$Release: 2.1.0 $' =~ /[\.\d]+/) && $&
97
+ puts version if opt_version
98
+ puts help() if opt_help
99
+ exit(0)
100
+ end
101
+
102
+
103
+ ## determine pattern
104
+ lang = opt_lang
105
+ unless lang
106
+ filename = ARGV[0]
107
+ if filename && filename =~ /\.(\w+)$/
108
+ case suffix = $1
109
+ when 'php', 'php5', 'inc' ; lang = 'php'
110
+ when 'ec' ; lang = 'c'
111
+ when 'ejava' ; lang = 'java'
112
+ when 'escheme', 'escm' ; lang = 'scheme'
113
+ when 'eperl' ; lang = 'perl'
114
+ when 'js', 'javascript' ; lang = 'javascript'
115
+ else ; lang = 'ruby'
116
+ end
117
+ else
118
+ lang = 'ruby'
119
+ end
120
+ end
121
+
122
+
123
+ ## determine pattern
124
+ if opt_pattern
125
+ pattern = opt_pattern
126
+ else
127
+ case lang
128
+ when 'php' ; pattern = '<\?(?:php\b|(?==)|(?=\s)) \?>'
129
+ when 'perl' ; pattern = '<\?(?=\s|=) !>'
130
+ else ; pattern = '<% %>'
131
+ end
132
+ end
133
+
134
+
135
+ ## read input and create engine
136
+ klass = klass_table[lang]
137
+ input = ARGF.read()
138
+ engine = klass.new(input, :pattern=>pattern, :trim=>false)
139
+
140
+
141
+ ## print embedded code
142
+ n = 0
143
+ prev_empty = false
144
+ engine.src.each_line do |line|
145
+ n += 1
146
+ if line =~ /^\s*$/
147
+ next if opt_compact || (opt_unique && prev_empty)
148
+ print opt_linenum && !opt_unique ? ("%3d: \n" % n) : "\n"
149
+ prev_empty = true
150
+ else
151
+ print opt_linenum ? ("%3d: %s" % [n, line]) : line
152
+ prev_empty = false
153
+ end
154
+ end
@@ -2,22 +2,22 @@
2
2
 
3
3
  ###
4
4
  ### $Rev: 10 $
5
- ### $Release: 2.0.1 $
5
+ ### $Release: 2.1.0 $
6
6
  ### copyright(c) 2006 kuwata-lab all rights reserved.
7
7
  ###
8
8
 
9
9
  #--begin of require 'erubis/main'
10
10
  ###
11
- ### $Rev: 21 $
12
- ### $Release: 2.0.1 $
11
+ ### $Rev: 41 $
12
+ ### $Release: 2.1.0 $
13
13
  ### copyright(c) 2006 kuwata-lab all rights reserved.
14
14
  ###
15
15
 
16
16
  require 'yaml'
17
17
  #--begin of require 'erubis'
18
18
  ##
19
- ## $Rev: 21 $
20
- ## $Release: 2.0.1 $
19
+ ## $Rev: 36 $
20
+ ## $Release: 2.1.0 $
21
21
  ## copyright(c) 2006 kuwata-lab all rights reserved.
22
22
  ##
23
23
 
@@ -41,12 +41,15 @@ require 'yaml'
41
41
  ## </ul>
42
42
  ## END
43
43
  ## list = ['<aaa>', 'b&b', '"ccc"']
44
- ## eruby = Erubis::Eruby.new(input)
45
- ## puts "--- source ---"
46
- ## puts eruby.src
44
+ ## eruby = Erubis::Eruby.new()
45
+ ## code = eruby.convert(input)
46
+ ## puts "--- code ---"
47
+ ## puts code
47
48
  ## puts "--- result ---"
48
- ## puts eruby.evaluate(:list=>list)
49
- ## # or puts eruby.result(binding())
49
+ ## context = Object.new
50
+ ## context.instance_variable_set("@list", list)
51
+ ## puts context.instance_eval(code)
52
+ ## # or @list = list; puts eval(code, binding())
50
53
  ##
51
54
  ## result:
52
55
  ## --- source ---
@@ -71,16 +74,24 @@ require 'yaml'
71
74
 
72
75
  #--begin of require 'erubis/engine'
73
76
  ##
74
- ## $Rev: 24 $
75
- ## $Release: 2.0.1 $
77
+ ## $Rev: 32 $
78
+ ## $Release: 2.1.0 $
79
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
80
+ ##
81
+
82
+
83
+ #--begin of require 'erubis/generator'
84
+ ##
85
+ ## $Rev: 32 $
86
+ ## $Release: 2.1.0 $
76
87
  ## copyright(c) 2006 kuwata-lab all rights reserved.
77
88
  ##
78
89
 
79
90
  #--begin of require 'abstract'
80
91
  ##
81
92
  ## $Rev: 1 $
82
- ## $Release$
83
- ## $Copyright$
93
+ ## $Release: 0.1.0 $
94
+ ## copyright(c) 2006 kuwata-lab.com all rights reserved.
84
95
  ##
85
96
  ##
86
97
  ## helper to define abstract method in Ruby.
@@ -154,116 +165,163 @@ module Kernel
154
165
  end
155
166
  #--end of require 'abstract'
156
167
 
157
-
158
168
  module Erubis
159
169
 
160
170
 
161
- ##
162
- ## base error class
163
- ##
164
- class ErubisError < StandardError
165
- end
171
+ module Generator
166
172
 
173
+ def self.supported_properties() # :nodoc:
174
+ return [
175
+ [:escapefunc, nil, "escape function name"],
176
+ ]
177
+ end
167
178
 
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
179
+ attr_accessor :escapefunc
189
180
 
190
- def initialize(hash=nil)
191
- hash.each do |name, value|
192
- self[name] = value
193
- end if hash
181
+ def init_generator(properties={})
182
+ @escapefunc = properties[:escapefunc]
194
183
  end
195
184
 
196
- def [](key)
197
- return instance_variable_get("@#{key}")
185
+
186
+ ## (abstract) escape text string
187
+ ##
188
+ ## ex.
189
+ ## def escape_text(text)
190
+ ## return text.dump
191
+ ## # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'"
192
+ ## end
193
+ def escape_text(text)
194
+ not_implemented
198
195
  end
199
196
 
200
- def []=(key, value)
201
- return instance_variable_set("@#{key}", value)
197
+ ## return escaped expression code (ex. 'h(...)' or 'htmlspecialchars(...)')
198
+ def escaped_expr(code)
199
+ code.strip!
200
+ return "#{@escapefunc}(#{code})"
202
201
  end
203
202
 
204
- def keys
205
- return instance_variables.collect { |name| name[1,name.length-1] }
203
+ ## (abstract) add @preamble to src
204
+ def add_preamble(src)
205
+ not_implemented
206
+ end
207
+
208
+ ## (abstract) add text string to src
209
+ def add_text(src, text)
210
+ not_implemented
211
+ end
212
+
213
+ ## (abstract) add statement code to src
214
+ def add_stmt(src, code)
215
+ not_implemented
216
+ end
217
+
218
+ ## (abstract) add expression literal code to src. this is called by add_expr().
219
+ def add_expr_literal(src, code)
220
+ not_implemented
221
+ end
222
+
223
+ ## (abstract) add escaped expression code to src. this is called by add_expr().
224
+ def add_expr_escaped(src, code)
225
+ not_implemented
226
+ end
227
+
228
+ ## (abstract) add expression code to src for debug. this is called by add_expr().
229
+ def add_expr_debug(src, code)
230
+ not_implemented
231
+ end
232
+
233
+ ## (abstract) add @postamble to src
234
+ def add_postamble(src)
235
+ not_implemented
206
236
  end
207
237
 
238
+
208
239
  end
209
240
 
210
241
 
242
+ end
243
+ #--end of require 'erubis/generator'
244
+ #--begin of require 'erubis/converter'
245
+ ##
246
+ ## $Rev: 37 $
247
+ ## $Release: 2.1.0 $
248
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
249
+ ##
250
+
251
+ #--already included require 'abstract'
252
+
253
+ module Erubis
254
+
255
+
211
256
  ##
212
- ## .[abstract] base engine class
257
+ ## convert
213
258
  ##
214
- class Engine
259
+ module Converter
260
+
261
+ attr_accessor :preamble, :postamble, :escape
215
262
 
216
263
  def self.supported_properties # :nodoc:
217
264
  return [
218
- [:pattern, '<% %>', "embed pattern"],
219
- #[:filename, nil, "filename"],
220
- [:trim, true, "trim spaces around <% ... %>"],
221
265
  [:preamble, nil, "preamble (no preamble when false)"],
222
266
  [:postamble, nil, "postamble (no postamble when false)"],
223
- [:escape, nil, "escape function name"],
267
+ [:escape, nil, "escape expression or not in default"],
224
268
  ]
225
269
  end
226
270
 
227
- def initialize(input, properties={})
228
- #@input = input
229
- @pattern = properties[:pattern]
230
- @filename = properties[:filename]
231
- @trim = properties[:trim] != false
271
+ def init_converter(properties={})
232
272
  @preamble = properties[:preamble]
233
273
  @postamble = properties[:postamble]
234
274
  @escape = properties[:escape]
235
- @src = compile(input) if input
236
275
  end
237
- attr_reader :src
238
- attr_accessor :filename
239
276
 
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
277
+ ## convert input string into target language
278
+ def convert(input)
279
+ codebuf = "" # or []
280
+ @preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble))
281
+ convert_input(codebuf, input)
282
+ @postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble))
283
+ return codebuf # or codebuf.join()
247
284
  end
248
285
 
249
- ## eval(@src) with binding object
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)'))
286
+ protected
287
+
288
+ ##
289
+ ## (abstract) convert input to code
290
+ ##
291
+ def convert_input(codebuf, input)
292
+ not_implemented
258
293
  end
259
294
 
260
- ## invoke 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)'))
295
+ end
296
+
297
+
298
+ module Basic
299
+ end
300
+
301
+
302
+ ##
303
+ ## basic converter which supports '<% ... %>' notation.
304
+ ##
305
+ module Basic::Converter
306
+ include Erubis::Converter
307
+
308
+ def self.supported_properties # :nodoc:
309
+ return [
310
+ [:pattern, '<% %>', "embed pattern"],
311
+ [:trim, true, "trim spaces around <% ... %>"],
312
+ ]
313
+ end
314
+
315
+ attr_accessor :pattern, :trim
316
+
317
+ def init_converter(properties={})
318
+ super(properties)
319
+ @pattern = properties[:pattern]
320
+ @trim = properties[:trim] != false
264
321
  end
265
322
 
266
- DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
323
+ #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
324
+ DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
267
325
 
268
326
  ## return regexp of pattern to parse eRuby script
269
327
  def pattern_regexp(pattern=@pattern)
@@ -271,17 +329,20 @@ module Erubis
271
329
  return DEFAULT_REGEXP
272
330
  else
273
331
  prefix, postfix = pattern.split()
274
- return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
332
+ #return /(.*?)(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
333
+ return /(^[ \t]*)?#{prefix}(=+|\#)?(.*?)-?#{postfix}([ \t]*\r?\n)?/m
275
334
  end
276
335
  end
277
336
  protected :pattern_regexp
278
337
 
279
- ## compile input string into target language
280
- def compile(input)
281
- src = ""
282
- @preamble.nil? ? add_preamble(src) : (@preamble && (src << @preamble))
338
+ def convert_input(src, input)
283
339
  regexp = pattern_regexp(@pattern)
284
- input.scan(regexp) do |text, lspace, indicator, code, rspace|
340
+ pos = 0
341
+ input.scan(regexp) do |lspace, indicator, code, rspace|
342
+ match = Regexp.last_match()
343
+ index = match.begin(0)
344
+ text = input[pos, index - pos]
345
+ pos = match.end(0)
285
346
  add_text(src, text)
286
347
  ## * when '<%= %>', do nothing
287
348
  ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
@@ -302,126 +363,447 @@ module Erubis
302
363
  add_stmt(src, "\n" * n)
303
364
  add_text(src, rspace) if rspace
304
365
  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
366
  else # <%= %>
311
367
  add_text(src, lspace) if lspace
312
368
  add_expr(src, code, indicator)
313
369
  add_text(src, rspace) if rspace
314
370
  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
371
  end
334
372
  rest = $' || input # add input when no matched
335
373
  add_text(src, rest)
336
- @postamble.nil? ? add_postamble(src) : (@postamble && (src << @postamble))
337
- return src
338
374
  end
339
375
 
340
- ## compile input string and set it to @src
341
- def compile!(input)
342
- @src = compile(input)
376
+ ## add expression code to src
377
+ def add_expr(src, code, indicator)
378
+ case indicator
379
+ when '='
380
+ @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
381
+ when '=='
382
+ @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
383
+ when '==='
384
+ add_expr_debug(src, code)
385
+ end
343
386
  end
344
387
 
345
- protected
388
+ end
346
389
 
347
- ## .[abstract] escape text string
348
- ##
349
- ## ex.
350
- ## def escape_text(text)
351
- ## return text.dump
352
- ## # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'"
353
- ## end
354
- def escape_text(text)
355
- not_implemented
390
+
391
+ module PI
392
+ end
393
+
394
+ ##
395
+ ## Processing Instructions (PI) converter for XML.
396
+ ## this class converts '<?rb ... ?>' and '${...}' notation.
397
+ ##
398
+ module PI::Converter
399
+ include Erubis::Converter
400
+
401
+ def self.desc # :nodoc:
402
+ "use processing instructions (PI) instead of '<% %>'"
356
403
  end
357
404
 
358
- ## .[abstract] return escaped expression code
359
- ##
360
- ## ex.
361
- ## def escaped_expr(code)
362
- ## @escape ||= 'escape'
363
- ## return "#{@escape}(#{code.strip})"
364
- ## end
365
- def escaped_expr(code)
366
- not_implemented
405
+ def self.supported_properties # :nodoc:
406
+ return [
407
+ [:trim, true, "trim spaces around <% ... %>"],
408
+ [:pi, 'rb', "PI (Processing Instrunctions) name"],
409
+ [:embchar, '@', "char for embedded expression pattern('@{...}@')"],
410
+ [:pattern, '<% %>', "embed pattern"],
411
+ ]
367
412
  end
368
413
 
369
- ## .[abstract] add @preamble to src
370
- def add_preamble(src)
371
- not_implemented
414
+ attr_accessor :pi, :prefix
415
+
416
+ def init_converter(properties={})
417
+ super(properties)
418
+ @trim = !(properties[:trim] == false)
419
+ @pi = properties[:pi] if properties[:pi]
420
+ @embchar = properties[:embchar] || '@'
421
+ @pattern = properties[:pattern]
422
+ @pattern = '<% %>' if @pattern.nil? #|| @pattern == true
372
423
  end
373
424
 
374
- ## .[abstract] add text string to src
375
- def add_text(src, text)
376
- not_implemented
425
+ def convert(input)
426
+ code = super(input)
427
+ return @header || @footer ? "#{@header}#{code}#{@footer}" : code
377
428
  end
378
429
 
379
- ## .[abstract] add statement code to src
380
- def add_stmt(src, code)
381
- not_implemented
430
+ protected
431
+
432
+ def convert_input(codebuf, input)
433
+ parse_stmts(codebuf, input)
434
+ #parse_stmts2(codebuf, input)
382
435
  end
383
436
 
384
- ## add expression code to src
385
- def add_expr(src, code, indicator)
437
+ def parse_stmts(codebuf, input)
438
+ #regexp = pattern_regexp(@pattern)
439
+ @pi ||= 'e'
440
+ @stmt_pattern ||= /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m
441
+ pos = 0
442
+ input.scan(@stmt_pattern) do |lspace, pi_arg, code, rspace|
443
+ match = Regexp.last_match
444
+ index = match.begin(0)
445
+ text = input[pos, index - pos]
446
+ pos = match.end(0)
447
+ parse_exprs(codebuf, text) # unless text.empty?
448
+ if @trim && lspace && rspace
449
+ add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
450
+ else
451
+ add_text(codebuf, lspace)
452
+ add_pi_stmt(codebuf, code, pi_arg)
453
+ add_text(codebuf, rspace)
454
+ end
455
+ end
456
+ rest = $' || input
457
+ parse_exprs(codebuf, rest)
458
+ end
459
+
460
+ def parse_exprs(codebuf, input)
461
+ unless @expr_pattern
462
+ ch = Regexp.escape(@embchar)
463
+ if @pattern
464
+ left, right = @pattern.split(' ')
465
+ @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/
466
+ else
467
+ @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/
468
+ end
469
+ end
470
+ pos = 0
471
+ input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2|
472
+ indicator = indicator1 || indicator2
473
+ code = code1 || code2
474
+ match = Regexp.last_match
475
+ index = match.begin(0)
476
+ text = input[pos, index - pos]
477
+ pos = match.end(0)
478
+ add_text(codebuf, text) # unless text.empty?
479
+ add_pi_expr(codebuf, code, indicator)
480
+ end
481
+ rest = $' || input
482
+ add_text(codebuf, rest)
483
+ end
484
+
485
+ def add_pi_stmt(codebuf, code, pi_arg) # :nodoc:
486
+ case pi_arg
487
+ when 'header' ; @header = code
488
+ when 'footer' ; @footer = code
489
+ when 'comment'; add_stmt(codebuf, "\n" * code.count("\n"))
490
+ when 'value' ; add_expr_literal(codebuf, code)
491
+ else ; add_stmt(codebuf, code)
492
+ end
493
+ end
494
+
495
+ def add_pi_expr(codebuf, code, indicator) # :nodoc:
386
496
  case indicator
387
- when '='
388
- add_expr_literal(src, code)
389
- when '=='
390
- add_expr_escaped(src, code)
391
- when '==='
392
- add_expr_debug(src, code)
497
+ when nil, '', '==' # @{...}@ or <%== ... %>
498
+ @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code)
499
+ when '!', '=' # @!{...}@ or <%= ... %>
500
+ @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code)
501
+ when '!!', '===' # @!!{...}@ or <%=== ... %>
502
+ add_expr_debug(codebuf, code)
503
+ else
504
+ # ignore
393
505
  end
394
506
  end
395
507
 
396
- ## .[abstract] add expression literal code to src. this is called by add_expr().
397
- def add_expr_literal(src, code)
398
- not_implemented
508
+ ## (obsolete) equivarent to parse_stmts(), but a little slower than it.
509
+ def parse_stmts2(codebuf, input) # :nodoc:
510
+ #regexp = pattern_regexp(@pattern)
511
+ @pi ||= 'e'
512
+ unless @embedded_pattern
513
+ ch = Regexp.escape(@embchar)
514
+ if @pattern
515
+ left, right = @pattern.split(' ')
516
+ @embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
517
+ else
518
+ @embedded_pattern = /(^[ \t]*)?<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
519
+ end
520
+ end
521
+ pos = 0
522
+ input.scan(@embedded_pattern) do |lspace, pi_arg, stmt, rspace,
523
+ indicator1, expr1, indicator2, expr2|
524
+ match = Regexp.last_match
525
+ index = match.begin(0)
526
+ text = input[pos, index - pos]
527
+ pos = match.end(0)
528
+ add_text(codebuf, text) # unless text.empty?
529
+ if stmt
530
+ code = stmt
531
+ if @trim && lspace && rspace
532
+ add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
533
+ else
534
+ add_text(codebuf, lspace)
535
+ add_pi_stmt(codebuf, code, pi_arg)
536
+ add_text(codebuf, rspace)
537
+ end
538
+ else
539
+ code = expr1 || expr2
540
+ indicator = indicator1 || indicator2
541
+ add_pi_expr(codebuf, code, indicator)
542
+ end
543
+ end
544
+ rest = $' || input
545
+ add_text(codebuf, rest)
399
546
  end
400
547
 
401
- ## .[abstract] add escaped expression code to src. this is called by add_expr().
402
- def add_expr_escaped(src, code)
403
- not_implemented
548
+ end
549
+
550
+
551
+ end
552
+ #--end of require 'erubis/converter'
553
+ #--begin of require 'erubis/evaluator'
554
+ ##
555
+ ## $Rev: 32 $
556
+ ## $Release: 2.1.0 $
557
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
558
+ ##
559
+
560
+ #--begin of require 'erubis/error'
561
+ ##
562
+ ## $Rev: 32 $
563
+ ## $Release: 2.1.0 $
564
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
565
+ ##
566
+
567
+ module Erubis
568
+
569
+
570
+ ##
571
+ ## base error class
572
+ ##
573
+ class ErubisError < StandardError
574
+ end
575
+
576
+
577
+ ##
578
+ ## raised when method or function is not supported
579
+ ##
580
+ class NotSupportedError < ErubisError
581
+ end
582
+
583
+
584
+ end
585
+ #--end of require 'erubis/error'
586
+ #--begin of require 'erubis/context'
587
+ ##
588
+ ## $Rev: 32 $
589
+ ## $Release: 2.1.0 $
590
+ ## copyright(c) 2006 kuwata-lab all rights reserved.
591
+ ##
592
+
593
+
594
+ module Erubis
595
+
596
+
597
+ ##
598
+ ## context object for Engine#evaluate
599
+ ##
600
+ ## ex.
601
+ ## template = <<'END'
602
+ ## Hello <%= @user %>!
603
+ ## <% for item in @list %>
604
+ ## - <%= item %>
605
+ ## <% end %>
606
+ ## END
607
+ ##
608
+ ## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
609
+ ## # or
610
+ ## # context = Erubis::Context.new
611
+ ## # context[:user] = 'World'
612
+ ## # context[:list] = ['a', 'b', 'c']
613
+ ##
614
+ ## eruby = Erubis::Eruby.new(template)
615
+ ## print eruby.evaluate(context)
616
+ ##
617
+ class Context
618
+
619
+ def initialize(hash=nil)
620
+ hash.each do |name, value|
621
+ self[name] = value
622
+ end if hash
404
623
  end
405
624
 
406
- ## .[abstract] add expression code to src for debug. this is called by add_expr().
407
- def add_expr_debug(src, code)
408
- not_implemented
625
+ def [](key)
626
+ return instance_variable_get("@#{key}")
409
627
  end
410
628
 
411
- ## .[abstract] add @postamble to src
412
- def add_postamble(src)
413
- not_implemented
629
+ def []=(key, value)
630
+ return instance_variable_set("@#{key}", value)
631
+ end
632
+
633
+ def keys
634
+ return instance_variables.collect { |name| name[1,name.length-1] }
635
+ end
636
+
637
+ end
638
+
639
+
640
+ end
641
+ #--end of require 'erubis/context'
642
+
643
+
644
+ module Erubis
645
+
646
+
647
+ ##
648
+ ## evaluate code
649
+ ##
650
+ module Evaluator
651
+
652
+ def self.supported_properties # :nodoc:
653
+ return []
654
+ end
655
+
656
+ attr_accessor :src, :filename
657
+
658
+ def init_evaluator(properties)
659
+ @filename = properties[:filename]
660
+ end
661
+
662
+ def result(*args)
663
+ raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
414
664
  end
415
665
 
666
+ def evaluate(*args)
667
+ raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
668
+ end
669
+
670
+ end
671
+
672
+
673
+ ##
674
+ ## evaluator for Ruby
675
+ ##
676
+ module RubyEvaluator
677
+ include Evaluator
678
+
679
+ def self.supported_properties # :nodoc:
680
+ list = Evaluator.supported_properties
681
+ return list
682
+ end
683
+
684
+ ## eval(@src) with binding object
685
+ def result(_binding_or_hash=TOPLEVEL_BINDING)
686
+ _arg = _binding_or_hash
687
+ if _arg.is_a?(Hash)
688
+ ## load _context data as local variables by eval
689
+ eval _arg.keys.inject("") { |s, k| s << "#{k.to_s} = _arg[#{k.inspect}];" }
690
+ _arg = binding()
691
+ end
692
+ return eval(@src, _arg, (@filename || '(erubis)'))
693
+ end
694
+
695
+ ## invoke context.instance_eval(@src)
696
+ def evaluate(context=Context.new)
697
+ context = Context.new(context) if context.is_a?(Hash)
698
+ return context.instance_eval(@src, (@filename || '(erubis)'))
699
+ end
700
+
701
+ end
702
+
703
+
704
+ end
705
+ #--end of require 'erubis/evaluator'
706
+ #--already included require 'erubis/context'
707
+
708
+
709
+ module Erubis
710
+
711
+
712
+ ##
713
+ ## (abstract) abstract engine class.
714
+ ## subclass must include evaluator and converter module.
715
+ ##
716
+ class Engine
717
+ #include Evaluator
718
+ #include Converter
719
+ #include Generator
720
+
721
+ # convert input string and set it to @src
722
+ def convert!(input)
723
+ @src = convert(input)
724
+ end
725
+
726
+ def initialize(input=nil, properties={})
727
+ #@input = input
728
+ init_generator(properties)
729
+ init_converter(properties)
730
+ init_evaluator(properties)
731
+ @src = convert(input) if input
732
+ end
733
+
734
+ ## load file and create engine object
735
+ def self.load_file(filename, properties={})
736
+ input = File.open(filename, 'rb') { |f| f.read }
737
+ input.untaint # is it ok?
738
+ properties[:filename] = filename
739
+ engine = self.new(input, properties)
740
+ return engine
741
+ end
742
+
743
+
744
+ ##
745
+ ## helper method to convert and evaluate input text with context object.
746
+ ## context may be Binding, Hash, or Object.
747
+ ##
748
+ def process(input, context=nil, filename=nil)
749
+ code = convert(input)
750
+ filename ||= '(erubis)'
751
+ if context.is_a?(Binding)
752
+ return eval(code, context, filename)
753
+ else
754
+ context = Context.new(context) if context.is_a?(Hash)
755
+ return context.instance_eval(code, filename)
756
+ end
757
+ end
758
+
759
+
760
+ ##
761
+ ## helper method evaluate Proc object iwth contect object.
762
+ ## context may be Binding, Hash, or Object.
763
+ ##
764
+ def process_proc(proc_obj, context=nil, filename=nil)
765
+ if context.is_a?(Binding)
766
+ filename ||= '(erubis)'
767
+ return eval(proc_obj, context, filename)
768
+ else
769
+ context = Context.new(context) if context.is_a?(Hash)
770
+ return context.instance_eval(&proc_obj)
771
+ end
772
+ end
773
+
774
+
416
775
  end # end of class Engine
417
776
 
418
777
 
778
+ ##
779
+ ## (abstract) base engine class for Eruby, Eperl, Ejava, and so on.
780
+ ## subclass must include generator.
781
+ ##
782
+ class Basic::Engine < Engine
783
+ include Evaluator
784
+ include Basic::Converter
785
+ include Generator
786
+ end
787
+
788
+
789
+ class PI::Engine < Engine
790
+ include Evaluator
791
+ include PI::Converter
792
+ include Generator
793
+ end
794
+
795
+
419
796
  end
420
797
  #--end of require 'erubis/engine'
798
+ #require 'erubis/generator'
799
+ #require 'erubis/converter'
800
+ #require 'erubis/evaluator'
801
+ #require 'erubis/error'
802
+ #require 'erubis/context'
421
803
  #--begin of require 'erubis/helper'
422
804
  ##
423
805
  ## $Rev: 21 $
424
- ## $Release: 2.0.1 $
806
+ ## $Release: 2.1.0 $
425
807
  ## copyright(c) 2006 kuwata-lab all rights reserved.
426
808
  ##
427
809
 
@@ -475,15 +857,12 @@ end
475
857
  #--end of require 'erubis/helper'
476
858
  #--begin of require 'erubis/enhancer'
477
859
  ##
478
- ## $Rev: 21 $
479
- ## $Release: 2.0.1 $
860
+ ## $Rev: 32 $
861
+ ## $Release: 2.1.0 $
480
862
  ## copyright(c) 2006 kuwata-lab all rights reserved.
481
863
  ##
482
864
 
483
865
 
484
- #--already included require 'erubis/engine'
485
-
486
-
487
866
  module Erubis
488
867
 
489
868
 
@@ -517,11 +896,9 @@ module Erubis
517
896
  def add_expr(src, code, indicator)
518
897
  case indicator
519
898
  when '='
520
- add_expr_escaped(src, code)
521
- #add_expr_literal(src, code)
899
+ @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
522
900
  when '=='
523
- add_expr_literal(src, code)
524
- #add_expr_escaped(src, code)
901
+ @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
525
902
  when '==='
526
903
  add_expr_debug(src, code)
527
904
  end
@@ -617,11 +994,11 @@ module Erubis
617
994
  end
618
995
  end
619
996
 
620
- def evaluate(context=Context.new)
997
+ def evaluate(context=nil)
621
998
  _src = @src
622
999
  if context.is_a?(Hash)
623
1000
  context.each do |key, val| instance_variable_set("@#{key}", val) end
624
- else
1001
+ elsif context
625
1002
  context.instance_variables.each do |name|
626
1003
  instance_variable_set(name, context.instance_variable_get(name))
627
1004
  end
@@ -728,46 +1105,85 @@ module Erubis
728
1105
  ## remove text and leave code, especially useful when debugging.
729
1106
  ##
730
1107
  ## ex.
731
- ## $ erubis -s -e NoText file.eruby | more
1108
+ ## $ erubis -s -E NoText file.eruby | more
1109
+ ##
1110
+ ## this is language independent.
1111
+ ##
1112
+ module NoTextEnhancer
1113
+
1114
+ def self.desc # :nodoc:
1115
+ "remove text and leave code (useful when debugging)"
1116
+ end
1117
+
1118
+ def add_text(src, text)
1119
+ src << ("\n" * text.count("\n"))
1120
+ if text[-1] != ?\n
1121
+ text =~ /^(.*?)\z/
1122
+ src << (' ' * $1.length)
1123
+ end
1124
+ end
1125
+
1126
+ end
1127
+
1128
+
1129
+ ##
1130
+ ## remove code and leave text, especially useful when validating HTML tags.
1131
+ ##
1132
+ ## ex.
1133
+ ## $ erubis -s -E NoCode file.eruby | tidy -errors
732
1134
  ##
733
1135
  ## this is language independent.
734
1136
  ##
735
- module NoTextEnhancer
1137
+ module NoCodeEnhancer
736
1138
 
737
1139
  def self.desc # :nodoc:
738
- "remove text and leave code (useful when debugging)"
1140
+ "remove code and leave text (useful when validating HTML)"
1141
+ end
1142
+
1143
+ def add_preamble(src)
1144
+ end
1145
+
1146
+ def add_postamble(src)
739
1147
  end
740
1148
 
741
1149
  def add_text(src, text)
742
- src << ("\n" * text.count("\n"))
743
- if text[-1] != ?\n
744
- text =~ /^(.*?)\z/
745
- src << (' ' * $1.length)
746
- end
1150
+ src << text
1151
+ end
1152
+
1153
+ def add_expr(src, code, indicator)
1154
+ src << "\n" * code.count("\n")
1155
+ end
1156
+
1157
+ def add_stmt(src, code)
1158
+ src << "\n" * code.count("\n")
747
1159
  end
748
1160
 
749
1161
  end
750
1162
 
751
1163
 
752
1164
  ##
753
- ## get compile faster, but spaces around '<%...%>' are not trimmed.
1165
+ ## get convert faster, but spaces around '<%...%>' are not trimmed.
754
1166
  ##
755
1167
  ## this is language-independent.
756
1168
  ##
757
1169
  module SimplifyEnhancer
758
1170
 
759
1171
  def self.desc # :nodoc:
760
- "get compile faster but leave spaces around '<% %>'"
1172
+ "get convert faster but leave spaces around '<% %>'"
761
1173
  end
762
1174
 
763
- #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
764
- SIMPLE_REGEXP = /(.*?)<%(=+|\#)?(.*?)-?%>/m
1175
+ #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
1176
+ SIMPLE_REGEXP = /<%(=+|\#)?(.*?)-?%>/m
765
1177
 
766
- def compile(input)
1178
+ def convert(input)
767
1179
  src = ""
768
1180
  add_preamble(src)
769
1181
  #regexp = pattern_regexp(@pattern)
770
- input.scan(SIMPLE_REGEXP) do |text, indicator, code|
1182
+ pos = 0
1183
+ input.scan(SIMPLE_REGEXP) do |indicator, code|
1184
+ index = Regexp.last_match.begin(0)
1185
+ text = input[pos, index - pos]
1186
+ pos = index + $&.length()
771
1187
  add_text(src, text)
772
1188
  if !indicator # <% %>
773
1189
  add_stmt(src, code)
@@ -952,7 +1368,7 @@ module Erubis
952
1368
 
953
1369
  attr_accessor :header, :footer
954
1370
 
955
- def compile(input)
1371
+ def convert(input)
956
1372
  source = super
957
1373
  return @src = "#{@header}#{source}#{@footer}"
958
1374
  end
@@ -965,27 +1381,34 @@ end
965
1381
  #require 'erubis/tiny'
966
1382
  #--begin of require 'erubis/engine/eruby'
967
1383
  ##
968
- ## $Rev: 21 $
969
- ## $Release: 2.0.1 $
1384
+ ## $Rev: 33 $
1385
+ ## $Release: 2.1.0 $
970
1386
  ## copyright(c) 2006 kuwata-lab all rights reserved.
971
1387
  ##
972
1388
 
973
1389
  #--already included require 'erubis/engine'
974
1390
  #--already included require 'erubis/enhancer'
1391
+ #--already included require 'abstract'
975
1392
 
976
1393
 
977
1394
  module Erubis
978
1395
 
979
1396
 
980
1397
  ##
981
- ## engine for Ruby
1398
+ ## code generator for Ruby
982
1399
  ##
983
- class Eruby < Engine
1400
+ module RubyGenerator
1401
+ include Generator
984
1402
  #include StringBufferEnhancer
985
1403
  include ArrayBufferEnhancer
986
1404
 
1405
+ def init_generator(properties={})
1406
+ super
1407
+ @escapefunc ||= "Erubis::XmlHelper.escape_xml"
1408
+ end
1409
+
987
1410
  def self.supported_properties() # :nodoc:
988
- return super
1411
+ return []
989
1412
  end
990
1413
 
991
1414
  def escape_text(text)
@@ -993,8 +1416,7 @@ module Erubis
993
1416
  end
994
1417
 
995
1418
  def escaped_expr(code)
996
- @escape ||= "Erubis::XmlHelper.escape_xml"
997
- return "#{@escape}(#{code})"
1419
+ return "#{@escapefunc}(#{code})"
998
1420
  end
999
1421
 
1000
1422
  #--
@@ -1036,6 +1458,15 @@ module Erubis
1036
1458
  end
1037
1459
 
1038
1460
 
1461
+ ##
1462
+ ## engine for Ruby
1463
+ ##
1464
+ class Eruby < Basic::Engine
1465
+ include RubyEvaluator
1466
+ include RubyGenerator
1467
+ end
1468
+
1469
+
1039
1470
  ##
1040
1471
  ## swtich '<%= %>' to escaped and '<%== %>' to not escaped
1041
1472
  ##
@@ -1054,6 +1485,18 @@ module Erubis
1054
1485
  end
1055
1486
 
1056
1487
 
1488
+ class PI::Eruby < PI::Engine
1489
+ include RubyEvaluator
1490
+ include RubyGenerator
1491
+
1492
+ def init_converter(properties={})
1493
+ @pi = 'rb'
1494
+ super(properties)
1495
+ end
1496
+
1497
+ end
1498
+
1499
+
1057
1500
  end
1058
1501
  #--end of require 'erubis/engine/eruby'
1059
1502
  #require 'erubis/engine/enhanced' # enhanced eruby engines
@@ -1065,11 +1508,10 @@ end
1065
1508
  #require 'erubis/engine/eperl'
1066
1509
  #require 'erubis/engine/ejavascript'
1067
1510
 
1068
-
1069
1511
  #--begin of require 'erubis/local-setting'
1070
1512
  ##
1071
1513
  ## $Rev: 13 $
1072
- ## $Release: 2.0.1 $
1514
+ ## $Release: 2.1.0 $
1073
1515
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1074
1516
  ##
1075
1517
 
@@ -1081,8 +1523,8 @@ end
1081
1523
  #--end of require 'erubis'
1082
1524
  #--begin of require 'erubis/tiny'
1083
1525
  ##
1084
- ## $Rev: 21 $
1085
- ## $Release: 2.0.1 $
1526
+ ## $Rev: 35 $
1527
+ ## $Release: 2.1.0 $
1086
1528
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1087
1529
  ##
1088
1530
 
@@ -1099,16 +1541,21 @@ module Erubis
1099
1541
  ##
1100
1542
  class TinyEruby
1101
1543
 
1102
- def initialize(input)
1103
- @src = compile(input)
1544
+ def initialize(input=nil)
1545
+ @src = convert(input) if input
1104
1546
  end
1105
1547
  attr_reader :src
1106
1548
 
1107
- EMBEDDED_PATTERN = /(.*?)<%(=+|\#)?(.*?)-?%>/m
1549
+ EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m
1108
1550
 
1109
- def compile(input)
1551
+ def convert(input)
1110
1552
  src = "_buf = [];" # preamble
1111
- input.scan(EMBEDDED_PATTERN) do |text, indicator, code|
1553
+ pos = 0
1554
+ input.scan(EMBEDDED_PATTERN) do |indicator, code|
1555
+ match = Regexp.last_match
1556
+ index = match.begin(0)
1557
+ text = input[pos, index - pos]
1558
+ pos = match.end(0)
1112
1559
  src << " _buf << '" << escape_text(text) << "';"
1113
1560
  if !indicator # <% %>
1114
1561
  src << code << ";"
@@ -1144,12 +1591,81 @@ module Erubis
1144
1591
 
1145
1592
  end
1146
1593
 
1594
+
1595
+
1596
+ module PI
1597
+ end
1598
+
1599
+ class PI::TinyEruby
1600
+
1601
+ def initialize(input=nil, options={})
1602
+ @escape = options[:escape] || 'Erubis::XmlHelper.escape_xml'
1603
+ @src = convert(input) if input
1604
+ end
1605
+
1606
+ attr_reader :src
1607
+
1608
+ EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|\$(!*)?\{(.*?)\}/
1609
+
1610
+ def convert(input)
1611
+ src = "_buf = [];" # preamble
1612
+ pos = 0
1613
+ input.scan(EMBEDDED_PATTERN) do |lspace, stmtcode, rspace, indicator, exprcode|
1614
+ match = Regexp.last_match
1615
+ index = match.begin(0)
1616
+ text = input[pos, index - pos]
1617
+ pos = match.end(0)
1618
+ if stmtcode # <?rb ... ?>
1619
+ code = stmtcode
1620
+ src << " _buf << '" << escape_text(text) << "';"
1621
+ if lspace && rspace
1622
+ src << "#{lspace}#{code}#{rspace}"
1623
+ else
1624
+ src << " _buf << '#{lspace}';" if lspace
1625
+ src << code << ";"
1626
+ src << " _buf << '#{rspace}';" if rspace
1627
+ end
1628
+ else # ${...}, $!{...}
1629
+ code = exprcode
1630
+ if indicator.nil? || indicator.empty?
1631
+ src << " _buf << #{@escape}(" << code << ");"
1632
+ elsif indicator == '!'
1633
+ src << " _buf << (" << code << ").to_s;"
1634
+ end
1635
+ end
1636
+ end
1637
+ rest = $' || input
1638
+ src << " _buf << '" << escape_text(rest) << "';"
1639
+ src << "\n_buf.join\n" # postamble
1640
+ return src
1641
+ end
1642
+
1643
+ def escape_text(text)
1644
+ return text.gsub!(/['\\]/, '\\\\\&') || text
1645
+ end
1646
+
1647
+ def result(binding=TOPLEVEL_BINDING)
1648
+ eval @src, binding
1649
+ end
1650
+
1651
+ def evaluate(context=Object.new)
1652
+ if context.is_a?(Hash)
1653
+ obj = Object.new
1654
+ context.each do |k, v| obj.instance_variable_set("@#{k}", v) end
1655
+ context = obj
1656
+ end
1657
+ context.instance_eval @src
1658
+ end
1659
+
1660
+ end
1661
+
1662
+
1147
1663
  end
1148
1664
  #--end of require 'erubis/tiny'
1149
1665
  #--begin of require 'erubis/engine/enhanced'
1150
1666
  ##
1151
- ## $Rev: 19 $
1152
- ## $Release: 2.0.1 $
1667
+ ## $Rev: 27 $
1668
+ ## $Release: 2.1.0 $
1153
1669
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1154
1670
  ##
1155
1671
 
@@ -1216,6 +1732,11 @@ module Erubis
1216
1732
  end
1217
1733
 
1218
1734
 
1735
+ class NoCodeEruby < Eruby
1736
+ include NoCodeEnhancer
1737
+ end
1738
+
1739
+
1219
1740
  class SimplifiedEruby < Eruby
1220
1741
  include SimplifyEnhancer
1221
1742
  end
@@ -1252,8 +1773,8 @@ end
1252
1773
  #--end of require 'erubis/engine/enhanced'
1253
1774
  #--begin of require 'erubis/engine/optimized'
1254
1775
  ##
1255
- ## $Rev: 21 $
1256
- ## $Release: 2.0.1 $
1776
+ ## $Rev: 31 $
1777
+ ## $Release: 2.1.0 $
1257
1778
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1258
1779
  ##
1259
1780
 
@@ -1264,19 +1785,18 @@ end
1264
1785
  module Erubis
1265
1786
 
1266
1787
 
1267
- ##
1268
- ## Eruby class which generates optimized ruby code
1269
- ##
1270
- class OptimizedEruby < Engine # Eruby
1788
+ module OptimizedGenerator
1789
+ include Generator
1271
1790
 
1272
1791
  def self.supported_properties() # :nodoc:
1273
- return super
1792
+ return []
1274
1793
  end
1275
1794
 
1276
- def initialize(input, properties={})
1795
+ def init_generator(properties={})
1796
+ super
1797
+ @escapefunc ||= "Erubis::XmlHelper.escape_xml"
1277
1798
  @initialized = false
1278
1799
  @prev_is_expr = false
1279
- super
1280
1800
  end
1281
1801
 
1282
1802
  protected
@@ -1286,8 +1806,8 @@ module Erubis
1286
1806
  end
1287
1807
 
1288
1808
  def escaped_expr(code)
1289
- @escape ||= 'Erubis::XmlHelper.escape_xml'
1290
- return "#{@escape}(#{code})"
1809
+ @escapefunc ||= 'Erubis::XmlHelper.escape_xml'
1810
+ return "#{@escapefunc}(#{code})"
1291
1811
  end
1292
1812
 
1293
1813
  def switch_to_expr(src)
@@ -1351,6 +1871,21 @@ module Erubis
1351
1871
  end # end of class OptimizedEruby
1352
1872
 
1353
1873
 
1874
+ ##
1875
+ ## Eruby class which generates optimized ruby code
1876
+ ##
1877
+ class OptimizedEruby < Basic::Engine # Eruby
1878
+ include RubyEvaluator
1879
+ include OptimizedGenerator
1880
+
1881
+ def init_converter(properties={})
1882
+ @pi = 'rb'
1883
+ super(properties)
1884
+ end
1885
+
1886
+ end
1887
+
1888
+
1354
1889
  ##
1355
1890
  ## XmlEruby class which generates optimized ruby code
1356
1891
  ##
@@ -1369,8 +1904,8 @@ end
1369
1904
  #--already included require 'erubis/engine/eruby'
1370
1905
  #--begin of require 'erubis/engine/ephp'
1371
1906
  ##
1372
- ## $Rev: 24 $
1373
- ## $Release: 2.0.1 $
1907
+ ## $Rev: 31 $
1908
+ ## $Release: 2.1.0 $
1374
1909
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1375
1910
  ##
1376
1911
 
@@ -1381,13 +1916,16 @@ end
1381
1916
  module Erubis
1382
1917
 
1383
1918
 
1384
- ##
1385
- ## engine for PHP
1386
- ##
1387
- class Ephp < Engine
1919
+ module PhpGenerator
1920
+ include Generator
1388
1921
 
1389
1922
  def self.supported_properties() # :nodoc:
1390
- return super
1923
+ return []
1924
+ end
1925
+
1926
+ def init_generator(properties={})
1927
+ super
1928
+ @escapefunc ||= 'htmlspecialchars'
1391
1929
  end
1392
1930
 
1393
1931
  def add_preamble(src)
@@ -1402,17 +1940,13 @@ module Erubis
1402
1940
  src << escape_text(text)
1403
1941
  end
1404
1942
 
1405
- def escaped_expr(code)
1406
- @escape ||= 'htmlspecialchars'
1407
- return "#{@escape}(#{code.strip})"
1408
- end
1409
-
1410
1943
  def add_expr_literal(src, code)
1411
- src << "<?php echo #{code.strip}; ?>"
1944
+ code.strip!
1945
+ src << "<?php echo #{code}; ?>"
1412
1946
  end
1413
1947
 
1414
1948
  def add_expr_escaped(src, code)
1415
- src << "<?php echo #{escaped_expr(code)}; ?>"
1949
+ add_expr_literal(src, escaped_expr(code))
1416
1950
  end
1417
1951
 
1418
1952
  def add_expr_debug(src, code)
@@ -1439,6 +1973,14 @@ module Erubis
1439
1973
  end
1440
1974
 
1441
1975
 
1976
+ ##
1977
+ ## engine for PHP
1978
+ ##
1979
+ class Ephp < Basic::Engine
1980
+ include PhpGenerator
1981
+ end
1982
+
1983
+
1442
1984
  class EscapedEphp < Ephp
1443
1985
  include EscapeEnhancer
1444
1986
  end
@@ -1449,12 +1991,23 @@ module Erubis
1449
1991
  #end
1450
1992
 
1451
1993
 
1994
+ class PI::Ephp < PI::Engine
1995
+ include PhpGenerator
1996
+
1997
+ def init_converter(properties={})
1998
+ @pi = 'php'
1999
+ super(properties)
2000
+ end
2001
+
2002
+ end
2003
+
2004
+
1452
2005
  end
1453
2006
  #--end of require 'erubis/engine/ephp'
1454
2007
  #--begin of require 'erubis/engine/ec'
1455
2008
  ##
1456
- ## $Rev: 24 $
1457
- ## $Release: 2.0.1 $
2009
+ ## $Rev: 33 $
2010
+ ## $Release: 2.1.0 $
1458
2011
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1459
2012
  ##
1460
2013
 
@@ -1465,22 +2018,21 @@ end
1465
2018
  module Erubis
1466
2019
 
1467
2020
 
1468
- ##
1469
- ## engine for C
1470
- ##
1471
- class Ec < Engine
2021
+ module CGenerator
2022
+ include Generator
1472
2023
 
1473
2024
  def self.supported_properties() # :nodoc:
1474
- list = super
1475
- list << [:indent, '', "indent spaces (ex. ' ')"]
1476
- list << [:out, 'stdout', "output file pointer name"]
1477
- return list
2025
+ return [
2026
+ [:indent, '', "indent spaces (ex. ' ')"],
2027
+ [:out, 'stdout', "output file pointer name"],
2028
+ ]
1478
2029
  end
1479
2030
 
1480
- def initialize(input, properties={})
2031
+ def init_generator(properties={})
2032
+ super
2033
+ @escapefunc ||= "escape"
1481
2034
  @indent = properties[:indent] || ''
1482
2035
  @out = properties[:out] || 'stdout'
1483
- super
1484
2036
  end
1485
2037
 
1486
2038
  def add_preamble(src)
@@ -1494,13 +2046,7 @@ module Erubis
1494
2046
  end
1495
2047
 
1496
2048
  def escaped_expr(code)
1497
- @escape ||= "escape"
1498
- code.strip!
1499
- if code =~ /\A(\".*?\")\s*,\s*(.*)/
1500
- return "#{$1}, #{@escape}(#{$2})"
1501
- else
1502
- return "#{@escape}(#{code})"
1503
- end
2049
+ return "#{@escapefunc}(#{code.strip}, #{@out})"
1504
2050
  end
1505
2051
 
1506
2052
  def add_text(src, text)
@@ -1528,7 +2074,7 @@ module Erubis
1528
2074
 
1529
2075
  def add_expr_escaped(src, code)
1530
2076
  src << @indent if src.empty? || src[-1] == ?\n
1531
- src << " fprintf(#{@out}, " << escaped_expr(code) << ');'
2077
+ src << ' ' << escaped_expr(code) << ';'
1532
2078
  end
1533
2079
 
1534
2080
  def add_expr_debug(src, code)
@@ -1548,6 +2094,14 @@ module Erubis
1548
2094
  end
1549
2095
 
1550
2096
 
2097
+ ##
2098
+ ## engine for C
2099
+ ##
2100
+ class Ec < Basic::Engine
2101
+ include CGenerator
2102
+ end
2103
+
2104
+
1551
2105
  class EscapedEc < Ec
1552
2106
  include EscapeEnhancer
1553
2107
  end
@@ -1557,13 +2111,23 @@ module Erubis
1557
2111
  # include EscapeEnhancer
1558
2112
  #end
1559
2113
 
2114
+ class PI::Ec < PI::Engine
2115
+ include CGenerator
2116
+
2117
+ def init_converter(properties={})
2118
+ @pi = 'c'
2119
+ super(properties)
2120
+ end
2121
+
2122
+ end
2123
+
1560
2124
 
1561
2125
  end
1562
2126
  #--end of require 'erubis/engine/ec'
1563
2127
  #--begin of require 'erubis/engine/ejava'
1564
2128
  ##
1565
- ## $Rev: 24 $
1566
- ## $Release: 2.0.1 $
2129
+ ## $Rev: 31 $
2130
+ ## $Release: 2.1.0 $
1567
2131
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1568
2132
  ##
1569
2133
 
@@ -1574,24 +2138,23 @@ end
1574
2138
  module Erubis
1575
2139
 
1576
2140
 
1577
- ##
1578
- ## engine for Java
1579
- ##
1580
- class Ejava < Engine
2141
+ module JavaGenerator
2142
+ include Generator
1581
2143
 
1582
2144
  def self.supported_properties() # :nodoc:
1583
- list = super
1584
- list << [:indent, '', "indent spaces (ex. ' ')"]
1585
- list << [:buf, '_buf', "output buffer name"]
1586
- list << [:bufclass, 'StringBuffer', "output buffer class (ex. 'StringBuilder')"]
1587
- return list
2145
+ return [
2146
+ [:indent, '', "indent spaces (ex. ' ')"],
2147
+ [:buf, '_buf', "output buffer name"],
2148
+ [:bufclass, 'StringBuffer', "output buffer class (ex. 'StringBuilder')"],
2149
+ ]
1588
2150
  end
1589
2151
 
1590
- def initialize(input, properties={})
2152
+ def init_generator(properties={})
2153
+ super
2154
+ @escapefunc ||= 'escape'
1591
2155
  @indent = properties[:indent] || ''
1592
2156
  @buf = properties[:buf] || '_buf'
1593
2157
  @bufclass = properties[:bufclass] || 'StringBuffer'
1594
- super
1595
2158
  end
1596
2159
 
1597
2160
  def add_preamble(src)
@@ -1603,11 +2166,6 @@ module Erubis
1603
2166
  return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
1604
2167
  end
1605
2168
 
1606
- def escaped_expr(code)
1607
- @escape ||= 'escape'
1608
- return "#{@escape}(#{code.strip})"
1609
- end
1610
-
1611
2169
  def add_text(src, text)
1612
2170
  return if text.empty?
1613
2171
  src << (src.empty? || src[-1] == ?\n ? @indent : ' ')
@@ -1627,12 +2185,12 @@ module Erubis
1627
2185
 
1628
2186
  def add_expr_literal(src, code)
1629
2187
  src << @indent if src.empty? || src[-1] == ?\n
1630
- src << ' ' << @buf << '.append(' << code.strip << ');'
2188
+ code.strip!
2189
+ src << " #{@buf}.append(#{code});"
1631
2190
  end
1632
2191
 
1633
2192
  def add_expr_escaped(src, code)
1634
- src << @indent if src.empty? || src[-1] == ?\n
1635
- src << ' ' << @buf << '.append(' << escaped_expr(code) << ');'
2193
+ add_expr_literal(src, escaped_expr(code))
1636
2194
  end
1637
2195
 
1638
2196
  def add_expr_debug(src, code)
@@ -1644,11 +2202,20 @@ module Erubis
1644
2202
  def add_postamble(src)
1645
2203
  src << "\n" if src[-1] == ?;
1646
2204
  src << @indent << "return " << @buf << ".toString();\n"
2205
+ #src << @indent << "System.out.print(" << @buf << ".toString());\n"
1647
2206
  end
1648
2207
 
1649
2208
  end
1650
2209
 
1651
2210
 
2211
+ ##
2212
+ ## engine for Java
2213
+ ##
2214
+ class Ejava < Basic::Engine
2215
+ include JavaGenerator
2216
+ end
2217
+
2218
+
1652
2219
  class EscapedEjava < Ejava
1653
2220
  include EscapeEnhancer
1654
2221
  end
@@ -1658,13 +2225,22 @@ module Erubis
1658
2225
  # include EscapeEnhancer
1659
2226
  #end
1660
2227
 
2228
+ class PI::Ejava < PI::Engine
2229
+ include JavaGenerator
2230
+
2231
+ def init_converter(properties={})
2232
+ @pi = 'java'
2233
+ super(properties)
2234
+ end
2235
+
2236
+ end
1661
2237
 
1662
2238
  end
1663
2239
  #--end of require 'erubis/engine/ejava'
1664
2240
  #--begin of require 'erubis/engine/escheme'
1665
2241
  ##
1666
- ## $Rev: 21 $
1667
- ## $Release: 2.0.1 $
2242
+ ## $Rev: 33 $
2243
+ ## $Release: 2.1.0 $
1668
2244
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1669
2245
  ##
1670
2246
 
@@ -1675,20 +2251,19 @@ end
1675
2251
  module Erubis
1676
2252
 
1677
2253
 
1678
- ##
1679
- ## engine for Scheme
1680
- ##
1681
- class Escheme < Engine
2254
+ module SchemeGenerator
2255
+ include Generator
1682
2256
 
1683
2257
  def self.supported_properties() # :nodoc:
1684
- list = super
1685
- list << [:func, '_add', "function name (ex. 'display')"]
1686
- return list
2258
+ return [
2259
+ [:func, '_add', "function name (ex. 'display')"],
2260
+ ]
1687
2261
  end
1688
2262
 
1689
- def initialize(input, properties={})
1690
- @func = properties[:func] || '_add' # or 'display'
2263
+ def init_generator(properties={})
1691
2264
  super
2265
+ @escapefunc ||= 'escape'
2266
+ @func = properties[:func] || '_add' # or 'display'
1692
2267
  end
1693
2268
 
1694
2269
  def add_preamble(src)
@@ -1706,8 +2281,8 @@ module Erubis
1706
2281
  end
1707
2282
 
1708
2283
  def escaped_expr(code)
1709
- @escape ||= 'escape'
1710
- return "(#{@escape} #{code.strip})"
2284
+ code.strip!
2285
+ return "(#{@escapefunc} #{code})"
1711
2286
  end
1712
2287
 
1713
2288
  def add_text(src, text)
@@ -1726,11 +2301,12 @@ module Erubis
1726
2301
  end
1727
2302
 
1728
2303
  def add_expr_literal(src, code)
1729
- src << "(#{@func} " << code.strip << ')'
2304
+ code.strip!
2305
+ src << "(#{@func} #{code})"
1730
2306
  end
1731
2307
 
1732
2308
  def add_expr_escaped(src, code)
1733
- src << "(#{@func} " << escaped_expr(code) << ')'
2309
+ add_expr_literal(src, escaped_expr(code))
1734
2310
  end
1735
2311
 
1736
2312
  def add_expr_debug(src, code)
@@ -1747,6 +2323,14 @@ module Erubis
1747
2323
  end
1748
2324
 
1749
2325
 
2326
+ ##
2327
+ ## engine for Scheme
2328
+ ##
2329
+ class Escheme < Basic::Engine
2330
+ include SchemeGenerator
2331
+ end
2332
+
2333
+
1750
2334
  class EscapedEscheme < Escheme
1751
2335
  include EscapeEnhancer
1752
2336
  end
@@ -1757,12 +2341,23 @@ module Erubis
1757
2341
  #end
1758
2342
 
1759
2343
 
2344
+ class PI::Escheme < PI::Engine
2345
+ include SchemeGenerator
2346
+
2347
+ def init_converter(properties={})
2348
+ @pi = 'scheme'
2349
+ super(properties)
2350
+ end
2351
+
2352
+ end
2353
+
2354
+
1760
2355
  end
1761
2356
  #--end of require 'erubis/engine/escheme'
1762
2357
  #--begin of require 'erubis/engine/eperl'
1763
2358
  ##
1764
- ## $Rev: 24 $
1765
- ## $Release: 2.0.1 $
2359
+ ## $Rev: 40 $
2360
+ ## $Release: 2.1.0 $
1766
2361
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1767
2362
  ##
1768
2363
 
@@ -1773,24 +2368,23 @@ end
1773
2368
  module Erubis
1774
2369
 
1775
2370
 
1776
- ##
1777
- ## engine for Perl
1778
- ##
1779
- class Eperl < Engine
2371
+ module PerlGenerator
2372
+ include Generator
1780
2373
 
1781
2374
  def self.supported_properties() # :nodoc:
1782
- list = super
1783
- list << [:func, 'print', "function name"]
1784
- return list
2375
+ return [
2376
+ [:func, 'print', "function name"],
2377
+ ]
1785
2378
  end
1786
2379
 
1787
- def initialize(input, properties={})
1788
- @func = properties[:func] || 'print'
2380
+ def init_generator(properties={})
1789
2381
  super
2382
+ @escapefunc ||= 'encode_entities'
2383
+ @func = properties[:func] || 'print'
1790
2384
  end
1791
2385
 
1792
2386
  def add_preamble(src)
1793
- # empty
2387
+ src << "use HTML::Entities; ";
1794
2388
  end
1795
2389
 
1796
2390
  def escape_text(text)
@@ -1801,17 +2395,13 @@ module Erubis
1801
2395
  src << @func << "('" << escape_text(text) << "'); " unless text.empty?
1802
2396
  end
1803
2397
 
1804
- def escaped_expr(code)
1805
- @escape ||= 'escape'
1806
- return "escape(#{code.strip})"
1807
- end
1808
-
1809
2398
  def add_expr_literal(src, code)
1810
- src << @func << "(" << code.strip << "); "
2399
+ code.strip!
2400
+ src << @func << "(" << code << "); "
1811
2401
  end
1812
2402
 
1813
2403
  def add_expr_escaped(src, code)
1814
- src << @func << "(" << escaped_expr(code) << "); "
2404
+ add_expr_literal(src, escaped_expr(code))
1815
2405
  end
1816
2406
 
1817
2407
  def add_expr_debug(src, code)
@@ -1831,6 +2421,14 @@ module Erubis
1831
2421
  end
1832
2422
 
1833
2423
 
2424
+ ##
2425
+ ## engine for Perl
2426
+ ##
2427
+ class Eperl < Basic::Engine
2428
+ include PerlGenerator
2429
+ end
2430
+
2431
+
1834
2432
  class EscapedEperl < Eperl
1835
2433
  include EscapeEnhancer
1836
2434
  end
@@ -1841,12 +2439,23 @@ module Erubis
1841
2439
  #end
1842
2440
 
1843
2441
 
2442
+ class PI::Eperl < PI::Engine
2443
+ include PerlGenerator
2444
+
2445
+ def init_converter(properties={})
2446
+ @pi = 'perl'
2447
+ super(properties)
2448
+ end
2449
+
2450
+ end
2451
+
2452
+
1844
2453
  end
1845
2454
  #--end of require 'erubis/engine/eperl'
1846
2455
  #--begin of require 'erubis/engine/ejavascript'
1847
2456
  ##
1848
- ## $Rev: 24 $
1849
- ## $Release: 2.0.1 $
2457
+ ## $Rev: 31 $
2458
+ ## $Release: 2.1.0 $
1850
2459
  ## copyright(c) 2006 kuwata-lab all rights reserved.
1851
2460
  ##
1852
2461
 
@@ -1857,23 +2466,21 @@ end
1857
2466
  module Erubis
1858
2467
 
1859
2468
 
1860
- ##
1861
- ## engine for JavaScript
1862
- ##
1863
- class Ejavascript < Engine
2469
+ module JavascriptGenerator
2470
+ include Generator
1864
2471
 
1865
2472
  def self.supported_properties() # :nodoc:
1866
- list = super
2473
+ list = []
1867
2474
  #list << [:indent, '', "indent spaces (ex. ' ')"]
1868
2475
  #list << [:buf, '_buf', "output buffer name"]
1869
2476
  return list
1870
2477
  end
1871
2478
 
1872
- def initialize(input, properties={})
2479
+ def init_generator(properties={})
2480
+ super
2481
+ @escapefunc ||= 'escape'
1873
2482
  @indent = properties[:indent] || ''
1874
2483
  @buf = properties[:out] || '_buf'
1875
- #@bufclass = properties[:outclass] || 'StringBuffer'
1876
- super
1877
2484
  end
1878
2485
 
1879
2486
  def add_preamble(src)
@@ -1885,11 +2492,6 @@ module Erubis
1885
2492
  return text.gsub!(/[\r\n\t"\\]/) { |m| @@table_[m] } || text
1886
2493
  end
1887
2494
 
1888
- def escaped_expr(code)
1889
- @escape ||= 'escape'
1890
- return "#{@escape}(#{code.strip})"
1891
- end
1892
-
1893
2495
  def add_indent(src, indent)
1894
2496
  src << (src.empty? || src[-1] == ?\n ? indent : ' ')
1895
2497
  end
@@ -1913,12 +2515,12 @@ module Erubis
1913
2515
 
1914
2516
  def add_expr_literal(src, code)
1915
2517
  add_indent(src, @indent)
1916
- src << @buf << '.push(' << code.strip << ');'
2518
+ code.strip!
2519
+ src << "#{@buf}.push(#{code});"
1917
2520
  end
1918
2521
 
1919
2522
  def add_expr_escaped(src, code)
1920
- add_indent(src, @indent)
1921
- src << @buf << '.push(' << escaped_expr(code) << ');'
2523
+ add_expr_literal(src, escaped_expr(code))
1922
2524
  end
1923
2525
 
1924
2526
  def add_expr_debug(src, code)
@@ -1935,6 +2537,14 @@ module Erubis
1935
2537
  end
1936
2538
 
1937
2539
 
2540
+ ##
2541
+ ## engine for JavaScript
2542
+ ##
2543
+ class Ejavascript < Basic::Engine
2544
+ include JavascriptGenerator
2545
+ end
2546
+
2547
+
1938
2548
  class EscapedEjavascript < Ejavascript
1939
2549
  include EscapeEnhancer
1940
2550
  end
@@ -1945,6 +2555,17 @@ module Erubis
1945
2555
  #end
1946
2556
 
1947
2557
 
2558
+ class PI::Ejavascript < PI::Engine
2559
+ include JavascriptGenerator
2560
+
2561
+ def init_converter(properties={})
2562
+ @pi = 'js'
2563
+ super(properties)
2564
+ end
2565
+
2566
+ end
2567
+
2568
+
1948
2569
  end
1949
2570
  #--end of require 'erubis/engine/ejavascript'
1950
2571
 
@@ -2043,15 +2664,15 @@ module Erubis
2043
2664
 
2044
2665
  ## action
2045
2666
  action = opts.action
2046
- action ||= 'compile' if opts.source
2667
+ action ||= 'convert' if opts.source
2047
2668
 
2048
2669
  ## lang
2049
2670
  lang = opts.lang || 'ruby'
2050
- action ||= 'compile' if opts.lang
2671
+ action ||= 'convert' if opts.lang
2051
2672
 
2052
2673
  ## class name of Eruby
2053
2674
  classname = opts.class
2054
- klass = get_classobj(classname, lang)
2675
+ klass = get_classobj(classname, lang, properties[:pi])
2055
2676
 
2056
2677
  ## kanji code
2057
2678
  $KCODE = opts.kanji if opts.kanji
@@ -2061,31 +2682,33 @@ module Erubis
2061
2682
  context = load_yamlfiles(yamlfiles, opts)
2062
2683
 
2063
2684
  ## properties for engine
2685
+ properties[:escape] = true if opts.escape && !properties.key?(:escape)
2064
2686
  properties[:pattern] = opts.pattern if opts.pattern
2065
2687
  properties[:trim] = false if opts.notrim
2066
2688
  properties[:preamble] = properties[:postamble] = false if opts.bodyonly
2689
+ properties[:pi] = nil if properties[:pi] == true
2067
2690
 
2068
2691
  ## create engine and extend enhancers
2069
2692
  engine = klass.new(nil, properties)
2070
2693
  enhancers = get_enhancers(opts.enhancers)
2071
- enhancers.push(Erubis::EscapeEnhancer) if opts.escape
2694
+ #enhancers.push(Erubis::EscapeEnhancer) if opts.escape
2072
2695
  enhancers.each do |enhancer|
2073
2696
  engine.extend(enhancer)
2074
2697
  engine.bipattern = properties[:bipattern] if enhancer == Erubis::BiPatternEnhancer
2075
2698
  end
2076
2699
 
2077
- ## compile and execute
2700
+ ## convert and execute
2078
2701
  val = nil
2079
2702
  if filenames && !filenames.empty?
2080
2703
  filenames.each do |filename|
2081
2704
  test(?f, filename) or raise CommandOptionError.new("#{filename}: file not found.")
2082
2705
  engine.filename = filename
2083
- engine.compile!(File.read(filename))
2706
+ engine.convert!(File.read(filename))
2084
2707
  print val if val = do_action(action, engine, context, opts)
2085
2708
  end
2086
2709
  else
2087
2710
  engine.filename = '(stdin)'
2088
- engine.compile!($stdin.read())
2711
+ engine.convert!($stdin.read())
2089
2712
  print val if val = do_action(action, engine, context, opts)
2090
2713
  end
2091
2714
 
@@ -2095,7 +2718,7 @@ module Erubis
2095
2718
 
2096
2719
  def do_action(action, engine, context, opts)
2097
2720
  case action
2098
- when 'compile'
2721
+ when 'convert'
2099
2722
  s = engine.src
2100
2723
  when nil, 'exec', 'execute'
2101
2724
  s = opts.binding ? engine.result(context) : engine.evaluate(context)
@@ -2107,42 +2730,61 @@ module Erubis
2107
2730
 
2108
2731
  def usage
2109
2732
  command = File.basename($0)
2110
- s = <<'END'
2111
- erubis - embedded program compiler for multi-language
2733
+ s = <<END
2734
+ erubis - embedded program converter for multi-language
2112
2735
  Usage: #{command} [..options..] [file ...]
2113
2736
  -h, --help : help
2114
2737
  -v : version
2115
- -x : compiled code
2738
+ -x : converted code
2116
2739
  -T : don't trim spaces around '<% %>'
2117
2740
  -b : body only (no preamble nor postamble)
2118
2741
  -e : escape (equal to '--E Escape')
2119
2742
  -p pattern : embedded pattern (default '<% %>')
2120
- -l lang : compile but no execute (ruby/php/c/java/scheme/perl/js)
2121
- -E enhancer,... : enhancer name (Escape, PercentLine, BiPattern, ...)
2743
+ -l lang : convert but no execute (ruby/php/c/java/scheme/perl/js)
2744
+ -E e1,e2,... : enhancer names (Escape, PercentLine, BiPattern, ...)
2122
2745
  -I path : library include path
2123
2746
  -K kanji : kanji code (euc/sjis/utf8) (default none)
2124
2747
  -f file.yaml : YAML file for context values (read stdin if filename is '-')
2125
2748
  -t : expand tab character in YAML file
2126
2749
  -S : convert mapping key from string to symbol in YAML file
2127
2750
  -B : invoke 'result(binding)' instead of 'evaluate(context)'
2751
+ --pi=name : parse '<?name ... ?>' instead of '<% ... %>'
2128
2752
 
2129
2753
  END
2754
+ #'
2130
2755
  # -c class : class name (XmlEruby/PercentLineEruby/...) (default Eruby)
2131
2756
  # -r library : require library
2132
- # -a : action (compile/execute)
2757
+ # -a : action (convert/execute)
2133
2758
  return s
2134
2759
  end
2135
2760
 
2761
+
2762
+ def collect_supported_properties(erubis_klass)
2763
+ list = []
2764
+ erubis_klass.ancestors.each do |klass|
2765
+ if klass.respond_to?(:supported_properties)
2766
+ list.concat(klass.supported_properties)
2767
+ end
2768
+ end
2769
+ return list
2770
+ end
2771
+
2136
2772
  def show_properties
2137
2773
  s = "supported properties:\n"
2138
- %w[(common) ruby php c java scheme perl javascript].each do |lang|
2139
- list = Erubis::Engine.supported_properties
2140
- if lang != '(common)'
2141
- klass = Erubis.const_get("E#{lang}")
2142
- list = klass.supported_properties - list
2143
- end
2774
+ basic_props = collect_supported_properties(Erubis::Basic::Engine)
2775
+ pi_props = collect_supported_properties(Erubis::PI::Engine)
2776
+ list = []
2777
+ common_props = basic_props & pi_props
2778
+ list << ['(common)', common_props]
2779
+ list << ['(basic)', basic_props - common_props]
2780
+ list << ['(pi)', pi_props - common_props]
2781
+ %w[ruby php c java scheme perl javascript].each do |lang|
2782
+ klass = Erubis.const_get("E#{lang}")
2783
+ list << [lang, collect_supported_properties(klass) - basic_props]
2784
+ end
2785
+ list.each do |lang, props|
2144
2786
  s << " * #{lang}\n"
2145
- list.each do |name, default_val, desc|
2787
+ props.each do |name, default_val, desc|
2146
2788
  s << (" --%-23s : %s\n" % ["#{name}=#{default_val.inspect}", desc])
2147
2789
  end
2148
2790
  end
@@ -2164,7 +2806,7 @@ END
2164
2806
  end
2165
2807
 
2166
2808
  def version
2167
- release = ('$Release: 2.0.1 $' =~ /([.\d]+)/) && $1
2809
+ release = ('$Release: 2.1.0 $' =~ /([.\d]+)/) && $1
2168
2810
  return release
2169
2811
  end
2170
2812
 
@@ -2214,27 +2856,42 @@ END
2214
2856
  return options, context
2215
2857
  end
2216
2858
 
2217
- def untabify(text, width=8)
2859
+
2860
+ def untabify(str, width=8)
2861
+ list = str.split(/\t/)
2862
+ last = list.pop
2218
2863
  sb = ''
2219
- text.scan(/(.*?)\t/m) do |s, |
2220
- len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
2221
- sb << s << (" " * (width - len % width))
2864
+ list.each do |s|
2865
+ column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
2866
+ n = width - (column % width)
2867
+ sb << s << (' ' * n)
2222
2868
  end
2223
- return $' ? (sb << $') : text
2869
+ sb << last
2870
+ return sb
2224
2871
  end
2872
+ #--
2873
+ #def untabify(str, width=8)
2874
+ # sb = ''
2875
+ # str.scan(/(.*?)\t/m) do |s, |
2876
+ # len = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
2877
+ # sb << s << (" " * (width - len % width))
2878
+ # end
2879
+ # return $' ? (sb << $') : str
2880
+ #end
2881
+ #++
2225
2882
 
2226
- def get_classobj(classname, lang)
2227
- unless classname
2228
- classname = lang =~ /\Axml(.*)/ ? "EscapedE#{$1}" : "E#{lang}"
2229
- end
2883
+
2884
+ def get_classobj(classname, lang, pi)
2885
+ classname ||= "E#{lang}"
2886
+ base_module = pi ? Erubis::PI : Erubis
2230
2887
  begin
2231
- klass = Erubis.const_get(classname)
2888
+ klass = base_module.const_get(classname)
2232
2889
  rescue NameError
2233
2890
  klass = nil
2234
2891
  end
2235
2892
  unless klass
2236
2893
  if lang
2237
- msg = "-l #{lang}: invalid language name (class Erubis::#{classname} not found)."
2894
+ msg = "-l #{lang}: invalid language name (class #{base_module.name}::#{classname} not found)."
2238
2895
  else
2239
2896
  msg = "-c #{classname}: invalid class name."
2240
2897
  end
@@ -2273,25 +2930,30 @@ END
2273
2930
  unless ydoc.is_a?(Hash)
2274
2931
  raise CommandOptionError.new("#{yamlfile}: root object is not a mapping.")
2275
2932
  end
2276
- convert_mapping_key_from_string_to_symbol(ydoc) if opts.intern
2933
+ intern_hash_keys(ydoc) if opts.intern
2277
2934
  hash.update(ydoc)
2278
2935
  end
2279
2936
  context = hash
2280
2937
  return context
2281
2938
  end
2282
2939
 
2283
- def convert_mapping_key_from_string_to_symbol(ydoc)
2284
- if ydoc.is_a?(Hash)
2285
- ydoc.each do |key, val|
2286
- ydoc[key.intern] = ydoc.delete(key) if key.is_a?(String)
2287
- convert_mapping_key_from_string_to_symbol(val)
2940
+ def intern_hash_keys(obj, done={})
2941
+ return if done.key?(obj.__id__)
2942
+ case obj
2943
+ when Hash
2944
+ done[obj.__id__] = obj
2945
+ obj.keys.each do |key|
2946
+ obj[key.intern] = obj.delete(key) if key.is_a?(String)
2947
+ end
2948
+ obj.values.each do |val|
2949
+ intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
2288
2950
  end
2289
- elsif ydoc.is_a?(Array)
2290
- ydoc.each do |val|
2291
- convert_mapping_key_from_string_to_symbol(val)
2951
+ when Array
2952
+ done[obj.__id__] = obj
2953
+ obj.each do |val|
2954
+ intern_hash_keys(val, done) if val.is_a?(Hash) || val.is_a?(Array)
2292
2955
  end
2293
2956
  end
2294
- return ydoc
2295
2957
  end
2296
2958
 
2297
2959
  end