mustache 1.1.1 → 1.1.3

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.
data/man/mustache.5.ron CHANGED
@@ -38,6 +38,12 @@ clauses, or for loops. Instead there are only tags. Some tags are
38
38
  replaced with a value, some nothing, and others a series of
39
39
  values. This document explains the different types of Mustache tags.
40
40
 
41
+ The Mustache language has a [formal specification][spec]. The current
42
+ manpage reflects version 1.3.0 of the specification, including the
43
+ official-but-optional extensions for lambdas and inheritance.
44
+
45
+ [spec]: https://github.com/mustache/spec
46
+
41
47
 
42
48
  ## TAG TYPES
43
49
 
@@ -85,16 +91,113 @@ Output:
85
91
  * <b>GitHub</b>
86
92
  * <b>GitHub</b>
87
93
 
94
+ **Dotted Names**
95
+
96
+ If the `name` contains dots, it is split on the dots to obtain multiple
97
+ keys. The first key is looked up in the context as described above. If it
98
+ is found, the next key is looked up within the previous result. This is
99
+ repeated until a key is not found or until the last key is found. The
100
+ final result is interpolated as above.
101
+
102
+ Template:
103
+
104
+ * {{client.name}}
105
+ * {{age}}
106
+ * {{client.company.name}}
107
+ * {{{company.name}}}
108
+
109
+ Hash:
110
+
111
+ {
112
+ "client": {
113
+ "name": "Chris & Friends",
114
+ "age": 50
115
+ },
116
+ "company": {
117
+ "name": "<b>GitHub</b>"
118
+ }
119
+ }
120
+
121
+ Output:
122
+
123
+ * Chris &amp; Friends
124
+ *
125
+ *
126
+ * <b>GitHub</b>
127
+
128
+ **Implicit Iterator**
129
+
130
+ As a special case, if the `name` consists of only a dot and nothing else,
131
+ the value that is the current context is interpolated as a whole. This
132
+ is especially useful if the parent context is a list; see **Sections**
133
+ below.
134
+
135
+ Template:
136
+
137
+ * {{.}}
138
+
139
+ Current context:
140
+
141
+ "Hello!"
142
+
143
+ Output:
144
+
145
+ * Hello!
146
+
147
+ **Lambdas**
148
+
149
+ If any value found during the lookup is a callable object, such as a
150
+ function or lambda, this object will be invoked with zero arguments. The
151
+ value that is returned is then used instead of the callable object itself.
152
+
153
+ An **optional** part of the specification states that if the final key in
154
+ the `name` is a lambda that returns a string, then that string should be
155
+ rendered as a Mustache template before interpolation. It will be rendered
156
+ using the default delimiters (see **Set Delimiter** below) against the
157
+ current context.
158
+
159
+ Template:
160
+
161
+ * {{time.hour}}
162
+ * {{today}}
163
+
164
+ Hash:
165
+
166
+ {
167
+ "year": 1970,
168
+ "month": 1,
169
+ "day": 1,
170
+ "time": function() {
171
+ return {
172
+ "hour": 0,
173
+ "minute": 0,
174
+ "second": 0
175
+ }
176
+ },
177
+ "today": function() {
178
+ return "{{year}}-{{month}}-{{day}}"
179
+ }
180
+ }
181
+
182
+ Output:
183
+
184
+ * 0
185
+ * 1970-1-1
186
+
88
187
 
89
188
  ### Sections
90
189
 
91
190
  Sections render blocks of text zero or more times, depending on the
92
191
  value of the key in the current context.
93
192
 
193
+ Lookup of dotted names works in the same way as with variables, except for
194
+ slightly different treatment of lambdas. More on this below.
195
+
94
196
  A section begins with a pound and ends with a slash. That is,
95
197
  `{{#person}}` begins a "person" section while `{{/person}}` ends it.
96
198
 
97
- The behavior of the section is determined by the value of the key.
199
+ The behavior of the section is determined by the final value of the key
200
+ lookup.
98
201
 
99
202
  **False Values or Empty Lists**
100
203
 
@@ -120,7 +223,7 @@ Output:
120
223
 
121
224
  **Non-Empty Lists**
