mustache 0.9.2 → 0.10.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/README.md CHANGED
@@ -8,7 +8,7 @@ As ctemplates says, "It emphasizes separating logic from presentation:
8
8
  it is impossible to embed application logic in this template language."
9
9
 
10
10
  For a list of implementations (other than Ruby) and tips, see
11
- <http://defunkt.github.com/mustache/>.
11
+ <http://mustache.github.com/>.
12
12
 
13
13
 
14
14
  Overview
@@ -99,7 +99,7 @@ Tag Types
99
99
 
100
100
  For a language-agnostic overview of Mustache's template syntax, see
101
101
  the `mustache(5)` manpage or
102
- <http://defunkt.github.com/mustache/mustache.5.html>.
102
+ <http://mustache.github.com/mustache.5.html>.
103
103
 
104
104
 
105
105
  Escaping
@@ -336,7 +336,7 @@ Command Line
336
336
  ------------
337
337
 
338
338
  See `mustache(1)` man page or
339
- <http://defunkt.github.com/mustache/mustache.1.html>
339
+ <http://mustache.github.com/mustache.1.html>
340
340
  for command line docs.
341
341
 
342
342
 
@@ -347,10 +347,6 @@ Installation
347
347
 
348
348
  $ gem install mustache
349
349
 
350
- ### [Rip](http://hellorip.com)
351
-
352
- $ rip install git://github.com/defunkt/mustache.git
353
-
354
350
 
355
351
  Acknowledgements
356
352
  ----------------
