mustache 0.99.5 → 0.99.6
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.
- checksums.yaml +4 -4
- data/README.md +19 -23
- data/Rakefile +1 -1
- data/bin/mustache +30 -12
- data/lib/mustache.rb +4 -11
- data/lib/mustache/blah.rb +116 -0
- data/lib/mustache/context.rb +28 -15
- data/lib/mustache/enumerable.rb +3 -0
- data/lib/mustache/generator.rb +16 -11
- data/lib/mustache/parser.rb +83 -33
- data/lib/mustache/sinatra.rb +1 -1
- data/lib/mustache/template.rb +52 -0
- data/lib/mustache/version.rb +1 -1
- data/man/mustache.1 +4 -4
- data/man/mustache.1.html +6 -6
- data/man/mustache.1.ron +3 -3
- data/man/mustache.5 +8 -8
- data/man/mustache.5.html +11 -9
- data/man/mustache.5.ron +9 -7
- data/test/fixtures/liberal.mustache +1 -0
- data/test/fixtures/liberal.rb +22 -0
- data/test/fixtures/simply_complicated.mustache +25 -0
- data/test/mustache_test.rb +67 -2
- data/test/parser_test.rb +15 -0
- data/test/partial_test.rb +1 -1
- data/test/spec_test.rb +6 -2
- data/test/template_test.rb +33 -0
- metadata +87 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3c1091a71418634c3e493d6b3aae1e5a8f0d0f0
|
4
|
+
data.tar.gz: 87936c1b015243222b2c95c29693106a9ea646a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a422377f6020f923eac84ca194e46b78d05ad611428faa4dede440c090c61e2a30d5d15618286ae72b8ebf486e9aae4b351fee521f5bdc4e13ecc99d1a1677e4
|
7
|
+
data.tar.gz: 30d05bc44030071c322a18ff64235c7bd8da19b03c1cbb4bc68dd3deba33c21d82af75dc435aa2c9845705ea8c7989130aa7626aced0ffb119d6bc18344fa420
|
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://mustache.github.
|
11
|
+
<http://mustache.github.io/>.
|
12
12
|
|
13
13
|
|
14
14
|
Overview
|
@@ -99,16 +99,16 @@ 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://mustache.github.
|
102
|
+
<http://mustache.github.io/mustache.5.html>.
|
103
103
|
|
104
104
|
|
105
105
|
Escaping
|
106
106
|
--------
|
107
107
|
|
108
108
|
Mustache does escape all values when using the standard double
|
109
|
-
Mustache syntax. Characters which will be escaped: `& \ " <
|
110
|
-
disable escaping, simply use triple
|
111
|
-
`{{{unescaped_variable}}}`.
|
109
|
+
Mustache syntax. Characters which will be escaped: `& \ " < >` (as
|
110
|
+
well as `'` in Ruby `>= 2.0`). To disable escaping, simply use triple
|
111
|
+
mustaches like `{{{unescaped_variable}}}`.
|
112
112
|
|
113
113
|
Example: Using `{{variable}}` inside a template for `5 > 2` will
|
114
114
|
result in `5 > 2`, where as the usage of `{{{variable}}}` will
|
@@ -283,16 +283,16 @@ Sinatra
|
|
283
283
|
|
284
284
|
Mustache ships with Sinatra integration. Please see
|
285
285
|
`lib/mustache/sinatra.rb` or
|
286
|
-
<
|
286
|
+
<https://github.com/defunkt/mustache/blob/master/lib/mustache/sinatra.rb>
|
287
287
|
for complete documentation.
|
288
288
|
|
289
289
|
An example Sinatra application is also provided:
|
290
|
-
<
|
290
|
+
<https://github.com/defunkt/mustache-sinatra-example>
|
291
291
|
|
292
292
|
If you are upgrading to Sinatra 1.0 and Mustache 0.9.0+ from Mustache
|
293
293
|
0.7.0 or lower, the settings have changed. But not that much.
|
294
294
|
|
295
|
-
See [this diff](
|
295
|
+
See [this diff](https://gist.github.com/defunkt/345490) for what you need to
|
296
296
|
do. Basically, things are named properly now and all should be
|
297
297
|
contained in a hash set using `set :mustache, hash`.
|
298
298
|
|
@@ -317,11 +317,7 @@ Using Rails? Add this to your initializer or environment file:
|
|
317
317
|
Vim
|
318
318
|
---
|
319
319
|
|
320
|
-
|
321
|
-
is included under the contrib/ directory.
|
322
|
-
|
323
|
-
See <http://gist.github.com/323622> for installation instructions.
|
324
|
-
|
320
|
+
vim-mustache-handlebars is available at https://github.com/mustache/vim-mustache-handlebars
|
325
321
|
|
326
322
|
Emacs
|
327
323
|
-----
|
@@ -332,16 +328,16 @@ mustache-mode.el is available at https://github.com/mustache/emacs
|
|
332
328
|
TextMate
|
333
329
|
--------
|
334
330
|
|
335
|
-
[Mustache.tmbundle](
|
331
|
+
[Mustache.tmbundle](https://github.com/defunkt/Mustache.tmbundle)
|
336
332
|
|
337
|
-
See <
|
333
|
+
See <https://gist.github.com/defunkt/323624> for installation instructions.
|
338
334
|
|
339
335
|
|
340
336
|
Command Line
|
341
337
|
------------
|
342
338
|
|
343
339
|
See `mustache(1)` man page or
|
344
|
-
<http://mustache.github.
|
340
|
+
<http://mustache.github.io/mustache.1.html>
|
345
341
|
for command line docs.
|
346
342
|
|
347
343
|
|
@@ -356,8 +352,8 @@ Installation
|
|
356
352
|
Acknowledgements
|
357
353
|
----------------
|
358
354
|
|
359
|
-
Thanks to [Tom Preston-Werner](
|
360
|
-
me ctemplate and [Leah Culver](
|
355
|
+
Thanks to [Tom Preston-Werner](https://github.com/mojombo) for showing
|
356
|
+
me ctemplate and [Leah Culver](https://github.com/leah) for the name "Mustache."
|
361
357
|
|
362
358
|
Special thanks to [Magnus Holm](http://judofyr.net/) for all his
|
363
359
|
awesome work on Mustache's parser.
|
@@ -391,9 +387,9 @@ The archive can be found at <http://librelist.com/browser/>.
|
|
391
387
|
Meta
|
392
388
|
----
|
393
389
|
|
394
|
-
* Code: `git clone
|
395
|
-
* Home: <http://mustache.github.
|
396
|
-
* Bugs: <
|
390
|
+
* Code: `git clone https://github.com/defunkt/mustache.git`
|
391
|
+
* Home: <http://mustache.github.io>
|
392
|
+
* Bugs: <https://github.com/defunkt/mustache/issues>
|
397
393
|
* List: <mustache@librelist.com>
|
398
394
|
* Gems: <http://rubygems.org/gems/mustache>
|
399
395
|
|
@@ -402,8 +398,8 @@ You can also find us in `#{` on irc.freenode.net.
|
|
402
398
|
[1]: http://code.google.com/p/google-ctemplate/
|
403
399
|
[2]: http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html
|
404
400
|
[3]: http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html
|
405
|
-
[4]:
|
401
|
+
[4]: https://github.com/brynary/rack-bug/
|
406
402
|
[5]: http://img.skitch.com/20091027-n8pxwwx8r61tc318a15q1n6m14.png
|
407
403
|
[cb]: http://wiki.github.com/defunkt/resque/contributing
|
408
404
|
[fk]: http://help.github.com/forking/
|
409
|
-
[is]:
|
405
|
+
[is]: https://github.com/defunkt/mustache/issues
|
data/Rakefile
CHANGED
data/bin/mustache
CHANGED
@@ -64,20 +64,38 @@ class Mustache
|
|
64
64
|
opts.parse!(args)
|
65
65
|
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
doc = input_stream.read
|
67
|
+
def self.yaml_is_array?(yaml)
|
68
|
+
yaml.is_a? Array and yaml.length == 1 and yaml[0].is_a? Array
|
69
|
+
end
|
71
70
|
|
72
|
-
|
73
|
-
yaml
|
74
|
-
|
71
|
+
def self.yaml_is_object?(yaml)
|
72
|
+
yaml.is_a? Array and yaml.length == 1 and yaml[0].is_a? Hash
|
73
|
+
end
|
75
74
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
# Does the dirty work of reading files from the command line then
|
76
|
+
# processing them. The meat of this script, if you will.
|
77
|
+
def self.process_files(input_files)
|
78
|
+
doc = input_files.file.read
|
79
|
+
|
80
|
+
yaml = nil
|
81
|
+
begin
|
82
|
+
yaml = RUBY_VERSION >= '1.9.3' ? YAML.load_stream(doc) : YAML.each_document(doc)
|
83
|
+
rescue
|
84
|
+
puts "Unable to parse yaml!"
|
85
|
+
end
|
86
|
+
|
87
|
+
if yaml.nil?
|
80
88
|
puts Mustache.render(doc)
|
89
|
+
else
|
90
|
+
template = input_files.skip.file.read
|
91
|
+
|
92
|
+
if self.yaml_is_array?(yaml)
|
93
|
+
puts Mustache.render(template, yaml[0].reduce({}) {|hash, currentHash| hash.merge(currentHash)})
|
94
|
+
elsif self.yaml_is_object?(yaml)
|
95
|
+
puts Mustache.render(template, yaml[0])
|
96
|
+
else
|
97
|
+
puts Mustache.render(template, yaml)
|
98
|
+
end
|
81
99
|
end
|
82
100
|
end
|
83
101
|
end
|
@@ -89,6 +107,6 @@ ARGV << '-h' if ARGV.empty? && $stdin.tty?
|
|
89
107
|
# Process options
|
90
108
|
Mustache::CLI.parse_options(ARGV) if $stdin.tty?
|
91
109
|
|
92
|
-
# Still here - process ARGF
|
110
|
+
# Still here - process rest of ARGF
|
93
111
|
Mustache::CLI.process_files(ARGF)
|
94
112
|
|
data/lib/mustache.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'mustache/enumerable'
|
1
2
|
require 'mustache/template'
|
2
3
|
require 'mustache/context'
|
3
4
|
require 'mustache/settings'
|
@@ -202,14 +203,10 @@ class Mustache
|
|
202
203
|
# Mustache.view_namespace = Hurl::Views
|
203
204
|
# Mustache.view_class(:Partial) # => Hurl::Views::Partial
|
204
205
|
def self.view_class(name)
|
205
|
-
|
206
|
-
name = classify(name.to_s)
|
207
|
-
end
|
206
|
+
name = classify(name.to_s)
|
208
207
|
|
209
208
|
# Emptiness begets emptiness.
|
210
|
-
if name.to_s == ''
|
211
|
-
return Mustache
|
212
|
-
end
|
209
|
+
return Mustache if name.to_s == ''
|
213
210
|
|
214
211
|
file_name = underscore(name)
|
215
212
|
name = "#{view_namespace}::#{name}"
|
@@ -280,11 +277,7 @@ class Mustache
|
|
280
277
|
# Turns a string into a Mustache::Template. If passed a Template,
|
281
278
|
# returns it.
|
282
279
|
def self.templateify(obj)
|
283
|
-
|
284
|
-
obj
|
285
|
-
else
|
286
|
-
Template.new(obj.to_s)
|
287
|
-
end
|
280
|
+
obj.is_a?(Template) ? obj : Template.new(obj.to_s)
|
288
281
|
end
|
289
282
|
|
290
283
|
def templateify(obj)
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'mustache'
|
2
|
+
|
3
|
+
class Mustache::Template
|
4
|
+
def token_names
|
5
|
+
def recursor(toks, section)
|
6
|
+
toks.map do |token|
|
7
|
+
next unless token.is_a? Array
|
8
|
+
if token[0] == :mustache && [:etag,:utag].include? token[1]
|
9
|
+
(section + [token[2][2][0]]).join '.'
|
10
|
+
elsif token[0] == :mustache && [:section,:inverted_section].include? token[1]
|
11
|
+
recursor(token[4], section + [token[2][2][0]])
|
12
|
+
else
|
13
|
+
recursor(token, section)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
recursor(tokens, []).flatten.reject(&:nil?).uniq
|
18
|
+
end
|
19
|
+
|
20
|
+
def section_names
|
21
|
+
def recursor(toks, section)
|
22
|
+
sections = []
|
23
|
+
toks.each do |token|
|
24
|
+
next unless token.is_a? Array
|
25
|
+
if token[0] == :mustache && [:section,:inverted_section].include? token[1]
|
26
|
+
new_section = section + [token[2][2][0]]
|
27
|
+
sections += [ new_section.join('.') ] + recursor(token[4], new_section)
|
28
|
+
else
|
29
|
+
sections += recursor(token, section)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
sections
|
33
|
+
end
|
34
|
+
recursor(tokens,[]).reject(&:nil?).uniq
|
35
|
+
end
|
36
|
+
|
37
|
+
def partial_names
|
38
|
+
def recursor(toks)
|
39
|
+
partials = []
|
40
|
+
toks.each do |token|
|
41
|
+
next unless token.is_a? Array
|
42
|
+
partials += if token[0..1] == [:mustache, :partial]
|
43
|
+
[token[2]] # partial here
|
44
|
+
else
|
45
|
+
recursor(token)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
partials
|
49
|
+
end
|
50
|
+
recursor(tokens).reject(&:nil?).uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
if __FILE__ == $0
|
56
|
+
require "test/unit"
|
57
|
+
|
58
|
+
class TestMustacheTokenNames < Test::Unit::TestCase
|
59
|
+
|
60
|
+
def setup
|
61
|
+
@template = Mustache::Template.new(@@template_text ||= DATA.read)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_token_names
|
65
|
+
assert_equal(@template.token_names,
|
66
|
+
[ "yourname",
|
67
|
+
"HOME",
|
68
|
+
"friend.name",
|
69
|
+
"friend.morr.word",
|
70
|
+
"friend.morr.up",
|
71
|
+
"friend.morr.awesomesauce",
|
72
|
+
"friend.morr.hiss",
|
73
|
+
"friend.notinmorr",
|
74
|
+
"friend.person",
|
75
|
+
"love",
|
76
|
+
"triplestash"
|
77
|
+
]
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_partial_names
|
82
|
+
assert_equal(@template.partial_names, ["partial1", "partial2"])
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_section_names
|
86
|
+
assert_equal(@template.section_names, ["friend", "friend.morr"])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
__END__
|
92
|
+
Hi there {{yourname}}. Your home directory is {{HOME}}.
|
93
|
+
|
94
|
+
{{#friend}}
|
95
|
+
Your friend is named {{name}}
|
96
|
+
{{#morr}}
|
97
|
+
Hey {{word}} {{up}} {{{awesomesauce}}}.
|
98
|
+
{{/morr}}
|
99
|
+
{{^morr}}
|
100
|
+
Booooo. {{hiss}}
|
101
|
+
{{/morr}}
|
102
|
+
{{notinmorr}}
|
103
|
+
{{> partial1}}
|
104
|
+
{{/friend}}
|
105
|
+
{{^friend}}
|
106
|
+
You have no friends, {{person}}. You suck.
|
107
|
+
{{/friend}}
|
108
|
+
|
109
|
+
{{> partial2}}
|
110
|
+
{{! comments are awesome }}
|
111
|
+
|
112
|
+
{{={% %}=}}
|
113
|
+
|
114
|
+
{%love%}
|
115
|
+
{%={{ }}=%}
|
116
|
+
{{{triplestash}}}
|
data/lib/mustache/context.rb
CHANGED
@@ -31,7 +31,7 @@ class Mustache
|
|
31
31
|
part = mustache.partial(name).to_s.gsub(/^/, indentation)
|
32
32
|
|
33
33
|
# Call the Mustache's `partial` method and render the result.
|
34
|
-
|
34
|
+
mustache.render(part, self)
|
35
35
|
end
|
36
36
|
|
37
37
|
# Find the first Mustache in the stack. If we're being rendered
|
@@ -80,7 +80,7 @@ class Mustache
|
|
80
80
|
# Do we know about a particular key? In other words, will calling
|
81
81
|
# `context[key]` give us a result that was set. Basically.
|
82
82
|
def has_key?(key)
|
83
|
-
!!fetch(key)
|
83
|
+
!!fetch(key, false)
|
84
84
|
rescue ContextMiss
|
85
85
|
false
|
86
86
|
end
|
@@ -97,9 +97,7 @@ class Mustache
|
|
97
97
|
next if frame == self
|
98
98
|
|
99
99
|
value = find(frame, name, :__missing)
|
100
|
-
if value != :__missing
|
101
|
-
return value
|
102
|
-
end
|
100
|
+
return value if value != :__missing
|
103
101
|
end
|
104
102
|
|
105
103
|
if default == :__raise || mustache_in_stack.raise_on_context_miss?
|
@@ -121,22 +119,37 @@ class Mustache
|
|
121
119
|
#
|
122
120
|
# Returns the value of key in obj if it is found and default otherwise.
|
123
121
|
def find(obj, key, default = nil)
|
124
|
-
hash = obj.respond_to?(:
|
122
|
+
hash = obj.respond_to?(:to_hash)
|
123
|
+
|
124
|
+
if !hash
|
125
|
+
# If a class, we need to find tags (methods) per Parser::ALLOWED_CONTENT.
|
126
|
+
if key.to_s.include?('-')
|
127
|
+
key = key.to_s.gsub('-', '_')
|
128
|
+
end
|
125
129
|
|
126
|
-
|
130
|
+
if obj.respond_to?(key)
|
131
|
+
meth = obj.method(key) rescue proc { obj.send(key) }
|
132
|
+
if meth.arity == 1
|
133
|
+
meth.to_proc
|
134
|
+
else
|
135
|
+
meth[]
|
136
|
+
end
|
137
|
+
else
|
138
|
+
default
|
139
|
+
end
|
140
|
+
elsif hash && obj.has_key?(key)
|
127
141
|
obj[key]
|
128
142
|
elsif hash && obj.has_key?(key.to_s)
|
129
143
|
obj[key.to_s]
|
130
|
-
elsif !hash && obj.respond_to?(key)
|
131
|
-
meth = obj.method(key) rescue proc { obj.send(key) }
|
132
|
-
if meth.arity == 1
|
133
|
-
meth.to_proc
|
134
|
-
else
|
135
|
-
meth[]
|
136
|
-
end
|
137
144
|
else
|
138
|
-
default
|
145
|
+
obj[key] || default
|
139
146
|
end
|
140
147
|
end
|
141
148
|
end
|
142
149
|
end
|
150
|
+
|
151
|
+
class Hash
|
152
|
+
def to_hash
|
153
|
+
self
|
154
|
+
end unless method_defined?(:to_hash)
|
155
|
+
end
|
data/lib/mustache/generator.rb
CHANGED
@@ -64,17 +64,22 @@ class Mustache
|
|
64
64
|
#
|
65
65
|
# [:multi,
|
66
66
|
# [:static, "Hello "],
|
67
|
-
# [:mustache, :etag,
|
67
|
+
# [:mustache, :etag,
|
68
|
+
# [:mustache, :fetch, ["name"]]],
|
68
69
|
# [:static, "\nYou have just won $"],
|
69
|
-
#
|
70
|
-
# [:
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
70
|
+
# [:mustache, :etag,
|
71
|
+
# [:mustache, :fetch, ["value"]]],
|
72
|
+
# [:static, "!\n"],
|
73
|
+
# [:mustache,
|
74
|
+
# :section,
|
75
|
+
# [:mustache, :fetch, ["in_ca"]],
|
76
|
+
# [:multi,
|
77
|
+
# [:static, "Well, $"],
|
78
|
+
# [:mustache, :etag,
|
79
|
+
# [:mustache, :fetch, ["taxed_value"]]],
|
80
|
+
# [:static, ", after taxes.\n"]],
|
81
|
+
# "Well, ${{taxed_value}}, after taxes.\n",
|
82
|
+
# ["{{", "}}"]]]
|
78
83
|
def compile!(exp)
|
79
84
|
case exp.first
|
80
85
|
when :multi
|
@@ -111,7 +116,7 @@ class Mustache
|
|
111
116
|
t.render(ctx.dup)
|
112
117
|
else
|
113
118
|
# Shortcut when passed non-array
|
114
|
-
v = [v] unless v.is_a?(Array) || defined?(Enumerator) && v.is_a?(Enumerator)
|
119
|
+
v = [v] unless v.is_a?(Array) || v.is_a?(Mustache::Enumerable) || defined?(Enumerator) && v.is_a?(Enumerator)
|
115
120
|
|
116
121
|
v.map { |h| ctx.push(h); r = #{code}; ctx.pop; r }.join
|
117
122
|
end
|