mustache 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +30 -179
- data/Rakefile +87 -46
- data/bin/mustache +10 -19
- data/lib/mustache/context.rb +55 -12
- data/lib/mustache/sinatra.rb +1 -1
- data/lib/mustache/template.rb +3 -15
- data/lib/mustache/version.rb +1 -1
- data/man/mustache.1 +138 -0
- data/man/mustache.1.html +168 -0
- data/man/mustache.1.ron +94 -0
- data/man/mustache.5 +364 -0
- data/man/mustache.5.html +300 -0
- data/man/mustache.5.ron +220 -0
- data/test/helper.rb +1 -0
- data/test/mustache_test.rb +25 -16
- metadata +32 -65
- data/.gitignore +0 -1
- data/.kick +0 -26
- data/CONTRIBUTORS +0 -6
- data/HISTORY.md +0 -70
- data/benchmarks/complex.erb +0 -15
- data/benchmarks/complex.haml +0 -10
- data/benchmarks/helper.rb +0 -20
- data/benchmarks/simple.erb +0 -5
- data/benchmarks/speed.rb +0 -76
- data/contrib/mustache.vim +0 -69
- data/contrib/tpl-mode.el +0 -274
- data/examples/comments.mustache +0 -1
- data/examples/comments.rb +0 -14
- data/examples/complex_view.mustache +0 -16
- data/examples/complex_view.rb +0 -34
- data/examples/delimiters.mustache +0 -6
- data/examples/delimiters.rb +0 -22
- data/examples/double_section.mustache +0 -7
- data/examples/double_section.rb +0 -14
- data/examples/escaped.mustache +0 -1
- data/examples/escaped.rb +0 -14
- data/examples/inner_partial.mustache +0 -1
- data/examples/inner_partial.txt +0 -1
- data/examples/namespaced.mustache +0 -1
- data/examples/namespaced.rb +0 -25
- data/examples/partial_with_module.mustache +0 -3
- data/examples/partial_with_module.rb +0 -37
- data/examples/passenger.conf +0 -5
- data/examples/passenger.rb +0 -27
- data/examples/simple.mustache +0 -5
- data/examples/simple.rb +0 -26
- data/examples/template_partial.mustache +0 -2
- data/examples/template_partial.rb +0 -18
- data/examples/template_partial.txt +0 -4
- data/examples/unescaped.mustache +0 -1
- data/examples/unescaped.rb +0 -14
data/README.md
CHANGED
|
@@ -7,6 +7,9 @@ framework-agnostic way to render logic-free views.
|
|
|
7
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
|
+
For a list of implementations (other than Ruby) and tips, see
|
|
11
|
+
<http://defunkt.github.com/mustache/>.
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
Overview
|
|
12
15
|
--------
|
|
@@ -94,139 +97,22 @@ Simple.
|
|
|
94
97
|
Tag Types
|
|
95
98
|
---------
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
### Variables
|
|
101
|
-
|
|
102
|
-
The most basic tag is the variable. A `{{name}}` tag in a basic
|
|
103
|
-
template will try to call the `name` method on your view. If there is
|
|
104
|
-
no `name` method, an exception will be raised.
|
|
105
|
-
|
|
106
|
-
All variables are HTML escaped by default. If you want to return
|
|
107
|
-
unescaped HTML, use the triple mustache: `{{{name}}}`.
|
|
108
|
-
|
|
109
|
-
By default a variable "miss" returns an empty string. You can
|
|
110
|
-
configure this by setting `Mustache.raise_on_context_miss` to true.
|
|
111
|
-
|
|
112
|
-
### Boolean Sections
|
|
113
|
-
|
|
114
|
-
A section begins with a pound and ends with a slash. That is,
|
|
115
|
-
`{{#person}}` begins a "person" section while `{{/person}}` ends it.
|
|
116
|
-
|
|
117
|
-
If the `person` method exists and calling it returns false, the HTML
|
|
118
|
-
between the pound and slash will not be displayed.
|
|
119
|
-
|
|
120
|
-
If the `person` method exists and calling it returns true, the HTML
|
|
121
|
-
between the pound and slash will be rendered and displayed.
|
|
122
|
-
|
|
123
|
-
### Enumerable Sections
|
|
124
|
-
|
|
125
|
-
Enumerable sections are syntactically identical to boolean sections in
|
|
126
|
-
that they begin with a pound and end with a slash. The difference,
|
|
127
|
-
however, is in the view: if the method called returns an enumerable,
|
|
128
|
-
the section is repeated as the enumerable is iterated over.
|
|
129
|
-
|
|
130
|
-
Each item in the enumerable is expected to be a hash which will then
|
|
131
|
-
become the context of the corresponding iteration. In this way we can
|
|
132
|
-
construct loops.
|
|
133
|
-
|
|
134
|
-
For example, imagine this template:
|
|
135
|
-
|
|
136
|
-
{{#repo}}
|
|
137
|
-
<b>{{name}}</b>
|
|
138
|
-
{{/repo}}
|
|
139
|
-
|
|
140
|
-
And this view code:
|
|
141
|
-
|
|
142
|
-
def repo
|
|
143
|
-
Repository.all.map { |r| { :name => r.to_s } }
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
When rendered, our view will contain a list of all repository names in
|
|
147
|
-
the database.
|
|
148
|
-
|
|
149
|
-
As a convenience, if a section returns a hash (as opposed to an array
|
|
150
|
-
or a boolean) it will be treated as a single item array.
|
|
151
|
-
|
|
152
|
-
With the above template, we could use this Ruby code for a single
|
|
153
|
-
iteration:
|
|
154
|
-
|
|
155
|
-
def repo
|
|
156
|
-
{ :name => Repository.first.to_s }
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
This would be treated by Mustache as functionally equivalent to the
|
|
160
|
-
following:
|
|
161
|
-
|
|
162
|
-
def repo
|
|
163
|
-
[ { :name => Repository.first.to_s } ]
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
### Comments
|
|
168
|
-
|
|
169
|
-
Comments begin with a bang and are ignored. The following template:
|
|
100
|
+
For a language-agnostic overview of Mustache's template syntax, see
|
|
101
|
+
the `mustache(5)` manpage or
|
|
102
|
+
<http://defunkt.github.com/mustache/mustache.5.html>.
|
|
170
103
|
|
|
171
|
-
<h1>Today{{! ignore me }}.</h1>
|
|
172
104
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<h1>Today.</h1>
|
|
176
|
-
|
|
177
|
-
### Partials
|
|
178
|
-
|
|
179
|
-
Partials begin with a greater than sign, like `{{> box}}`.
|
|
180
|
-
|
|
181
|
-
It is useful to think of partials as a "template expansion" - that is,
|
|
182
|
-
the actual partial tag will be replaced with the content of the
|
|
183
|
-
partial. Therefor partials share the current context.
|
|
184
|
-
|
|
185
|
-
For example, this template and partial:
|
|
186
|
-
|
|
187
|
-
base.mustache
|
|
188
|
-
Names:
|
|
189
|
-
{{# names }}
|
|
190
|
-
{{> user }}
|
|
191
|
-
{{/ names }}
|
|
192
|
-
|
|
193
|
-
user.mustache:
|
|
194
|
-
<strong>{{ name }}</strong>
|
|
195
|
-
|
|
196
|
-
Can be thought of as a single, expanded template:
|
|
197
|
-
|
|
198
|
-
Names:
|
|
199
|
-
{{# names }}
|
|
200
|
-
<strong>{{ name }}</strong>
|
|
201
|
-
{{/ names }}
|
|
202
|
-
|
|
203
|
-
Have partial-specific code you want to share between view classes?
|
|
204
|
-
Consider using a module and including it.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
### Set Delimiter
|
|
208
|
-
|
|
209
|
-
Set Delimiter tags start with an equal sign and change the tag
|
|
210
|
-
delimiters from {{ and }} to custom strings.
|
|
211
|
-
|
|
212
|
-
Consider the following contrived example:
|
|
213
|
-
|
|
214
|
-
* {{ default_tags }}
|
|
215
|
-
{{=<% %>=}}
|
|
216
|
-
* <% erb_style_tags %>
|
|
217
|
-
<%={{ }}=%>
|
|
218
|
-
* {{ default_tags_again }}
|
|
219
|
-
|
|
220
|
-
Here we have a list with three items. The first item uses the default
|
|
221
|
-
tag style, the second uses erb style as defined by the Set Delimiter
|
|
222
|
-
tag, and the third returns to the default style after yet another Set
|
|
223
|
-
Delimiter declaration.
|
|
105
|
+
Escaping
|
|
106
|
+
--------
|
|
224
107
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
108
|
+
Mustache does escape all values when using the standard double
|
|
109
|
+
Mustache syntax. Characters which will be escaped: `& \ " < >`. To
|
|
110
|
+
disable escaping, simply use tripple mustaches like
|
|
111
|
+
`{{{unescaped_variable}}}`.
|
|
228
112
|
|
|
229
|
-
|
|
113
|
+
Example: Using `{{variable}}` inside a template for `5 > 2` will
|
|
114
|
+
result in `5 > 2`, where as the usage of `{{{variable}}}` will
|
|
115
|
+
result in `5 > 2`.
|
|
230
116
|
|
|
231
117
|
|
|
232
118
|
Dict-Style Views
|
|
@@ -417,69 +303,37 @@ Vim
|
|
|
417
303
|
Thanks to [Juvenn Woo](http://github.com/juvenn) for mustache.vim. It
|
|
418
304
|
is included under the contrib/ directory.
|
|
419
305
|
|
|
306
|
+
See <http://gist.github.com/323622> for installation instructions.
|
|
420
307
|
|
|
421
308
|
Emacs
|
|
422
309
|
-----
|
|
423
310
|
|
|
424
|
-
|
|
425
|
-
Based on Google's tpl-mode for ctemplates, it adds
|
|
426
|
-
more lenient tag values and includes a few
|
|
311
|
+
mustache-mode.el is included under the contrib/ directory for any
|
|
312
|
+
Emacs users. Based on Google's tpl-mode for ctemplates, it adds
|
|
313
|
+
support for Mustache's more lenient tag values and includes a few
|
|
314
|
+
commands for your editing pleasure.
|
|
315
|
+
|
|
316
|
+
See <http://gist.github.com/323619> for installation instructions.
|
|
427
317
|
|
|
428
318
|
|
|
429
319
|
TextMate
|
|
430
320
|
--------
|
|
431
321
|
|
|
432
|
-
|
|
433
|
-
[Mustache.tmbundle](http://github.com/tekkub/Mustache.tmbundle).
|
|
322
|
+
[Mustache.tmbundle](http://github.com/defunkt/Mustache.tmbundle)
|
|
434
323
|
|
|
324
|
+
See <http://gist.github.com/323624> for installation instructions.
|
|
435
325
|
|
|
436
326
|
Command Line
|
|
437
327
|
------------
|
|
438
328
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
HTML as Mustache later, you can do it now!
|
|
443
|
-
|
|
444
|
-
The script expects a Mustache template on STDIN with YAML
|
|
445
|
-
frontmatter. An example looks like this:
|
|
446
|
-
|
|
447
|
-
$ cat complete.mustache
|
|
448
|
-
---
|
|
449
|
-
names: [ {name: chris}, {name: mark}, {name: scott} ]
|
|
450
|
-
---
|
|
451
|
-
{{#names}}
|
|
452
|
-
Hi {{name}}!
|
|
453
|
-
{{/names}}
|
|
454
|
-
|
|
455
|
-
$ cat complete.mustache | mustache
|
|
456
|
-
Hi chris!
|
|
457
|
-
Hi mark!
|
|
458
|
-
Hi scott!
|
|
459
|
-
|
|
460
|
-
It's probably more useful to keep the YAML and HTML in separate files,
|
|
461
|
-
though. Luckily `cat` works great for this, too:
|
|
462
|
-
|
|
463
|
-
$ cat data.yml
|
|
464
|
-
---
|
|
465
|
-
names: [ {name: chris}, {name: mark}, {name: scott} ]
|
|
466
|
-
---
|
|
467
|
-
|
|
468
|
-
$ cat template.mustache
|
|
469
|
-
{{#names}}
|
|
470
|
-
Hi {{name}}!
|
|
471
|
-
{{/names}}
|
|
472
|
-
|
|
473
|
-
$ cat data.yml template.mustache | mustache
|
|
474
|
-
Hi chris!
|
|
475
|
-
Hi mark!
|
|
476
|
-
Hi scott!
|
|
477
|
-
|
|
329
|
+
See `mustache(1)` man page or
|
|
330
|
+
<http://defunkt.github.com/mustache/mustache.1.html>
|
|
331
|
+
for command line docs.
|
|
478
332
|
|
|
479
333
|
Installation
|
|
480
334
|
------------
|
|
481
335
|
|
|
482
|
-
### [
|
|
336
|
+
### [RubyGems](http://rubygems.org/)
|
|
483
337
|
|
|
484
338
|
$ gem install mustache
|
|
485
339
|
|
|
@@ -487,7 +341,6 @@ Installation
|
|
|
487
341
|
|
|
488
342
|
$ rip install git://github.com/defunkt/mustache.git
|
|
489
343
|
|
|
490
|
-
|
|
491
344
|
Acknowledgements
|
|
492
345
|
----------------
|
|
493
346
|
|
|
@@ -499,13 +352,11 @@ Meta
|
|
|
499
352
|
----
|
|
500
353
|
|
|
501
354
|
* Code: `git clone git://github.com/defunkt/mustache.git`
|
|
502
|
-
* Home: <http://github.com/
|
|
503
|
-
* Docs: <http://defunkt.github.com/mustache>
|
|
355
|
+
* Home: <http://defunkt.github.com/mustache>
|
|
504
356
|
* Bugs: <http://github.com/defunkt/mustache/issues>
|
|
505
357
|
* List: <http://groups.google.com/group/mustache-rb>
|
|
506
358
|
* Test: <http://runcoderun.com/defunkt/mustache>
|
|
507
|
-
* Gems: <http://
|
|
508
|
-
* Boss: Chris Wanstrath :: <http://github.com/defunkt>
|
|
359
|
+
* Gems: <http://rubygems.org/gems/mustache>
|
|
509
360
|
|
|
510
361
|
[1]: http://code.google.com/p/google-ctemplate/
|
|
511
362
|
[2]: http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html
|
data/Rakefile
CHANGED
|
@@ -1,66 +1,107 @@
|
|
|
1
1
|
require 'rake/testtask'
|
|
2
2
|
require 'rake/rdoctask'
|
|
3
3
|
|
|
4
|
+
def command?(command)
|
|
5
|
+
system("type #{command} > /dev/null")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Tests
|
|
10
|
+
#
|
|
11
|
+
|
|
4
12
|
task :default => :test
|
|
5
13
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
if command? :turn
|
|
15
|
+
desc "Run tests"
|
|
16
|
+
task :test do
|
|
17
|
+
exec "turn"
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
Rake::TestTask.new do |t|
|
|
21
|
+
t.libs << 'lib'
|
|
22
|
+
t.pattern = 'test/**/*_test.rb'
|
|
23
|
+
t.verbose = false
|
|
24
|
+
end
|
|
10
25
|
end
|
|
11
26
|
|
|
12
|
-
|
|
13
|
-
|
|
27
|
+
#
|
|
28
|
+
# Ron
|
|
29
|
+
#
|
|
14
30
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
31
|
+
if command? :ron
|
|
32
|
+
desc "Show the manual"
|
|
33
|
+
task :man => "man:build" do
|
|
34
|
+
exec "man man/mustache.1"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
desc "Build the manual"
|
|
38
|
+
task "man:build" do
|
|
39
|
+
sh "ron -br5 --organization=DEFUNKT --manual='Mustache Manual' man/*.ron"
|
|
40
|
+
end
|
|
19
41
|
end
|
|
20
42
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
gemspec.name = "mustache"
|
|
27
|
-
gemspec.summary = "Mustache is a framework-agnostic way to render logic-free views."
|
|
28
|
-
gemspec.description = "Mustache is a framework-agnostic way to render logic-free views."
|
|
29
|
-
gemspec.email = "chris@ozmm.org"
|
|
30
|
-
gemspec.homepage = "http://github.com/defunkt/mustache"
|
|
31
|
-
gemspec.authors = ["Chris Wanstrath"]
|
|
32
|
-
gemspec.version = Mustache::Version
|
|
43
|
+
if command? :kicker
|
|
44
|
+
desc "Launch Kicker (like autotest)"
|
|
45
|
+
task :kicker do
|
|
46
|
+
puts "Kicking... (ctrl+c to cancel)"
|
|
47
|
+
exec "kicker -e rake test lib examples"
|
|
33
48
|
end
|
|
34
|
-
rescue LoadError
|
|
35
|
-
puts "Jeweler not available."
|
|
36
|
-
puts "Install it with: gem install jeweler"
|
|
37
49
|
end
|
|
38
50
|
|
|
51
|
+
#
|
|
52
|
+
# Gems
|
|
53
|
+
#
|
|
54
|
+
|
|
39
55
|
begin
|
|
40
|
-
require '
|
|
56
|
+
require 'mg'
|
|
57
|
+
MG.new("mustache.gemspec")
|
|
58
|
+
|
|
59
|
+
desc "Build a gem."
|
|
60
|
+
task :gem => :package
|
|
61
|
+
|
|
62
|
+
# Ensure tests pass before pushing a gem.
|
|
63
|
+
task :gemcutter => :test
|
|
64
|
+
|
|
65
|
+
desc "Push a new version to Gemcutter and publish docs."
|
|
66
|
+
task :publish => :gemcutter do
|
|
67
|
+
system "git tag v#{Mustache::Version}"
|
|
68
|
+
system "git push origin v#{Mustache::Version}"
|
|
69
|
+
system "git push origin master"
|
|
70
|
+
system "gem push pkg/mustache-#{Mustache::Version}.gem"
|
|
71
|
+
system "git clean -fd"
|
|
72
|
+
exec "rake pages"
|
|
73
|
+
end
|
|
41
74
|
rescue LoadError
|
|
42
|
-
|
|
75
|
+
warn "mg not available."
|
|
76
|
+
warn "Install it with: gem i mg"
|
|
43
77
|
end
|
|
44
78
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
system "git push origin v#{Mustache::Version}"
|
|
49
|
-
system "git push origin master"
|
|
50
|
-
system "gem push pkg/mustache-#{Mustache::Version}.gem"
|
|
51
|
-
system "git clean -fd"
|
|
52
|
-
exec "rake pages"
|
|
53
|
-
end
|
|
79
|
+
#
|
|
80
|
+
# Documentation
|
|
81
|
+
#
|
|
54
82
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
83
|
+
# begin
|
|
84
|
+
# require 'sdoc_helpers'
|
|
85
|
+
# rescue LoadError
|
|
86
|
+
# warn "sdoc support not enabled. Please gem install sdoc-helpers."
|
|
87
|
+
# end
|
|
88
|
+
|
|
89
|
+
desc "Publish to GitHub Pages"
|
|
90
|
+
task :pages => [ "build:man" ] do
|
|
91
|
+
Dir['man/*.html'].each do |f|
|
|
92
|
+
cp f, File.basename(f).sub('.html', '.newhtml')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
`git commit -am 'generated manual'`
|
|
96
|
+
`git checkout gh-pages`
|
|
97
|
+
|
|
98
|
+
Dir['*.newhtml'].each do |f|
|
|
99
|
+
mv f, f.sub('.newhtml', '.html')
|
|
100
|
+
end
|
|
59
101
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Mustache.const_set(:Version, version)
|
|
102
|
+
`git add .`
|
|
103
|
+
`git commit -m updated`
|
|
104
|
+
`git push origin gh-pages`
|
|
105
|
+
`git checkout master`
|
|
106
|
+
puts :done
|
|
66
107
|
end
|
data/bin/mustache
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
require 'mustache'
|
|
4
4
|
require 'yaml'
|
|
5
5
|
|
|
6
|
-
if
|
|
7
|
-
doc =
|
|
6
|
+
if !$stdin.tty?
|
|
7
|
+
doc = $stdin.read
|
|
8
8
|
if doc =~ /^(\s*---(.*)---\s*)/m
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
yaml = $2.strip
|
|
10
|
+
template = doc.sub($1, '')
|
|
11
|
+
|
|
12
|
+
YAML.each_document(yaml) do |data|
|
|
13
|
+
puts Mustache.render(template, data)
|
|
14
|
+
end
|
|
11
15
|
else
|
|
12
16
|
puts doc
|
|
13
17
|
end
|
|
@@ -15,20 +19,7 @@ else
|
|
|
15
19
|
puts <<-usage
|
|
16
20
|
Usage: cat data.yml template.mustache | mustache
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Runs template.mustache through Mustache, using the data in data.yml to
|
|
22
|
-
replace sections and variables. Useful when developing templates
|
|
23
|
-
before hooking them into your website or whatnot.
|
|
24
|
-
|
|
25
|
-
The data.yml file should start with --- on a single line and end with
|
|
26
|
-
--- on a single line, e.g.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
names: [ {name: chris}, {name: mark}, {name: scott} ]
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
The converted document will be printed on STDOUT.
|
|
22
|
+
See mustache(1) or http://defunkt.github.com/mustache/mustache.1.html
|
|
23
|
+
for an overview.
|
|
33
24
|
usage
|
|
34
25
|
end
|
data/lib/mustache/context.rb
CHANGED
|
@@ -4,30 +4,73 @@ class Mustache
|
|
|
4
4
|
# set to true.
|
|
5
5
|
#
|
|
6
6
|
# For example, if your View class does not respond to `music` but
|
|
7
|
-
# your template contains a `{{
|
|
7
|
+
# your template contains a `{{music}}` tag this exception will be raised.
|
|
8
8
|
#
|
|
9
9
|
# By default it is not raised. See Mustache.raise_on_context_miss.
|
|
10
10
|
class ContextMiss < RuntimeError; end
|
|
11
11
|
|
|
12
12
|
# A Context represents the context which a Mustache template is
|
|
13
13
|
# executed within. All Mustache tags reference keys in the Context.
|
|
14
|
-
class Context
|
|
14
|
+
class Context
|
|
15
|
+
# Expect to be passed an instance of `Mustache`.
|
|
15
16
|
def initialize(mustache)
|
|
16
17
|
@mustache = mustache
|
|
17
|
-
|
|
18
|
+
@stack = [@mustache]
|
|
18
19
|
end
|
|
19
20
|
|
|
21
|
+
# Adds a new object to the context's internal stack.
|
|
22
|
+
#
|
|
23
|
+
# Returns the Context.
|
|
24
|
+
def push(new)
|
|
25
|
+
@stack.unshift(new)
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
alias_method :update, :push
|
|
29
|
+
|
|
30
|
+
# Removes the most recently added object from the context's
|
|
31
|
+
# internal stack.
|
|
32
|
+
#
|
|
33
|
+
# Returns the Context.
|
|
34
|
+
def pop
|
|
35
|
+
@stack.shift
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Can be used to add a value to the context in a hash-like way.
|
|
40
|
+
#
|
|
41
|
+
# context[:name] = "Chris"
|
|
42
|
+
def []=(name, value)
|
|
43
|
+
push(name => value)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Alias for `fetch`.
|
|
20
47
|
def [](name)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
48
|
+
fetch(name, nil)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Similar to Hash#fetch, finds a value by `name` in the context's
|
|
52
|
+
# stack. You may specify the default return value by passing a
|
|
53
|
+
# second parameter.
|
|
54
|
+
#
|
|
55
|
+
# If no second parameter is passed (or raise_on_context_miss is
|
|
56
|
+
# set to true), will raise a ContextMiss exception on miss.
|
|
57
|
+
def fetch(name, default = :__raise)
|
|
58
|
+
@stack.each do |frame|
|
|
59
|
+
hash = frame.respond_to?(:has_key?)
|
|
60
|
+
|
|
61
|
+
if hash && frame.has_key?(name)
|
|
62
|
+
return frame[name]
|
|
63
|
+
elsif hash && frame.has_key?(name.to_s)
|
|
64
|
+
return frame[name.to_s]
|
|
65
|
+
elsif !hash && frame.respond_to?(name)
|
|
66
|
+
return frame.__send__(name)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if default == :__raise || @mustache.raise_on_context_miss?
|
|
71
|
+
raise ContextMiss.new("Can't find #{name} in #{@stack.inspect}")
|
|
29
72
|
else
|
|
30
|
-
|
|
73
|
+
default
|
|
31
74
|
end
|
|
32
75
|
end
|
|
33
76
|
end
|
data/lib/mustache/sinatra.rb
CHANGED
data/lib/mustache/template.rb
CHANGED
|
@@ -76,20 +76,8 @@ class Mustache
|
|
|
76
76
|
ctxtmp = "ctx#{tmpid}"
|
|
77
77
|
res << ev(<<-compiled)
|
|
78
78
|
if v = ctx[#{name}]
|
|
79
|
-
v = [v]
|
|
80
|
-
|
|
81
|
-
#{ctxtmp} = ctx.dup
|
|
82
|
-
begin
|
|
83
|
-
r = v.map { |h| ctx.update(h); #{code} }.join
|
|
84
|
-
rescue TypeError => e
|
|
85
|
-
raise TypeError,
|
|
86
|
-
"All elements in {{#{name.to_s[1..-1]}}} are not hashes!"
|
|
87
|
-
end
|
|
88
|
-
ctx.replace(#{ctxtmp})
|
|
89
|
-
r
|
|
90
|
-
else
|
|
91
|
-
#{code}
|
|
92
|
-
end
|
|
79
|
+
v = [v] unless v.is_a?(Array) # shortcut when passed non-array
|
|
80
|
+
v.map { |h| ctx.push(h); c = #{code}; ctx.pop; c }.join
|
|
93
81
|
end
|
|
94
82
|
compiled
|
|
95
83
|
# $' = The string to the right of the last successful match
|
|
@@ -106,7 +94,7 @@ class Mustache
|
|
|
106
94
|
# 4. Partial tags - {{> partial_name }}
|
|
107
95
|
def compile_tags(src)
|
|
108
96
|
res = ""
|
|
109
|
-
while src =~ /#{otag}(#|=|!|<|>|\{)?(.+?)\1?#{ctag}+/
|
|
97
|
+
while src =~ /#{otag}(#|=|!|<|>|\{)?(.+?)\1?#{ctag}+/m
|
|
110
98
|
res << str($`)
|
|
111
99
|
case $1
|
|
112
100
|
when '#'
|
data/lib/mustache/version.rb
CHANGED