porthole 0.99.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +415 -0
  3. data/Rakefile +89 -0
  4. data/bin/porthole +94 -0
  5. data/lib/porthole.rb +304 -0
  6. data/lib/porthole/context.rb +142 -0
  7. data/lib/porthole/generator.rb +195 -0
  8. data/lib/porthole/parser.rb +263 -0
  9. data/lib/porthole/settings.rb +226 -0
  10. data/lib/porthole/sinatra.rb +205 -0
  11. data/lib/porthole/template.rb +58 -0
  12. data/lib/porthole/version.rb +3 -0
  13. data/lib/rack/bug/panels/mustache_panel.rb +81 -0
  14. data/lib/rack/bug/panels/mustache_panel/mustache_extension.rb +27 -0
  15. data/lib/rack/bug/panels/mustache_panel/view.mustache +46 -0
  16. data/man/porthole.1 +165 -0
  17. data/man/porthole.1.html +213 -0
  18. data/man/porthole.1.ron +127 -0
  19. data/man/porthole.5 +539 -0
  20. data/man/porthole.5.html +422 -0
  21. data/man/porthole.5.ron +324 -0
  22. data/test/autoloading_test.rb +56 -0
  23. data/test/fixtures/comments.porthole +1 -0
  24. data/test/fixtures/comments.rb +14 -0
  25. data/test/fixtures/complex_view.porthole +17 -0
  26. data/test/fixtures/complex_view.rb +34 -0
  27. data/test/fixtures/crazy_recursive.porthole +9 -0
  28. data/test/fixtures/crazy_recursive.rb +31 -0
  29. data/test/fixtures/delimiters.porthole +8 -0
  30. data/test/fixtures/delimiters.rb +23 -0
  31. data/test/fixtures/dot_notation.porthole +10 -0
  32. data/test/fixtures/dot_notation.rb +25 -0
  33. data/test/fixtures/double_section.porthole +7 -0
  34. data/test/fixtures/double_section.rb +14 -0
  35. data/test/fixtures/escaped.porthole +1 -0
  36. data/test/fixtures/escaped.rb +14 -0
  37. data/test/fixtures/inner_partial.porthole +1 -0
  38. data/test/fixtures/inner_partial.txt +1 -0
  39. data/test/fixtures/inverted_section.porthole +7 -0
  40. data/test/fixtures/inverted_section.rb +14 -0
  41. data/test/fixtures/lambda.porthole +7 -0
  42. data/test/fixtures/lambda.rb +31 -0
  43. data/test/fixtures/method_missing.rb +19 -0
  44. data/test/fixtures/namespaced.porthole +1 -0
  45. data/test/fixtures/namespaced.rb +25 -0
  46. data/test/fixtures/nested_objects.porthole +17 -0
  47. data/test/fixtures/nested_objects.rb +35 -0
  48. data/test/fixtures/node.porthole +8 -0
  49. data/test/fixtures/partial_with_module.porthole +4 -0
  50. data/test/fixtures/partial_with_module.rb +37 -0
  51. data/test/fixtures/passenger.conf +5 -0
  52. data/test/fixtures/passenger.rb +27 -0
  53. data/test/fixtures/recursive.porthole +4 -0
  54. data/test/fixtures/recursive.rb +14 -0
  55. data/test/fixtures/simple.porthole +5 -0
  56. data/test/fixtures/simple.rb +26 -0
  57. data/test/fixtures/template_partial.porthole +2 -0
  58. data/test/fixtures/template_partial.rb +18 -0
  59. data/test/fixtures/template_partial.txt +4 -0
  60. data/test/fixtures/unescaped.porthole +1 -0
  61. data/test/fixtures/unescaped.rb +14 -0
  62. data/test/fixtures/utf8.porthole +3 -0
  63. data/test/fixtures/utf8_partial.porthole +1 -0
  64. data/test/helper.rb +7 -0
  65. data/test/parser_test.rb +78 -0
  66. data/test/partial_test.rb +168 -0
  67. data/test/porthole_test.rb +677 -0
  68. data/test/spec_test.rb +68 -0
  69. data/test/template_test.rb +20 -0
  70. metadata +127 -0
