erubis 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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