tenjin 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.txt +54 -0
  3. data/benchmark/bench.rb +502 -0
  4. data/benchmark/bench_context.rb +17 -0
  5. data/benchmark/bench_context.yaml +141 -0
  6. data/benchmark/templates/_footer.html +4 -0
  7. data/benchmark/templates/_header.html +52 -0
  8. data/benchmark/templates/bench_eruby.rhtml +29 -0
  9. data/benchmark/templates/bench_tenjin.rbhtml +29 -0
  10. data/bin/rbtenjin +449 -0
  11. data/doc-api/classes/Tenjin.html +141 -0
  12. data/doc-api/classes/Tenjin/ArrayBufferTemplate.html +270 -0
  13. data/doc-api/classes/Tenjin/BaseContext.html +312 -0
  14. data/doc-api/classes/Tenjin/Context.html +126 -0
  15. data/doc-api/classes/Tenjin/ContextHelper.html +433 -0
  16. data/doc-api/classes/Tenjin/Engine.html +616 -0
  17. data/doc-api/classes/Tenjin/ErubisTemplate.html +166 -0
  18. data/doc-api/classes/Tenjin/HtmlHelper.html +359 -0
  19. data/doc-api/classes/Tenjin/Preprocessor.html +242 -0
  20. data/doc-api/classes/Tenjin/Template.html +916 -0
  21. data/doc-api/created.rid +1 -0
  22. data/doc-api/files/README_txt.html +185 -0
  23. data/doc-api/files/lib/tenjin_rb.html +136 -0
  24. data/doc-api/fr_class_index.html +36 -0
  25. data/doc-api/fr_file_index.html +28 -0
  26. data/doc-api/fr_method_index.html +89 -0
  27. data/doc-api/index.html +24 -0
  28. data/doc-api/rdoc-style.css +208 -0
  29. data/doc/docstyle.css +188 -0
  30. data/doc/examples.html +312 -0
  31. data/doc/faq.html +909 -0
  32. data/doc/users-guide.html +1691 -0
  33. data/lib/tenjin.rb +959 -0
  34. data/setup.rb +1331 -0
  35. data/tenjin.gemspec +58 -0
  36. data/test/assert-text-equal.rb +45 -0
  37. data/test/data/examples/form/create.rbhtml +4 -0
  38. data/test/data/examples/form/form.rbhtml +14 -0
  39. data/test/data/examples/form/layout.rbhtml +8 -0
  40. data/test/data/examples/form/main.rb +9 -0
  41. data/test/data/examples/form/main.result +21 -0
  42. data/test/data/examples/form/update.rbhtml +4 -0
  43. data/test/data/examples/preprocessing/helper.rb +16 -0
  44. data/test/data/examples/preprocessing/main.rb +11 -0
  45. data/test/data/examples/preprocessing/main.result +17 -0
  46. data/test/data/examples/preprocessing/select.rbhtml +15 -0
  47. data/test/data/examples/preprocessing/select_P.result +18 -0
  48. data/test/data/examples/table/table.rb +9 -0
  49. data/test/data/examples/table/table.rbhtml +16 -0
  50. data/test/data/examples/table/table.result +20 -0
  51. data/test/data/examples/table/table_s.result +18 -0
  52. data/test/data/faq/ex1.rbhtml +5 -0
  53. data/test/data/faq/ex10-baselayout.rbhtml +27 -0
  54. data/test/data/faq/ex10-content.rbhtml +12 -0
  55. data/test/data/faq/ex10-customlayout.rbhtml +11 -0
  56. data/test/data/faq/ex10_inherit.result +25 -0
  57. data/test/data/faq/ex11-bench.rb +28 -0
  58. data/test/data/faq/ex11-content.rbhtml +9 -0
  59. data/test/data/faq/ex11-layout1.rbhtml +5 -0
  60. data/test/data/faq/ex11-layout2.rbhtml +6 -0
  61. data/test/data/faq/ex11.rb +5 -0
  62. data/test/data/faq/ex11.rbhtml +8 -0
  63. data/test/data/faq/ex11.source +11 -0
  64. data/test/data/faq/ex11_arraybuffer.result +15 -0
  65. data/test/data/faq/ex1_chksyntax.result +3 -0
  66. data/test/data/faq/ex2-content.rbhtml +3 -0
  67. data/test/data/faq/ex2-layout.rbhtml +11 -0
  68. data/test/data/faq/ex2_removenl.result +19 -0
  69. data/test/data/faq/ex3.rb +4 -0
  70. data/test/data/faq/ex3.rbhtml +1 -0
  71. data/test/data/faq/ex3_escapefunc1.result +2 -0
  72. data/test/data/faq/ex3_escapefunc2.result +2 -0
  73. data/test/data/faq/ex5.rbhtml +7 -0
  74. data/test/data/faq/ex5_template_args.source +9 -0
  75. data/test/data/faq/ex6-content.rhtml +6 -0
  76. data/test/data/faq/ex6-layout.rhtml +6 -0
  77. data/test/data/faq/ex6.rb +10 -0
  78. data/test/data/faq/ex6_eruby.result +12 -0
  79. data/test/data/faq/ex7-expr-pattern.rb +34 -0
  80. data/test/data/faq/ex7-expr-pattern.rbhtml +3 -0
  81. data/test/data/faq/ex7_expr_pattern.result +4 -0
  82. data/test/data/faq/ex8-m18n.rb +77 -0
  83. data/test/data/faq/ex8-m18n.rbhtml +4 -0
  84. data/test/data/faq/ex8_m18n.result +10 -0
  85. data/test/data/faq/ex9-baselayout.rbhtml +8 -0
  86. data/test/data/faq/ex9-content.rbhtml +6 -0
  87. data/test/data/faq/ex9-mylayout.rbhtml +5 -0
  88. data/test/data/faq/ex9_changelayout.result +11 -0
  89. data/test/data/users_guide/content6.rbhtml +3 -0
  90. data/test/data/users_guide/content7.rbhtml +5 -0
  91. data/test/data/users_guide/content8.rbhtml +2 -0
  92. data/test/data/users_guide/contextdata.rb +7 -0
  93. data/test/data/users_guide/datafile.rb +5 -0
  94. data/test/data/users_guide/datafile.yaml +10 -0
  95. data/test/data/users_guide/ex.rbhtml +6 -0
  96. data/test/data/users_guide/ex.result +7 -0
  97. data/test/data/users_guide/ex.script +5 -0
  98. data/test/data/users_guide/ex_script.result +7 -0
  99. data/test/data/users_guide/ex_source.result +8 -0
  100. data/test/data/users_guide/example1.rbhtml +12 -0
  101. data/test/data/users_guide/example1.result +17 -0
  102. data/test/data/users_guide/example10.rbhtml +4 -0
  103. data/test/data/users_guide/example10_template_args.result +6 -0
  104. data/test/data/users_guide/example11.rbhtml +5 -0
  105. data/test/data/users_guide/example11_template_args_result +2 -0
  106. data/test/data/users_guide/example12.rbhtml +12 -0
  107. data/test/data/users_guide/example12_preprocessed.result +10 -0
  108. data/test/data/users_guide/example12_preprocessed_source.result +10 -0
  109. data/test/data/users_guide/example13.rbhtml +6 -0
  110. data/test/data/users_guide/example13_preprocessed.result +2 -0
  111. data/test/data/users_guide/example13_preprocessed_source.result +2 -0
  112. data/test/data/users_guide/example14.rb +32 -0
  113. data/test/data/users_guide/example14.rbhtml +6 -0
  114. data/test/data/users_guide/example14_tmplclass.result +15 -0
  115. data/test/data/users_guide/example15.rb +10 -0
  116. data/test/data/users_guide/example15_escapefunc.result +14 -0
  117. data/test/data/users_guide/example16.rbhtml +4 -0
  118. data/test/data/users_guide/example16a.rb +10 -0
  119. data/test/data/users_guide/example16a.result +4 -0
  120. data/test/data/users_guide/example16b.rb +13 -0
  121. data/test/data/users_guide/example16b.result +4 -0
  122. data/test/data/users_guide/example16c.rb +12 -0
  123. data/test/data/users_guide/example16c.result +4 -0
  124. data/test/data/users_guide/example1_S.result +14 -0
  125. data/test/data/users_guide/example1_SXNC.result +10 -0
  126. data/test/data/users_guide/example1_source.result +14 -0
  127. data/test/data/users_guide/example2.rbhtml +3 -0
  128. data/test/data/users_guide/example2_sb.result2 +9 -0
  129. data/test/data/users_guide/example3.rbhtml +5 -0
  130. data/test/data/users_guide/example3_syntaxcheck.result +2 -0
  131. data/test/data/users_guide/example4.rbhtml +13 -0
  132. data/test/data/users_guide/example4_datafile_rb.result +13 -0
  133. data/test/data/users_guide/example4_yaml.result +13 -0
  134. data/test/data/users_guide/example5.rbhtml +9 -0
  135. data/test/data/users_guide/example5_datastr_rb.result +9 -0
  136. data/test/data/users_guide/example5_datastr_yaml.result +9 -0
  137. data/test/data/users_guide/example6.rbhtml +19 -0
  138. data/test/data/users_guide/example6_layout.result +29 -0
  139. data/test/data/users_guide/example6_nested.result +28 -0
  140. data/test/data/users_guide/example7_layout2.result +13 -0
  141. data/test/data/users_guide/example8_layout3.result +8 -0
  142. data/test/data/users_guide/example9.rbhtml +18 -0
  143. data/test/data/users_guide/example9_capture.result +26 -0
  144. data/test/data/users_guide/footer.html +5 -0
  145. data/test/data/users_guide/footer.rbhtml +4 -0
  146. data/test/data/users_guide/layout6.rbhtml +17 -0
  147. data/test/data/users_guide/layout7.rbhtml +9 -0
  148. data/test/data/users_guide/layout8_html.rbhtml +5 -0
  149. data/test/data/users_guide/layout8_xhtml.rbhtml +6 -0
  150. data/test/data/users_guide/layout9.rbhtml +25 -0
  151. data/test/data/users_guide/sidemenu.rbhtml +5 -0
  152. data/test/data/users_guide/user_app.cgi +39 -0
  153. data/test/data/users_guide/user_app.result +30 -0
  154. data/test/data/users_guide/user_create.rbhtml +6 -0
  155. data/test/data/users_guide/user_edit.rbhtml +7 -0
  156. data/test/data/users_guide/user_form.rbhtml +10 -0
  157. data/test/data/users_guide/user_layout.rbhtml +16 -0
  158. data/test/test_all.rb +23 -0
  159. data/test/test_engine.rb +526 -0
  160. data/test/test_engine.yaml +2039 -0
  161. data/test/test_examples.rb +81 -0
  162. data/test/test_faq.rb +60 -0
  163. data/test/test_htmlhelper.rb +78 -0
  164. data/test/test_main.rb +564 -0
  165. data/test/test_main.yaml +174 -0
  166. data/test/test_template.rb +113 -0
  167. data/test/test_template.yaml +1244 -0
  168. data/test/test_users_guide.rb +75 -0
  169. data/test/testcase-helper.rb +166 -0
  170. metadata +226 -0
