mustache 1.0.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NTQ2NzA3NTY3ZTQ4MzNkNWY1MzU4MjBlZjgwZmNiZDg3NjA5OTU4NQ==
5
- data.tar.gz: !binary |-
6
- MGYwNTg4YTNlMGIzMDFlM2RlZWRlYjgxOWVkYzVmMjBkYTY0NjJlMg==
2
+ SHA1:
3
+ metadata.gz: bf94eeecd19f735037d7bbb26dec6b31fd744220
4
+ data.tar.gz: 1950b718fced739f53562898d3577a10ca88cdbf
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZDZkYjBjYmJlN2E3ZTg0ODliZDM0MTAwM2Q5YTQ4OTU4YmRhZDQwMzZjMWU2
10
- ODk0MDY3NTliYjM2NGI1OGUzMzZiNDkzNzA4NjEzNWJhMGRhZGFiZmUwYjJj
11
- ODYzNjY3MWU0MDg2NjUzMzdkYTcwZGZhOTk4NWQ1MWZhYzBlNGQ=
12
- data.tar.gz: !binary |-
13
- NDA2ZDRiNjRlYTg3MjRkZjhmNWFjZDAyMjY3YzU1YzM0NTU4MWNlMzkzMmI0
14
- MjAxMjAxOWYyNDdmYWE5MzEwODYzYzExZjBmM2VkN2E3YzdmODYxNGI2NTc3
15
- N2U3ZGExOTcxMmE3MDBmMTdmMWI1YmUzNmE4YTFlMTdiMjQwNmM=
6
+ metadata.gz: 2aa2853641590267b49b7264f8592fed44f3fa430ea10e60ae3ce8b58a5fadea3b532f256b70229a0fbd62835176ead87b8dff0d66ac73750af603c9739e6587
7
+ data.tar.gz: 31a31d089046ab7d11b6541a02b588d92c26a6b5879185203ddc4ffedd64a41cc6b0651b818066333ee9af4000754a8f1d3885b5647895390ebe3e62d65532ae
data/README.md CHANGED
@@ -44,10 +44,12 @@ in my HTML, or putting JavaScript in my HTML.
44
44
  Install the gem locally with:
45
45
 
46
46
  $ gem install mustache
47
-
48
- Or add it to your `gemspec`:
49
47
 
50
- s.add_dependency "mustache", "~> 1.0"
48
+ Or add it to your `Gemfile`:
49
+
50
+ ```ruby
51
+ gem "mustache", "~> 1.0"
52
+ ```
51
53
 
52
54
 
53
55
  ## Usage
@@ -56,28 +58,30 @@ Quick example:
56
58
 
57
59
  >> require 'mustache'
58
60
  => true
59
- >> Mustache.render("Hello {{planet}}", :planet => "World!")
61
+ >> Mustache.render("Hello {{planet}}", planet: "World!")
60
62
  => "Hello World!"
61
63
 
62
64
  We've got an `examples` folder but here's the canonical one:
63
65
 
64
- class Simple < Mustache
65
- def name
66
- "Chris"
67
- end
66
+ ```ruby
67
+ class Simple < Mustache
68
+ def name
69
+ "Chris"
70
+ end
68
71
 
69
- def value
70
- 10_000
71
- end
72
+ def value
73
+ 10_000
74
+ end
72
75
 
73
- def taxed_value
74
- value * 0.6
75
- end
76
+ def taxed_value
77
+ value * 0.6
78
+ end
76
79
 
77
- def in_ca
78
- true
79
- end
80
- end
80
+ def in_ca
81
+ true
82
+ end
83
+ end
84
+ ```
81
85
 
82
86
  We simply create a normal Ruby class and define methods. Some methods
83
87
  reference others, some return values, some return only booleans.
@@ -92,9 +96,9 @@ Now let's write the template:
92
96
 
93
97
  This template references our view methods. To bring it all together,
94
98
  here's the code to render actual HTML;
95
-
96
- Simple.render
97
-
99
+ ```ruby
100
+ Simple.render
101
+ ```
98
102
  Which returns the following:
99
103
 
100
104
  Hello Chris
@@ -114,7 +118,7 @@ the `mustache(5)` manpage or
114
118
  ## Escaping
115
119
 
116
120
  Mustache does escape all values when using the standard double