122
225
 
123
- If the `person` key exists and has a non-false value, the HTML between
226
+ If the `repo` key exists and has a non-false value, the HTML between
124
227
  the pound and slash will be rendered and displayed one or more times.
125
228
 
126
229
  When the value is a non-empty list, the text in the block will be
@@ -146,32 +249,54 @@ Hash:
146
249
 
147
250
  Output:
148
251
 
149
- <b>resque</b>
150
- <b>hub</b>
151
- <b>rip</b>
252
+ <b>resque</b>
253
+ <b>hub</b>
254
+ <b>rip</b>
255
+
256
+ The same effect as above can be obtained without nested objects, by using
257
+ the implicit iterator (see **Variables** above).
258
+
259
+ Template:
260
+
261
+ {{#repo}}
262
+ <b>{{.}}</b>
263
+ {{/repo}}
264
+
265
+ Hash:
266
+
267
+ {
268
+ "repo": ["resque", "hub", "rip"]
269
+ }
270
+
271
+ Output:
272
+
273
+ <b>resque</b>
274
+ <b>hub</b>
275
+ <b>rip</b>
152
276
 
153
277
  **Lambdas**
154
278
 
155
- When the value is a callable object, such as a function or lambda, the
156
- object will be invoked and passed the block of text. The text passed
157
- is the literal block, unrendered. `{{tags}}` will not have been expanded
158
- - the lambda should do that on its own. In this way you can implement
159
- filters or caching.
279
+ When any value found during the lookup is a callable object, such as a
280
+ function or lambda, the object will be invoked and passed the block of
281
+ text. The text passed is the literal block, unrendered. `{{tags}}` will
282
+ not have been expanded.
283
+
284
+ An **optional** part of the specification states that if the final key in
285
+ the `name` is a lambda that returns a string, then that string replaces
286
+ the content of the section. It will be rendered using the same delimiters
287
+ (see **Set Delimiter** below) as the original section content. In this way
288
+ you can implement filters or caching.
160
289
 
161
290
  Template:
162
291
 
163
- {{#wrapped}}
164
- {{name}} is awesome.
165
- {{/wrapped}}
292
+ {{#wrapped}}{{name}} is awesome.{{/wrapped}}
166
293
 
167
294
  Hash:
168
295
 
169
296
  {
170
297
  "name": "Willy",
171
- "wrapped": function() {
172
- return function(text, render) {
173
- return "<b>" + render(text) + "</b>"
174
- }
298
+ "wrapped": function(text) {
299
+ return "<b>" + text + "</b>"
175
300
  }
176
301
  }
177
302
 
@@ -198,7 +323,7 @@ Hash:
198
323
 
199
324
  Output:
200
325
 
201
- Hi Jon!
326
+ Hi Jon!
202
327
 
203
328
 
204
329
  ### Inverted Sections
@@ -229,7 +354,7 @@ Hash:
229
354
 
230
355
  Output:
231
356
 
232
- No repos :(
357
+ No repos :(
233
358
 
234
359
 
235
360
  ### Comments
@@ -286,6 +411,139 @@ Can be thought of as a single, expanded template:
286
411
  {{/names}}
287
412
 
288
413
 
414
+ **Dynamic Names**
415
+
416
+ Partials can be loaded dynamically at runtime using Dynamic Names; an
417
+ **optional** part of the Mustache specification which allows to dynamically
418
+ determine a tag's content at runtime.
419
+
420
+ Dynamic Names consists of an asterisk, followed by a dotted name which follows
421
+ the same notation and the same resolution as in an variable tag. That is
422
+ `{{>*dynamic}}`. It can be thought as the following **hypothetical** tag
423
+ (which is **not allowed**!): `{{>{{dynamic}}}}`.
424
+
425
+ Templates:
426
+
427
+ main.mustache:
428
+ Hello {{>*dynamic}}
429
+
430
+ world.template:
431
+ everyone!
432
+
433
+ Hash:
434
+
435
+ {
436
+ "dynamic": "world"
437
+ }
438
+
439
+ Output:
440
+
441
+ Hello everyone!
442
+
443
+
444
+ ### Blocks
445
+
446
+ A block begins with a dollar and ends with a slash. That is, `{{$title}}`
447
+ begins a "title" block and `{{/title}}` ends it.
448
+
449
+ Blocks mark parts of the template that may be overridden. This can be done
450
+ with a block of the same name within a parent section in the calling
451
+ template (see **Parents** below). If not overridden, the contents of a
452
+ block render just as if the `{{$title}}` and `{{/title}}` tags weren't
453
+ there.
454
+
455
+ Blocks could be thought of as template parameters or as inline partials
456
+ that may be passed to another template. They are part of the optional
457
+ inheritance extension.
458
+
459
+ Template `article.mustache`:
460
+
461
+ <h1>{{$title}}The News of Today{{/title}}</h1>
462
+ {{$body}}
463
+ <p>Nothing special happened.</p>
464
+ {{/body}}
465
+
466
+ Output:
467
+
468
+ <h1>The News of Today</h1>
469
+ <p>Nothing special happened.</p>
470
+
471
+
472
+ ### Parents
473
+
474
+ A parent begins with a less than sign and ends with a slash. That is,
475
+ `{{<article}}` begins an "article" parent and `{{/article}}` ends it.
476
+
477
+ Like an `{{>article}}` partial, a parent lets you expand another template
478
+ inside the current one. Unlike a partial, a parent also lets you override
479
+ blocks of the other template.
480
+
481
+ Blocks within a parent can again be overridden by another including
482
+ template. Other content within a parent is ignored, like comments.
483
+
484
+ Template:
485
+
486
+ {{<article}}
487
+ Never shown
488
+ {{$body}}
489
+ {{#headlines}}
490
+ <p>{{.}}</p>
491
+ {{/headlines}}
492
+ {{/body}}
493
+ {{/article}}
494
+
495
+ {{<article}}
496
+ {{$title}}Yesterday{{/title}}
497
+ {{/article}}
498
+
499
+ Hash:
500
+
501
+ {
502
+ "headlines": [
503
+ "A pug's handler grew mustaches.",
504
+ "What an exciting day!"
505
+ ]
506
+ }
507
+
508
+ Output, assuming the `article.mustache` from before:
509
+
510
+ <h1>The News of Today</h1>
511
+ <p>A pug's handler grew mustaches.</p>
512
+ <p>What an exciting day!</p>
513
+
514
+ <h1>Yesterday</h1>
515
+ <p>Nothing special happened.</p>
516
+
517
+ **Dynamic Names**
518
+
519
+ Some mustache implementations may allow the use of Dynamic Names in
520
+ parent tags, similar to dynamic names in partials. Here's an example of
521
+ how Dynamic Names in parent tags work.
522
+
523
+ Templates:
524
+
525
+ {{!normal.mustache}}
526
+ {{$text}}Here goes nothing.{{/text}}
527
+
528
+ {{!bold.mustache}}
529
+ <b>{{$text}}Here also goes nothing but it's bold.{{/text}}</b>
530
+
531
+ {{!dynamic.mustache}}
532
+ {{<*dynamic}}
533
+ {{$text}}Hello World!{{/text}}
534
+ {{/*dynamic}}
535
+
536
+ Hash:
537
+
538
+ {
539
+ "dynamic": "bold"
540
+ }
541
+
542
+ Output:
543
+
544
+ <b>Hello World!</b>
545
+
546
+
289
547
  ### Set Delimiter
290
548
 
291
549
  Set Delimiter tags start with an equal sign and change the tag
@@ -7,6 +7,11 @@ class AutoloadingTest < Minitest::Test
7
7
  Mustache.view_path = File.dirname(__FILE__) + '/fixtures'
8
8
  end
9
9
 
10
+ # Restore `view_namespace` to the default value
11
+ def teardown
12
+ Mustache.view_namespace = Object
13
+ end
14
+
10
15
  def test_autoload
11
16
  klass = Mustache.view_class(:Comments)
12
17
  assert_equal Comments, klass
@@ -0,0 +1,6 @@
1
+ <VirtualHost *>
2
+ ServerAdmin override@mustache.com
3
+ ServerName {{server}}
4
+ DocumentRoot {{deploy_to}}
5
+ RailsEnv {{stage}}
6
+ </VirtualHost>
@@ -66,6 +66,14 @@ end_complex
66
66
  instance.render
67
67
  end
68
68
 
69
+ def test_empty_string_as_section_does_not_render_inverted
70
+ instance = Mustache.new
71
+ instance[:value] = ""
72
+ instance.template = "{{#value}}Value Found{{/value}}{{^value}}Value Not Found{{/value}}"
73
+
74
+ assert_equal "Value Found", instance.render
75
+ end
76
+
69
77
  def test_sassy_single_line_sections
70
78
  instance = Mustache.new
71
79
  instance[:full_time] = true
@@ -726,14 +734,17 @@ text
726
734
  base = Class.new(Mustache)
727
735
  tmpl = Class.new(base)
728
736
 
729
- {:template_path => File.expand_path('./foo'),
730
- :template_extension => 'stache',
737
+ {:template_extension => 'stache',
731
738
  :view_namespace => TestNamespace,
732
739
  :view_path => './foo'
733
740
  }.each do |attr, value|
734
741
  base.send("#{attr}=", value)
735
742
  assert_equal value, tmpl.send(attr)
736
743
  end
744
+ attr = :template_path
745
+ value = File.expand_path('./foo')
746
+ base.send("#{attr}=", value)
747
+ assert_equal value, tmpl.send(attr).first
737
748
  end
738
749
 
739
750
  def test_hash_default_proc
@@ -841,4 +852,11 @@ template
841
852
  klass.template = "Hi {{name}}!"
842
853
  assert_equal "Hi Dougal!", klass.new("Dougal").render
843
854
  end
855
+
856
+ def test_variable_with_at_name
857
+ instance = Mustache.new
858
+ instance.template = "\t{{#list@home}}a{{/list@home}}"
859
+
860
+ assert_equal "\taa", instance.render(:"list@home" => [1, 2])
861
+ end
844
862
  end
data/test/path_test.rb ADDED
@@ -0,0 +1,49 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative 'helper'
3
+
4
+ class MustacheTest < Minitest::Test
5
+
6
+ def test_default_path
7
+ assert_instance_of Array, Mustache.template_path
8
+ assert_equal 1, Mustache.template_path.size
9
+ assert_includes Mustache.template_path, Dir.pwd
10
+ end
11
+
12
+ def test_set_multiple_paths
13
+ old_path = Mustache.template_path
14
+ Mustache.template_path = "this#{File::PATH_SEPARATOR}that"
15
+ assert_instance_of Array, Mustache.template_path
16
+ assert_equal 2, Mustache.template_path.size
17
+ Mustache.template_path = old_path
18
+ end
19
+
20
+ def test_override_found
21
+
22
+ expected = <<-data
23
+ <VirtualHost *>
24
+ ServerAdmin override@mustache.com
25
+ ServerName example.com
26
+ DocumentRoot /var/www/example.com
27
+ RailsEnv production
28
+ </VirtualHost>
29
+ data
30
+ old_path = Mustache.template_path
31
+ old_extension = Mustache.template_extension
32
+
33
+ begin
34
+ base = File.dirname(__FILE__)
35
+ Mustache.template_extension = "conf"
36
+ Mustache.template_path = "#{base}/fixtures/override:#{base}/fixtures"
37
+ assert_equal expected, Mustache.render(:passenger, :stage => 'production',
38
+ :server => 'example.com',
39
+ :deploy_to => '/var/www/example.com')
40
+ Mustache.template_path = "#{base}/fixtures:#{base}/fixtures/override"
41
+ refute_equal expected, Mustache.render(:passenger, :stage => 'production',
42
+ :server => 'example.com',
43
+ :deploy_to => '/var/www/example.com')
44
+ ensure
45
+ Mustache.template_path, Mustache.template_extension = old_path, old_extension
46
+ end
47
+ end
48
+
49
+ end
metadata CHANGED
@@ -1,116 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mustache
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
8
8
  - Magnus Holm
9
9
  - Pieter van de Bruggen
10
10
  - Ricardo Mendes
11
- autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2019-12-03 00:00:00.000000000 Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: bundler
18
- requirement: !ruby/object:Gem::Requirement
19
- requirements:
20
- - - "~>"
21
- - !ruby/object:Gem::Version
22
- version: '1.6'
23
- type: :development
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '1.6'
30
- - !ruby/object:Gem::Dependency
31
- name: rake
32
- requirement: !ruby/object:Gem::Requirement
33
- requirements:
34
- - - "~>"
35
- - !ruby/object:Gem::Version
36
- version: '10.3'
37
- type: :development
38
- prerelease: false
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - "~>"
42
- - !ruby/object:Gem::Version
43
- version: '10.3'
44
- - !ruby/object:Gem::Dependency
45
- name: minitest
46
- requirement: !ruby/object:Gem::Requirement
47
- requirements:
48
- - - "~>"
49
- - !ruby/object:Gem::Version
50
- version: '5.4'
51
- type: :development
52
- prerelease: false
53
- version_requirements: !ruby/object:Gem::Requirement
54
- requirements:
55
- - - "~>"
56
- - !ruby/object:Gem::Version
57
- version: '5.4'
58
- - !ruby/object:Gem::Dependency
59
- name: benchmark-ips
60
- requirement: !ruby/object:Gem::Requirement
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- version: '0'
65
- type: :development
66
- prerelease: false
67
- version_requirements: !ruby/object:Gem::Requirement
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- version: '0'
72
- - !ruby/object:Gem::Dependency
73
- name: ruby-prof
74
- requirement: !ruby/object:Gem::Requirement
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- version: '0'
79
- type: :development
80
- prerelease: false
81
- version_requirements: !ruby/object:Gem::Requirement
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- version: '0'
86
- - !ruby/object:Gem::Dependency
87
- name: rdoc
88
- requirement: !ruby/object:Gem::Requirement
89
- requirements:
90
- - - "~>"
91
- - !ruby/object:Gem::Version
92
- version: '4.1'
93
- type: :development
94
- prerelease: false
95
- version_requirements: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - "~>"
98
- - !ruby/object:Gem::Version
99
- version: '4.1'
100
- - !ruby/object:Gem::Dependency
101
- name: ronn
102
- requirement: !ruby/object:Gem::Requirement
103
- requirements:
104
- - - "~>"
105
- - !ruby/object:Gem::Version
106
- version: '0.7'
107
- type: :development
108
- prerelease: false
109
- version_requirements: !ruby/object:Gem::Requirement
110
- requirements:
111
- - - "~>"
112
- - !ruby/object:Gem::Version
113
- version: '0.7'
13
+ date: 2026-08-20 00:00:00.000000000 Z
14
+ dependencies: []
114
15
  description: |
115
16
  Inspired by ctemplate, Mustache is a framework-agnostic way to render
116
17
  logic-free views.
@@ -178,6 +79,7 @@ files:
178
79
  - test/fixtures/nested_objects.mustache
179
80
  - test/fixtures/nested_objects.rb
180
81
  - test/fixtures/node.mustache
82
+ - test/fixtures/override/passenger.conf
181
83
  - test/fixtures/partial_with_module.mustache
182
84
  - test/fixtures/partial_with_module.rb
183
85
  - test/fixtures/passenger.conf
@@ -198,13 +100,13 @@ files:
198
100
  - test/mustache_test.rb
199
101
  - test/parser_test.rb
200
102
  - test/partial_test.rb
103
+ - test/path_test.rb
201
104
  - test/spec_test.rb
202
105
  - test/template_test.rb
203
106
  homepage: https://github.com/mustache/mustache
204
107
  licenses:
205
108
  - MIT
206
109
  metadata: {}
207
- post_install_message:
208
110
  rdoc_options: []
209
111
  require_paths:
210
112
  - lib
@@ -219,8 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
121
  - !ruby/object:Gem::Version
220
122
  version: '0'
221
123
  requirements: []
222
- rubygems_version: 3.0.3
223
- signing_key:
124
+ rubygems_version: 3.6.9
224
125
  specification_version: 4
225
126
  summary: Mustache is a framework-agnostic way to render logic-free views.
226
127
  test_files: []