mustache 1.0.3 → 1.0.5

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 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.