flavour_saver 4.0.2 → 5.0.0
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/.github/workflows/ci.yml +14 -0
- data/.standard.yml +1 -0
- data/CHANGELOG.md +57 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +48 -5
- data/README.md +153 -271
- data/flavour_saver.gemspec +17 -19
- data/lib/flavour_saver/error.rb +5 -0
- data/lib/flavour_saver/helpers.rb +19 -18
- data/lib/flavour_saver/lexer.rb +123 -50
- data/lib/flavour_saver/nodes.rb +107 -19
- data/lib/flavour_saver/parser.rb +339 -161
- data/lib/flavour_saver/partial.rb +4 -6
- data/lib/flavour_saver/rails_partial.rb +10 -4
- data/lib/flavour_saver/runtime.rb +76 -81
- data/lib/flavour_saver/template.rb +3 -5
- data/lib/flavour_saver/version.rb +1 -1
- data/lib/flavour_saver.rb +17 -17
- data/spec/acceptance/backtrack_spec.rb +9 -9
- data/spec/acceptance/comment_spec.rb +7 -7
- data/spec/acceptance/custom_block_helper_spec.rb +12 -12
- data/spec/acceptance/custom_helper_spec.rb +8 -8
- data/spec/acceptance/ensure_no_rce_spec.rb +64 -53
- data/spec/acceptance/handlebars_qunit_spec.rb +295 -297
- data/spec/acceptance/if_else_spec.rb +6 -6
- data/spec/acceptance/multi_level_with_spec.rb +10 -11
- data/spec/acceptance/nesting_depth_spec.rb +34 -0
- data/spec/acceptance/one_character_identifier_spec.rb +8 -8
- data/spec/acceptance/raw_block_spec.rb +7 -7
- data/spec/acceptance/sections_spec.rb +17 -14
- data/spec/acceptance/segment_literals_spec.rb +5 -5
- data/spec/acceptance/simple_expression_spec.rb +9 -9
- data/spec/acceptance/subexpression_spec.rb +18 -17
- data/spec/acceptance/unless_spec.rb +19 -6
- data/spec/lib/flavour_saver/lexer_spec.rb +103 -89
- data/spec/lib/flavour_saver/nodes_spec.rb +85 -0
- data/spec/lib/flavour_saver/parser_spec.rb +155 -95
- data/spec/lib/flavour_saver/runtime_spec.rb +94 -96
- data/spec/lib/flavour_saver/template_spec.rb +1 -2
- metadata +19 -48
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "cgi"
|
|
2
2
|
|
|
3
3
|
module FlavourSaver
|
|
4
|
-
UnknownNodeTypeException
|
|
5
|
-
UnknownContextException
|
|
6
|
-
InappropriateUseOfElseException
|
|
4
|
+
UnknownNodeTypeException = Class.new(StandardError)
|
|
5
|
+
UnknownContextException = Class.new(StandardError)
|
|
6
|
+
InappropriateUseOfElseException = Class.new(StandardError)
|
|
7
7
|
UndefinedPrivateVariableException = Class.new(StandardError)
|
|
8
|
-
UnknownHelperException
|
|
9
|
-
ForbiddenMethodException
|
|
8
|
+
UnknownHelperException = Class.new(RuntimeError)
|
|
9
|
+
ForbiddenMethodException = Class.new(UnknownHelperException)
|
|
10
10
|
class Runtime
|
|
11
|
+
attr_accessor :context, :ast, :privates
|
|
12
|
+
attr_writer :parent
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def self.run(ast, context, locals={}, helpers=[])
|
|
15
|
-
self.new(ast, context, locals, helpers).to_s
|
|
14
|
+
def self.run(ast, context, locals = {}, helpers = [])
|
|
15
|
+
new(ast, context, locals, helpers).to_s
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def initialize(ast, context=nil, locals={}, helpers=[],parent=nil)
|
|
18
|
+
def initialize(ast, context = nil, locals = {}, helpers = [], parent = nil)
|
|
19
19
|
@ast = ast
|
|
20
20
|
@locals = locals
|
|
21
21
|
@helpers = helpers
|
|
22
22
|
@context = context
|
|
23
23
|
@parent = parent
|
|
24
|
-
@privates = parent ? parent.privates.dup : {
|
|
24
|
+
@privates = parent ? parent.privates.dup : {"root" => context}
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def to_s(tmp_context = nil,privates={})
|
|
27
|
+
def to_s(tmp_context = nil, privates = {})
|
|
28
28
|
result = nil
|
|
29
29
|
if tmp_context
|
|
30
30
|
old_context = @context
|
|
@@ -35,37 +35,35 @@ module FlavourSaver
|
|
|
35
35
|
@privates = old_privates
|
|
36
36
|
@context = old_context
|
|
37
37
|
else
|
|
38
|
-
result = evaluate_node(@ast).to_s.force_encoding(Encoding
|
|
38
|
+
result = evaluate_node(@ast).to_s.force_encoding(Encoding.default_external)
|
|
39
39
|
end
|
|
40
40
|
result
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def private_variable_set(name,value)
|
|
43
|
+
def private_variable_set(name, value)
|
|
44
44
|
@privates[name.to_s] = value
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def private_variable_get(name)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
raise UndefinedPrivateVariableException, "private variable not found @#{name}"
|
|
52
|
-
end
|
|
48
|
+
@privates.fetch(name)
|
|
49
|
+
rescue KeyError
|
|
50
|
+
raise UndefinedPrivateVariableException, "private variable not found @#{name}"
|
|
53
51
|
end
|
|
54
52
|
|
|
55
53
|
def strip(tmp_context = nil)
|
|
56
|
-
|
|
54
|
+
to_s(tmp_context).gsub(/\s+/, " ").strip
|
|
57
55
|
end
|
|
58
56
|
|
|
59
57
|
def evaluate_node(node)
|
|
60
58
|
case node
|
|
61
59
|
when TemplateNode
|
|
62
|
-
node.items.map { |n| evaluate_node(n) }.join(
|
|
60
|
+
node.items.map { |n| evaluate_node(n) }.join("")
|
|
63
61
|
when BlockExpressionNode
|
|
64
62
|
evaluate_block(node).to_s
|
|
65
63
|
when OutputNode
|
|
66
64
|
node.value
|
|
67
65
|
when NumberNode
|
|
68
|
-
if node.value
|
|
66
|
+
if /\./.match?(node.value)
|
|
69
67
|
node.value.to_f
|
|
70
68
|
else
|
|
71
69
|
node.value.to_i
|
|
@@ -79,12 +77,12 @@ module FlavourSaver
|
|
|
79
77
|
when CallNode
|
|
80
78
|
evaluate_call(node)
|
|
81
79
|
when Hash
|
|
82
|
-
node.each do |key,value|
|
|
80
|
+
node.each do |key, value|
|
|
83
81
|
node[key] = evaluate_argument(value)
|
|
84
82
|
end
|
|
85
83
|
node
|
|
86
84
|
when CommentNode
|
|
87
|
-
|
|
85
|
+
""
|
|
88
86
|
when PartialNode
|
|
89
87
|
evaluate_partial(node)
|
|
90
88
|
else
|
|
@@ -102,37 +100,37 @@ module FlavourSaver
|
|
|
102
100
|
end
|
|
103
101
|
|
|
104
102
|
def evaluate_partial(node)
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
partial_context = context
|
|
104
|
+
partial_context = evaluate_argument(node.context) if node.context
|
|
107
105
|
if defined?(::Rails)
|
|
108
|
-
context.send(:render, :
|
|
106
|
+
context.send(:render, partial: node.name, object: partial_context)
|
|
109
107
|
else
|
|
110
108
|
partial = Partial.fetch(node.name)
|
|
111
109
|
if partial.respond_to? :call
|
|
112
|
-
partial.call(
|
|
110
|
+
partial.call(partial_context)
|
|
113
111
|
else
|
|
114
|
-
create_child_runtime(partial).to_s(
|
|
112
|
+
create_child_runtime(partial).to_s(partial_context)
|
|
115
113
|
end
|
|
116
114
|
end
|
|
117
115
|
end
|
|
118
116
|
|
|
119
|
-
def evaluate_call(call, context=self.context, &block)
|
|
120
|
-
context = Helpers.decorate_with(context
|
|
117
|
+
def evaluate_call(call, context = self.context, &block)
|
|
118
|
+
context = Helpers.decorate_with(context, @helpers, @locals) unless context.is_a? Helpers::Decorator
|
|
121
119
|
case call
|
|
122
120
|
when ParentCallNode
|
|
123
121
|
depth = call.depth
|
|
124
|
-
(2..depth).inject(parent) { |p| p.parent }.evaluate_call(call.to_callnode
|
|
122
|
+
(2..depth).inject(parent) { |p| p.parent }.evaluate_call(call.to_callnode, &block)
|
|
125
123
|
when LiteralCallNode
|
|
126
124
|
result = context.send(:[], call.name)
|
|
127
|
-
result = result.call(*call.arguments.map { |a| evaluate_argument(a) }
|
|
125
|
+
result = result.call(*call.arguments.map { |a| evaluate_argument(a) }, &block) if result.respond_to? :call
|
|
128
126
|
result
|
|
129
127
|
when LocalVarNode
|
|
130
|
-
|
|
128
|
+
private_variable_get(call.name)
|
|
131
129
|
else
|
|
132
130
|
if forbidden_method? context, call.name
|
|
133
131
|
raise ForbiddenMethodException, "Refusing to call #{call.name.inspect} from a template: it isn't a helper, a local, or part of the template context's own API. Register a helper if you meant to expose it, or use #{"{{[#{call.name}]}}"} to read a data field of that name."
|
|
134
132
|
end
|
|
135
|
-
if call.parent.is_a?
|
|
133
|
+
if call.parent.is_a?(BlockExpressionNode) && !context.respond_to?(call.name)
|
|
136
134
|
raise UnknownHelperException, "Template context doesn't respond to method #{call.name.inspect}."
|
|
137
135
|
end
|
|
138
136
|
context.public_send(call.name, *call.arguments.map { |a| evaluate_argument(a) }, &block)
|
|
@@ -148,8 +146,8 @@ module FlavourSaver
|
|
|
148
146
|
end
|
|
149
147
|
|
|
150
148
|
def evaluate_object_path(path, &block)
|
|
151
|
-
path.inject(context) do |context,call|
|
|
152
|
-
|
|
149
|
+
path.inject(context) do |context, call|
|
|
150
|
+
evaluate_call(call, context, &block)
|
|
153
151
|
end
|
|
154
152
|
end
|
|
155
153
|
|
|
@@ -157,11 +155,11 @@ module FlavourSaver
|
|
|
157
155
|
evaluate_object_path(node.method)
|
|
158
156
|
end
|
|
159
157
|
|
|
160
|
-
def evaluate_block(node,block_context
|
|
158
|
+
def evaluate_block(node, block_context = @context)
|
|
161
159
|
call = node.method.first
|
|
162
160
|
content_runtime = create_child_runtime(node.contents)
|
|
163
161
|
alternate_runtime = create_child_runtime(node.alternate) if node.respond_to? :alternate
|
|
164
|
-
block_runtime = BlockRuntime.new(block_context,content_runtime,alternate_runtime)
|
|
162
|
+
block_runtime = BlockRuntime.new(block_context, content_runtime, alternate_runtime)
|
|
165
163
|
|
|
166
164
|
result = evaluate_call(call, block_context) { block_runtime }
|
|
167
165
|
|
|
@@ -172,17 +170,17 @@ module FlavourSaver
|
|
|
172
170
|
|
|
173
171
|
# If the result is collectiony then act as an implicit
|
|
174
172
|
# "each"
|
|
175
|
-
if result
|
|
173
|
+
if result&.respond_to?(:each)
|
|
176
174
|
if result.respond_to?(:size) && (result.size > 0)
|
|
177
175
|
r = []
|
|
178
176
|
# Not using #each_with_index because the object might
|
|
179
177
|
# not actually be an Enumerable
|
|
180
178
|
count = 0
|
|
181
179
|
result.each do |e|
|
|
182
|
-
r << block_runtime.contents(e, {
|
|
180
|
+
r << block_runtime.contents(e, {"index" => count})
|
|
183
181
|
count += 1
|
|
184
182
|
end
|
|
185
|
-
result = r.join(
|
|
183
|
+
result = r.join("")
|
|
186
184
|
else
|
|
187
185
|
result = block_runtime.inverse
|
|
188
186
|
end
|
|
@@ -191,19 +189,19 @@ module FlavourSaver
|
|
|
191
189
|
elsif result
|
|
192
190
|
result = block_runtime.contents result
|
|
193
191
|
else
|
|
194
|
-
if block_runtime.has_inverse?
|
|
195
|
-
|
|
192
|
+
result = if block_runtime.has_inverse?
|
|
193
|
+
block_runtime.inverse
|
|
196
194
|
else
|
|
197
|
-
|
|
195
|
+
""
|
|
198
196
|
end
|
|
199
197
|
end
|
|
200
198
|
end
|
|
201
199
|
result
|
|
202
200
|
end
|
|
203
201
|
|
|
204
|
-
def create_child_runtime(body=[])
|
|
202
|
+
def create_child_runtime(body = [])
|
|
205
203
|
node = body.is_a?(TemplateNode) ? body : TemplateNode.new(body)
|
|
206
|
-
Runtime.new(node,nil
|
|
204
|
+
Runtime.new(node, nil, @locals, @helpers, self)
|
|
207
205
|
end
|
|
208
206
|
|
|
209
207
|
def inspect
|
|
@@ -211,21 +209,21 @@ module FlavourSaver
|
|
|
211
209
|
end
|
|
212
210
|
|
|
213
211
|
class BlockRuntime
|
|
214
|
-
def initialize(block_context,content_runtime,alternate_runtime=nil)
|
|
212
|
+
def initialize(block_context, content_runtime, alternate_runtime = nil)
|
|
215
213
|
@block_context = block_context
|
|
216
214
|
@content_runtime = content_runtime
|
|
217
215
|
@alternate_runtime = alternate_runtime
|
|
218
216
|
@render_count = 0
|
|
219
217
|
end
|
|
220
218
|
|
|
221
|
-
def contents(context
|
|
219
|
+
def contents(context = @block_context, locals = {})
|
|
222
220
|
@render_count += 1
|
|
223
|
-
@content_runtime
|
|
221
|
+
@content_runtime&.to_s(context, locals)
|
|
224
222
|
end
|
|
225
223
|
|
|
226
|
-
def inverse(context
|
|
224
|
+
def inverse(context = @block_context)
|
|
227
225
|
@render_count += 1
|
|
228
|
-
@alternate_runtime
|
|
226
|
+
@alternate_runtime&.to_s(context)
|
|
229
227
|
end
|
|
230
228
|
|
|
231
229
|
def has_inverse?
|
|
@@ -233,7 +231,7 @@ module FlavourSaver
|
|
|
233
231
|
end
|
|
234
232
|
|
|
235
233
|
def rendered?
|
|
236
|
-
@render_count > 0 ? @render_count : false
|
|
234
|
+
(@render_count > 0) ? @render_count : false
|
|
237
235
|
end
|
|
238
236
|
|
|
239
237
|
def rendered!
|
|
@@ -273,10 +271,10 @@ module FlavourSaver
|
|
|
273
271
|
# public_send.
|
|
274
272
|
def forbidden_method?(context, name)
|
|
275
273
|
owner = begin
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
274
|
+
context.method(name).owner
|
|
275
|
+
rescue NameError
|
|
276
|
+
return false
|
|
277
|
+
end
|
|
280
278
|
|
|
281
279
|
return false if owner.equal? Helpers::Defaults
|
|
282
280
|
return false unless Helpers::Decorator.ancestors.include? owner
|
|
@@ -294,32 +292,29 @@ module FlavourSaver
|
|
|
294
292
|
end
|
|
295
293
|
|
|
296
294
|
def escape(output)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
when '`'
|
|
314
|
-
"`"
|
|
315
|
-
end
|
|
295
|
+
# If the string is already marked as html_safe then don't
|
|
296
|
+
# escape it any further.
|
|
297
|
+
return output if output.respond_to?(:html_safe) && output.html_safe?
|
|
298
|
+
|
|
299
|
+
output = CGI.escapeHTML(output)
|
|
300
|
+
|
|
301
|
+
# We can't just use CGI.escapeHTML because Handlebars does extra
|
|
302
|
+
# escaping for its JavaScript environment. Thems the breaks.
|
|
303
|
+
output = output.gsub(/(['"`])/) do |match|
|
|
304
|
+
case match
|
|
305
|
+
when "'"
|
|
306
|
+
"'"
|
|
307
|
+
when '"'
|
|
308
|
+
"""
|
|
309
|
+
when "`"
|
|
310
|
+
"`"
|
|
316
311
|
end
|
|
312
|
+
end
|
|
317
313
|
|
|
318
|
-
|
|
319
|
-
|
|
314
|
+
# Mark it as already escaped if we're in Rails
|
|
315
|
+
output.html_safe if output.respond_to? :html_safe
|
|
320
316
|
|
|
321
|
-
|
|
322
|
-
end
|
|
317
|
+
output
|
|
323
318
|
end
|
|
324
319
|
end
|
|
325
320
|
end
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "tilt/template"
|
|
2
2
|
|
|
3
3
|
module FlavourSaver
|
|
4
4
|
class Template < Tilt::Template
|
|
5
|
-
|
|
6
5
|
def self.engine_initialized?
|
|
7
6
|
true
|
|
8
7
|
end
|
|
@@ -11,9 +10,8 @@ module FlavourSaver
|
|
|
11
10
|
@ast = Parser.parse(Lexer.lex(data))
|
|
12
11
|
end
|
|
13
12
|
|
|
14
|
-
def evaluate(scope=Object.new,locals={}
|
|
15
|
-
Runtime.run(@ast,scope,locals)
|
|
13
|
+
def evaluate(scope = Object.new, locals = {}, &block)
|
|
14
|
+
Runtime.run(@ast, scope, locals)
|
|
16
15
|
end
|
|
17
|
-
|
|
18
16
|
end
|
|
19
17
|
end
|
data/lib/flavour_saver.rb
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
require "flavour_saver/version"
|
|
2
|
-
require
|
|
2
|
+
require "flavour_saver/error"
|
|
3
|
+
require "tilt"
|
|
3
4
|
|
|
4
5
|
module FlavourSaver
|
|
5
|
-
|
|
6
|
-
autoload :
|
|
7
|
-
autoload :
|
|
8
|
-
autoload :
|
|
9
|
-
autoload :
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :
|
|
12
|
-
autoload :
|
|
13
|
-
autoload :NodeCollection, 'flavour_saver/node_collection'
|
|
6
|
+
autoload :Lexer, "flavour_saver/lexer"
|
|
7
|
+
autoload :Parser, "flavour_saver/parser"
|
|
8
|
+
autoload :Runtime, "flavour_saver/runtime"
|
|
9
|
+
autoload :Helpers, "flavour_saver/helpers"
|
|
10
|
+
autoload :Partial, "flavour_saver/partial"
|
|
11
|
+
autoload :RailsPartial, "flavour_saver/rails_partial"
|
|
12
|
+
autoload :Template, "flavour_saver/template"
|
|
13
|
+
autoload :NodeCollection, "flavour_saver/node_collection"
|
|
14
14
|
|
|
15
15
|
if defined? Rails
|
|
16
16
|
class Engine < Rails::Engine
|
|
@@ -45,20 +45,20 @@ module FlavourSaver
|
|
|
45
45
|
Parser.parse(tokens)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
def evaluate(template,context)
|
|
48
|
+
def evaluate(template, context)
|
|
49
49
|
Runtime.run(parse(lex(template)), context)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
def register_helper(*args
|
|
53
|
-
Helpers.register_helper(*args
|
|
52
|
+
def register_helper(*args, &b)
|
|
53
|
+
Helpers.register_helper(*args, &b)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def reset_helpers
|
|
57
57
|
Helpers.reset_helpers
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
def register_partial(name,content=nil
|
|
61
|
-
Partial.register_partial(name,content
|
|
60
|
+
def register_partial(name, content = nil, &block)
|
|
61
|
+
Partial.register_partial(name, content, &block)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def reset_partials
|
|
@@ -70,10 +70,10 @@ module FlavourSaver
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def logger=(logger)
|
|
73
|
-
@logger=logger
|
|
73
|
+
@logger = logger
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
Tilt.register(Template,
|
|
76
|
+
Tilt.register(Template, "handlebars", "hbs")
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
FS = FlavourSaver
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "tilt"
|
|
2
|
+
require "flavour_saver"
|
|
3
3
|
|
|
4
|
-
describe
|
|
5
|
-
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/,
|
|
6
|
-
let(:template) { File.expand_path(
|
|
7
|
-
let(:context) { Struct.new(:person
|
|
4
|
+
describe "Fixture: backtrack.hbs" do
|
|
5
|
+
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/, " ").strip }
|
|
6
|
+
let(:template) { File.expand_path("../../fixtures/backtrack.hbs", __FILE__) }
|
|
7
|
+
let(:context) { Struct.new(:person, :company).new }
|
|
8
8
|
|
|
9
|
-
it
|
|
10
|
-
context.person = Struct.new(:name).new(
|
|
11
|
-
context.company = Struct.new(:name).new(
|
|
9
|
+
it "renders correctly" do
|
|
10
|
+
context.person = Struct.new(:name).new("Alan")
|
|
11
|
+
context.company = Struct.new(:name).new("Rad, Inc.")
|
|
12
12
|
expect(subject).to eq "Alan - Rad, Inc."
|
|
13
13
|
end
|
|
14
14
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "tilt"
|
|
2
|
+
require "flavour_saver"
|
|
3
3
|
|
|
4
|
-
describe
|
|
5
|
-
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/,
|
|
6
|
-
let(:template) { File.expand_path(
|
|
7
|
-
let(:context)
|
|
4
|
+
describe "Fixture: comment.hbs" do
|
|
5
|
+
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/, " ").strip }
|
|
6
|
+
let(:template) { File.expand_path("../../fixtures/comment.hbs", __FILE__) }
|
|
7
|
+
let(:context) { double(:context) }
|
|
8
8
|
|
|
9
|
-
it
|
|
9
|
+
it "renders correctly" do
|
|
10
10
|
expect(subject).to eq "I am a very nice person!"
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "tilt"
|
|
2
|
+
require "flavour_saver"
|
|
3
3
|
|
|
4
|
-
describe
|
|
5
|
-
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/,
|
|
6
|
-
let(:template) { File.expand_path(
|
|
7
|
-
let(:context)
|
|
4
|
+
describe "Fixture: custom_block_helper.hbs" do
|
|
5
|
+
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/, " ").strip }
|
|
6
|
+
let(:template) { File.expand_path("../../fixtures/custom_block_helper.hbs", __FILE__) }
|
|
7
|
+
let(:context) { double(:context) }
|
|
8
8
|
|
|
9
9
|
before(:each) do
|
|
10
10
|
FlavourSaver::Helpers.reset_helpers
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
describe
|
|
14
|
-
it
|
|
13
|
+
describe "method helper" do
|
|
14
|
+
it "renders correctly" do
|
|
15
15
|
def three_times
|
|
16
16
|
(1..3).map do |i|
|
|
17
17
|
yield.contents i
|
|
18
|
-
end.join
|
|
18
|
+
end.join ""
|
|
19
19
|
end
|
|
20
20
|
FlavourSaver.register_helper(method(:three_times))
|
|
21
21
|
expect(subject).to eq "1 time. 2 time. 3 time."
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
describe
|
|
26
|
-
it
|
|
25
|
+
describe "proc helper" do
|
|
26
|
+
it "renders correctly" do
|
|
27
27
|
FlavourSaver.register_helper(:three_times) { |&b|
|
|
28
28
|
(1..3).map do |i|
|
|
29
29
|
b.call.contents i
|
|
30
|
-
end.join
|
|
30
|
+
end.join ""
|
|
31
31
|
}
|
|
32
32
|
expect(subject).to eq "1 time. 2 time. 3 time."
|
|
33
33
|
end
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "tilt"
|
|
2
|
+
require "flavour_saver"
|
|
3
3
|
|
|
4
|
-
describe
|
|
5
|
-
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/,
|
|
6
|
-
let(:template) { File.expand_path(
|
|
7
|
-
let(:context)
|
|
4
|
+
describe "Fixture: custom_helper.hbs" do
|
|
5
|
+
subject { Tilt.new(template).render(context).gsub(/[\s\r\n]+/, " ").strip }
|
|
6
|
+
let(:template) { File.expand_path("../../fixtures/custom_helper.hbs", __FILE__) }
|
|
7
|
+
let(:context) { double(:context) }
|
|
8
8
|
|
|
9
|
-
it
|
|
9
|
+
it "renders correctly" do
|
|
10
10
|
FlavourSaver.register_helper(:say_what_again) do
|
|
11
|
-
|
|
11
|
+
"What?"
|
|
12
12
|
end
|
|
13
13
|
expect(subject).to eq "What?"
|
|
14
14
|
end
|