@@ -362,13 +358,38 @@ Special thanks to [Magnus Holm](http://judofyr.net/) for all his
362
358
  awesome work on Mustache's parser.
363
359
 
364
360
 
361
+ Contributing
362
+ ------------
363
+
364
+ Once you've made your great commits:
365
+
366
+ 1. [Fork][fk] Mustache
367
+ 2. Create a topic branch - `git checkout -b my_branch`
368
+ 3. Push to your branch - `git push origin my_branch`
369
+ 4. Create an [Issue][is] with a link to your branch
370
+ 5. That's it!
371
+
372
+ You might want to checkout Resque's [Contributing][cb] wiki page for information
373
+ on coding standards, new features, etc.
374
+
375
+
376
+ Mailing List
377
+ ------------
378
+
379
+ To join the list simply send an email to <mustache@librelist.com>. This
380
+ will subscribe you and send you information about your subscription,
381
+ including unsubscribe information.
382
+
383
+ The archive can be found at <http://librelist.com/browser/>.
384
+
385
+
365
386
  Meta
366
387
  ----
367
388
 
368
389
  * Code: `git clone git://github.com/defunkt/mustache.git`
369
- * Home: <http://defunkt.github.com/mustache>
390
+ * Home: <http://mustache.github.com>
370
391
  * Bugs: <http://github.com/defunkt/mustache/issues>
371
- * List: <http://groups.google.com/group/mustache-rb>
392
+ * List: <mustache@librelist.com>
372
393
  * Test: <http://runcoderun.com/defunkt/mustache>
373
394
  * Gems: <http://rubygems.org/gems/mustache>
374
395
 
@@ -379,3 +400,6 @@ You can also find us in `#{` on irc.freenode.net.
379
400
  [3]: http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html
380
401
  [4]: http://github.com/brynary/rack-bug/
381
402
  [5]: http://img.skitch.com/20091027-n8pxwwx8r61tc318a15q1n6m14.png
403
+ [cb]: http://wiki.github.com/defunkt/resque/contributing
404
+ [fk]: http://help.github.com/forking/
405
+ [is]: http://github.com/defunkt/mustache/issues
data/Rakefile CHANGED
@@ -94,7 +94,7 @@ task :pages => [ "man:build" ] do
94
94
  end
95
95
 
96
96
  `git commit -am 'generated manual'`
97
- `git checkout gh-pages`
97
+ `git checkout site`
98
98
 
99
99
  Dir['*.newhtml'].each do |f|
100
100
  mv f, f.sub('.newhtml', '.html')
@@ -102,7 +102,7 @@ task :pages => [ "man:build" ] do
102
102
 
103
103
  `git add .`
104
104
  `git commit -m updated`
105
- `git push origin gh-pages`
105
+ `git push site site:master`
106
106
  `git checkout master`
107
107
  puts :done
108
108
  end
data/bin/mustache CHANGED
@@ -23,7 +23,7 @@ class Mustache
23
23
  opts.separator " "
24
24
 
25
25
  opts.separator " See mustache(1) or " +
26
- "http://defunkt.github.com/mustache/mustache.1.html"
26
+ "http://mustache.github.com/mustache.1.html"
27
27
  opts.separator " for more details."
28
28
 
29
29
  opts.separator " "
@@ -109,6 +109,23 @@ class Mustache
109
109
  compiled
110
110
  end
111
111
 
112
+ # Fired when we find an inverted section. Just like `on_section`,
113
+ # we're passed the inverted section name and the array of tokens.
114
+ def on_inverted_section(name, content)
115
+ # Convert the tokenized content of this section into a Ruby
116
+ # string we can use.
117
+ code = compile(content)
118
+
119
+ # Compile the Ruby for this inverted section now that we know
120
+ # what's inside.
121
+ ev(<<-compiled)
122
+ v = ctx[#{name.to_sym.inspect}]
123
+ if v.nil? || v == false || v.respond_to?(:empty?) && v.empty?
124
+ #{code}
125
+ end
126
+ compiled
127
+ end
128
+
112
129
  # Fired when the compiler finds a partial. We want to return code
113
130
  # which calls a partial at runtime instead of expanding and
114
131
  # including the partial's body to allow for recursive partials.
@@ -45,7 +45,7 @@ EOF
45
45
  end
46
46
 
47
47
  # After these types of tags, all whitespace will be skipped.
48
- SKIP_WHITESPACE = [ '#', '/' ]
48
+ SKIP_WHITESPACE = [ '#', '^', '/' ]
49
49
 
50
50
  # The content allowed in a tag name.
51
51
  ALLOWED_CONTENT = /(\w|[?!\/-])*/
@@ -75,6 +75,13 @@ EOF
75
75
 
76
76
  # Given a string template, returns an array of tokens.
77
77
  def compile(template)
78
+ if template.respond_to?(:encoding)
79
+ @encoding = template.encoding
80
+ template = template.dup.force_encoding("BINARY")
81
+ else
82
+ @encoding = nil
83
+ end
84
+
78
85
  # Keeps information about opened sections.
79
86
  @sections = []
80
87
  @result = [:multi]
@@ -102,7 +109,7 @@ EOF
102
109
  # Since {{= rewrites ctag, we store the ctag which should be used
103
110
  # when parsing this specific tag.
104
111
  current_ctag = self.ctag
105
- type = @scanner.scan(/#|\/|=|!|<|>|&|\{/)
112
+ type = @scanner.scan(/#|\^|\/|=|!|<|>|&|\{/)
106
113
  @scanner.skip(/\s*/)
107
114
 
108
115
  # ANY_CONTENT tags allow any character inside of them, while
@@ -124,6 +131,11 @@ EOF
124
131
  @result << [:mustache, :section, content, block]
125
132
  @sections << [content, position, @result]
126
133
  @result = block
134
+ when '^'
135
+ block = [:multi]
136
+ @result << [:mustache, :inverted_section, content, block]
137
+ @sections << [content, position, @result]
138
+ @result = block
127
139
  when '/'
128
140
  section, pos, result = @sections.pop
129
141
  @result = result
@@ -173,6 +185,8 @@ EOF
173
185
  @scanner.clear
174
186
  end
175
187
 
188
+ text.force_encoding(@encoding) if @encoding
189
+
176
190
  @result << [:static, text]
177
191
  end
178
192
 
@@ -70,7 +70,7 @@ class Mustache
70
70
 
71
71
  # If it's just an anonymous subclass then don't bother, otherwise
72
72
  # give us a layout instance.
73
- if layout.name.empty?
73
+ if layout.name && layout.name.empty?
74
74
  layout = nil
75
75
  else
76
76
  layout = layout.new
@@ -15,6 +15,8 @@ class Mustache
15
15
  #
16
16
  # >> Mustache.render(template, hash)
17
17
  class Template
18
+ attr_reader :source
19
+
18
20
  # Expects a Mustache template as a string along with a template
19
21
  # path, which it uses to find partials.
20
22
  def initialize(source)
@@ -1,3 +1,3 @@
1
1
  class Mustache
2
- Version = '0.9.2'
2
+ Version = '0.10.0'
3
3
  end
data/man/mustache.1.ron CHANGED
@@ -124,4 +124,4 @@ Original CTemplate by Google
124
124
  ## SEE ALSO
125
125
 
126
126
  mustache(5), mustache(7), gem(1),
127
- <http://defunkt.github.com/mustache/>
127
+ <http://mustache.github.com/>
data/man/mustache.5 CHANGED
@@ -65,13 +65,12 @@ replaced with a value, some nothing, and others a series of
65
65
  values. This document explains the different types of Mustache tags.
66
66
  .
67
67
  .SH "TAG TYPES"
68
- Tags are indicated by the double mustaches. \fB{{name}}\fR is a tag. Let's
69
- talk about the different types of tags.
68
+ Tags are indicated by the double mustaches. \fB{{name}}\fR is a tag, as is \fB{{#name}}\fR. Let's talk about the different types of tags.
70
69
  .
71
70
  .SS "Variables"
72
71
  The most basic tag is the variable. A \fB{{name}}\fR tag in a basic
73
- template will try to call the \fBname\fR method on your view. If there is
74
- no \fBname\fR method, an exception will be raised.
72
+ template will try to find the \fBname\fR key or method on your view. If
73
+ there is no \fBname\fR method, nothing will be rendered.
75
74
  .
76
75
  .P
77
76
  All variables are HTML escaped by default. If you want to return
@@ -83,7 +82,8 @@ useful when changing delimiters (see "Set Delimter" below).
83
82
  .
84
83
  .P
85
84
  By default a variable "miss" returns an empty string. This can usually
86
- be configured in your Mustache library.
85
+ be configured in your Mustache library. The Ruby version of Mustache
86
+ supports raising an exception in this situation, for instance.
87
87
  .
88
88
  .P
89
89
  Template:
@@ -130,16 +130,27 @@ Output:
130
130
  .
131
131
  .IP "" 0
132
132
  .
133
- .SS "Boolean Sections"
133
+ .SS "Sections"
134
+ Sections render blocks of text one or more times, depending on the
135
+ value of the referenced tag.
136
+ .
137
+ .P
134
138
  A section begins with a pound and ends with a slash. That is,\fB{{#person}}\fR begins a "person" section while \fB{{/person}}\fR ends it.
135
139
  .
136
140
  .P
137
- If the \fBperson\fR key exists and calling it returns false, the HTML
138
- between the pound and slash will not be displayed.
141
+ If the \fBperson\fR key exists and calling it returns false or an empty
142
+ list, the HTML between the pound and slash will not be displayed.
143
+ .
144
+ .P
145
+ If the \fBperson\fR method exists and calling it returns true or an
146
+ object, the HTML between the pound and slash will be rendered and
147
+ displayed exactly one time. The object that was returned by the \fBperson\fR method will become the context of the block, as well.
139
148
  .
140
149
  .P
141
- If the \fBperson\fR method exists and calling it returns true, the HTML
142
- between the pound and slash will be rendered and displayed.
150
+ If the \fBperson\fR method exists and calling it returns a non\-empty list,
151
+ the text in the block will be displayed once for each item in the
152
+ list. The context of the block will be set to the current item for
153
+ each iteration. In this way we can loop over collections.
143
154
  .
144
155
  .P
145
156
  Template:
@@ -153,6 +164,9 @@ Template:
153
164
  {{#anything_else}}
154
165
  Never shown!
155
166
  {{/anything_else}}
167
+ {{#repo}}
168
+ <b>{{name}}</b>
169
+ {{/repo}}
156
170
  .
157
171
  .fi
158
172
  .
@@ -165,7 +179,12 @@ Hash:
165
179
  .
166
180
  .nf
167
181
  {
168
- "person": true
182
+ "person": true,
183
+ "repo": [
184
+ { "name": "resque" },
185
+ { "name": "hub" },
186
+ { "name": "rip" },
187
+ ]
169
188
  }
170
189
  .
171
190
  .fi
@@ -179,21 +198,23 @@ Output:
179
198
  .
180
199
  .nf
181
200
  Shown!
201
+ <b>resque</b>
202
+ <b>hub</b>
203
+ <b>rip</b>
182
204
  .
183
205
  .fi
184
206
  .
185
207
  .IP "" 0
186
208
  .
187
- .SS "Enumerable Sections"
188
- Enumerable sections are syntactically identical to boolean sections in
189
- that they begin with a pound and end with a slash. The difference,
190
- however, is in the view: if the method called returns an enumerable,
191
- the section is repeated as the enumerable is iterated over.
209
+ .SS "Inverted Sections"
210
+ An inverted section begins with a caret (hat) and ends with a
211
+ slash. That is \fB{{^person}}\fR begins a "person" inverted section while \fB{{/person}}\fR ends it.
192
212
  .
193
213
  .P
194
- Each item in the enumerable is expected to be a hash which will then
195
- become the context of the corresponding iteration. In this way we can
196
- construct loops.
214
+ While sections can be used to render text one or more times based on the
215
+ value of the key given, inverted sections may render text once based
216
+ on the inverse value of the key given. That is, they will be rendered
217
+ if the key doesn't exist, is false, or is an empty list.
197
218
  .
198
219
  .P
199
220
  Template:
@@ -204,6 +225,9 @@ Template:
204
225
  {{#repo}}
205
226
  <b>{{name}}</b>
206
227
  {{/repo}}
228
+ {{^repo}}
229
+ No repos :(
230
+ {{/repo}}
207
231
  .
208
232
  .fi
209
233
  .
@@ -216,11 +240,7 @@ Hash:
216
240
  .
217
241
  .nf
218
242
  {
219
- "repo": [
220
- { "name": "resque" },
221
- { "name": "hub" },
222
- { "name": "rip" },
223
- ]
243
+ "repo": []
224
244
  }
225
245
  .
226
246
  .fi
@@ -233,9 +253,7 @@ Output:
233
253
  .IP "" 4
234
254
  .
235
255
  .nf
236
- <b>resque</b>
237
- <b>hub</b>
238
- <b>rip</b>
256
+ No repos :(
239
257
  .
240
258
  .fi
241
259
  .
@@ -269,9 +287,40 @@ Will render as follows:
269
287
  Partials begin with a greater than sign, like \fB{{> box}}\fR.
270
288
  .
271
289
  .P
272
- It is useful to think of partials as a "template expansion" \- that is,
273
- the actual partial tag will be replaced with the content of the
274
- partial. Therefor partials share the current context.
290
+ Partials are rendered at runtime (as opposed to compile time), so
291
+ recursive partials are possible. Just avoid infinite loops.
292
+ .
293
+ .P
294
+ They also inherit the calling context. Whereas in ERB you may have
295
+ this:
296
+ .
297
+ .IP "" 4
298
+ .
299
+ .nf
300
+ <%= partial :next_more, :start => start, :size => size %>
301
+ .
302
+ .fi
303
+ .
304
+ .IP "" 0
305
+ .
306
+ .P
307
+ Mustache requires only this:
308
+ .
309
+ .IP "" 4
310
+ .
311
+ .nf
312
+ {{> next_more}}
313
+ .
314
+ .fi
315
+ .
316
+ .IP "" 0
317
+ .
318
+ .P
319
+ Why? Because the \fBnext_more.mustache\fR file will inherit the \fBsize\fR and \fBstart\fR methods from the calling context.
320
+ .
321
+ .P
322
+ In this way you may want to think of partials as includes, or template
323
+ expansion, even though it's not literally true.
275
324
  .
276
325
  .P
277
326
  For example, this template and partial:
data/man/mustache.5.html CHANGED
@@ -106,14 +106,14 @@ values. This document explains the different types of Mustache tags.</p>
106
106
 
107
107
  <h2>TAG TYPES</h2>
108
108
 
109
- <p>Tags are indicated by the double mustaches. <code>{{name}}</code> is a tag. Let's
110
- talk about the different types of tags.</p>
109
+ <p>Tags are indicated by the double mustaches. <code>{{name}}</code> is a tag, as is
110
+ <code>{{#name}}</code>. Let's talk about the different types of tags.</p>
111
111
 
112
112
  <h3>Variables</h3>
113
113
 
114
114
  <p>The most basic tag is the variable. A <code>{{name}}</code> tag in a basic
115
- template will try to call the <code>name</code> method on your view. If there is
116
- no <code>name</code> method, an exception will be raised.</p>
115
+ template will try to find the <code>name</code> key or method on your view. If
116
+ there is no <code>name</code> method, nothing will be rendered.</p>
117
117
 
118
118
  <p>All variables are HTML escaped by default. If you want to return
119
119
  unescaped HTML, use the triple mustache: <code>{{{name}}}</code>.</p>
@@ -122,7 +122,8 @@ unescaped HTML, use the triple mustache: <code>{{{name}}}</code>.</p>
122
122
  useful when changing delimiters (see "Set Delimter" below).</p>
123
123
 
124
124
  <p>By default a variable "miss" returns an empty string. This can usually
125
- be configured in your Mustache library.</p>
125
+ be configured in your Mustache library. The Ruby version of Mustache
126
+ supports raising an exception in this situation, for instance.</p>
126
127
 
127
128
  <p>Template:</p>
128
129
 
@@ -148,16 +149,26 @@ be configured in your Mustache library.</p>
148
149
  * &lt;b&gt;GitHub&lt;/b&gt;
149
150
  </code></pre>
150
151
 
151
- <h3>Boolean Sections</h3>
152
+ <h3>Sections</h3>
153
+
154
+ <p>Sections render blocks of text one or more times, depending on the
155
+ value of the referenced tag.</p>
152
156
 
153
157
  <p>A section begins with a pound and ends with a slash. That is,
154
158
  <code>{{#person}}</code> begins a "person" section while <code>{{/person}}</code> ends it.</p>
155
159
 
156
- <p>If the <code>person</code> key exists and calling it returns false, the HTML
157
- between the pound and slash will not be displayed.</p>
160
+ <p>If the <code>person</code> key exists and calling it returns false or an empty
161
+ list, the HTML between the pound and slash will not be displayed.</p>
162
+
163
+ <p>If the <code>person</code> method exists and calling it returns true or an
164
+ object, the HTML between the pound and slash will be rendered and
165
+ displayed exactly one time. The object that was returned by the
166
+ <code>person</code> method will become the context of the block, as well.</p>
158
167
 
159
- <p>If the <code>person</code> method exists and calling it returns true, the HTML
160
- between the pound and slash will be rendered and displayed.</p>
168
+ <p>If the <code>person</code> method exists and calling it returns a non-empty list,
169
+ the text in the block will be displayed once for each item in the
170
+ list. The context of the block will be set to the current item for
171
+ each iteration. In this way we can loop over collections.</p>
161
172
 
162
173
  <p>Template:</p>
163
174
 
@@ -167,54 +178,62 @@ between the pound and slash will be rendered and displayed.</p>
167
178
  {{#anything_else}}
168
179
  Never shown!
169
180
  {{/anything_else}}
181
+ {{#repo}}
182
+ &lt;b&gt;{{name}}&lt;/b&gt;
183
+ {{/repo}}
170
184
  </code></pre>
171
185
 
172
186
  <p>Hash:</p>
173
187
 
174
188
  <pre><code>{
175
- "person": true
189
+ "person": true,
190
+ "repo": [
191
+ { "name": "resque" },
192
+ { "name": "hub" },
193
+ { "name": "rip" },
194
+ ]
176
195
  }
177
196
  </code></pre>
178
197
 
179
198
  <p>Output:</p>
180
199
 
181
200
  <pre><code>Shown!
201
+ &lt;b&gt;resque&lt;/b&gt;
202
+ &lt;b&gt;hub&lt;/b&gt;
203
+ &lt;b&gt;rip&lt;/b&gt;
182
204
  </code></pre>
183
205
 
184
- <h3>Enumerable Sections</h3>
206
+ <h3>Inverted Sections</h3>
185
207
 
186
- <p>Enumerable sections are syntactically identical to boolean sections in
187
- that they begin with a pound and end with a slash. The difference,
188
- however, is in the view: if the method called returns an enumerable,
189
- the section is repeated as the enumerable is iterated over.</p>
208
+ <p>An inverted section begins with a caret (hat) and ends with a
209
+ slash. That is <code>{{^person}}</code> begins a "person" inverted section while
210
+ <code>{{/person}}</code> ends it.</p>
190
211
 
191
- <p>Each item in the enumerable is expected to be a hash which will then
192
- become the context of the corresponding iteration. In this way we can
193
- construct loops.</p>
212
+ <p>While sections can be used to render text one or more times based on the
213
+ value of the key given, inverted sections may render text once based
214
+ on the inverse value of the key given. That is, they will be rendered
215
+ if the key doesn't exist, is false, or is an empty list.</p>
194
216
 
195
217
  <p>Template:</p>
196
218
 
197
219
  <pre><code>{{#repo}}
198
220
  &lt;b&gt;{{name}}&lt;/b&gt;
199
221
  {{/repo}}
222
+ {{^repo}}
223
+ No repos :(
224
+ {{/repo}}
200
225
  </code></pre>
201
226
 
202
227
  <p>Hash:</p>
203
228
 
204
229
  <pre><code>{
205
- "repo": [
206
- { "name": "resque" },
207
- { "name": "hub" },
208
- { "name": "rip" },
209
- ]
230
+ "repo": []
210
231
  }
211
232
  </code></pre>
212
233
 
213
234
  <p>Output:</p>
214
235
 
215
- <pre><code>&lt;b&gt;resque&lt;/b&gt;
216
- &lt;b&gt;hub&lt;/b&gt;
217
- &lt;b&gt;rip&lt;/b&gt;
236
+ <pre><code>No repos :(
218
237
  </code></pre>
219
238
 
220
239
  <h3>Comments</h3>
@@ -233,9 +252,25 @@ construct loops.</p>
233
252
 
234
253
  <p>Partials begin with a greater than sign, like <code>{{&gt; box}}</code>.</p>
235
254
 
236
- <p>It is useful to think of partials as a "template expansion" - that is,
237
- the actual partial tag will be replaced with the content of the
238
- partial. Therefor partials share the current context.</p>
255
+ <p>Partials are rendered at runtime (as opposed to compile time), so
256
+ recursive partials are possible. Just avoid infinite loops.</p>
257
+
258
+ <p>They also inherit the calling context. Whereas in ERB you may have
259
+ this:</p>
260
+
261
+ <pre><code>&lt;%= partial :next_more, :start =&gt; start, :size =&gt; size %&gt;
262
+ </code></pre>
263
+
264
+ <p>Mustache requires only this:</p>
265
+
266
+ <pre><code>{{&gt; next_more}}
267
+ </code></pre>
268
+
269
+ <p>Why? Because the <code>next_more.mustache</code> file will inherit the <code>size</code> and
270
+ <code>start</code> methods from the calling context.</p>
271
+
272
+ <p>In this way you may want to think of partials as includes, or template
273
+ expansion, even though it's not literally true.</p>
239
274
 
240
275
  <p>For example, this template and partial:</p>
241
276
 
data/man/mustache.5.ron CHANGED
@@ -41,15 +41,15 @@ values. This document explains the different types of Mustache tags.
41
41
 
42
42
  ## TAG TYPES
43
43
 
44
- Tags are indicated by the double mustaches. `{{name}}` is a tag. Let's
45
- talk about the different types of tags.
44
+ Tags are indicated by the double mustaches. `{{name}}` is a tag, as is
45
+ `{{#name}}`. Let's talk about the different types of tags.
46
46
 
47
47
 
48
48
  ### Variables
49
49
 
50
50
  The most basic tag is the variable. A `{{name}}` tag in a basic
51
- template will try to call the `name` method on your view. If there is
52
- no `name` method, an exception will be raised.
51
+ template will try to find the `name` key or method on your view. If
52
+ there is no `name` method, nothing will be rendered.
53
53
 
54
54
  All variables are HTML escaped by default. If you want to return
55
55
  unescaped HTML, use the triple mustache: `{{{name}}}`.
@@ -58,7 +58,8 @@ You can also use `&` to unescape a variable: `{{& name}}`. This may be
58
58
  useful when changing delimiters (see "Set Delimter" below).
59
59
 
60
60
  By default a variable "miss" returns an empty string. This can usually
61
- be configured in your Mustache library.
61
+ be configured in your Mustache library. The Ruby version of Mustache
62
+ supports raising an exception in this situation, for instance.
62
63
 
63
64
  Template:
64
65
 
@@ -81,16 +82,27 @@ Output:
81
82
  * &lt;b&gt;GitHub&lt;/b&gt;
82
83
  * <b>GitHub</b>
83
84
 
84
- ### Boolean Sections
85
+
86
+ ### Sections
87
+
88
+ Sections render blocks of text one or more times, depending on the
89
+ value of the referenced tag.
85
90
 
86
91
  A section begins with a pound and ends with a slash. That is,
87
92
  `{{#person}}` begins a "person" section while `{{/person}}` ends it.
88
93
 
89
- If the `person` key exists and calling it returns false, the HTML
90
- between the pound and slash will not be displayed.
94
+ If the `person` key exists and calling it returns false or an empty
95
+ list, the HTML between the pound and slash will not be displayed.
91
96
 
92
- If the `person` method exists and calling it returns true, the HTML
93
- between the pound and slash will be rendered and displayed.
97
+ If the `person` method exists and calling it returns true or an
98
+ object, the HTML between the pound and slash will be rendered and
99
+ displayed exactly one time. The object that was returned by the
100
+ `person` method will become the context of the block, as well.
101
+
102
+ If the `person` method exists and calling it returns a non-empty list,
103
+ the text in the block will be displayed once for each item in the
104
+ list. The context of the block will be set to the current item for
105
+ each iteration. In this way we can loop over collections.
94
106
 
95
107
  Template:
96
108
 
@@ -100,49 +112,58 @@ Template:
100
112
  {{#anything_else}}
101
113
  Never shown!
102
114
  {{/anything_else}}
115
+ {{#repo}}
116
+ <b>{{name}}</b>
117
+ {{/repo}}
103
118
 
104
119
  Hash:
105
120
 
106
121
  {
107
- "person": true
122
+ "person": true,
123
+ "repo": [
124
+ { "name": "resque" },
125
+ { "name": "hub" },
126
+ { "name": "rip" },
127
+ ]
108
128
  }
109
129
 
110
130
  Output:
111
131
 
112
132
  Shown!
133
+ <b>resque</b>
134
+ <b>hub</b>
135
+ <b>rip</b>
136
+
113
137
 
114
- ### Enumerable Sections
138
+ ### Inverted Sections
115
139
 
116
- Enumerable sections are syntactically identical to boolean sections in
117
- that they begin with a pound and end with a slash. The difference,
118
- however, is in the view: if the method called returns an enumerable,
119
- the section is repeated as the enumerable is iterated over.
140
+ An inverted section begins with a caret (hat) and ends with a
141
+ slash. That is `{{^person}}` begins a "person" inverted section while
142
+ `{{/person}}` ends it.
120
143
 
121
- Each item in the enumerable is expected to be a hash which will then
122
- become the context of the corresponding iteration. In this way we can
123
- construct loops.
144
+ While sections can be used to render text one or more times based on the
145
+ value of the key given, inverted sections may render text once based
146
+ on the inverse value of the key given. That is, they will be rendered
147
+ if the key doesn't exist, is false, or is an empty list.
124
148
 
125
149
  Template:
126
150
 
127
151
  {{#repo}}
128
152
  <b>{{name}}</b>
129
153
  {{/repo}}
154
+ {{^repo}}
155
+ No repos :(
156
+ {{/repo}}
130
157
 
131
158
  Hash:
132
159
 
133
160
  {
134
- "repo": [
135
- { "name": "resque" },
136
- { "name": "hub" },
137
- { "name": "rip" },
138
- ]
161
+ "repo": []
139
162
  }
140
163
 
141
164
  Output:
142
165
 
143
- <b>resque</b>
144
- <b>hub</b>
145
- <b>rip</b>
166
+ No repos :(
146
167
 
147
168
 
148
169
  ### Comments
@@ -160,9 +181,23 @@ Will render as follows:
160
181
 
161
182
  Partials begin with a greater than sign, like `{{> box}}`.
162
183
 
163
- It is useful to think of partials as a "template expansion" - that is,
164
- the actual partial tag will be replaced with the content of the
165
- partial. Therefor partials share the current context.
184
+ Partials are rendered at runtime (as opposed to compile time), so
185
+ recursive partials are possible. Just avoid infinite loops.
186
+
187
+ They also inherit the calling context. Whereas in ERB you may have
188
+ this:
189
+
190
+ <%= partial :next_more, :start => start, :size => size %>
191
+
192
+ Mustache requires only this:
193
+
194
+ {{> next_more}}
195
+
196
+ Why? Because the `next_more.mustache` file will inherit the `size` and
197
+ `start` methods from the calling context.
198
+
199
+ In this way you may want to think of partials as includes, or template
200
+ expansion, even though it's not literally true.
166
201
 
167
202
  For example, this template and partial:
168
203
 
@@ -220,4 +255,4 @@ Original CTemplate by Google
220
255
  ## SEE ALSO
221
256
 
222
257
  mustache(1), mustache(7), gem(1),
223
- <http://defunkt.github.com/mustache/>
258
+ <http://mustache.github.com/>
@@ -11,6 +11,7 @@
11
11
  {{/item}}
12
12
  </ul>
13
13
  {{/list}}
14
- {{#empty}}
14
+
15
+ {{^list}}
15
16
  <p>The list is empty.</p>
16
- {{/empty}}
17
+ {{/list}}
@@ -0,0 +1,7 @@
1
+ {{^t}}
2
+ * first
3
+ {{/t}}
4
+ * {{two}}
5
+ {{^t}}
6
+ * third
7
+ {{/t}}
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ class InvertedSection < Mustache
5
+ self.path = File.dirname(__FILE__)
6
+
7
+ def t
8
+ false
9
+ end
10
+
11
+ def two
12
+ "second"
13
+ end
14
+ end
@@ -11,6 +11,7 @@
11
11
  {{/item}}
12
12
  </ul>
13
13
  {{/list}}
14
- {{#empty}}
14
+
15
+ {{^list}}
15
16
  <p>The list is empty.</p>
16
- {{/empty}}
17
+ {{/list}}
@@ -57,6 +57,16 @@ rendered
57
57
  rendered
58
58
  end
59
59
 
60
+ def test_single_line_inverted_sections
61
+ html = %(<p class="flash-notice" {{^ flash }}style="display: none;"{{/ flash }}>)
62
+
63
+ instance = Mustache.new
64
+ instance.template = html
65
+ assert_equal <<-rendered.strip, instance.render
66
+ <p class="flash-notice" style="display: none;">
67
+ rendered
68
+ end
69
+
60
70
  def test_simple
61
71
  assert_equal <<-end_simple, Simple.render
62
72
  Hello Chris
@@ -123,6 +133,14 @@ end_template
123
133
  end_section
124
134
  end
125
135
 
136
+ def test_inverted_section
137
+ assert_equal <<-end_section.strip, InvertedSection.render.strip
138
+ * first
139
+ * second
140
+ * third
141
+ end_section
142
+ end
143
+
126
144
  def test_comments
127
145
  assert_equal "<h1>A Comedy of Errors</h1>\n", Comments.render
128
146
  end
@@ -393,4 +411,21 @@ rendered
393
411
  <h2>中文又来啦</h2>
394
412
  rendered
395
413
  end
414
+
415
+ def test_indentation
416
+ view = Mustache.new
417
+ view[:name] = 'indent'
418
+ view[:text] = 'puts :indented!'
419
+ view.template = <<template
420
+ def {{name}}
421
+ {{text}}
422
+ end
423
+ template
424
+
425
+ assert_equal <<template, view.render
426
+ def indent
427
+ puts :indented!
428
+ end
429
+ template
430
+ end
396
431
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mustache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-03-29 00:00:00 -07:00
12
+ date: 2010-04-02 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -69,6 +69,8 @@ files:
69
69
  - test/fixtures/escaped.rb
70
70
  - test/fixtures/inner_partial.mustache
71
71
  - test/fixtures/inner_partial.txt
72
+ - test/fixtures/inverted_section.mustache
73
+ - test/fixtures/inverted_section.rb
72
74
  - test/fixtures/namespaced.mustache
73
75
  - test/fixtures/namespaced.rb
74
76
  - test/fixtures/nested_objects.mustache