mustache 0.99.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +53 -67
  3. data/Rakefile +4 -12
  4. data/lib/mustache.rb +67 -73
  5. data/lib/mustache/context.rb +57 -48
  6. data/lib/mustache/context_miss.rb +14 -0
  7. data/lib/mustache/generator.rb +5 -1
  8. data/lib/mustache/parser.rb +39 -14
  9. data/lib/mustache/settings.rb +1 -2
  10. data/lib/mustache/template.rb +37 -18
  11. data/lib/mustache/version.rb +1 -1
  12. data/test/autoloading_test.rb +2 -3
  13. data/test/fixtures/comments.rb +0 -1
  14. data/test/fixtures/complex_view.rb +0 -1
  15. data/test/fixtures/crazy_recursive.rb +0 -1
  16. data/test/fixtures/delimiters.rb +0 -1
  17. data/test/fixtures/dot_notation.rb +0 -1
  18. data/test/fixtures/double_section.rb +0 -1
  19. data/test/fixtures/inverted_section.rb +0 -1
  20. data/test/fixtures/lambda.rb +0 -1
  21. data/test/fixtures/liberal.rb +0 -1
  22. data/test/fixtures/method_missing.rb +0 -1
  23. data/test/fixtures/namespaced.rb +0 -1
  24. data/test/fixtures/nested_objects.rb +0 -1
  25. data/test/fixtures/partial_with_module.rb +0 -1
  26. data/test/fixtures/passenger.rb +0 -1
  27. data/test/fixtures/recursive.rb +0 -1
  28. data/test/fixtures/simple.rb +0 -1
  29. data/test/fixtures/template_partial.rb +0 -1
  30. data/test/fixtures/unescaped.rb +0 -1
  31. data/test/helper.rb +3 -2
  32. data/test/mustache_test.rb +13 -13
  33. data/test/parser_test.rb +2 -3
  34. data/test/partial_test.rb +2 -3
  35. data/test/spec_test.rb +2 -2
  36. data/test/template_test.rb +3 -4
  37. metadata +17 -19
  38. data/lib/mustache/sinatra.rb +0 -205
  39. data/lib/rack/bug/panels/mustache_panel.rb +0 -81
  40. data/lib/rack/bug/panels/mustache_panel/mustache_extension.rb +0 -27
  41. data/lib/rack/bug/panels/mustache_panel/view.mustache +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d833a2b9076086446f4ee505f0b05cd069028a99
4
- data.tar.gz: 911b43c7a69bf4694d0198945bfb9ca2005acb7c
3
+ metadata.gz: a9a22c993556413f34a18b5f74023dbf1dfbdd92
4
+ data.tar.gz: 28b5ac5ef50228c3bc860762c6a70e546022dd3d
5
5
  SHA512:
6
- metadata.gz: e8bc8262ef5e651d643116de6038312ccfc35880e02bfbc3e9a93f3c0c37d0de59991e32533dfc8f87fac9a95ea24306bc5f57130f6f5ceae4c1cba67f334331
7
- data.tar.gz: c55226cd631a7d314e16cc2fc39424458f17f4cc77c65004256d28589cdf8866a5841b4640702c7924efccd2de3f32518ee11cb4a314dd447f4c0fa474d794c1
6
+ metadata.gz: 0dcaecf69cf26d4a540f5e47d862b5bb318114e74f9885a03f180c510ed5fcff53d91ba56d8a97bd6b45fa8e1272c761230f9fb71c76fca8dd3332a0e1a8e900
7
+ data.tar.gz: b1bb13fd0e318e55aa037616b86629a00fa3a2b54b350b93d4df738d9de816e9e145804da3519c145c49c2db142a5ff748b24c661d7133565da0ad3683d4c946
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
- Mustache
2
- =========
1
+ # Mustache
3
2
 
4
3
  Inspired by [ctemplate][1] and [et][2], Mustache is a
