curlybars 1.4.0 → 1.5.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/lib/curlybars/lexer.rb +3 -0
- data/lib/curlybars/node/sub_expression.rb +62 -0
- data/lib/curlybars/parser.rb +11 -0
- data/lib/curlybars/version.rb +1 -1
- data/spec/curlybars/lexer_spec.rb +22 -0
- data/spec/integration/node/sub_expression_spec.rb +428 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 662148aedd0a8a6fdb84727cbe92b66fe66abf3fc11fa3e7720d70337fd9c1ff
|
4
|
+
data.tar.gz: 9b599e7c0232ee1442e6f9e410a7e19f10405ea0dbb150bc309121a18be6afef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35b139b2d8c393a2a5a0f413edb687dfae425d315ef22b6cf9652a34a2367737dab922417c52494983f32e10b4f86dbc85ff62a12ac30cf178b7953af3dae3f1
|
7
|
+
data.tar.gz: 271f1f72a18ec374eadead76df6eda66e982ee5863d0be690903d581fbf6387cd83af6e9dbeed2b1351bfd2206c99a7b74ef4619fe2166c2b8a446033a164eac
|
data/lib/curlybars/lexer.rb
CHANGED
@@ -32,6 +32,9 @@ module Curlybars
|
|
32
32
|
r(/{{/) { push_state :curly; :START }
|
33
33
|
r(/}}/, :curly) { pop_state; :END }
|
34
34
|
|
35
|
+
r(/\(/, :curly) { push_state :curly; :LPAREN }
|
36
|
+
r(/\)/, :curly) { pop_state; :RPAREN }
|
37
|
+
|
35
38
|
r(/#/, :curly) { :HASH }
|
36
39
|
r(/\//, :curly) { :SLASH }
|
37
40
|
r(/>/, :curly) { :GT }
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Curlybars
|
2
|
+
module Node
|
3
|
+
SubExpression = Struct.new(:helper, :arguments, :options, :position) do
|
4
|
+
def compile
|
5
|
+
compiled_arguments = arguments.map do |argument|
|
6
|
+
"arguments.push(rendering.cached_call(#{argument.compile}))"
|
7
|
+
end.join("\n")
|
8
|
+
|
9
|
+
compiled_options = options.map do |option|
|
10
|
+
"options.merge!(#{option.compile})"
|
11
|
+
end.join("\n")
|
12
|
+
|
13
|
+
# NOTE: the following is a heredoc string, representing the ruby code fragment
|
14
|
+
# outputted by this node.
|
15
|
+
<<-RUBY
|
16
|
+
::Module.new do
|
17
|
+
def self.exec(contexts, rendering)
|
18
|
+
rendering.check_timeout!
|
19
|
+
|
20
|
+
-> {
|
21
|
+
options = ::ActiveSupport::HashWithIndifferentAccess.new
|
22
|
+
#{compiled_options}
|
23
|
+
|
24
|
+
arguments = []
|
25
|
+
#{compiled_arguments}
|
26
|
+
|
27
|
+
helper = #{helper.compile}
|
28
|
+
helper_position = rendering.position(#{helper.position.line_number},
|
29
|
+
#{helper.position.line_offset})
|
30
|
+
|
31
|
+
options[:this] = contexts.last
|
32
|
+
|
33
|
+
rendering.call(helper, #{helper.path.inspect}, helper_position,
|
34
|
+
arguments, options)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end.exec(contexts, rendering)
|
38
|
+
RUBY
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate_as_value(branches, check_type: :anything)
|
42
|
+
validate(branches, check_type: check_type)
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate(branches, check_type: :anything)
|
46
|
+
[
|
47
|
+
helper.validate(branches, check_type: :helper),
|
48
|
+
arguments.map { |argument| argument.validate_as_value(branches) },
|
49
|
+
options.map { |option| option.validate(branches) }
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
def cache_key
|
54
|
+
[
|
55
|
+
helper,
|
56
|
+
arguments,
|
57
|
+
options
|
58
|
+
].flatten.map(&:cache_key).push(self.class.name).join("/")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/curlybars/parser.rb
CHANGED
@@ -15,6 +15,7 @@ require 'curlybars/node/block_helper_else'
|
|
15
15
|
require 'curlybars/node/option'
|
16
16
|
require 'curlybars/node/partial'
|
17
17
|
require 'curlybars/node/output'
|
18
|
+
require 'curlybars/node/sub_expression'
|
18
19
|
|
19
20
|
module Curlybars
|
20
21
|
class Parser < RLTK::Parser
|
@@ -155,6 +156,7 @@ module Curlybars
|
|
155
156
|
production(:expression) do
|
156
157
|
clause('value') { |value| value }
|
157
158
|
clause('path') { |path| path }
|
159
|
+
clause('subexpression') { |subexpression| subexpression }
|
158
160
|
end
|
159
161
|
|
160
162
|
production(:value) do
|
@@ -164,6 +166,15 @@ module Curlybars
|
|
164
166
|
|
165
167
|
production(:path, 'PATH') { |path| Node::Path.new(path, pos(0)) }
|
166
168
|
|
169
|
+
production(:subexpression, 'LPAREN .path .expressions? .options? RPAREN') do |helper, arguments, options|
|
170
|
+
Node::SubExpression.new(
|
171
|
+
helper,
|
172
|
+
arguments || [],
|
173
|
+
options || [],
|
174
|
+
pos(0)
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
167
178
|
finalize
|
168
179
|
|
169
180
|
VOID = Class.new do
|
data/lib/curlybars/version.rb
CHANGED
@@ -160,6 +160,28 @@ describe Curlybars::Lexer do
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
+
describe "{{path (path context options)}}" do
|
164
|
+
it "is lexed with path, context and options" do
|
165
|
+
expect(lex('{{path (path context key=value)}}')).to produce [:START, :PATH, :LPAREN, :PATH, :PATH, :KEY, :PATH, :RPAREN, :END]
|
166
|
+
end
|
167
|
+
|
168
|
+
it "is lexed without options" do
|
169
|
+
expect(lex('{{path (path context)}}')).to produce [:START, :PATH, :LPAREN, :PATH, :PATH, :RPAREN, :END]
|
170
|
+
end
|
171
|
+
|
172
|
+
it "is lexed without context" do
|
173
|
+
expect(lex('{{path (path key=value)}}')).to produce [:START, :PATH, :LPAREN, :PATH, :KEY, :PATH, :RPAREN, :END]
|
174
|
+
end
|
175
|
+
|
176
|
+
it "is lexed without context and options" do
|
177
|
+
expect(lex('{{path (path)}}')).to produce [:START, :PATH, :LPAREN, :PATH, :RPAREN, :END]
|
178
|
+
end
|
179
|
+
|
180
|
+
it "is lexed with a nested subexpression" do
|
181
|
+
expect(lex('{{path (path (path context key=value) key=value)}}')).to produce [:START, :PATH, :LPAREN, :PATH, :LPAREN, :PATH, :PATH, :KEY, :PATH, :RPAREN, :KEY, :PATH, :RPAREN, :END]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
163
185
|
describe "{{#if path}}...{{/if}}" do
|
164
186
|
it "is lexed" do
|
165
187
|
expect(lex('{{#if path}} text {{/if}}')).to produce(
|
@@ -0,0 +1,428 @@
|
|
1
|
+
describe "{{(helper arg1 arg2 ... key=value ...)}}" do
|
2
|
+
let(:global_helpers_providers) { [IntegrationTest::GlobalHelperProvider.new] }
|
3
|
+
|
4
|
+
describe "#compile" do
|
5
|
+
let(:presenter) { IntegrationTest::Presenter.new(double("view_context")) }
|
6
|
+
|
7
|
+
it "can be an argument to helpers" do
|
8
|
+
template = Curlybars.compile(<<-HBS)
|
9
|
+
{{global_helper (global_helper 'argument' option='value') option='value'}}
|
10
|
+
HBS
|
11
|
+
|
12
|
+
expect(eval(template)).to resemble(<<-HTML)
|
13
|
+
argument - option:value - option:value
|
14
|
+
HTML
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can be an argument to itself" do
|
18
|
+
template = Curlybars.compile(<<-HBS)
|
19
|
+
{{global_helper (global_helper (global_helper 'a' option='b') option='c') option='d'}}
|
20
|
+
HBS
|
21
|
+
|
22
|
+
expect(eval(template)).to resemble(<<-HTML)
|
23
|
+
a - option:b - option:c - option:d
|
24
|
+
HTML
|
25
|
+
end
|
26
|
+
|
27
|
+
it "can handle data objects as argument" do
|
28
|
+
template = Curlybars.compile(<<-HBS)
|
29
|
+
{{global_helper (extract user attribute='first_name') option='value'}}
|
30
|
+
HBS
|
31
|
+
|
32
|
+
expect(eval(template)).to resemble(<<-HTML)
|
33
|
+
Libo - option:value
|
34
|
+
HTML
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can handle calls inside with" do
|
38
|
+
template = Curlybars.compile(<<-HBS)
|
39
|
+
{{#with article}}
|
40
|
+
{{global_helper (extract author attribute='first_name') option='value'}}
|
41
|
+
{{/with}}
|
42
|
+
HBS
|
43
|
+
|
44
|
+
expect(eval(template)).to resemble(<<-HTML)
|
45
|
+
Nicolò - option:value
|
46
|
+
HTML
|
47
|
+
end
|
48
|
+
|
49
|
+
it "does not accept subexpressions in the root" do
|
50
|
+
expect do
|
51
|
+
Curlybars.compile(<<-HBS)
|
52
|
+
{{(join articles attribute='title' separator='-'}}
|
53
|
+
HBS
|
54
|
+
end.to raise_error(Curlybars::Error::Parse)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "can be called within if expressions" do
|
58
|
+
template = Curlybars.compile(<<-HBS)
|
59
|
+
{{#if (calc 3 ">" 1)}}
|
60
|
+
True
|
61
|
+
{{/if}}
|
62
|
+
HBS
|
63
|
+
|
64
|
+
expect(eval(template)).to resemble(<<-HTML)
|
65
|
+
True
|
66
|
+
HTML
|
67
|
+
end
|
68
|
+
|
69
|
+
# Replication of Handlebars' subexpression specs for feature parity
|
70
|
+
# https://github.com/handlebars-lang/handlebars.js/blob/1a08e1d0a7f500f2c1188cbd21750bb9180afcbb/spec/subexpressions.js
|
71
|
+
|
72
|
+
it "arg-less helper" do
|
73
|
+
template = Curlybars.compile(<<-HBS)
|
74
|
+
{{foo (bar)}}!
|
75
|
+
HBS
|
76
|
+
|
77
|
+
expect(eval(template)).to resemble(<<-HTML)
|
78
|
+
LOLLOL!
|
79
|
+
HTML
|
80
|
+
end
|
81
|
+
|
82
|
+
context "with blog presenter" do
|
83
|
+
let(:presenter) do
|
84
|
+
IntegrationTest::BlogPresenter.new(
|
85
|
+
lambda { |*args, options|
|
86
|
+
val = args.first
|
87
|
+
"val is #{val}"
|
88
|
+
}
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "helper w args" do
|
93
|
+
template = Curlybars.compile(<<-HBS)
|
94
|
+
{{blog (equal a b)}}
|
95
|
+
HBS
|
96
|
+
|
97
|
+
expect(eval(template)).to resemble(<<-HTML)
|
98
|
+
val is true
|
99
|
+
HTML
|
100
|
+
end
|
101
|
+
|
102
|
+
it "supports much nesting" do
|
103
|
+
template = Curlybars.compile(<<-HBS)
|
104
|
+
{{blog (equal (equal true true) true)}}
|
105
|
+
HBS
|
106
|
+
|
107
|
+
expect(eval(template)).to resemble(<<-HTML)
|
108
|
+
val is true
|
109
|
+
HTML
|
110
|
+
end
|
111
|
+
|
112
|
+
it "with hashes" do
|
113
|
+
template = Curlybars.compile(<<-HBS)
|
114
|
+
{{blog (equal (equal true true) true fun='yes')}}
|
115
|
+
HBS
|
116
|
+
|
117
|
+
expect(eval(template)).to resemble(<<-HTML)
|
118
|
+
val is true
|
119
|
+
HTML
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "with a different blog presenter" do
|
124
|
+
let(:presenter) do
|
125
|
+
IntegrationTest::BlogPresenter.new(
|
126
|
+
lambda { |*args, options|
|
127
|
+
"val is #{options[:fun]}"
|
128
|
+
}
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "as hashes" do
|
133
|
+
template = Curlybars.compile(<<-HBS)
|
134
|
+
{{blog fun=(equal (blog fun=1) 'val is 1')}}
|
135
|
+
HBS
|
136
|
+
|
137
|
+
expect(eval(template)).to resemble(<<-HTML)
|
138
|
+
val is true
|
139
|
+
HTML
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "with yet another blog presenter" do
|
144
|
+
let(:presenter) do
|
145
|
+
IntegrationTest::BlogPresenter.new(
|
146
|
+
lambda { |*args, options|
|
147
|
+
first, second, third = args
|
148
|
+
"val is #{first}, #{second} and #{third}"
|
149
|
+
}
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "mixed paths and helpers" do
|
154
|
+
template = Curlybars.compile(<<-HBS)
|
155
|
+
{{blog baz.bat (equal a b) baz.bar}}
|
156
|
+
HBS
|
157
|
+
|
158
|
+
expect(eval(template)).to resemble(<<-HTML)
|
159
|
+
val is bat!, true and bar!
|
160
|
+
HTML
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "GH-800 : Complex subexpressions" do
|
165
|
+
let(:presenter) do
|
166
|
+
IntegrationTest::LetterPresenter.new(
|
167
|
+
a: 'a', b: 'b', c: { c: 'c' }, d: 'd', e: { e: 'e' }
|
168
|
+
)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "can handle complex subexpressions" do
|
172
|
+
inputs = [
|
173
|
+
"{{dash 'abc' (concat a b)}}",
|
174
|
+
"{{dash d (concat a b)}}",
|
175
|
+
"{{dash c.c (concat a b)}}",
|
176
|
+
"{{dash (concat a b) c.c}}",
|
177
|
+
"{{dash (concat a e.e) c.c}}"
|
178
|
+
]
|
179
|
+
|
180
|
+
expected_results = [
|
181
|
+
"abc-ab",
|
182
|
+
"d-ab",
|
183
|
+
"c-ab",
|
184
|
+
"ab-c",
|
185
|
+
"ae-c"
|
186
|
+
]
|
187
|
+
|
188
|
+
aggregate_failures do
|
189
|
+
inputs.each_with_index do |input, i|
|
190
|
+
expect(eval(Curlybars.compile(input))).to resemble(expected_results[i])
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
it "multiple subexpressions in a hash" do
|
197
|
+
template = Curlybars.compile(<<-HBS)
|
198
|
+
{{input aria-label=(t "Name") placeholder=(t "Example User")}}
|
199
|
+
HBS
|
200
|
+
|
201
|
+
expected_output = '<input aria-label="Name" placeholder="Example User" />'
|
202
|
+
.gsub("<", "<")
|
203
|
+
.gsub(">", ">")
|
204
|
+
.gsub('"', """)
|
205
|
+
|
206
|
+
expect(eval(template)).to resemble(expected_output)
|
207
|
+
end
|
208
|
+
|
209
|
+
context "with item show presenter" do
|
210
|
+
let(:presenter) do
|
211
|
+
IntegrationTest::ItemShowPresenter.new(field: "Name", placeholder: "Example User")
|
212
|
+
end
|
213
|
+
|
214
|
+
it "multiple subexpressions in a hash with context" do
|
215
|
+
template = Curlybars.compile(<<-HBS)
|
216
|
+
{{input aria-label=(t item.field) placeholder=(t item.placeholder)}}
|
217
|
+
HBS
|
218
|
+
|
219
|
+
expected_output = '<input aria-label="Name" placeholder="Example User" />'
|
220
|
+
.gsub("<", "<")
|
221
|
+
.gsub(">", ">")
|
222
|
+
.gsub('"', """)
|
223
|
+
|
224
|
+
expect(eval(template)).to resemble(expected_output)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "#validate" do
|
230
|
+
let(:presenter_class) { double(:presenter_class) }
|
231
|
+
|
232
|
+
before do
|
233
|
+
allow(Curlybars.configuration).to receive(:global_helpers_provider_classes).and_return([IntegrationTest::GlobalHelperProvider])
|
234
|
+
end
|
235
|
+
|
236
|
+
it "without errors when global helper" do
|
237
|
+
dependency_tree = {}
|
238
|
+
|
239
|
+
source = <<-HBS
|
240
|
+
{{#if (global_helper)}} ... {{/if}}
|
241
|
+
HBS
|
242
|
+
|
243
|
+
errors = Curlybars.validate(dependency_tree, source)
|
244
|
+
|
245
|
+
expect(errors).to be_empty
|
246
|
+
end
|
247
|
+
|
248
|
+
it "with errors when invoking a leaf" do
|
249
|
+
dependency_tree = { name: nil }
|
250
|
+
|
251
|
+
source = <<-HBS
|
252
|
+
{{#if (name)}} ... {{/if}}
|
253
|
+
HBS
|
254
|
+
|
255
|
+
errors = Curlybars.validate(dependency_tree, source)
|
256
|
+
|
257
|
+
expect(errors).not_to be_empty
|
258
|
+
end
|
259
|
+
|
260
|
+
it "without errors if argument is a leaf" do
|
261
|
+
dependency_tree = { helper: :helper, argument: nil }
|
262
|
+
|
263
|
+
source = <<-HBS
|
264
|
+
{{#if (helper argument)}} ... {{/if}}
|
265
|
+
HBS
|
266
|
+
|
267
|
+
errors = Curlybars.validate(dependency_tree, source)
|
268
|
+
|
269
|
+
expect(errors).to be_empty
|
270
|
+
end
|
271
|
+
|
272
|
+
it "without errors if argument is a literal" do
|
273
|
+
dependency_tree = { helper: :helper }
|
274
|
+
|
275
|
+
source = <<-HBS
|
276
|
+
{{#if (helper 'argument')}} ... {{/if}}
|
277
|
+
HBS
|
278
|
+
|
279
|
+
errors = Curlybars.validate(dependency_tree, source)
|
280
|
+
|
281
|
+
expect(errors).to be_empty
|
282
|
+
end
|
283
|
+
|
284
|
+
it "without errors if argument is a variable" do
|
285
|
+
dependency_tree = { helper: :helper }
|
286
|
+
|
287
|
+
source = <<-HBS
|
288
|
+
{{#if (helper @var)}} ... {{/if}}
|
289
|
+
HBS
|
290
|
+
|
291
|
+
errors = Curlybars.validate(dependency_tree, source)
|
292
|
+
|
293
|
+
expect(errors).to be_empty
|
294
|
+
end
|
295
|
+
|
296
|
+
it "without errors if argument is another subexpression" do
|
297
|
+
dependency_tree = { helper: :helper }
|
298
|
+
|
299
|
+
source = <<-HBS
|
300
|
+
{{#if (helper (helper option='argument'))}} ... {{/if}}
|
301
|
+
HBS
|
302
|
+
|
303
|
+
errors = Curlybars.validate(dependency_tree, source)
|
304
|
+
|
305
|
+
expect(errors).to be_empty
|
306
|
+
end
|
307
|
+
|
308
|
+
it "without errors if option is a leaf" do
|
309
|
+
dependency_tree = { helper: :helper, argument: nil }
|
310
|
+
|
311
|
+
source = <<-HBS
|
312
|
+
{{#if (helper option=argument)}} ... {{/if}}
|
313
|
+
HBS
|
314
|
+
|
315
|
+
errors = Curlybars.validate(dependency_tree, source)
|
316
|
+
|
317
|
+
expect(errors).to be_empty
|
318
|
+
end
|
319
|
+
|
320
|
+
it "without errors if option is a literal" do
|
321
|
+
dependency_tree = { helper: :helper }
|
322
|
+
|
323
|
+
source = <<-HBS
|
324
|
+
{{#if (helper option='argument')}} ... {{/if}}
|
325
|
+
HBS
|
326
|
+
|
327
|
+
errors = Curlybars.validate(dependency_tree, source)
|
328
|
+
|
329
|
+
expect(errors).to be_empty
|
330
|
+
end
|
331
|
+
|
332
|
+
it "without errors if option is a variable" do
|
333
|
+
dependency_tree = { helper: :helper }
|
334
|
+
|
335
|
+
source = <<-HBS
|
336
|
+
{{#if (helper option=@var)}} ... {{/if}}
|
337
|
+
HBS
|
338
|
+
|
339
|
+
errors = Curlybars.validate(dependency_tree, source)
|
340
|
+
|
341
|
+
expect(errors).to be_empty
|
342
|
+
end
|
343
|
+
|
344
|
+
it "without errors if option is another subexpression" do
|
345
|
+
dependency_tree = { helper: :helper }
|
346
|
+
|
347
|
+
source = <<-HBS
|
348
|
+
{{#if (helper option=(helper))}} ... {{/if}}
|
349
|
+
HBS
|
350
|
+
|
351
|
+
errors = Curlybars.validate(dependency_tree, source)
|
352
|
+
|
353
|
+
expect(errors).to be_empty
|
354
|
+
end
|
355
|
+
|
356
|
+
it "with errors when helper does not exist" do
|
357
|
+
dependency_tree = {}
|
358
|
+
|
359
|
+
source = <<-HBS
|
360
|
+
{{#if (helper)}} ... {{/if}}
|
361
|
+
HBS
|
362
|
+
|
363
|
+
errors = Curlybars.validate(dependency_tree, source)
|
364
|
+
|
365
|
+
expect(errors).not_to be_empty
|
366
|
+
end
|
367
|
+
|
368
|
+
it "with errors when invoking a leaf with arguments" do
|
369
|
+
dependency_tree = { name: nil }
|
370
|
+
|
371
|
+
source = <<-HBS
|
372
|
+
{{#if (name 'argument')}} ... {{/if}}
|
373
|
+
HBS
|
374
|
+
|
375
|
+
errors = Curlybars.validate(dependency_tree, source)
|
376
|
+
|
377
|
+
expect(errors).not_to be_empty
|
378
|
+
end
|
379
|
+
|
380
|
+
it "with errors when invoking a leaf with options" do
|
381
|
+
dependency_tree = { name: nil }
|
382
|
+
|
383
|
+
source = <<-HBS
|
384
|
+
{{#if (name option='value')}} ... {{/if}}
|
385
|
+
HBS
|
386
|
+
|
387
|
+
errors = Curlybars.validate(dependency_tree, source)
|
388
|
+
|
389
|
+
expect(errors).not_to be_empty
|
390
|
+
end
|
391
|
+
|
392
|
+
it "with errors if argument is not a value" do
|
393
|
+
dependency_tree = { helper: :helper }
|
394
|
+
|
395
|
+
source = <<-HBS
|
396
|
+
{{#if (helper not_a_value)}} ... {{/if}}
|
397
|
+
HBS
|
398
|
+
|
399
|
+
errors = Curlybars.validate(dependency_tree, source)
|
400
|
+
|
401
|
+
expect(errors).not_to be_empty
|
402
|
+
end
|
403
|
+
|
404
|
+
it "with errors if option is not a value" do
|
405
|
+
dependency_tree = { helper: :helper }
|
406
|
+
|
407
|
+
source = <<-HBS
|
408
|
+
{{#if (helper option=not_a_value)}} ... {{/if}}
|
409
|
+
HBS
|
410
|
+
|
411
|
+
errors = Curlybars.validate(dependency_tree, source)
|
412
|
+
|
413
|
+
expect(errors).not_to be_empty
|
414
|
+
end
|
415
|
+
|
416
|
+
it "without errors when invoking a helper with the result of a subexpression" do
|
417
|
+
dependency_tree = { join: :helper, uppercase: :helper, article: nil }
|
418
|
+
|
419
|
+
source = <<-HBS
|
420
|
+
{{join (uppercase article) attribute='title' separator='-'}}
|
421
|
+
HBS
|
422
|
+
|
423
|
+
errors = Curlybars.validate(dependency_tree, source)
|
424
|
+
|
425
|
+
expect(errors).to be_empty
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: curlybars
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Libo Cannici
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2020-
|
17
|
+
date: 2020-10-27 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: actionpack
|
@@ -220,6 +220,7 @@ files:
|
|
220
220
|
- lib/curlybars/node/path.rb
|
221
221
|
- lib/curlybars/node/root.rb
|
222
222
|
- lib/curlybars/node/string.rb
|
223
|
+
- lib/curlybars/node/sub_expression.rb
|
223
224
|
- lib/curlybars/node/template.rb
|
224
225
|
- lib/curlybars/node/text.rb
|
225
226
|
- lib/curlybars/node/unless_else.rb
|
@@ -266,6 +267,7 @@ files:
|
|
266
267
|
- spec/integration/node/partial_spec.rb
|
267
268
|
- spec/integration/node/path_spec.rb
|
268
269
|
- spec/integration/node/root_spec.rb
|
270
|
+
- spec/integration/node/sub_expression_spec.rb
|
269
271
|
- spec/integration/node/template_spec.rb
|
270
272
|
- spec/integration/node/unless_else_spec.rb
|
271
273
|
- spec/integration/node/unless_spec.rb
|
@@ -293,7 +295,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
293
295
|
- !ruby/object:Gem::Version
|
294
296
|
version: '0'
|
295
297
|
requirements: []
|
296
|
-
rubygems_version: 3.
|
298
|
+
rubygems_version: 3.1.4
|
297
299
|
signing_key:
|
298
300
|
specification_version: 4
|
299
301
|
summary: Create your views using Handlebars templates!
|
@@ -319,6 +321,7 @@ test_files:
|
|
319
321
|
- spec/integration/node/unless_else_spec.rb
|
320
322
|
- spec/integration/node/output_spec.rb
|
321
323
|
- spec/integration/node/if_spec.rb
|
324
|
+
- spec/integration/node/sub_expression_spec.rb
|
322
325
|
- spec/integration/node/unless_spec.rb
|
323
326
|
- spec/integration/node/with_spec.rb
|
324
327
|
- spec/integration/node/partial_spec.rb
|