Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Import version 0.6.2 of rbTenjin

  • Loading branch information...
commit e882636eb39825b01ea337f46193465528a29c15 0 parents
Luis Hurtado authored
Showing with 18,447 additions and 0 deletions.
  1. +76 −0 CHANGES.txt
  2. +20 −0 MIT-LICENSE
  3. +56 −0 README.txt
  4. +502 −0 benchmark/bench.rb
  5. +17 −0 benchmark/bench_context.rb
  6. +141 −0 benchmark/bench_context.yaml
  7. +4 −0 benchmark/templates/_footer.html
  8. +52 −0 benchmark/templates/_header.html
  9. +29 −0 benchmark/templates/bench_eruby.rhtml
  10. +29 −0 benchmark/templates/bench_tenjin.rbhtml
  11. +454 −0 bin/rbtenjin
  12. +141 −0 doc-api/classes/Tenjin.html
  13. +270 −0 doc-api/classes/Tenjin/ArrayBufferTemplate.html
  14. +329 −0 doc-api/classes/Tenjin/BaseContext.html
  15. +126 −0 doc-api/classes/Tenjin/Context.html
  16. +461 −0 doc-api/classes/Tenjin/ContextHelper.html
  17. +616 −0 doc-api/classes/Tenjin/Engine.html
  18. +166 −0 doc-api/classes/Tenjin/ErubisTemplate.html
  19. +359 −0 doc-api/classes/Tenjin/HtmlHelper.html
  20. +242 −0 doc-api/classes/Tenjin/Preprocessor.html
  21. +916 −0 doc-api/classes/Tenjin/Template.html
  22. +1 −0  doc-api/created.rid
  23. +188 −0 doc-api/files/README_txt.html
  24. +136 −0 doc-api/files/lib/tenjin_rb.html
  25. +36 −0 doc-api/fr_class_index.html
  26. +28 −0 doc-api/fr_file_index.html
  27. +91 −0 doc-api/fr_method_index.html
  28. +24 −0 doc-api/index.html
  29. +208 −0 doc-api/rdoc-style.css
  30. +188 −0 doc/docstyle.css
  31. +312 −0 doc/examples.html
  32. +909 −0 doc/faq.html
  33. +1,734 −0 doc/users-guide.html
  34. +8 −0 examples/form/Makefile
  35. +11 −0 examples/form/Rakefile
  36. +4 −0 examples/form/create.rbhtml
  37. +14 −0 examples/form/form.rbhtml
  38. +8 −0 examples/form/layout.rbhtml
  39. +9 −0 examples/form/main.rb
  40. +4 −0 examples/form/update.rbhtml
  41. +11 −0 examples/preprocessing/Makefile
  42. +15 −0 examples/preprocessing/Rakefile
  43. +16 −0 examples/preprocessing/helper.rb
  44. +11 −0 examples/preprocessing/main.rb
  45. +15 −0 examples/preprocessing/select.rbhtml
  46. +17 −0 examples/preprocessing/select.rbhtml.cache
  47. +8 −0 examples/table/Makefile
  48. +11 −0 examples/table/Rakefile
  49. +9 −0 examples/table/table.rb
  50. +16 −0 examples/table/table.rbhtml
  51. +969 −0 lib/tenjin.rb
  52. +1,585 −0 setup.rb
  53. +62 −0 tenjin.gemspec
  54. +14 −0 test/Rookbook.yaml
  55. +45 −0 test/assert-text-equal.rb
  56. +4 −0 test/data/examples/form/create.rbhtml
  57. +14 −0 test/data/examples/form/form.rbhtml
  58. +8 −0 test/data/examples/form/layout.rbhtml
  59. +9 −0 test/data/examples/form/main.rb
  60. +21 −0 test/data/examples/form/main.result
  61. +4 −0 test/data/examples/form/update.rbhtml
  62. +16 −0 test/data/examples/preprocessing/helper.rb
  63. +11 −0 test/data/examples/preprocessing/main.rb
  64. +17 −0 test/data/examples/preprocessing/main.result
  65. +15 −0 test/data/examples/preprocessing/select.rbhtml
  66. +18 −0 test/data/examples/preprocessing/select_P.result
  67. +9 −0 test/data/examples/table/table.rb
  68. +16 −0 test/data/examples/table/table.rbhtml
  69. +20 −0 test/data/examples/table/table.result
  70. +18 −0 test/data/examples/table/table_s.result
  71. +5 −0 test/data/faq/ex1.rbhtml
  72. +27 −0 test/data/faq/ex10-baselayout.rbhtml
  73. +12 −0 test/data/faq/ex10-content.rbhtml
  74. +11 −0 test/data/faq/ex10-customlayout.rbhtml
  75. +25 −0 test/data/faq/ex10_inherit.result
  76. +28 −0 test/data/faq/ex11-bench.rb
  77. +9 −0 test/data/faq/ex11-content.rbhtml
  78. +5 −0 test/data/faq/ex11-layout1.rbhtml
  79. +6 −0 test/data/faq/ex11-layout2.rbhtml
  80. +5 −0 test/data/faq/ex11.rb
  81. +8 −0 test/data/faq/ex11.rbhtml
  82. +11 −0 test/data/faq/ex11.source
  83. +15 −0 test/data/faq/ex11_arraybuffer.result
  84. +3 −0  test/data/faq/ex1_chksyntax.result
  85. +3 −0  test/data/faq/ex2-content.rbhtml
  86. +11 −0 test/data/faq/ex2-layout.rbhtml
  87. +19 −0 test/data/faq/ex2_removenl.result
  88. +4 −0 test/data/faq/ex3.rb
  89. +1 −0  test/data/faq/ex3.rbhtml
  90. +2 −0  test/data/faq/ex3_escapefunc1.result
  91. +2 −0  test/data/faq/ex3_escapefunc2.result
  92. +7 −0 test/data/faq/ex5.rbhtml
  93. +9 −0 test/data/faq/ex5_template_args.source
  94. +6 −0 test/data/faq/ex6-content.rhtml
  95. +6 −0 test/data/faq/ex6-layout.rhtml
  96. +10 −0 test/data/faq/ex6.rb
  97. +12 −0 test/data/faq/ex6_eruby.result
  98. +34 −0 test/data/faq/ex7-expr-pattern.rb
  99. +3 −0  test/data/faq/ex7-expr-pattern.rbhtml
  100. +4 −0 test/data/faq/ex7_expr_pattern.result
  101. +77 −0 test/data/faq/ex8-m18n.rb
  102. +4 −0 test/data/faq/ex8-m18n.rbhtml
  103. +10 −0 test/data/faq/ex8_m18n.result
  104. +8 −0 test/data/faq/ex9-baselayout.rbhtml
  105. +6 −0 test/data/faq/ex9-content.rbhtml
  106. +5 −0 test/data/faq/ex9-mylayout.rbhtml
  107. +11 −0 test/data/faq/ex9_changelayout.result
  108. +3 −0  test/data/users_guide/content6.rbhtml
  109. +5 −0 test/data/users_guide/content7.rbhtml
  110. +2 −0  test/data/users_guide/content8.rbhtml
  111. +7 −0 test/data/users_guide/contextdata.rb
  112. +5 −0 test/data/users_guide/datafile.rb
  113. +10 −0 test/data/users_guide/datafile.yaml
  114. +6 −0 test/data/users_guide/ex.rbhtml
  115. +7 −0 test/data/users_guide/ex.result
  116. +5 −0 test/data/users_guide/ex.script
  117. +7 −0 test/data/users_guide/ex_script.result
  118. +8 −0 test/data/users_guide/ex_source.result
  119. +12 −0 test/data/users_guide/example1.rbhtml
  120. +17 −0 test/data/users_guide/example1.result
  121. +4 −0 test/data/users_guide/example10.rbhtml
  122. +6 −0 test/data/users_guide/example10_template_args.result
  123. +5 −0 test/data/users_guide/example11.rbhtml
  124. +2 −0  test/data/users_guide/example11_template_args_result
  125. +12 −0 test/data/users_guide/example12.rbhtml
  126. +10 −0 test/data/users_guide/example12_preprocessed.result
  127. +10 −0 test/data/users_guide/example12_preprocessed_source.result
  128. +6 −0 test/data/users_guide/example13.rbhtml
  129. +2 −0  test/data/users_guide/example13_preprocessed.result
  130. +2 −0  test/data/users_guide/example13_preprocessed_source.result
  131. +32 −0 test/data/users_guide/example14.rb
  132. +6 −0 test/data/users_guide/example14.rbhtml
  133. +15 −0 test/data/users_guide/example14_tmplclass.result
  134. +10 −0 test/data/users_guide/example15.rb
  135. +14 −0 test/data/users_guide/example15_escapefunc.result
  136. +4 −0 test/data/users_guide/example16.rbhtml
  137. +10 −0 test/data/users_guide/example16a.rb
  138. +4 −0 test/data/users_guide/example16a.result
  139. +13 −0 test/data/users_guide/example16b.rb
  140. +4 −0 test/data/users_guide/example16b.result
  141. +12 −0 test/data/users_guide/example16c.rb
  142. +4 −0 test/data/users_guide/example16c.result
  143. +27 −0 test/data/users_guide/example16d.rb
  144. +4 −0 test/data/users_guide/example16d.result
  145. +14 −0 test/data/users_guide/example1_S.result
  146. +10 −0 test/data/users_guide/example1_SXNC.result
  147. +14 −0 test/data/users_guide/example1_source.result
  148. +3 −0  test/data/users_guide/example2.rbhtml
  149. +9 −0 test/data/users_guide/example2_sb.result2
  150. +5 −0 test/data/users_guide/example3.rbhtml
  151. +2 −0  test/data/users_guide/example3_syntaxcheck.result
  152. +13 −0 test/data/users_guide/example4.rbhtml
  153. +13 −0 test/data/users_guide/example4_datafile_rb.result
  154. +13 −0 test/data/users_guide/example4_yaml.result
  155. +9 −0 test/data/users_guide/example5.rbhtml
  156. +9 −0 test/data/users_guide/example5_datastr_rb.result
  157. +9 −0 test/data/users_guide/example5_datastr_yaml.result
  158. +19 −0 test/data/users_guide/example6.rbhtml
  159. +29 −0 test/data/users_guide/example6_layout.result
  160. +28 −0 test/data/users_guide/example6_nested.result
  161. +13 −0 test/data/users_guide/example7_layout2.result
  162. +8 −0 test/data/users_guide/example8_layout3.result
  163. +18 −0 test/data/users_guide/example9.rbhtml
  164. +26 −0 test/data/users_guide/example9_capture.result
  165. +5 −0 test/data/users_guide/footer.html
  166. +4 −0 test/data/users_guide/footer.rbhtml
  167. +17 −0 test/data/users_guide/layout6.rbhtml
  168. +9 −0 test/data/users_guide/layout7.rbhtml
  169. +5 −0 test/data/users_guide/layout8_html.rbhtml
  170. +6 −0 test/data/users_guide/layout8_xhtml.rbhtml
  171. +25 −0 test/data/users_guide/layout9.rbhtml
  172. +5 −0 test/data/users_guide/sidemenu.rbhtml
  173. +39 −0 test/data/users_guide/user_app.cgi
  174. +30 −0 test/data/users_guide/user_app.result
  175. +6 −0 test/data/users_guide/user_create.rbhtml
  176. +7 −0 test/data/users_guide/user_edit.rbhtml
  177. +10 −0 test/data/users_guide/user_form.rbhtml
  178. +16 −0 test/data/users_guide/user_layout.rbhtml
  179. +23 −0 test/test_all.rb
  180. +495 −0 test/test_engine.rb
  181. +2,039 −0 test/test_engine.yaml
  182. +81 −0 test/test_examples.rb
  183. +60 −0 test/test_faq.rb
  184. +78 −0 test/test_htmlhelper.rb
  185. +748 −0 test/test_main.rb
  186. +174 −0 test/test_main.yaml
  187. +128 −0 test/test_template.rb
  188. +1,245 −0 test/test_template.yaml
  189. +75 −0 test/test_users_guide.rb
  190. +194 −0 test/testcase-helper.rb
