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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e598c073f543841b69a2384f922a006d8f30ea469b59ffb7400ce6a16970a58
4
- data.tar.gz: 824baa455f2eeaab4952424cbf84e88eb983ef4559d1a78e27caf2f249d0200d
3
+ metadata.gz: bf066480926aaca95b8ebbb4e45de15a11cae753e407be03a8059bee4deb9837
4
+ data.tar.gz: a334278f764909eb095bed8bf31132af6c61d6dffadbf5688cd745e85517a7a6
5
5
  SHA512:
6
- metadata.gz: '02199b9d2d753dad273b70dc41019b10732a904002273f5f7677929574a2301bc235ad4028bf6c4157aaeb127b9766e79e9e43afd7ec4a0f625a9c4273223ad6'
7
- data.tar.gz: e643d2c2f06222d751bdd6f6b26a3f1d88bd8bca9be050895a8057b3d36e2d43338bd28f31ead374c9c918a0e409d70b9cb1664771552c13b7b9c159dd6042da
6
+ metadata.gz: 571c5ff585457d1073fa4de0d506073b55a7c3409967d39a488b71fe38b03e7074312ad5e9e379d0f654043dc8be7ffdba4e1cb3b6df4ba6e884920885064ecd
7
+ data.tar.gz: cb3b39d80301b99e13e4cf412e5da3065ecf5215d7b7bece535c032e6cec5c452a0d44f43363d4d35a06a2267e67945325c177ae8631f8b19bac8f344fad2768
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Mustache
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/mustache.svg)](http://badge.fury.io/rb/mustache)
4
- [![Build Status](https://travis-ci.org/mustache/mustache.svg?branch=master)](https://travis-ci.org/mustache/mustache)
4
+ [![Test](https://github.com/mustache/mustache/actions/workflows/test.yml/badge.svg)](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`. It can be set on a
170
- class by class basis:
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
@@ -35,7 +35,7 @@ if command? :ronn
35
35
 
36
36
  desc "Build the manual"
37
37
  task "man:build" do
38
- sh "ronn -br5 --organization=DEFUNKT --manual='Mustache Manual' man/*.ron"
38
+ sh "ronn-ng -br5 --organization=DEFUNKT --manual='Mustache Manual' man/*.ron"
39
39
  end
40
40
  end
41
41
 
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
@@ -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
@@ -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
@@ -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.
@@ -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. By default it's the current directory (".")
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 :template_path, '.'
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 = File.expand_path(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 = File.expand_path(path)
66
+ @template_path = self.class.setup_path(path)
55
67
  @template = nil
56
68
  end
57
69
 
58
- # Alias for `template_path`
59
- def self.path
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
- # use as its template. By default it's ./class_name.mustache
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 || "#{path}/#{template_name}.#{template_extension}"
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=(template_file)
139
- @template_file = 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 || "#{path}/#{template_name}.#{template_extension}"
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=(template_file)
150
- @template_file = 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
@@ -1,3 +1,3 @@
1
1
  class Mustache
2
- VERSION = '1.1.2'
2
+ VERSION = '1.1.3'
3
3
  end
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
- path = "#{template_path}/#{name}.#{template_extension}"
190
+ partialpath = template_path.map{|p| "#{p}/#{name}.#{template_extension}" }.find{|pf| File.readable? pf}
191
191
 
192
- begin
193
- File.read(path)
194
- rescue
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 \fBperson\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\.
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>person</code> key exists and has a non-false value, the HTML between
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 `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
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
@@ -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.2
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-02-24 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.1
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: []