5
4
  framework-agnostic way to render logic-free views.
@@ -11,8 +10,7 @@ For a list of implementations (other than Ruby) and tips, see
11
10
  <http://mustache.github.io/>.
12
11
 
13
12
 
14
- Overview
15
- --------
13
+ ## Overview
16
14
 
17
15
  Think of Mustache as a replacement for your views. Instead of views
18
16
  consisting of ERB or HAML with random helpers and arbitrary logic,
@@ -30,8 +28,7 @@ This strict separation makes it easier to write clean templates,
30
28
  easier to test your views, and more fun to work on your app's front end.
31
29
 
32
30
 
33
- Why?
34
- ----
31
+ ## Why?
35
32
 
36
33
  I like writing Ruby. I like writing HTML. I like writing JavaScript.
37
34
 
@@ -39,8 +36,18 @@ I don't like writing ERB, Haml, Liquid, Django Templates, putting Ruby
39
36
  in my HTML, or putting JavaScript in my HTML.
40
37
 
41
38
 
42
- Usage
43
- -----
39
+ ## Installation
40
+
41
+ Install the gem locally with:
42
+
43
+ $ gem install mustache
44
+
45
+ Or add it to your `gemspec`:
46
+
47
+ s.add_dependency "mustache", "~> 1.0"
48
+
49
+
50
+ ## Usage
44
51
 
45
52
  Quick example:
46
53
 
@@ -94,16 +101,14 @@ Which returns the following:
94
101
  Simple.
95
102
 
96
103
 
97
- Tag Types
98
- ---------
104
+ ## Tag Types
99
105
 
100
106
  For a language-agnostic overview of Mustache's template syntax, see
101
107
  the `mustache(5)` manpage or
102
108
  <http://mustache.github.io/mustache.5.html>.
103
109
 
104
110
 
105
- Escaping
106
- --------
111
+ ## Escaping
107
112
 
108
113
  Mustache does escape all values when using the standard double
