curlybars 1.8.0 → 1.9.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/curlybars/error/lex.rb +1 -1
  3. data/lib/curlybars/error/parse.rb +1 -1
  4. data/lib/curlybars/node/path.rb +11 -13
  5. data/lib/curlybars/presenter.rb +2 -2
  6. data/lib/curlybars/template_handler.rb +3 -11
  7. data/lib/curlybars/version.rb +1 -1
  8. metadata +14 -90
  9. data/spec/acceptance/application_layout_spec.rb +0 -60
  10. data/spec/acceptance/collection_blocks_spec.rb +0 -28
  11. data/spec/acceptance/global_helper_spec.rb +0 -25
  12. data/spec/curlybars/configuration_spec.rb +0 -57
  13. data/spec/curlybars/error/base_spec.rb +0 -41
  14. data/spec/curlybars/error/compile_spec.rb +0 -19
  15. data/spec/curlybars/error/lex_spec.rb +0 -25
  16. data/spec/curlybars/error/parse_spec.rb +0 -74
  17. data/spec/curlybars/error/render_spec.rb +0 -19
  18. data/spec/curlybars/error/validate_spec.rb +0 -19
  19. data/spec/curlybars/lexer_spec.rb +0 -490
  20. data/spec/curlybars/method_whitelist_spec.rb +0 -299
  21. data/spec/curlybars/processor/tilde_spec.rb +0 -60
  22. data/spec/curlybars/rendering_support_spec.rb +0 -421
  23. data/spec/curlybars/safe_buffer_spec.rb +0 -46
  24. data/spec/curlybars/template_handler_spec.rb +0 -225
  25. data/spec/integration/cache_spec.rb +0 -126
  26. data/spec/integration/comment_spec.rb +0 -60
  27. data/spec/integration/exception_spec.rb +0 -31
  28. data/spec/integration/node/block_helper_else_spec.rb +0 -420
  29. data/spec/integration/node/each_else_spec.rb +0 -408
  30. data/spec/integration/node/each_spec.rb +0 -289
  31. data/spec/integration/node/escape_spec.rb +0 -27
  32. data/spec/integration/node/helper_spec.rb +0 -186
  33. data/spec/integration/node/if_else_spec.rb +0 -170
  34. data/spec/integration/node/if_spec.rb +0 -153
  35. data/spec/integration/node/output_spec.rb +0 -66
  36. data/spec/integration/node/partial_spec.rb +0 -64
  37. data/spec/integration/node/path_spec.rb +0 -296
  38. data/spec/integration/node/root_spec.rb +0 -13
  39. data/spec/integration/node/sub_expression_spec.rb +0 -426
  40. data/spec/integration/node/template_spec.rb +0 -84
  41. data/spec/integration/node/unless_else_spec.rb +0 -139
  42. data/spec/integration/node/unless_spec.rb +0 -128
  43. data/spec/integration/node/with_spec.rb +0 -178
  44. data/spec/integration/processor/tilde_spec.rb +0 -38
  45. data/spec/integration/processors_spec.rb +0 -29
  46. data/spec/integration/visitor_spec.rb +0 -154
