mustache 0.4.2 → 0.5.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.
@@ -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