109
114
  Mustache syntax. Characters which will be escaped: `& \ " < >` (as
@@ -115,8 +120,7 @@ result in `5 &gt; 2`, where as the usage of `{{{variable}}}` will
115
120
  result in `5 > 2`.
116
121
 
117
122
 
118
- Dict-Style Views
119
- ----------------
123
+ ## Dict-Style Views
120
124
 
121
125
  ctemplate and friends want you to hand a dictionary to the template
122
126
  processor. Mustache supports a similar concept. Feel free to mix the
@@ -147,8 +151,7 @@ We can re-use the same object, too:
147
151
  You have just won 100 bucks!
148
152
 
149
153
 
150
- Templates
151
- ---------
154
+ ## Templates
152
155
 
153
156
  A word on templates. By default, a view will try to find its template
154
157
  on disk by searching for an HTML file in the current directory that
@@ -190,8 +193,7 @@ Or set a different template for a single instance:
190
193
  Whatever works.
191
194
 
192
195
 
193
- Views
194
- -----
196
+ ## Views
195
197
 
196
198
  Mustache supports a bit of magic when it comes to views. If you're
197
199
  authoring a plugin or extension for a web framework (Sinatra, Rails,
@@ -199,8 +201,7 @@ etc), check out the `view_namespace` and `view_path` settings on the
199
201
  `Mustache` class. They will surely provide needed assistance.
200
202
 
201
203
 
202
- Helpers
203
- -------
204
+ ## Helpers
204
205
 
205
206
  What about global helpers? Maybe you have a nifty `gravatar` function
206
207
  you want to use in all your views? No problem.
@@ -278,12 +279,13 @@ Finally, our template might look like this:
278
279
  </ul>
279
280
 
280
281
 
281
- Sinatra
282
- -------
282
+ ## Integrations
283
+
284
+ ### Sinatra
283
285
 
284
- Mustache ships with Sinatra integration. Please see
286
+ Mustache provides Sinatra integration. Please see
285
287
  `lib/mustache/sinatra.rb` or
286
- <https://github.com/defunkt/mustache/blob/master/lib/mustache/sinatra.rb>
288
+ <https://github.com/mustache/mustache/blob/master/lib/mustache/sinatra.rb>
287
289
  for complete documentation.
288
290
 
289
291
  An example Sinatra application is also provided:
@@ -292,16 +294,15 @@ An example Sinatra application is also provided:
292
294
  If you are upgrading to Sinatra 1.0 and Mustache 0.9.0+ from Mustache
293
295
  0.7.0 or lower, the settings have changed. But not that much.
294
296
 
295
- See [this diff](https://gist.github.com/defunkt/345490) for what you need to
297
+ See [this diff][diff] for what you need to
296
298
  do. Basically, things are named properly now and all should be
297
299
  contained in a hash set using `set :mustache, hash`.
298
300
 
299
301
 
300
- [Rack::Bug][4]
301
- --------------
302
+ ### [Rack::Bug][4]
302
303
 
303
- Mustache also ships with a `Rack::Bug` panel. In your `config.ru` add
304
- the following code:
304
+ Mustache also provides a `Rack::Bug` panel.
305
+ First you have to install the `rack-bug-mustache_panel` gem, then in your `config.ru` add the following code:
305
306
 
306
307
  require 'rack/bug/panels/mustache_panel'
307
308
  use Rack::Bug::MustachePanel
@@ -311,46 +312,32 @@ Using Rails? Add this to your initializer or environment file:
311
312
  require 'rack/bug/panels/mustache_panel'
312
313
  config.middleware.use "Rack::Bug::MustachePanel"
313
314
 
314
- [![Rack::Bug](http://img.skitch.com/20091027-xyf4h1yxnefpp7usyddrcmc7dn.png)][5]
315
+ ![Rack::Bug][5]
315
316
 
316
317
 
317
- Vim
318
- ---
318
+ ### Vim
319
319
 
320
- vim-mustache-handlebars is available at https://github.com/mustache/vim-mustache-handlebars
320
+ vim-mustache-handlebars is available at [mustache/vim-mustache-handlebars][vim]
321
321
 
322
- Emacs
323
- -----
322
+ ### Emacs
324
323
 
325
- mustache-mode.el is available at https://github.com/mustache/emacs
324
+ mustache-mode.el is available at [mustache/emacs][emacs]
326
325
 
327
326
 
328
- TextMate
329
- --------
327
+ ### TextMate
330
328
 
331
- [Mustache.tmbundle](https://github.com/defunkt/Mustache.tmbundle)
329
+ [Mustache.tmbundle][tmbundle]
332
330
 
333
331
  See <https://gist.github.com/defunkt/323624> for installation instructions.
334
332
 
335
333
 
336
- Command Line
337
- ------------
334
+ ### Command Line
338
335
 
339
- See `mustache(1)` man page or
340
- <http://mustache.github.io/mustache.1.html>
336
+ See `mustache(1)` man page or <http://mustache.github.io/mustache.1.html>
341
337
  for command line docs.
342
338
 
343
339
 
344
- Installation
345
- ------------
346
-
347
- ### [RubyGems](http://rubygems.org/)
348
-
349
- $ gem install mustache
350
-
351
-
352
- Acknowledgements
353
- ----------------
340
+ ## Acknowledgements
354
341
 
355
342
  Thanks to [Tom Preston-Werner](https://github.com/mojombo) for showing
356
343
  me ctemplate and [Leah Culver](https://github.com/leah) for the name "Mustache."
@@ -359,8 +346,7 @@ Special thanks to [Magnus Holm](http://judofyr.net/) for all his
359
346
  awesome work on Mustache's parser.
360
347
 
361
348
 
362
- Contributing
363
- ------------
349
+ ## Contributing
364
350
 
365
351
  Once you've made your great commits:
366
352
 
@@ -370,36 +356,36 @@ Once you've made your great commits:
370
356
  4. Create an [Issue][is] with a link to your branch
371
357
  5. That's it!
372
358
 
373
- You might want to checkout Resque's [Contributing][cb] wiki page for information
374
- on coding standards, new features, etc.
375
-
376
359
 
377
- Mailing List
378
- ------------
360
+ ## Mailing List
379
361
 
380
362
  To join the list simply send an email to <mustache@librelist.com>. This
381
363
  will subscribe you and send you information about your subscription,
382
364
  including unsubscribe information.
383
365
 
384
- The archive can be found at <http://librelist.com/browser/>.
366
+ The archive can be found at <http://librelist.com/browser/mustache/>.
385
367
 
386
368
 
387
- Meta
388
- ----
369
+ ## Meta
389
370
 
390
- * Code: `git clone https://github.com/defunkt/mustache.git`
371
+ * Code: `git clone https://github.com/mustache/mustache.git`
391
372
  * Home: <http://mustache.github.io>
392
- * Bugs: <https://github.com/defunkt/mustache/issues>
373
+ * Bugs: <https://github.com/mustache/mustache/issues>
393
374
  * List: <mustache@librelist.com>
394
375
  * Gems: <http://rubygems.org/gems/mustache>
395
376
 
396
- You can also find us in `#{` on irc.freenode.net.
377
+ You can also find us in #{ on [irc.freenode.net][irc].
378
+
397
379
 
398
380
  [1]: http://code.google.com/p/google-ctemplate/
399
381
  [2]: http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html
400
382
  [3]: http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html
401
383
  [4]: https://github.com/brynary/rack-bug/
402
384
  [5]: http://img.skitch.com/20091027-n8pxwwx8r61tc318a15q1n6m14.png
403
- [cb]: http://wiki.github.com/defunkt/resque/contributing
404
385
  [fk]: http://help.github.com/forking/
405
386
  [is]: https://github.com/defunkt/mustache/issues
387
+ [irc]: irc://irc.freenode.net/#{
388
+ [vim]: https://github.com/mustache/vim-mustache-handlebars
389
+ [emacs]: https://github.com/mustache/vim-mustache-handlebars
390
+ [tmbundle]: https://github.com/defunkt/Mustache.tmbundle
391
+ [diff]: https://gist.github.com/defunkt/345490
data/Rakefile CHANGED
@@ -16,18 +16,10 @@ end
16
16
 
17
17
  task :default => :test
18
18
 
19
- if command? :turn
20
- desc "Run tests"
21
- task :test do
22
- suffix = "-n #{ENV['TEST']}" if ENV['TEST']
23
- sh "turn test/*.rb #{suffix}"
24
- end
25
- else
26
- Rake::TestTask.new do |t|
27
- t.libs << 'lib'
28
- t.pattern = 'test/**/*_test.rb'
29
- t.verbose = false
30
- end
19
+ Rake::TestTask.new do |t|
20
+ t.libs << 'lib'
21
+ t.pattern = 'test/**/*_test.rb'
22
+ t.verbose = false
31
23
  end
32
24
 
33
25
 
@@ -73,46 +73,43 @@ require 'mustache/settings'
73
73
  #
74
74
  class Mustache
75
75
 
76
- #
77
- # Public API
78
- #
79
-
80
76
  # Instantiates an instance of this class and calls `render` with
81
77
  # the passed args.
82
78
  #
83
- # Returns a rendered String version of a template
79
+ # @return A rendered String version of a template.
84
80
  def self.render(*args)
85
81
  new.render(*args)
86
82
  end
87
83
 
88
- class << self
89
- alias_method :to_html, :render
90
- alias_method :to_text, :render
91
- end
92
-
93
84
  # Parses our fancy pants template file and returns normal file with
94
85
  # all special {{tags}} and {{#sections}}replaced{{/sections}}.
95
86
  #
96
- # data - A String template or a Hash context. If a Hash is given,
97
- # we'll try to figure out the template from the class.
98
- # ctx - A Hash context if `data` is a String template.
99
- #
100
87
  # Examples
101
88
  #
102
- # @view.render("Hi {{thing}}!", :thing => :world)
89
+ # @view.render("Hi {{thing}}!", :thing => :world)
103
90
  #
104
- # View.template = "Hi {{thing}}!"
105
- # @view = View.new
106
- # @view.render(:thing => :world)
91
+ # View.template = "Hi {{thing}}!"
92
+ # @view = View.new
93
+ # @view.render(:thing => :world)
107
94
  #
108
- # Returns a rendered String version of a template
95
+ # @param [String,Hash] data A String template or a Hash context.
96
+ # If a Hash is given, we'll try to figure
97
+ # out the template from the class.
98
+ # @param [Hash] ctx A Hash context if `data` is a String template.
99
+ #
100
+ # @return [String] Returns a rendered version of a template.
109
101
  def render(data = template, ctx = {})
110
- tpl = case data
102
+ case data
111
103
  when Hash
112
104
  ctx = data
113
- templateify(template)
114
105
  when Symbol
115
106
  self.template_name = data
107
+ end
108
+
109
+ tpl = case data
110
+ when Hash
111
+ templateify(template)
112
+ when Symbol
116
113
  templateify(template)
117
114
  else
118
115
  templateify(data)
@@ -128,15 +125,13 @@ class Mustache
128
125
  end
129
126
  end
130
127
 
131
- alias_method :to_html, :render
132
- alias_method :to_text, :render
133
-
134
128
  # Context accessors.
135
129
  #
136
- # view = Mustache.new
137
- # view[:name] = "Jon"
138
- # view.template = "Hi, {{name}}!"
139
- # view.render # => "Hi, Jon!"
130
+ # Example:
131
+ # view = Mustache.new
132
+ # view[:name] = "Jon"
133
+ # view.template = "Hi, {{name}}!"
134
+ # view.render # => "Hi, Jon!"
140
135
  def [](key)
141
136
  context[key.to_sym]
142
137
  end
@@ -182,21 +177,29 @@ class Mustache
182
177
 
183
178
  # Override this to provide custom escaping.
184
179
  #
185
- # class PersonView < Mustache
186
- # def escapeHTML(str)
187
- # my_html_escape_method(str)
180
+ # Example:
181
+ #
182
+ # class PersonView < Mustache
183
+ # def escapeHTML(str)
184
+ # my_html_escape_method(str)
185
+ # end
188
186
  # end
189
- # end
190
187
  #
191
- # Returns a String
188
+ # @param [String] str String to escape.
189
+ #
190
+ # @return [String] Escaped HTML.
192
191
  def escapeHTML(str)
193
192
  CGI.escapeHTML(str)
194
193
  end
195
194
 
195
+ # Has this instance or its class already compiled a template?
196
+ def compiled?
197
+ (@template && @template.is_a?(Template)) || self.class.compiled?
198
+ end
199
+
200
+
201
+ private
196
202
 
197
- #
198
- # Private API
199
- #
200
203
 
201
204
  # When given a symbol or string representing a class, will try to produce an
202
205
  # appropriate view class.
@@ -207,55 +210,46 @@ class Mustache
207
210
  name = classify(name.to_s)
208
211
 
209
212
  # Emptiness begets emptiness.
210
- return Mustache if name.to_s == ''
213
+ return Mustache if name.to_s.empty?
211
214
 
212
- file_name = underscore(name)
213
215
  name = "#{view_namespace}::#{name}"
216
+ const = rescued_const_get(name)
214
217
 
215
- if const = const_get!(name)
216
- const
217
- elsif File.exists?(file = "#{view_path}/#{file_name}.rb")
218
- require "#{file}".chomp('.rb')
219
- const_get!(name) || Mustache
220
- else
221
- Mustache
222
- end
218
+ return const if const
219
+
220
+ const_from_file(name)
223
221
  end
224
222
 
225
- # Supercharged version of Module#const_get.
226
- #
227
- # Always searches under Object and can find constants by their full name,
228
- # e.g. Mustache::Views::Index
229
- #
230
- # name - The full constant name to find.
231
- #
232
- # Returns the constant if found
233
- # Returns nil if nothing is found
234
- def self.const_get!(name)
235
- name.split('::').reduce(Object) do |klass, cname|
236
- klass.const_get(cname)
237
- end
223
+ def self.rescued_const_get name
224
+ const_get(name, true) || Mustache
238
225
  rescue NameError
239
226
  nil
240
227
  end
241
228
 
229
+ def self.const_from_file name
230
+ file_name = underscore(name)
231
+ file_path = "#{view_path}/#{file_name}.rb"
232
+
233
+ return Mustache unless File.exists?(file_path)
234
+
235
+ require file_path.chomp('.rb')
236
+ rescued_const_get(name)
237
+ end
238
+
242
239
  # Has this template already been compiled? Compilation is somewhat
243
240
  # expensive so it may be useful to check this before attempting it.
244
241
  def self.compiled?
245
242
  @template.is_a? Template
246
243
  end
247
244
 
248
- # Has this instance or its class already compiled a template?
249
- def compiled?
250
- (@template && @template.is_a?(Template)) || self.class.compiled?
251
- end
252
245
 
253
246
  # template_partial => TemplatePartial
254
247
  # template/partial => Template::Partial
255
248
  def self.classify(underscored)
256
249
  underscored.split('/').map do |namespace|
257
250
  namespace.split(/[-_]/).map do |part|
258
- part[0] = part[0].chr.upcase; part
251
+ part[0] = part.chars.first.upcase
252
+ part
259
253
  end.join
260
254
  end.join('::')
261
255
  end
@@ -264,21 +258,19 @@ class Mustache
264
258
  # Template::Partial => template/partial
265
259
  # Takes a string but defaults to using the current class' name.
266
260
  def self.underscore(classified = name)
267
- classified = name if classified.to_s.empty?
268
261
  classified = superclass.name if classified.to_s.empty?
269
262
 
270
263
  string = classified.dup.split("#{view_namespace}::").last
271
264
 
272
265
  string.split('::').map do |part|
273
- part[0] = part[0].chr.downcase
274
- part.gsub(/[A-Z]/) { |s| "_#{s.downcase}"}
266
+ part[0] = part[0].downcase
267
+ part.gsub(/[A-Z]/) { |s| "_" << s.downcase }
275
268
  end.join('/')
276
269
  end
277
270
 
278
- # Turns a string into a Mustache::Template. If passed a Template,
279
- # returns it.
271
+ # @param [Template,String] obj Turns `obj` into a template
280
272
  def self.templateify(obj)
281
- obj.is_a?(Template) ? obj : Template.new(obj.to_s)
273
+ obj.is_a?(Template) ? obj : Template.new(obj)
282
274
  end
283
275
 
284
276
  def templateify(obj)
@@ -288,10 +280,12 @@ class Mustache
288
280
  # Return the value of the configuration setting on the superclass, or return
289
281
  # the default.
290
282
  #
291
- # attr_name - Symbol name of the attribute. It should match the instance variable.
292
- # default - Default value to use if the superclass does not respond.
283
+ # @param [Symbol] attr_name Name of the attribute. It should match
284
+ # the instance variable.
285
+ # @param [Object] default Default value to use if the superclass does
286
+ # not respond.
293
287
  #
294
- # Returns the inherited or default configuration setting.
288
+ # @return Inherited or default configuration setting.
295
289
  def self.inheritable_config_for(attr_name, default)
296
290
  superclass.respond_to?(attr_name) ? superclass.send(attr_name) : default
297
291
  end