@@ -0,0 +1,422 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv='content-type' value='text/html;charset=utf8'>
5
+ <meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
6
+ <title>porthole(5) - Logic-less templates.</title>
7
+ <style type='text/css' media='all'>
8
+ /* style: man */
9
+ body#manpage {margin:0}
10
+ .mp {max-width:100ex;padding:0 9ex 1ex 4ex}
11
+ .mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
12
+ .mp h2 {margin:10px 0 0 0}
13
+ .mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
14
+ .mp h3 {margin:0 0 0 4ex}
15
+ .mp dt {margin:0;clear:left}
16
+ .mp dt.flush {float:left;width:8ex}
17
+ .mp dd {margin:0 0 0 9ex}
18
+ .mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
19
+ .mp pre {margin-bottom:20px}
20
+ .mp pre+h2,.mp pre+h3 {margin-top:22px}
21
+ .mp h2+pre,.mp h3+pre {margin-top:5px}
22
+ .mp img {display:block;margin:auto}
23
+ .mp h1.man-title {display:none}
24
+ .mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
25
+ .mp h2 {font-size:16px;line-height:1.25}
26
+ .mp h1 {font-size:20px;line-height:2}
27
+ .mp {text-align:justify;background:#fff}
28
+ .mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
29
+ .mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
30
+ .mp u {text-decoration:underline}
31
+ .mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
32
+ .mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
33
+ .mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
34
+ .mp b.man-ref {font-weight:normal;color:#434241}
35
+ .mp pre {padding:0 4ex}
36
+ .mp pre code {font-weight:normal;color:#434241}
37
+ .mp h2+pre,h3+pre {padding-left:0}
38
+ ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
39
+ ol.man-decor {width:100%}
40
+ ol.man-decor li.tl {text-align:left}
41
+ ol.man-decor li.tc {text-align:center;letter-spacing:4px}
42
+ ol.man-decor li.tr {text-align:right;float:right}
43
+ </style>
44
+ </head>
45
+ <!--
46
+ The following styles are deprecated and will be removed at some point:
47
+ div#man, div#man ol.man, div#man ol.head, div#man ol.man.
48
+
49
+ The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
50
+ .man-navigation should be used instead.
51
+ -->
52
+ <body id='manpage'>
53
+ <div class='mp' id='man'>
54
+
55
+ <div class='man-navigation' style='display:none'>
56
+ <a href="#NAME">NAME</a>
57
+ <a href="#SYNOPSIS">SYNOPSIS</a>
58
+ <a href="#DESCRIPTION">DESCRIPTION</a>
59
+ <a href="#TAG-TYPES">TAG TYPES</a>
60
+ <a href="#COPYRIGHT">COPYRIGHT</a>
61
+ <a href="#SEE-ALSO">SEE ALSO</a>
62
+ </div>
63
+
64
+ <ol class='man-decor man-head man head'>
65
+ <li class='tl'>porthole(5)</li>
66
+ <li class='tc'>Porthole Manual</li>
67
+ <li class='tr'>porthole(5)</li>
68
+ </ol>
69
+
70
+ <h2 id="NAME">NAME</h2>
71
+ <p class="man-name">
72
+ <code>porthole</code> - <span class="man-whatis">Logic-less templates.</span>
73
+ </p>
74
+
75
+ <h2 id="SYNOPSIS">SYNOPSIS</h2>
76
+
77
+ <p>A typical Porthole template:</p>
78
+
79
+ <pre><code>Hello {{name}}
80
+ You have just won {{value}} dollars!
81
+ {{#in_ca}}
82
+ Well, {{taxed_value}} dollars, after taxes.
83
+ {{/in_ca}}
84
+ </code></pre>
85
+
86
+ <p>Given the following hash:</p>
87
+
88
+ <pre><code>{
89
+ "name": "Chris",
90
+ "value": 10000,
91
+ "taxed_value": 10000 - (10000 * 0.4),
92
+ "in_ca": true
93
+ }
94
+ </code></pre>
95
+
96
+ <p>Will produce the following:</p>
97
+
98
+ <pre><code>Hello Chris
99
+ You have just won 10000 dollars!
100
+ Well, 6000.0 dollars, after taxes.
101
+ </code></pre>
102
+
103
+ <h2 id="DESCRIPTION">DESCRIPTION</h2>
104
+
105
+ <p>Porthole can be used for HTML, config files, source code -
106
+ anything. It works by expanding tags in a template using values
107
+ provided in a hash or object.</p>
108
+
109
+ <p>We call it "logic-less" because there are no if statements, else
110
+ clauses, or for loops. Instead there are only tags. Some tags are
111
+ replaced with a value, some nothing, and others a series of
112
+ values. This document explains the different types of Porthole tags.</p>
113
+
114
+ <h2 id="TAG-TYPES">TAG TYPES</h2>
115
+
116
+ <p>Tags are indicated by the double portholes. <code>{{person}}</code> is a tag, as
117
+ is <code>{{#person}}</code>. In both examples, we'd refer to <code>person</code> as the key
118
+ or tag key. Let's talk about the different types of tags.</p>
119
+
120
+ <h3 id="Variables">Variables</h3>
121
+
122
+ <p>The most basic tag type is the variable. A <code>{{name}}</code> tag in a basic
123
+ template will try to find the <code>name</code> key in the current context. If
124
+ there is no <code>name</code> key, nothing will be rendered.</p>
125
+
126
+ <p>All variables are HTML escaped by default. If you want to return
127
+ unescaped HTML, use the triple porthole: <code>{{{name}}}</code>.</p>
128
+
129
+ <p>You can also use <code>&amp;</code> to unescape a variable: <code>{{&amp; name}}</code>. This may be
130
+ useful when changing delimiters (see "Set Delimiter" below).</p>
131
+
132
+ <p>By default a variable "miss" returns an empty string. This can usually
133
+ be configured in your Porthole library. The Ruby version of Porthole
134
+ supports raising an exception in this situation, for instance.</p>
135
+
136
+ <p>Template:</p>
137
+
138
+ <pre><code>* {{name}}
139
+ * {{age}}
140
+ * {{company}}
141
+ * {{{company}}}
142
+ </code></pre>
143
+
144
+ <p>Hash:</p>
145
+
146
+ <pre><code>{
147
+ "name": "Chris",
148
+ "company": "&lt;b&gt;GitHub&lt;/b&gt;"
149
+ }
150
+ </code></pre>
151
+
152
+ <p>Output:</p>
153
+
154
+ <pre><code>* Chris
155
+ *
156
+ * &amp;lt;b&amp;gt;GitHub&amp;lt;/b&amp;gt;
157
+ * &lt;b&gt;GitHub&lt;/b&gt;
158
+ </code></pre>
159
+
160
+ <h3 id="Sections">Sections</h3>
161
+
162
+ <p>Sections render blocks of text one or more times, depending on the
163
+ value of the key in the current context.</p>
164
+
165
+ <p>A section begins with a pound and ends with a slash. That is,
166
+ <code>{{#person}}</code> begins a "person" section while <code>{{/person}}</code> ends it.</p>
167
+
168
+ <p>The behavior of the section is determined by the value of the key.</p>
169
+
170
+ <p><strong>False Values or Empty Lists</strong></p>
171
+
172
+ <p>If the <code>person</code> key exists and has a value of false or an empty
173
+ list, the HTML between the pound and slash will not be displayed.</p>
174
+
175
+ <p>Template:</p>
176
+
177
+ <pre><code>Shown.
178
+ {{#nothin}}
179
+ Never shown!
180
+ {{/nothin}}
181
+ </code></pre>
182
+
183
+ <p>Hash:</p>
184
+
185
+ <pre><code>{
186
+ "person": true,
187
+ }
188
+ </code></pre>
189
+
190
+ <p>Output:</p>
191
+
192
+ <pre><code>Shown.
193
+ </code></pre>
194
+
195
+ <p><strong>Non-Empty Lists</strong></p>
196
+
197
+ <p>If the <code>person</code> key exists and has a non-false value, the HTML between
198
+ the pound and slash will be rendered and displayed one or more times.</p>
199
+
200
+ <p>When the value is a non-empty list, the text in the block will be
201
+ displayed once for each item in the list. The context of the block
202
+ will be set to the current item for each iteration. In this way we can
203
+ loop over collections.</p>
204
+
205
+ <p>Template:</p>
206
+
207
+ <pre><code>{{#repo}}
208
+ &lt;b&gt;{{name}}&lt;/b&gt;
209
+ {{/repo}}
210
+ </code></pre>
211
+
212
+ <p>Hash:</p>
213
+
214
+ <pre><code>{
215
+ "repo": [
216
+ { "name": "resque" },
217
+ { "name": "hub" },
218
+ { "name": "rip" },
219
+ ]
220
+ }
221
+ </code></pre>
222
+
223
+ <p>Output:</p>
224
+
225
+ <pre><code>&lt;b&gt;resque&lt;/b&gt;
226
+ &lt;b&gt;hub&lt;/b&gt;
227
+ &lt;b&gt;rip&lt;/b&gt;
228
+ </code></pre>
229
+
230
+ <p><strong>Lambdas</strong></p>
231
+
232
+ <p>When the value is a callable object, such as a function or lambda, the
233
+ object will be invoked and passed the block of text. The text passed
234
+ is the literal block, unrendered. <code>{{tags}}</code> will not have been expanded
235
+ - the lambda should do that on its own. In this way you can implement
236
+ filters or caching.</p>
237
+
238
+ <p>Template:</p>
239
+
240
+ <pre><code>{{#wrapped}}
241
+ {{name}} is awesome.
242
+ {{/wrapped}}
243
+ </code></pre>
244
+
245
+ <p>Hash:</p>
246
+
247
+ <pre><code>{
248
+ "name": "Willy",
249
+ "wrapped": function() {
250
+ return function(text) {
251
+ return "&lt;b&gt;" + render(text) + "&lt;/b&gt;"
252
+ }
253
+ }
254
+ }
255
+ </code></pre>
256
+
257
+ <p>Output:</p>
258
+
259
+ <pre><code>&lt;b&gt;Willy is awesome.&lt;/b&gt;
260
+ </code></pre>
261
+
262
+ <p><strong>Non-False Values</strong></p>
263
+
264
+ <p>When the value is non-false but not a list, it will be used as the
265
+ context for a single rendering of the block.</p>
266
+
267
+ <p>Template:</p>
268
+
269
+ <pre><code>{{#person?}}
270
+ Hi {{name}}!
271
+ {{/person?}}
272
+ </code></pre>
273
+
274
+ <p>Hash:</p>
275
+
276
+ <pre><code>{
277
+ "person?": { "name": "Jon" }
278
+ }
279
+ </code></pre>
280
+
281
+ <p>Output:</p>
282
+
283
+ <pre><code>Hi Jon!
284
+ </code></pre>
285
+
286
+ <h3 id="Inverted-Sections">Inverted Sections</h3>
287
+
288
+ <p>An inverted section begins with a caret (hat) and ends with a
289
+ slash. That is <code>{{^person}}</code> begins a "person" inverted section while
290
+ <code>{{/person}}</code> ends it.</p>
291
+
292
+ <p>While sections can be used to render text one or more times based on the
293
+ value of the key, inverted sections may render text once based
294
+ on the inverse value of the key. That is, they will be rendered
295
+ if the key doesn't exist, is false, or is an empty list.</p>
296
+
297
+ <p>Template:</p>
298
+
299
+ <pre><code>{{#repo}}
300
+ &lt;b&gt;{{name}}&lt;/b&gt;
301
+ {{/repo}}
302
+ {{^repo}}
303
+ No repos :(
304
+ {{/repo}}
305
+ </code></pre>
306
+
307
+ <p>Hash:</p>
308
+
309
+ <pre><code>{
310
+ "repo": []
311
+ }
312
+ </code></pre>
313
+
314
+ <p>Output:</p>
315
+
316
+ <pre><code>No repos :(
317
+ </code></pre>
318
+
319
+ <h3 id="Comments">Comments</h3>
320
+
321
+ <p>Comments begin with a bang and are ignored. The following template:</p>
322
+
323
+ <pre><code>&lt;h1&gt;Today{{! ignore me }}.&lt;/h1&gt;
324
+ </code></pre>
325
+
326
+ <p>Will render as follows:</p>
327
+
328
+ <pre><code>&lt;h1&gt;Today.&lt;/h1&gt;
329
+ </code></pre>
330
+
331
+ <p>Comments may contain newlines.</p>
332
+
333
+ <h3 id="Partials">Partials</h3>
334
+
335
+ <p>Partials begin with a greater than sign, like <code>{{&gt; box}}</code>.</p>
336
+
337
+ <p>Partials are rendered at runtime (as opposed to compile time), so
338
+ recursive partials are possible. Just avoid infinite loops.</p>
339
+
340
+ <p>They also inherit the calling context. Whereas in ERB you may have
341
+ this:</p>
342
+
343
+ <pre><code>&lt;%= partial :next_more, :start =&gt; start, :size =&gt; size %&gt;
344
+ </code></pre>
345
+
346
+ <p>Porthole requires only this:</p>
347
+
348
+ <pre><code>{{&gt; next_more}}
349
+ </code></pre>
350
+
351
+ <p>Why? Because the <code>next_more.porthole</code> file will inherit the <code>size</code> and
352
+ <code>start</code> methods from the calling context.</p>
353
+
354
+ <p>In this way you may want to think of partials as includes, or template
355
+ expansion, even though it's not literally true.</p>
356
+
357
+ <p>For example, this template and partial:</p>
358
+
359
+ <pre><code>base.porthole:
360
+ &lt;h2&gt;Names&lt;/h2&gt;
361
+ {{#names}}
362
+ {{&gt; user}}
363
+ {{/names}}
364
+
365
+ user.porthole:
366
+ &lt;strong&gt;{{name}}&lt;/strong&gt;
367
+ </code></pre>
368
+
369
+ <p>Can be thought of as a single, expanded template:</p>
370
+
371
+ <pre><code>&lt;h2&gt;Names&lt;/h2&gt;
372
+ {{#names}}
373
+ &lt;strong&gt;{{name}}&lt;/strong&gt;
374
+ {{/names}}
375
+ </code></pre>
376
+
377
+ <h3 id="Set-Delimiter">Set Delimiter</h3>
378
+
379
+ <p>Set Delimiter tags start with an equal sign and change the tag
380
+ delimiters from <code>{{</code> and <code>}}</code> to custom strings.</p>
381
+
382
+ <p>Consider the following contrived example:</p>
383
+
384
+ <pre><code>* {{default_tags}}
385
+ {{=&lt;% %>=}}
386
+ * &lt;% erb_style_tags %>
387
+ &lt;%={{ }}=%>
388
+ * {{ default_tags_again }}
389
+ </code></pre>
390
+
391
+ <p>Here we have a list with three items. The first item uses the default
392
+ tag style, the second uses erb style as defined by the Set Delimiter
393
+ tag, and the third returns to the default style after yet another Set
394
+ Delimiter declaration.</p>
395
+
396
+ <p>According to <a href="http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html">ctemplates</a>, this "is useful for languages like TeX, where
397
+ double-braces may occur in the text and are awkward to use for
398
+ markup."</p>
399
+
400
+ <p>Custom delimiters may not contain whitespace or the equals sign.</p>
401
+
402
+ <h2 id="COPYRIGHT">COPYRIGHT</h2>
403
+
404
+ <p>Porthole is Copyright (C) 2009 Chris Wanstrath</p>
405
+
406
+ <p>Original CTemplate by Google</p>
407
+
408
+ <h2 id="SEE-ALSO">SEE ALSO</h2>
409
+
410
+ <p><a href="porthole.1.ron.html" class="man-ref">porthole<span class="s">(1)</span></a>,
411
+ <a href="http://porthole.github.com/" data-bare-link="true">http://porthole.github.com/</a></p>
412
+
413
+
414
+ <ol class='man-decor man-foot man foot'>
415
+ <li class='tl'>DEFUNKT</li>
416
+ <li class='tc'>August 2011</li>
417
+ <li class='tr'>porthole(5)</li>
418
+ </ol>
419
+
420
+ </div>
421
+ </body>
422
+ </html>
@@ -0,0 +1,324 @@
1
+ porthole(5) -- Logic-less templates.
2
+ ====================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ A typical Porthole template:
7
+
8
+ Hello {{name}}
9
+ You have just won {{value}} dollars!
10
+ {{#in_ca}}
11
+ Well, {{taxed_value}} dollars, after taxes.
12
+ {{/in_ca}}
13
+
14
+ Given the following hash:
15
+
16
+ {
17
+ "name": "Chris",
18
+ "value": 10000,
19
+ "taxed_value": 10000 - (10000 * 0.4),
20
+ "in_ca": true
21
+ }
22
+
23
+ Will produce the following:
24
+
25
+ Hello Chris
26
+ You have just won 10000 dollars!
27
+ Well, 6000.0 dollars, after taxes.
28
+
29
+
30
+ ## DESCRIPTION
31
+
32
+ Porthole can be used for HTML, config files, source code -
33
+ anything. It works by expanding tags in a template using values
34
+ provided in a hash or object.
35
+
36
+ We call it "logic-less" because there are no if statements, else
37
+ clauses, or for loops. Instead there are only tags. Some tags are
38
+ replaced with a value, some nothing, and others a series of
39
+ values. This document explains the different types of Porthole tags.
40
+
41
+
42
+ ## TAG TYPES
43
+
44
+ Tags are indicated by the double portholes. `{{person}}` is a tag, as
45
+ is `{{#person}}`. In both examples, we'd refer to `person` as the key
46
+ or tag key. Let's talk about the different types of tags.
47
+
48
+
49
+ ### Variables
50
+
51
+ The most basic tag type is the variable. A `{{name}}` tag in a basic
52
+ template will try to find the `name` key in the current context. If
53
+ there is no `name` key, nothing will be rendered.
54
+
55
+ All variables are HTML escaped by default. If you want to return
56
+ unescaped HTML, use the triple porthole: `{{{name}}}`.
57
+
58
+ You can also use `&` to unescape a variable: `{{& name}}`. This may be
59
+ useful when changing delimiters (see "Set Delimiter" below).
60
+
61
+ By default a variable "miss" returns an empty string. This can usually
62
+ be configured in your Porthole library. The Ruby version of Porthole
63
+ supports raising an exception in this situation, for instance.
64
+
65
+ Template:
66
+
67
+ * {{name}}
68
+ * {{age}}
69
+ * {{company}}
70
+ * {{{company}}}
71
+
72
+ Hash:
73
+
74
+ {
75
+ "name": "Chris",
76
+ "company": "<b>GitHub</b>"
77
+ }
78
+
79
+ Output:
80
+
81
+ * Chris
82
+ *
83
+ * &lt;b&gt;GitHub&lt;/b&gt;
84
+ * <b>GitHub</b>
85
+
86
+
87
+ ### Sections
88
+
89
+ Sections render blocks of text one or more times, depending on the
90
+ value of the key in the current context.
91
+
92
+ A section begins with a pound and ends with a slash. That is,
93
+ `{{#person}}` begins a "person" section while `{{/person}}` ends it.
94
+
95
+ The behavior of the section is determined by the value of the key.
96
+
97
+ **False Values or Empty Lists**
98
+
99
+ If the `person` key exists and has a value of false or an empty
100
+ list, the HTML between the pound and slash will not be displayed.
101
+
102
+ Template:
103
+
104
+ Shown.
105
+ {{#nothin}}
106
+ Never shown!
107
+ {{/nothin}}
108
+
109
+ Hash:
110
+
111
+ {
112
+ "person": true,
113
+ }
114
+
115
+ Output:
116
+
117
+ Shown.
118
+
119
+ **Non-Empty Lists**
120
+
121
+ If the `person` key exists and has a non-false value, the HTML between
122
+ the pound and slash will be rendered and displayed one or more times.
123
+
124
+ When the value is a non-empty list, the text in the block will be
125
+ displayed once for each item in the list. The context of the block
126
+ will be set to the current item for each iteration. In this way we can
127
+ loop over collections.
128
+
129
+ Template:
130
+
131
+ {{#repo}}
132
+ <b>{{name}}</b>
133
+ {{/repo}}
134
+
135
+ Hash:
136
+
137
+ {
138
+ "repo": [
139
+ { "name": "resque" },
140
+ { "name": "hub" },
141
+ { "name": "rip" },
142
+ ]
143
+ }
144
+
145
+ Output:
146
+
147
+ <b>resque</b>
148
+ <b>hub</b>
149
+ <b>rip</b>
150
+
151
+ **Lambdas**
152
+
153
+ When the value is a callable object, such as a function or lambda, the
154
+ object will be invoked and passed the block of text. The text passed
155
+ is the literal block, unrendered. `{{tags}}` will not have been expanded
156
+ - the lambda should do that on its own. In this way you can implement
157
+ filters or caching.
158
+
159
+ Template:
160
+
161
+ {{#wrapped}}
162
+ {{name}} is awesome.
163
+ {{/wrapped}}
164
+
165
+ Hash:
166
+
167
+ {
168
+ "name": "Willy",
169
+ "wrapped": function() {
170
+ return function(text) {
171
+ return "<b>" + render(text) + "</b>"
172
+ }
173
+ }
174
+ }
175
+
176
+ Output:
177
+
178
+ <b>Willy is awesome.</b>
179
+
180
+ **Non-False Values**
181
+
182
+ When the value is non-false but not a list, it will be used as the
183
+ context for a single rendering of the block.
184
+
185
+ Template:
186
+
187
+ {{#person?}}
188
+ Hi {{name}}!
189
+ {{/person?}}
190
+
191
+ Hash:
192
+
193
+ {
194
+ "person?": { "name": "Jon" }
195
+ }
196
+
197
+ Output:
198
+
199
+ Hi Jon!
200
+
201
+
202
+ ### Inverted Sections
203
+
204
+ An inverted section begins with a caret (hat) and ends with a
205
+ slash. That is `{{^person}}` begins a "person" inverted section while
206
+ `{{/person}}` ends it.
207
+
208
+ While sections can be used to render text one or more times based on the
209
+ value of the key, inverted sections may render text once based
210
+ on the inverse value of the key. That is, they will be rendered
211
+ if the key doesn't exist, is false, or is an empty list.
212
+
213
+ Template:
214
+
215
+ {{#repo}}
216
+ <b>{{name}}</b>
217
+ {{/repo}}
218
+ {{^repo}}
219
+ No repos :(
220
+ {{/repo}}
221
+
222
+ Hash:
223
+
224
+ {
225
+ "repo": []
226
+ }
227
+
228
+ Output:
229
+
230
+ No repos :(
231
+
232
+
233
+ ### Comments
234
+
235
+ Comments begin with a bang and are ignored. The following template:
236
+
237
+ <h1>Today{{! ignore me }}.</h1>
238
+
239
+ Will render as follows:
240
+
241
+ <h1>Today.</h1>
242
+
243
+ Comments may contain newlines.
244
+
245
+
246
+ ### Partials
247
+
248
+ Partials begin with a greater than sign, like `{{> box}}`.
249
+
250
+ Partials are rendered at runtime (as opposed to compile time), so
251
+ recursive partials are possible. Just avoid infinite loops.
252
+
253
+ They also inherit the calling context. Whereas in ERB you may have
254
+ this:
255
+
256
+ <%= partial :next_more, :start => start, :size => size %>
257
+
258
+ Porthole requires only this:
259
+
260
+ {{> next_more}}
261
+
262
+ Why? Because the `next_more.porthole` file will inherit the `size` and
263
+ `start` methods from the calling context.
264
+
265
+ In this way you may want to think of partials as includes, or template
266
+ expansion, even though it's not literally true.
267
+
268
+ For example, this template and partial:
269
+
270
+ base.porthole:
271
+ <h2>Names</h2>
272
+ {{#names}}
273
+ {{> user}}
274
+ {{/names}}
275
+
276
+ user.porthole:
277
+ <strong>{{name}}</strong>
278
+
279
+ Can be thought of as a single, expanded template:
280
+
281
+ <h2>Names</h2>
282
+ {{#names}}
283
+ <strong>{{name}}</strong>
284
+ {{/names}}
285
+
286
+
287
+ ### Set Delimiter
288
+
289
+ Set Delimiter tags start with an equal sign and change the tag
290
+ delimiters from `{{` and `}}` to custom strings.
291
+
292
+ Consider the following contrived example:
293
+
294
+ * {{default_tags}}
295
+ {{=<% %>=}}
296
+ * <% erb_style_tags %>
297
+ <%={{ }}=%>
298
+ * {{ default_tags_again }}
299
+
300
+ Here we have a list with three items. The first item uses the default
301
+ tag style, the second uses erb style as defined by the Set Delimiter
302
+ tag, and the third returns to the default style after yet another Set
303
+ Delimiter declaration.
304
+
305
+ According to [ctemplates][ct], this "is useful for languages like TeX, where
306
+ double-braces may occur in the text and are awkward to use for
307
+ markup."
308
+
309
+ Custom delimiters may not contain whitespace or the equals sign.
310
+
311
+ [ct]: http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html
312
+
313
+
314
+ ## COPYRIGHT
315
+
316
+ Porthole is Copyright (C) 2009 Chris Wanstrath
317
+
318
+ Original CTemplate by Google
319
+
320
+
321
+ ## SEE ALSO
322
+
323
+ porthole(1),
324
+ <http://porthole.github.com/>