@handlebars/parser 2.0.0 → 2.2.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.
package/spec/parser.js CHANGED
@@ -1,358 +1,413 @@
1
- import { parse, print } from '../dist/esm';
2
- import { equals, shouldThrow } from './utils';
1
+ import { parse, print } from '../dist/esm/index.js';
2
+ import { equals, equalsAst, shouldThrow } from './utils.js';
3
3
 
4
- describe('parser', function() {
4
+ describe('parser', function () {
5
5
  function astFor(template) {
6
6
  let ast = parse(template);
7
7
  return print(ast);
8
8
  }
9
9
 
10
- it('parses simple mustaches', function() {
11
- equals(astFor('{{123}}'), '{{ NUMBER{123} [] }}\n');
12
- equals(astFor('{{"foo"}}'), '{{ "foo" [] }}\n');
13
- equals(astFor('{{false}}'), '{{ BOOLEAN{false} [] }}\n');
14
- equals(astFor('{{true}}'), '{{ BOOLEAN{true} [] }}\n');
15
- equals(astFor('{{foo}}'), '{{ PATH:foo [] }}\n');
16
- equals(astFor('{{foo?}}'), '{{ PATH:foo? [] }}\n');
17
- equals(astFor('{{foo_}}'), '{{ PATH:foo_ [] }}\n');
18
- equals(astFor('{{foo-}}'), '{{ PATH:foo- [] }}\n');
19
- equals(astFor('{{foo:}}'), '{{ PATH:foo: [] }}\n');
10
+ it('parses simple mustaches', function () {
11
+ equalsAst('{{123}}', '{{ n%123 }}');
12
+ equalsAst('{{"foo"}}', '{{ "foo" }}');
13
+ equalsAst('{{false}}', '{{ b%false }}');
14
+ equalsAst('{{true}}', '{{ b%true }}');
15
+ equalsAst('{{foo}}', '{{ p%foo }}');
16
+ equalsAst('{{foo?}}', '{{ p%foo? }}');
17
+ equalsAst('{{foo_}}', '{{ p%foo_ }}');
18
+ equalsAst('{{foo-}}', '{{ p%foo- }}');
19
+ equalsAst('{{foo:}}', '{{ p%foo: }}');
20
20
  });
21
21
 
22
- it('parses simple mustaches with data', function() {
23
- equals(astFor('{{@foo}}'), '{{ @PATH:foo [] }}\n');
22
+ it('parses simple mustaches with data', function () {
23
+ equalsAst('{{@foo}}', '{{ p%@foo }}');
24
24
  });
25
25
 
26
- it('parses simple mustaches with data paths', function() {
27
- equals(astFor('{{@../foo}}'), '{{ @PATH:foo [] }}\n');
26
+ it('parses simple mustaches with data paths', function () {
27
+ equalsAst('{{@../foo}}', '{{ p%@foo }}');
28
28
  });
29
29
 
30
- it('parses mustaches with paths', function() {
31
- equals(astFor('{{foo/bar}}'), '{{ PATH:foo/bar [] }}\n');
30
+ it('parses mustaches with paths', function () {
31
+ equalsAst('{{foo/bar}}', '{{ p%foo/bar }}');
32
+ equalsAst('{{foo.bar}}', '{{ p%foo/bar }}');
33
+ equalsAst('{{foo.#bar}}', '{{ p%foo/#bar }}');
34
+ equalsAst('{{@foo.#bar}}', '{{ p%@foo/#bar }}');
35
+
36
+ equalsAst('{{this/foo}}', '{{ p%foo }}');
37
+ equalsAst('{{this.foo}}', '{{ p%this.foo }}');
38
+ equalsAst('{{this.#foo}}', '{{ p%this.#foo }}');
32
39
  });
33
40
 
34
- it('parses mustaches with this/foo', function() {
35
- equals(astFor('{{this/foo}}'), '{{ PATH:foo [] }}\n');
41
+ it('parses mustaches with - in a path', function () {
42
+ equalsAst('{{foo-bar}}', '{{ p%foo-bar }}');
36
43
  });
37
44
 
38
- it('parses mustaches with - in a path', function() {
39
- equals(astFor('{{foo-bar}}'), '{{ PATH:foo-bar [] }}\n');
45
+ it('parses mustaches with escaped [] in a path', function () {
46
+ equalsAst('{{[foo[\\]]}}', '{{ p%foo[] }}');
40
47
  });
41
- it('parses mustaches with escaped [] in a path', function() {
42
- equals(astFor('{{[foo[\\]]}}'), '{{ PATH:foo[] [] }}\n');
48
+
49
+ it('parses escaped \\\\ in path', function () {
50
+ equalsAst('{{[foo\\\\]}}', '{{ p%foo\\ }}');
43
51
  });
44
- it('parses escaped \\\\ in path', function() {
45
- equals(astFor('{{[foo\\\\]}}'), '{{ PATH:foo\\ [] }}\n');
52
+
53
+ it('parses hash literals', function () {
54
+ equalsAst('{{(foo=bar)}}', '{{ Hash{foo=p%bar} }}');
55
+ equalsAst('{{(foo=bar)}}', '{{ p%@hello }}', {
56
+ options: {
57
+ syntax: {
58
+ hash: (hash, loc, { yy }) => {
59
+ return yy.preparePath(
60
+ true,
61
+ false,
62
+ [{ part: yy.id('hello'), original: 'hello' }],
63
+ loc
64
+ );
65
+ },
66
+ },
67
+ },
68
+ });
46
69
  });
47
70
 
48
- it('parses mustaches with parameters', function() {
49
- equals(astFor('{{foo bar}}'), '{{ PATH:foo [PATH:bar] }}\n');
71
+ it('parses array literals', function () {
72
+ equalsAst('{{[foo bar]}}', '{{ Array[p%foo, p%bar] }}', {
73
+ options: { syntax: { square: 'node' } },
74
+ });
75
+
76
+ equalsAst('{{[foo bar].baz}}', '{{ p%[Array[p%foo, p%bar]]/baz }}', {
77
+ options: { syntax: { square: 'node' } },
78
+ });
50
79
  });
51
80
 
52
- it('parses mustaches with string parameters', function() {
53
- equals(astFor('{{foo bar "baz" }}'), '{{ PATH:foo [PATH:bar, "baz"] }}\n');
81
+ it('parses mustaches that are hash literals', function () {
82
+ equalsAst('{{foo=bar}}', '{{ Hash{foo=p%bar} }}');
83
+ equalsAst('{{foo=bar}}', `{{ "HASH{foo=p%bar}" }}`, {
84
+ options: {
85
+ syntax: {
86
+ hash: (hash, loc) => {
87
+ return {
88
+ type: 'StringLiteral',
89
+ original: print(hash),
90
+ value: print(hash),
91
+ loc,
92
+ };
93
+ },
94
+ },
95
+ },
96
+ });
54
97
  });
55
98
 
56
- it('parses mustaches with NUMBER parameters', function() {
57
- equals(astFor('{{foo 1}}'), '{{ PATH:foo [NUMBER{1}] }}\n');
99
+ it('parses mustaches with parameters', function () {
100
+ equalsAst('{{foo bar}}', '{{ p%foo [p%bar] }}');
101
+ equalsAst('{{this.foo bar}}', '{{ p%this.foo [p%bar] }}');
102
+ equalsAst('{{this.foo this.bar}}', '{{ p%this.foo [p%this.bar] }}');
103
+ equalsAst('{{this.#foo this.#bar}}', '{{ p%this.#foo [p%this.#bar] }}');
104
+ equalsAst('{{foo.#bar foo.#baz}}', '{{ p%foo/#bar [p%foo/#baz] }}');
105
+ equalsAst('{{@foo.#bar @foo.#baz}}', '{{ p%@foo/#bar [p%@foo/#baz] }}');
58
106
  });
59
107
 
60
- it('parses mustaches with BOOLEAN parameters', function() {
61
- equals(astFor('{{foo true}}'), '{{ PATH:foo [BOOLEAN{true}] }}\n');
62
- equals(astFor('{{foo false}}'), '{{ PATH:foo [BOOLEAN{false}] }}\n');
108
+ it('parses mustaches with string parameters', function () {
109
+ equalsAst('{{foo bar "baz" }}', '{{ p%foo [p%bar, "baz"] }}');
110
+ equalsAst('{{this.foo bar "baz" }}', '{{ p%this.foo [p%bar, "baz"] }}');
111
+ equalsAst('{{this.#foo bar "baz" }}', '{{ p%this.#foo [p%bar, "baz"] }}');
112
+ equalsAst('{{@item.#foo bar "baz" }}', '{{ p%@item/#foo [p%bar, "baz"] }}');
63
113
  });
64
114
 
65
- it('parses mustaches with undefined and null paths', function() {
66
- equals(astFor('{{undefined}}'), '{{ UNDEFINED [] }}\n');
67
- equals(astFor('{{null}}'), '{{ NULL [] }}\n');
115
+ it('parses mustaches with NUMBER parameters', function () {
116
+ equalsAst('{{foo 1}}', '{{ p%foo [n%1] }}');
117
+ equalsAst('{{this.foo 1}}', '{{ p%this.foo [n%1] }}');
118
+ equalsAst('{{this.#foo 1}}', '{{ p%this.#foo [n%1] }}');
68
119
  });
69
- it('parses mustaches with undefined and null parameters', function() {
70
- equals(
71
- astFor('{{foo undefined null}}'),
72
- '{{ PATH:foo [UNDEFINED, NULL] }}\n'
73
- );
120
+
121
+ it('parses mustaches with BOOLEAN parameters', function () {
122
+ equalsAst('{{foo true}}', '{{ p%foo [b%true] }}');
123
+ equalsAst('{{foo false}}', '{{ p%foo [b%false] }}');
74
124
  });
75
125
 
76
- it('parses mustaches with DATA parameters', function() {
77
- equals(astFor('{{foo @bar}}'), '{{ PATH:foo [@PATH:bar] }}\n');
126
+ it('parses mustaches with undefined and null paths', function () {
127
+ equalsAst('{{undefined}}', '{{ UNDEFINED }}');
128
+ equalsAst('{{null}}', '{{ NULL }}');
78
129
  });
79
130
 
80
- it('parses mustaches with hash arguments', function() {
81
- equals(astFor('{{foo bar=baz}}'), '{{ PATH:foo [] HASH{bar=PATH:baz} }}\n');
82
- equals(astFor('{{foo bar=1}}'), '{{ PATH:foo [] HASH{bar=NUMBER{1}} }}\n');
83
- equals(
84
- astFor('{{foo bar=true}}'),
85
- '{{ PATH:foo [] HASH{bar=BOOLEAN{true}} }}\n'
86
- );
87
- equals(
88
- astFor('{{foo bar=false}}'),
89
- '{{ PATH:foo [] HASH{bar=BOOLEAN{false}} }}\n'
90
- );
91
- equals(
92
- astFor('{{foo bar=@baz}}'),
93
- '{{ PATH:foo [] HASH{bar=@PATH:baz} }}\n'
94
- );
131
+ it('parses mustaches with undefined and null parameters', function () {
132
+ equalsAst('{{foo undefined null}}', '{{ p%foo [UNDEFINED, NULL] }}');
133
+ });
95
134
 
96
- equals(
97
- astFor('{{foo bar=baz bat=bam}}'),
98
- '{{ PATH:foo [] HASH{bar=PATH:baz, bat=PATH:bam} }}\n'
135
+ it('parses mustaches with DATA parameters', function () {
136
+ equalsAst('{{foo @bar}}', '{{ p%foo [p%@bar] }}');
137
+ });
138
+
139
+ it('parses mustaches with hash arguments', function () {
140
+ equalsAst('{{foo bar=baz}}', '{{ p%foo HASH{bar=p%baz} }}');
141
+ equalsAst('{{foo bar=1}}', '{{ p%foo HASH{bar=n%1} }}');
142
+ equalsAst('{{foo bar=true}}', '{{ p%foo HASH{bar=b%true} }}');
143
+ equalsAst('{{foo bar=false}}', '{{ p%foo HASH{bar=b%false} }}');
144
+ equalsAst('{{foo bar=@baz}}', '{{ p%foo HASH{bar=p%@baz} }}');
145
+
146
+ equalsAst(
147
+ '{{foo bar=baz bat=bam}}',
148
+ '{{ p%foo HASH{bar=p%baz bat=p%bam} }}'
99
149
  );
100
- equals(
101
- astFor('{{foo bar=baz bat="bam"}}'),
102
- '{{ PATH:foo [] HASH{bar=PATH:baz, bat="bam"} }}\n'
150
+ equalsAst(
151
+ '{{foo bar=baz bat="bam"}}',
152
+ '{{ p%foo HASH{bar=p%baz bat="bam"} }}'
103
153
  );
104
154
 
105
- equals(astFor("{{foo bat='bam'}}"), '{{ PATH:foo [] HASH{bat="bam"} }}\n');
155
+ equalsAst("{{foo bat='bam'}}", '{{ p%foo HASH{bat="bam"} }}');
106
156
 
107
- equals(
108
- astFor('{{foo omg bar=baz bat="bam"}}'),
109
- '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam"} }}\n'
157
+ equalsAst(
158
+ '{{foo omg bar=baz bat="bam"}}',
159
+ '{{ p%foo [p%omg] HASH{bar=p%baz bat="bam"} }}'
110
160
  );
111
- equals(
112
- astFor('{{foo omg bar=baz bat="bam" baz=1}}'),
113
- '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=NUMBER{1}} }}\n'
161
+ equalsAst(
162
+ '{{foo omg bar=baz bat="bam" baz=1}}',
163
+ '{{ p%foo [p%omg] HASH{bar=p%baz bat="bam" baz=n%1} }}'
114
164
  );
115
- equals(
116
- astFor('{{foo omg bar=baz bat="bam" baz=true}}'),
117
- '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=BOOLEAN{true}} }}\n'
165
+ equalsAst(
166
+ '{{foo omg bar=baz bat="bam" baz=true}}',
167
+ '{{ p%foo [p%omg] HASH{bar=p%baz bat="bam" baz=b%true} }}'
118
168
  );
119
- equals(
120
- astFor('{{foo omg bar=baz bat="bam" baz=false}}'),
121
- '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=BOOLEAN{false}} }}\n'
169
+ equalsAst(
170
+ '{{foo omg bar=baz bat="bam" baz=false}}',
171
+ '{{ p%foo [p%omg] HASH{bar=p%baz bat="bam" baz=b%false} }}'
122
172
  );
123
173
  });
124
174
 
125
- it('parses contents followed by a mustache', function() {
126
- equals(
127
- astFor('foo bar {{baz}}'),
128
- "CONTENT[ 'foo bar ' ]\n{{ PATH:baz [] }}\n"
129
- );
175
+ it('parses contents followed by a mustache', function () {
176
+ equalsAst('foo bar {{baz}}', "CONTENT[ 'foo bar ' ]\n{{ p%baz }}");
130
177
  });
131
178
 
132
- it('parses a partial', function() {
133
- equals(astFor('{{> foo }}'), '{{> PARTIAL:foo }}\n');
134
- equals(astFor('{{> "foo" }}'), '{{> PARTIAL:foo }}\n');
135
- equals(astFor('{{> 1 }}'), '{{> PARTIAL:1 }}\n');
179
+ it('parses a partial', function () {
180
+ equalsAst('{{> foo }}', '{{> PARTIAL:foo }}');
181
+ equalsAst('{{> "foo" }}', '{{> PARTIAL:foo }}');
182
+ equalsAst('{{> 1 }}', '{{> PARTIAL:1 }}');
136
183
  });
137
184
 
138
- it('parses a partial with context', function() {
139
- equals(astFor('{{> foo bar}}'), '{{> PARTIAL:foo PATH:bar }}\n');
185
+ it('parses a partial with context', function () {
186
+ equalsAst('{{> foo bar}}', '{{> PARTIAL:foo p%bar }}');
140
187
  });
141
188
 
142
- it('parses a partial with hash', function() {
143
- equals(
144
- astFor('{{> foo bar=bat}}'),
145
- '{{> PARTIAL:foo HASH{bar=PATH:bat} }}\n'
146
- );
189
+ it('parses a partial with hash', function () {
190
+ equalsAst('{{> foo bar=bat}}', '{{> PARTIAL:foo HASH{bar=p%bat} }}');
147
191
  });
148
192
 
149
- it('parses a partial with context and hash', function() {
150
- equals(
151
- astFor('{{> foo bar bat=baz}}'),
152
- '{{> PARTIAL:foo PATH:bar HASH{bat=PATH:baz} }}\n'
193
+ it('parses a partial with context and hash', function () {
194
+ equalsAst(
195
+ '{{> foo bar bat=baz}}',
196
+ '{{> PARTIAL:foo p%bar HASH{bat=p%baz} }}'
153
197
  );
154
198
  });
155
199
 
156
- it('parses a partial with a complex name', function() {
157
- equals(
158
- astFor('{{> shared/partial?.bar}}'),
159
- '{{> PARTIAL:shared/partial?.bar }}\n'
200
+ it('parses a partial with a complex name', function () {
201
+ equalsAst(
202
+ '{{> shared/partial?.bar}}',
203
+ '{{> PARTIAL:shared/partial?.bar }}'
160
204
  );
161
205
  });
162
206
 
163
- it('parsers partial blocks', function() {
164
- equals(
165
- astFor('{{#> foo}}bar{{/foo}}'),
166
- "{{> PARTIAL BLOCK:foo PROGRAM:\n CONTENT[ 'bar' ]\n }}\n"
207
+ it('parsers partial blocks', function () {
208
+ equalsAst(
209
+ '{{#> foo}}bar{{/foo}}',
210
+ "{{> PARTIAL BLOCK:foo PROGRAM:\n CONTENT[ 'bar' ]\n }}"
167
211
  );
168
212
  });
169
- it('should handle parser block mismatch', function() {
213
+ it('should handle parser block mismatch', function () {
170
214
  shouldThrow(
171
- function() {
215
+ function () {
172
216
  astFor('{{#> goodbyes}}{{/hellos}}');
173
217
  },
174
218
  Error,
175
219
  /goodbyes doesn't match hellos/
176
220
  );
177
221
  });
178
- it('parsers partial blocks with arguments', function() {
179
- equals(
180
- astFor('{{#> foo context hash=value}}bar{{/foo}}'),
181
- "{{> PARTIAL BLOCK:foo PATH:context HASH{hash=PATH:value} PROGRAM:\n CONTENT[ 'bar' ]\n }}\n"
222
+ it('parsers partial blocks with arguments', function () {
223
+ equalsAst(
224
+ '{{#> foo context hash=value}}bar{{/foo}}',
225
+ "{{> PARTIAL BLOCK:foo p%context HASH{hash=p%value} PROGRAM:\n CONTENT[ 'bar' ]\n }}"
182
226
  );
183
227
  });
184
228
 
185
- it('parses a comment', function() {
186
- equals(
187
- astFor('{{! this is a comment }}'),
188
- "{{! ' this is a comment ' }}\n"
189
- );
229
+ it('parses a comment', function () {
230
+ equalsAst('{{! this is a comment }}', "{{! ' this is a comment ' }}");
190
231
  });
191
232
 
192
- it('parses a multi-line comment', function() {
193
- equals(
194
- astFor('{{!\nthis is a multi-line comment\n}}'),
195
- "{{! '\nthis is a multi-line comment\n' }}\n"
233
+ it('parses a multi-line comment', function () {
234
+ equalsAst(
235
+ '{{!\nthis is a multi-line comment\n}}',
236
+ "{{! '\nthis is a multi-line comment\n' }}"
196
237
  );
197
238
  });
198
239
 
199
- it('parses an inverse section', function() {
200
- equals(
201
- astFor('{{#foo}} bar {{^}} baz {{/foo}}'),
202
- "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n CONTENT[ ' baz ' ]\n"
240
+ it('parses an inverse section', function () {
241
+ equalsAst(
242
+ '{{#foo}} bar {{^}} baz {{/foo}}',
243
+ "BLOCK:\n p%foo\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n CONTENT[ ' baz ' ]"
203
244
  );
204
245
  });
205
246
 
206
- it('parses an inverse (else-style) section', function() {
207
- equals(
208
- astFor('{{#foo}} bar {{else}} baz {{/foo}}'),
209
- "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n CONTENT[ ' baz ' ]\n"
247
+ it('parses an inverse (else-style) section', function () {
248
+ equalsAst(
249
+ '{{#foo}} bar {{else}} baz {{/foo}}',
250
+ "BLOCK:\n p%foo\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n CONTENT[ ' baz ' ]"
210
251
  );
211
252
  });
212
253
 
213
- it('parses multiple inverse sections', function() {
214
- equals(
215
- astFor('{{#foo}} bar {{else if bar}}{{else}} baz {{/foo}}'),
216
- "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n BLOCK:\n PATH:if [PATH:bar]\n PROGRAM:\n {{^}}\n CONTENT[ ' baz ' ]\n"
254
+ it('parses multiple inverse sections', function () {
255
+ equalsAst(
256
+ '{{#foo}} bar {{else if bar}}{{else}} baz {{/foo}}',
257
+ "BLOCK:\n p%foo\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n BLOCK:\n p%if [p%bar]\n PROGRAM:\n {{^}}\n CONTENT[ ' baz ' ]"
217
258
  );
218
259
  });
219
260
 
220
- it('parses empty blocks', function() {
221
- equals(astFor('{{#foo}}{{/foo}}'), 'BLOCK:\n PATH:foo []\n PROGRAM:\n');
261
+ it('parses empty blocks', function () {
262
+ equalsAst('{{#foo}}{{/foo}}', 'BLOCK:\n p%foo\n PROGRAM:');
222
263
  });
223
264
 
224
- it('parses empty blocks with empty inverse section', function() {
225
- equals(
226
- astFor('{{#foo}}{{^}}{{/foo}}'),
227
- 'BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n'
228
- );
265
+ it('parses empty blocks with empty inverse section', function () {
266
+ equalsAst('{{#foo}}{{^}}{{/foo}}', 'BLOCK:\n p%foo\n PROGRAM:\n {{^}}');
229
267
  });
230
268
 
231
- it('parses empty blocks with empty inverse (else-style) section', function() {
232
- equals(
233
- astFor('{{#foo}}{{else}}{{/foo}}'),
234
- 'BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n'
269
+ it('parses empty blocks with empty inverse (else-style) section', function () {
270
+ equalsAst(
271
+ '{{#foo}}{{else}}{{/foo}}',
272
+ 'BLOCK:\n p%foo\n PROGRAM:\n {{^}}'
235
273
  );
236
274
  });
237
275
 
238
- it('parses non-empty blocks with empty inverse section', function() {
239
- equals(
240
- astFor('{{#foo}} bar {{^}}{{/foo}}'),
241
- "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n"
276
+ it('parses non-empty blocks with empty inverse section', function () {
277
+ equalsAst(
278
+ '{{#foo}} bar {{^}}{{/foo}}',
279
+ "BLOCK:\n p%foo\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}"
242
280
  );
243
281
  });
244
282
 
245
- it('parses non-empty blocks with empty inverse (else-style) section', function() {
246
- equals(
247
- astFor('{{#foo}} bar {{else}}{{/foo}}'),
248
- "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n"
283
+ it('parses non-empty blocks with empty inverse (else-style) section', function () {
284
+ equalsAst(
285
+ '{{#foo}} bar {{else}}{{/foo}}',
286
+ "BLOCK:\n p%foo\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}"
249
287
  );
250
288
  });
251
289
 
252
- it('parses empty blocks with non-empty inverse section', function() {
253
- equals(
254
- astFor('{{#foo}}{{^}} bar {{/foo}}'),
255
- "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n CONTENT[ ' bar ' ]\n"
290
+ it('parses empty blocks with non-empty inverse section', function () {
291
+ equalsAst(
292
+ '{{#foo}}{{^}} bar {{/foo}}',
293
+ "BLOCK:\n p%foo\n PROGRAM:\n {{^}}\n CONTENT[ ' bar ' ]"
256
294
  );
257
295
  });
258
296
 
259
- it('parses empty blocks with non-empty inverse (else-style) section', function() {
260
- equals(
261
- astFor('{{#foo}}{{else}} bar {{/foo}}'),
262
- "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n CONTENT[ ' bar ' ]\n"
297
+ it('parses empty blocks with non-empty inverse (else-style) section', function () {
298
+ equalsAst(
299
+ '{{#foo}}{{else}} bar {{/foo}}',
300
+ "BLOCK:\n p%foo\n PROGRAM:\n {{^}}\n CONTENT[ ' bar ' ]"
263
301
  );
264
302
  });
265
303
 
266
- it('parses a standalone inverse section', function() {
267
- equals(
268
- astFor('{{^foo}}bar{{/foo}}'),
269
- "BLOCK:\n PATH:foo []\n {{^}}\n CONTENT[ 'bar' ]\n"
304
+ it('parses a standalone inverse section', function () {
305
+ equalsAst(
306
+ '{{^foo}}bar{{/foo}}',
307
+ "BLOCK:\n p%foo\n {{^}}\n CONTENT[ 'bar' ]"
270
308
  );
271
309
  });
272
- it('throws on old inverse section', function() {
273
- shouldThrow(function() {
310
+
311
+ it('throws on old inverse section', function () {
312
+ shouldThrow(function () {
274
313
  astFor('{{else foo}}bar{{/foo}}');
275
314
  }, Error);
276
315
  });
277
316
 
278
- it('parses block with block params', function() {
279
- equals(
280
- astFor('{{#foo as |bar baz|}}content{{/foo}}'),
281
- "BLOCK:\n PATH:foo []\n PROGRAM:\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]\n"
317
+ it('parses block with block params', function () {
318
+ equalsAst(
319
+ '{{#foo as |bar baz|}}content{{/foo}}',
320
+ "BLOCK:\n p%foo\n PROGRAM:\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]"
282
321
  );
283
322
  });
284
323
 
285
- it('parses mustaches with sub-expressions as the callable', function() {
286
- equals(
287
- astFor('{{(my-helper foo)}}'),
288
- '{{ PATH:my-helper [PATH:foo] [] }}\n'
324
+ it('parses mustaches with sub-expressions as the callable', function () {
325
+ equalsAst('{{(my-helper foo)}}', '{{ (p%my-helper [p%foo]) }}');
326
+ });
327
+
328
+ it('parses mustaches with sub-expressions as the callable (with args)', function () {
329
+ equalsAst('{{(my-helper foo) bar}}', '{{ (p%my-helper [p%foo]) [p%bar] }}');
330
+ });
331
+
332
+ it('parses sub-expressions with a sub-expression as the callable', function () {
333
+ equalsAst('{{((my-helper foo))}}', '{{ ((p%my-helper [p%foo])) }}');
334
+ });
335
+
336
+ it('parses sub-expressions with a sub-expression as the callable (with args)', function () {
337
+ equalsAst(
338
+ '{{((my-helper foo) bar)}}',
339
+ '{{ ((p%my-helper [p%foo]) [p%bar]) }}'
289
340
  );
290
341
  });
291
342
 
292
- it('parses mustaches with sub-expressions as the callable (with args)', function() {
293
- equals(
294
- astFor('{{(my-helper foo) bar}}'),
295
- '{{ PATH:my-helper [PATH:foo] [PATH:bar] }}\n'
343
+ it('parses arguments with a sub-expression as the callable (with args)', function () {
344
+ equalsAst(
345
+ '{{my-helper ((foo) bar) baz=((foo bar))}}',
346
+ '{{ p%my-helper [((p%foo) [p%bar])] HASH{baz=((p%foo [p%bar]))} }}'
296
347
  );
297
348
  });
298
349
 
299
- it('parses sub-expressions with a sub-expression as the callable', function() {
300
- equals(
301
- astFor('{{((my-helper foo))}}'),
302
- '{{ PATH:my-helper [PATH:foo] [] [] }}\n'
350
+ it('parses paths with sub-expressions as the root', function () {
351
+ equalsAst('{{(my-helper foo).bar}}', '{{ p%[(p%my-helper [p%foo])]/bar }}');
352
+ });
353
+
354
+ it('parses paths with sub-expressions as the root as a callable', function () {
355
+ equalsAst(
356
+ '{{((my-helper foo).bar baz)}}',
357
+ '{{ (p%[(p%my-helper [p%foo])]/bar [p%baz]) }}'
303
358
  );
304
359
  });
305
360
 
306
- it('parses sub-expressions with a sub-expression as the callable (with args)', function() {
307
- equals(
308
- astFor('{{((my-helper foo) bar)}}'),
309
- '{{ PATH:my-helper [PATH:foo] [PATH:bar] [] }}\n'
361
+ it('parses paths with sub-expressions as the root as an argument', function () {
362
+ equalsAst(
363
+ '{{(foo (my-helper bar).baz)}}',
364
+ '{{ (p%foo [p%[(p%my-helper [p%bar])]/baz]) }}'
310
365
  );
311
366
  });
312
367
 
313
- it('parses arguments with a sub-expression as the callable (with args)', function() {
314
- equals(
315
- astFor('{{my-helper ((foo) bar) baz=((foo bar))}}'),
316
- '{{ PATH:my-helper [PATH:foo [] [PATH:bar]] HASH{baz=PATH:foo [PATH:bar] []} }}\n'
368
+ it('parses paths with sub-expressions as the root as a named argument', function () {
369
+ equalsAst(
370
+ '{{(foo bar=(my-helper baz).qux)}}',
371
+ '{{ (p%foo HASH{bar=p%[(p%my-helper [p%baz])]/qux}) }}'
317
372
  );
318
373
  });
319
374
 
320
- it('parses inverse block with block params', function() {
321
- equals(
322
- astFor('{{^foo as |bar baz|}}content{{/foo}}'),
323
- "BLOCK:\n PATH:foo []\n {{^}}\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]\n"
375
+ it('parses inverse block with block params', function () {
376
+ equalsAst(
377
+ '{{^foo as |bar baz|}}content{{/foo}}',
378
+ "BLOCK:\n p%foo\n {{^}}\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]"
324
379
  );
325
380
  });
326
- it('parses chained inverse block with block params', function() {
327
- equals(
328
- astFor('{{#foo}}{{else foo as |bar baz|}}content{{/foo}}'),
329
- "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n BLOCK:\n PATH:foo []\n PROGRAM:\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]\n"
381
+ it('parses chained inverse block with block params', function () {
382
+ equalsAst(
383
+ '{{#foo}}{{else foo as |bar baz|}}content{{/foo}}',
384
+ "BLOCK:\n p%foo\n PROGRAM:\n {{^}}\n BLOCK:\n p%foo\n PROGRAM:\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]"
330
385
  );
331
386
  });
332
- it("raises if there's a Parse error", function() {
387
+ it("raises if there's a Parse error", function () {
333
388
  shouldThrow(
334
- function() {
389
+ function () {
335
390
  astFor('foo{{^}}bar');
336
391
  },
337
392
  Error,
338
393
  /Parse error on line 1/
339
394
  );
340
395
  shouldThrow(
341
- function() {
396
+ function () {
342
397
  astFor('{{foo}');
343
398
  },
344
399
  Error,
345
400
  /Parse error on line 1/
346
401
  );
347
402
  shouldThrow(
348
- function() {
403
+ function () {
349
404
  astFor('{{foo &}}');
350
405
  },
351
406
  Error,
352
407
  /Parse error on line 1/
353
408
  );
354
409
  shouldThrow(
355
- function() {
410
+ function () {
356
411
  astFor('{{#goodbyes}}{{/hellos}}');
357
412
  },
358
413
  Error,
@@ -360,7 +415,7 @@ describe('parser', function() {
360
415
  );
361
416
 
362
417
  shouldThrow(
363
- function() {
418
+ function () {
364
419
  astFor('{{{{goodbyes}}}} {{{{/hellos}}}}');
365
420
  },
366
421
  Error,
@@ -368,23 +423,23 @@ describe('parser', function() {
368
423
  );
369
424
  });
370
425
 
371
- it('should handle invalid paths', function() {
426
+ it('should handle invalid paths', function () {
372
427
  shouldThrow(
373
- function() {
428
+ function () {
374
429
  astFor('{{foo/../bar}}');
375
430
  },
376
431
  Error,
377
432
  /Invalid path: foo\/\.\. - 1:2/
378
433
  );
379
434
  shouldThrow(
380
- function() {
435
+ function () {
381
436
  astFor('{{foo/./bar}}');
382
437
  },
383
438
  Error,
384
439
  /Invalid path: foo\/\. - 1:2/
385
440
  );
386
441
  shouldThrow(
387
- function() {
442
+ function () {
388
443
  astFor('{{foo/this/bar}}');
389
444
  },
390
445
  Error,
@@ -392,16 +447,16 @@ describe('parser', function() {
392
447
  );
393
448
  });
394
449
 
395
- it('knows how to report the correct line number in errors', function() {
450
+ it('knows how to report the correct line number in errors', function () {
396
451
  shouldThrow(
397
- function() {
452
+ function () {
398
453
  astFor('hello\nmy\n{{foo}');
399
454
  },
400
455
  Error,
401
456
  /Parse error on line 3/
402
457
  );
403
458
  shouldThrow(
404
- function() {
459
+ function () {
405
460
  astFor('hello\n\nmy\n\n{{foo}');
406
461
  },
407
462
  Error,
@@ -409,9 +464,9 @@ describe('parser', function() {
409
464
  );
410
465
  });
411
466
 
412
- it('knows how to report the correct line number in errors when the first character is a newline', function() {
467
+ it('knows how to report the correct line number in errors when the first character is a newline', function () {
413
468
  shouldThrow(
414
- function() {
469
+ function () {
415
470
  astFor('\n\nhello\n\nmy\n\n{{foo}');
416
471
  },
417
472
  Error,
@@ -419,31 +474,28 @@ describe('parser', function() {
419
474
  );
420
475
  });
421
476
 
422
- describe('externally compiled AST', function() {
423
- it('can pass through an already-compiled AST', function() {
477
+ describe('externally compiled AST', function () {
478
+ it('can pass through an already-compiled AST', function () {
424
479
  equals(
425
480
  astFor({
426
481
  type: 'Program',
427
- body: [{ type: 'ContentStatement', value: 'Hello' }]
482
+ body: [{ type: 'ContentStatement', value: 'Hello' }],
428
483
  }),
429
484
  "CONTENT[ 'Hello' ]\n"
430
485
  );
431
486
  });
432
487
  });
433
488
 
434
- describe('directives', function() {
435
- it('should parse block directives', function() {
436
- equals(
437
- astFor('{{#* foo}}{{/foo}}'),
438
- 'DIRECTIVE BLOCK:\n PATH:foo []\n PROGRAM:\n'
439
- );
489
+ describe('directives', function () {
490
+ it('should parse block directives', function () {
491
+ equalsAst('{{#* foo}}{{/foo}}', 'DIRECTIVE BLOCK:\n p%foo\n PROGRAM:');
440
492
  });
441
- it('should parse directives', function() {
442
- equals(astFor('{{* foo}}'), '{{ DIRECTIVE PATH:foo [] }}\n');
493
+ it('should parse directives', function () {
494
+ equalsAst('{{* foo}}', '{{ DIRECTIVE p%foo }}');
443
495
  });
444
- it('should fail if directives have inverse', function() {
496
+ it('should fail if directives have inverse', function () {
445
497
  shouldThrow(
446
- function() {
498
+ function () {
447
499
  astFor('{{#* foo}}{{^}}{{/foo}}');
448
500
  },
449
501
  Error,
@@ -452,7 +504,7 @@ describe('parser', function() {
452
504
  });
453
505
  });
454
506
 
455
- it('GH1024 - should track program location properly', function() {
507
+ it('GH1024 - should track program location properly', function () {
456
508
  let p = parse(
457
509
  '\n' +
458
510
  ' {{#if foo}}\n' +
@@ -468,21 +520,21 @@ describe('parser', function() {
468
520
  JSON.stringify(p.loc),
469
521
  JSON.stringify({
470
522
  start: { line: 1, column: 0 },
471
- end: { line: 7, column: 4 }
523
+ end: { line: 7, column: 4 },
472
524
  })
473
525
  );
474
526
  equals(
475
527
  JSON.stringify(p.body[1].program.loc),
476
528
  JSON.stringify({
477
529
  start: { line: 2, column: 13 },
478
- end: { line: 4, column: 7 }
530
+ end: { line: 4, column: 7 },
479
531
  })
480
532
  );
481
533
  equals(
482
534
  JSON.stringify(p.body[1].inverse.loc),
483
535
  JSON.stringify({
484
536
  start: { line: 4, column: 15 },
485
- end: { line: 6, column: 5 }
537
+ end: { line: 6, column: 5 },
486
538
  })
487
539
  );
488
540
  });