76 CHANGES.txt
@@ -0,0 +1,76 @@
+=begin
+= CHANGES
+
+
+== Release 0.6.2 (2008-02-24)
+
+* Rubinius supported.
+
+* Changed to convert texts before expressions into spaces when
+ command-line option '-S' specified.
+
+ ex. hoge.rbhtml
+ <?rb for item in @list ?>
+ <p>${item}</p>
+ <?rb end ?>
+
+ ex. result of '-S'
+ ## 0.6.1
+ $ rbtenjin -S hoge.rbhtml
+ _buf = ''; for item in @list
+ escape((item).to_s);
+ end
+ _buf.to_s
+
+ ## 0.6.2
+ $ rbtenjin -S hoge.rbhtml
+ _buf = ''; for item in @list
+ escape((item).to_s);
+ end
+ _buf.to_s
+
+
+
+== Release 0.6.1 (2007-02-07)
+
+=== Enhancements
+
+* It is able to make any class which includes
+ Tenjin::ContextHelper module as context object class.
+ This is useful if you want to define helper functions
+ as instance method of that class.
+ See section 'Add Your Helper Functions' for details.
+ http://www.kuwata-lab.com/tenjin/rbtenjin-users-guide.html#dev-helpers
+
+ ex.
+ require 'tenjin'
+
+ class MyClass
+ include Tenjin::ContextHelper
+ #include Tenjin::HtmlHelper # optional
+
+ ## define helper functions in current class
+ def link_to(label, url)
+ return "<a href=\"#{escape(url)}\">#{escape(label)}</a>"
+ end
+
+ def render_template(template_name)
+ engine = Tenjin::Engine.new()
+ ## pass self as context object
+ output = engine.render(template_name, self)
+ return output
+ end
+
+ def main
+ ## set context data as instance variables
+ @label = 'Top'
+ @url = '/'
+ output = render_template('example.rbhtml')
+ print output
+ end
+
+ end
+
+ MyClass.new.main()
+
+=end
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56 README.txt
@@ -0,0 +1,56 @@
+= README
+
+release:: 0.6.2
+copyright:: copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
+
+
+== About
+
+rbTenjin is a very fast and full-featured template engine.
+You can embed Ruby statements and expressions into your text file.
+rbTenjin converts it into Ruby program and evaluate it.
+
+
+== Features
+
+* Very fast (twice faster than eruby and three times faster than ERB)
+* Lightweight (only a file which contains about 1000 lines)
+* Not break HTML design because it uses XML Processing
+ Instructions (PI) as embedded notation for Python statements.
+* Secure because it supports escaping expression value by default.
+* Auto caching of converted Python code.
+* Nestable layout template
+* Inlucde other templates
+* Capture part of template
+* Load YAML file as context data
+* Preprocessing support
+
+See doc/*.html for details.
+
+
+== Installation
+
+* If you have installed RubyGems, just type <tt>gem install tenjin</tt>.
+
+ $ sudo gem install tenjin
+
+* Else download rbtenjin-0.6.2.tar.bz2 and just copy 'lib/tenjin.rb' and
+ 'bin/rbtenjin' into proper directory.
+
+ $ tar xjf rbtenjin-0.6.2.tar.bz2
+ $ cd rbtenjin-0.6.2/
+ $ sudo copy lib/tenjin.rb /usr/local/lib/ruby/1.8/site_ruby/1.8/
+ $ sudo copy bin/rbtenjin /usr/local/bin/
+
+rbTenjin is tested with Ruby 1.8.6 and Rubinius.
+
+
+== Attention
+
+rbTenjin is beta released. It means that API or specification may change
+in the future.
+
+
+== License
+
+MIT License
502 benchmark/bench.rb
@@ -0,0 +1,502 @@
+## parse options
+require 'optparse'
+optparser = OptionParser.new()
+options = {}
+['-h', '-p', '-n N', '-e', '-q', '-A', '-f file', '-m mode', '-x exclude'].each do |opt|
+ optparser.on(opt) { |val| options[opt[1].chr] = val }
+end
+begin
+ filenames = optparser.parse!(ARGV)
+rescue => ex
+ command = File.basename($0)
+ $stderr.puts "#{command}: #{ex.to_s}"
+ exit(1)
+end
+
+
+## defaults
+ntimes = 1000
+mode = 'class' # 'class' or 'hash'
+escape = options['e']
+targets = %w[eruby eruby-cache erb erb-cache erb-reuse erb-defmethod erubis erubis-cache erubis-reuse tenjin tenjin-nocache tenjin-reuse]
+#targets_all = targets + %w[tenjin-tmpl tenjin-defun tenjin-defun-reuse] + %w[eruby-convert erb-convert erubis-convert tenjin-convert]
+targets_all = targets + %w[tenjin-arrbuf tenjin-arrbuf-nocache tenjin-arrbuf-reuse]
+
+
+## help
+if options['h']
+ command = File.basename($0)
+ puts "Usage: ruby %s [-h] [-n N] [targets] " % command
+ puts " -h : help"
+ #puts " -p : print output"
+ puts " -n N : loop N times (default %d)" % ntimes
+ puts " -f file : context data file"
+ puts " -x exclude : excluded target name"
+ puts " -q : quiet mode"
+ puts " -m mode : 'class' or 'hash' (default '%s')" % mode
+ puts " -e : escape html"
+ exit(0)
+end
+
+
+## set parameters
+ntimes = options.fetch('n', ntimes).to_i
+mode = options.fetch('m', mode)
+$quiet = options['q']
+datafile = options['f']
+unless datafile
+ if mode == 'class'
+ datafile = 'bench_context.rb'
+ elsif mode == 'hash'
+ datafile = 'bench_context.yaml'
+ else
+ assert unreachable
+ end
+end
+if options['A']
+ targets = targets_all
+elsif filenames && !filenames.empty?
+ if filenames[0] =~ /^\/.*\/$/
+ regexp = eval filenames[0]
+ targets = targets_all.select { |t| t =~ regexp }
+ else
+ targets = filenames
+ end
+end
+exclude = options['x']
+targets.delete(exclude) if exclude
+
+
+## require libraries
+require 'erb'
+require 'tenjin'
+begin
+ require 'eruby'
+rescue LoadError
+ ERuby = nil
+end
+begin
+ require 'erubis'
+rescue LoadError
+ Erubis = nil
+end
+require 'cgi'
+include ERB::Util
+
+
+## context data
+if datafile =~ /\.rb$/
+ context = Tenjin::Context.new
+ context.instance_eval(File.read(datafile), datafile)
+elsif datafile =~ /\.ya?ml$/
+ require 'yaml'
+ ydoc = YAML.load_file(datafile)
+ context = Tenjin::Context.new(ydoc)
+end
+if escape
+ context[:list].each do |item|
+ if item.name =~ / /
+ item.name = "<#{item.name.gsub(/ /, '&')}>"
+ else
+ item.name = "\"#{item.name}\""
+ end
+ end
+end
+s = ''
+context.instance_variables.each do |varname|
+ name = varname[1..-1]
+ s << "#{name} = context[#{name.inspect}]\n"
+end
+bindobj = nil
+s << "bindobj = binding()\n"
+eval s
+#eval "puts '** title='+title\n" # error on 1.9
+#eval "puts '** title='+title\n", bindobj # ok
+
+
+## helper methods
+def msg(message)
+ unless $quiet
+ $stdout.write(message)
+ $stdout.flush()
+ end
+end
+
+
+def defun_code(rbcode)
+ return <<-END
+ def tmpl_tenjin_view()
+ _buf = ''
+ _tmpl_tenjin_view(_buf)
+ return _buf
+ end
+ def _tmpl_tenjin_view(_buf)
+#{rbcode}
+ end
+ END
+end
+
+
+def read_and_convert(filename, &block)
+ cachename = filename + '.cache'
+ if !test(?f, cachename) || File.mtime(cachename) < File.mtime(filename)
+ rbcode = yield(filename)
+ File.open(cachename, 'w') { |f| f.write(rbcode) }
+ else
+ rbcode = File.read(cachename)
+ end
+ return rbcode
+end
+
+
+## preparation
+#msg('----- start benchmark preparations.\n')
+#msg('----- end benchmark preparations.\n\n')
+
+
+## generate templates
+template_filenames = [
+ tmpl_eruby = 'bench_eruby.rhtml',
+ tmpl_erb = 'bench_erb.rhtml',
+ tmpl_erubis = 'bench_erubis.rhtml',
+ tmpl_tenjin = 'bench_tenjin.rbhtml',
+ tmpl_tenjin2 = 'bench_tenjin2.rbhtml',
+]
+header = File.read("templates/_header.html")
+footer = File.read("templates/_footer.html")
+template_filenames.uniq.each do |fname|
+ begin
+ body = File.read("templates/#{fname}")
+ rescue
+ if fname =~ /tenjin/
+ body = File.read("templates/#{tmpl_tenjin}")
+ else
+ body = File.read("templates/#{tmpl_eruby}")
+ body = body.gsub(/list/, '@list') if fname =~ /erubis/
+ end
+ end
+ ## item['key'] ==> item.key
+ if mode == 'class'
+ body.gsub!(/(\w+)\['(\w+)'\]/, '\1.\2')
+ end
+ ## escape
+ if escape
+ case fname
+ when /_eruby/
+ body.gsub!(/<%= (.*?) %>/, '<%= CGI.escapeHTML((\1).to_s) %>')
+ when /_erb/
+ body.gsub!(/<%= (.*?) %>/, '<%=h \1 %>')
+ when /_erubis/
+ body.gsub!(/<%= (.*?) %>/, '<%== \1 %>')
+ when /_tenjin/
+ body.gsub!(/\#\{(.*?)\}/, '${\1}')
+ end
+ end
+ #
+ s = header + body + footer
+ File.open(fname, 'w') { |f| f.write(s) }
+end
+
+
+
+## change benchmark library to use $stderr instead of $stdout
+require 'benchmark'
+module Benchmark
+ class Report
+ def print(*args)
+ $stderr.print(*args)
+ end
+ end
+ module_function
+ def print(*args)
+ $stderr.print(*args)
+ end
+end
+
+
+## open /dev/null
+$stdout = File.open('/dev/null', 'w')
+at_exit do
+ $stdout.close()
+end
+
+
+##
+def delete_caches()
+ Dir.glob('*.cache').each { |fname| File.unlink(fname) }
+end
+
+
+## do benchmark
+if options['p']
+ ntimes = 1
+end
+output = nil
+Benchmark.bm(20) do |job|
+
+ for target in targets
+ delete_caches()
+ GC.start()
+ case target
+
+ when 'eruby'
+ job.report(target) do
+ ntimes.times do
+ ERuby.import(tmpl_eruby)
+ end
+ end if ERuby
+
+ when 'eruby-cache'
+ job.report(target) do
+ ntimes.times do
+ rbcode = read_and_convert(tmpl_eruby) do |fname|
+ ERuby::Compiler.new.compile_string(File.read(fname))
+ end
+ eval rbcode, bindobj
+ end
+ end if ERuby
+
+ when 'eruby-convert'
+ s = File.read(tmpl_eruby)
+ job.report(target) do
+ ntimes.times do
+ compiler = ERuby::Compiler.new
+ output = compiler.compile_string(s)
+ end
+ end if ERuby
+
+ when 'erb'
+ job.report(target) do
+ ntimes.times do
+ erb = ERB.new(File.read(tmpl_erb))
+ output = erb.result(bindobj)
+ print output
+ end
+ end if ERB
+
+ when 'erb-cache'
+ job.report(target) do
+ ntimes.times do
+ rbcode = read_and_convert(tmpl_erb) do |fname|
+ ERB.new(File.read(fname)).src
+ end
+ output = eval rbcode, bindobj
+ print output
+ end
+ end if ERB
+
+ when 'erb-reuse'
+ job.report(target) do
+ erb = ERB.new(File.read(tmpl_erb))
+ ntimes.times do
+ output = erb.result(bindobj)
+ print output
+ end
+ end if ERB
+
+ when 'erb-defmethod'
+ job.report(target) do
+ erb = ERB.new(File.read(tmpl_erb))
+ class Dummy; end
+ erb.def_method(Dummy, 'render(list)')
+ dummy = Dummy.new
+ ntimes.times do
+ output = dummy.render(context[:list])
+ print output
+ end
+ end if ERB
+
+ when 'erb-convert'
+ s = File.read(tmpl_erb)
+ job.report(target) do
+ ntimes.times do
+ erb = ERB.new(s)
+ output = erb.src
+ end
+ end if ERB
+
+ when 'erubis'
+ job.report(target) do
+ ntimes.times do
+ eruby = Erubis::Eruby.new(File.read(tmpl_erubis))
+ #output = eruby.result(bindobj)
+ output = eruby.evaluate(context)
+ print output
+ end
+ end if Erubis
+
+ when 'erubis-cache'
+ job.report(target) do
+ ntimes.times do
+ erubis = Erubis::Eruby.load_file(tmpl_erubis)
+ #output = erubis.result(bindobj)
+ output = erubis.evaluate(context)
+ print output
+ end
+ end if Erubis
+
+ when 'erubis-reuse'
+ job.report(target) do
+ erubis = Erubis::Eruby.new(File.read(tmpl_erubis))
+ ntimes.times do
+ #output = erubis.result(bindobj)
+ output = erubis.evaluate(context)
+ print output
+ end
+ end if Erubis
+
+ when 'erubis-convert'
+ s = File.read(tmpl_erubis)
+ job.report(target) do
+ ntimes.times do
+ erubis = Erubis::Eruby.new()
+ output = erubis.convert(s)
+ end
+ end if Erubis
+
+ when 'tenjin-tmpl'
+ job.report(target) do
+ ntimes.times do
+ template = Tenjin::Template.new(tmpl_tenjin)
+ output = template.render(context)
+ print output
+ end
+ end if Tenjin
+
+ when 'tenjin-tmpl-reuse'
+ job.report(target) do
+ template = Tenjin::Template.new(tmpl_tenjin)
+ ntimes.times do
+ output = template.render(context)
+ print output
+ end
+ end if Tenjin
+
+ when 'tenjin'
+ job.report(target) do
+ ntimes.times do
+ engine = Tenjin::Engine.new(:cache=>true)
+ output = engine.render(tmpl_tenjin, context)
+ print output
+ end
+ end if Tenjin
+
+ when 'tenjin-nocache'
+ job.report(target) do
+ ntimes.times do
+ engine = Tenjin::Engine.new(:cache=>false)
+ output = engine.render(tmpl_tenjin, context)
+ print output
+ end
+ end if Tenjin
+
+ when 'tenjin-reuse'
+ job.report(target) do
+ engine = Tenjin::Engine.new()
+ ntimes.times do
+ output = engine.render(tmpl_tenjin, context)
+ print output
+ end
+ end if Tenjin
+
+ when 'tenjin-convert'
+ s = File.read(tmpl_tenjin)
+ job.report(target) do
+ ntimes.times do
+ tenjin = Tenjin::Template.new(:preamble=>true, :postamble=>true)
+ output = tenjin.convert(s)
+ end
+ end if Erubis
+
+ when 'tenjin-defun'
+ job.report(target) do
+ template = Tenjin::Template.new(tmpl_tenjin)
+ defun = defun_code(template.rbcode)
+ ntimes.times do
+ context.instance_eval(defun)
+ output = context.tmpl_tenjin_view()
+ print output
+ end
+ end if Tenjin
+
+ when 'tenjin-defun-reuse'
+ job.report(target) do
+ template = Tenjin::Template.new(tmpl_tenjin)
+ defun = defun_code(template.rbcode)
+ context.instance_eval(defun)
+ ntimes.times do
+ output = context.tmpl_tenjin_view()
+ print output
+ end
+ end if Tenjin
+
+ ##
+
+ when 'tenjin-arrbuftmpl'
+ job.report(target) do
+ ntimes.times do
+ template = Tenjin::ArrayBufferTemplate.new(tmpl_tenjin2)
+ output = template.render(context)
+ print output
+ end
+ end if Tenjin::ArrayBufferTemplate
+
+ when 'tenjin-arrbuftmpl-reuse'
+ job.report(target) do
+ template = Tenjin::ArrayBufferTemplate.new(tmpl_tenjin2)
+ ntimes.times do
+ output = template.render(context)
+ print output
+ end
+ end if Tenjin::ArrayBufferTemplate
+
+ when 'tenjin-arrbuf'
+ job.report(target) do
+ ntimes.times do
+ engine = Tenjin::Engine.new(:cache=>true, :templateclass=>Tenjin::ArrayBufferTemplate)
+ output = engine.render(tmpl_tenjin2, context)
+ print output
+ end
+ end if Tenjin::ArrayBufferTemplate
+
+ when 'tenjin-arrbuf-nocache'
+ job.report(target) do
+ ntimes.times do
+ engine = Tenjin::Engine.new(:cache=>false, :templateclass=>Tenjin::ArrayBufferTemplate)
+ output = engine.render(tmpl_tenjin2, context)
+ print output
+ end
+ end if Tenjin::ArrayBufferTemplate
+
+ when 'tenjin-arrbuf-reuse'
+ job.report(target) do
+ engine = Tenjin::Engine.new(:templateclass=>Tenjin::ArrayBufferTemplate)
+ ntimes.times do
+ output = engine.render(tmpl_tenjin2, context)
+ print output
+ end
+ end if Tenjin::ArrayBufferTemplate
+
+ when 'tenjin-arrbuf-convert'
+ s = File.read(tmpl_tenjin2)
+ job.report(target) do
+ ntimes.times do
+ tenjin = Tenjin::ArrayBufferTemplate.new(:preamble=>true, :postamble=>true)
+ output = tenjin.convert(s)
+ end
+ end if Erubis
+
+ else
+ $stderr.puts("*** %s: invalid target.\n" % target)
+ exit(1)
+ end
+
+ if options['p']
+ File.open('%s.result' % target, 'w') { |f| f.write(output) } unless target =~ /^eruby/ && target !~ /-convert$/
+ puts 'created: %s.result' % target
+ #next
+ end
+
+ end
+
+end
17 benchmark/bench_context.rb
@@ -0,0 +1,17 @@
+require 'yaml'
+
+class StockInfo
+ def initialize(values={})
+ @name = values['name']
+ @name2 = values['name2']
+ @url = values['url']
+ @symbol = values['symbol']
+ @price = values['price']
+ @change = values['change']
+ @ratio = values['ratio']
+ end
+ attr_accessor :name, :name2, :url, :symbol, :price, :change, :ratio
+end
+
+ydoc = YAML.load_file('bench_context.yaml')
+@list = ydoc['list'].collect { |values| StockInfo.new(values) }
141 benchmark/bench_context.yaml
@@ -0,0 +1,141 @@
+list:
+ - name: Adobe Systems
+ name2: Adobe Systems Inc.
+ url: http://www.adobe.com
+ symbol: ADBE
+ price: 39.26
+ change: 0.13
+ ratio: 0.33
+ - name: Advanced Micro Devices
+ name2: Advanced Micro Devices Inc.
+ url: http://www.amd.com
+ symbol: AMD
+ price: 16.22
+ change: 0.17
+ ratio: 1.06
+ - name: Amazon.com
+ name2: Amazon.com Inc
+ url: http://www.amazon.com
+ symbol: AMZN
+ price: 36.85
+ change: -0.23
+ ratio: -0.62
+ - name: Apple
+ name2: Apple Inc.
+ url: http://www.apple.com
+ symbol: AAPL
+ price: 85.38
+ change: -0.87
+ ratio: -1.01
+ - name: BEA Systems
+ name2: BEA Systems Inc.
+ url: http://www.bea.com
+ symbol: BEAS
+ price: 12.46
+ change: 0.09
+ ratio: 0.73
+ - name: CA
+ name2: CA, Inc.
+ url: http://www.ca.com
+ symbol: CA
+ price: 24.66
+ change: 0.38
+ ratio: 1.57
+ - name: Cisco Systems
+ name2: Cisco Systems Inc.
+ url: http://www.cisco.com
+ symbol: CSCO
+ price: 26.35
+ change: 0.13
+ ratio: 0.5
+ - name: Dell
+ name2: Dell Corp.
+ url: http://www.dell.com/
+ symbol: DELL
+ price: 23.73
+ change: -0.42
+ ratio: -1.74
+ - name: eBay
+ name2: eBay Inc.
+ url: http://www.ebay.com
+ symbol: EBAY
+ price: 31.65
+ change: -0.8
+ ratio: -2.47
+ - name: Google
+ name2: Google Inc.
+ url: http://www.google.com
+ symbol: GOOG
+ price: 495.84
+ change: 7.75
+ ratio: 1.59
+ - name: Hewlett-Packard
+ name2: Hewlett-Packard Co.
+ url: http://www.hp.com
+ symbol: HPQ
+ price: 41.69
+ change: -0.02
+ ratio: -0.05
+ - name: IBM
+ name2: International Business Machines Corp.
+ url: http://www.ibm.com
+ symbol: IBM
+ price: 97.45
+ change: -0.06
+ ratio: -0.06
+ - name: Intel
+ name2: Intel Corp.
+ url: http://www.intel.com
+ symbol: INTC
+ price: 20.53
+ change: -0.07
+ ratio: -0.34
+ - name: Juniper Networks
+ name2: Juniper Networks, Inc
+ url: http://www.juniper.net/
+ symbol: JNPR
+ price: 18.96
+ change: 0.5
+ ratio: 2.71
+ - name: Microsoft
+ name2: Microsoft Corp
+ url: http://www.microsoft.com
+ symbol: MSFT
+ price: 30.6
+ change: 0.15
+ ratio: 0.49
+ - name: Oracle
+ name2: Oracle Corp.
+ url: http://www.oracle.com
+ symbol: ORCL
+ price: 17.15
+ change: 0.17
+ ratio: 1.0
+ - name: SAP
+ name2: SAP AG
+ url: http://www.sap.com
+ symbol: SAP
+ price: 46.2
+ change: -0.16
+ ratio: -0.35
+ - name: Seagate Technology
+ name2: Seagate Technology
+ url: http://www.seagate.com/
+ symbol: STX
+ price: 27.35
+ change: -0.36
+ ratio: -1.3
+ - name: Sun Microsystems
+ name2: Sun Microsystems Inc.
+ url: http://www.sun.com
+ symbol: SUNW
+ price: 6.33
+ change: -0.01
+ ratio: -0.16
+ - name: Yahoo
+ name2: Yahoo! Inc.
+ url: http://www.yahoo.com
+ symbol: YHOO
+ price: 28.04
+ change: -0.17
+ ratio: -0.6
4 benchmark/templates/_footer.html
@@ -0,0 +1,4 @@
+ </table>
+
+ </body>
+</html>
52 benchmark/templates/_header.html
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Stock Prices</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Style-Type" content="text/css" />
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
+ <link rel="shortcut icon" href="/images/favicon.ico" />
+ <link rel="stylesheet" type="text/css" href="/css/style.css" media="all" />
+ <script type="text/javascript" src="/js/util.js"></script>
+ <style type="text/css">
+ /*<![CDATA[*/
+
+body {
+ color: #333333;
+ line-height: 150%;
+}
+
+thead {
+ font-weight: bold;
+ background-color: #CCCCCC;
+}
+
+.odd {
+ background-color: #FFCCCC;
+}
+
+.even {
+ background-color: #CCCCFF;
+}
+
+.minus {
+ color: #FF0000;
+}
+
+ /*]]>*/
+ </style>
+
+ </head>
+
+ <body>
+
+ <h1>Stock Prices</h1>
+
+ <table>
+ <thead>
+ <tr>
+ <th>#</th><th>symbol</th><th>name</th><th>price</th><th>change</th><th>ratio</th>
+ </tr>
+ </thead>
29 benchmark/templates/bench_eruby.rhtml
@@ -0,0 +1,29 @@
+ <tbody>
+<%
+n = 0
+for item in list
+ n += 1
+ %>
+ <tr class="<%= n % 2 == 0 ? 'even' : 'odd' %>">
+ <td style="text-align: center"><%= n %></td>
+ <td>
+ <a href="/stocks/<%= item['symbol'] %>"><%= item['symbol'] %></a>
+ </td>
+ <td>
+ <a href="<%= item['url'] %>"><%= item['name'] %></a>
+ </td>
+ <td>
+ <strong><%= item['price'] %></strong>
+ </td>
+<% if item['change'] < 0.0 %>
+ <td class="minus"><%= item['change'] %></td>
+ <td class="minus"><%= item['ratio'] %></td>
+<% else %>
+ <td><%= item['change'] %></td>
+ <td><%= item['ratio'] %></td>
+<% end %>
+ </tr>
+<%
+end
+ %>
+ </tbody>
29 benchmark/templates/bench_tenjin.rbhtml
@@ -0,0 +1,29 @@
+ <tbody>
+<?rb
+n = 0
+for item in @list
+ n += 1
+ ?>
+ <tr class="#{n % 2 == 0 ? 'even' : 'odd'}">
+ <td style="text-align: center">#{n}</td>
+ <td>
+ <a href="/stocks/#{item['symbol']}">#{item['symbol']}</a>
+ </td>
+ <td>
+ <a href="#{item['url']}">#{item['name']}</a>
+ </td>
+ <td>
+ <strong>#{item['price']}</strong>
+ </td>
+<?rb if item['change'] < 0.0 ?>
+ <td class="minus">#{item['change']}</td>
+ <td class="minus">#{item['ratio']}</td>
+<?rb else ?>
+ <td>#{item['change']}</td>
+ <td>#{item['ratio']}</td>
+<?rb end ?>
+ </tr>
+<?rb
+end
+ ?>
+ </tbody>
454 bin/rbtenjin
@@ -0,0 +1,454 @@
+#!/usr/bin/env ruby
+
+##
+## copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
+##
+## Permission is hereby granted, free of charge, to any person obtaining
+## a copy of this software and associated documentation files (the
+## "Software"), to deal in the Software without restriction, including
+## without limitation the rights to use, copy, modify, merge, publish,
+## distribute, sublicense, and/or sell copies of the Software, and to
+## permit persons to whom the Software is furnished to do so, subject to
+## the following conditions:
+##
+## The above copyright notice and this permission notice shall be
+## included in all copies or substantial portions of the Software.
+##
+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+## OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+## WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+##
+
+## $Rev: 70 $
+## $Release: 0.6.2 $
+
+require 'tenjin'
+
+module Tenjin
+
+
+ module NoTextModule
+
+ def initialize(*args)
+ @noexpr = args[-1].is_a?(Hash) ? args[-1].delete(:noexpr) : nil
+ super
+ end
+
+ def start_text_part()
+ nil
+ end
+
+ def stop_text_part()
+ nil
+ end
+
+ def add_text(text, encode_newline=false)
+ return unless text && !text.empty?
+ n = text.count("\n")
+ n -= 1 if encode_newline && text[-1] == ?\n
+ @script << (@newline * n)
+ if text[-1] != ?\n
+ pos = text.rindex(?\n)
+ s = pos ? text[(pos+1)..-1] : text
+ @script << s.gsub(/[^\t]/, ' ')
+ end
+ end
+
+ ## add expression code
+ def add_expr(code, flag_escape=nil)
+ return if !code || code.empty?
+ if @noexpr
+ @script << (@newline * code.count("\n"))
+ elsif flag_escape
+ #@script << "_buf << %Q`\#{#{@escapefunc}((#{code}).to_s)}`"
+ @script << "#{@escapefunc}((#{code}).to_s); "
+ else
+ #@script << "_buf << %Q`\#{#{code}}`"
+ @script << "#{code}; "
+ end
+ end
+
+ end
+
+
+ class NoTextTemplate < Template
+ include NoTextModule
+ end
+
+
+ class CommandOptionError < StandardError
+ end
+
+
+ class Main
+
+
+ def self.main()
+ begin
+ output = self.new().execute()
+ print output if output
+ exit(0)
+ rescue CommandOptionError => ex
+ $stderr.puts ex.message
+ exit(1)
+ end
+ end
+
+
+ def initialize(argv=nil)
+ @command = File.basename($0)
+ @argv = argv || ARGV
+ end
+
+
+ def execute()
+ command = @command
+
+ ## parse options
+ noargopts = 'hvsSNXCUbxzqwTPdD'
+ argopts = 'fckra'
+ argopts2 = ''
+ command = File.basename($0)
+ options, properties, filenames = parse_argv(@argv, noargopts, argopts, argopts2)
+ debug = options[:D]
+ debug and $stderr.puts "*** debug: options=#{options.inspect}"
+ debug and $stderr.puts "*** debug: properties=#{properties.inspect}"
+ debug and $stderr.puts "*** debug: filenames=#{filenames.inspect}"
+
+ ## help, version
+ return usage() if options[:h] || properties[:help]
+ return version()+"\n" if options[:v] || properties[:version]
+
+ ## check options
+ datafile = options[:f]
+ if datafile && !test(?f, datafile)
+ raise _error("-f %s: file not found." % datafile)
+ end
+
+ ## action
+ action = options[:a]
+ actions = %w[render convert retrieve statements syntax dump preprocess]
+ if action
+ unless actions.include?(action)
+ raise _error("-a #{action}: unknown action.")
+ end
+ action = action.intern
+ else
+ action = options[:s] && :convert ||
+ options[:X] && :statements ||
+ options[:S] && :retrieve ||
+ options[:z] && :syntax ||
+ options[:P] && :preprocess ||
+ true && :render
+ end
+
+ ## ruby global options
+ $KCODE = options[:k] if options[:k]
+ $VERBOSE = 2 if options[:w]
+
+ ## lib
+ if options[:r]
+ begin
+ for lib in options[:r].split(/,/)
+ require lib
+ end
+ rescue LoadError => ex
+ raise _error("-r %s: library not found." % lib)
+ end
+ end
+
+ ## context data file
+ context = Tenjin::Context.new
+ if options[:f]
+ datafile = options[:f]
+ content = File.read(datafile)
+ if datafile =~ /\.ya?ml\z/
+ content = _expandtabs(content) unless options[:T]
+ hash = load_yaml(content, datafile)
+ context.update(hash)
+ elsif datafile =~ /\.rb\z/
+ load_rubycode_as_contextdata(content, context, datafile)
+ else
+ raise _error("-f %s: unknown file type ('*.yaml' or '*.rb' expected)." % datafile)
+ end
+ end
+
+ ## context data
+ if options[:c]
+ if options[:c][0] == ?{
+ yamlstr = options[:c]
+ hash = load_yaml(yamlstr, '-c')
+ context.update(hash)
+ else
+ ruby_code = options[:c]
+ load_rubycode_as_contextdata(ruby_code, context, '-c')
+ end
+ end
+
+ ## set initalizer option for Tenjin::Template.new()
+ if options[:b]
+ properties[:preamble] = properties[:postamble] = nil
+ elsif action == :convert || action == :retrieve || action == :statements
+ properties[:preamble] = true unless properties.key?(:preamble)
+ properties[:postamble] = true unless properties.key?(:postamble)
+ end
+
+ ## set initalizer option for Tenjin::Engine.new()
+ properties[:cache] = false unless properties.key?(:cache)
+ properties[:path] = properties[:path].split(/,/) if properties[:path]
+ if properties.key?(:templateclass)
+ classname = properties[:templateclass]
+ klass = _to_class(classname)
+ properties[:templateclass] = klass
+ elsif action == :preprocess || options[:P]
+ properties[:templateclass] = Tenjin::Preprocessor
+ properties[:preprocess] = false
+ elsif action == :retrieve
+ properties[:templateclass] = Tenjin::NoTextTemplate
+ elsif action == :statements
+ properties[:templateclass] = Tenjin::NoTextTemplate
+ properties[:noexpr] = true
+ end
+
+ ## create Engine instance
+ engine = Tenjin::Engine.new(properties)
+
+ ## execute
+ filenames = [nil] if filenames.empty?
+ output_buf = ''
+ for template_name in filenames
+ if template_name.nil?
+ input = $stdin.read()
+ template_class = properties.fetch(:templateclass, Tenjin::Template)
+ template = template_class.new(properties)
+ engine.register_template(template_name, template)
+ end
+ case action
+ when :convert, :retrieve, :statements
+ template = engine.get_template(template_name)
+ output = template.script
+ when :syntax
+ template = engine.get_template(template_name)
+ output = check_syntax(template.script, template.filename, options[:q], options[:w])
+ when :render, :preprocess
+ output = engine.render(template_name, context)
+ else
+ assert unreachable
+ end
+ output_buf << manipulate_output(output, options)
+ end
+ return output_buf
+ end
+
+
+ def check_syntax(script, filename, quiet, warning)
+ command = warning ? "ruby -wc" : "ruby -c"
+ require 'open3'
+ stdin, stdout, stderr = *Open3.popen3(command)
+ stdin.write(script) ; stdin.close()
+ result = stdout.read() ; stdout.close()
+ errmsg = stderr.read() ; stderr.close()
+ if errmsg && !errmsg.empty?
+ errmsg.gsub!(/^-(:\d+: )/, "#{filename}\\1")
+ return errmsg
+ else
+ return quiet ? '' : "#{filename}: #{result}"
+ end
+ end
+
+
+ def manipulate_output(output, options)
+ flag_linenum = options[:N] # add line numbers
+ flag_compact = options[:C] # remove empty lines
+ flag_unique = options[:U] # compress empty lines to a line
+ if flag_linenum
+ n = 0
+ output.gsub!(/^/) { n += 1; "%5d: " % n }
+ output.gsub!(/^ *\d+:\s+?\n/, '') if flag_compact
+ output.gsub!(/(^ *\d+:\s+?\n)+/, "\n") if flag_unique
+ else
+ output.gsub!(/^\s*?\n/, '') if flag_compact
+ output.gsub!(/(^\s*?\n)+/, "\n") if flag_unique
+ end
+ return output
+ end
+
+
+ def load_yaml(yamlstr, filename)
+ require 'yaml'
+ hash = YAML.load(yamlstr)
+ unless hash.is_a?(Hash)
+ raise _error("%s: not a mapping (hash)." % filename)
+ end
+ return hash
+ end
+
+
+ def load_rubycode_as_contextdata(_rubycode, _context, _filename)
+ _context.instance_eval(_rubycode, _filename)
+ end
+
+
+ def usage(command=nil)
+ command ||= @command
+ s = <<"END"
+Usage: #{command} [..options..] [file1 [file2...]]
+ -h, --help : help
+ -v, --version : version
+ -a action : action
+ -a render : render template (default)
+ -a convert : convert template into script
+ -a retrieve : retrieve statements and expressons
+ -a statements : retrieve only statements
+ -a syntax : syntax check
+ -a preprocess : show preprocessed template
+ -s : alias of '-a convert'
+ -S : alias of '-a retrieve'
+ -z : alias of '-a syntax'
+ -X : alias of '-a statements'
+# -d : alias of '-a dump'
+ -P : alias of '-a preprocess'
+ -N : add line number
+ -C : compact: remove empty lines
+ -U : uniq: compress empty lines into a line
+ -b : remove "_buf='';" and "_buf.to_s"
+ -q : quet mode (for '-a syntax')
+# -w : use strict package
+ -c string : context data string (yaml or ruby)
+ -f file : context data file (*.yaml or *.rb)
+ -T : unexpand tab chars in datafile
+ -r lib1,lib2,.. : require libraries
+ -k code : kanji code for $KCODE
+# --encoding=encoding : encoding name, with converting into unicode
+ --escapefunc=name : 'escape' function name
+# --tostrfunc=name : 'to_str' function name
+ --preamble=text : preamble which is insreted into ruby script
+ --postamble=text : postamble which is insreted into ruby script
+# --smarttrim : trim "\\n{expr}\\n" into "\\n{expr}".
+ --prefix=str : prefix string for template shortname
+ --postfix=str : postfix string for template shortname
+ --layout=filename : layout template name
+ --path=dir1,dir2,.. : template lookup path
+ --preprocess : activate preprocessing
+ --templateclass=name: template class (default: Tenjin::Template)
+Examples:
+ ex1. render template
+ $ #{command} file.rbhtml
+ ex2. convert template into ruby script
+ $ #{command} -a convert file.rbhtml
+ $ #{command} -a retrieve -UN file.rbhtml # for debug
+ ex3. render with context data file (*.yaml or *.rb)
+ $ #{command} -f datafile.yaml file.rbhtml
+ ex4. render with context data string
+ $ #{command} -c '{title: tenjin example, items: [1, 2, 3]}' file.rbhtml # yaml
+ $ #{command} -c '@title="tenjin example"; @items=[1,2,3]' file.rbhtml # ruby
+ ex5. syntax check
+ $ #{command} -wa syntax *.rbhtml # or '-wz'
+END
+ return s.gsub(/^\#.*\n/, '')
+ end
+
+
+ def version()
+ return RELEASE
+ end
+
+
+ def parse_argv(argv, noargopts, argopts, argopts2='')
+ options = {}
+ properties = {}
+ while argv[0] && argv[0][0] == ?-
+ optstr = argv.shift
+ if optstr == '-'
+ break
+ elsif optstr =~ /\A--([-\w]+)(=.*)?/
+ name = $1
+ value = $2 && !$2.empty? ? _to_value($2[1..-1]) : true
+ properties[name.intern] = value
+ else
+ optstr = optstr[1..-1]
+ while !optstr.empty?
+ ch = optstr[0].chr
+ optstr = optstr[1..-1]
+ if noargopts.include?(ch)
+ options[ch.intern] = true
+ elsif argopts.include?(ch)
+ if !optstr.empty?
+ options[ch.intern] = optstr
+ optstr = ''
+ elsif !argv.empty?
+ options[ch.intern] = argv.shift
+ else
+ raise _error("-#{ch}: argument required.")
+ end
+ elsif argopts2.include?(ch)
+ options[ch.intern] = !optstr.empty? ? optstr : true
+ optstr = ''
+ else
+ raise _error("-#{ch}: unknown option.")
+ end
+ end
+ end
+ end
+ filenames = argv
+ return options, properties, filenames
+ end
+
+
+ def _to_value(s)
+ case s
+ when 'true', 'yes' ; return true
+ when 'false', 'no' ; return false
+ when 'null', 'nil' ; return nil
+ when /\A\d+\z/ ; return s.to_i
+ when /\A\d+\.\d+\z/ ; return s.to_f
+ when /\A:[-\w]+\z/ ; return s[1..-1].intern
+ else ; return s
+ end
+ end
+
+
+ def _to_class(classname)
+ klass = Object
+ begin
+ classname.split(/::/).each { |m| klass = klass.const_get(m) }
+ rescue NameError => ex
+ raise _error("%s: class not found." % classname)
+ end
+ return klass
+ end
+
+
+ def _error(message)
+ return CommandOptionError.new(message)
+ end
+
+
+ def _expandtabs(input, width=8)
+ arr = input.split(/\t/)
+ last = arr.pop
+ buf = ''
+ arr.each do |s|
+ column = (n = s.rindex(?\n)) ? s.length - n - 1 : s.length
+ n = width - (column % width)
+ buf << s << (' ' * n)
+ end
+ buf << last
+ return buf
+ end
+
+
+ end
+
+
+end
+
+
+#if __FILE__ == $0
+unless defined?(DONT_INVOKE)
+ Tenjin::Main.main()
+end
141 doc-api/classes/Tenjin.html
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Module: Tenjin</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
+ <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
+ <script type="text/javascript">
+ // <![CDATA[
+
+ function popupCode( url ) {
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+ }
+
+ function toggleCode( id ) {
+ if ( document.getElementById )
+ elem = document.getElementById( id );
+ else if ( document.all )
+ elem = eval( "document.all." + id );
+ else
+ return false;
+
+ elemStyle = elem.style;
+
+ if ( elemStyle.display != "block" ) {
+ elemStyle.display = "block"
+ } else {
+ elemStyle.display = "none"
+ }
+
+ return true;
+ }
+
+ // Make codeblocks hidden by default
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+
+ // ]]>
+ </script>
+
+</head>
+<body>
+
+
+
+ <div id="classHeader">
+ <table class="header-table">
+ <tr class="top-aligned-row">
+ <td><strong>Module</strong></td>
+ <td class="class-name-in-header">Tenjin</td>
+ </tr>
+ <tr class="top-aligned-row">
+ <td><strong>In:</strong></td>
+ <td>
+ <a href="../files/lib/tenjin_rb.html">
+ lib/tenjin.rb
+ </a>
+ <br />
+ </td>
+ </tr>
+
+ </table>
+ </div>
+ <!-- banner header -->
+
+ <div id="bodyContent">
+
+
+
+ <div id="contextContent">
+
+ <div id="description">
+ <p>
+<a href="Tenjin.html">Tenjin</a> module
+</p>
+<p>
+$Rev: 65 $ $Release: 0.6.2 $
+</p>
+
+ </div>
+
+
+ </div>
+
+
+ </div>
+
+
+ <!-- if includes -->
+
+ <div id="section">
+
+ <div id="class-list">
+ <h3 class="section-bar">Classes and Modules</h3>
+
+ Module <a href="Tenjin/ContextHelper.html" class="link">Tenjin::ContextHelper</a><br />
+Module <a href="Tenjin/HtmlHelper.html" class="link">Tenjin::HtmlHelper</a><br />
+Class <a href="Tenjin/ArrayBufferTemplate.html" class="link">Tenjin::ArrayBufferTemplate</a><br />
+Class <a href="Tenjin/BaseContext.html" class="link">Tenjin::BaseContext</a><br />
+Class <a href="Tenjin/Context.html" class="link">Tenjin::Context</a><br />
+Class <a href="Tenjin/Engine.html" class="link">Tenjin::Engine</a><br />
+Class <a href="Tenjin/ErubisTemplate.html" class="link">Tenjin::ErubisTemplate</a><br />
+Class <a href="Tenjin/Preprocessor.html" class="link">Tenjin::Preprocessor</a><br />
+Class <a href="Tenjin/Template.html" class="link">Tenjin::Template</a><br />
+
+ </div>
+
+ <div id="constants-list">
+ <h3 class="section-bar">Constants</h3>
+
+ <div class="name-list">
+ <table summary="Constants">
+ <tr class="top-aligned-row context-row">
+ <td class="context-item-name">RELEASE</td>
+ <td>=</td>
+ <td class="context-item-value">('$Release: 0.6.2 $' =~ /[\d.]+/) &amp;&amp; $&amp;</td>
+ </tr>
+ </table>
+ </div>
+ </div>
+
+
+
+
+
+
+ <!-- if method_list -->
+
+
+ </div>
+
+
+<div id="validator-badges">
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html>
270 doc-api/classes/Tenjin/ArrayBufferTemplate.html
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Class: Tenjin::ArrayBufferTemplate</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
+ <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+ <script type="text/javascript">
+ // <![CDATA[
+
+ function popupCode( url ) {
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+ }
+
+ function toggleCode( id ) {
+ if ( document.getElementById )
+ elem = document.getElementById( id );
+ else if ( document.all )
+ elem = eval( "document.all." + id );
+ else
+ return false;
+
+ elemStyle = elem.style;
+
+ if ( elemStyle.display != "block" ) {
+ elemStyle.display = "block"
+ } else {
+ elemStyle.display = "none"
+ }
+
+ return true;
+ }
+
+ // Make codeblocks hidden by default
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+
+ // ]]>
+ </script>
+
+</head>
+<body>
+
+
+
+ <div id="classHeader">
+ <table class="header-table">
+ <tr class="top-aligned-row">
+ <td><strong>Class</strong></td>
+ <td class="class-name-in-header">Tenjin::ArrayBufferTemplate</td>
+ </tr>
+ <tr class="top-aligned-row">
+ <td><strong>In:</strong></td>
+ <td>
+ <a href="../../files/lib/tenjin_rb.html">
+ lib/tenjin.rb
+ </a>
+ <br />
+ </td>
+ </tr>
+
+ <tr class="top-aligned-row">
+ <td><strong>Parent:</strong></td>
+ <td>
+ <a href="Template.html">
+ Template
+ </a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <!-- banner header -->
+
+ <div id="bodyContent">
+
+
+
+ <div id="contextContent">
+
+ <div id="description">
+ <p>
+(experimental) fast template class which use Array buffer and Array#push()
+</p>
+<p>
+ex. (&#8216;foo.rb&#8217;)
+</p>
+<pre>
+ require 'tenjin'
+ engine = Tenjin::Engine.new(:templateclass=&gt;Tenjin::ArrayBufferTemplate)
+ template = engine.get_template('foo.rbhtml')
+ puts template.script
+</pre>
+<p>
+result:
+</p>
+<pre>
+ $ cat foo.rbhtml
+ &lt;ul&gt;
+ &lt;?rb for item in items ?&gt;
+ &lt;li&gt;#{item}&lt;/li&gt;
+ &lt;?rb end ?&gt;
+ &lt;/ul&gt;
+ $ ruby foo.rb
+ _buf.push('&lt;ul&gt;
+ '); for item in items
+ _buf.push(' &lt;li&gt;', (item).to_s, '&lt;/li&gt;
+ '); end
+ _buf.push('&lt;/ul&gt;
+ ');
+</pre>
+
+ </div>
+
+
+ </div>
+
+ <div id="method-list">
+ <h3 class="section-bar">Methods</h3>
+
+ <div class="name-list">
+ <a href="#M000019">expr_pattern</a>&nbsp;&nbsp;
+ <a href="#M000020">parse_exprs</a>&nbsp;&nbsp;
+ <a href="#M000022">quote_expr</a>&nbsp;&nbsp;
+ <a href="#M000021">quote_str</a>&nbsp;&nbsp;
+ </div>
+ </div>
+
+ </div>
+
+
+ <!-- if includes -->
+
+ <div id="section">
+
+
+
+
+
+
+
+
+ <!-- if method_list -->
+ <div id="methods">
+ <h3 class="section-bar">Protected Instance methods</h3>
+
+ <div id="method-M000019" class="method-detail">
+ <a name="M000019"></a>
+
+ <div class="method-heading">
+ <a href="#M000019" class="method-signature">
+ <span class="method-name">expr_pattern</span><span class="method-args">()</span>
+ </a>
+ </div>
+
+ <div class="method-description">
+ <p><a class="source-toggle" href="#"
+ onclick="toggleCode('M000019-source');return false;">[Source]</a></p>
+ <div class="method-source-code" id="M000019-source">
+<pre>
+<span class="ruby-comment cmt"># File lib/tenjin.rb, line 696</span>
+ <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">expr_pattern</span>
+ <span class="ruby-keyword kw">return</span> <span class="ruby-regexp re">/([\#$])\{(.*?)\}/</span>
+ <span class="ruby-keyword kw">end</span>
+</pre>
+ </div>
+ </div>
+ </div>
+
+ <div id="method-M000020" class="method-detail">
+ <a name="M000020"></a>
+
+ <div class="method-heading">
+ <a href="#M000020" class="method-signature">
+ <span class="method-name">parse_exprs</span><span class="method-args">(input)</span>
+ </a>
+ </div>
+
+ <div class="method-description">
+ <p>
+parse expressions (&#8217;#{&#8230;}&#8217; and &#8217;${&#8230;}&#8217;)
+</p>
+ <p><a class="source-toggle" href="#"
+ onclick="toggleCode('M000020-source');return false;">[Source]</a></p>
+ <div class="method-source-code" id="M000020-source">
+<pre>
+<span class="ruby-comment cmt"># File lib/tenjin.rb, line 701</span>
+ <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">parse_exprs</span>(<span class="ruby-identifier">input</span>)
+ <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">if</span> <span class="ruby-operator">!</span><span class="ruby-identifier">input</span> <span class="ruby-keyword kw">or</span> <span class="ruby-identifier">input</span>.<span class="ruby-identifier">empty?</span>
+ <span class="ruby-identifier">pos</span> = <span class="ruby-value">0</span>
+ <span class="ruby-identifier">items</span> = []
+ <span class="ruby-identifier">input</span>.<span class="ruby-identifier">scan</span>(<span class="ruby-identifier">expr_pattern</span>()) <span class="ruby-keyword kw">do</span>
+ <span class="ruby-identifier">prefix</span>, <span class="ruby-identifier">expr</span> = <span class="ruby-identifier">$1</span>, <span class="ruby-identifier">$2</span>
+ <span class="ruby-identifier">m</span> = <span class="ruby-constant">Regexp</span>.<span class="ruby-identifier">last_match</span>
+ <span class="ruby-identifier">text</span> = <span class="ruby-identifier">input</span>[<span class="ruby-identifier">pos</span>, <span class="ruby-identifier">m</span>.<span class="ruby-identifier">begin</span>(<span class="ruby-value">0</span>) <span class="ruby-operator">-</span> <span class="ruby-identifier">pos</span>]
+ <span class="ruby-identifier">pos</span> = <span class="ruby-identifier">m</span>.<span class="ruby-identifier">end</span>(<span class="ruby-value">0</span>)
+ <span class="ruby-identifier">items</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">quote_str</span>(<span class="ruby-identifier">text</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">text</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-operator">!</span><span class="ruby-identifier">text</span>.<span class="ruby-identifier">empty?</span>
+ <span class="ruby-identifier">items</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">quote_expr</span>(<span class="ruby-identifier">expr</span>, <span class="ruby-identifier">prefix</span> <span class="ruby-operator">==</span> <span class="ruby-value str">'$'</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">expr</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-operator">!</span><span class="ruby-identifier">expr</span>.<span class="ruby-identifier">empty?</span>
+ <span class="ruby-keyword kw">end</span>
+ <span class="ruby-identifier">rest</span> = <span class="ruby-identifier">$'</span> <span class="ruby-operator">||</span> <span class="ruby-identifier">input</span>
+ <span class="ruby-identifier">items</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">quote_str</span>(<span class="ruby-identifier">rest</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">rest</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-operator">!</span><span class="ruby-identifier">rest</span>.<span class="ruby-identifier">empty?</span>
+ <span class="ruby-ivar">@script</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-value str">&quot; _buf.push(&quot;</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">items</span>.<span class="ruby-identifier">join</span>(<span class="ruby-value str">&quot;, &quot;</span>) <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-value str">&quot;); &quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">items</span>.<span class="ruby-identifier">empty?</span>
+ <span class="ruby-keyword kw">end</span>
+</pre>
+ </div>
+ </div>
+ </div>
+
+ <div id="method-M000022" class="method-detail">
+ <a name="M000022"></a>
+
+ <div class="method-heading">
+ <a href="#M000022" class="method-signature">
+ <span class="method-name">quote_expr</span><span class="method-args">(expr, flag_escape)</span>
+ </a>
+ </div>
+
+ <div class="method-description">
+ <p><a class="source-toggle" href="#"
+ onclick="toggleCode('M000022-source');return false;">[Source]</a></p>
+ <div class="method-source-code" id="M000022-source">
+<pre>
+<span class="ruby-comment cmt"># File lib/tenjin.rb, line 723</span>
+ <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">quote_expr</span>(<span class="ruby-identifier">expr</span>, <span class="ruby-identifier">flag_escape</span>)
+ <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">flag_escape</span> <span class="ruby-operator">?</span> <span class="ruby-node">&quot;#{@escapefunc}((#{expr}).to_s)&quot;</span> <span class="ruby-operator">:</span> <span class="ruby-node">&quot;(#{expr}).to_s&quot;</span> <span class="ruby-comment cmt"># or &quot;(#{expr})&quot;</span>
+ <span class="ruby-keyword kw">end</span>
+</pre>
+ </div>
+ </div>
+ </div>
+
+ <div id="method-M000021" class="method-detail">
+ <a name="M000021"></a>
+
+ <div class="method-heading">
+ <a href="#M000021" class="method-signature">
+ <span class="method-name">quote_str</span><span class="method-args">(text)</span>
+ </a>
+ </div>
+
+ <div class="method-description">
+ <p><a class="source-toggle" href="#"
+ onclick="toggleCode('M000021-source');return false;">[Source]</a></p>
+ <div class="method-source-code" id="M000021-source">
+<pre>
+<span class="ruby-comment cmt"># File lib/tenjin.rb, line 718</span>
+ <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">quote_str</span>(<span class="ruby-identifier">text</span>)
+ <span class="ruby-identifier">text</span>.<span class="ruby-identifier">gsub!</span>(<span class="ruby-regexp re">/[\'\\]/</span>, <span class="ruby-value str">'\\\\\&amp;'</span>)
+ <span class="ruby-keyword kw">return</span> <span class="ruby-node">&quot;'#{text}'&quot;</span>
+ <span class="ruby-keyword kw">end</span>
+</pre>
+ </div>
+ </div>
+ </div>
+
+
+ </div>
+
+
+ </div>
+
+
+<div id="validator-badges">
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html>
329 doc-api/classes/Tenjin/BaseContext.html
@@ -0,0 +1,329 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Class: Tenjin::BaseContext</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
+ <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
+ <script type="text/javascript">
+ // <![CDATA[
+
+ function popupCode( url ) {
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+ }
+
+ function toggleCode( id ) {
+ if ( document.getElementById )
+ elem = document.getElementById( id );
+ else if ( document.all )
+ elem = eval( "document.all." + id );
+ else
+ return false;
+
+ elemStyle = elem.style;
+
+ if ( elemStyle.display != "block" ) {
+ elemStyle.display = "block"
+ } else {
+ elemStyle.display = "none"
+ }
+
+ return true;
+ }
+
+ // Make codeblocks hidden by default
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
+
+ // ]]>
+ </script>
+
+</head>
+<body>
+
+
+
+ <div id="classHeader">
+ <table class="header-table">
+ <tr class="top-aligned-row">
+ <td><strong>Class</strong></td>
+ <td class="class-name-in-header">Tenjin::BaseContext</td>
+ </tr>
+ <tr class="top-aligned-row">
+ <td><strong>In:</strong></td>
+ <td>
+ <a href="../../files/lib/tenjin_rb.html">
+ lib/tenjin.rb
+ </a>
+ <br />
+ </td>
+ </tr>
+
+ <tr class="top-aligned-row">
+ <td><strong>Parent:</strong></td>
+ <td>
+ Object
+ </td>
+ </tr>
+ </table>
+ </div>
+ <!-- banner header -->
+
+ <div id="bodyContent">
+
+
+
+ <div id="contextContent">
+
+ <div id="description">
+ <p>
+base class for <a href="Context.html">Context</a> class
+</p>
+
+ </div>
+
+
+ </div>
+
+ <div id="method-list">
+ <h3 class="section-bar">Methods</h3>
+
+ <div class="name-list">
+ <a href="#M000024">[]</a>&nbsp;&nbsp;
+ <a href="#M000025">[]=</a>&nbsp;&nbsp;
+ <a href="#M000030">each</a>&nbsp;&nbsp;
+ <a href="#M000029">has_key?</a>&nbsp;&nbsp;
+ <a href="#M000028">key?</a>&nbsp;&nbsp;
+ <a href="#M000027">key?</a>&nbsp;&nbsp;
+ <a href="#M000023">new</a>&nbsp;&nbsp;
+ <a href="#M000026">update</a>&nbsp;&nbsp;
+ </div>
+ </div>
+
+ </div>
+
+
+ <!-- if includes -->
+ <div id="includes">
+ <h3 class="section-bar">Included Modules</h3>
+
+ <div id="includes-list">
+ <span class="include-name">Enumerable</span>
+ <span class="include-name"><a href="ContextHelper.html">ContextHelper</a></span>
+ </div>
+ </div>
+
+ <div id="section">
+
+
+
+
+
+
+
+
+ <!-- if method_list -->
+ <div id="methods">
+ <h3 class="section-bar">Public Class methods</h3>
+
+ <div id="method-M000023" class="method-detail">
+ <a name="M000023"></a>
+
+ <div class="method-heading">
+ <a href="#M000023" class="method-signature">
+ <span class="method-name">new</span><span class="method-args">(vars=nil)</span>
+ </a>
+ </div>
+
+ <div class="method-description">
+ <p><a class="source-toggle" href="#"
+ onclick="toggleCode('M000023-source');return false;">[Source]</a></p>
+ <div class="method-source-code" id="M000023-source">
+<pre>
+<span class="ruby-comment cmt"># File lib/tenjin.rb, line 236</span>
+ <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">vars</span>=<span class="ruby-keyword kw">nil</span>)
+ <span class="ruby-identifier">update</span>(<span class="ruby-identifier">vars</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">vars</span>.<span class="ruby-identifier">is_a?</span>(<span class="ruby-constant">Hash</span>)
+ <span class="ruby-keyword kw">end</span>
+</pre>
+ </div>
+ </div>
+ </div>
+
+ <h3 class="section-bar">Public Instance methods</h3>