@@ -0,0 +1,1691 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html">
5
+ <title>rbTenjin User's Guide</title>
6
+ <meta name="generator" content="kwaser">
7
+ <meta http-equiv="Content-Style-Type" content="text/css">
8
+ <link rel="stylesheet" href="docstyle.css" type="text/css">
9
+ </head>
10
+ <body>
11
+
12
+ <blockquote>
13
+ <div class="mainbody">
14
+
15
+ <div align="left"><h1>rbTenjin User's Guide</h1></div>
16
+ <div align="left">
17
+ last update: $Date: 2007-08-04 13:23:33 +0900 (Sat, 04 Aug 2007) $<br>
18
+ </div>
19
+
20
+ <p>Release: 0.6.0
21
+ </p>
22
+ <p>Table of Contents:
23
+ <ul>
24
+ <li><a href="#intro">Introduction</a>
25
+ <ul>
26
+ <li><a href="#overview">Overview</a>
27
+ </li>
28
+ <li><a href="#features">Features</a>
29
+ </li>
30
+ <li><a href="#benchmark">Benchmark</a>
31
+ </li>
32
+ </ul>
33
+ </li>
34
+ <li><a href="#installation">Installation</a>
35
+ </li>
36
+ <li><a href="#desguide">Designer's Guide</a>
37
+ <ul>
38
+ <li><a href="#des-notation">Notation</a>
39
+ </li>
40
+ <li><a href="#des-convert">Convert into Ruby Code</a>
41
+ </li>
42
+ <li><a href="#des-syntaxchk">Syntax Checking</a>
43
+ </li>
44
+ <li><a href="#des-contextdata">Context Data File</a>
45
+ </li>
46
+ <li><a href="#des-cmlinecontext">Command-line Context Data</a>
47
+ </li>
48
+ <li><a href="#des-nested-template">Nested Template</a>
49
+ </li>
50
+ <li><a href="#des-layout">Layout Template</a>
51
+ </li>
52
+ <li><a href="#des-capturing">Capturing</a>
53
+ </li>
54
+ <li><a href="#des-args">Template Arguments</a>
55
+ </li>
56
+ <li><a href="#des-preprocess">Preprocessing</a>
57
+ </li>
58
+ <li><a href="#des-otheropts">Other Options</a>
59
+ </li>
60
+ </ul>
61
+ </li>
62
+ <li><a href="#devguide">Developer's Guide</a>
63
+ <ul>
64
+ <li><a href="#dev-example">An Example</a>
65
+ </li>
66
+ <li><a href="#dev-classes">Classes and Functions in rbTenjin</a>
67
+ </li>
68
+ <li><a href="#dev-templateclass">Class Tenjin::Template</a>
69
+ </li>
70
+ <li><a href="#dev-engineclass">Class Tenjin::Engine</a>
71
+ </li>
72
+ <li><a href="#dev-initopts">Template Initialize Options</a>
73
+ </li>
74
+ <li><a href="#dev-helpers">Add Your Helper Functions</a>
75
+ </li>
76
+ <li><a href="#dev-othertopics">Other Topics</a>
77
+ </li>
78
+ </ul>
79
+ </li>
80
+ </ul>
81
+ </p>
82
+ <a name="intro"></a>
83
+ <h2 class="section1">Introduction</h2>
84
+ <a name="overview"></a>
85
+ <h3 class="section2">Overview</h3>
86
+ <p>rbTenjin is a very fast and lightweight template engine based on embedded Ruby.
87
+ You can embed Ruby statements and expressions into your text file.
88
+ rbTenjin converts it into Ruby script and evaluate it.
89
+ </p>
90
+ <p>The following is an example of rbTenjin.
91
+ </p>
92
+ <a name="ex.rbhtml"></a>
93
+ <div class="program_caption">
94
+ File 'ex.rbhtml':</div>
95
+ <pre class="program">Hello <strong>#{@name}</strong>!
96
+ &lt;ul&gt;
97
+ <strong>&lt;?rb for item in @items ?&gt;</strong>
98
+ &lt;li&gt;<strong>${item}</strong>&lt;/li&gt;
99
+ <strong>&lt;?rb end ?&gt;</strong>
100
+ &lt;/ul&gt;
101
+ </pre>
102
+ <p>Here is the notation:
103
+ </p>
104
+ <ul type="disc">
105
+ <li><code>&lt;?rb ... ?&gt;</code> represents embedded Ruby statements.
106
+ </li>
107
+ <li><code>#{...}</code> represents embedded Ruby expression.
108
+ </li>
109
+ <li><code>${...}</code> represents embedded escaped (sanitized) Ruby expression.
110
+ </li>
111
+ </ul>
112
+ <a name="ex_source.result"></a>
113
+ <div class="terminal_caption">
114
+ Result of covertion into Ruby script:</div>
115
+ <pre class="terminal">$ rbtenjin -s ex.rbhtml
116
+ _buf = ''; _buf &lt;&lt; %Q`Hello <strong>#{@name}</strong>!
117
+ &lt;ul&gt;\n`
118
+ <strong>for item in @items</strong>
119
+ _buf &lt;&lt; %Q` &lt;li&gt;<strong>#{escape((item).to_s)}</strong>&lt;/li&gt;\n`
120
+ <strong>end</strong>
121
+ _buf &lt;&lt; %Q`&lt;/ul&gt;\n`
122
+ _buf.to_s
123
+ </pre>
124
+ <a name="ex.result"></a>
125
+ <div class="terminal_caption">
126
+ Output of execution with context data:</div>
127
+ <pre class="terminal">$ rbtenjin -c "@name='World'; @items=['&lt;AAA&gt;','B&amp;B','\"CCC\"']" ex.rbhtml
128
+ Hello World!
129
+ &lt;ul&gt;
130
+ &lt;li&gt;&amp;lt;AAA&amp;gt;&lt;/li&gt;
131
+ &lt;li&gt;B&amp;amp;B&lt;/li&gt;
132
+ &lt;li&gt;&amp;quot;CCC&amp;quot;&lt;/li&gt;
133
+ &lt;/ul&gt;
134
+ </pre>
135
+ <a name="ex.script"></a>
136
+ <div class="program_caption">
137
+ Example of Ruby script</div>
138
+ <pre class="program">require 'tenjin'
139
+ engine = Tenjin::Engine.new()
140
+ context = { :name=&gt;'World', :items=&gt;['&lt;AAA&gt;', 'B&amp;B', '"CCC"'] }
141
+ output = engine.render('ex.rbhtml', context)
142
+ print output
143
+ </pre>
144
+ <br>
145
+
146
+
147
+ <a name="features"></a>
148
+ <h3 class="section2">Features</h3>
149
+ <p>rbTenjin has the following features:
150
+ </p>
151
+ <ul type="disc">
152
+ <li>rbTenjin runs very fast. It works about three times as fast as ERB.
153
+ </li>
154
+ <li>rbTenjin doesn't break HTML design because it uses XML Processing
155
+ Instructions (PI) as embedded notation for Ruby statements.
156
+ </li>
157
+ <li>rbTenjin is secure because it supports escaping expression value by default.
158
+ </li>
159
+ <li>rbTenjin is small and lightweight. It is very easy to include rbTenjin
160
+ into your application.
161
+ </li>
162
+ <li>rbTenjin supports auto caching of converted Ruby code.
163
+ </li>
164
+ <li>rbTenjin supports partial template and layout template.
165
+ These are very useful especially for web application.
166
+ </li>
167
+ <li>rbTenjin supports partial capturing of template.
168
+ </li>
169
+ <li>rbTenjin can load YAML file as context data. Using rbTenjin, it is able to
170
+ separate template file and data file.
171
+ </li>
172
+ </ul>
173
+ <br>
174
+
175
+
176
+ <a name="benchmark"></a>
177
+ <h3 class="section2">Benchmark</h3>
178
+ <p>Benchmark script is contained in rbTenjin archive.
179
+ The following is an example of benchmark.
180
+ </p>
181
+ <div class="terminal_caption">
182
+ MacOS X 10.4 Tiger, Intel CoreDuo 1.83GHz, Memory 2GB</div>
183
+ <pre class="terminal">$ cd rbtenjin-X.X.X/benchmark
184
+ $ ruby -v
185
+ ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.9.1]
186
+ $ ruby bench.rb -n 10000
187
+ user system total real
188
+ eruby 12.02000 0.27000 12.29000 ( 12.34855)
189
+ eruby-cache 11.09000 0.43000 11.53000 ( 11.58262)
190
+ erb 36.32000 0.41000 36.73000 ( 36.89404)
191
+ erb-cache 11.13000 0.45000 11.57000 ( 11.62259)
192
+ erb-reuse 10.78000 0.03000 10.81000 ( 10.85908)
193
+ erb-defmethod 5.82000 0.02000 5.84000 ( 5.86168)
194
+ erubis 10.31000 0.32000 10.64000 ( 10.68644)
195
+ erubis-cache 7.02000 0.43000 7.45000 ( 7.50923)
196
+ erubis-reuse 4.43000 0.01000 4.44000 ( 4.45338)
197
+ tenjin 6.87000 0.47000 7.34000 ( 7.37263)
198
+ tenjin-nocache 8.73000 0.36000 9.10000 ( 9.14337)
199
+ tenjin-reuse 4.45000 0.07000 4.52000 ( 4.53931)
200
+ </pre>
201
+ <p>This shows that rbTenjin is much faster than any other eRuby implementations.
202
+ </p>
203
+ <br>
204
+
205
+
206
+ <br>
207
+
208
+
209
+ <a name="installation"></a>
210
+ <h2 class="section1">Installation</h2>
211
+ <p>rbTenjin requires Ruby 1.8 or later.
212
+ </p>
213
+ <ul type="disc">
214
+ <li>If you have installed RubyGems, just type '<code>gem install rbtenjin</code>'.
215
+ </li>
216
+ <li>Or if you have administrator privilegde, install with setup.rb.
217
+ <pre class="terminal">$ tar xjf rbtenjin_X.X.X.tar.bz
218
+ $ cd rbtenjin_X.X.X/
219
+ $ ruby setup.rb --help | more
220
+ $ ruby setup.rb config
221
+ $ ruby setup.rb setup
222
+ $ sudo ruby setup.rb install
223
+ </pre>
224
+ </li>
225
+ <li>Or copy 'lib/tenjin.rb' and 'bin/rbtenjin' to proper directories.
226
+ <pre class="terminal">$ tar xjf rbtenjin_X.X.X.tar.bz
227
+ $ cd rbtenjin_X.X.X/
228
+ $ cp lib/tenjin.rb $HOME/lib/ruby/
229
+ $ cp bin/rbtenjin $HOME/bin/
230
+ </pre>
231
+ </li>
232
+ </ul>
233
+ <br>
234
+
235
+
236
+ <a name="desguide"></a>
237
+ <h2 class="section1">Designer's Guide</h2>
238
+ <p>This section shows how to use rbTenjin for designer.
239
+ </p>
240
+ <p>If you want to know how to use rbTenjin in your program, see <a href="#devguide">Developer's Guide</a> section.
241
+ </p>
242
+ <a name="des-notation"></a>
243
+ <h3 class="section2">Notation</h3>
244
+ <p>The following is the notation of rbTenjin.
245
+ </p>
246
+ <ul type="disc">
247
+ <li>'<code>&lt;?rb ... ?&gt;</code>' represents embedded Ruby statement.
248
+ </li>
249
+ <li>'<code>#{...}</code>' represents embedded Ruby expression.
250
+ </li>
251
+ <li>'<code>${...}</code>' represents embedded Ruby expression which is to be escaped (for example, '<code>&amp; &lt; &gt; "</code>' is escaped to '<code>&amp;amp; &amp;lt; &amp;gt; &amp;quot;</code>').
252
+ </li>
253
+ </ul>
254
+ <a name="example1.rbhtml"></a>
255
+ <div class="program_caption">
256
+ File 'example1.rbhtml':</div>
257
+ <pre class="program">&lt;table&gt;
258
+ &lt;tbody&gt;
259
+ <strong>&lt;?rb i = 0 ?&gt;</strong>
260
+ <strong>&lt;?rb for item in ['&lt;foo&gt;', 'bar&amp;bar', '"baz"'] ?&gt;</strong>
261
+ <strong>&lt;?rb i += 1 ?&gt;</strong>
262
+ &lt;tr&gt;
263
+ &lt;td&gt;<strong>#{item}</strong>&lt;/td&gt;
264
+ &lt;td&gt;<strong>${item}</strong>&lt;/td&gt;
265
+ &lt;/tr&gt;
266
+ <strong>&lt;?rb end ?&gt;</strong>
267
+ &lt;tbody&gt;
268
+ &lt;/table&gt;
269
+ </pre>
270
+ <p>The following is the result of executing 'example1.rbhtml'.
271
+ </p>
272
+ <a name="example1.result"></a>
273
+ <div class="terminal_caption">
274
+ Result:</div>
275
+ <pre class="terminal">$ rbtenjin example1.rbhtml
276
+ &lt;table&gt;
277
+ &lt;tbody&gt;
278
+ &lt;tr&gt;
279
+ &lt;td&gt;<strong>&lt;foo&gt;</strong>&lt;/td&gt;
280
+ &lt;td&gt;<strong>&amp;lt;foo&amp;gt;</strong>&lt;/td&gt;
281
+ &lt;/tr&gt;
282
+ &lt;tr&gt;
283
+ &lt;td&gt;<strong>bar&amp;bar</strong>&lt;/td&gt;
284
+ &lt;td&gt;<strong>bar&amp;amp;bar</strong>&lt;/td&gt;
285
+ &lt;/tr&gt;
286
+ &lt;tr&gt;
287
+ &lt;td&gt;<strong>"baz"</strong>&lt;/td&gt;
288
+ &lt;td&gt;<strong>&amp;quot;baz&amp;quot;</strong>&lt;/td&gt;
289
+ &lt;/tr&gt;
290
+ &lt;tbody&gt;
291
+ &lt;/table&gt;
292
+ </pre>
293
+ <br>
294
+
295
+
296
+ <a name="des-convert"></a>
297
+ <h3 class="section2">Convert into Ruby Code</h3>
298
+ <p>Command-line option '-s' converts embedded files into Ruby code.
299
+ </p>
300
+ <a name="example1_source.result"></a>
301
+ <div class="terminal_caption">
302
+ Result:</div>
303
+ <pre class="terminal">$ rbtenjin <strong>-s</strong> example1.rbhtml
304
+ _buf = ''; _buf &lt;&lt; %Q`&lt;table&gt;
305
+ &lt;tbody&gt;\n`
306
+ <strong>i = 0</strong>
307
+ <strong>for item in ['&lt;foo&gt;', 'bar&amp;bar', '"baz"']</strong>
308
+ <strong>i += 1</strong>
309
+ _buf &lt;&lt; %Q` &lt;tr&gt;
310
+ &lt;td&gt;<strong>#{item}</strong>&lt;/td&gt;
311
+ &lt;td&gt;<strong>#{escape((item).to_s)}</strong>&lt;/td&gt;
312
+ &lt;/tr&gt;\n`
313
+ <strong>end</strong>
314
+ _buf &lt;&lt; %Q` &lt;tbody&gt;
315
+ &lt;/table&gt;\n`
316
+ _buf.to_s
317
+ </pre>
318
+ <ul type="disc">
319
+ <li>Variable <code>@_buf</code> is a String.
320
+ </li>
321
+ <li>Function <code>escape()</code> (= <code>Tenjin::Context.escape()</code>) escapes <code>'&amp; &lt; &gt; "'</code> into <code>'&amp;amp; &amp;lt; &amp;gt; &amp;quot;'</code>.
322
+ Command-line option <code>--escapefunc=func</code> makes rbtenjin to use <code>func()</code> instead of <code>escape()</code>.
323
+ </li>
324
+ <li>Newline character ("\n" or "\r\n") is automatically detected by rbTenjin.
325
+ </li>
326
+ </ul>
327
+ <p>'<code>_buf = '';</code>' is called as preamble and '<code>_buf.to_s</code>' is called as postamble.
328
+ Command-line option '<code>-b</code>' removes preamble and postamble.
329
+ </p>
330
+ <a name="example2.rbhtml"></a>
331
+ <div class="program_caption">
332
+ File 'example2.rbhtml'</div>
333
+ <pre class="program">&lt;?rb for i in [1, 2, 3] ?&gt;
334
+ &lt;p&gt;#{item}&lt;/p&gt;
335
+ &lt;?rb end ?&gt;
336
+ </pre>
337
+ <a name="example2_sb.result2"></a>
338
+ <div class="terminal_caption">
339
+ Result:</div>
340
+ <pre class="terminal">$ rbtenjin -s example2.rbhtml
341
+ <strong>_buf = '';</strong> for i in [1, 2, 3]
342
+ _buf &lt;&lt; %Q`&lt;p&gt;#{item}&lt;/p&gt;\n`
343
+ end
344
+ <strong>_buf.to_s</strong>
345
+ $ rbtenjin -s<strong>b</strong> example2.rbhtml
346
+ for i in [1, 2, 3]
347
+ _buf &lt;&lt; %Q`&lt;p&gt;#{item}&lt;/p&gt;\n`
348
+ end
349
+ </pre>
350
+ <p>Command-line option '-S' also show converted Ruby code but it doesn't print text part.
351
+ This is useful to check Ruby code for debugging.
352
+ </p>
353
+ <a name="example1_S.result"></a>
354
+ <div class="terminal_caption">
355
+ Result:</div>
356
+ <pre class="terminal">$ rbtenjin <strong>-S</strong> example1.rbhtml
357
+ _buf = '';
358
+
359
+ i = 0
360
+ for item in ['&lt;foo&gt;', 'bar&amp;bar', '"baz"']
361
+ i += 1
362
+
363
+
364
+ escape((item).to_s);
365
+
366
+ end
367
+
368
+
369
+ _buf.to_s
370
+ </pre>
371
+ <p>In addition, the following command-line options are available.
372
+ </p>
373
+ <dl class="dl3" compact>
374
+ <dt class="dt3"><b>
375
+ -N </b></dt>
376
+ <dd class="dd3">
377
+ Add line number.
378
+ </dd>
379
+ <dt class="dt3"><b>
380
+ -X </b></dt>
381
+ <dd class="dd3">
382
+ Delete expressions.
383
+ </dd>
384
+ <dt class="dt3"><b>
385
+ -C </b></dt>
386
+ <dd class="dd3">
387
+ Remove empty lines (compact-mode).
388
+ </dd>
389
+ <dt class="dt3"><b>
390
+ -U </b></dt>
391
+ <dd class="dd3">
392
+ Compress empty lines to a line (uniq-mode).
393
+ </dd>
394
+ </dl>
395
+ <a name="example1_SXNC.result"></a>
396
+ <div class="terminal_caption">
397
+ Result:</div>
398
+ <pre class="terminal">$ rbtenjin <strong>-SUNX</strong> example1.rbhtml
399
+ 1: _buf = '';
400
+
401
+ 3: i = 0
402
+ 4: for item in ['&lt;foo&gt;', 'bar&amp;bar', '"baz"']
403
+ 5: i += 1
404
+
405
+ 10: end
406
+
407
+ 13: _buf.to_s
408
+ </pre>
409
+ <br>
410
+
411
+
412
+ <a name="des-syntaxchk"></a>
413
+ <h3 class="section2">Syntax Checking</h3>
414
+ <p>Command-line option '<code>-z</code>' checks syntax error in embedded Ruby code
415
+ and command-line option '<code>-w</code>' sets warning level to 2.
416
+ It is recommended to use '-w' when you specify '-z'.
417
+ </p>
418
+ <a name="example3.rbhtml"></a>
419
+ <div class="program_caption">
420
+ File example3.rbhtml:</div>
421
+ <pre class="program">&lt;ul&gt;
422
+ &lt;?rb for item in items ?&gt;
423
+ &lt;li&gt;${item}&lt;/li&gt;
424
+ &lt;?rb <strong>ende</strong> ?&gt;
425
+ &lt;/ul&gt;
426
+ </pre>
427
+ <a name="example3_syntaxcheck.result"></a>
428
+ <div class="terminal_caption">
429
+ Result:</div>
430
+ <pre class="terminal">$ rbtenjin <strong>-wz</strong> example3.rbhtml
431
+ example3.rbhtml:5: syntax error, unexpected $end, expecting kEND
432
+ </pre>
433
+ <p>Command-line option '-wz' is more convenient than '<code>rbtenjin -s file | ruby -wz</code>'
434
+ because the former can take several filenames.
435
+ </p>
436
+ <p>Command-line option '-q' (quiet-mode) prints nothing if it has no errors.
437
+ </p>
438
+ <br>
439
+
440
+
441
+ <a name="des-contextdata"></a>
442
+ <h3 class="section2">Context Data File</h3>
443
+ <p>rbTenjin allows you to specify context data by YAML file or Ruby script.
444
+ </p>
445
+ <a name="example4.rbhtml"></a>
446
+ <div class="program_caption">
447
+ File 'example4.rbhtml':</div>
448
+ <pre class="program">&lt;p&gt;
449
+ ${@text}
450
+ #{@num}
451
+ #{@flag}
452
+ &lt;/p&gt;
453
+
454
+ &lt;?rb for item in @items ?&gt;
455
+ &lt;p&gt;${item}&lt;/p&gt;
456
+ &lt;?rb end ?&gt;
457
+
458
+ &lt;?rb for key, value in @hash ?&gt;
459
+ &lt;p&gt;#{key} = ${value}&lt;/p&gt;
460
+ &lt;?rb end ?&gt;
461
+ </pre>
462
+ <a name="datafile.yaml"></a>
463
+ <div class="program_caption">
464
+ File 'datafile.yaml':</div>
465
+ <pre class="program">text: foo
466
+ num: 3.14
467
+ flag: yes
468
+ items:
469
+ - foo
470
+ - bar
471
+ - baz
472
+ hash:
473
+ x: 1
474
+ y: 2
475
+ </pre>
476
+ <a name="example4_yaml.result"></a>
477
+ <div class="terminal_caption">
478
+ Result:</div>
479
+ <pre class="terminal">$ rbtenjin <strong>-f datafile.yaml</strong> example4.rbhtml
480
+ &lt;p&gt;
481
+ foo
482
+ 3.14
483
+ true
484
+ &lt;/p&gt;
485
+
486
+ &lt;p&gt;foo&lt;/p&gt;
487
+ &lt;p&gt;bar&lt;/p&gt;
488
+ &lt;p&gt;baz&lt;/p&gt;
489
+
490
+ &lt;p&gt;x = 1&lt;/p&gt;
491
+ &lt;p&gt;y = 2&lt;/p&gt;
492
+ </pre>
493
+ <a name="datafile.rb"></a>
494
+ <div class="program_caption">
495
+ File 'datafile.rb':</div>
496
+ <pre class="program">@text = "foo"
497
+ @num = 3.14
498
+ @flag = true
499
+ @items = ["foo", "bar", "baz"]
500
+ @hash = {:x=&gt;1, :y=&gt;2}
501
+ </pre>
502
+ <a name="example4_datafile_rb.result"></a>
503
+ <div class="terminal_caption">
504
+ Result:</div>
505
+ <pre class="terminal">$ rbtenjin <strong>-f datafile.rb</strong> example4.rbhtml
506
+ &lt;p&gt;
507
+ foo
508
+ 3.14
509
+ true
510
+ &lt;/p&gt;
511
+
512
+ &lt;p&gt;foo&lt;/p&gt;
513
+ &lt;p&gt;bar&lt;/p&gt;
514
+ &lt;p&gt;baz&lt;/p&gt;
515
+
516
+ &lt;p&gt;x = 1&lt;/p&gt;
517
+ &lt;p&gt;y = 2&lt;/p&gt;
518
+ </pre>
519
+ <br>
520
+
521
+
522
+ <a name="des-cmlinecontext"></a>
523
+ <h3 class="section2">Command-line Context Data</h3>
524
+ <p>Command-line option '<code>-z</code>' specifies context data in YAML format or Ruby code.
525
+ </p>
526
+ <a name="example5.rbhtml"></a>
527
+ <div class="program_caption">
528
+ File 'example5.rbhtml':</div>
529
+ <pre class="program">text: #{@text}
530
+ items:
531
+ &lt;?rb for item in @items ?&gt;
532
+ - #{item}
533
+ &lt;?rb end ?&gt;
534
+ hash:
535
+ &lt;?rb for key, val in @hash ?&gt;
536
+ #{key}: #{val}
537
+ &lt;?rb end ?&gt;
538
+ </pre>
539
+ <a name="example5_datastr_rb.result"></a>
540
+ <div class="terminal_caption">
541
+ Result of context data in ruby code:</div>
542
+ <pre class="terminal">$ rbtenjin <strong>-c '@text="foo"; @items=%w[a b c]; @hash={"x"=&gt;1,"y"=&gt;2}'</strong> example5.rbhtml
543
+ text: foo
544
+ items:
545
+ - a
546
+ - b
547
+ - c
548
+ hash:
549
+ x: 1
550
+ y: 2
551
+ </pre>
552
+ <a name="example5_datastr_yaml.result"></a>
553
+ <div class="terminal_caption">
554
+ Result of context data in yaml format:</div>
555
+ <pre class="terminal">$ rbtenjin <strong>-c '{text: foo, items: [a, b, c], hash: {x: 1, y: 2} }'</strong> example5.rbhtml
556
+ text: foo
557
+ items:
558
+ - a
559
+ - b
560
+ - c
561
+ hash:
562
+ x: 1
563
+ y: 2
564
+ </pre>
565
+ <br>
566
+
567
+
568
+ <a name="des-nested-template"></a>
569
+ <h3 class="section2">Nested Template</h3>
570
+ <p>Template can include other templates.
571
+ Included templates can also include other templates.
572
+ </p>
573
+ <p>The following function is available to include other templates.
574
+ </p>
575
+ <dl class="dl3">
576
+ <dt class="dt3"><b>
577
+ import(template_name) </b></dt>
578
+ <dd class="dd3">
579
+ Include other template.
580
+ </dd>
581
+ </dl>
582
+ <a name="example6.rbhtml"></a>
583
+ <div class="program_caption">
584
+ File 'example6.rbhtml':</div>
585
+ <pre class="program">&lt;html&gt;
586
+ &lt;body&gt;
587
+
588
+ &lt;div id="sidemenu"&gt;
589
+ <strong>&lt;?rb import 'sidemenu.rbhtml' ?&gt;</strong>
590
+ &lt;/div&gt;
591
+
592
+ &lt;div id="main-content"&gt;
593
+ &lt;?rb for item in @items ?&gt;
594
+ &lt;p&gt;${item}&lt;/p&gt;
595
+ &lt;?rb end ?&gt;
596
+ &lt;/div&gt;
597
+
598
+ &lt;div id="footer"&gt;
599
+ <strong>#{import 'footer.rbhtml', false}</strong>
600
+ &lt;/div&gt;
601
+
602
+ &lt;/body&gt;
603
+ &lt;/table&gt;
604
+ </pre>
605
+ <a name="sidemenu.rbhtml"></a>
606
+ <div class="program_caption">
607
+ File 'sidemenu.rbhtml':</div>
608
+ <pre class="program">&lt;ul&gt;
609
+ &lt;?rb for item in @menu ?&gt;
610
+ &lt;li&gt;&lt;a href="${item['url']}"&gt;${item['name']}&lt;/a&gt;&lt;/li&gt;
611
+ &lt;?rb end ?&gt;
612
+ &lt;/ul&gt;
613
+ </pre>
614
+ <a name="footer.rbhtml"></a>
615
+ <div class="program_caption">
616
+ File 'footer.rbhtml':</div>
617
+ <pre class="program">&lt;hr /&gt;
618
+ &lt;address&gt;
619
+ &lt;a href="mailto:${@webmaster_email}"&gt;${@webmaster_email}&lt;/a&gt;
620
+ &lt;/address&gt;
621
+ </pre>
622
+ <a name="contextdata.rb"></a>
623
+ <div class="program_caption">
624
+ File 'contextdata.rb':</div>
625
+ <pre class="program">@items = [ '&lt;FOO&gt;', '&amp;BAR', '"BAZ"' ]
626
+ @webmaster_email = 'webmaster@example.com'
627
+ @menu = [
628
+ {'name'=&gt; 'Top', 'url'=&gt; '/' },
629
+ {'name'=&gt; 'Products', 'url'=&gt; '/prod' },
630
+ {'name'=&gt; 'Support', 'url'=&gt; '/support' },
631
+ ]
632
+ </pre>
633
+ <a name="example6_nested.result"></a>
634
+ <div class="terminal_caption">
635
+ Result:</div>
636
+ <pre class="terminal">$ rbtenjin -f contextdata.rb example6.rbhtml
637
+ &lt;html&gt;
638
+ &lt;body&gt;
639
+
640
+ &lt;div id="sidemenu"&gt;
641
+ <strong>&lt;ul&gt;</strong>
642
+ <strong>&lt;li&gt;&lt;a href="/"&gt;Top&lt;/a&gt;&lt;/li&gt;</strong>
643
+ <strong>&lt;li&gt;&lt;a href="/prod"&gt;Products&lt;/a&gt;&lt;/li&gt;</strong>
644
+ <strong>&lt;li&gt;&lt;a href="/support"&gt;Support&lt;/a&gt;&lt;/li&gt;</strong>
645
+ <strong>&lt;/ul&gt;</strong>
646
+ &lt;/div&gt;
647
+
648
+ &lt;div id="main-content"&gt;
649
+ &lt;p&gt;&amp;lt;FOO&amp;gt;&lt;/p&gt;
650
+ &lt;p&gt;&amp;amp;BAR&lt;/p&gt;
651
+ &lt;p&gt;&amp;quot;BAZ&amp;quot;&lt;/p&gt;
652
+ &lt;/div&gt;
653
+
654
+ &lt;div id="footer"&gt;
655
+ <strong>&lt;hr /&gt;</strong>
656
+ <strong>&lt;address&gt;</strong>
657
+ <strong> &lt;a href="mailto:webmaster@example.com"&gt;webmaster@example.com&lt;/a&gt;</strong>
658
+ <strong>&lt;/address&gt;</strong>
659
+
660
+ &lt;/div&gt;
661
+
662
+ &lt;/body&gt;
663
+ &lt;/table&gt;
664
+ </pre>
665
+ <p>Function '<code>import()</code>' can take template filename
666
+ (ex. 'user_main.rbhtml') or template short name (ex. :main).
667
+ Template short name is a Symbol.
668
+ </p>
669
+ <p>To make template short name available, command-line option '<code>--prefix</code>' and
670
+ '<code>--postfix</code>' are required.
671
+ For example, '<code>include("user_main.rbhtml")</code>' can be described as '<code>include(:main)</code>'
672
+ when '<code>--prefix="user_"</code>' and '<code>--postfix=".rbhtml"</code>' are specified in command-line.
673
+ </p>
674
+ <br>
675
+
676
+
677
+ <a name="des-layout"></a>
678
+ <h3 class="section2">Layout Template</h3>
679
+ <p>Command-line option '<code>--layout=templatename</code>' specifies layout template name.
680
+ </p>
681
+ <p>For example, 'exmample6.rbhtml' template in the previous section can be divided
682
+ into layout file 'layout6.rbhtml' and content file 'content6.rbhtml'.
683
+ Variable '<code>@_content</code>' in layout template represents the result of content file.
684
+ </p>
685
+ <a name="layout6.rbhtml"></a>
686
+ <div class="program_caption">
687
+ File 'layout6.rbhtml':</div>
688
+ <pre class="program">&lt;html&gt;
689
+ &lt;body&gt;
690
+
691
+ &lt;div id="sidemenu"&gt;
692
+ &lt;?rb import 'sidemenu.rbhtml' ?&gt;
693
+ &lt;/div&gt;
694
+
695
+ &lt;div id="main-content"&gt;
696
+ <strong>#{@_content}</strong>
697
+ &lt;/div&gt;
698
+
699
+ &lt;div id="footer"&gt;
700
+ #{import 'footer.rbhtml', false}
701
+ &lt;/div&gt;
702
+
703
+ &lt;/body&gt;
704
+ &lt;/table&gt;
705
+ </pre>
706
+ <a name="content6.rbhtml"></a>
707
+ <div class="program_caption">
708
+ File 'content6.rbhtml':</div>
709
+ <pre class="program">&lt;?rb for item in @items ?&gt;
710
+ &lt;p&gt;${item}&lt;/p&gt;
711
+ &lt;?rb end ?&gt;
712
+ </pre>
713
+ <a name="example6_layout.result"></a>
714
+ <div class="terminal_caption">
715
+ Result:</div>
716
+ <pre class="terminal">$ rbtenjin -f contextdata.rb <strong>--layout=layout6.rbhtml</strong> content6.rbhtml
717
+ &lt;html&gt;
718
+ &lt;body&gt;
719
+
720
+ &lt;div id="sidemenu"&gt;
721
+ &lt;ul&gt;
722
+ &lt;li&gt;&lt;a href="/"&gt;Top&lt;/a&gt;&lt;/li&gt;
723
+ &lt;li&gt;&lt;a href="/prod"&gt;Products&lt;/a&gt;&lt;/li&gt;
724
+ &lt;li&gt;&lt;a href="/support"&gt;Support&lt;/a&gt;&lt;/li&gt;
725
+ &lt;/ul&gt;
726
+ &lt;/div&gt;
727
+
728
+ &lt;div id="main-content"&gt;
729
+ <strong> &lt;p&gt;&amp;lt;FOO&amp;gt;&lt;/p&gt;</strong>
730
+ <strong> &lt;p&gt;&amp;amp;BAR&lt;/p&gt;</strong>
731
+ <strong> &lt;p&gt;&amp;quot;BAZ&amp;quot;&lt;/p&gt;</strong>
732
+
733
+ &lt;/div&gt;
734
+
735
+ &lt;div id="footer"&gt;
736
+ &lt;hr /&gt;
737
+ &lt;address&gt;
738
+ &lt;a href="mailto:webmaster@example.com"&gt;webmaster@example.com&lt;/a&gt;
739
+ &lt;/address&gt;
740
+
741
+ &lt;/div&gt;
742
+
743
+ &lt;/body&gt;
744
+ &lt;/table&gt;
745
+ </pre>
746
+ <p>Target template and layout template don't share local variables.
747
+ It means that local variables set in a template are not available in layout template.
748
+ </p>
749
+ <p>If you want variables set in a temlate to be available in layout template,
750
+ use instance variables instead of local variables.
751
+ </p>
752
+ <a name="layout7.rbhtml"></a>
753
+ <div class="program_caption">
754
+ File 'layout7.rbhtml':</div>
755
+ <pre class="program">...
756
+ &lt;h1&gt;<strong>${@title}</strong>&lt;/h1&gt;
757
+
758
+ &lt;div id="main-content"&gt;
759
+ #{@_content}
760
+ &lt;div&gt;
761
+
762
+ &lt;a href="<strong>${@url}</strong>"&gt;Next page&lt;/a&gt;
763
+ ...
764
+ </pre>
765
+ <a name="content7.rbhtml"></a>
766
+ <div class="program_caption">
767
+ File 'content7.rbhtml':</div>
768
+ <pre class="program"><strong>&lt;?rb @title = 'Document Title' ?&gt;</strong>
769
+ <strong>&lt;?rb @url = '/next/page' ?&gt;</strong>
770
+ &lt;table&gt;
771
+ ...content...
772
+ &lt;/table&gt;
773
+ </pre>
774
+ <a name="example7_layout2.result"></a>
775
+ <div class="terminal_caption">
776
+ Result:</div>
777
+ <pre class="terminal">$ rbtenjin --layout=layout7.rbhtml content7.rbhtml
778
+ ...
779
+ &lt;h1&gt;<strong>Document Title</strong>&lt;/h1&gt;
780
+
781
+ &lt;div id="main-content"&gt;
782
+ &lt;table&gt;
783
+ ...content...
784
+ &lt;/table&gt;
785
+
786
+ &lt;div&gt;
787
+
788
+ &lt;a href="<strong>/next/page</strong>"&gt;Next page&lt;/a&gt;
789
+ ...
790
+ </pre>
791
+ <p>Using '@_layout' variable, it is able to specify layout template name in each template file.
792
+ If you assigned false to '@_layout' variable, no layout template is used.
793
+ </p>
794
+ <a name="content8.rbhtml"></a>
795
+ <div class="program_caption">
796
+ File 'content8.rbhtml':</div>
797
+ <pre class="program"><strong>&lt;?rb @_layout = :layout8_xhtml ?&gt;</strong>
798
+ &lt;h1&gt;Hello World!&lt;/h1&gt;
799
+ </pre>
800
+ <a name="layout8_html.rbhtml"></a>
801
+ <div class="program_caption">
802
+ File 'layout8_html.rbhtml':</div>
803
+ <pre class="program">&lt;html&gt;
804
+ &lt;body&gt;
805
+ #{@_content}
806
+ &lt;/body&gt;
807
+ &lt;/html&gt;
808
+ </pre>
809
+ <a name="layout8_xhtml.rbhtml"></a>
810
+ <div class="program_caption">
811
+ File 'layout8_xhtml.rbhtml':</div>
812
+ <pre class="program">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
813
+ &lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
814
+ &lt;body&gt;
815
+ #{@_content}
816
+ &lt;/body&gt;
817
+ &lt;/html&gt;
818
+ </pre>
819
+ <a name="example8_layout3.result"></a>
820
+ <div class="terminal_caption">
821
+ Result: ':layout8_html' is specified in command-line option but ':layout8_xhtml' is used</div>
822
+ <pre class="terminal">$ rbtenjin --postfix='.rbhtml' <strong>--layout=':layout8_html'</strong> content8.rbhtml
823
+ &lt;?xml version="1.0" encoding="UTF-8"?&gt;
824
+ &lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
825
+ &lt;body&gt;
826
+ &lt;h1&gt;Hello World!&lt;/h1&gt;
827
+
828
+ &lt;/body&gt;
829
+ &lt;/html&gt;
830
+ </pre>
831
+ <br>
832
+
833
+
834
+ <a name="des-capturing"></a>
835
+ <h3 class="section2">Capturing</h3>
836
+ <p>It is able to capture any part of template.
837
+ </p>
838
+ <a name="example9.rbhtml"></a>
839
+ <div class="program_caption">
840
+ File 'example9.rbhtml':</div>
841
+ <pre class="program">&lt;?rb @title = 'Capture Test' ?&gt;
842
+ &lt;html&gt;
843
+ &lt;body&gt;
844
+
845
+ <strong>&lt;?rb start_capture(:content_part) ?&gt;</strong>
846
+ &lt;ul&gt;
847
+ &lt;?rb for i in [0, 1, 2] ?&gt;
848
+ &lt;li&gt;i = #{i}&lt;/li&gt;
849
+ &lt;?rb end ?&gt;
850
+ &lt;/ul&gt;
851
+ <strong>&lt;?rb stop_capture() ?&gt;</strong>
852
+
853
+ <strong>&lt;?rb start_capture('footer_part') ?&gt;</strong>
854
+ &lt;div class="footer"&gt;copyright&amp;copy; 2007 kuwata-lab.com&lt;/div&gt;
855
+ <strong>&lt;?rb stop_capture() ?&gt;</strong>
856
+
857
+ &lt;/body&gt;
858
+ &lt;/html&gt;
859
+ </pre>
860
+ <p>Captured strings are accessable as local variables.
861
+ For example, you can get captured string as a variable '<code>content_part</code>' in the above example.
862
+ </p>
863
+ <p>A template can contain several capturing.
864
+ It is not able to nest capturing.
865
+ </p>
866
+ <p>In layout file, it is able to use strings captured in templates.
867
+ </p>
868
+ <a name="layout9.rbhtml"></a>
869
+ <div class="program_caption">
870
+ File 'layout9.rbhtml':</div>
871
+ <pre class="program">&lt;html lang="en"&gt;
872
+ &lt;head&gt;
873
+ &lt;title&gt;${@title}&lt;/title&gt;
874
+ &lt;/head&gt;
875
+ &lt;body&gt;
876
+
877
+ &lt;!-- HEADER --&gt;
878
+ <strong>&lt;?rb unless captured_as('header_part') ?&gt;</strong>
879
+ &lt;h1&gt;${@title}&lt;/h1&gt;
880
+ <strong>&lt;?rb end ?&gt;</strong>
881
+ &lt;!-- /HEADER --&gt;
882
+
883
+ &lt;!-- CONTENT --&gt;
884
+ <strong>#{@content_part}</strong>
885
+ &lt;!-- /CONTENT --&gt;
886
+
887
+ &lt;!-- FOOTER --&gt;
888
+ <strong>&lt;?rb unless captured_as('footer_part') ?&gt;</strong>
889
+ &lt;hr /&gt;
890
+ &lt;address&gt;webmaster@localhost&lt;/address&gt;
891
+ <strong>&lt;?rb end ?&gt;</strong>
892
+ &lt;!-- /FOOTER --&gt;
893
+
894
+ &lt;/body&gt;
895
+ &lt;/html&gt;
896
+ </pre>
897
+ <p>'<code>unless captured_as("name") ... end</code>' is equivarent to the following.
898
+ </p>
899
+ <pre class="program">&lt;?rb if @name ?&gt;
900
+ &lt;?rb _buf &lt;&lt; @name ?&gt;
901
+ &lt;?rb else ?&gt;
902
+ ...
903
+ &lt;?rb end ?&gt;
904
+ </pre>
905
+ <p>The following result shows that content part and footer part are overrided by capturing in content template but header part is not.
906
+ </p>
907
+ <a name="example9_capture.result"></a>
908
+ <div class="terminal_caption">
909
+ Result:</div>
910
+ <pre class="terminal">$ rbtenjin --layout=layout9.rbhtml example9.rbhtml
911
+ &lt;html lang="en"&gt;
912
+ &lt;head&gt;
913
+ &lt;title&gt;Capture Test&lt;/title&gt;
914
+ &lt;/head&gt;
915
+ &lt;body&gt;
916
+
917
+ &lt;!-- HEADER --&gt;
918
+ &lt;h1&gt;Capture Test&lt;/h1&gt;
919
+ &lt;!-- /HEADER --&gt;
920
+
921
+ &lt;!-- CONTENT --&gt;
922
+ <strong>&lt;ul&gt;</strong>
923
+ <strong>&lt;li&gt;i = 0&lt;/li&gt;</strong>
924
+ <strong>&lt;li&gt;i = 1&lt;/li&gt;</strong>
925
+ <strong>&lt;li&gt;i = 2&lt;/li&gt;</strong>
926
+ <strong>&lt;/ul&gt;</strong>
927
+
928
+ &lt;!-- /CONTENT --&gt;
929
+
930
+ &lt;!-- FOOTER --&gt;
931
+ <strong>&lt;div class="footer"&gt;copyright&amp;copy; 2007 kuwata-lab.com&lt;/div&gt;</strong>
932
+ &lt;!-- /FOOTER --&gt;
933
+
934
+ &lt;/body&gt;
935
+ &lt;/html&gt;
936
+ </pre>
937
+ <br>
938
+
939
+
940
+ <a name="des-args"></a>
941
+ <h3 class="section2">Template Arguments</h3>
942
+ <p>It is able to specify template arguments in template files.
943
+ Template arguments are variables which are passed by main program via context object.
944
+ In the following example, '<code>title</code>' and '<code>name</code>' are template arguments.
945
+ </p>
946
+ <a name="example10.rbhtml"></a>
947
+ <div class="program_caption">
948
+ File 'example10.rbhtml':</div>
949
+ <pre class="program">&lt;?xml version="1.0"?&gt;
950
+ <strong>&lt;?rb #@ARGS title, name ?&gt;</strong>
951
+ &lt;h1&gt;${title}&lt;/h1&gt;
952
+ &lt;p&gt;Hello ${name}!&lt;/p&gt;
953
+ </pre>
954
+ <p>Template arguments line is converted into assignment statements of local variables.
955
+ </p>
956
+ <a name="example10_template_args.result"></a>
957
+ <pre class="terminal">$ rbtenjin -s example10.rbhtml
958
+ _buf = ''; _buf &lt;&lt; %Q`&lt;?xml version="1.0"?&gt;\n`
959
+ <strong> title = @title; name = @name;</strong>
960
+ _buf &lt;&lt; %Q`&lt;h1&gt;#{escape((title).to_s)}&lt;/h1&gt;
961
+ &lt;p&gt;Hello #{escape((name).to_s)}!&lt;/p&gt;\n`
962
+ _buf.to_s
963
+ </pre>
964
+ <p>If template arguments are specified, other variables passed by context object are not set.
965
+ </p>
966
+ <a name="example11.rbhtml"></a>
967
+ <div class="program_caption">
968
+ File 'example11.rbhtml':</div>
969
+ <pre class="program">&lt;p&gt;
970
+ <strong>&lt;?rb #@ARGS x ?&gt;</strong>
971
+ x = #{x}
972
+ y = #{y} # NameError
973
+ &lt;/p&gt;
974
+ </pre>
975
+ <a name="example11_template_args_result"></a>
976
+ <div class="terminal_caption">
977
+ Result:</div>
978
+ <pre class="terminal">$ rbtenjin <strong>-c '@x=10;@y=20'</strong> example11.rbhtml
979
+ example12.rbhtml:4:in `_render': undefined local variable or method `y' (NameError)
980
+ </pre>
981
+ <br>
982
+
983
+
984
+ <a name="des-preprocess"></a>
985
+ <h3 class="section2">Preprocessing</h3>
986
+ <p>rbTenjin supports preprocessing of template.
987
+ Preprocessing executes some logics when templates are loaded and that logics are not executed when rendering.
988
+ Preprocessing makes your application much faster.
989
+ </p>
990
+ <p>Notation of preprocessing is the following.
991
+ </p>
992
+ <ul type="disc">
993
+ <li><code>&lt;?RB ... ?&gt;</code> represents preprocessing statement.
994
+ </li>
995
+ <li><code>#{{...}}</code> represents preprocessing expression (without HTML escape).
996
+ </li>
997
+ <li><code>${{...}}</code> represents preprocessing expression (with HTML escape).
998
+ </li>
999
+ </ul>
1000
+ <p>For example, assume the following template.
1001
+ </p>
1002
+ <a name="example12.rbhtml"></a>
1003
+ <div class="program_caption">
1004
+ File 'example12.rbhtml':</div>
1005
+ <pre class="program"><strong>&lt;?RB states = { "CA" =&gt; "California", ?&gt;</strong>
1006
+ <strong>&lt;?RB "NY" =&gt; "New York", ?&gt;</strong>
1007
+ <strong>&lt;?RB "FL" =&gt; "Florida", ?&gt;</strong>
1008
+ <strong>&lt;?RB "TX" =&gt; "Texas", ?&gt;</strong>
1009
+ <strong>&lt;?RB "HI" =&gt; "Hawaii", } ?&gt;</strong>
1010
+ &lt;?rb chk = { @params['state'] =&gt; ' selected="selected"' } ?&gt;
1011
+ &lt;select name="state"&gt;
1012
+ &lt;option value=""&gt;-&lt;/option&gt;
1013
+ <strong>&lt;?RB for code in states.keys.sort ?&gt;</strong>
1014
+ &lt;option value="<strong>#{{code}}</strong>"#{chk[<strong>#{{code.inspect}}</strong>]}&gt;<strong>${{states[code]}}</strong>&lt;/option&gt;
1015
+ <strong>&lt;?RB end ?&gt;</strong>
1016
+ &lt;/select&gt;
1017
+ </pre>
1018
+ <p>If preprocessing is activated, the above will be converted into the following when template is loaded.
1019
+ (Command-line option <code>-P</code> shows the result of preprocessing.)
1020
+ </p>
1021
+ <a name="example12_preprocessed.result"></a>
1022
+ <div class="terminal_caption">
1023
+ Result of preprocessing:</div>
1024
+ <pre class="terminal">$ rbtenjin <strong>-P</strong> example12.rbhtml
1025
+ &lt;?rb chk = { @params['state'] =&gt; ' selected="selected"' } ?&gt;
1026
+ &lt;select name="state"&gt;
1027
+ &lt;option value=""&gt;-&lt;/option&gt;
1028
+ &lt;option value="CA"#{chk["CA"]}&gt;California&lt;/option&gt;
1029
+ &lt;option value="FL"#{chk["FL"]}&gt;Florida&lt;/option&gt;
1030
+ &lt;option value="HI"#{chk["HI"]}&gt;Hawaii&lt;/option&gt;
1031
+ &lt;option value="NY"#{chk["NY"]}&gt;New York&lt;/option&gt;
1032
+ &lt;option value="TX"#{chk["TX"]}&gt;Texas&lt;/option&gt;
1033
+ &lt;/select&gt;
1034
+ </pre>
1035
+ <p>This means that for-loop is executed only once when template is loaded and is not executed when rendering.
1036
+ In the result, rendering speed becomes to be much faster.
1037
+ </p>
1038
+ <p>And the Ruby code is here. This shows that there is no for-loop.
1039
+ </p>
1040
+ <a name="example12_preprocessed_source.result"></a>
1041
+ <div class="terminal_caption">
1042
+ Translated script code:</div>
1043
+ <pre class="terminal">$ rbtenjin <strong>--preprocess</strong> -sb example12.rbhtml
1044
+ chk = { @params['state'] =&gt; ' selected="selected"' }
1045
+ _buf &lt;&lt; %Q`&lt;select name="state"&gt;
1046
+ &lt;option value=""&gt;-&lt;/option&gt;
1047
+ &lt;option value="CA"#{chk["CA"]}&gt;California&lt;/option&gt;
1048
+ &lt;option value="FL"#{chk["FL"]}&gt;Florida&lt;/option&gt;
1049
+ &lt;option value="HI"#{chk["HI"]}&gt;Hawaii&lt;/option&gt;
1050
+ &lt;option value="NY"#{chk["NY"]}&gt;New York&lt;/option&gt;
1051
+ &lt;option value="TX"#{chk["TX"]}&gt;Texas&lt;/option&gt;
1052
+ &lt;/select&gt;\n`
1053
+ </pre>
1054
+ <p>If you have errors on preprocessing, you should check source script by <code>-Ps</code> option<sup>(<a href="#fnref:1" name="fnlink:1">*1</a>)</sup>.
1055
+ </p>
1056
+ <p>The following is an another example.
1057
+ Assume that <code>link_to()</code> is a helper method which takes label and url and generate
1058
+ <code>&lt;a&gt;&lt;/a&gt;</code> tag.
1059
+ In this case, label and url can be parameterized by <code>_p("...")</code> and <code>_P("...")</code>.
1060
+ The former is converted into <code>#{...}</code> and the latter converted into <code>${...}</code>
1061
+ by preprocessor.
1062
+ </p>
1063
+ <a name="example13.rbhtml"></a>
1064
+ <div class="program_caption">
1065
+ File 'example13.rbhtml':</div>
1066
+ <pre class="program">&lt;?RB require 'cgi' ?&gt;
1067
+ &lt;?RB ## ex. link_to('Show', '/show/1') =&gt; &lt;a href="/show/1"&gt;Show&lt;/a&gt; ?&gt;
1068
+ &lt;?RB def link_to(label, url) ?&gt;
1069
+ &lt;?RB return "&lt;a href=\"#{CGI.unescape(url)}\"&gt;#{label}&lt;/a&gt;" ?&gt;
1070
+ &lt;?RB end ?&gt;
1071
+ #{{link_to 'Show '+<strong>_P('@params["name"]')</strong>, '/items/show/'+<strong>_p('@params["id"]')</strong>}}
1072
+ </pre>
1073
+ <a name="example13_preprocessed.result"></a>
1074
+ <div class="terminal_caption">
1075
+ Preprocessed template:</div>
1076
+ <pre class="terminal">$ rbtenjin <strong>-P</strong> example13.rbhtml
1077
+ &lt;a href="/items/show/<strong>#{@params["id"]}"</strong>&gt;Show <strong>${@params["name"]}</strong>&lt;/a&gt;
1078
+ </pre>
1079
+ <a name="example13_preprocessed_source.result"></a>
1080
+ <div class="terminal_caption">
1081
+ Translated script code:</div>
1082
+ <pre class="terminal">$ rbtenjin <strong>--preprocess</strong> -sb example13.rbhtml
1083
+ _buf &lt;&lt; %Q`&lt;a href="/items/show/<strong>#{@params["id"]}</strong>"&gt;Show <strong>#{escape((@params["name"]).to_s)}</strong>&lt;/a&gt;\n`
1084
+ </pre>
1085
+ <p>There are many web-application framework and they provides helper functions.
1086
+ These helper functions are divided into two groups.
1087
+ </p>
1088
+ <ul type="disc">
1089
+ <li><code>link_to()</code> or <code>_()</code> (function for M17N) return the same result
1090
+ when the same arguments are passed.
1091
+ These functions can be expanded by preprocessor.
1092
+ </li>
1093
+ <li>Some functions return the different result even if the same arguments are passed.
1094
+ These functions can't be expaned by preprocessor.
1095
+ </li>
1096
+ </ul>
1097
+ <p>Preprocessor has the power to make your application much faster,
1098
+ but it may make the debugging difficult.
1099
+ You should use it carefully.
1100
+ </p>
1101
+ <div class="footnote">
1102
+ <dl compact>
1103
+ <dt>(<a name="fnref:1" href="#fnlink:1">*1</a>)</dt>
1104
+ <dd>Command-line option '-Ps' is available but '-PS' is not availabe. This is a current restriction of rbtenjin. </dd>
1105
+ </dl>
1106
+ </div>
1107
+ <br>
1108
+
1109
+
1110
+ <a name="des-otheropts"></a>
1111
+ <h3 class="section2">Other Options</h3>
1112
+ <ul type="disc">
1113
+ <li>Command-line option '<code>--escapefunc=func1</code>' changes <code>escape()</code> function name to <code>func1</code>.
1114
+ For example, '<code>--escapefunc=h</code>' changes escape function from <code>escape()</code> to <code>h()</code>.
1115
+ </li>
1116
+ <li>It is not able to contain '<code>}</code>' character in '<code>${...}</code>'.
1117
+ For example, '<code>${hash["}"]}</code>' will be converted into '<code>_buf &lt;&lt; %Q`#{escape((hash[").to_s)}"]}</code>` and not '<code>_buf &lt;&lt; %Q`#{escape((hash["}"]).to_s)}`</code>'.
1118
+ There is no such restriction about '<code>#{...}</code>'.
1119
+ </li>
1120
+ <li>It is not able to contain '<code>\</code>' and '<code>`</code>' characters in '<code>#{...}</code>'
1121
+ because these characters are escaped.
1122
+ For example, '<code>#{hash["\n"]}</code>' will be converted into '<code>_buf &lt;&lt; %Q`hash["\n"]`</code>'.
1123
+ There is no such restriction about '<code>${...}</code>'.
1124
+ </li>
1125
+ <li>Command-line option '<code>--path=dir1,dir2,...</code>' sepcifies template directory path.
1126
+ </li>
1127
+ </ul>
1128
+ <br>
1129
+
1130
+
1131
+ <br>
1132
+
1133
+
1134
+ <a name="devguide"></a>
1135
+ <h2 class="section1">Developer's Guide</h2>
1136
+ <p>This section shows how to use rbTenjin in your Ruby script.
1137
+ </p>
1138
+ <p>If you want to know the notation or features of rbTenjin, see <a href="#desguide">Designer's Guide</a> section.
1139
+ </p>
1140
+ <a name="dev-example"></a>
1141
+ <h3 class="section2">An Example</h3>
1142
+ <p>The following is an example to use rbTenjin in Ruby.
1143
+ </p>
1144
+ <div class="program_caption">
1145
+ Example:</div>
1146
+ <pre class="program">require 'tenjin'
1147
+ engine = Tenjin::Engine.new()
1148
+ context = { :title=&gt;'rbTenjin Example', :items=&gt;['AAA', 'BBB', 'CCC'] }
1149
+ filename = 'file.rbhtml'
1150
+ output = engine.render(filename, context)
1151
+ print output
1152
+ </pre>
1153
+ <br>
1154
+
1155
+
1156
+ <a name="dev-classes"></a>
1157
+ <h3 class="section2">Classes and Functions in rbTenjin</h3>
1158
+ <p>rbTenjin has the follwoing classes.
1159
+ </p>
1160
+ <dl class="dl3">
1161
+ <dt class="dt3"><b>
1162
+ Tenjin::Template </b></dt>
1163
+ <dd class="dd3">
1164
+ This class represents a template file.
1165
+ An object of Tenjin::Template correspond to a template file.
1166
+ </dd>
1167
+ </dl>
1168
+ <dl class="dl3">
1169
+ <dt class="dt3"><b>
1170
+ Tenjin::Engine </b></dt>
1171
+ <dd class="dd3">
1172
+ This class represents some template objects.
1173
+ It can handle nested template and layout template.
1174
+ Using Tenjin::Engine class, you can use rbTenjin as a template engine for web application.
1175
+ </dd>
1176
+ </dl>
1177
+ <dl class="dl3">
1178
+ <dt class="dt3"><b>
1179
+ Tenjin::Context </b></dt>
1180
+ <dd class="dd3">
1181
+ This class represents context data.
1182
+ </dd>
1183
+ </dl>
1184
+ <p>rbTenjin has the following utility functions.
1185
+ These are defined at Tenjin::HtmlHelper module and Tenjin::Context class includes it.
1186
+ </p>
1187
+ <br>
1188
+
1189
+
1190
+ <a name="dev-templateclass"></a>
1191
+ <h3 class="section2">Class Tenjin::Template</h3>
1192
+ <p>Tenjin::Template class represents a template file.
1193
+ An object of Tenjin::Template corresponds to a template file.
1194
+ It doesn't support nested template nor layout template (use Tenjin::Engine class instead).
1195
+ </p>
1196
+ <p>This class has the following methods and attributes.
1197
+ </p>
1198
+ <dl class="dl3">
1199
+ <dt class="dt3"><b>
1200
+ Tenjin::Template.new(filename=nil, :escapefunc=&gt;'escape') </b></dt>
1201
+ <dd class="dd3">
1202
+ Create template object. If filename is given, read and convert it to Ruby code.
1203
+ </dd>
1204
+ </dl>
1205
+ <dl class="dl3">
1206
+ <dt class="dt3"><b>
1207
+ Tenjin::Template#convert(input, filename=None) </b></dt>
1208
+ <dd class="dd3">
1209
+ Convert input text into Ruby code and return it.
1210
+ </dd>
1211
+ </dl>
1212
+ <dl class="dl3">
1213
+ <dt class="dt3"><b>
1214
+ Tenjin::Template#convert_file(filename) </b></dt>
1215
+ <dd class="dd3">
1216
+ Convert file into Ruby code and return it.
1217
+ This is equivarent to <code>Tenjin::Template#convert(File.read(filename), filename)</code>
1218
+ </dd>
1219
+ </dl>
1220
+ <dl class="dl3">
1221
+ <dt class="dt3"><b>
1222
+ Tenjin::Template#render(context=nil) </b></dt>
1223
+ <dd class="dd3">
1224
+ Compile Ruby code, evaluate it with context data, and return the result of evaluation.
1225
+ </dd>
1226
+ </dl>
1227
+ <dl class="dl3">
1228
+ <dt class="dt3"><b>
1229
+ Tenjin::Template#script </b></dt>
1230
+ <dd class="dd3">
1231
+ Converted Ruby code
1232
+ </dd>
1233
+ </dl>
1234
+ <p>The followings are examples to use Tenjin::Template in Ruby script.
1235
+ </p>
1236
+ <a name="example14.rbhtml"></a>
1237
+ <div class="program_caption">
1238
+ File 'example14.rbhtml':</div>
1239
+ <pre class="program">&lt;h1&gt;#{@title}&lt;/h1&gt;
1240
+ &lt;ul&gt;
1241
+ &lt;?rb for item in @items ?&gt;
1242
+ &lt;li&gt;${item}&lt;/li&gt;
1243
+ &lt;?rb end ?&gt;
1244
+ &lt;/ul&gt;
1245
+ </pre>
1246
+ <a name="example14.rb"></a>
1247
+ <div class="program_caption">
1248
+ File 'example14.rb':</div>
1249
+ <pre class="program">## template file
1250
+ filename = 'example14.rbhtml'
1251
+
1252
+ ## convert into ruby code
1253
+ require 'tenjin'
1254
+ template = <strong>Tenjin::Template.new(filename)</strong>
1255
+ ## or
1256
+ # template = Tenjin::Template.new()
1257
+ # script = <strong>template.convert_file(filename)</strong>
1258
+ ## or
1259
+ # template = Tenjin::Template.new()
1260
+ # input = File.read(filename)
1261
+ # script = <strong>template.convert(input, filename)</strong> # filename is optional
1262
+
1263
+ ## show converted ruby code
1264
+ puts "---- ruby code ----"
1265
+ puts <strong>template.script</strong>
1266
+
1267
+ ## evaluate ruby code
1268
+ hash = {:title=&gt;'rbTenjin Example', :items=&gt;['&lt;AAA&gt;','B&amp;B','"CCC"']}
1269
+ output = <strong>template.render(hash)</strong>
1270
+ puts "---- output ----"
1271
+ puts output
1272
+ ## or
1273
+ #hash = {:title=&gt;'rbTenjin Example', :items=&gt;['&lt;AAA&gt;','B&amp;B','"CCC"']}
1274
+ #context = <strong>Tenjin::Context.new(hash)</strong>
1275
+ #output = <strong>template.render(context)</strong>
1276
+ ## or
1277
+ # context = Tenjin::Context.new
1278
+ # context[:title] = 'rbTenjin Example'
1279
+ # context[:items] = ['&lt;AAA&gt;','B&amp;B','"CCC"']
1280
+ # output = template.render(context)
1281
+ </pre>
1282
+ <a name="example14_tmplclass.result"></a>
1283
+ <div class="terminal_caption">
1284
+ Result:</div>
1285
+ <pre class="terminal">$ ruby example14.rb
1286
+ ---- ruby code ----
1287
+ _buf &lt;&lt; %Q`&lt;h1&gt;#{@title}&lt;/h1&gt;
1288
+ &lt;ul&gt;\n`
1289
+ for item in @items
1290
+ _buf &lt;&lt; %Q` &lt;li&gt;#{escape((item).to_s)}&lt;/li&gt;\n`
1291
+ end
1292
+ _buf &lt;&lt; %Q`&lt;/ul&gt;\n`
1293
+ ---- output ----
1294
+ &lt;h1&gt;rbTenjin Example&lt;/h1&gt;
1295
+ &lt;ul&gt;
1296
+ &lt;li&gt;&amp;lt;AAA&amp;gt;&lt;/li&gt;
1297
+ &lt;li&gt;B&amp;amp;B&lt;/li&gt;
1298
+ &lt;li&gt;&amp;quot;CCC&amp;quot;&lt;/li&gt;
1299
+ &lt;/ul&gt;
1300
+ </pre>
1301
+ <br>
1302
+
1303
+
1304
+ <a name="dev-engineclass"></a>
1305
+ <h3 class="section2">Class Tenjin::Engine</h3>
1306
+ <p>Tenjin::Engine class contains some template objects.
1307
+ It can handle nested template and layout template.
1308
+ Using Tenjin::Engine class, you can use rbTenjin as a template engine for web application.
1309
+ </p>
1310
+ <p>This class has the following methods.
1311
+ </p>
1312
+ <dl class="dl3">
1313
+ <dt class="dt3"><b>
1314
+ Tenjin::Engine.new(:prefix=&gt;'', :postfix=&gt;'', :layout=&gt;nil, :path=nil, :cache=&gt;true, :preprocess=&gt;false, :templateclass=&gt;Tenjin::Template) </b></dt>
1315
+ <dd class="dd3">
1316
+ Create Engine object.
1317
+ <code>:path</code> represents template search path and it should be an Array of directory name.
1318
+ Other arguments are passed to Tenjin::Template.new() internally.
1319
+ </dd>
1320
+ </dl>
1321
+ <dl class="dl3">
1322
+ <dt class="dt3"><b>
1323
+ Tenjin::Engine#render(template_name, context=nil, layout=nil) </b></dt>
1324
+ <dd class="dd3">
1325
+ Convert template into Ruby code, evaluate it with context data, and return the result of it.
1326
+ If <code>layout</code> is true or nil then layout template name specified by constructor option is
1327
+ used as layout template, else if false then layout template is not used,
1328
+ else if string then it is regarded as layout template name.
1329
+ </dd>
1330
+ </dl>
1331
+ <p>Argument <code>template_name</code> in render() methods is filename or short name of template.
1332
+ Template short name is a Symbol.
1333
+ For example, '<code>render(:list, context)</code>' is equivarent to '<code>render("user_list.rbhtml", context)</code>' if prefix option is '<code>user_</code>' and postfix option is '<code>.rbhtml</code>'.
1334
+ </p>
1335
+ <p>In template file, the followings are available.
1336
+ </p>
1337
+ <dl class="dl3">
1338
+ <dt class="dt3"><b>
1339
+ @_content </b></dt>
1340
+ <dd class="dd3">
1341
+ This variable represents the result of evaluation of other template.
1342
+ This is available only in layout template file.
1343
+ </dd>
1344
+ </dl>
1345
+ <dl class="dl3">
1346
+ <dt class="dt3"><b>
1347
+ import(template_name) </b></dt>
1348
+ <dd class="dd3">
1349
+ Include and evaluate other template.
1350
+ This method is an instance method of Tenjin::Context class.
1351
+ </dd>
1352
+ </dl>
1353
+ <dl class="dl3">
1354
+ <dt class="dt3"><b>
1355
+ start_capture(name) </b></dt>
1356
+ <dd class="dd3">
1357
+ Start capturing. Result will be stored into <code>@<em>name</em></code>.
1358
+ </dd>
1359
+ </dl>
1360
+ <dl class="dl3">
1361
+ <dt class="dt3"><b>
1362
+ stop_capture() </b></dt>
1363
+ <dd class="dd3">
1364
+ Stop capturing.
1365
+ </dd>
1366
+ </dl>
1367
+ <dl class="dl3">
1368
+ <dt class="dt3"><b>
1369
+ captured_as(varname) </b></dt>
1370
+ <dd class="dd3">
1371
+ If captured string as <em>varname</em> is exist then append it into
1372
+ <code>@_buf</code> and return true, else return false.
1373
+ This is a helper function for layout template.
1374
+ </dd>
1375
+ </dl>
1376
+ <p>The followings are example of Tenjin::Engine class.
1377
+ </p>
1378
+ <a name="user_form.rbhtml"></a>
1379
+ <div class="program_caption">
1380
+ File 'user_form.rbhtml':</div>
1381
+ <pre class="program">&lt;?rb #@ARGS params ?&gt;
1382
+ &lt;p&gt;
1383
+ Name: &lt;input type="text" name="name" value="${params['name']}" /&gt;&lt;br /&gt;
1384
+ Email: &lt;input type="text" name="email" value="${params['email']}" /&gt;&lt;br /&gt;
1385
+ Gender:
1386
+ &lt;?rb gender = @params['gender'] ?&gt;
1387
+ &lt;?rb chk = { true=&gt;' checked="checked"', false=&gt;'' } ?&gt;
1388
+ &lt;input type="radio" name="gender" value="m" #{chk[gender=='m']} /&gt;Male
1389
+ &lt;input type="radio" name="gender" value="f" #{chk[gender=='f']} /&gt;Female
1390
+ &lt;/p&gt;
1391
+ </pre>
1392
+ <a name="user_create.rbhtml"></a>
1393
+ <div class="program_caption">
1394
+ File 'user_create.rbhtml':</div>
1395
+ <pre class="program">&lt;?rb #@ARGS ?&gt;
1396
+ &lt;form action="user_app.cgi" method="post"&gt;
1397
+ &lt;input type="hidden" name="action" value="create" /&gt;
1398
+ <strong>&lt;?rb import :form ?&gt;</strong>
1399
+ &lt;input type="submit" value="Create" /&gt;
1400
+ &lt;/form&gt;
1401
+ </pre>
1402
+ <a name="user_edit.rbhtml"></a>
1403
+ <div class="program_caption">
1404
+ File 'user_edit.rbhtml':</div>
1405
+ <pre class="program">&lt;?rb #@ARGS params ?&gt;
1406
+ &lt;form action="user_app.cgi" method="post"&gt;
1407
+ &lt;input type="hidden" name="action" value="edit" /&gt;
1408
+ &lt;input type="hidden" name="id" value="${params['id']}" /&gt;
1409
+ <strong>&lt;?rb import :form ?&gt;</strong>
1410
+ &lt;input type="submit" value="Edit" /&gt;
1411
+ &lt;/form&gt;
1412
+ </pre>
1413
+ <a name="user_layout.rbhtml"></a>
1414
+ <div class="program_caption">
1415
+ File 'user_layout.rbhtml':</div>
1416
+ <pre class="program">&lt;?rb #@ARGS _content, title ?&gt;
1417
+ &lt;html&gt;
1418
+ &lt;body&gt;
1419
+
1420
+ &lt;h1&gt;${title}&lt;/h1&gt;
1421
+
1422
+ &lt;div id="main-content"&gt;
1423
+ <strong>#{_content}</strong>
1424
+ &lt;/div&gt;
1425
+
1426
+ &lt;div id="footer"&gt;
1427
+ <strong>&lt;?rb import 'footer.html' ?&gt;</strong>
1428
+ &lt;/div&gt;
1429
+
1430
+ &lt;/body&gt;
1431
+ &lt;/html&gt;
1432
+ </pre>
1433
+ <a name="footer.html"></a>
1434
+ <div class="program_caption">
1435
+ File 'footer.html':</div>
1436
+ <pre class="program">&lt;?rb #@ARGS ?&gt;
1437
+ &lt;hr /&gt;
1438
+ &lt;address&gt;
1439
+ &lt;a href="mailto:webmaster@example.com"&gt;webmaster@example.com&lt;/a&gt;
1440
+ &lt;/address&gt;
1441
+ </pre>
1442
+ <a name="user_app.cgi"></a>
1443
+ <div class="program_caption">
1444
+ File 'user_app.cgi':</div>
1445
+ <pre class="program">#!/usr/bin/env ruby
1446
+
1447
+ require 'cgi'
1448
+ <strong>require 'tenjin'</strong>
1449
+
1450
+ ## set action ('create' or 'edit')
1451
+ action = nil
1452
+ cgi = nil
1453
+ if ENV['REQUEST_METHOD']
1454
+ cgi = CGI.new
1455
+ action = cgi['action']
1456
+ elsif ARGV[0]
1457
+ action = ARGV[0]
1458
+ end
1459
+ action = 'create' unless ['create', 'edit'].include?(action)
1460
+
1461
+ ## set context data
1462
+ if action == 'create'
1463
+ title = 'Create User'
1464
+ params = {}
1465
+ else
1466
+ title = 'Edit User'
1467
+ params = {:name=&gt;'Margalette',
1468
+ :email=&gt;'meg@example.com',
1469
+ :gender=&gt;'f',
1470
+ :id=&gt;123 }
1471
+ end
1472
+ <strong>context = { :title=&gt;title, :params=&gt;params }</strong>
1473
+ <strong># or context = Tenjin::Context.new(:title=&gt;title, :params=&gt;params)</strong>
1474
+
1475
+ ## create engine object
1476
+ layout = :layout # or 'user_layout.rbhtml'
1477
+ <strong>engine = Tenjin::Engine.new(:prefix=&gt;'user_', :postfix=&gt;'.rbhtml', :layout=&gt;layout)</strong>
1478
+
1479
+ ## evaluate template
1480
+ template_name = action.intern # :create or :edit
1481
+ <strong>output = engine.render(template_name, context)</strong>
1482
+ print cgi.header() if cgi
1483
+ print output
1484
+ </pre>
1485
+ <a name="user_app.result"></a>
1486
+ <div class="terminal_caption">
1487
+ Result:</div>
1488
+ <pre class="terminal">$ ruby user_app.cgi create
1489
+ &lt;html&gt;
1490
+ &lt;body&gt;
1491
+
1492
+ &lt;h1&gt;Create User&lt;/h1&gt;
1493
+
1494
+ &lt;div id="main-content"&gt;
1495
+ <strong>&lt;form action="user_app.cgi" method="post"&gt;</strong>
1496
+ <strong> &lt;input type="hidden" name="action" value="create" /&gt;</strong>
1497
+ <strong>&lt;p&gt;</strong>
1498
+ <strong> Name: &lt;input type="text" name="name" value="" /&gt;&lt;br /&gt;</strong>
1499
+ <strong> Email: &lt;input type="text" name="email" value="" /&gt;&lt;br /&gt;</strong>
1500
+ <strong> Gender:</strong>
1501
+ <strong> &lt;input type="radio" name="gender" value="m" /&gt;Male</strong>
1502
+ <strong> &lt;input type="radio" name="gender" value="f" /&gt;Female</strong>
1503
+ <strong>&lt;/p&gt;</strong>
1504
+ <strong> &lt;input type="submit" value="Create" /&gt;</strong>
1505
+ <strong>&lt;/form&gt;</strong>
1506
+
1507
+ &lt;/div&gt;
1508
+
1509
+ &lt;div id="footer"&gt;
1510
+ <strong>&lt;hr /&gt;</strong>
1511
+ <strong>&lt;address&gt;</strong>
1512
+ <strong> &lt;a href="mailto:webmaster@example.com"&gt;webmaster@example.com&lt;/a&gt;</strong>
1513
+ <strong>&lt;/address&gt;</strong>
1514
+ &lt;/div&gt;
1515
+
1516
+ &lt;/body&gt;
1517
+ &lt;/html&gt;
1518
+ </pre>
1519
+ <br>
1520
+
1521
+
1522
+ <a name="dev-initopts"></a>
1523
+ <h3 class="section2">Template Initialize Options</h3>
1524
+ <p>Tenjin::Template() can take the follwoing options.
1525
+ </p>
1526
+ <ul type="disc">
1527
+ <li>'<code>escapefunc</code>' (string) specifies function name to escape string.
1528
+ Default is '<code>escape</code>' (= <code>Tenjin::Context#escape</code>).
1529
+ </li>
1530
+ </ul>
1531
+ <p>Constructor of Tenjin::Engine can also take the same options as above.
1532
+ These options given to constructor of Tenjin::Engine are passed to constructor of Tenjin::Template internally.
1533
+ </p>
1534
+ <a name="example15.rb"></a>
1535
+ <div class="program_caption">
1536
+ File 'example15.rb':</div>
1537
+ <pre class="program">require 'tenjin'
1538
+ filename = 'example14.rbhtml'
1539
+ template = Tenjin::Template.new(filename, <strong>:escapefunc=&gt;'CGI.escapeHTML'</strong>)
1540
+ print template.script, "\n"
1541
+
1542
+ require 'cgi'
1543
+ title = 'rbTenjin Example'
1544
+ items = ['&lt;foo&gt;', '&amp;bar', '"baz"']
1545
+ output = template.render(:title=&gt;title, :items=&gt;items)
1546
+ print output
1547
+ </pre>
1548
+ <a name="example15_escapefunc.result"></a>
1549
+ <div class="terminal_caption">
1550
+ Result:</div>
1551
+ <pre class="terminal">$ ruby example15.rb
1552
+ _buf &lt;&lt; %Q`&lt;h1&gt;#{@title}&lt;/h1&gt;
1553
+ &lt;ul&gt;\n`
1554
+ for item in @items
1555
+ _buf &lt;&lt; %Q` &lt;li&gt;#{<strong>CGI.escapeHTML</strong>((item).to_s)}&lt;/li&gt;\n`
1556
+ end
1557
+ _buf &lt;&lt; %Q`&lt;/ul&gt;\n`
1558
+
1559
+ &lt;h1&gt;rbTenjin Example&lt;/h1&gt;
1560
+ &lt;ul&gt;
1561
+ &lt;li&gt;&amp;lt;foo&amp;gt;&lt;/li&gt;
1562
+ &lt;li&gt;&amp;amp;bar&lt;/li&gt;
1563
+ &lt;li&gt;&amp;quot;baz&amp;quot;&lt;/li&gt;
1564
+ &lt;/ul&gt;
1565
+ </pre>
1566
+ <br>
1567
+
1568
+
1569
+ <a name="dev-helpers"></a>
1570
+ <h3 class="section2">Add Your Helper Functions</h3>
1571
+ <p>There are several ways to use helper functions.
1572
+ </p>
1573
+ <p>Assume the following template.
1574
+ </p>
1575
+ <a name="example16.rbhtml"></a>
1576
+ <div class="program_caption">
1577
+ File 'example16.rbhtml':</div>
1578
+ <pre class="program">&lt;?rb #@ARGS label, url ?&gt;
1579
+ &lt;ul&gt;
1580
+ &lt;li&gt;#{<strong>link_to(label, url)</strong>}&lt;/li&gt;
1581
+ &lt;/ul&gt;
1582
+ </pre>
1583
+ <p>(A) Define helper functions as global function.
1584
+ </p>
1585
+ <a name="example16a.rb"></a>
1586
+ <div class="program_caption">
1587
+ File 'example16a.rb':</div>
1588
+ <pre class="program">require 'tenjin'
1589
+
1590
+ def link_to(label, url)
1591
+ return "&lt;a href=\"#{escape_xml(url)}\"&gt;#{escape_xml(label)}&lt;/a&gt;"
1592
+ end
1593
+
1594
+ engine = Tenjin::Engine.new()
1595
+ context = { :label=&gt;'Top', :url=&gt;'/' }
1596
+ output = engine.render('example16.rbhtml', context)
1597
+ print output
1598
+ </pre>
1599
+ <a name="example16a.result"></a>
1600
+ <div class="terminal_caption">
1601
+ Result:</div>
1602
+ <pre class="terminal">$ ruby example16a.rb
1603
+ &lt;ul&gt;
1604
+ &lt;li&gt;&lt;a href="/"&gt;Top&lt;/a&gt;&lt;/li&gt;
1605
+ &lt;/ul&gt;
1606
+ </pre>
1607
+ <p>(B) Define helper functions as module function of Tenjin::ContextHelper module.
1608
+ </p>
1609
+ <a name="example16b.rb"></a>
1610
+ <div class="program_caption">
1611
+ File 'example16b.rb':</div>
1612
+ <pre class="program">require 'tenjin'
1613
+
1614
+ <strong>module Tenjin::ContextHelper</strong>
1615
+ module_function
1616
+ def link_to(label, url)
1617
+ return "&lt;a href=\"#{escape_xml(url)}\"&gt;#{escape_xml(label)}&lt;/a&gt;"
1618
+ end
1619
+ <strong>end</strong>
1620
+
1621
+ engine = Tenjin::Engine.new()
1622
+ context = { :label=&gt;'Top', :url=&gt;'/' }
1623
+ output = engine.render('example16.rbhtml', context)
1624
+ print output
1625
+ </pre>
1626
+ <a name="example16b.result"></a>
1627
+ <div class="terminal_caption">
1628
+ Result:</div>
1629
+ <pre class="terminal">$ ruby example16b.rb
1630
+ &lt;ul&gt;
1631
+ &lt;li&gt;&lt;a href="/"&gt;Top&lt;/a&gt;&lt;/li&gt;
1632
+ &lt;/ul&gt;
1633
+ </pre>
1634
+ <p>(C) Define subclass of Tenjin::Context and define helper functions as instance method.
1635
+ </p>
1636
+ <a name="example16c.rb"></a>
1637
+ <div class="program_caption">
1638
+ File 'example16c.rb':</div>
1639
+ <pre class="program">require 'tenjin'
1640
+
1641
+ <strong>class MyContext &lt; Tenjin::Context</strong>
1642
+ def link_to(label, url)
1643
+ return "&lt;a href=\"#{escape_xml(url)}\"&gt;#{escape_xml(label)}&lt;/a&gt;"
1644
+ end
1645
+ <strong>end</strong>
1646
+
1647
+ engine = Tenjin::Engine.new()
1648
+ <strong>context = MyContext.new(:label=&gt;'Top', :url=&gt;'/')</strong>
1649
+ output = engine.render('example16.rbhtml', context)
1650
+ print output
1651
+ </pre>
1652
+ <a name="example16c.result"></a>
1653
+ <div class="terminal_caption">
1654
+ Result:</div>
1655
+ <pre class="terminal">$ ruby example16c.rb
1656
+ &lt;ul&gt;
1657
+ &lt;li&gt;&lt;a href="/"&gt;Top&lt;/a&gt;&lt;/li&gt;
1658
+ &lt;/ul&gt;
1659
+ </pre>
1660
+ <br>
1661
+
1662
+
1663
+ <a name="dev-othertopics"></a>
1664
+ <h3 class="section2">Other Topics</h3>
1665
+ <ul type="disc">
1666
+ <li>Tenjin::Template detects newline character ("\n" or "\r\n") automatically.
1667
+ If input file contains "\r\n", rbTenjin generates output which contains "\r\n".
1668
+ </li>
1669
+ </ul>
1670
+ <ul type="disc">
1671
+ <li>Tenjin::Template#render() can be called many times.
1672
+ If you create a Tenjin::Template object, you can call render() method many times.
1673
+ </li>
1674
+ </ul>
1675
+ <ul type="disc">
1676
+ <li>Tenjin::Template#convert() also can be called many times.
1677
+ If you create a Tenjin::Template object, you can call convert() (and also render()) method many times.
1678
+ </li>
1679
+ </ul>
1680
+ <br>
1681
+
1682
+
1683
+ <br>
1684
+
1685
+
1686
+
1687
+ </div>
1688
+ </blockquote>
1689
+
1690
+ </body>
1691
+ </html>