117
- Mustache syntax. Characters which will be escaped: `& \ " < >` (as
121
+ Mustache syntax. Characters which will be escaped: `& \ " < >` (as
118
122
  well as `'` in Ruby `>= 2.0`). To disable escaping, simply use triple
119
123
  mustaches like `{{{unescaped_variable}}}`.
120
124
 
@@ -136,11 +140,12 @@ Given this template (winner.mustache):
136
140
 
137
141
  We can fill in the values at will:
138
142
 
139
- view = Winner.new
140
- view[:name] = 'George'
141
- view[:value] = 100
142
- view.render
143
-
143
+ ```ruby
144
+ view = Winner.new
145
+ view[:name] = 'George'
146
+ view[:value] = 100
147
+ view.render
148
+ ```
144
149
  Which returns:
145
150
 
146
151
  Hello George
@@ -148,11 +153,10 @@ Which returns:
148
153
 
149
154
  We can re-use the same object, too:
150
155
 
151
- view[:name] = 'Tony'
152
- view.render
153
- Hello Tony
154
- You have just won 100 bucks!
155
-
156
+ ```ruby
157
+ view[:name] = 'Tony'
158
+ view.render # => Hello Tony\nYou have just won 100 bucks!
159
+ ```
156
160
 
157
161
  ## Templates
158
162
 
@@ -165,33 +169,38 @@ follows the classic Ruby naming convention.
165
169
  You can set the search path using `Mustache.template_path`. It can be set on a
166
170
  class by class basis:
167
171
 
168
- class Simple < Mustache
169
- self.template_path = File.dirname(__FILE__)
170
- ... etc ...
171
- end
172
-
172
+ ```ruby
173
+ class Simple < Mustache
174
+ self.template_path = __dir__
175
+ end
176
+ ```
173
177
  Now `Simple` will look for `simple.mustache` in the directory it resides
174
178
  in, no matter the cwd.
175
179
 
176
180
  If you want to just change what template is used you can set
177
181
  `Mustache.template_file` directly:
178
182
 
179
- Simple.template_file = './blah.mustache'
180
-
183
+ ```ruby
184
+ Simple.template_file = './blah.mustache'
185
+ ```
181
186
  Mustache also allows you to define the extension it'll use.
182
187
 
183
- Simple.template_extension = 'xml'
184
-
188
+ ```ruby
189
+ Simple.template_extension = 'xml'
190
+ ```
185
191
  Given all other defaults, the above line will cause Mustache to look
186
192
  for './blah.xml'
187
193
 
188
194
  Feel free to set the template directly:
189
195
 
190
- Simple.template = 'Hi {{person}}!'
196
+ ```ruby
197
+ Simple.template = 'Hi {{person}}!'
198
+ ```
191
199
 
192
200
  Or set a different template for a single instance:
193
-
194
- Simple.new.template = 'Hi {{person}}!'
201
+ ```ruby
202
+ Simple.new.template = 'Hi {{person}}!'
203
+ ```
195
204
 
196
205
  Whatever works.
197
206
 
@@ -211,46 +220,50 @@ you want to use in all your views? No problem.
211
220
 
212
221
  This is just Ruby, after all.
213
222
 
214
- module ViewHelpers
215
- def gravatar
216
- gravatar_id = Digest::MD5.hexdigest(self[:email].to_s.strip.downcase)
217
- gravatar_for_id(gravatar_id)
218
- end
223
+ ```ruby
224
+ module ViewHelpers
225
+ def gravatar
226
+ gravatar_id = Digest::MD5.hexdigest(self[:email].to_s.strip.downcase)
227
+ gravatar_for_id(gravatar_id)
228
+ end
219
229
 
220
- def gravatar_for_id(gid, size = 30)
221
- "#{gravatar_host}/avatar/#{gid}?s=#{size}"
222
- end
230
+ def gravatar_for_id(gid, size = 30)
231
+ "#{gravatar_host}/avatar/#{gid}?s=#{size}"
232
+ end
223
233
 
224
- def gravatar_host
225
- @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com'
226
- end
227
- end
234
+ def gravatar_host
235
+ @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com'
236
+ end
237
+ end
238
+ ```
228
239
 
229
240
  Then just include it:
230
241
 
231
- class Simple < Mustache
232
- include ViewHelpers
242
+ ```ruby
243
+ class Simple < Mustache
244
+ include ViewHelpers
233
245
 
234
- def name
235
- "Chris"
236
- end
246
+ def name
247
+ "Chris"
248
+ end
237
249
 
238
- def value
239
- 10_000
240
- end
250
+ def value
251
+ 10_000
252
+ end
241
253
 
242
- def taxed_value
243
- value * 0.6
244
- end
254
+ def taxed_value
255
+ value * 0.6
256
+ end
245
257
 
246
- def in_ca
247
- true
248
- end
258
+ def in_ca
259
+ true
260
+ end
249
261
 
250
- def users
251
- User.all
252
- end
253
- end
262
+ def users
263
+ User.all
264
+ end
265
+ end
266
+ ```
254
267
 
255
268
  Great, but what about that `@ssl` ivar in `gravatar_host`? There are
256
269
  many ways we can go about setting it.
@@ -259,19 +272,21 @@ Here's an example which illustrates a key feature of Mustache: you
259
272
  are free to use the `initialize` method just as you would in any
260
273
  normal class.
261
274
 
262
- class Simple < Mustache
263
- include ViewHelpers
264
-
265
- def initialize(ssl = false)
266
- @ssl = ssl
267
- end
275
+ ```ruby
276
+ class Simple < Mustache
277
+ include ViewHelpers
268
278
 
269
- ... etc ...
270
- end
279
+ def initialize(ssl = false)
280
+ @ssl = ssl
281
+ end
282
+ end
283
+ ```
271
284
 
272
285
  Now:
273
286
 
274
- Simple.new(request.ssl?).render
287
+ ```ruby
288
+ Simple.new(request.ssl?).render
289
+ ```
275
290
 
276
291
  Finally, our template might look like this:
277
292
 
@@ -286,7 +301,7 @@ Finally, our template might look like this:
286
301
 
287
302
  ### Sinatra
288
303
 
289
- Sinatra integration is available with the
304
+ Sinatra integration is available with the
290
305
  [mustache-sinatra gem](https://github.com/mustache/mustache-sinatra).
291
306
 
292
307
  An example Sinatra application is also provided:
@@ -305,13 +320,17 @@ contained in a hash set using `set :mustache, hash`.
305
320
  Mustache also provides a `Rack::Bug` panel.
306
321
  First you have to install the `rack-bug-mustache_panel` gem, then in your `config.ru` add the following code:
307
322
 
308
- require 'rack/bug/panels/mustache_panel'
309
- use Rack::Bug::MustachePanel
323
+ ```ruby
324
+ require 'rack/bug/panels/mustache_panel'
325
+ use Rack::Bug::MustachePanel
326
+ ```
310
327
 
311
328
  Using Rails? Add this to your initializer or environment file:
312
329
 
313
- require 'rack/bug/panels/mustache_panel'
314
- config.middleware.use "Rack::Bug::MustachePanel"
330
+ ```ruby
331
+ require 'rack/bug/panels/mustache_panel'
332
+ config.middleware.use "Rack::Bug::MustachePanel"
333
+ ```
315
334
 
316
335
  ![Rack::Bug][5]
317
336
 
@@ -390,6 +409,6 @@ or IRC:
390
409
  [is]: https://github.com/mustache/mustache/issues
391
410
  [irc]: irc://irc.freenode.net/#{
392
411
  [vim]: https://github.com/mustache/vim-mustache-handlebars
393
- [emacs]: https://github.com/mustache/vim-mustache-handlebars
412
+ [emacs]: https://github.com/mustache/emacs
394
413
  [tmbundle]: https://github.com/defunkt/Mustache.tmbundle
395
414
  [diff]: https://gist.github.com/defunkt/345490
@@ -74,6 +74,12 @@ require 'mustache/utils'
74
74
  #
75
75
  class Mustache
76
76
 
77
+ # Initialize a new mustache instance.
78
+ # @param [Hash] options An options hash
79
+ def initialize(options = {})
80
+ @options = options
81
+ end
82
+
77
83
  # Instantiates an instance of this class and calls `render` with
78
84
  # the passed args.
79
85
  #
@@ -266,13 +272,16 @@ class Mustache
266
272
  Mustache::Utils::String.new(classified).underscore(view_namespace)
267
273
  end
268
274
 
269
- # @param [Template,String] obj Turns `obj` into a template
270
- def self.templateify(obj)
271
- obj.is_a?(Template) ? obj : Template.new(obj)
275
+ # @param [Template,String] obj Turns `obj` into a template
276
+ # @param [Hash] options Options for template creation
277
+ def self.templateify(obj, options = {})
278
+ obj.is_a?(Template) ? obj : Template.new(obj, options)
272
279
  end
273
280
 
274
281
  def templateify(obj)
275
- self.class.templateify(obj)
282
+ opts = {:partial_resolver => self.method(:partial)}
283
+ opts.merge!(@options) if @options.is_a?(Hash)
284
+ self.class.templateify(obj, opts)
276
285
  end
277
286
 
278
287
  # Return the value of the configuration setting on the superclass, or return
@@ -159,6 +159,7 @@ class Mustache
159
159
  def find_in_hash(obj, key, default)
160
160
  return obj[key] if obj.has_key?(key)
161
161
  return obj[key.to_s] if obj.has_key?(key.to_s)
162
+ return obj[key] if obj.respond_to?(:default_proc) && obj.default_proc && obj[key]
162
163
 
163
164
  # If default is :__missing then we are from #fetch which is hunting through the stack
164
165
  # If default is nil then we are reducing dot notation
@@ -27,9 +27,10 @@ class Mustache
27
27
  # $ mustache --compile test.mustache
28
28
  # "Hi #{CGI.escapeHTML(ctx[:thing].to_s)}!\n"
29
29
  class Generator
30
- # Options are unused for now but may become useful in the future.
30
+ # Options can be used to manipulate the resulting ruby code string behavior.
31
31
  def initialize(options = {})
32
32
  @options = options
33
+ @option_static_lambdas = options[:static_lambdas] == true
33
34
  end
34
35
 
35
36
  # Given an array of tokens, returns an interpolatable Ruby string.
@@ -104,13 +105,14 @@ class Mustache
104
105
  # string we can use.
105
106
  code = compile(content)
106
107
 
107
- # Compile the Ruby for this section now that we know what's
108
- # inside the section.
109
- ev(<<-compiled)
110
- if v = #{compile!(name)}
111
- if v == true
112
- #{code}
113
- elsif v.is_a?(Proc)
108
+ # Lambda handling - default handling is to dynamically interpret
109
+ # the returned lambda result as mustache source
110
+ proc_handling = if @option_static_lambdas
111
+ <<-compiled
112
+ v.call(lambda {|v| #{code}}.call(v)).to_s
113
+ compiled
114
+ else
115
+ <<-compiled
114
116
  t = Mustache::Template.new(v.call(#{raw.inspect}).to_s)
115
117
  def t.tokens(src=@source)
116
118
  p = Mustache::Parser.new
@@ -118,12 +120,22 @@ class Mustache
118
120
  p.compile(src)
119
121
  end
120
122
  t.render(ctx.dup)
121
- else
122
- # Shortcut when passed non-array
123
- v = [v] unless v.is_a?(Array) || v.is_a?(Mustache::Enumerable) || defined?(Enumerator) && v.is_a?(Enumerator)
123
+ compiled
124
+ end
124
125
 
125
- v.map { |h| ctx.push(h); r = #{code}; ctx.pop; r }.join
126
- end
126
+ # Compile the Ruby for this section now that we know what's
127
+ # inside the section.
128
+ ev(<<-compiled)
129
+ case v = #{compile!(name)}
130
+ when NilClass, FalseClass
131
+ when TrueClass
132
+ #{code}
133
+ when Proc
134
+ #{proc_handling}
135
+ when Array, Enumerator, Mustache::Enumerable
136
+ v.map { |h| ctx.push(h); r = #{code}; ctx.pop; r }.join
137
+ else
138
+ ctx.push(v); r = #{code}; ctx.pop; r
127
139
  end
128
140
  compiled
129
141
  end
@@ -157,7 +169,7 @@ class Mustache
157
169
  ev(<<-compiled)
158
170
  v = #{compile!(name)}
159
171
  if v.is_a?(Proc)
160
- v = Mustache::Template.new(v.call.to_s).render(ctx.dup)
172
+ v = #{@option_static_lambdas ? 'v.call' : 'Mustache::Template.new(v.call.to_s).render(ctx.dup)'}
161
173
  end
162
174
  v.to_s
163
175
  compiled
@@ -168,7 +180,7 @@ class Mustache
168
180
  ev(<<-compiled)
169
181
  v = #{compile!(name)}
170
182
  if v.is_a?(Proc)
171
- v = Mustache::Template.new(v.call.to_s).render(ctx.dup)
183
+ v = #{@option_static_lambdas ? 'v.call' : 'Mustache::Template.new(v.call.to_s).render(ctx.dup)'}
172
184
  end
173
185
  ctx.escapeHTML(v.to_s)
174
186
  compiled
@@ -180,11 +192,15 @@ class Mustache
180
192
  names = names.map { |n| n.to_sym }
181
193
 
182
194
  initial, *rest = names
183
- <<-compiled
184
- #{rest.inspect}.reduce(ctx[#{initial.inspect}]) { |value, key|
185
- value && ctx.find(value, key)
186
- }
187
- compiled
195
+ if rest.any?
196
+ <<-compiled
197
+ #{rest.inspect}.reduce(ctx[#{initial.inspect}]) { |value, key| value && ctx.find(value, key) }
198
+ compiled
199
+ else
200
+ <<-compiled
201
+ ctx[#{initial.inspect}]
202
+ compiled
203
+ end
188
204
  end
189
205
 
190
206
  # An interpolation-friendly version of a string, for use within a
@@ -84,22 +84,35 @@ EOF
84
84
  # the rest only allow ALLOWED_CONTENT.
85
85
  ANY_CONTENT = [ '!', '=' ].map(&:freeze)
86
86
 
87
- attr_writer :otag, :ctag
87
+ attr_reader :otag, :ctag
88
88
 
89
89
  # Accepts an options hash which does nothing but may be used in
90
90
  # the future.
91
91
  def initialize(options = {})
92
- @options = {}
92
+ @options = options
93
+ @option_inline_partials_at_compile_time = options[:inline_partials_at_compile_time]
94
+ if @option_inline_partials_at_compile_time
95
+ @partial_resolver = options[:partial_resolver]
96
+ raise ArgumentError.new "Missing or invalid partial_resolver" unless @partial_resolver.respond_to? :call
97
+ end
98
+
99
+ # Initialize default tags
100
+ self.otag ||= '{{'
101
+ self.ctag ||= '}}'
93
102
  end
94
103
 
95
104
  # The opening tag delimiter. This may be changed at runtime.
96
- def otag
97
- @otag ||= '{{'
105
+ def otag=(value)
106
+ regex = regexp value
107
+ @otag_regex = /([ \t]*)?#{regex}/
108
+ @otag_not_regex = /(^[ \t]*)?#{regex}/
109
+ @otag = value
98
110
  end
99
111
 
100
112
  # The closing tag delimiter. This too may be changed at runtime.
101
- def ctag
102
- @ctag ||= '}}'
113
+ def ctag=(value)
114
+ @ctag_regex = regexp value
115
+ @ctag = value
103
116
  end
104
117
 
105
118
  # Given a string template, returns an array of tokens.
@@ -134,9 +147,9 @@ EOF
134
147
  private
135
148
 
136
149
 
137
- def content_tags type, current_ctag
150
+ def content_tags type, current_ctag_regex
138
151
  if ANY_CONTENT.include?(type)
139
- r = /\s*#{regexp(type)}?#{regexp(current_ctag)}/
152
+ r = /\s*#{regexp(type)}?#{current_ctag_regex}/
140
153
  scan_until_exclusive(r)
141
154
  else
142
155
  @scanner.scan(ALLOWED_CONTENT)
@@ -147,8 +160,8 @@ EOF
147
160
  send("scan_tag_#{type}", content, fetch, padding, pre_match_position)
148
161
  end
149
162
 
150
- def find_closing_tag scanner, current_ctag
151
- error "Unclosed tag" unless scanner.scan(regexp(current_ctag))
163
+ def find_closing_tag scanner, current_ctag_regex
164
+ error "Unclosed tag" unless scanner.scan(current_ctag_regex)
152
165
  end
153
166
 
154
167
  # Find {{mustaches}} and add them to the @result array.
@@ -158,7 +171,7 @@ EOF
158
171
  pre_match_position = @scanner.pos
159
172
  last_index = @result.length
160
173
 
161
- return unless @scanner.scan(/([ \t]*)?#{Regexp.escape(otag)}/)
174
+ return unless @scanner.scan @otag_regex
162
175
  padding = @scanner[1] || ''
163
176
 
164
177
  # Don't touch the preceding whitespace unless we're matching the start
@@ -171,13 +184,13 @@ EOF
171
184
 
172
185
  # Since {{= rewrites ctag, we store the ctag which should be used
173
186
  # when parsing this specific tag.
174
- current_ctag = self.ctag
187
+ current_ctag_regex = @ctag_regex
175
188
  type = @scanner.scan(self.class.valid_types)
176
189
  @scanner.skip(/\s*/)
177
190
 
178
191
  # ANY_CONTENT tags allow any character inside of them, while
179
192
  # other tags (such as variables) are more strict.
180
- content = content_tags(type, current_ctag)
193
+ content = content_tags(type, current_ctag_regex)
181
194
 
182
195
  # We found {{ but we can't figure out what's going on inside.
183
196
  error "Illegal content in tag" if content.empty?
@@ -196,7 +209,7 @@ EOF
196
209
  @scanner.skip(/\s+/)
197
210
  @scanner.skip(regexp(type)) if type
198
211
 
199
- find_closing_tag(@scanner, current_ctag)
212
+ find_closing_tag(@scanner, current_ctag_regex)
200
213
 
201
214
  # If this tag was the only non-whitespace content on this line, strip
202
215
  # the remaining whitespace. If not, but we've been hanging on to padding
@@ -218,7 +231,7 @@ EOF
218
231
 
219
232
  # Try to find static text, e.g. raw HTML with no {{mustaches}}.
220
233
  def scan_text
221
- text = scan_until_exclusive(/(^[ \t]*)?#{Regexp.escape(otag)}/)
234
+ text = scan_until_exclusive @otag_not_regex
222
235
 
223
236
  if text.nil?
224
237
  # Couldn't find any otag, which means the rest is just static text.
@@ -263,7 +276,7 @@ EOF
263
276
  # Used to quickly convert a string into a regular expression
264
277
  # usable by the string scanner.
265
278
  def regexp(thing)
266
- /#{Regexp.escape(thing)}/
279
+ Regexp.new Regexp.escape(thing) if thing
267
280
  end
268
281
 
269
282
  # Raises a SyntaxError. The message should be the name of the
@@ -334,7 +347,13 @@ EOF
334
347
 
335
348
 
336
349
  def scan_tag_open_partial content, fetch, padding, pre_match_position
337
- @result << [:mustache, :partial, content, offset, padding]
350
+ @result << if @option_inline_partials_at_compile_time
351
+ partial = @partial_resolver.call content
352
+ partial.gsub!(/^/, padding) unless padding.empty?
353
+ self.class.new(@options).compile partial
354
+ else
355
+ [:mustache, :partial, content, offset, padding]
356
+ end
338
357
  end
339
358
  alias_method :'scan_tag_<', :scan_tag_open_partial
340
359
  alias_method :'scan_tag_>', :scan_tag_open_partial
@@ -18,9 +18,10 @@ class Mustache
18
18
  attr_reader :source
19
19
 
20
20
  # Expects a Mustache template as a string along with a template
21
- # path, which it uses to find partials.
22
- def initialize(source)
21
+ # path, which it uses to find partials. Options may be passed.
22
+ def initialize(source, options = {})
23
23
  @source = source
24
+ @options = options
24
25
  end
25
26
 
26
27
  # Renders the `@source` Mustache template using the given
@@ -46,7 +47,7 @@ class Mustache
46
47
  # Does the dirty work of transforming a Mustache template into an
47
48
  # interpolation-friendly Ruby string.
48
49
  def compile(src = @source)
49
- Generator.new.compile(tokens(src))
50
+ Generator.new(@options).compile(tokens(src))
50
51
  end
51
52
  alias_method :to_s, :compile
52
53
 
@@ -55,7 +56,7 @@ class Mustache
55
56
  # @return [Array] Array of tokens.
56
57
  #
57
58
  def tokens(src = @source)
58
- Parser.new.compile(src)
59
+ Parser.new(@options).compile(src)
59
60
  end
60
61
 
61
62
  # Returns an array of tags.
@@ -1,3 +1,3 @@
1
1
  class Mustache
2
- VERSION = '1.0.3'
2
+ VERSION = '1.0.5'
3
3
  end
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "MUSTACHE" "1" "February 2015" "DEFUNKT" "Mustache Manual"
4
+ .TH "MUSTACHE" "1" "November 2016" "DEFUNKT" "Mustache Manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBmustache\fR \- Mustache processor
@@ -75,7 +75,7 @@ $ cat template\.mustache
75
75
  Hi {{name}}!
76
76
  {{/names}}
77
77
 
78
- $ cat data\.yml template\.mustache | mustache
78
+ $ mustache data\.yml template\.mustache
79
79
  Hi chris!
80
80
  Hi mark!
81
81
  Hi scott!
@@ -106,7 +106,7 @@ name: scott
106
106
  $ cat template\.mustache
107
107
  Hi {{name}}!
108
108
 
109
- $ cat data\.yml template\.mustache | mustache
109
+ $ mustache data\.yml template\.mustache
110
110
  Hi chris!
111
111
  Hi mark!
112
112
  Hi scott!
@@ -123,7 +123,7 @@ $ cat template.mustache
123
123
  Hi {{name}}!
124
124
  {{/names}}
125
125
 
126
- $ cat data.yml template.mustache | mustache
126
+ $ mustache data.yml template.mustache
127
127
  Hi chris!
128
128
  Hi mark!
129
129
  Hi scott!
@@ -146,7 +146,7 @@ name: scott
146
146
  $ cat template.mustache
147
147
  Hi {{name}}!
148
148
 
149
- $ cat data.yml template.mustache | mustache
149
+ $ mustache data.yml template.mustache
150
150
  Hi chris!
151
151
  Hi mark!
152
152
  Hi scott!
@@ -204,7 +204,7 @@ data
204
204
 
205
205
  <ol class='man-decor man-foot man foot'>
206
206
  <li class='tl'>DEFUNKT</li>
207
- <li class='tc'>February 2015</li>
207
+ <li class='tc'>November 2016</li>
208
208
  <li class='tr'>mustache(1)</li>
209
209
  </ol>
210
210
 
@@ -48,7 +48,7 @@ Now let's combine them.
48
48
  Hi {{name}}!
49
49
  {{/names}}
50
50
 
51
- $ cat data.yml template.mustache | mustache
51
+ $ mustache data.yml template.mustache
52
52
  Hi chris!
53
53
  Hi mark!
54
54
  Hi scott!
@@ -70,7 +70,7 @@ For example:
70
70
  $ cat template.mustache
71
71
  Hi {{name}}!
72
72
 
73
- $ cat data.yml template.mustache | mustache
73
+ $ mustache data.yml template.mustache
74
74
  Hi chris!
75
75
  Hi mark!
76
76
  Hi scott!
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "MUSTACHE" "5" "February 2015" "DEFUNKT" "Mustache Manual"
4
+ .TH "MUSTACHE" "5" "November 2016" "DEFUNKT" "Mustache Manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBmustache\fR \- Logic\-less templates\.
@@ -415,7 +415,7 @@ markup."</p>
415
415
 
416
416
  <ol class='man-decor man-foot man foot'>
417
417
  <li class='tl'>DEFUNKT</li>
418
- <li class='tc'>February 2015</li>
418
+ <li class='tc'>November 2016</li>
419
419
  <li class='tr'>mustache(5)</li>
420
420
  </ol>
421
421
 
@@ -1,7 +1,9 @@
1
- require 'minitest/autorun'
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/test/'
4
+ end
2
5
 
3
- require "codeclimate-test-reporter"
4
- CodeClimate::TestReporter.start
6
+ require 'minitest/autorun'
5
7
 
6
8
  Dir[File.dirname(__FILE__) + '/fixtures/*.rb'].each do |f|
7
9
  require f
@@ -362,7 +362,7 @@ data
362
362
  end
363
363
 
364
364
  def each *args, &block
365
- @people.each *args, &block
365
+ @people.each(*args, &block)
366
366
  end
367
367
  end
368
368
 
@@ -506,6 +506,24 @@ Benvolio is 15
506
506
  assert_equal 1, view.calls
507
507
  end
508
508
 
509
+ def test_sections_returning_lambdas_get_called_dynamically_with_text
510
+ view = Mustache.new
511
+ view.template = '{{name}}'
512
+ view[:name] = lambda { '{{dynamic_name}}' }
513
+ view[:dynamic_name] = 'Chris'
514
+
515
+ assert_equal "Chris", view.render.chomp
516
+ end
517
+
518
+ def test_sections_returning_lambdas_get_not_called_dynamically_with_text_if_static
519
+ view = Mustache.new :static_lambdas => true
520
+ view.template = '{{name}}'
521
+ view[:name] = lambda { '{{dynamic_name}}' }
522
+ view[:dynamic_name] = 'Chris'
523
+
524
+ assert_equal "{{dynamic_name}}", view.render.chomp
525
+ end
526
+
509
527
  def test_sections_which_refer_to_unary_method_call_them_as_proc
510
528
  kls = Class.new(Mustache) do
511
529
  def unary_method(arg)
@@ -706,6 +724,23 @@ text
706
724
  end
707
725
  end
708
726
 
727
+ def test_hash_default_proc
728
+ template = <<template
729
+ {{greetings.Peter}}
730
+ {{greetings.Paul}}
731
+ {{greetings.Mary}}
732
+ template
733
+ data = {
734
+ 'greetings' => Hash.new { |hash, key| hash[key] = "Hello, #{key}!" }
735
+ }
736
+
737
+ assert_equal <<expected, Mustache.render(template, data)
738
+ Hello, Peter!
739
+ Hello, Paul!
740
+ Hello, Mary!
741
+ expected
742
+ end
743
+
709
744
  def test_array_of_arrays
710
745
  template = <<template
711
746
  {{#items}}
@@ -780,7 +815,17 @@ template
780
815
  template = '%%{{title}}%%'
781
816
 
782
817
  assert_equal '%%title%%', Mustache.render(template, hashlike)
783
-
784
818
  end
785
819
 
820
+ def test_instance_with_initialize_render
821
+ klass = Class.new(Mustache) do
822
+ def initialize(name)
823
+ @name = name
824
+ end
825
+ attr_reader :name
826
+ end
827
+
828
+ klass.template = "Hi {{name}}!"
829
+ assert_equal "Hi Dougal!", klass.new("Dougal").render
830
+ end
786
831
  end
@@ -20,6 +20,19 @@ end_partial
20
20
  assert_equal "Again, success!", view.render
21
21
  end
22
22
 
23
+ def test_partial_inlining
24
+ view = Mustache.new :inline_partials_at_compile_time => true
25
+ view.template = '{{> test/fixtures/inner_partial}}'
26
+ view[:title] = 'success'
27
+
28
+ # Test the rendered result first
29
+ assert_equal "Again, success!", view.render
30
+
31
+ # Now the template should be compiled.
32
+ # There should be no :partial instruction as the partial has been in-lined.
33
+ assert_equal false, view.template.tokens.flatten.include?(:partial)
34
+ end
35
+
23
36
  def test_view_partial_inherits_context
24
37
  klass = Class.new(TemplatePartial)
25
38
  view = klass.new
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: 1.0.3
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -11,127 +11,118 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2016-03-24 00:00:00.000000000 Z
14
+ date: 2017-03-26 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - ~>
20
+ - - "~>"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '1.6'
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ~>
27
+ - - "~>"
28
28
  - !ruby/object:Gem::Version
29
29
  version: '1.6'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - ~>
34
+ - - "~>"
35
35
  - !ruby/object:Gem::Version
36
36
  version: '10.3'
37
37
  type: :development
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
- - - ~>
41
+ - - "~>"
42
42
  - !ruby/object:Gem::Version
43
43
  version: '10.3'
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: minitest
46
46
  requirement: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - ~>
48
+ - - "~>"
49
49
  - !ruby/object:Gem::Version
50
50
  version: '5.4'
51
51
  type: :development
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - ~>
55
+ - - "~>"
56
56
  - !ruby/object:Gem::Version
57
57
  version: '5.4'
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: benchmark-ips
60
60
  requirement: !ruby/object:Gem::Requirement
61
61
  requirements:
62
- - - ! '>='
62
+ - - ">="
63
63
  - !ruby/object:Gem::Version
64
64
  version: '0'
65
65
  type: :development
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - ! '>='
69
+ - - ">="
70
70
  - !ruby/object:Gem::Version
71
71
  version: '0'
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: ruby-prof
74
74
  requirement: !ruby/object:Gem::Requirement
75
75
  requirements:
76
- - - ! '>='
76
+ - - ">="
77
77
  - !ruby/object:Gem::Version
78
78
  version: '0'
79
79
  type: :development
80
80
  prerelease: false
81
81
  version_requirements: !ruby/object:Gem::Requirement
82
82
  requirements:
83
- - - ! '>='
83
+ - - ">="
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
86
  - !ruby/object:Gem::Dependency
87
87
  name: rdoc
88
88
  requirement: !ruby/object:Gem::Requirement
89
89
  requirements:
90
- - - ~>
90
+ - - "~>"
91
91
  - !ruby/object:Gem::Version
92
92
  version: '4.1'
93
93
  type: :development
94
94
  prerelease: false
95
95
  version_requirements: !ruby/object:Gem::Requirement
96
96
  requirements:
97
- - - ~>
97
+ - - "~>"
98
98
  - !ruby/object:Gem::Version
99
99
  version: '4.1'
100
100
  - !ruby/object:Gem::Dependency
101
101
  name: ronn
102
102
  requirement: !ruby/object:Gem::Requirement
103
103
  requirements:
104
- - - ~>
104
+ - - "~>"
105
105
  - !ruby/object:Gem::Version
106
106
  version: '0.7'
107
107
  type: :development
108
108
  prerelease: false
109
109
  version_requirements: !ruby/object:Gem::Requirement
110
110
  requirements:
111
- - - ~>
111
+ - - "~>"
112
112
  - !ruby/object:Gem::Version
113
113
  version: '0.7'
114
- description: ! 'Inspired by ctemplate, Mustache is a framework-agnostic way to render
115
-
114
+ description: |
115
+ Inspired by ctemplate, Mustache is a framework-agnostic way to render
116
116
  logic-free views.
117
117
 
118
-
119
118
  As ctemplates says, "It emphasizes separating logic from presentation:
120
-
121
119
  it is impossible to embed application logic in this template
122
-
123
120
  language.
124
121
 
125
-
126
122
  Think of Mustache as a replacement for your views. Instead of views
127
-
128
123
  consisting of ERB or HAML with random helpers and arbitrary logic,
129
-
130
124
  your views are broken into two parts: a Ruby class and an HTML
131
-
132
125
  template.
133
-
134
- '
135
126
  email: rokusu@gmail.com
136
127
  executables:
137
128
  - mustache
@@ -219,17 +210,17 @@ require_paths:
219
210
  - lib
220
211
  required_ruby_version: !ruby/object:Gem::Requirement
221
212
  requirements:
222
- - - ~>
213
+ - - ">="
223
214
  - !ruby/object:Gem::Version
224
215
  version: '2.0'
225
216
  required_rubygems_version: !ruby/object:Gem::Requirement
226
217
  requirements:
227
- - - ! '>='
218
+ - - ">="
228
219
  - !ruby/object:Gem::Version
229
220
  version: '0'
230
221
  requirements: []
231
222
  rubyforge_project:
232
- rubygems_version: 2.5.1
223
+ rubygems_version: 2.6.8
233
224
  signing_key:
234
225
  specification_version: 4
235
226
  summary: Mustache is a framework-agnostic way to render logic-free views.