@@ -1,426 +0,0 @@
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("<", "&lt;")
203
- .gsub(">", "&gt;")
204
- .gsub('"', "&quot;")
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("<", "&lt;")
221
- .gsub(">", "&gt;")
222
- .gsub('"', "&quot;")
223
-
224
- expect(eval(template)).to resemble(expected_output)
225
- end
226
- end
227
- end
228
-
229
- describe "#validate" do
230
- before do
231
- allow(Curlybars.configuration).to receive(:global_helpers_provider_classes).and_return([IntegrationTest::GlobalHelperProvider])
232
- end
233
-
234
- it "without errors when global helper" do
235
- dependency_tree = {}
236
-
237
- source = <<-HBS
238
- {{#if (global_helper)}} ... {{/if}}
239
- HBS
240
-
241
- errors = Curlybars.validate(dependency_tree, source)
242
-
243
- expect(errors).to be_empty
244
- end
245
-
246
- it "with errors when invoking a leaf" do
247
- dependency_tree = { name: nil }
248
-
249
- source = <<-HBS
250
- {{#if (name)}} ... {{/if}}
251
- HBS
252
-
253
- errors = Curlybars.validate(dependency_tree, source)
254
-
255
- expect(errors).not_to be_empty
256
- end
257
-
258
- it "without errors if argument is a leaf" do
259
- dependency_tree = { helper: :helper, argument: nil }
260
-
261
- source = <<-HBS
262
- {{#if (helper argument)}} ... {{/if}}
263
- HBS
264
-
265
- errors = Curlybars.validate(dependency_tree, source)
266
-
267
- expect(errors).to be_empty
268
- end
269
-
270
- it "without errors if argument is a literal" do
271
- dependency_tree = { helper: :helper }
272
-
273
- source = <<-HBS
274
- {{#if (helper 'argument')}} ... {{/if}}
275
- HBS
276
-
277
- errors = Curlybars.validate(dependency_tree, source)
278
-
279
- expect(errors).to be_empty
280
- end
281
-
282
- it "without errors if argument is a variable" do
283
- dependency_tree = { helper: :helper }
284
-
285
- source = <<-HBS
286
- {{#if (helper @var)}} ... {{/if}}
287
- HBS
288
-
289
- errors = Curlybars.validate(dependency_tree, source)
290
-
291
- expect(errors).to be_empty
292
- end
293
-
294
- it "without errors if argument is another subexpression" do
295
- dependency_tree = { helper: :helper }
296
-
297
- source = <<-HBS
298
- {{#if (helper (helper option='argument'))}} ... {{/if}}
299
- HBS
300
-
301
- errors = Curlybars.validate(dependency_tree, source)
302
-
303
- expect(errors).to be_empty
304
- end
305
-
306
- it "without errors if option is a leaf" do
307
- dependency_tree = { helper: :helper, argument: nil }
308
-
309
- source = <<-HBS
310
- {{#if (helper option=argument)}} ... {{/if}}
311
- HBS
312
-
313
- errors = Curlybars.validate(dependency_tree, source)
314
-
315
- expect(errors).to be_empty
316
- end
317
-
318
- it "without errors if option is a literal" do
319
- dependency_tree = { helper: :helper }
320
-
321
- source = <<-HBS
322
- {{#if (helper option='argument')}} ... {{/if}}
323
- HBS
324
-
325
- errors = Curlybars.validate(dependency_tree, source)
326
-
327
- expect(errors).to be_empty
328
- end
329
-
330
- it "without errors if option is a variable" do
331
- dependency_tree = { helper: :helper }
332
-
333
- source = <<-HBS
334
- {{#if (helper option=@var)}} ... {{/if}}
335
- HBS
336
-
337
- errors = Curlybars.validate(dependency_tree, source)
338
-
339
- expect(errors).to be_empty
340
- end
341
-
342
- it "without errors if option is another subexpression" do
343
- dependency_tree = { helper: :helper }
344
-
345
- source = <<-HBS
346
- {{#if (helper option=(helper))}} ... {{/if}}
347
- HBS
348
-
349
- errors = Curlybars.validate(dependency_tree, source)
350
-
351
- expect(errors).to be_empty
352
- end
353
-
354
- it "with errors when helper does not exist" do
355
- dependency_tree = {}
356
-
357
- source = <<-HBS
358
- {{#if (helper)}} ... {{/if}}
359
- HBS
360
-
361
- errors = Curlybars.validate(dependency_tree, source)
362
-
363
- expect(errors).not_to be_empty
364
- end
365
-
366
- it "with errors when invoking a leaf with arguments" do
367
- dependency_tree = { name: nil }
368
-
369
- source = <<-HBS
370
- {{#if (name 'argument')}} ... {{/if}}
371
- HBS
372
-
373
- errors = Curlybars.validate(dependency_tree, source)
374
-
375
- expect(errors).not_to be_empty
376
- end
377
-
378
- it "with errors when invoking a leaf with options" do
379
- dependency_tree = { name: nil }
380
-
381
- source = <<-HBS
382
- {{#if (name option='value')}} ... {{/if}}
383
- HBS
384
-
385
- errors = Curlybars.validate(dependency_tree, source)
386
-
387
- expect(errors).not_to be_empty
388
- end
389
-
390
- it "with errors if argument is not a value" do
391
- dependency_tree = { helper: :helper }
392
-
393
- source = <<-HBS
394
- {{#if (helper not_a_value)}} ... {{/if}}
395
- HBS
396
-
397
- errors = Curlybars.validate(dependency_tree, source)
398
-
399
- expect(errors).not_to be_empty
400
- end
401
-
402
- it "with errors if option is not a value" do
403
- dependency_tree = { helper: :helper }
404
-
405
- source = <<-HBS
406
- {{#if (helper option=not_a_value)}} ... {{/if}}
407
- HBS
408
-
409
- errors = Curlybars.validate(dependency_tree, source)
410
-
411
- expect(errors).not_to be_empty
412
- end
413
-
414
- it "without errors when invoking a helper with the result of a subexpression" do
415
- dependency_tree = { join: :helper, uppercase: :helper, article: nil }
416
-
417
- source = <<-HBS
418
- {{join (uppercase article) attribute='title' separator='-'}}
419
- HBS
420
-
421
- errors = Curlybars.validate(dependency_tree, source)
422
-
423
- expect(errors).to be_empty
424
- end
425
- end
426
- end
@@ -1,84 +0,0 @@
1
- describe "template" do
2
- let(:global_helpers_providers) { [] }
3
-
4
- describe "#compile" do
5
- let(:post) { double("post") }
6
- let(:presenter) { IntegrationTest::Presenter.new(double("view_context"), post: post) }
7
-
8
- it "raises an exception when contexts stack is too deep (>= 10)" do
9
- template = Curlybars.compile(hbs_with_depth(10))
10
-
11
- expect do
12
- eval(template)
13
- end.to raise_error(Curlybars::Error::Render)
14
- end
15
-
16
- it "raises an exception when contexts stack is not too deep (< 10)" do
17
- template = Curlybars.compile(hbs_with_depth(9))
18
-
19
- expect do
20
- eval(template)
21
- end.not_to raise_error
22
- end
23
-
24
- it "can be empty" do
25
- template = Curlybars.compile('')
26
-
27
- expect(eval(template)).to resemble("")
28
- end
29
-
30
- it "can contain a single curly" do
31
- template = Curlybars.compile('{')
32
-
33
- expect(eval(template)).to resemble(<<-HTML)
34
- {
35
- HTML
36
- end
37
-
38
- it "can contain a single backslash" do
39
- template = Curlybars.compile('\\')
40
-
41
- expect(eval(template)).to resemble(<<-HTML)
42
- \\
43
- HTML
44
- end
45
-
46
- private
47
-
48
- def hbs_with_depth(depth)
49
- hbs = "%s"
50
- depth.times { hbs %= "{{#with this}}%s{{/with}}" }
51
- hbs %= ''
52
- end
53
- end
54
-
55
- describe "#validate" do
56
- it "without errors" do
57
- dependency_tree = { presenter: { field: nil } }
58
-
59
- source = <<-HBS
60
- {{#with presenter}}
61
- {{field}}
62
- {{/with}}
63
- HBS
64
-
65
- errors = Curlybars.validate(dependency_tree, source)
66
-
67
- expect(errors).to be_empty
68
- end
69
-
70
- it "with errors" do
71
- dependency_tree = { presenter: { field: nil } }
72
-
73
- source = <<-HBS
74
- {{#with presenter}}
75
- {{unallowed}}
76
- {{/with}}
77
- HBS
78
-
79
- errors = Curlybars.validate(dependency_tree, source)
80
-
81
- expect(errors).not_to be_empty
82
- end
83
- end
84
- end
@@ -1,139 +0,0 @@
1
- describe "{{#unless}}...{{else}}...{{/unless}}" do
2
- let(:global_helpers_providers) { [] }
3
-
4
- describe "#compile" do
5
- let(:post) { double("post") }
6
- let(:presenter) { IntegrationTest::Presenter.new(double("view_context"), post: post) }
7
-
8
- it "renders the unless_template" do
9
- allow(presenter).to receive(:allows_method?).with(:condition).and_return(true)
10
- allow(presenter).to receive(:condition).and_return(false)
11
-
12
- template = Curlybars.compile(<<-HBS)
13
- {{#unless condition}}
14
- unless_template
15
- {{else}}
16
- else_template
17
- {{/unless}}
18
- HBS
19
-
20
- expect(eval(template)).to resemble(<<-HTML)
21
- unless_template
22
- HTML
23
- end
24
-
25
- it "renders the else_template" do
26
- allow(presenter).to receive(:allows_method?).with(:condition).and_return(true)
27
- allow(presenter).to receive(:condition).and_return(true)
28
-
29
- template = Curlybars.compile(<<-HBS)
30
- {{#unless condition}}
31
- unless_template
32
- {{else}}
33
- else_template
34
- {{/unless}}
35
- HBS
36
-
37
- expect(eval(template)).to resemble(<<-HTML)
38
- else_template
39
- HTML
40
- end
41
-
42
- it "allows empty else_template" do
43
- allow(presenter).to receive(:allows_method?).with(:valid).and_return(true)
44
- allow(presenter).to receive(:valid).and_return(false)
45
-
46
- template = Curlybars.compile(<<-HBS)
47
- {{#unless valid}}
48
- unless_template
49
- {{else}}{{/unless}}
50
- HBS
51
-
52
- expect(eval(template)).to resemble(<<-HTML)
53
- unless_template
54
- HTML
55
- end
56
-
57
- it "allows empty unless_template" do
58
- allow(presenter).to receive(:allows_method?).with(:valid).and_return(true)
59
- allow(presenter).to receive(:valid).and_return(true)
60
-
61
- template = Curlybars.compile(<<-HBS)
62
- {{#unless valid}}{{else}}
63
- else_template
64
- {{/unless}}
65
- HBS
66
-
67
- expect(eval(template)).to resemble(<<-HTML)
68
- else_template
69
- HTML
70
- end
71
-
72
- it "allows empty unless_template and else_template" do
73
- allow(presenter).to receive(:allows_method?).with(:valid).and_return(true)
74
- allow(presenter).to receive(:valid).and_return(false)
75
-
76
- template = Curlybars.compile(<<-HBS)
77
- {{#unless valid}}{{else}}{{/unless}}
78
- HBS
79
-
80
- expect(eval(template)).to resemble("")
81
- end
82
- end
83
-
84
- describe "#validate" do
85
- it "validates with errors the condition" do
86
- dependency_tree = {}
87
-
88
- source = <<-HBS
89
- {{#unless condition}}{{else}}{{/unless}}
90
- HBS
91
-
92
- errors = Curlybars.validate(dependency_tree, source)
93
-
94
- expect(errors).not_to be_empty
95
- end
96
-
97
- it "validates without errors when using a helper in the condition" do
98
- dependency_tree = { helper: :helper }
99
-
100
- source = <<-HBS
101
- {{#unless helper}}{{/unless}}
102
- HBS
103
-
104
- errors = Curlybars.validate(dependency_tree, source)
105
-
106
- expect(errors).to be_empty
107
- end
108
-
109
- it "validates with errors the nested unless_template" do
110
- dependency_tree = { condition: nil }
111
-
112
- source = <<-HBS
113
- {{#unless condition}}
114
- {{unallowed_method}}
115
- {{else}}
116
- {{/unless}}
117
- HBS
118
-
119
- errors = Curlybars.validate(dependency_tree, source)
120
-
121
- expect(errors).not_to be_empty
122
- end
123
-
124
- it "validates with errors the nested else_template" do
125
- dependency_tree = { condition: nil }
126
-
127
- source = <<-HBS
128
- {{#unless condition}}
129
- {{else}}
130
- {{unallowed_method}}
131
- {{/unless}}
132
- HBS
133
-
134
- errors = Curlybars.validate(dependency_tree, source)
135
-
136
- expect(errors).not_to be_empty
137
- end
138
- end
139
- end