mustache 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,3 +3,4 @@
3
3
  * Magnus Holm
4
4
  * Nicolas Sanguinetti
5
5
  * Jan-Erik Rediger
6
+ * Aaron Patterson
data/HISTORY.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.5.0 (2009-11-23)
2
+
3
+ * Partial classes are no longer supported. Use modules!
4
+ * Added `mustache` script for rendering templates on the command line.
5
+ * ctemplate compat: Partials are indicated by >, not <
6
+ * Bugfix: Context miss should return nil, not empty string. Fixes 1.9.x
7
+
1
8
  ## 0.4.2 (2009-10-28)
2
9
 
3
10
  * Bugfix: Ignore bad constant names when autoloading
data/README.md CHANGED
@@ -176,13 +176,32 @@ Will render as follows:
176
176
 
177
177
  ### Partials
178
178
 
179
- Partials begin with a less than sign, like `{{< box}}`.
179
+ Partials begin with a greater than sign, like `{{> box}}`.
180
180
 
181
- If a partial's view is loaded, we use that to render the HTML. If
182
- nothing is loaded we render the template directly using our current context.
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.
183
184
 
184
- In this way partials can reference variables or sections the calling
185
- view defines.
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.
186
205
 
187
206
 
188
207
  ### Set Delimiter
@@ -376,7 +395,7 @@ An example Sinatra application is also provided:
376
395
 
377
396
 
378
397
  [Rack::Bug][4]
379
- ---------
398
+ --------------
380
399
 
381
400
  Mustache also ships with a `Rack::Bug` panel. In your `config.ru` add
382
401
  the following code:
@@ -400,13 +419,63 @@ is included under the contrib/ directory.
400
419
 
401
420
 
402
421
  Emacs
403
- ----
422
+ -----
404
423
 
405
424
  tpl-mode.el is included under the contrib/ directory for any Emacs users.
406
425
  Based on Google's tpl-mode for ctemplates, it adds support for Mustache's
407
426
  more lenient tag values and includes a few commands for your editing pleasure.
408
427
 
409
428
 
