mustache 1.0.5 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Rakefile +1 -1
- data/lib/mustache/context.rb +4 -4
- data/lib/mustache/generator.rb +2 -2
- data/lib/mustache/parser.rb +5 -3
- data/lib/mustache/settings.rb +24 -0
- data/lib/mustache/version.rb +1 -1
- data/lib/mustache.rb +46 -18
- data/man/mustache.1.html +2 -2
- data/man/mustache.5.html +1 -1
- data/man/mustache.5.ron +1 -1
- data/test/mustache_test.rb +14 -1
- data/test/parser_test.rb +64 -0
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bfcec948b9e5fbd73d9c72e3ade21724d3fd73a1d2ee2ea58ab26bf7e1a341ba
|
4
|
+
data.tar.gz: 1a5d4d062ad29d4a4057a6489f6779d3e61bb7132ecf56fc1ab97a48bfcb926d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afd9888e324611b31fb9a6ac809393b2c42261befce363ab691d68719edb2687dda2129ba64a12367bd0f39d31b1fda861b209345f2abfc06debf67aa0e3ab99
|
7
|
+
data.tar.gz: c225773518109b0eeeecaf89d39faaec30b951361b10c16944f4e016aec6597fc41e75237920dc8c44e00956a00edfcf1b72f2e914ea4dc3f8b296f2436977dc
|
data/Rakefile
CHANGED
data/lib/mustache/context.rb
CHANGED
@@ -51,12 +51,12 @@ class Mustache
|
|
51
51
|
|
52
52
|
# Allows customization of how Mustache escapes things.
|
53
53
|
#
|
54
|
-
# @param [
|
54
|
+
# @param [Object] value Value to escape.
|
55
55
|
#
|
56
|
-
# @return [String] Escaped
|
56
|
+
# @return [String] Escaped string.
|
57
57
|
#
|
58
|
-
def
|
59
|
-
mustache_in_stack.
|
58
|
+
def escape(value)
|
59
|
+
mustache_in_stack.escape(value)
|
60
60
|
end
|
61
61
|
|
62
62
|
# Adds a new object to the context's internal stack.
|
data/lib/mustache/generator.rb
CHANGED
@@ -133,7 +133,7 @@ class Mustache
|
|
133
133
|
when Proc
|
134
134
|
#{proc_handling}
|
135
135
|
when Array, Enumerator, Mustache::Enumerable
|
136
|
-
v.map { |
|
136
|
+
v.map { |_| ctx.push(_); r = #{code}; ctx.pop; r }.join
|
137
137
|
else
|
138
138
|
ctx.push(v); r = #{code}; ctx.pop; r
|
139
139
|
end
|
@@ -182,7 +182,7 @@ class Mustache
|
|
182
182
|
if v.is_a?(Proc)
|
183
183
|
v = #{@option_static_lambdas ? 'v.call' : 'Mustache::Template.new(v.call.to_s).render(ctx.dup)'}
|
184
184
|
end
|
185
|
-
ctx.
|
185
|
+
ctx.escape(v)
|
186
186
|
compiled
|
187
187
|
end
|
188
188
|
|
data/lib/mustache/parser.rb
CHANGED
@@ -323,12 +323,14 @@ EOF
|
|
323
323
|
|
324
324
|
def scan_tag_close content, fetch, padding, pre_match_position
|
325
325
|
section, pos, result = @sections.pop
|
326
|
+
if section.nil?
|
327
|
+
error "Closing unopened #{content.inspect}"
|
328
|
+
end
|
329
|
+
|
326
330
|
raw = @scanner.pre_match[pos[3]...pre_match_position] + padding
|
327
331
|
(@result = result).last << raw << [self.otag, self.ctag]
|
328
332
|
|
329
|
-
if section
|
330
|
-
error "Closing unopened #{content.inspect}"
|
331
|
-
elsif section != content
|
333
|
+
if section != content
|
332
334
|
error "Unclosed section #{section.inspect}", pos
|
333
335
|
end
|
334
336
|
end
|
data/lib/mustache/settings.rb
CHANGED
@@ -2,6 +2,30 @@
|
|
2
2
|
# view class, or a single Mustache instance.
|
3
3
|
class Mustache
|
4
4
|
|
5
|
+
def initialize_settings
|
6
|
+
@template = nil
|
7
|
+
@template_path = nil
|
8
|
+
@template_extension = nil
|
9
|
+
@template_name = nil
|
10
|
+
@template_file = nil
|
11
|
+
@raise_on_context_miss = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.initialize_settings
|
15
|
+
@template = nil
|
16
|
+
@template_path = nil
|
17
|
+
@template_extension = nil
|
18
|
+
@template_name = nil
|
19
|
+
@template_file = nil
|
20
|
+
@raise_on_context_miss = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
initialize_settings
|
24
|
+
|
25
|
+
def self.inherited(subclass)
|
26
|
+
subclass.initialize_settings
|
27
|
+
end
|
28
|
+
|
5
29
|
#
|
6
30
|
# Template Path
|
7
31
|
#
|
data/lib/mustache/version.rb
CHANGED
data/lib/mustache.rb
CHANGED
@@ -74,10 +74,19 @@ require 'mustache/utils'
|
|
74
74
|
#
|
75
75
|
class Mustache
|
76
76
|
|
77
|
-
# Initialize a new
|
77
|
+
# Initialize a new Mustache instance.
|
78
|
+
#
|
78
79
|
# @param [Hash] options An options hash
|
80
|
+
# @option options [String] template_path
|
81
|
+
# @option options [String] template_extension
|
82
|
+
# @option options [String] template_file
|
83
|
+
# @option options [String] template
|
84
|
+
# @option options [String] view_namespace
|
85
|
+
# @option options [String] view_path
|
79
86
|
def initialize(options = {})
|
80
87
|
@options = options
|
88
|
+
|
89
|
+
initialize_settings
|
81
90
|
end
|
82
91
|
|
83
92
|
# Instantiates an instance of this class and calls `render` with
|
@@ -91,19 +100,18 @@ class Mustache
|
|
91
100
|
# Parses our fancy pants template file and returns normal file with
|
92
101
|
# all special {{tags}} and {{#sections}}replaced{{/sections}}.
|
93
102
|
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
# @view.render("Hi {{thing}}!", :thing => :world)
|
103
|
+
# @example Render view
|
104
|
+
# @view.render("Hi {{thing}}!", :thing => :world)
|
97
105
|
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
106
|
+
# @example Set view template and then render
|
107
|
+
# View.template = "Hi {{thing}}!"
|
108
|
+
# @view = View.new
|
109
|
+
# @view.render(:thing => :world)
|
101
110
|
#
|
102
111
|
# @param [String,Hash] data A String template or a Hash context.
|
103
112
|
# If a Hash is given, we'll try to figure
|
104
113
|
# out the template from the class.
|
105
114
|
# @param [Hash] ctx A Hash context if `data` is a String template.
|
106
|
-
#
|
107
115
|
# @return [String] Returns a rendered version of a template.
|
108
116
|
def render(data = template, ctx = {})
|
109
117
|
case data
|
@@ -134,11 +142,11 @@ class Mustache
|
|
134
142
|
|
135
143
|
# Context accessors.
|
136
144
|
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
145
|
+
# @example Context accessors
|
146
|
+
# view = Mustache.new
|
147
|
+
# view[:name] = "Jon"
|
148
|
+
# view.template = "Hi, {{name}}!"
|
149
|
+
# view.render # => "Hi, Jon!"
|
142
150
|
def [](key)
|
143
151
|
context[key.to_sym]
|
144
152
|
end
|
@@ -190,17 +198,36 @@ class Mustache
|
|
190
198
|
end
|
191
199
|
|
192
200
|
# Override this to provide custom escaping.
|
201
|
+
# By default it uses `CGI.escapeHTML`.
|
202
|
+
#
|
203
|
+
# @example Overriding #escape
|
204
|
+
# class PersonView < Mustache
|
205
|
+
# def escape(value)
|
206
|
+
# my_html_escape_method(value.to_s)
|
207
|
+
# end
|
208
|
+
# end
|
193
209
|
#
|
194
|
-
#
|
210
|
+
# @param [Object] value Value to escape.
|
211
|
+
# @return [String] Escaped content.
|
212
|
+
def escape(value)
|
213
|
+
self.escapeHTML(value.to_s)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Override this to provide custom escaping.
|
195
217
|
#
|
218
|
+
# @example Overriding #escapeHTML
|
196
219
|
# class PersonView < Mustache
|
197
220
|
# def escapeHTML(str)
|
198
221
|
# my_html_escape_method(str)
|
199
222
|
# end
|
200
223
|
# end
|
201
224
|
#
|
202
|
-
# @
|
225
|
+
# @deprecated Use {#escape} instead.
|
203
226
|
#
|
227
|
+
# Note that {#escape} can receive any kind of object.
|
228
|
+
# If your override logic is expecting a string, you will
|
229
|
+
# have to call to_s on it yourself.
|
230
|
+
# @param [String] str String to escape.
|
204
231
|
# @return [String] Escaped HTML.
|
205
232
|
def escapeHTML(str)
|
206
233
|
CGI.escapeHTML(str)
|
@@ -217,7 +244,8 @@ class Mustache
|
|
217
244
|
|
218
245
|
# When given a symbol or string representing a class, will try to produce an
|
219
246
|
# appropriate view class.
|
220
|
-
#
|
247
|
+
#
|
248
|
+
# @example
|
221
249
|
# Mustache.view_namespace = Hurl::Views
|
222
250
|
# Mustache.view_class(:Partial) # => Hurl::Views::Partial
|
223
251
|
def self.view_class(name)
|
@@ -244,7 +272,7 @@ class Mustache
|
|
244
272
|
file_name = underscore(name)
|
245
273
|
file_path = "#{view_path}/#{file_name}.rb"
|
246
274
|
|
247
|
-
return Mustache unless File.
|
275
|
+
return Mustache unless File.exist?(file_path)
|
248
276
|
|
249
277
|
require file_path.chomp('.rb')
|
250
278
|
rescued_const_get(name)
|
@@ -263,7 +291,7 @@ class Mustache
|
|
263
291
|
Mustache::Utils::String.new(underscored).classify
|
264
292
|
end
|
265
293
|
|
266
|
-
#
|
294
|
+
# TemplatePartial => template_partial
|
267
295
|
# Template::Partial => template/partial
|
268
296
|
# Takes a string but defaults to using the current class' name.
|
269
297
|
def self.underscore(classified = name)
|
data/man/mustache.1.html
CHANGED
@@ -102,7 +102,7 @@ names: [ {name: chris}, {name: mark}, {name: scott} ]
|
|
102
102
|
should work fine.</p>
|
103
103
|
|
104
104
|
<p>After the frontmatter should come any valid Mustache template. See
|
105
|
-
<a class="man-ref" href="mustache.5.
|
105
|
+
<a class="man-ref" href="mustache.5.ronn.html">mustache<span class="s">(5)</span></a> for an overview of Mustache templates.</p>
|
106
106
|
|
107
107
|
<p>For example:</p>
|
108
108
|
|
@@ -198,7 +198,7 @@ data
|
|
198
198
|
|
199
199
|
<h2 id="SEE-ALSO">SEE ALSO</h2>
|
200
200
|
|
201
|
-
<p><a class="man-ref" href="mustache.5.
|
201
|
+
<p><a class="man-ref" href="mustache.5.ronn.html">mustache<span class="s">(5)</span></a>, <span class="man-ref">gem<span class="s">(1)</span></span>,
|
202
202
|
<a href="http://mustache.github.io/" data-bare-link="true">http://mustache.github.io/</a></p>
|
203
203
|
|
204
204
|
|
data/man/mustache.5.html
CHANGED
@@ -409,7 +409,7 @@ markup."</p>
|
|
409
409
|
|
410
410
|
<h2 id="SEE-ALSO">SEE ALSO</h2>
|
411
411
|
|
412
|
-
<p><a class="man-ref" href="mustache.1.
|
412
|
+
<p><a class="man-ref" href="mustache.1.ronn.html">mustache<span class="s">(1)</span></a>,
|
413
413
|
<a href="http://mustache.github.io/" data-bare-link="true">http://mustache.github.io/</a></p>
|
414
414
|
|
415
415
|
|
data/man/mustache.5.ron
CHANGED
data/test/mustache_test.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require_relative 'helper'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
class MustacheTest < Minitest::Test
|
5
6
|
def test_instance_render
|
@@ -659,7 +660,7 @@ template
|
|
659
660
|
assert_equal('[ 0 1 2 3 4 5 6 7 8 9 10 ]', MethodMissing.render)
|
660
661
|
end
|
661
662
|
|
662
|
-
def
|
663
|
+
def test_custom_html_escaping
|
663
664
|
view = Class.new(Mustache) do
|
664
665
|
def escapeHTML(str)
|
665
666
|
"pong"
|
@@ -670,6 +671,17 @@ template
|
|
670
671
|
assert_equal 'nothing', Mustache.render("{{thing}}", :thing => "nothing")
|
671
672
|
end
|
672
673
|
|
674
|
+
def test_custom_escaping
|
675
|
+
view = Class.new(Mustache) do
|
676
|
+
def escape(str)
|
677
|
+
JSON.dump(str)
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
assert_equal '{ "key": "a\"b" }', view.render('{ "key": {{thing}} }', :thing => 'a"b')
|
682
|
+
assert_equal 'nothing', Mustache.render("{{thing}}", :thing => "nothing")
|
683
|
+
end
|
684
|
+
|
673
685
|
def test_implicit_iterator
|
674
686
|
view = Mustache.new
|
675
687
|
view.template = "{{#people}}* {{.}}\n{{/people}}"
|
@@ -820,6 +832,7 @@ template
|
|
820
832
|
def test_instance_with_initialize_render
|
821
833
|
klass = Class.new(Mustache) do
|
822
834
|
def initialize(name)
|
835
|
+
super
|
823
836
|
@name = name
|
824
837
|
end
|
825
838
|
attr_reader :name
|
data/test/parser_test.rb
CHANGED
@@ -94,4 +94,68 @@ EOF
|
|
94
94
|
|
95
95
|
assert_equal expected, tokens
|
96
96
|
end
|
97
|
+
|
98
|
+
def test_unclosed_section
|
99
|
+
lexer = Mustache::Parser.new
|
100
|
+
exception = assert_raises Mustache::Parser::SyntaxError do
|
101
|
+
lexer.compile("{{#list}}")
|
102
|
+
end
|
103
|
+
|
104
|
+
expected = <<-EOF
|
105
|
+
Unclosed section "list"
|
106
|
+
Line 1
|
107
|
+
{{#list}}
|
108
|
+
^
|
109
|
+
EOF
|
110
|
+
|
111
|
+
assert_equal expected, exception.message
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_closing_unopened
|
115
|
+
lexer = Mustache::Parser.new
|
116
|
+
exception = assert_raises Mustache::Parser::SyntaxError do
|
117
|
+
lexer.compile("{{/list}}")
|
118
|
+
end
|
119
|
+
|
120
|
+
expected = <<-EOF
|
121
|
+
Closing unopened "list"
|
122
|
+
Line 1
|
123
|
+
{{/list}}
|
124
|
+
^
|
125
|
+
EOF
|
126
|
+
|
127
|
+
assert_equal expected, exception.message
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_unclosed_tag
|
131
|
+
lexer = Mustache::Parser.new
|
132
|
+
exception = assert_raises Mustache::Parser::SyntaxError do
|
133
|
+
lexer.compile("{{list")
|
134
|
+
end
|
135
|
+
|
136
|
+
expected = <<-EOF
|
137
|
+
Unclosed tag
|
138
|
+
Line 1
|
139
|
+
{{list
|
140
|
+
^
|
141
|
+
EOF
|
142
|
+
|
143
|
+
assert_equal expected, exception.message
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_illegal_content
|
147
|
+
lexer = Mustache::Parser.new
|
148
|
+
exception = assert_raises Mustache::Parser::SyntaxError do
|
149
|
+
lexer.compile("{{")
|
150
|
+
end
|
151
|
+
|
152
|
+
expected = <<-EOF
|
153
|
+
Illegal content in tag
|
154
|
+
Line 1
|
155
|
+
{{
|
156
|
+
^
|
157
|
+
EOF
|
158
|
+
|
159
|
+
assert_equal expected, exception.message
|
160
|
+
end
|
97
161
|
end
|
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.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Wanstrath
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2019-12-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -219,8 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
219
|
- !ruby/object:Gem::Version
|
220
220
|
version: '0'
|
221
221
|
requirements: []
|
222
|
-
|
223
|
-
rubygems_version: 2.6.8
|
222
|
+
rubygems_version: 3.0.3
|
224
223
|
signing_key:
|
225
224
|
specification_version: 4
|
226
225
|
summary: Mustache is a framework-agnostic way to render logic-free views.
|