mvz-ruby-handlebars 0.0.8 → 0.0.9
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/CHANGELOG.md +10 -0
- data/README.md +59 -17
- data/lib/ruby-handlebars.rb +21 -38
- data/lib/ruby-handlebars/context.rb +30 -4
- data/lib/ruby-handlebars/escapers/dummy_escaper.rb +9 -0
- data/lib/ruby-handlebars/escapers/html_escaper.rb +9 -0
- data/lib/ruby-handlebars/helper.rb +23 -19
- data/lib/ruby-handlebars/helpers/default_helper.rb +28 -0
- data/lib/ruby-handlebars/helpers/each_helper.rb +31 -0
- data/lib/ruby-handlebars/helpers/helper_missing_helper.rb +18 -0
- data/lib/ruby-handlebars/helpers/if_helper.rb +23 -0
- data/lib/ruby-handlebars/helpers/register_default_helpers.rb +15 -0
- data/lib/ruby-handlebars/helpers/unless_helper.rb +21 -0
- data/lib/ruby-handlebars/parser.rb +53 -7
- data/lib/ruby-handlebars/tree.rb +99 -11
- data/lib/ruby-handlebars/version.rb +1 -1
- data/spec/handlebars_spec.rb +143 -193
- data/spec/parser_spec.rb +162 -21
- data/spec/ruby-handlebars/context_spec.rb +145 -0
- data/spec/ruby-handlebars/helpers/each_helper_spec.rb +331 -0
- data/spec/ruby-handlebars/helpers/helper_missing_helper_spec.rb +45 -0
- data/spec/ruby-handlebars/helpers/if_helper_spec.rb +90 -0
- data/spec/ruby-handlebars/helpers/register_default_helpers_spec.rb +34 -0
- data/spec/ruby-handlebars/helpers/shared.rb +55 -0
- data/spec/ruby-handlebars/helpers/unless_helper_spec.rb +65 -0
- data/spec/spec_helper.rb +5 -0
- metadata +36 -6
data/spec/parser_spec.rb
CHANGED
@@ -16,22 +16,43 @@ describe Handlebars::Parser do
|
|
16
16
|
it 'simple replacements' do
|
17
17
|
expect(parser.parse('{{plic}}')).to eq({
|
18
18
|
block_items: [
|
19
|
-
{
|
19
|
+
{replaced_unsafe_item: 'plic'}
|
20
20
|
]
|
21
21
|
})
|
22
|
+
|
22
23
|
expect(parser.parse('{{ plic}}')).to eq({
|
23
24
|
block_items: [
|
24
|
-
{
|
25
|
+
{replaced_unsafe_item: 'plic'}
|
25
26
|
]
|
26
27
|
})
|
28
|
+
|
27
29
|
expect(parser.parse('{{plic }}')).to eq({
|
28
30
|
block_items: [
|
29
|
-
{
|
31
|
+
{replaced_unsafe_item: 'plic'}
|
30
32
|
]
|
31
33
|
})
|
34
|
+
|
32
35
|
expect(parser.parse('{{ plic }}')).to eq({
|
33
36
|
block_items: [
|
34
|
-
{
|
37
|
+
{replaced_unsafe_item: 'plic'}
|
38
|
+
]
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'special variables' do
|
43
|
+
expect(parser.parse('{{@first}}')).to eq({
|
44
|
+
block_items: [
|
45
|
+
{replaced_unsafe_item: '@first'}
|
46
|
+
]
|
47
|
+
})
|
48
|
+
expect(parser.parse('{{@last}}')).to eq({
|
49
|
+
block_items: [
|
50
|
+
{replaced_unsafe_item: '@last'}
|
51
|
+
]
|
52
|
+
})
|
53
|
+
expect(parser.parse('{{@index}}')).to eq({
|
54
|
+
block_items: [
|
55
|
+
{replaced_unsafe_item: '@index'}
|
35
56
|
]
|
36
57
|
})
|
37
58
|
end
|
@@ -39,25 +60,25 @@ describe Handlebars::Parser do
|
|
39
60
|
it 'safe strings' do
|
40
61
|
expect(parser.parse('{{{plic}}}')).to eq({
|
41
62
|
block_items: [
|
42
|
-
{
|
63
|
+
{replaced_safe_item: 'plic'}
|
43
64
|
]
|
44
65
|
})
|
45
66
|
|
46
67
|
expect(parser.parse('{{{ plic}}}')).to eq({
|
47
68
|
block_items: [
|
48
|
-
{
|
69
|
+
{replaced_safe_item: 'plic'}
|
49
70
|
]
|
50
71
|
})
|
51
72
|
|
52
73
|
expect(parser.parse('{{{plic }}}')).to eq({
|
53
74
|
block_items: [
|
54
|
-
{
|
75
|
+
{replaced_safe_item: 'plic'}
|
55
76
|
]
|
56
77
|
})
|
57
78
|
|
58
79
|
expect(parser.parse('{{{ plic }}}')).to eq({
|
59
80
|
block_items: [
|
60
|
-
{
|
81
|
+
{replaced_safe_item: 'plic'}
|
61
82
|
]
|
62
83
|
})
|
63
84
|
|
@@ -68,7 +89,7 @@ describe Handlebars::Parser do
|
|
68
89
|
expect(parser.parse('{{ capitalize plic }}')).to eq({
|
69
90
|
block_items: [
|
70
91
|
{
|
71
|
-
|
92
|
+
unsafe_helper_name: 'capitalize',
|
72
93
|
parameters: {parameter_name: 'plic'}
|
73
94
|
}
|
74
95
|
]
|
@@ -79,7 +100,7 @@ describe Handlebars::Parser do
|
|
79
100
|
expect(parser.parse("{{ capitalize 'hi'}}")).to eq({
|
80
101
|
block_items: [
|
81
102
|
{
|
82
|
-
|
103
|
+
unsafe_helper_name: 'capitalize',
|
83
104
|
parameters: {parameter_name: {str_content: 'hi'}},
|
84
105
|
}
|
85
106
|
]
|
@@ -90,7 +111,7 @@ describe Handlebars::Parser do
|
|
90
111
|
expect(parser.parse("{{ capitalize ''}}")).to eq({
|
91
112
|
block_items: [
|
92
113
|
{
|
93
|
-
|
114
|
+
unsafe_helper_name: 'capitalize',
|
94
115
|
parameters: {parameter_name: {str_content: ''}},
|
95
116
|
}
|
96
117
|
]
|
@@ -101,7 +122,7 @@ describe Handlebars::Parser do
|
|
101
122
|
expect(parser.parse('{{ capitalize "hi"}}')).to eq({
|
102
123
|
block_items: [
|
103
124
|
{
|
104
|
-
|
125
|
+
unsafe_helper_name: 'capitalize',
|
105
126
|
parameters: {parameter_name: {str_content: 'hi'}},
|
106
127
|
}
|
107
128
|
]
|
@@ -112,7 +133,7 @@ describe Handlebars::Parser do
|
|
112
133
|
expect(parser.parse('{{ capitalize ""}}')).to eq({
|
113
134
|
block_items: [
|
114
135
|
{
|
115
|
-
|
136
|
+
unsafe_helper_name: 'capitalize',
|
116
137
|
parameters: {parameter_name: {str_content: ''}},
|
117
138
|
}
|
118
139
|
]
|
@@ -123,7 +144,7 @@ describe Handlebars::Parser do
|
|
123
144
|
expect(parser.parse('{{ concat plic ploc plouf }}')).to eq({
|
124
145
|
block_items: [
|
125
146
|
{
|
126
|
-
|
147
|
+
unsafe_helper_name: 'concat',
|
127
148
|
parameters: [
|
128
149
|
{parameter_name: 'plic'},
|
129
150
|
{parameter_name: 'ploc'},
|
@@ -179,6 +200,82 @@ describe Handlebars::Parser do
|
|
179
200
|
]
|
180
201
|
})
|
181
202
|
end
|
203
|
+
|
204
|
+
it 'helpers as arguments' do
|
205
|
+
expect(parser.parse('{{foo (bar baz)}}')).to eq({
|
206
|
+
block_items: [
|
207
|
+
{
|
208
|
+
unsafe_helper_name: 'foo',
|
209
|
+
parameters: {
|
210
|
+
safe_helper_name: 'bar',
|
211
|
+
parameters: {parameter_name: 'baz'}
|
212
|
+
}
|
213
|
+
}
|
214
|
+
]
|
215
|
+
})
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'as helpers' do
|
220
|
+
it 'recognizes the "as |...|" writing' do
|
221
|
+
expect(parser.parse('{{#each items as |item|}}plic{{/each}}')).to eq({
|
222
|
+
block_items: [
|
223
|
+
{
|
224
|
+
helper_name: 'each',
|
225
|
+
parameters: {parameter_name: 'items'},
|
226
|
+
as_parameters: {parameter_name: 'item'},
|
227
|
+
block_items: [
|
228
|
+
{template_content: 'plic'}
|
229
|
+
]
|
230
|
+
}
|
231
|
+
]
|
232
|
+
})
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'supports the "else" statement' do
|
236
|
+
expect(parser.parse('{{#each items as |item|}}plic{{else}}Hummm, empty{{/each}}')).to eq({
|
237
|
+
block_items: [
|
238
|
+
{
|
239
|
+
helper_name: 'each',
|
240
|
+
parameters: {parameter_name: 'items'},
|
241
|
+
as_parameters: {parameter_name: 'item'},
|
242
|
+
block_items: [
|
243
|
+
{template_content: 'plic'}
|
244
|
+
],
|
245
|
+
else_block_items: [
|
246
|
+
{template_content: 'Hummm, empty'}
|
247
|
+
]
|
248
|
+
}
|
249
|
+
]
|
250
|
+
})
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'can be imbricated' do
|
254
|
+
expect(parser.parse('{{#each items as |item|}}{{#each item as |char index|}}show item{{/each}}{{else}}Hummm, empty{{/each}}')).to eq({
|
255
|
+
block_items: [
|
256
|
+
{
|
257
|
+
helper_name: 'each',
|
258
|
+
parameters: {parameter_name: 'items'},
|
259
|
+
as_parameters: {parameter_name: 'item'},
|
260
|
+
block_items: [
|
261
|
+
{
|
262
|
+
helper_name: 'each',
|
263
|
+
parameters: {parameter_name: 'item'},
|
264
|
+
as_parameters: [
|
265
|
+
{parameter_name: 'char'},
|
266
|
+
{parameter_name: 'index'}],
|
267
|
+
block_items: [
|
268
|
+
{template_content: 'show item'}
|
269
|
+
]
|
270
|
+
}
|
271
|
+
],
|
272
|
+
else_block_items: [
|
273
|
+
{template_content: 'Hummm, empty'}
|
274
|
+
]
|
275
|
+
}
|
276
|
+
]
|
277
|
+
})
|
278
|
+
end
|
182
279
|
end
|
183
280
|
|
184
281
|
context 'if block' do
|
@@ -203,8 +300,9 @@ describe Handlebars::Parser do
|
|
203
300
|
helper_name: 'if',
|
204
301
|
parameters: {parameter_name: 'something'},
|
205
302
|
block_items: [
|
206
|
-
{template_content: 'Ok'}
|
207
|
-
|
303
|
+
{template_content: 'Ok'}
|
304
|
+
],
|
305
|
+
else_block_items: [
|
208
306
|
{template_content: 'not ok'}
|
209
307
|
]
|
210
308
|
}
|
@@ -232,6 +330,49 @@ describe Handlebars::Parser do
|
|
232
330
|
]
|
233
331
|
})
|
234
332
|
end
|
333
|
+
|
334
|
+
it 'imbricated block with elses' do
|
335
|
+
expect(parser.parse('{{#if something}}{{#if another_thing}}Case 1{{else}}Case 2{{/if}}{{else}}{{#if another_thing}}Case 3{{else}}Case 4{{/if}}{{/if}}')).to eq({
|
336
|
+
block_items: [
|
337
|
+
{
|
338
|
+
helper_name: "if",
|
339
|
+
parameters: {parameter_name: "something"},
|
340
|
+
block_items: [
|
341
|
+
{
|
342
|
+
helper_name: "if",
|
343
|
+
parameters: {parameter_name: "another_thing"},
|
344
|
+
block_items:[
|
345
|
+
{
|
346
|
+
template_content:"Case 1"
|
347
|
+
}
|
348
|
+
],
|
349
|
+
else_block_items: [
|
350
|
+
{
|
351
|
+
template_content: "Case 2"
|
352
|
+
}
|
353
|
+
]
|
354
|
+
}
|
355
|
+
],
|
356
|
+
else_block_items: [
|
357
|
+
{
|
358
|
+
helper_name: "if",
|
359
|
+
parameters: {parameter_name: "another_thing"},
|
360
|
+
block_items:[
|
361
|
+
{
|
362
|
+
template_content:"Case 3"
|
363
|
+
}
|
364
|
+
],
|
365
|
+
else_block_items: [
|
366
|
+
{
|
367
|
+
template_content: "Case 4"
|
368
|
+
}
|
369
|
+
]
|
370
|
+
}
|
371
|
+
]
|
372
|
+
}
|
373
|
+
]
|
374
|
+
})
|
375
|
+
end
|
235
376
|
end
|
236
377
|
|
237
378
|
context 'each block' do
|
@@ -243,7 +384,7 @@ describe Handlebars::Parser do
|
|
243
384
|
parameters: {parameter_name: 'people'},
|
244
385
|
block_items: [
|
245
386
|
{template_content: ' '},
|
246
|
-
{
|
387
|
+
{replaced_unsafe_item: 'this.name'},
|
247
388
|
{template_content: ' '}
|
248
389
|
]
|
249
390
|
}
|
@@ -259,14 +400,14 @@ describe Handlebars::Parser do
|
|
259
400
|
parameters: {parameter_name: 'people'},
|
260
401
|
block_items: [
|
261
402
|
{template_content: ' '},
|
262
|
-
{
|
403
|
+
{replaced_unsafe_item: 'this.name'},
|
263
404
|
{template_content: ' <ul> '},
|
264
405
|
{
|
265
406
|
helper_name: 'each',
|
266
407
|
parameters: {parameter_name: 'this.contact'},
|
267
408
|
block_items: [
|
268
409
|
{template_content: ' <li>'},
|
269
|
-
{
|
410
|
+
{replaced_unsafe_item: 'this'},
|
270
411
|
{template_content: '</li> '}
|
271
412
|
]
|
272
413
|
},
|
@@ -299,7 +440,7 @@ describe Handlebars::Parser do
|
|
299
440
|
expect(parser.parse('Hi }{{ hey }}')).to eq({
|
300
441
|
block_items: [
|
301
442
|
{template_content: 'Hi }'},
|
302
|
-
{
|
443
|
+
{replaced_unsafe_item: 'hey'}
|
303
444
|
]
|
304
445
|
})
|
305
446
|
end
|
@@ -308,7 +449,7 @@ describe Handlebars::Parser do
|
|
308
449
|
expect(parser.parse('}{{ hey }}')).to eq({
|
309
450
|
block_items: [
|
310
451
|
{template_content: '}'},
|
311
|
-
{
|
452
|
+
{replaced_unsafe_item: 'hey'}
|
312
453
|
]
|
313
454
|
})
|
314
455
|
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require_relative '../../lib/ruby-handlebars/context'
|
3
|
+
|
4
|
+
describe Handlebars::Context do
|
5
|
+
let(:ctx) { described_class.new(nil, data) }
|
6
|
+
|
7
|
+
context 'get' do
|
8
|
+
let(:data) { {
|
9
|
+
key_data: 'Some value'
|
10
|
+
} }
|
11
|
+
|
12
|
+
before do
|
13
|
+
ctx.add_item(:key_locals, 'Some other value')
|
14
|
+
ctx.add_item(:a_list, ['a', 'b', 'c'])
|
15
|
+
ctx.add_item(:a_hash, {key: 'A third value'})
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'fetches data stored in the context' do
|
19
|
+
expect(ctx.get('key_data')).to eq('Some value')
|
20
|
+
expect(ctx.get('key_locals')).to eq('Some other value')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'uses data from @locals before @data' do
|
24
|
+
ctx.add_item(:key_data, 'Now stored in @locals')
|
25
|
+
|
26
|
+
expect(ctx.get('key_data')).to eq('Now stored in @locals')
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when digging inside data' do
|
30
|
+
it 'uses keys separated by dots' do
|
31
|
+
expect(ctx.get('a_hash.key')).to eq('A third value')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'can also use methods' do
|
35
|
+
expect(ctx.get('a_list.first')).to eq('a')
|
36
|
+
expect(ctx.get('a_list.last')).to eq('c')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'add_item' do
|
42
|
+
let(:data) { {} }
|
43
|
+
|
44
|
+
it 'adds a new key to the stored data' do
|
45
|
+
expect(ctx.get('my_key')).to be nil
|
46
|
+
ctx.add_item('my_key', 'With some value')
|
47
|
+
expect(ctx.get('my_key')).to eq('With some value')
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'overrides existing values' do
|
51
|
+
ctx.add_item('a', 12)
|
52
|
+
ctx.add_item('a', 25)
|
53
|
+
|
54
|
+
expect(ctx.get('a')).to eq(25)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'does not make differences between string and sym keys' do
|
58
|
+
ctx.add_item('a', 12)
|
59
|
+
ctx.add_item(:a, 25)
|
60
|
+
|
61
|
+
expect(ctx.get('a')).to eq(25)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'add_items' do
|
66
|
+
let(:data) { {} }
|
67
|
+
|
68
|
+
it 'is basically a wrapper around add_item to add multiple items' do
|
69
|
+
allow(ctx).to receive(:add_item)
|
70
|
+
|
71
|
+
ctx.add_items(a: 'One key', b: 'A second key', c: 'A third key')
|
72
|
+
expect(ctx).to have_received(:add_item).at_most(3).times
|
73
|
+
expect(ctx).to have_received(:add_item).once.with(:a, 'One key')
|
74
|
+
expect(ctx).to have_received(:add_item).once.with(:b, 'A second key')
|
75
|
+
expect(ctx).to have_received(:add_item).once.with(:c, 'A third key')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with_temporary_context' do
|
80
|
+
let(:data) { {} }
|
81
|
+
|
82
|
+
before do
|
83
|
+
ctx.add_items(
|
84
|
+
key: 'some key',
|
85
|
+
value: 'some value'
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'allows creating temporary variables' do
|
90
|
+
expect(ctx.get('unknown_key')).to be nil
|
91
|
+
|
92
|
+
ctx.with_temporary_context(unknown_key: 42) do
|
93
|
+
expect(ctx.get('unknown_key')).to eq(42)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'can override an existing variable' do
|
98
|
+
ctx.with_temporary_context(value: 'A completelly new value') do
|
99
|
+
expect(ctx.get('value')).to eq('A completelly new value')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'provides mutable variables (well, variables ...)' do
|
104
|
+
ctx.with_temporary_context(unknown_key: 42) do
|
105
|
+
expect(ctx.get('unknown_key')).to eq(42)
|
106
|
+
ctx.add_item('unknown_key', 56)
|
107
|
+
expect(ctx.get('unknown_key')).to eq(56)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'after the block, existing variables are restored' do
|
112
|
+
ctx.with_temporary_context(value: 'A completelly new value') do
|
113
|
+
expect(ctx.get('value')).to eq('A completelly new value')
|
114
|
+
end
|
115
|
+
|
116
|
+
expect(ctx.get('value')).to eq('some value')
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'after the block, the declared variables are not available anymore' do
|
120
|
+
ctx.with_temporary_context(unknown_key: 42) do
|
121
|
+
expect(ctx.get('unknown_key')).to eq(42)
|
122
|
+
end
|
123
|
+
|
124
|
+
expect(ctx.get('unknown_key')).to be nil
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'returns the data executed by the block' do
|
128
|
+
expect( ctx.with_temporary_context(value: 'A completelly new value') { 12 } ).to eq(12)
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'when data are stored in @data' do
|
132
|
+
let(:data) { {my_key: "With some value"} }
|
133
|
+
|
134
|
+
it 'let them available after the block is executed' do
|
135
|
+
expect(ctx.get('my_key')).to eq('With some value')
|
136
|
+
|
137
|
+
ctx.with_temporary_context(my_key: 12) do
|
138
|
+
expect(ctx.get('my_key')).to eq(12)
|
139
|
+
end
|
140
|
+
|
141
|
+
expect(ctx.get('my_key')).to eq('With some value')
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|