260621c60ab3023ee7ce3bdff7d560df2f02f0ff
[bse.git] / site / docs / Squirrel::Template.html
1 <?xml version="1.0" ?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5 <title>Squirrel::Template - simple templating system</title>
6 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7 <link rev="made" href="mailto:root@localhost" />
8 </head>
9
10 <body style="background-color: white">
11
12
13 <!-- INDEX BEGIN -->
14 <div name="index">
15 <p><a name="__index__"></a></p>
16
17 <ul>
18
19         <li><a href="#name">NAME</a></li>
20         <li><a href="#synopsis">SYNOPSIS</a></li>
21         <li><a href="#description">DESCRIPTION</a></li>
22         <li><a href="#methods">METHODS</a></li>
23         <li><a href="#template_syntax">TEMPLATE SYNTAX</a></li>
24         <li><a href="#wrapping">WRAPPING</a></li>
25         <li><a href="#tag_evaluation">TAG EVALUATION</a></li>
26         <ul>
27
28                 <li><a href="#simple_tag_evaluation">Simple tag evaluation</a></li>
29                 <li><a href="#conditional_tag_evaluation">Conditional tag evaluation</a></li>
30                 <li><a href="#iterator_tag_evaluation">Iterator tag evaluation</a></li>
31         </ul>
32
33         <li><a href="#special_actions">SPECIAL ACTIONS</a></li>
34         <li><a href="#see_also">SEE ALSO</a></li>
35         <li><a href="#history">HISTORY</a></li>
36 </ul>
37
38 <hr name="index" />
39 </div>
40 <!-- INDEX END -->
41
42 <p>
43 </p>
44 <h1><a name="name">NAME</a></h1>
45 <pre>
46   Squirrel::Template - simple templating system</pre>
47 <p>
48 </p>
49 <hr />
50 <h1><a name="synopsis">SYNOPSIS</a></h1>
51 <pre>
52   use Squirrel::Template;
53   my $templater = Squirrel::Template-&gt;new(template_dir =&gt; $some_dir);
54   my $result = $templater-&gt;show_page($base, $filename, \%acts, undef, $alt);
55   my $result = $templater-&gt;replace_template($text, \%acts, undef, $display_name);
56   my @errors = $templater-&gt;errors;
57   my @args = $templater-&gt;get_parms($args, \%acts, $keep_unknown)</pre>
58 <p>
59 </p>
60 <hr />
61 <h1><a name="description">DESCRIPTION</a></h1>
62 <p>BSE's template engine.</p>
63 <p>
64 </p>
65 <hr />
66 <h1><a name="methods">METHODS</a></h1>
67 <dl>
68 <dt><strong><a name="new" class="item"><code>new()</code></a></strong></dt>
69
70 <dd>
71 <pre>
72   $templater = Squirrel::Template-&gt;new(%opts);</pre>
73 <p>Create a new templating object.</p>
74 <p>Possible options are:</p>
75 <dl>
76 <dt><strong><a name="verbose" class="item">verbose</a></strong></dt>
77
78 <dd>
79 <p>If a tag isn't found in the actions then it is replaced with an error
80 message rather than being left in place.</p>
81 </dd>
82 <dt><strong><a name="template_dir" class="item">template_dir</a></strong></dt>
83
84 <dd>
85 <p>Used to find wrapper and include templates.  See <em>WRAPPING</em> below.
86 This can be either a scalar, or a reference to an array of locations
87 to search for the wrapper.</p>
88 </dd>
89 <dt><strong><a name="utf8" class="item">utf8</a></strong></dt>
90
91 <dd>
92 <p>If this is true then the template engine works in unicode internally.
93 Template files are read into memory using the charecter set specified
94 by <a href="#charset"><code>charset</code></a>.</p>
95 </dd>
96 <dt><strong><a name="charset" class="item">charset</a></strong></dt>
97
98 <dd>
99 <p>Ignored unless <a href="#utf8"><code>utf8</code></a> is true.  Specifies the character encoding used
100 by template files.  Defaults to <code>&quot;utf-8&quot;</code>.</p>
101 </dd>
102 <dt><strong><a name="cache" class="item">cache</a></strong></dt>
103
104 <dd>
105 <p>A BSE::Cache object to use for caching compiled templates.  Note that
106 templates are currently only cached by filename.</p>
107 </dd>
108 </dl>
109 </dd>
110 <dt><strong><a name="show_page" class="item"><code>show_page()</code></a></strong></dt>
111
112 <dd>
113 <pre>
114   $text = $templ-&gt;show_page($base, $template, \%acts, $iter)</pre>
115 <p>Performs template replacement on the text from the file $template in
116 directory $base.</p>
117 </dd>
118 <dt><strong><a name="replace_template" class="item"><code>replace_template()</code></a></strong></dt>
119
120 <dd>
121 <pre>
122   $text = $templ-&gt;replace_template($intext, \%acts, $iter, $name)</pre>
123 <p>Performs template replacement on <code>$intext</code> using the tags in
124 <code>%acts</code>.  <code>$iter</code> is accepted only for backward compatibility and it
125 no longer used.  Errors are reported as if <code>$intext</code> had been read
126 from a file called <code>$name</code>.</p>
127 </dd>
128 <dt><strong><a name="errors" class="item"><code>errors()</code></a></strong></dt>
129
130 <dd>
131 <p>Return errors from the last <a href="#show_page"><code>show_page()</code></a> or <a href="#replace_template"><code>replace_template()</code></a>.</p>
132 <p>This can include:</p>
133 <ul>
134 <li>
135 <p>tokenization errors - an unknown token was found in the template</p>
136 </li>
137 <li>
138 <p>parsing errors - mismatched if/eif, etc</p>
139 </li>
140 <li>
141 <p>processing errors - die from tag handlers, etc</p>
142 </li>
143 <li>
144 <p>file errors - missing include or wrap files, and recursion from those.</p>
145 </li>
146 </ul>
147 <p>Returns a list of error tokens, each of which is an array reference
148 with:</p>
149 <ul>
150 <li>
151 <p>The text &quot;error&quot;.</p>
152 </li>
153 <li>
154 <p>An template text that caused the error.  This may be blank some cases.</p>
155 </li>
156 <li>
157 <p>The line number.</p>
158 </li>
159 <li>
160 <p>The filename.  If you called <a href="#replace_template"><code>replace_template()</code></a> this will be the
161 <code>$name</code> supplied to <a href="#replace_template"><code>replace_template()</code></a>.</p>
162 </li>
163 <li>
164 <p>An error message.</p>
165 </li>
166 </ul>
167 </dd>
168 <dt><strong><a name="get_parms" class="item"><code>get_parms()</code></a></strong></dt>
169
170 <dd>
171 <pre>
172   my @args = get_parms($args, $acts, $keep_unknown)</pre>
173 <p>Does simple and stupid processing of <code>$args</code> parsing it for a list of
174 arguments.</p>
175 <p>Possible arguments that are parsed are:</p>
176 <ul>
177 <li>
178 <p><code>[</code><em>tagname</em> <em>arguments</em><code>]</code> - return the results of calling the
179 specified tag.  Only a limited amount of nesting is parsed.</p>
180 </li>
181 <li>
182 <p><code>&quot;</code><em>text</em><code>&quot;</code> - quoted text.  No escaping is done on the text.</p>
183 </li>
184 <li>
185 <p><em>text</em> - plain text not containing any <code>[</code> or <code>]</code>.</p>
186 </li>
187 </ul>
188 <p>Returns a list of parsed arguments.</p>
189 <p>If <em>tagname</em> in <code>$args</code> isn't defined, dies with an <code>ENOIMPL\n</code>
190 message.</p>
191 </dd>
192 </dl>
193 <p>
194 </p>
195 <hr />
196 <h1><a name="template_syntax">TEMPLATE SYNTAX</a></h1>
197 <p>In general, if the tag has no definition the original tag directive is
198 left in place.  If the tag has sub-components (like <code>if</code> or
199 <code>iterate</code>) tag replacement is done on the sub-components.</p>
200 <p>Directives available in templates:</p>
201 <ul>
202 <li>
203 <p><code>&lt;: name args :&gt;</code></p>
204 <p>Replaced with the value of the tag.  See <a href="#simple_tag_evaluation">Simple tag evaluation</a>.</p>
205 </li>
206 <li>
207 <p><code>&lt;: iterator begin name args :&gt; text &lt;: iterator separator name :&gt; separator &lt;: iterator end name :&gt;</code></p>
208 <p><code>&lt;: iterator begin name args :&gt; text &lt;: iterator end name :&gt;</code></p>
209 <p>Replaced with repeated templating of <em>text</em> separated by <em>separator</em>.</p>
210 <p>See <a href="#iterator_tag_evaluation">Iterator tag evaluation</a>.</p>
211 </li>
212 <li>
213 <p><code>&lt;: ifName args :&gt; true &lt;: or :&gt; false &lt;: eif :&gt;</code></p>
214 <p><code>&lt;: if Name args :&gt; true &lt;: or Name :&gt; false &lt;: eif Name :&gt;</code></p>
215 <p>Emits <em>true</em> if the tag evaluates to a true value, otherwise the
216 <em>false</em> text.  See <a href="#conditional_tag_evaluation">Conditional tag evaluation</a>.</p>
217 <p>Note that only the <code>if</code> now requires the <code>Name</code>.  The <code>or</code> and
218 <code>eif</code> may include the name, but it is not required.  If the <code>Name</code>
219 is supplied it must match the <code>if</code> <code>Name</code> or an error will be
220 returned.</p>
221 </li>
222 <li>
223 <p><code>&lt;: with begin name args :&gt; replaced &lt;: with end name :&gt;</code></p>
224 <p>Calls <code>$acts-&gt;{&quot;with_name&quot;}-&gt;($args, $replaced, &quot;&quot;, \%acts,
225 $name, $templaer)</code> where <code>$replaced</code> is the processed text and
226 inserts that.</p>
227 </dd>
228 <dt><strong><a name="your_comment" class="item">&lt;: # <em>your comment</em> :&gt;</a></strong></dt>
229
230 <dd>
231 <p>A comment, not included in the output.</p>
232 </dd>
233 <dt><strong><a name="switch_case_name_optional_args_content_endswitch" class="item">&lt;:switch:&gt;&lt;:case <em>Name</em> <em>optional-args</em> :&gt;<em>content</em> ... &lt;:endswitch:&gt;</a></strong></dt>
234
235 <dd>
236 <p>Replaced with the first matching conditional where <code>&lt;:case Name
237 optional-args :&gt;</code> is treated like an <code>if</code>.</p>
238 <p>A <code>&lt;:case default:&gt;</code> is always true.</p>
239 </li>
240 <li>
241 <p><code>&lt;: include filename options :&gt;</code></p>
242 <p>Replaced with the content of the supplied filename.</p>
243 <p>If the file <em>filename</em> is not found, this results in an error being
244 inserted (and reported via <a href="#errors">errors()</a>) unless <em>options</em> contains
245 <code>optional</code>.</p>
246 <p>No more than 10 levels of include can be nested.</p>
247 </li>
248 </ul>
249 <p>
250 </p>
251 <hr />
252 <h1><a name="wrapping">WRAPPING</a></h1>
253 <p>If you define the template_dir option when you create your templating
254 object, then a mechnism to wrap the current template with another is
255 enabled.</p>
256 <p>For the wrapping to occur:</p>
257 <ul>
258 <li>
259 <p>The template specified in the call to <a href="#replace_template"><code>replace_template()</code></a> or
260 <a href="#show_page"><code>show_page()</code></a> needs to start with:</p>
261 <p>&lt;: wrap <em>templatename</em> :&gt;</p>
262 <p>or:</p>
263 <p>&lt;: wrap <em>templatename</em> <em>name</em> =&gt; <em>value</em>, ... :&gt;</p>
264 </li>
265 <li>
266 <p>The template specified in the &lt;: wrap ... :&gt; tag must exist in the
267 directory specified by the <em>template_dir</em> option.</p>
268 </li>
269 <li>
270 <p>The template specified in the &lt;: wrap ... :&gt; tag must contain a:</p>
271 <pre>
272    &lt;: wrap here :&gt;</pre>
273 <p>tag.</p>
274 </li>
275 </ul>
276 <p>The current template text is then replaced with the contents of the
277 template specified by <em>templatename</em>, with the &lt;: wrap here :&gt;
278 replaced by the original template text.</p>
279 <p>This is then repeated for the new template text.</p>
280 <p>
281 </p>
282 <hr />
283 <h1><a name="tag_evaluation">TAG EVALUATION</a></h1>
284 <p>
285 </p>
286 <h2><a name="simple_tag_evaluation">Simple tag evaluation</a></h2>
287 <p>Tag definitions in <code>%acts</code> can be in any of five forms:</p>
288 <ul>
289 <li>
290 <p>A simple scalar - the value of the scalar is returned.</p>
291 </li>
292 <li>
293 <p>A scalar reference - the referred to scalar is returned.</p>
294 </li>
295 <li>
296 <p>A code reference - the code reference is called as:</p>
297 <pre>
298   $code-&gt;($args, \%acts, $tagname, $templater)</pre>
299 </li>
300 <li>
301 <p>An array reference starting with a code reference, followed by
302 arguments, eg <code>[ \&amp;tag_sometag, $foo, $bar ]</code>.  This is called
303 as:</p>
304 <pre>
305   $code-&gt;($foo, $bar, \%acts, $tagname, $templater)</pre>
306 </li>
307 <li>
308 <p>An array reference starting with a scalar, followed by an object or
309 class name, followed by arguments, eg <code>[ method =&gt; $obj, $foo, $bar
310 ]</code>.  This is called as:</p>
311 <pre>
312   $obj-&gt;$method($foo, $bar, \%acts, $tagname, $templater)</pre>
313 </li>
314 </ul>
315 <p>A warning is produced if the tag returns an undef value.</p>
316 <p>
317 </p>
318 <h2><a name="conditional_tag_evaluation">Conditional tag evaluation</a></h2>
319 <p>Given a <code>ifSomeName</code>, does <a href="#simple_tag_evaluation">Simple tag evaluation</a> on the
320 first tag of <code>ifSomeName</code> or <code>someName</code> found.</p>
321 <p>Unlike simple tag evaluation this does not warn if the result is undef.</p>
322 <p>
323 </p>
324 <h2><a name="iterator_tag_evaluation">Iterator tag evaluation</a></h2>
325 <p>This uses two members of <code>%acts</code>:</p>
326 <ul>
327 <li>
328 <p><code>iterate_name_reset</code> - called to start iteration.  Optional
329 but recommended.</p>
330 </li>
331 <li>
332 <p><code>iterate_name</code> - called until it returns false for each
333 iteration.</p>
334 </li>
335 </ul>
336 <p>Either can be any of:</p>
337 <ul>
338 <li>
339 <p>a code reference - called as:</p>
340 <pre>
341   $code-&gt;($args, \%acts, $name, $templater)</pre>
342 </li>
343 <li>
344 <p>an array reference starting with a code reference:</p>
345 <pre>
346   $arrayref-&gt;[0]-&gt;(@{$arrayref}[1 .. $#$arrayref], \%acts, $name, $templater);</pre>
347 </li>
348 <li>
349 <p>an array reference starting with a scalar:</p>
350 <pre>
351   $arrayref-&gt;[1]-&gt;$method(@{$arrayref}[2 .. $#$arrayref], \%acts, $name, $templater);</pre>
352 </li>
353 </ul>
354 <p>
355 </p>
356 <hr />
357 <h1><a name="special_actions">SPECIAL ACTIONS</a></h1>
358 <p>So far there's just one:</p>
359 <dl>
360 <dt><strong><a name="_format" class="item">_format</a></strong></dt>
361
362 <dd>
363 <p>If the _format action is defined in your $acts then if a function tag
364 has |text at the end of it then the function is evaluated, and the
365 resulting text and the text after the | is passed to the format
366 function.</p>
367 </dd>
368 </dl>
369 <p>
370 </p>
371 <hr />
372 <h1><a name="see_also">SEE ALSO</a></h1>
373 <p>Squirrel::Row(3p), Squirel::Table(3p)</p>
374 <p>
375 </p>
376 <hr />
377 <h1><a name="history">HISTORY</a></h1>
378 <p>Started as a quick hack from seeing the hacky template replacement
379 done by an employer.</p>
380 <p>It grew.</p>
381 <p>Largely rewritten in 2012 to avoid processing the same string a few
382 hundred times.</p>
383
384 </body>
385
386 </html>