tenjin 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.txt +54 -0
- data/benchmark/bench.rb +502 -0
- data/benchmark/bench_context.rb +17 -0
- data/benchmark/bench_context.yaml +141 -0
- data/benchmark/templates/_footer.html +4 -0
- data/benchmark/templates/_header.html +52 -0
- data/benchmark/templates/bench_eruby.rhtml +29 -0
- data/benchmark/templates/bench_tenjin.rbhtml +29 -0
- data/bin/rbtenjin +449 -0
- data/doc-api/classes/Tenjin.html +141 -0
- data/doc-api/classes/Tenjin/ArrayBufferTemplate.html +270 -0
- data/doc-api/classes/Tenjin/BaseContext.html +312 -0
- data/doc-api/classes/Tenjin/Context.html +126 -0
- data/doc-api/classes/Tenjin/ContextHelper.html +433 -0
- data/doc-api/classes/Tenjin/Engine.html +616 -0
- data/doc-api/classes/Tenjin/ErubisTemplate.html +166 -0
- data/doc-api/classes/Tenjin/HtmlHelper.html +359 -0
- data/doc-api/classes/Tenjin/Preprocessor.html +242 -0
- data/doc-api/classes/Tenjin/Template.html +916 -0
- data/doc-api/created.rid +1 -0
- data/doc-api/files/README_txt.html +185 -0
- data/doc-api/files/lib/tenjin_rb.html +136 -0
- data/doc-api/fr_class_index.html +36 -0
- data/doc-api/fr_file_index.html +28 -0
- data/doc-api/fr_method_index.html +89 -0
- data/doc-api/index.html +24 -0
- data/doc-api/rdoc-style.css +208 -0
- data/doc/docstyle.css +188 -0
- data/doc/examples.html +312 -0
- data/doc/faq.html +909 -0
- data/doc/users-guide.html +1691 -0
- data/lib/tenjin.rb +959 -0
- data/setup.rb +1331 -0
- data/tenjin.gemspec +58 -0
- data/test/assert-text-equal.rb +45 -0
- data/test/data/examples/form/create.rbhtml +4 -0
- data/test/data/examples/form/form.rbhtml +14 -0
- data/test/data/examples/form/layout.rbhtml +8 -0
- data/test/data/examples/form/main.rb +9 -0
- data/test/data/examples/form/main.result +21 -0
- data/test/data/examples/form/update.rbhtml +4 -0
- data/test/data/examples/preprocessing/helper.rb +16 -0
- data/test/data/examples/preprocessing/main.rb +11 -0
- data/test/data/examples/preprocessing/main.result +17 -0
- data/test/data/examples/preprocessing/select.rbhtml +15 -0
- data/test/data/examples/preprocessing/select_P.result +18 -0
- data/test/data/examples/table/table.rb +9 -0
- data/test/data/examples/table/table.rbhtml +16 -0
- data/test/data/examples/table/table.result +20 -0
- data/test/data/examples/table/table_s.result +18 -0
- data/test/data/faq/ex1.rbhtml +5 -0
- data/test/data/faq/ex10-baselayout.rbhtml +27 -0
- data/test/data/faq/ex10-content.rbhtml +12 -0
- data/test/data/faq/ex10-customlayout.rbhtml +11 -0
- data/test/data/faq/ex10_inherit.result +25 -0
- data/test/data/faq/ex11-bench.rb +28 -0
- data/test/data/faq/ex11-content.rbhtml +9 -0
- data/test/data/faq/ex11-layout1.rbhtml +5 -0
- data/test/data/faq/ex11-layout2.rbhtml +6 -0
- data/test/data/faq/ex11.rb +5 -0
- data/test/data/faq/ex11.rbhtml +8 -0
- data/test/data/faq/ex11.source +11 -0
- data/test/data/faq/ex11_arraybuffer.result +15 -0
- data/test/data/faq/ex1_chksyntax.result +3 -0
- data/test/data/faq/ex2-content.rbhtml +3 -0
- data/test/data/faq/ex2-layout.rbhtml +11 -0
- data/test/data/faq/ex2_removenl.result +19 -0
- data/test/data/faq/ex3.rb +4 -0
- data/test/data/faq/ex3.rbhtml +1 -0
- data/test/data/faq/ex3_escapefunc1.result +2 -0
- data/test/data/faq/ex3_escapefunc2.result +2 -0
- data/test/data/faq/ex5.rbhtml +7 -0
- data/test/data/faq/ex5_template_args.source +9 -0
- data/test/data/faq/ex6-content.rhtml +6 -0
- data/test/data/faq/ex6-layout.rhtml +6 -0
- data/test/data/faq/ex6.rb +10 -0
- data/test/data/faq/ex6_eruby.result +12 -0
- data/test/data/faq/ex7-expr-pattern.rb +34 -0
- data/test/data/faq/ex7-expr-pattern.rbhtml +3 -0
- data/test/data/faq/ex7_expr_pattern.result +4 -0
- data/test/data/faq/ex8-m18n.rb +77 -0
- data/test/data/faq/ex8-m18n.rbhtml +4 -0
- data/test/data/faq/ex8_m18n.result +10 -0
- data/test/data/faq/ex9-baselayout.rbhtml +8 -0
- data/test/data/faq/ex9-content.rbhtml +6 -0
- data/test/data/faq/ex9-mylayout.rbhtml +5 -0
- data/test/data/faq/ex9_changelayout.result +11 -0
- data/test/data/users_guide/content6.rbhtml +3 -0
- data/test/data/users_guide/content7.rbhtml +5 -0
- data/test/data/users_guide/content8.rbhtml +2 -0
- data/test/data/users_guide/contextdata.rb +7 -0
- data/test/data/users_guide/datafile.rb +5 -0
- data/test/data/users_guide/datafile.yaml +10 -0
- data/test/data/users_guide/ex.rbhtml +6 -0
- data/test/data/users_guide/ex.result +7 -0
- data/test/data/users_guide/ex.script +5 -0
- data/test/data/users_guide/ex_script.result +7 -0
- data/test/data/users_guide/ex_source.result +8 -0
- data/test/data/users_guide/example1.rbhtml +12 -0
- data/test/data/users_guide/example1.result +17 -0
- data/test/data/users_guide/example10.rbhtml +4 -0
- data/test/data/users_guide/example10_template_args.result +6 -0
- data/test/data/users_guide/example11.rbhtml +5 -0
- data/test/data/users_guide/example11_template_args_result +2 -0
- data/test/data/users_guide/example12.rbhtml +12 -0
- data/test/data/users_guide/example12_preprocessed.result +10 -0
- data/test/data/users_guide/example12_preprocessed_source.result +10 -0
- data/test/data/users_guide/example13.rbhtml +6 -0
- data/test/data/users_guide/example13_preprocessed.result +2 -0
- data/test/data/users_guide/example13_preprocessed_source.result +2 -0
- data/test/data/users_guide/example14.rb +32 -0
- data/test/data/users_guide/example14.rbhtml +6 -0
- data/test/data/users_guide/example14_tmplclass.result +15 -0
- data/test/data/users_guide/example15.rb +10 -0
- data/test/data/users_guide/example15_escapefunc.result +14 -0
- data/test/data/users_guide/example16.rbhtml +4 -0
- data/test/data/users_guide/example16a.rb +10 -0
- data/test/data/users_guide/example16a.result +4 -0
- data/test/data/users_guide/example16b.rb +13 -0
- data/test/data/users_guide/example16b.result +4 -0
- data/test/data/users_guide/example16c.rb +12 -0
- data/test/data/users_guide/example16c.result +4 -0
- data/test/data/users_guide/example1_S.result +14 -0
- data/test/data/users_guide/example1_SXNC.result +10 -0
- data/test/data/users_guide/example1_source.result +14 -0
- data/test/data/users_guide/example2.rbhtml +3 -0
- data/test/data/users_guide/example2_sb.result2 +9 -0
- data/test/data/users_guide/example3.rbhtml +5 -0
- data/test/data/users_guide/example3_syntaxcheck.result +2 -0
- data/test/data/users_guide/example4.rbhtml +13 -0
- data/test/data/users_guide/example4_datafile_rb.result +13 -0
- data/test/data/users_guide/example4_yaml.result +13 -0
- data/test/data/users_guide/example5.rbhtml +9 -0
- data/test/data/users_guide/example5_datastr_rb.result +9 -0
- data/test/data/users_guide/example5_datastr_yaml.result +9 -0
- data/test/data/users_guide/example6.rbhtml +19 -0
- data/test/data/users_guide/example6_layout.result +29 -0
- data/test/data/users_guide/example6_nested.result +28 -0
- data/test/data/users_guide/example7_layout2.result +13 -0
- data/test/data/users_guide/example8_layout3.result +8 -0
- data/test/data/users_guide/example9.rbhtml +18 -0
- data/test/data/users_guide/example9_capture.result +26 -0
- data/test/data/users_guide/footer.html +5 -0
- data/test/data/users_guide/footer.rbhtml +4 -0
- data/test/data/users_guide/layout6.rbhtml +17 -0
- data/test/data/users_guide/layout7.rbhtml +9 -0
- data/test/data/users_guide/layout8_html.rbhtml +5 -0
- data/test/data/users_guide/layout8_xhtml.rbhtml +6 -0
- data/test/data/users_guide/layout9.rbhtml +25 -0
- data/test/data/users_guide/sidemenu.rbhtml +5 -0
- data/test/data/users_guide/user_app.cgi +39 -0
- data/test/data/users_guide/user_app.result +30 -0
- data/test/data/users_guide/user_create.rbhtml +6 -0
- data/test/data/users_guide/user_edit.rbhtml +7 -0
- data/test/data/users_guide/user_form.rbhtml +10 -0
- data/test/data/users_guide/user_layout.rbhtml +16 -0
- data/test/test_all.rb +23 -0
- data/test/test_engine.rb +526 -0
- data/test/test_engine.yaml +2039 -0
- data/test/test_examples.rb +81 -0
- data/test/test_faq.rb +60 -0
- data/test/test_htmlhelper.rb +78 -0
- data/test/test_main.rb +564 -0
- data/test/test_main.yaml +174 -0
- data/test/test_template.rb +113 -0
- data/test/test_template.yaml +1244 -0
- data/test/test_users_guide.rb +75 -0
- data/test/testcase-helper.rb +166 -0
- 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
|
+
<ul>
|
|
97
|
+
<strong><?rb for item in @items ?></strong>
|
|
98
|
+
<li><strong>${item}</strong></li>
|
|
99
|
+
<strong><?rb end ?></strong>
|
|
100
|
+
</ul>
|
|
101
|
+
</pre>
|
|
102
|
+
<p>Here is the notation:
|
|
103
|
+
</p>
|
|
104
|
+
<ul type="disc">
|
|
105
|
+
<li><code><?rb ... ?></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 << %Q`Hello <strong>#{@name}</strong>!
|
|
117
|
+
<ul>\n`
|
|
118
|
+
<strong>for item in @items</strong>
|
|
119
|
+
_buf << %Q` <li><strong>#{escape((item).to_s)}</strong></li>\n`
|
|
120
|
+
<strong>end</strong>
|
|
121
|
+
_buf << %Q`</ul>\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=['<AAA>','B&B','\"CCC\"']" ex.rbhtml
|
|
128
|
+
Hello World!
|
|
129
|
+
<ul>
|
|
130
|
+
<li>&lt;AAA&gt;</li>
|
|
131
|
+
<li>B&amp;B</li>
|
|
132
|
+
<li>&quot;CCC&quot;</li>
|
|
133
|
+
</ul>
|
|
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=>'World', :items=>['<AAA>', 'B&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><?rb ... ?></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>& < > "</code>' is escaped to '<code>&amp; &lt; &gt; &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"><table>
|
|
258
|
+
<tbody>
|
|
259
|
+
<strong><?rb i = 0 ?></strong>
|
|
260
|
+
<strong><?rb for item in ['<foo>', 'bar&bar', '"baz"'] ?></strong>
|
|
261
|
+
<strong><?rb i += 1 ?></strong>
|
|
262
|
+
<tr>
|
|
263
|
+
<td><strong>#{item}</strong></td>
|
|
264
|
+
<td><strong>${item}</strong></td>
|
|
265
|
+
</tr>
|
|
266
|
+
<strong><?rb end ?></strong>
|
|
267
|
+
<tbody>
|
|
268
|
+
</table>
|
|
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
|
+
<table>
|
|
277
|
+
<tbody>
|
|
278
|
+
<tr>
|
|
279
|
+
<td><strong><foo></strong></td>
|
|
280
|
+
<td><strong>&lt;foo&gt;</strong></td>
|
|
281
|
+
</tr>
|
|
282
|
+
<tr>
|
|
283
|
+
<td><strong>bar&bar</strong></td>
|
|
284
|
+
<td><strong>bar&amp;bar</strong></td>
|
|
285
|
+
</tr>
|
|
286
|
+
<tr>
|
|
287
|
+
<td><strong>"baz"</strong></td>
|
|
288
|
+
<td><strong>&quot;baz&quot;</strong></td>
|
|
289
|
+
</tr>
|
|
290
|
+
<tbody>
|
|
291
|
+
</table>
|
|
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 << %Q`<table>
|
|
305
|
+
<tbody>\n`
|
|
306
|
+
<strong>i = 0</strong>
|
|
307
|
+
<strong>for item in ['<foo>', 'bar&bar', '"baz"']</strong>
|
|
308
|
+
<strong>i += 1</strong>
|
|
309
|
+
_buf << %Q` <tr>
|
|
310
|
+
<td><strong>#{item}</strong></td>
|
|
311
|
+
<td><strong>#{escape((item).to_s)}</strong></td>
|
|
312
|
+
</tr>\n`
|
|
313
|
+
<strong>end</strong>
|
|
314
|
+
_buf << %Q` <tbody>
|
|
315
|
+
</table>\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>'& < > "'</code> into <code>'&amp; &lt; &gt; &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"><?rb for i in [1, 2, 3] ?>
|
|
334
|
+
<p>#{item}</p>
|
|
335
|
+
<?rb end ?>
|
|
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 << %Q`<p>#{item}</p>\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 << %Q`<p>#{item}</p>\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 ['<foo>', 'bar&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 ['<foo>', 'bar&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"><ul>
|
|
422
|
+
<?rb for item in items ?>
|
|
423
|
+
<li>${item}</li>
|
|
424
|
+
<?rb <strong>ende</strong> ?>
|
|
425
|
+
</ul>
|
|
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"><p>
|
|
449
|
+
${@text}
|
|
450
|
+
#{@num}
|
|
451
|
+
#{@flag}
|
|
452
|
+
</p>
|
|
453
|
+
|
|
454
|
+
<?rb for item in @items ?>
|
|
455
|
+
<p>${item}</p>
|
|
456
|
+
<?rb end ?>
|
|
457
|
+
|
|
458
|
+
<?rb for key, value in @hash ?>
|
|
459
|
+
<p>#{key} = ${value}</p>
|
|
460
|
+
<?rb end ?>
|
|
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
|
+
<p>
|
|
481
|
+
foo
|
|
482
|
+
3.14
|
|
483
|
+
true
|
|
484
|
+
</p>
|
|
485
|
+
|
|
486
|
+
<p>foo</p>
|
|
487
|
+
<p>bar</p>
|
|
488
|
+
<p>baz</p>
|
|
489
|
+
|
|
490
|
+
<p>x = 1</p>
|
|
491
|
+
<p>y = 2</p>
|
|
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=>1, :y=>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
|
+
<p>
|
|
507
|
+
foo
|
|
508
|
+
3.14
|
|
509
|
+
true
|
|
510
|
+
</p>
|
|
511
|
+
|
|
512
|
+
<p>foo</p>
|
|
513
|
+
<p>bar</p>
|
|
514
|
+
<p>baz</p>
|
|
515
|
+
|
|
516
|
+
<p>x = 1</p>
|
|
517
|
+
<p>y = 2</p>
|
|
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
|
+
<?rb for item in @items ?>
|
|
532
|
+
- #{item}
|
|
533
|
+
<?rb end ?>
|
|
534
|
+
hash:
|
|
535
|
+
<?rb for key, val in @hash ?>
|
|
536
|
+
#{key}: #{val}
|
|
537
|
+
<?rb end ?>
|
|
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"=>1,"y"=>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"><html>
|
|
586
|
+
<body>
|
|
587
|
+
|
|
588
|
+
<div id="sidemenu">
|
|
589
|
+
<strong><?rb import 'sidemenu.rbhtml' ?></strong>
|
|
590
|
+
</div>
|
|
591
|
+
|
|
592
|
+
<div id="main-content">
|
|
593
|
+
<?rb for item in @items ?>
|
|
594
|
+
<p>${item}</p>
|
|
595
|
+
<?rb end ?>
|
|
596
|
+
</div>
|
|
597
|
+
|
|
598
|
+
<div id="footer">
|
|
599
|
+
<strong>#{import 'footer.rbhtml', false}</strong>
|
|
600
|
+
</div>
|
|
601
|
+
|
|
602
|
+
</body>
|
|
603
|
+
</table>
|
|
604
|
+
</pre>
|
|
605
|
+
<a name="sidemenu.rbhtml"></a>
|
|
606
|
+
<div class="program_caption">
|
|
607
|
+
File 'sidemenu.rbhtml':</div>
|
|
608
|
+
<pre class="program"><ul>
|
|
609
|
+
<?rb for item in @menu ?>
|
|
610
|
+
<li><a href="${item['url']}">${item['name']}</a></li>
|
|
611
|
+
<?rb end ?>
|
|
612
|
+
</ul>
|
|
613
|
+
</pre>
|
|
614
|
+
<a name="footer.rbhtml"></a>
|
|
615
|
+
<div class="program_caption">
|
|
616
|
+
File 'footer.rbhtml':</div>
|
|
617
|
+
<pre class="program"><hr />
|
|
618
|
+
<address>
|
|
619
|
+
<a href="mailto:${@webmaster_email}">${@webmaster_email}</a>
|
|
620
|
+
</address>
|
|
621
|
+
</pre>
|
|
622
|
+
<a name="contextdata.rb"></a>
|
|
623
|
+
<div class="program_caption">
|
|
624
|
+
File 'contextdata.rb':</div>
|
|
625
|
+
<pre class="program">@items = [ '<FOO>', '&BAR', '"BAZ"' ]
|
|
626
|
+
@webmaster_email = 'webmaster@example.com'
|
|
627
|
+
@menu = [
|
|
628
|
+
{'name'=> 'Top', 'url'=> '/' },
|
|
629
|
+
{'name'=> 'Products', 'url'=> '/prod' },
|
|
630
|
+
{'name'=> 'Support', 'url'=> '/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
|
+
<html>
|
|
638
|
+
<body>
|
|
639
|
+
|
|
640
|
+
<div id="sidemenu">
|
|
641
|
+
<strong><ul></strong>
|
|
642
|
+
<strong><li><a href="/">Top</a></li></strong>
|
|
643
|
+
<strong><li><a href="/prod">Products</a></li></strong>
|
|
644
|
+
<strong><li><a href="/support">Support</a></li></strong>
|
|
645
|
+
<strong></ul></strong>
|
|
646
|
+
</div>
|
|
647
|
+
|
|
648
|
+
<div id="main-content">
|
|
649
|
+
<p>&lt;FOO&gt;</p>
|
|
650
|
+
<p>&amp;BAR</p>
|
|
651
|
+
<p>&quot;BAZ&quot;</p>
|
|
652
|
+
</div>
|
|
653
|
+
|
|
654
|
+
<div id="footer">
|
|
655
|
+
<strong><hr /></strong>
|
|
656
|
+
<strong><address></strong>
|
|
657
|
+
<strong> <a href="mailto:webmaster@example.com">webmaster@example.com</a></strong>
|
|
658
|
+
<strong></address></strong>
|
|
659
|
+
|
|
660
|
+
</div>
|
|
661
|
+
|
|
662
|
+
</body>
|
|
663
|
+
</table>
|
|
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"><html>
|
|
689
|
+
<body>
|
|
690
|
+
|
|
691
|
+
<div id="sidemenu">
|
|
692
|
+
<?rb import 'sidemenu.rbhtml' ?>
|
|
693
|
+
</div>
|
|
694
|
+
|
|
695
|
+
<div id="main-content">
|
|
696
|
+
<strong>#{@_content}</strong>
|
|
697
|
+
</div>
|
|
698
|
+
|
|
699
|
+
<div id="footer">
|
|
700
|
+
#{import 'footer.rbhtml', false}
|
|
701
|
+
</div>
|
|
702
|
+
|
|
703
|
+
</body>
|
|
704
|
+
</table>
|
|
705
|
+
</pre>
|
|
706
|
+
<a name="content6.rbhtml"></a>
|
|
707
|
+
<div class="program_caption">
|
|
708
|
+
File 'content6.rbhtml':</div>
|
|
709
|
+
<pre class="program"><?rb for item in @items ?>
|
|
710
|
+
<p>${item}</p>
|
|
711
|
+
<?rb end ?>
|
|
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
|
+
<html>
|
|
718
|
+
<body>
|
|
719
|
+
|
|
720
|
+
<div id="sidemenu">
|
|
721
|
+
<ul>
|
|
722
|
+
<li><a href="/">Top</a></li>
|
|
723
|
+
<li><a href="/prod">Products</a></li>
|
|
724
|
+
<li><a href="/support">Support</a></li>
|
|
725
|
+
</ul>
|
|
726
|
+
</div>
|
|
727
|
+
|
|
728
|
+
<div id="main-content">
|
|
729
|
+
<strong> <p>&lt;FOO&gt;</p></strong>
|
|
730
|
+
<strong> <p>&amp;BAR</p></strong>
|
|
731
|
+
<strong> <p>&quot;BAZ&quot;</p></strong>
|
|
732
|
+
|
|
733
|
+
</div>
|
|
734
|
+
|
|
735
|
+
<div id="footer">
|
|
736
|
+
<hr />
|
|
737
|
+
<address>
|
|
738
|
+
<a href="mailto:webmaster@example.com">webmaster@example.com</a>
|
|
739
|
+
</address>
|
|
740
|
+
|
|
741
|
+
</div>
|
|
742
|
+
|
|
743
|
+
</body>
|
|
744
|
+
</table>
|
|
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
|
+
<h1><strong>${@title}</strong></h1>
|
|
757
|
+
|
|
758
|
+
<div id="main-content">
|
|
759
|
+
#{@_content}
|
|
760
|
+
<div>
|
|
761
|
+
|
|
762
|
+
<a href="<strong>${@url}</strong>">Next page</a>
|
|
763
|
+
...
|
|
764
|
+
</pre>
|
|
765
|
+
<a name="content7.rbhtml"></a>
|
|
766
|
+
<div class="program_caption">
|
|
767
|
+
File 'content7.rbhtml':</div>
|
|
768
|
+
<pre class="program"><strong><?rb @title = 'Document Title' ?></strong>
|
|
769
|
+
<strong><?rb @url = '/next/page' ?></strong>
|
|
770
|
+
<table>
|
|
771
|
+
...content...
|
|
772
|
+
</table>
|
|
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
|
+
<h1><strong>Document Title</strong></h1>
|
|
780
|
+
|
|
781
|
+
<div id="main-content">
|
|
782
|
+
<table>
|
|
783
|
+
...content...
|
|
784
|
+
</table>
|
|
785
|
+
|
|
786
|
+
<div>
|
|
787
|
+
|
|
788
|
+
<a href="<strong>/next/page</strong>">Next page</a>
|
|
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><?rb @_layout = :layout8_xhtml ?></strong>
|
|
798
|
+
<h1>Hello World!</h1>
|
|
799
|
+
</pre>
|
|
800
|
+
<a name="layout8_html.rbhtml"></a>
|
|
801
|
+
<div class="program_caption">
|
|
802
|
+
File 'layout8_html.rbhtml':</div>
|
|
803
|
+
<pre class="program"><html>
|
|
804
|
+
<body>
|
|
805
|
+
#{@_content}
|
|
806
|
+
</body>
|
|
807
|
+
</html>
|
|
808
|
+
</pre>
|
|
809
|
+
<a name="layout8_xhtml.rbhtml"></a>
|
|
810
|
+
<div class="program_caption">
|
|
811
|
+
File 'layout8_xhtml.rbhtml':</div>
|
|
812
|
+
<pre class="program"><?xml version="1.0" encoding="UTF-8"?>
|
|
813
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
814
|
+
<body>
|
|
815
|
+
#{@_content}
|
|
816
|
+
</body>
|
|
817
|
+
</html>
|
|
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
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
824
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
825
|
+
<body>
|
|
826
|
+
<h1>Hello World!</h1>
|
|
827
|
+
|
|
828
|
+
</body>
|
|
829
|
+
</html>
|
|
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"><?rb @title = 'Capture Test' ?>
|
|
842
|
+
<html>
|
|
843
|
+
<body>
|
|
844
|
+
|
|
845
|
+
<strong><?rb start_capture(:content_part) ?></strong>
|
|
846
|
+
<ul>
|
|
847
|
+
<?rb for i in [0, 1, 2] ?>
|
|
848
|
+
<li>i = #{i}</li>
|
|
849
|
+
<?rb end ?>
|
|
850
|
+
</ul>
|
|
851
|
+
<strong><?rb stop_capture() ?></strong>
|
|
852
|
+
|
|
853
|
+
<strong><?rb start_capture('footer_part') ?></strong>
|
|
854
|
+
<div class="footer">copyright&copy; 2007 kuwata-lab.com</div>
|
|
855
|
+
<strong><?rb stop_capture() ?></strong>
|
|
856
|
+
|
|
857
|
+
</body>
|
|
858
|
+
</html>
|
|
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"><html lang="en">
|
|
872
|
+
<head>
|
|
873
|
+
<title>${@title}</title>
|
|
874
|
+
</head>
|
|
875
|
+
<body>
|
|
876
|
+
|
|
877
|
+
<!-- HEADER -->
|
|
878
|
+
<strong><?rb unless captured_as('header_part') ?></strong>
|
|
879
|
+
<h1>${@title}</h1>
|
|
880
|
+
<strong><?rb end ?></strong>
|
|
881
|
+
<!-- /HEADER -->
|
|
882
|
+
|
|
883
|
+
<!-- CONTENT -->
|
|
884
|
+
<strong>#{@content_part}</strong>
|
|
885
|
+
<!-- /CONTENT -->
|
|
886
|
+
|
|
887
|
+
<!-- FOOTER -->
|
|
888
|
+
<strong><?rb unless captured_as('footer_part') ?></strong>
|
|
889
|
+
<hr />
|
|
890
|
+
<address>webmaster@localhost</address>
|
|
891
|
+
<strong><?rb end ?></strong>
|
|
892
|
+
<!-- /FOOTER -->
|
|
893
|
+
|
|
894
|
+
</body>
|
|
895
|
+
</html>
|
|
896
|
+
</pre>
|
|
897
|
+
<p>'<code>unless captured_as("name") ... end</code>' is equivarent to the following.
|
|
898
|
+
</p>
|
|
899
|
+
<pre class="program"><?rb if @name ?>
|
|
900
|
+
<?rb _buf << @name ?>
|
|
901
|
+
<?rb else ?>
|
|
902
|
+
...
|
|
903
|
+
<?rb end ?>
|
|
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
|
+
<html lang="en">
|
|
912
|
+
<head>
|
|
913
|
+
<title>Capture Test</title>
|
|
914
|
+
</head>
|
|
915
|
+
<body>
|
|
916
|
+
|
|
917
|
+
<!-- HEADER -->
|
|
918
|
+
<h1>Capture Test</h1>
|
|
919
|
+
<!-- /HEADER -->
|
|
920
|
+
|
|
921
|
+
<!-- CONTENT -->
|
|
922
|
+
<strong><ul></strong>
|
|
923
|
+
<strong><li>i = 0</li></strong>
|
|
924
|
+
<strong><li>i = 1</li></strong>
|
|
925
|
+
<strong><li>i = 2</li></strong>
|
|
926
|
+
<strong></ul></strong>
|
|
927
|
+
|
|
928
|
+
<!-- /CONTENT -->
|
|
929
|
+
|
|
930
|
+
<!-- FOOTER -->
|
|
931
|
+
<strong><div class="footer">copyright&copy; 2007 kuwata-lab.com</div></strong>
|
|
932
|
+
<!-- /FOOTER -->
|
|
933
|
+
|
|
934
|
+
</body>
|
|
935
|
+
</html>
|
|
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"><?xml version="1.0"?>
|
|
950
|
+
<strong><?rb #@ARGS title, name ?></strong>
|
|
951
|
+
<h1>${title}</h1>
|
|
952
|
+
<p>Hello ${name}!</p>
|
|
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 << %Q`<?xml version="1.0"?>\n`
|
|
959
|
+
<strong> title = @title; name = @name;</strong>
|
|
960
|
+
_buf << %Q`<h1>#{escape((title).to_s)}</h1>
|
|
961
|
+
<p>Hello #{escape((name).to_s)}!</p>\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"><p>
|
|
970
|
+
<strong><?rb #@ARGS x ?></strong>
|
|
971
|
+
x = #{x}
|
|
972
|
+
y = #{y} # NameError
|
|
973
|
+
</p>
|
|
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><?RB ... ?></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><?RB states = { "CA" => "California", ?></strong>
|
|
1006
|
+
<strong><?RB "NY" => "New York", ?></strong>
|
|
1007
|
+
<strong><?RB "FL" => "Florida", ?></strong>
|
|
1008
|
+
<strong><?RB "TX" => "Texas", ?></strong>
|
|
1009
|
+
<strong><?RB "HI" => "Hawaii", } ?></strong>
|
|
1010
|
+
<?rb chk = { @params['state'] => ' selected="selected"' } ?>
|
|
1011
|
+
<select name="state">
|
|
1012
|
+
<option value="">-</option>
|
|
1013
|
+
<strong><?RB for code in states.keys.sort ?></strong>
|
|
1014
|
+
<option value="<strong>#{{code}}</strong>"#{chk[<strong>#{{code.inspect}}</strong>]}><strong>${{states[code]}}</strong></option>
|
|
1015
|
+
<strong><?RB end ?></strong>
|
|
1016
|
+
</select>
|
|
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
|
+
<?rb chk = { @params['state'] => ' selected="selected"' } ?>
|
|
1026
|
+
<select name="state">
|
|
1027
|
+
<option value="">-</option>
|
|
1028
|
+
<option value="CA"#{chk["CA"]}>California</option>
|
|
1029
|
+
<option value="FL"#{chk["FL"]}>Florida</option>
|
|
1030
|
+
<option value="HI"#{chk["HI"]}>Hawaii</option>
|
|
1031
|
+
<option value="NY"#{chk["NY"]}>New York</option>
|
|
1032
|
+
<option value="TX"#{chk["TX"]}>Texas</option>
|
|
1033
|
+
</select>
|
|
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'] => ' selected="selected"' }
|
|
1045
|
+
_buf << %Q`<select name="state">
|
|
1046
|
+
<option value="">-</option>
|
|
1047
|
+
<option value="CA"#{chk["CA"]}>California</option>
|
|
1048
|
+
<option value="FL"#{chk["FL"]}>Florida</option>
|
|
1049
|
+
<option value="HI"#{chk["HI"]}>Hawaii</option>
|
|
1050
|
+
<option value="NY"#{chk["NY"]}>New York</option>
|
|
1051
|
+
<option value="TX"#{chk["TX"]}>Texas</option>
|
|
1052
|
+
</select>\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><a></a></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"><?RB require 'cgi' ?>
|
|
1067
|
+
<?RB ## ex. link_to('Show', '/show/1') => <a href="/show/1">Show</a> ?>
|
|
1068
|
+
<?RB def link_to(label, url) ?>
|
|
1069
|
+
<?RB return "<a href=\"#{CGI.unescape(url)}\">#{label}</a>" ?>
|
|
1070
|
+
<?RB end ?>
|
|
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
|
+
<a href="/items/show/<strong>#{@params["id"]}"</strong>>Show <strong>${@params["name"]}</strong></a>
|
|
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 << %Q`<a href="/items/show/<strong>#{@params["id"]}</strong>">Show <strong>#{escape((@params["name"]).to_s)}</strong></a>\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 << %Q`#{escape((hash[").to_s)}"]}</code>` and not '<code>_buf << %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 << %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=>'rbTenjin Example', :items=>['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=>'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"><h1>#{@title}</h1>
|
|
1240
|
+
<ul>
|
|
1241
|
+
<?rb for item in @items ?>
|
|
1242
|
+
<li>${item}</li>
|
|
1243
|
+
<?rb end ?>
|
|
1244
|
+
</ul>
|
|
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=>'rbTenjin Example', :items=>['<AAA>','B&B','"CCC"']}
|
|
1269
|
+
output = <strong>template.render(hash)</strong>
|
|
1270
|
+
puts "---- output ----"
|
|
1271
|
+
puts output
|
|
1272
|
+
## or
|
|
1273
|
+
#hash = {:title=>'rbTenjin Example', :items=>['<AAA>','B&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] = ['<AAA>','B&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 << %Q`<h1>#{@title}</h1>
|
|
1288
|
+
<ul>\n`
|
|
1289
|
+
for item in @items
|
|
1290
|
+
_buf << %Q` <li>#{escape((item).to_s)}</li>\n`
|
|
1291
|
+
end
|
|
1292
|
+
_buf << %Q`</ul>\n`
|
|
1293
|
+
---- output ----
|
|
1294
|
+
<h1>rbTenjin Example</h1>
|
|
1295
|
+
<ul>
|
|
1296
|
+
<li>&lt;AAA&gt;</li>
|
|
1297
|
+
<li>B&amp;B</li>
|
|
1298
|
+
<li>&quot;CCC&quot;</li>
|
|
1299
|
+
</ul>
|
|
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=>'', :postfix=>'', :layout=>nil, :path=nil, :cache=>true, :preprocess=>false, :templateclass=>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"><?rb #@ARGS params ?>
|
|
1382
|
+
<p>
|
|
1383
|
+
Name: <input type="text" name="name" value="${params['name']}" /><br />
|
|
1384
|
+
Email: <input type="text" name="email" value="${params['email']}" /><br />
|
|
1385
|
+
Gender:
|
|
1386
|
+
<?rb gender = @params['gender'] ?>
|
|
1387
|
+
<?rb chk = { true=>' checked="checked"', false=>'' } ?>
|
|
1388
|
+
<input type="radio" name="gender" value="m" #{chk[gender=='m']} />Male
|
|
1389
|
+
<input type="radio" name="gender" value="f" #{chk[gender=='f']} />Female
|
|
1390
|
+
</p>
|
|
1391
|
+
</pre>
|
|
1392
|
+
<a name="user_create.rbhtml"></a>
|
|
1393
|
+
<div class="program_caption">
|
|
1394
|
+
File 'user_create.rbhtml':</div>
|
|
1395
|
+
<pre class="program"><?rb #@ARGS ?>
|
|
1396
|
+
<form action="user_app.cgi" method="post">
|
|
1397
|
+
<input type="hidden" name="action" value="create" />
|
|
1398
|
+
<strong><?rb import :form ?></strong>
|
|
1399
|
+
<input type="submit" value="Create" />
|
|
1400
|
+
</form>
|
|
1401
|
+
</pre>
|
|
1402
|
+
<a name="user_edit.rbhtml"></a>
|
|
1403
|
+
<div class="program_caption">
|
|
1404
|
+
File 'user_edit.rbhtml':</div>
|
|
1405
|
+
<pre class="program"><?rb #@ARGS params ?>
|
|
1406
|
+
<form action="user_app.cgi" method="post">
|
|
1407
|
+
<input type="hidden" name="action" value="edit" />
|
|
1408
|
+
<input type="hidden" name="id" value="${params['id']}" />
|
|
1409
|
+
<strong><?rb import :form ?></strong>
|
|
1410
|
+
<input type="submit" value="Edit" />
|
|
1411
|
+
</form>
|
|
1412
|
+
</pre>
|
|
1413
|
+
<a name="user_layout.rbhtml"></a>
|
|
1414
|
+
<div class="program_caption">
|
|
1415
|
+
File 'user_layout.rbhtml':</div>
|
|
1416
|
+
<pre class="program"><?rb #@ARGS _content, title ?>
|
|
1417
|
+
<html>
|
|
1418
|
+
<body>
|
|
1419
|
+
|
|
1420
|
+
<h1>${title}</h1>
|
|
1421
|
+
|
|
1422
|
+
<div id="main-content">
|
|
1423
|
+
<strong>#{_content}</strong>
|
|
1424
|
+
</div>
|
|
1425
|
+
|
|
1426
|
+
<div id="footer">
|
|
1427
|
+
<strong><?rb import 'footer.html' ?></strong>
|
|
1428
|
+
</div>
|
|
1429
|
+
|
|
1430
|
+
</body>
|
|
1431
|
+
</html>
|
|
1432
|
+
</pre>
|
|
1433
|
+
<a name="footer.html"></a>
|
|
1434
|
+
<div class="program_caption">
|
|
1435
|
+
File 'footer.html':</div>
|
|
1436
|
+
<pre class="program"><?rb #@ARGS ?>
|
|
1437
|
+
<hr />
|
|
1438
|
+
<address>
|
|
1439
|
+
<a href="mailto:webmaster@example.com">webmaster@example.com</a>
|
|
1440
|
+
</address>
|
|
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=>'Margalette',
|
|
1468
|
+
:email=>'meg@example.com',
|
|
1469
|
+
:gender=>'f',
|
|
1470
|
+
:id=>123 }
|
|
1471
|
+
end
|
|
1472
|
+
<strong>context = { :title=>title, :params=>params }</strong>
|
|
1473
|
+
<strong># or context = Tenjin::Context.new(:title=>title, :params=>params)</strong>
|
|
1474
|
+
|
|
1475
|
+
## create engine object
|
|
1476
|
+
layout = :layout # or 'user_layout.rbhtml'
|
|
1477
|
+
<strong>engine = Tenjin::Engine.new(:prefix=>'user_', :postfix=>'.rbhtml', :layout=>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
|
+
<html>
|
|
1490
|
+
<body>
|
|
1491
|
+
|
|
1492
|
+
<h1>Create User</h1>
|
|
1493
|
+
|
|
1494
|
+
<div id="main-content">
|
|
1495
|
+
<strong><form action="user_app.cgi" method="post"></strong>
|
|
1496
|
+
<strong> <input type="hidden" name="action" value="create" /></strong>
|
|
1497
|
+
<strong><p></strong>
|
|
1498
|
+
<strong> Name: <input type="text" name="name" value="" /><br /></strong>
|
|
1499
|
+
<strong> Email: <input type="text" name="email" value="" /><br /></strong>
|
|
1500
|
+
<strong> Gender:</strong>
|
|
1501
|
+
<strong> <input type="radio" name="gender" value="m" />Male</strong>
|
|
1502
|
+
<strong> <input type="radio" name="gender" value="f" />Female</strong>
|
|
1503
|
+
<strong></p></strong>
|
|
1504
|
+
<strong> <input type="submit" value="Create" /></strong>
|
|
1505
|
+
<strong></form></strong>
|
|
1506
|
+
|
|
1507
|
+
</div>
|
|
1508
|
+
|
|
1509
|
+
<div id="footer">
|
|
1510
|
+
<strong><hr /></strong>
|
|
1511
|
+
<strong><address></strong>
|
|
1512
|
+
<strong> <a href="mailto:webmaster@example.com">webmaster@example.com</a></strong>
|
|
1513
|
+
<strong></address></strong>
|
|
1514
|
+
</div>
|
|
1515
|
+
|
|
1516
|
+
</body>
|
|
1517
|
+
</html>
|
|
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=>'CGI.escapeHTML'</strong>)
|
|
1540
|
+
print template.script, "\n"
|
|
1541
|
+
|
|
1542
|
+
require 'cgi'
|
|
1543
|
+
title = 'rbTenjin Example'
|
|
1544
|
+
items = ['<foo>', '&bar', '"baz"']
|
|
1545
|
+
output = template.render(:title=>title, :items=>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 << %Q`<h1>#{@title}</h1>
|
|
1553
|
+
<ul>\n`
|
|
1554
|
+
for item in @items
|
|
1555
|
+
_buf << %Q` <li>#{<strong>CGI.escapeHTML</strong>((item).to_s)}</li>\n`
|
|
1556
|
+
end
|
|
1557
|
+
_buf << %Q`</ul>\n`
|
|
1558
|
+
|
|
1559
|
+
<h1>rbTenjin Example</h1>
|
|
1560
|
+
<ul>
|
|
1561
|
+
<li>&lt;foo&gt;</li>
|
|
1562
|
+
<li>&amp;bar</li>
|
|
1563
|
+
<li>&quot;baz&quot;</li>
|
|
1564
|
+
</ul>
|
|
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"><?rb #@ARGS label, url ?>
|
|
1579
|
+
<ul>
|
|
1580
|
+
<li>#{<strong>link_to(label, url)</strong>}</li>
|
|
1581
|
+
</ul>
|
|
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 "<a href=\"#{escape_xml(url)}\">#{escape_xml(label)}</a>"
|
|
1592
|
+
end
|
|
1593
|
+
|
|
1594
|
+
engine = Tenjin::Engine.new()
|
|
1595
|
+
context = { :label=>'Top', :url=>'/' }
|
|
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
|
+
<ul>
|
|
1604
|
+
<li><a href="/">Top</a></li>
|
|
1605
|
+
</ul>
|
|
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 "<a href=\"#{escape_xml(url)}\">#{escape_xml(label)}</a>"
|
|
1618
|
+
end
|
|
1619
|
+
<strong>end</strong>
|
|
1620
|
+
|
|
1621
|
+
engine = Tenjin::Engine.new()
|
|
1622
|
+
context = { :label=>'Top', :url=>'/' }
|
|
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
|
+
<ul>
|
|
1631
|
+
<li><a href="/">Top</a></li>
|
|
1632
|
+
</ul>
|
|
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 < Tenjin::Context</strong>
|
|
1642
|
+
def link_to(label, url)
|
|
1643
|
+
return "<a href=\"#{escape_xml(url)}\">#{escape_xml(label)}</a>"
|
|
1644
|
+
end
|
|
1645
|
+
<strong>end</strong>
|
|
1646
|
+
|
|
1647
|
+
engine = Tenjin::Engine.new()
|
|
1648
|
+
<strong>context = MyContext.new(:label=>'Top', :url=>'/')</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
|
+
<ul>
|
|
1657
|
+
<li><a href="/">Top</a></li>
|
|
1658
|
+
</ul>
|
|
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>
|