porthole 0.99.4

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.
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/>