429
+ TextMate
430
+ --------
431
+
432
+ Check out Tekkub's
433
+ [Mustache.tmbundle](http://github.com/tekkub/Mustache.tmbundle).
434
+
435
+
436
+ Command Line
437
+ ------------
438
+
439
+ Mustache includes a `mustache` script for rendering templates on the
440
+ command line. This can be useful when designing HTML that will
441
+ eventually be included in a website: instead of having to format the
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
+
478
+
410
479
  Installation
411
480
  ------------
412
481
 
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ task :gem => [ :gemspec, :build ]
15
15
  desc "Launch Kicker (like autotest)"
16
16
  task :kicker do
17
17
  puts "Kicking... (ctrl+c to cancel)"
18
- exec "kicker -e rake test lib"
18
+ exec "kicker -e rake test lib examples"
19
19
  end
20
20
 
21
21
  begin
@@ -46,6 +46,7 @@ desc "Push a new version to Gemcutter"
46
46
  task :publish => [ :test, :gemspec, :build ] do
47
47
  system "git tag v#{Mustache::Version}"
48
48
  system "git push origin v#{Mustache::Version}"
49
+ system "git push origin master"
49
50
  system "gem push pkg/mustache-#{Mustache::Version}.gem"
50
51
  system "git clean -fd"
51
52
  exec "rake pages"
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mustache'
4
+ require 'yaml'
5
+
6
+ if STDIN.stat.size > 0
7
+ doc = STDIN.read
8
+ if doc =~ /^(\s*---(.*)---\s*)/m
9
+ data = YAML.load($2.strip)
10
+ puts Mustache.render(doc.sub($1, ''), data)
11
+ else
12
+ puts doc
13
+ end
14
+ else
15
+ puts <<-usage
16
+ Usage: cat data.yml template.mustache | mustache
17
+
18
+ Expects a single Mustache template on STDIN complete with YAML
19
+ frontmatter.
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.
33
+ usage
34
+ end
@@ -11,14 +11,11 @@ module TestViews
11
11
  end
12
12
 
13
13
  class NamespacedWithPartial < Mustache
14
- self.template = "My opinion: {{<MyPartial}}"
15
- end
16
-
17
- class MyPartial < Mustache
18
- self.template = "{{exclamation}}!"
14
+ self.path = File.dirname(__FILE__)
15
+ self.template = "My opinion: {{>inner_partial}}"
19
16
 
20
- def exclamation
21
- :Victory
17
+ def title
18
+ "Victory"
22
19
  end
23
20
  end
24
21
  end
@@ -0,0 +1,3 @@
1
+ <h1>{{greeting}}</h1>
2
+ {{>simple}}
3
+ <h3>{{farewell}}</h3>
@@ -0,0 +1,37 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ module SimpleView
5
+ def name
6
+ "Bob"
7
+ end
8
+
9
+ def value
10
+ 100_000
11
+ end
12
+
13
+ def taxed_value
14
+ value - (value * 0.4)
15
+ end
16
+
17
+ def in_ca
18
+ false
19
+ end
20
+ end
21
+
22
+ class PartialWithModule < Mustache
23
+ include SimpleView
24
+ self.path = File.dirname(__FILE__)
25
+
26
+ def greeting
27
+ "Welcome"
28
+ end
29
+
30
+ def farewell
31
+ "Fair enough, right?"
32
+ end
33
+ end
34
+
35
+ if $0 == __FILE__
36
+ puts PartialWithModule.to_html
37
+ end
@@ -1,2 +1,2 @@
1
1
  <h1>{{title}}</h1>
2
- {{<inner_partial}}
2
+ {{>inner_partial}}
@@ -1,4 +1,4 @@
1
1
  {{title}}
2
2
  {{title_bars}}
3
3
 
4
- {{<inner_partial}}
4
+ {{>inner_partial}}
@@ -27,7 +27,7 @@ class Mustache
27
27
  elsif @mustache.raise_on_context_miss?
28
28
  raise ContextMiss.new("Can't find #{name} in #{@mustache.inspect}")
29
29
  else
30
- ''
30
+ nil
31
31
  end
32
32
  end
33
33
  end
@@ -103,10 +103,10 @@ class Mustache
103
103
  # 1. Escaped variable tags - {{var}}
104
104
  # 2. Unescaped variable tags - {{{var}}}
105
105
  # 3. Comment variable tags - {{! comment}
106
- # 4. Partial tags - {{< partial_name }}
106
+ # 4. Partial tags - {{> partial_name }}
107
107
  def compile_tags(src)
108
108
  res = ""
109
- while src =~ /#{otag}(#|=|!|<|\{)?(.+?)\1?#{ctag}+/
109
+ while src =~ /#{otag}(#|=|!|<|>|\{)?(.+?)\1?#{ctag}+/
110
110
  res << str($`)
111
111
  case $1
112
112
  when '#'
@@ -117,7 +117,7 @@ class Mustache
117
117
  # ignore comments
118
118
  when '='
119
119
  self.otag, self.ctag = $2.strip.split(' ', 2)
120
- when '<'
120
+ when '>', '<'
121
121
  res << compile_partial($2.strip)
122
122
  when '{'
123
123
  res << utag($2.strip)
@@ -131,13 +131,8 @@ class Mustache
131
131
 
132
132
  # Partials are basically a way to render views from inside other views.
133
133
  def compile_partial(name)
134
- klass = Mustache.view_class(name)
135
- if klass != Mustache
136
- ev("#{klass}.render")
137
- else
138
- src = File.read("#{@template_path}/#{name}.#{@template_extension}")
139
- compile(src)[1..-2]
140
- end
134
+ src = File.read("#{@template_path}/#{name}.#{@template_extension}")
135
+ compile(src)[1..-2]
141
136
  end
142
137
 
143
138
  # Generate a temporary id, used when compiling code.
@@ -1,3 +1,3 @@
1
1
  class Mustache
2
- Version = '0.4.2'
2
+ Version = '0.5.0'
3
3
  end
@@ -1,4 +1,5 @@
1
- require 'test/unit'
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+ require 'helper'
2
3
 
3
4
  module TestViews; end
4
5
 
@@ -41,7 +42,7 @@ end_render
41
42
  klass = Mustache.view_class(:namespaced_with_partial)
42
43
  assert_equal TestViews::NamespacedWithPartial, klass
43
44
  assert_equal <<-end_render.strip, klass.render
44
- My opinion: Victory!
45
+ My opinion: Again, Victory!
45
46
  end_render
46
47
  end
47
48
 
@@ -0,0 +1,13 @@
1
+ require 'test/unit'
2
+
3
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../examples'
4
+ require 'simple'
5
+ require 'complex_view'
6
+ require 'partial_with_module'
7
+ require 'template_partial'
8
+ require 'escaped'
9
+ require 'unescaped'
10
+ require 'comments'
11
+ require 'passenger'
12
+ require 'delimiters'
13
+ require 'double_section'
@@ -1,16 +1,5 @@
1
- require 'test/unit'
2
-
3
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../examples'
4
- require 'simple'
5
- require 'complex_view'
6
- require 'view_partial'
7
- require 'template_partial'
8
- require 'escaped'
9
- require 'unescaped'
10
- require 'comments'
11
- require 'passenger'
12
- require 'delimiters'
13
- require 'double_section'
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+ require 'helper'
14
3
 
15
4
  class MustacheTest < Test::Unit::TestCase
16
5
  def test_passenger
@@ -113,46 +102,15 @@ end_simple
113
102
  assert_equal 'Hi mom!', view.render
114
103
  end
115
104
 
116
- def test_view_partial
117
- assert_equal <<-end_partial.strip, ViewPartial.render
118
- <h1>Welcome</h1>
119
- Hello Chris
120
- You have just won $10000!
121
- Well, $6000.0, after taxes.
122
-
123
- <h3>Fair enough, right?</h3>
124
- end_partial
125
- end
126
-
127
- def test_template_partial
128
- assert_equal <<-end_partial.strip, TemplatePartial.render
129
- <h1>Welcome</h1>
130
- Again, Welcome!
131
- end_partial
132
- end
133
-
134
- def test_template_partial_with_custom_extension
135
- partial = Class.new(TemplatePartial)
136
- partial.template_extension = 'txt'
137
- partial.template_path = File.dirname(__FILE__) + '/../examples'
138
-
139
- assert_equal <<-end_partial.strip, partial.render.strip
140
- Welcome
141
- -------
142
-
143
- ## Again, Welcome! ##
144
- end_partial
145
- end
146
-
147
105
  def test_delimiters
148
- assert_equal <<-end_partial, Delimiters.render
106
+ assert_equal <<-end_template, Delimiters.render
149
107
 
150
108
  * It worked the first time.
151
109
 
152
110
  * And it worked the second time.
153
111
 
154
112
  * Then, surprisingly, it worked the third time.
155
- end_partial
113
+ end_template
156
114
  end
157
115
 
158
116
  def test_double_section
@@ -0,0 +1,80 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+ require 'helper'
3
+
4
+ class PartialTest < Test::Unit::TestCase
5
+ def test_view_partial
6
+ assert_equal <<-end_partial.strip, PartialWithModule.render
7
+ <h1>Welcome</h1>
8
+ Hello Bob
9
+ You have just won $100000!
10
+
11
+ <h3>Fair enough, right?</h3>
12
+ end_partial
13
+ end
14
+
15
+ def test_view_partial_inherits_context
16
+ klass = Class.new(TemplatePartial)
17
+ klass.template_path = File.dirname(__FILE__) + '/../examples'
18
+ view = klass.new
19
+ view[:titles] = [{:title => :One}, {:title => :Two}]
20
+ view.template = <<-end_template
21
+ <h1>Context Test</h1>
22
+ <ul>
23
+ {{#titles}}
24
+ <li>{{>inner_partial}}</li>
25
+ {{/titles}}
26
+ </ul>
27
+ end_template
28
+ assert_equal <<-end_partial, view.render
29
+ <h1>Context Test</h1>
30
+ <ul>
31
+ <li>Again, One!</li>
32
+ <li>Again, Two!</li>
33
+ </ul>
34
+ end_partial
35
+ end
36
+
37
+ def test_view_partial_inherits_context_of_class_methods
38
+ klass = Class.new(TemplatePartial)
39
+ klass.template_path = File.dirname(__FILE__) + '/../examples'
40
+ klass.send(:define_method, :titles) do
41
+ [{:title => :One}, {:title => :Two}]
42
+ end
43
+ view = klass.new
44
+ view.template = <<-end_template
45
+ <h1>Context Test</h1>
46
+ <ul>
47
+ {{#titles}}
48
+ <li>{{>inner_partial}}</li>
49
+ {{/titles}}
50
+ </ul>
51
+ end_template
52
+ assert_equal <<-end_partial, view.render
53
+ <h1>Context Test</h1>
54
+ <ul>
55
+ <li>Again, One!</li>
56
+ <li>Again, Two!</li>
57
+ </ul>
58
+ end_partial
59
+ end
60
+
61
+ def test_template_partial
62
+ assert_equal <<-end_partial.strip, TemplatePartial.render
63
+ <h1>Welcome</h1>
64
+ Again, Welcome!
65
+ end_partial
66
+ end
67
+
68
+ def test_template_partial_with_custom_extension
69
+ partial = Class.new(TemplatePartial)
70
+ partial.template_extension = 'txt'
71
+ partial.template_path = File.dirname(__FILE__) + '/../examples'
72
+
73
+ assert_equal <<-end_partial.strip, partial.render.strip
74
+ Welcome
75
+ -------
76
+
77
+ ## Again, Welcome! ##
78
+ end_partial
79
+ end
80
+ 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.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -9,14 +9,14 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-28 00:00:00 -07:00
13
- default_executable:
12
+ date: 2009-11-23 00:00:00 -08:00
13
+ default_executable: mustache
14
14
  dependencies: []
15
15
 
16
16
  description: Mustache is a framework-agnostic way to render logic-free views.
17
17
  email: chris@ozmm.org
18
- executables: []
19
-
18
+ executables:
19
+ - mustache
20
20
  extensions: []
21
21
 
22
22
  extra_rdoc_files:
@@ -35,6 +35,7 @@ files:
35
35
  - benchmarks/helper.rb
36
36
  - benchmarks/simple.erb
37
37
  - benchmarks/speed.rb
38
+ - bin/mustache
38
39
  - contrib/mustache.vim
39
40
  - contrib/tpl-mode.el
40
41
  - examples/comments.mustache
@@ -51,6 +52,8 @@ files:
51
52
  - examples/inner_partial.txt
52
53
  - examples/namespaced.mustache
53
54
  - examples/namespaced.rb
55
+ - examples/partial_with_module.mustache
56
+ - examples/partial_with_module.rb
54
57
  - examples/passenger.conf
55
58
  - examples/passenger.rb
56
59
  - examples/simple.mustache
@@ -60,8 +63,6 @@ files:
60
63
  - examples/template_partial.txt
61
64
  - examples/unescaped.mustache
62
65
  - examples/unescaped.rb
63
- - examples/view_partial.mustache
64
- - examples/view_partial.rb
65
66
  - lib/mustache.rb
66
67
  - lib/mustache/context.rb
67
68
  - lib/mustache/sinatra.rb
@@ -71,7 +72,9 @@ files:
71
72
  - lib/rack/bug/panels/mustache_panel/mustache_extension.rb
72
73
  - lib/rack/bug/panels/mustache_panel/view.mustache
73
74
  - test/autoloading_test.rb
75
+ - test/helper.rb
74
76
  - test/mustache_test.rb
77
+ - test/partial_test.rb
75
78
  has_rdoc: true
76
79
  homepage: http://github.com/defunkt/mustache
77
80
  licenses: []
@@ -102,15 +105,17 @@ specification_version: 3
102
105
  summary: Mustache is a framework-agnostic way to render logic-free views.
103
106
  test_files:
104
107
  - test/autoloading_test.rb
108
+ - test/helper.rb
105
109
  - test/mustache_test.rb
110
+ - test/partial_test.rb
106
111
  - examples/comments.rb
107
112
  - examples/complex_view.rb
108
113
  - examples/delimiters.rb
109
114
  - examples/double_section.rb
110
115
  - examples/escaped.rb
111
116
  - examples/namespaced.rb
117
+ - examples/partial_with_module.rb
112
118
  - examples/passenger.rb
113
119
  - examples/simple.rb
114
120
  - examples/template_partial.rb
115
121
  - examples/unescaped.rb
116
- - examples/view_partial.rb
@@ -1,3 +0,0 @@
1
- <h1>{{greeting}}</h1>
2
- {{<simple}}
3
- <h3>{{farewell}}</h3>
@@ -1,18 +0,0 @@
1
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
- require 'mustache'
3
-
4
- class ViewPartial < Mustache
5
- self.path = File.dirname(__FILE__)
6
-
7
- def greeting
8
- "Welcome"
9
- end
10
-
11
- def farewell
12
- "Fair enough, right?"
13
- end
14
- end
15
-
16
- if $0 == __FILE__
17
- puts ViewPartial.to_html
18
- end