mustache 1.1.2 → 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.
- checksums.yaml +4 -4
- data/README.md +6 -5
- data/Rakefile +1 -1
- data/bin/mustache +6 -1
- data/lib/mustache/context.rb +21 -0
- data/lib/mustache/context_miss.rb +41 -0
- data/lib/mustache/generator.rb +1 -1
- data/lib/mustache/parser.rb +1 -1
- data/lib/mustache/settings.rb +59 -22
- data/lib/mustache/version.rb +1 -1
- data/lib/mustache.rb +4 -7
- data/man/mustache.5 +2 -1
- data/man/mustache.5.html +1 -1
- data/man/mustache.5.ron +1 -1
- data/test/autoloading_test.rb +5 -0
- data/test/fixtures/override/passenger.conf +6 -0
- data/test/mustache_test.rb +20 -2
- data/test/path_test.rb +49 -0
- metadata +6 -105
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf066480926aaca95b8ebbb4e45de15a11cae753e407be03a8059bee4deb9837
|
|
4
|
+
data.tar.gz: a334278f764909eb095bed8bf31132af6c61d6dffadbf5688cd745e85517a7a6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 571c5ff585457d1073fa4de0d506073b55a7c3409967d39a488b71fe38b03e7074312ad5e9e379d0f654043dc8be7ffdba4e1cb3b6df4ba6e884920885064ecd
|
|
7
|
+
data.tar.gz: cb3b39d80301b99e13e4cf412e5da3065ecf5215d7b7bece535c032e6cec5c452a0d44f43363d4d35a06a2267e67945325c177ae8631f8b19bac8f344fad2768
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Mustache
|
|
2
2
|
|
|
3
3
|
[](http://badge.fury.io/rb/mustache)
|
|
4
|
-
[](https://github.com/mustache/mustache/actions/workflows/test.yml)
|
|
5
5
|
|
|
6
6
|
Inspired by [ctemplate][1] and [et][2], Mustache is a
|
|
7
7
|
framework-agnostic way to render logic-free views.
|
|
@@ -166,8 +166,9 @@ follows the classic Ruby naming convention.
|
|
|
166
166
|
|
|
167
167
|
TemplatePartial => ./template_partial.mustache
|
|
168
168
|
|
|
169
|
-
You can set the search path using `Mustache.template_path`.
|
|
170
|
-
|
|
169
|
+
You can set the search path using `Mustache.template_path`. Search multiple
|
|
170
|
+
paths by delimiting them with your platform's 'path separator' (colon on Unix).
|
|
171
|
+
It can be set on a class by class basis:
|
|
171
172
|
|
|
172
173
|
```ruby
|
|
173
174
|
class Simple < Mustache
|
|
@@ -381,9 +382,9 @@ Once you've made your great commits:
|
|
|
381
382
|
|
|
382
383
|
~~To join the list simply send an email to <mustache@librelist.com>. This
|
|
383
384
|
will subscribe you and send you information about your subscription,
|
|
384
|
-
including unsubscribe information
|
|
385
|
+
including unsubscribe information.~~
|
|
385
386
|
|
|
386
|
-
The archive can be found at <http://librelist.com/browser/mustache/>.~~
|
|
387
|
+
~~The archive can be found at <http://librelist.com/browser/mustache/>.~~
|
|
387
388
|
|
|
388
389
|
The mailing list hasn't been updated in quite a while, please join us on Gitter
|
|
389
390
|
or IRC:
|
data/Rakefile
CHANGED
data/bin/mustache
CHANGED
|
@@ -11,7 +11,7 @@ class Mustache
|
|
|
11
11
|
# Return a structure describing the options.
|
|
12
12
|
def self.parse_options(args)
|
|
13
13
|
opts = OptionParser.new do |opts|
|
|
14
|
-
opts.banner = "Usage: mustache [-c] [-t] [-e] [-r library] FILE ..."
|
|
14
|
+
opts.banner = "Usage: mustache [-c] [-t] [-l level] [-e] [-r library] FILE ..."
|
|
15
15
|
|
|
16
16
|
opts.separator " "
|
|
17
17
|
|
|
@@ -42,6 +42,11 @@ class Mustache
|
|
|
42
42
|
exit
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
opts.on("-l", "--level",
|
|
46
|
+
"Provide a context access security level.") do |level|
|
|
47
|
+
Mustache.context_access_security_level = level.to_i
|
|
48
|
+
end
|
|
49
|
+
|
|
45
50
|
opts.on("-e", "--error",
|
|
46
51
|
"Raise an error on context misses.") do |e|
|
|
47
52
|
Mustache.raise_on_context_miss = true
|
data/lib/mustache/context.rb
CHANGED
|
@@ -136,14 +136,35 @@ class Mustache
|
|
|
136
136
|
# @return [Object] The value of key in object if it is found, and default otherwise.
|
|
137
137
|
#
|
|
138
138
|
def find(obj, key, default = nil)
|
|
139
|
+
|
|
140
|
+
if mustache_in_stack.context_access_security_level == 5 and !obj.instance_of?(Hash)
|
|
141
|
+
# on level 5, object must be exactly Hash
|
|
142
|
+
return context_level_violation("Detected key access attempt for a non-Hash object using '#{key}'", default)
|
|
143
|
+
end
|
|
144
|
+
|
|
139
145
|
return find_in_hash(obj.to_hash, key, default) if obj.respond_to?(:to_hash)
|
|
140
146
|
|
|
147
|
+
if mustache_in_stack.context_access_security_level >= 4
|
|
148
|
+
# on levels 4 and 5, method access is not allowed
|
|
149
|
+
return context_level_violation("Detected method access attempt using '#{key}'", default)
|
|
150
|
+
end
|
|
151
|
+
|
|
141
152
|
unless obj.respond_to?(key)
|
|
142
153
|
# no match for the key, but it may include a hyphen, so try again replacing hyphens with underscores.
|
|
143
154
|
key = key.to_s.tr('-', '_')
|
|
144
155
|
return default unless obj.respond_to?(key)
|
|
145
156
|
end
|
|
146
157
|
|
|
158
|
+
if mustache_in_stack.context_access_security_level >= 3 && !obj.class.instance_methods(false).include?(key.to_sym)
|
|
159
|
+
# on level 3, inherited methods are blocked
|
|
160
|
+
return context_level_violation("Detected inherited method '#{key}'", default)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if mustache_in_stack.context_access_security_level >= 2 && MethodBlacklist.include?(key.to_s)
|
|
164
|
+
# on levels 2 and 3, reflection-based methods are blacklisted
|
|
165
|
+
return context_level_violation("Detected blacklisted reflection-related key '#{key}'", default)
|
|
166
|
+
end
|
|
167
|
+
|
|
147
168
|
meth = obj.method(key) rescue proc { obj.send(key) }
|
|
148
169
|
meth.arity == 1 ? meth.to_proc : meth.call
|
|
149
170
|
end
|
|
@@ -11,4 +11,45 @@ class Mustache
|
|
|
11
11
|
#
|
|
12
12
|
class ContextMiss < RuntimeError; end
|
|
13
13
|
|
|
14
|
+
# A ContextLevelViolation is raised whenever accessing a key in the context is
|
|
15
|
+
# not allowed by the selected context access security level
|
|
16
|
+
#
|
|
17
|
+
# For example, if your context access security level is set to 3 but
|
|
18
|
+
# your template tries to access an inherited method this exception will be raised.
|
|
19
|
+
#
|
|
20
|
+
# By default it is only raised for blacklisted keys in objects.
|
|
21
|
+
# See Mustache.context_access_security_level.
|
|
22
|
+
#
|
|
23
|
+
class ContextLevelViolation < ContextMiss; end
|
|
24
|
+
|
|
25
|
+
class Context
|
|
26
|
+
# Raises ContextLevelViolation or returns default depending on raise_on_context_miss
|
|
27
|
+
#
|
|
28
|
+
# @param [String] message The error message if raise_on_context_miss is set
|
|
29
|
+
# @param [Object] default An optional default value, to return if the key is not found.
|
|
30
|
+
#
|
|
31
|
+
# @return [Object] The default value if errors are not raised
|
|
32
|
+
#
|
|
33
|
+
def context_level_violation(message, default = nil)
|
|
34
|
+
return default unless mustache_in_stack.raise_on_context_miss?
|
|
35
|
+
raise ContextLevelViolation.new(message)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
MethodBlacklist = ["allocate", "attached_object", "superclass", "subclasses", "new", "autoload?", "autoload",
|
|
41
|
+
"included_modules", "include?", "set_temporary_name", "ancestors", "attr", "attr_reader", "attr_writer",
|
|
42
|
+
"attr_accessor", "public_instance_method", "instance_methods", "public_instance_methods",
|
|
43
|
+
"protected_instance_methods", "private_instance_methods", "undefined_instance_methods", "freeze", "const_get",
|
|
44
|
+
"constants", "const_missing", "const_defined?", "const_set", "const_source_location", "remove_class_variable",
|
|
45
|
+
"class_variable_get", "class_variables", "private_constant", "class_variable_set", "class_variable_defined?",
|
|
46
|
+
"public_constant", "include", "deprecate_constant", "singleton_class?", "prepend", "refinements", "define_method",
|
|
47
|
+
"module_exec", "class_exec", "module_eval", "class_eval", "remove_method", "undef_method", "alias_method",
|
|
48
|
+
"method_defined?", "public_method_defined?", "private_method_defined?", "protected_method_defined?",
|
|
49
|
+
"public_class_method", "private_class_method", "instance_method", "singleton_class", "dup", "itself", "methods",
|
|
50
|
+
"singleton_methods", "protected_methods", "private_methods", "public_methods", "instance_variables",
|
|
51
|
+
"instance_variable_get", "instance_variable_set", "instance_variable_defined?", "remove_instance_variable",
|
|
52
|
+
"instance_of?", "kind_of?", "is_a?", "display", "public_send", "extend", "clone", "class", "frozen?", "tap",
|
|
53
|
+
"then", "yield_self", "respond_to?", "method", "public_method", "singleton_method", "define_singleton_method",
|
|
54
|
+
"hash", "object_id", "send", "enum_for", "__send__", "instance_eval", "instance_exec", "__id__"]
|
|
14
55
|
end
|
data/lib/mustache/generator.rb
CHANGED
|
@@ -151,7 +151,7 @@ class Mustache
|
|
|
151
151
|
# what's inside.
|
|
152
152
|
ev(<<-compiled)
|
|
153
153
|
v = #{compile!(name)}
|
|
154
|
-
if v.nil? || v == false || v.respond_to?(:empty?) && v.empty?
|
|
154
|
+
if v.nil? || v == false || (v.class != String && v.respond_to?(:empty?) && v.empty?)
|
|
155
155
|
#{code}
|
|
156
156
|
end
|
|
157
157
|
compiled
|
data/lib/mustache/parser.rb
CHANGED
|
@@ -78,7 +78,7 @@ EOF
|
|
|
78
78
|
SKIP_WHITESPACE = [ '#', '^', '/', '<', '>', '=', '!' ].map(&:freeze)
|
|
79
79
|
|
|
80
80
|
# The content allowed in a tag name.
|
|
81
|
-
ALLOWED_CONTENT = /(\w|[
|
|
81
|
+
ALLOWED_CONTENT = /(\w|[?!\/.@-])*/
|
|
82
82
|
|
|
83
83
|
# These types of tags allow any content,
|
|
84
84
|
# the rest only allow ALLOWED_CONTENT.
|
data/lib/mustache/settings.rb
CHANGED
|
@@ -9,6 +9,7 @@ class Mustache
|
|
|
9
9
|
@template_name = nil
|
|
10
10
|
@template_file = nil
|
|
11
11
|
@raise_on_context_miss = nil
|
|
12
|
+
@context_access_security_level = 2
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def self.initialize_settings
|
|
@@ -18,6 +19,7 @@ class Mustache
|
|
|
18
19
|
@template_name = nil
|
|
19
20
|
@template_file = nil
|
|
20
21
|
@raise_on_context_miss = nil
|
|
22
|
+
@context_access_security_level = 2
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
initialize_settings
|
|
@@ -31,38 +33,43 @@ class Mustache
|
|
|
31
33
|
#
|
|
32
34
|
|
|
33
35
|
# The template path informs your Mustache view where to look for its
|
|
34
|
-
# corresponding template.
|
|
36
|
+
# corresponding template. It is an array of paths, by default containing
|
|
37
|
+
# one entry: the current directory (".")
|
|
38
|
+
# When setting up from a string, use path delimiters to create a search path
|
|
39
|
+
# When the template_file is requested, a search is done to find the file in the
|
|
40
|
+
# path, this is then stored as the name.
|
|
35
41
|
#
|
|
36
42
|
# A class named Stat with a template_path of "app/templates" will look
|
|
37
43
|
# for "app/templates/stat.mustache"
|
|
38
44
|
|
|
45
|
+
def self.setup_path path
|
|
46
|
+
path = path.split(File::PATH_SEPARATOR) if path.is_a? String
|
|
47
|
+
path.map{|p| File.expand_path(p)}
|
|
48
|
+
end
|
|
49
|
+
|
|
39
50
|
def self.template_path
|
|
40
|
-
@template_path ||= inheritable_config_for
|
|
51
|
+
@template_path ||= setup_path(inheritable_config_for(:template_path, '.'))
|
|
41
52
|
end
|
|
42
53
|
|
|
43
54
|
def self.template_path=(path)
|
|
44
|
-
@template_path =
|
|
55
|
+
@template_path = setup_path(path)
|
|
45
56
|
@template = nil
|
|
46
57
|
end
|
|
47
58
|
|
|
48
59
|
def template_path
|
|
49
60
|
@template_path ||= self.class.template_path
|
|
50
61
|
end
|
|
62
|
+
|
|
51
63
|
alias_method :path, :template_path
|
|
52
64
|
|
|
53
65
|
def template_path=(path)
|
|
54
|
-
@template_path =
|
|
66
|
+
@template_path = self.class.setup_path(path)
|
|
55
67
|
@template = nil
|
|
56
68
|
end
|
|
57
69
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
template_path
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Alias for `template_path`
|
|
64
|
-
def self.path=(path)
|
|
65
|
-
self.template_path = path
|
|
70
|
+
class << self
|
|
71
|
+
alias_method :path, :template_path
|
|
72
|
+
alias_method :path=, :template_path=
|
|
66
73
|
end
|
|
67
74
|
|
|
68
75
|
|
|
@@ -128,26 +135,25 @@ class Mustache
|
|
|
128
135
|
# Template File
|
|
129
136
|
#
|
|
130
137
|
|
|
131
|
-
# The template file is the absolute path of the file Mustache will
|
|
132
|
-
#
|
|
138
|
+
# The template file is the absolute path of the file Mustache will use as its template.
|
|
139
|
+
# By default it's ./class_name.mustache
|
|
140
|
+
#
|
|
133
141
|
|
|
134
142
|
def self.template_file
|
|
135
|
-
@template_file || "#{
|
|
143
|
+
@template_file || path.map{|p| "#{p}/#{template_name}.#{template_extension}" }.find{|tf| File.readable? tf}
|
|
136
144
|
end
|
|
137
145
|
|
|
138
|
-
def self.template_file=(
|
|
139
|
-
@template_file =
|
|
146
|
+
def self.template_file=(tf)
|
|
147
|
+
@template_file = tf
|
|
140
148
|
@template = nil
|
|
141
149
|
end
|
|
142
150
|
|
|
143
|
-
# The template file is the absolute path of the file Mustache will
|
|
144
|
-
# use as its template. By default it's ./class_name.mustache
|
|
145
151
|
def template_file
|
|
146
|
-
@template_file || "#{
|
|
152
|
+
@template_file || path.map{|p| "#{p}/#{template_name}.#{template_extension}" }.find{|tf| File.readable? tf}
|
|
147
153
|
end
|
|
148
154
|
|
|
149
|
-
def template_file=(
|
|
150
|
-
@template_file =
|
|
155
|
+
def template_file=(tf)
|
|
156
|
+
@template_file = tf
|
|
151
157
|
@template = nil
|
|
152
158
|
end
|
|
153
159
|
|
|
@@ -214,6 +220,37 @@ class Mustache
|
|
|
214
220
|
@raise_on_context_miss = boolean
|
|
215
221
|
end
|
|
216
222
|
|
|
223
|
+
#
|
|
224
|
+
# Context access security level
|
|
225
|
+
#
|
|
226
|
+
|
|
227
|
+
# What object methods could be accessed from the template?
|
|
228
|
+
# This level determines the security restrictions for method access to protect against unsafe reflection
|
|
229
|
+
# Possible values are integers from 1 to 5:
|
|
230
|
+
#
|
|
231
|
+
# 1 - All methods allowed (use only with trusted templates)
|
|
232
|
+
# 2 - Reflection-related methods are blacklisted (default)
|
|
233
|
+
# 3 - All inherited or reflection-related methods are prohibited
|
|
234
|
+
# 4 - Access allowed only for Hash elements
|
|
235
|
+
# 5 - Access allowed only for Hash elements, only numbers, strings, hashes and functions allowed
|
|
236
|
+
|
|
237
|
+
def self.context_access_security_level
|
|
238
|
+
@context_access_security_level
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def self.context_access_security_level=(integer)
|
|
242
|
+
@context_access_security_level = integer
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Instance level version of `Mustache.context_access_security_level`
|
|
246
|
+
def context_access_security_level
|
|
247
|
+
self.class.context_access_security_level || @context_access_security_level
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def context_access_security_level=(integer)
|
|
251
|
+
@context_access_security_level = integer
|
|
252
|
+
end
|
|
253
|
+
|
|
217
254
|
|
|
218
255
|
#
|
|
219
256
|
# View Namespace
|
data/lib/mustache/version.rb
CHANGED
data/lib/mustache.rb
CHANGED
|
@@ -187,14 +187,11 @@ class Mustache
|
|
|
187
187
|
# reading templates from a database. It will be rendered by the
|
|
188
188
|
# context, so all you need to do is return a string.
|
|
189
189
|
def partial(name)
|
|
190
|
-
|
|
190
|
+
partialpath = template_path.map{|p| "#{p}/#{name}.#{template_extension}" }.find{|pf| File.readable? pf}
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
raise if raise_on_context_miss?
|
|
196
|
-
""
|
|
197
|
-
end
|
|
192
|
+
raise RuntimeError.new("Can't find partial #{name}") if not partialpath and raise_on_context_miss?
|
|
193
|
+
|
|
194
|
+
partialpath ? File.read(partialpath) : ""
|
|
198
195
|
end
|
|
199
196
|
|
|
200
197
|
# Override this to provide custom escaping.
|
data/man/mustache.5
CHANGED
|
@@ -229,7 +229,8 @@ Shown\.
|
|
|
229
229
|
.P
|
|
230
230
|
\fBNon\-Empty Lists\fR
|
|
231
231
|
.P
|
|
232
|
-
If the \
|
|
232
|
+
If the \fBrepo\fR key exists and has a non\-false value, the HTML between the pound and slash will be rendered and displayed one or more times\.
|
|
233
|
+
.
|
|
233
234
|
.P
|
|
234
235
|
When the value is a non\-empty list, the text in the block will be displayed once for each item in the list\. The context of the block will be set to the current item for each iteration\. In this way we can loop over collections\.
|
|
235
236
|
.P
|
data/man/mustache.5.html
CHANGED
|
@@ -307,7 +307,7 @@ list, the HTML between the pound and slash will not be displayed.</p>
|
|
|
307
307
|
|
|
308
308
|
<p><strong>Non-Empty Lists</strong></p>
|
|
309
309
|
|
|
310
|
-
<p>If the <code>
|
|
310
|
+
<p>If the <code>repo</code> key exists and has a non-false value, the HTML between
|
|
311
311
|
the pound and slash will be rendered and displayed one or more times.</p>
|
|
312
312
|
|
|
313
313
|
<p>When the value is a non-empty list, the text in the block will be
|
data/man/mustache.5.ron
CHANGED
|
@@ -223,7 +223,7 @@ Output:
|
|
|
223
223
|
|
|
224
224
|
**Non-Empty Lists**
|
|
225
225
|
|
|
226
|
-
If the `
|
|
226
|
+
If the `repo` key exists and has a non-false value, the HTML between
|
|
227
227
|
the pound and slash will be rendered and displayed one or more times.
|
|
228
228
|
|
|
229
229
|
When the value is a non-empty list, the text in the block will be
|
data/test/autoloading_test.rb
CHANGED
|
@@ -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
|
data/test/mustache_test.rb
CHANGED
|
@@ -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
|
-
{:
|
|
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.
|
|
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: 2026-
|
|
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.
|
|
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: []
|