@weborigami/language 0.3.3-jse.3 → 0.3.4-jse.4
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/package.json +3 -3
- package/src/compiler/compile.js +5 -3
- package/src/compiler/isOrigamiFrontMatter.js +4 -3
- package/src/compiler/optimize.js +225 -112
- package/src/compiler/origami.pegjs +214 -201
- package/src/compiler/parse.js +1403 -1473
- package/src/compiler/parserHelpers.js +65 -157
- package/src/runtime/expressionObject.js +13 -7
- package/src/runtime/handlers.js +1 -1
- package/src/runtime/jsGlobals.js +7 -0
- package/src/runtime/ops.js +4 -18
- package/test/compiler/compile.test.js +14 -9
- package/test/compiler/optimize.test.js +234 -64
- package/test/compiler/parse.test.js +618 -476
- package/test/runtime/expressionObject.test.js +2 -2
- package/test/runtime/handlers.test.js +2 -2
- package/src/runtime/templateStandard.js +0 -13
- package/test/runtime/templateText.test.js +0 -18
|
@@ -21,38 +21,47 @@ describe("Origami parser", () => {
|
|
|
21
21
|
|
|
22
22
|
describe("angleBracketLiteral", () => {
|
|
23
23
|
test("with path", () => {
|
|
24
|
+
assertParse("angleBracketLiteral", "<index.html>", [
|
|
25
|
+
markers.traverse,
|
|
26
|
+
[markers.external, "index.html"],
|
|
27
|
+
]);
|
|
24
28
|
assertParse(
|
|
25
29
|
"angleBracketLiteral",
|
|
26
|
-
"<
|
|
27
|
-
[[ops.scope], [ops.literal, "index.html"]],
|
|
28
|
-
"jse"
|
|
29
|
-
);
|
|
30
|
-
assertParse(
|
|
31
|
-
"angleBracketLiteral",
|
|
32
|
-
"<foo/bar/baz>",
|
|
30
|
+
"<Path with spaces (and parens).html>",
|
|
33
31
|
[
|
|
34
|
-
|
|
35
|
-
[
|
|
36
|
-
|
|
37
|
-
[ops.literal, "baz"],
|
|
38
|
-
],
|
|
39
|
-
"jse"
|
|
32
|
+
markers.traverse,
|
|
33
|
+
[markers.external, "Path with spaces (and parens).html"],
|
|
34
|
+
]
|
|
40
35
|
);
|
|
36
|
+
assertParse("angleBracketLiteral", "<foo/bar/baz>", [
|
|
37
|
+
markers.traverse,
|
|
38
|
+
[markers.external, "foo/"],
|
|
39
|
+
[ops.literal, "bar/"],
|
|
40
|
+
[ops.literal, "baz"],
|
|
41
|
+
]);
|
|
41
42
|
});
|
|
42
43
|
|
|
43
44
|
test("root directory", () => {
|
|
44
|
-
assertParse("angleBracketLiteral", "</>", [
|
|
45
|
+
assertParse("angleBracketLiteral", "</>", [
|
|
46
|
+
markers.traverse,
|
|
47
|
+
[markers.external, "/"],
|
|
48
|
+
]);
|
|
45
49
|
assertParse("angleBracketLiteral", "</etc/passwd>", [
|
|
46
|
-
|
|
50
|
+
markers.traverse,
|
|
51
|
+
[markers.external, "/"],
|
|
47
52
|
[ops.literal, "etc/"],
|
|
48
53
|
[ops.literal, "passwd"],
|
|
49
54
|
]);
|
|
50
55
|
});
|
|
51
56
|
|
|
52
57
|
test("home directory", () => {
|
|
53
|
-
assertParse("angleBracketLiteral", "<~>", [
|
|
58
|
+
assertParse("angleBracketLiteral", "<~>", [
|
|
59
|
+
markers.traverse,
|
|
60
|
+
[markers.external, "~"],
|
|
61
|
+
]);
|
|
54
62
|
assertParse("angleBracketLiteral", "<~/.bash_profile>", [
|
|
55
|
-
|
|
63
|
+
markers.traverse,
|
|
64
|
+
[markers.external, "~/"],
|
|
56
65
|
[ops.literal, ".bash_profile"],
|
|
57
66
|
]);
|
|
58
67
|
});
|
|
@@ -117,12 +126,12 @@ describe("Origami parser", () => {
|
|
|
117
126
|
assertParse("arrowFunction", "() => foo", [
|
|
118
127
|
ops.lambda,
|
|
119
128
|
[],
|
|
120
|
-
[markers.
|
|
129
|
+
[markers.traverse, [markers.reference, "foo"]],
|
|
121
130
|
]);
|
|
122
131
|
assertParse("arrowFunction", "x => y", [
|
|
123
132
|
ops.lambda,
|
|
124
133
|
[[ops.literal, "x"]],
|
|
125
|
-
[markers.
|
|
134
|
+
[markers.traverse, [markers.reference, "y"]],
|
|
126
135
|
]);
|
|
127
136
|
assertParse("arrowFunction", "(a, b, c) ⇒ fn(a, b, c)", [
|
|
128
137
|
ops.lambda,
|
|
@@ -132,10 +141,10 @@ describe("Origami parser", () => {
|
|
|
132
141
|
[ops.literal, "c"],
|
|
133
142
|
],
|
|
134
143
|
[
|
|
135
|
-
[markers.
|
|
136
|
-
[markers.
|
|
137
|
-
[markers.
|
|
138
|
-
[markers.
|
|
144
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
145
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
146
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
147
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
139
148
|
],
|
|
140
149
|
]);
|
|
141
150
|
assertParse("arrowFunction", "a => b => fn(a, b)", [
|
|
@@ -145,9 +154,9 @@ describe("Origami parser", () => {
|
|
|
145
154
|
ops.lambda,
|
|
146
155
|
[[ops.literal, "b"]],
|
|
147
156
|
[
|
|
148
|
-
[markers.
|
|
149
|
-
[markers.
|
|
150
|
-
[markers.
|
|
157
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
158
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
159
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
151
160
|
],
|
|
152
161
|
],
|
|
153
162
|
]);
|
|
@@ -180,75 +189,74 @@ describe("Origami parser", () => {
|
|
|
180
189
|
describe("callExpression", () => {
|
|
181
190
|
test("with parentheses arguments", () => {
|
|
182
191
|
assertParse("callExpression", "fn()", [
|
|
183
|
-
[markers.
|
|
192
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
184
193
|
undefined,
|
|
185
194
|
]);
|
|
186
195
|
assertParse("callExpression", "foo.js(arg)", [
|
|
187
|
-
[markers.
|
|
188
|
-
[markers.
|
|
196
|
+
[markers.traverse, [markers.reference, "foo.js"]],
|
|
197
|
+
[markers.traverse, [markers.reference, "arg"]],
|
|
189
198
|
]);
|
|
190
199
|
assertParse("callExpression", "fn(a, b)", [
|
|
191
|
-
[markers.
|
|
192
|
-
[markers.
|
|
193
|
-
[markers.
|
|
200
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
201
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
202
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
194
203
|
]);
|
|
195
204
|
assertParse("callExpression", "foo.js( a , b )", [
|
|
196
|
-
[markers.
|
|
197
|
-
[markers.
|
|
198
|
-
[markers.
|
|
205
|
+
[markers.traverse, [markers.reference, "foo.js"]],
|
|
206
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
207
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
199
208
|
]);
|
|
200
209
|
assertParse("callExpression", "fn()(arg)", [
|
|
201
|
-
[[markers.
|
|
202
|
-
[markers.
|
|
210
|
+
[[markers.traverse, [markers.reference, "fn"]], undefined],
|
|
211
|
+
[markers.traverse, [markers.reference, "arg"]],
|
|
203
212
|
]);
|
|
204
213
|
});
|
|
214
|
+
|
|
205
215
|
test("call chains", () => {
|
|
206
216
|
assertParse("callExpression", "(foo.js())('arg')", [
|
|
207
|
-
[[markers.
|
|
217
|
+
[[markers.traverse, [markers.reference, "foo.js"]], undefined],
|
|
208
218
|
[ops.literal, "arg"],
|
|
209
219
|
]);
|
|
210
220
|
assertParse("callExpression", "fn('a')('b')", [
|
|
211
221
|
[
|
|
212
|
-
[markers.
|
|
222
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
213
223
|
[ops.literal, "a"],
|
|
214
224
|
],
|
|
215
225
|
[ops.literal, "b"],
|
|
216
226
|
]);
|
|
217
227
|
assertParse("callExpression", "(foo.js())(a, b)", [
|
|
218
|
-
[[markers.
|
|
219
|
-
[markers.
|
|
220
|
-
[markers.
|
|
228
|
+
[[markers.traverse, [markers.reference, "foo.js"]], undefined],
|
|
229
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
230
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
221
231
|
]);
|
|
222
232
|
});
|
|
233
|
+
|
|
223
234
|
test("with paths", () => {
|
|
224
|
-
assertParse("callExpression", "/", [ops.rootDirectory]);
|
|
225
235
|
assertParse("callExpression", "tree/", [
|
|
226
236
|
ops.unpack,
|
|
227
|
-
[markers.
|
|
237
|
+
[markers.traverse, [markers.reference, "tree/"]],
|
|
228
238
|
]);
|
|
229
239
|
assertParse("callExpression", "tree/foo/bar", [
|
|
230
|
-
markers.
|
|
231
|
-
[
|
|
240
|
+
markers.traverse,
|
|
241
|
+
[markers.reference, "tree/"],
|
|
232
242
|
[ops.literal, "foo/"],
|
|
233
243
|
[ops.literal, "bar"],
|
|
234
244
|
]);
|
|
235
245
|
assertParse("callExpression", "tree/foo/bar/", [
|
|
236
|
-
|
|
237
|
-
[
|
|
238
|
-
|
|
239
|
-
|
|
246
|
+
ops.unpack,
|
|
247
|
+
[
|
|
248
|
+
markers.traverse,
|
|
249
|
+
[markers.reference, "tree/"],
|
|
250
|
+
[ops.literal, "foo/"],
|
|
251
|
+
[ops.literal, "bar/"],
|
|
252
|
+
],
|
|
240
253
|
]);
|
|
241
254
|
// Consecutive slahes in a path are removed
|
|
242
|
-
assertParse("callExpression", "
|
|
243
|
-
markers.
|
|
244
|
-
[
|
|
255
|
+
assertParse("callExpression", "tree//key", [
|
|
256
|
+
markers.traverse,
|
|
257
|
+
[markers.reference, "tree/"],
|
|
245
258
|
[ops.literal, "key"],
|
|
246
259
|
]);
|
|
247
|
-
assertParse("callExpression", "/foo/bar", [
|
|
248
|
-
[ops.rootDirectory],
|
|
249
|
-
[ops.literal, "foo/"],
|
|
250
|
-
[ops.literal, "bar"],
|
|
251
|
-
]);
|
|
252
260
|
assertParse("callExpression", "{ a: 1, b: 2}/b", [
|
|
253
261
|
[ops.object, ["a", [ops.literal, 1]], ["b", [ops.literal, 2]]],
|
|
254
262
|
[ops.literal, "b"],
|
|
@@ -259,22 +267,19 @@ describe("Origami parser", () => {
|
|
|
259
267
|
[ops.literal, "bar"],
|
|
260
268
|
]);
|
|
261
269
|
});
|
|
270
|
+
|
|
262
271
|
test("path and parentheses chains", () => {
|
|
263
272
|
assertParse("callExpression", "foo.js()/key", [
|
|
264
|
-
[[markers.
|
|
273
|
+
[[markers.traverse, [markers.reference, "foo.js"]], undefined],
|
|
265
274
|
[ops.literal, "key"],
|
|
266
275
|
]);
|
|
267
276
|
assertParse("callExpression", "tree/key()", [
|
|
268
|
-
[markers.
|
|
277
|
+
[markers.traverse, [markers.reference, "tree/"], [ops.literal, "key"]],
|
|
269
278
|
undefined,
|
|
270
279
|
]);
|
|
271
|
-
assertParse("callExpression", "(tree)/", [
|
|
272
|
-
ops.unpack,
|
|
273
|
-
[markers.reference, [ops.literal, "tree/"]],
|
|
274
|
-
]);
|
|
275
280
|
assertParse("callExpression", "fn()/key()", [
|
|
276
281
|
[
|
|
277
|
-
[[markers.
|
|
282
|
+
[[markers.traverse, [markers.reference, "fn"]], undefined],
|
|
278
283
|
[ops.literal, "key"],
|
|
279
284
|
],
|
|
280
285
|
undefined,
|
|
@@ -286,68 +291,44 @@ describe("Origami parser", () => {
|
|
|
286
291
|
[ops.literal, "dropbox/"],
|
|
287
292
|
[ops.literal, "auth"],
|
|
288
293
|
],
|
|
289
|
-
[markers.
|
|
294
|
+
[markers.traverse, [markers.reference, "creds"]],
|
|
290
295
|
]);
|
|
291
296
|
});
|
|
297
|
+
|
|
292
298
|
test("tagged templates", () => {
|
|
293
299
|
assertParse("callExpression", "indent`hello`", [
|
|
294
|
-
[markers.
|
|
300
|
+
[markers.traverse, [markers.reference, "indent"]],
|
|
295
301
|
[ops.literal, ["hello"]],
|
|
296
302
|
]);
|
|
297
303
|
assertParse("callExpression", "fn.js`Hello, world.`", [
|
|
298
|
-
[markers.
|
|
304
|
+
[markers.traverse, [markers.reference, "fn.js"]],
|
|
299
305
|
[ops.literal, ["Hello, world."]],
|
|
300
306
|
]);
|
|
301
307
|
});
|
|
308
|
+
|
|
302
309
|
test("protocols", () => {
|
|
303
310
|
assertParse("callExpression", "files:src/assets", [
|
|
304
311
|
[markers.global, "files:"],
|
|
305
312
|
[ops.literal, "src/"],
|
|
306
313
|
[ops.literal, "assets"],
|
|
307
314
|
]);
|
|
308
|
-
assertParse("callExpression", "
|
|
309
|
-
[markers.global, "new:"],
|
|
315
|
+
assertParse("callExpression", "<node:process>.env", [
|
|
310
316
|
[
|
|
311
|
-
[markers.global, "
|
|
312
|
-
[ops.literal, "
|
|
317
|
+
[markers.global, "node:"],
|
|
318
|
+
[ops.literal, "process"],
|
|
313
319
|
],
|
|
314
|
-
[ops.literal, "
|
|
320
|
+
[ops.literal, "env"],
|
|
315
321
|
]);
|
|
316
322
|
});
|
|
317
323
|
});
|
|
318
324
|
|
|
319
|
-
test("callExpression using property acccess", () => {
|
|
320
|
-
assertParse("callExpression", "(foo).bar", [
|
|
321
|
-
markers.reference,
|
|
322
|
-
[ops.literal, "foo/"],
|
|
323
|
-
[ops.literal, "bar"],
|
|
324
|
-
]);
|
|
325
|
-
assertParse("callExpression", "(foo).bar.baz", [
|
|
326
|
-
markers.reference,
|
|
327
|
-
[ops.literal, "foo/"],
|
|
328
|
-
[ops.literal, "bar/"],
|
|
329
|
-
[ops.literal, "baz"],
|
|
330
|
-
]);
|
|
331
|
-
assertParse("callExpression", "foo[bar]", [
|
|
332
|
-
markers.reference,
|
|
333
|
-
[ops.literal, "foo/"],
|
|
334
|
-
[markers.reference, [ops.literal, "bar"]],
|
|
335
|
-
]);
|
|
336
|
-
assertParse(
|
|
337
|
-
"callExpression",
|
|
338
|
-
"Tree.map",
|
|
339
|
-
[markers.reference, [ops.literal, "Tree/"], [ops.literal, "map"]],
|
|
340
|
-
"jse"
|
|
341
|
-
);
|
|
342
|
-
});
|
|
343
|
-
|
|
344
325
|
test("commaExpression", () => {
|
|
345
326
|
assertParse("commaExpression", "1", [ops.literal, 1]);
|
|
346
327
|
assertParse("commaExpression", "a, b, c", [
|
|
347
328
|
ops.comma,
|
|
348
|
-
[markers.
|
|
349
|
-
[markers.
|
|
350
|
-
[markers.
|
|
329
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
330
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
331
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
351
332
|
]);
|
|
352
333
|
});
|
|
353
334
|
|
|
@@ -355,19 +336,19 @@ describe("Origami parser", () => {
|
|
|
355
336
|
assertParse("conditionalExpression", "1", [ops.literal, 1]);
|
|
356
337
|
assertParse("conditionalExpression", "true ? 1 : 0", [
|
|
357
338
|
ops.conditional,
|
|
358
|
-
[markers.
|
|
339
|
+
[markers.traverse, [markers.reference, "true"]],
|
|
359
340
|
[ops.literal, 1],
|
|
360
341
|
[ops.literal, 0],
|
|
361
342
|
]);
|
|
362
343
|
assertParse("conditionalExpression", "false ? () => 1 : 0", [
|
|
363
344
|
ops.conditional,
|
|
364
|
-
[markers.
|
|
345
|
+
[markers.traverse, [markers.reference, "false"]],
|
|
365
346
|
[ops.lambda, [], [ops.lambda, [], [ops.literal, 1]]],
|
|
366
347
|
[ops.literal, 0],
|
|
367
348
|
]);
|
|
368
349
|
assertParse("conditionalExpression", "false ? =1 : 0", [
|
|
369
350
|
ops.conditional,
|
|
370
|
-
[markers.
|
|
351
|
+
[markers.traverse, [markers.reference, "false"]],
|
|
371
352
|
[ops.lambda, [], [ops.lambda, [[ops.literal, "_"]], [ops.literal, 1]]],
|
|
372
353
|
[ops.literal, 0],
|
|
373
354
|
]);
|
|
@@ -383,10 +364,10 @@ describe("Origami parser", () => {
|
|
|
383
364
|
ops.strictEqual,
|
|
384
365
|
[
|
|
385
366
|
ops.strictEqual,
|
|
386
|
-
[markers.
|
|
387
|
-
[markers.
|
|
367
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
368
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
388
369
|
],
|
|
389
|
-
[markers.
|
|
370
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
390
371
|
]);
|
|
391
372
|
assertParse("equalityExpression", "1 !== 1", [
|
|
392
373
|
ops.notStrictEqual,
|
|
@@ -440,182 +421,244 @@ Body`,
|
|
|
440
421
|
]);
|
|
441
422
|
});
|
|
442
423
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
"expression",
|
|
446
|
-
|
|
424
|
+
describe("expression", () => {
|
|
425
|
+
test("slash with and without spaces", () => {
|
|
426
|
+
assertParse("expression", "x/y", [
|
|
427
|
+
markers.traverse,
|
|
428
|
+
[markers.reference, "x/"],
|
|
429
|
+
[ops.literal, "y"],
|
|
430
|
+
]);
|
|
431
|
+
assertParse("expression", "x / y", [
|
|
432
|
+
ops.division,
|
|
433
|
+
[markers.traverse, [markers.reference, "x"]],
|
|
434
|
+
[markers.traverse, [markers.reference, "y"]],
|
|
435
|
+
]);
|
|
436
|
+
// Parses as a call, not a path
|
|
437
|
+
assertParse("expression", "(x)/y", [
|
|
438
|
+
[markers.traverse, [markers.reference, "x"]],
|
|
439
|
+
[ops.literal, "y"],
|
|
440
|
+
]);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
test("operators with spaces = math", () => {
|
|
444
|
+
assertParse("expression", "a + b", [
|
|
445
|
+
ops.addition,
|
|
446
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
447
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
448
|
+
]);
|
|
449
|
+
assertParse("expression", "a - b", [
|
|
450
|
+
ops.subtraction,
|
|
451
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
452
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
453
|
+
]);
|
|
454
|
+
assertParse("expression", "a & b", [
|
|
455
|
+
ops.bitwiseAnd,
|
|
456
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
457
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
458
|
+
]);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
test("operators without spaces = reference", () => {
|
|
462
|
+
assertParse("expression", "a+b", [
|
|
463
|
+
markers.traverse,
|
|
464
|
+
[markers.reference, "a+b"],
|
|
465
|
+
]);
|
|
466
|
+
assertParse("expression", "a-b", [
|
|
467
|
+
markers.traverse,
|
|
468
|
+
[markers.reference, "a-b"],
|
|
469
|
+
]);
|
|
470
|
+
assertParse("expression", "a&b", [
|
|
471
|
+
markers.traverse,
|
|
472
|
+
[markers.reference, "a&b"],
|
|
473
|
+
]);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("property acccess", () => {
|
|
477
|
+
assertParse("expression", "(foo).bar", [
|
|
478
|
+
[markers.traverse, [markers.reference, "foo"]],
|
|
479
|
+
[ops.literal, "bar"],
|
|
480
|
+
]);
|
|
481
|
+
assertParse("expression", "(foo).bar.baz", [
|
|
482
|
+
[
|
|
483
|
+
[markers.traverse, [markers.reference, "foo"]],
|
|
484
|
+
[ops.literal, "bar"],
|
|
485
|
+
],
|
|
486
|
+
[ops.literal, "baz"],
|
|
487
|
+
]);
|
|
488
|
+
assertParse("expression", "foo[bar]", [
|
|
489
|
+
[markers.traverse, [markers.reference, "foo"]],
|
|
490
|
+
[markers.traverse, [markers.reference, "bar"]],
|
|
491
|
+
]);
|
|
492
|
+
assertParse("expression", "Tree.map", [
|
|
493
|
+
markers.traverse,
|
|
494
|
+
[markers.reference, "Tree.map"],
|
|
495
|
+
]);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
test("consecutive slashes at start of something = comment", () => {
|
|
499
|
+
assertParse(
|
|
500
|
+
"expression",
|
|
501
|
+
"x //comment",
|
|
502
|
+
[markers.traverse, [markers.reference, "x"]],
|
|
503
|
+
"jse",
|
|
504
|
+
false
|
|
505
|
+
);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
test("complex expressions", () => {
|
|
509
|
+
assertParse("expression", "page.ori(mdHtml(about.md))", [
|
|
510
|
+
[markers.traverse, [markers.reference, "page.ori"]],
|
|
511
|
+
[
|
|
512
|
+
[markers.traverse, [markers.reference, "mdHtml"]],
|
|
513
|
+
[markers.traverse, [markers.reference, "about.md"]],
|
|
514
|
+
],
|
|
515
|
+
]);
|
|
516
|
+
|
|
517
|
+
assertParse("expression", "keys(</>)", [
|
|
518
|
+
[markers.traverse, [markers.reference, "keys"]],
|
|
519
|
+
[markers.traverse, [markers.external, "/"]],
|
|
520
|
+
]);
|
|
521
|
+
|
|
522
|
+
assertParse("expression", "'Hello' -> test.ori.html", [
|
|
523
|
+
[markers.traverse, [markers.reference, "test.ori.html"]],
|
|
524
|
+
[ops.literal, "Hello"],
|
|
525
|
+
]);
|
|
526
|
+
assertParse("expression", "obj.json", [
|
|
527
|
+
markers.traverse,
|
|
528
|
+
[markers.reference, "obj.json"],
|
|
529
|
+
]);
|
|
530
|
+
assertParse("expression", "(fn a, b, c)", [
|
|
531
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
532
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
533
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
534
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
535
|
+
]);
|
|
536
|
+
assertParse("expression", "foo.bar('hello', 'world')", [
|
|
537
|
+
[markers.traverse, [markers.reference, "foo.bar"]],
|
|
538
|
+
[ops.literal, "hello"],
|
|
539
|
+
[ops.literal, "world"],
|
|
540
|
+
]);
|
|
541
|
+
assertParse("expression", "(key)('a')", [
|
|
542
|
+
[markers.traverse, [markers.reference, "key"]],
|
|
543
|
+
[ops.literal, "a"],
|
|
544
|
+
]);
|
|
545
|
+
assertParse("expression", "1", [ops.literal, 1]);
|
|
546
|
+
assertParse("expression", "{ a: 1, b: 2 }", [
|
|
547
|
+
ops.object,
|
|
548
|
+
["a", [ops.literal, 1]],
|
|
549
|
+
["b", [ops.literal, 2]],
|
|
550
|
+
]);
|
|
551
|
+
assertParse("expression", "serve { index.html: 'hello' }", [
|
|
552
|
+
[markers.traverse, [markers.reference, "serve"]],
|
|
553
|
+
[ops.object, ["index.html", [ops.literal, "hello"]]],
|
|
554
|
+
]);
|
|
555
|
+
assertParse("expression", "fn =`x`", [
|
|
556
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
557
|
+
[
|
|
558
|
+
ops.lambda,
|
|
559
|
+
[[ops.literal, "_"]],
|
|
560
|
+
[ops.templateTree, [ops.literal, ["x"]]],
|
|
561
|
+
],
|
|
562
|
+
]);
|
|
563
|
+
assertParse("expression", "copy app.js(formulas), files:snapshot", [
|
|
564
|
+
[markers.traverse, [markers.reference, "copy"]],
|
|
565
|
+
[
|
|
566
|
+
[markers.traverse, [markers.reference, "app.js"]],
|
|
567
|
+
[markers.traverse, [markers.reference, "formulas"]],
|
|
568
|
+
],
|
|
569
|
+
[
|
|
570
|
+
[markers.global, "files:"],
|
|
571
|
+
[ops.literal, "snapshot"],
|
|
572
|
+
],
|
|
573
|
+
]);
|
|
574
|
+
assertParse("expression", "map =`<li>${_}</li>`", [
|
|
575
|
+
[markers.traverse, [markers.reference, "map"]],
|
|
576
|
+
[
|
|
577
|
+
ops.lambda,
|
|
578
|
+
[[ops.literal, "_"]],
|
|
579
|
+
[
|
|
580
|
+
ops.templateTree,
|
|
581
|
+
[ops.literal, ["<li>", "</li>"]],
|
|
582
|
+
[markers.traverse, [markers.reference, "_"]],
|
|
583
|
+
],
|
|
584
|
+
],
|
|
585
|
+
]);
|
|
586
|
+
assertParse("expression", `https://example.com/about/`, [
|
|
587
|
+
[markers.global, "https:"],
|
|
588
|
+
[ops.literal, "example.com/"],
|
|
589
|
+
[ops.literal, "about/"],
|
|
590
|
+
]);
|
|
591
|
+
assertParse("expression", "tag`Hello, ${name}!`", [
|
|
592
|
+
[markers.traverse, [markers.reference, "tag"]],
|
|
593
|
+
[ops.literal, ["Hello, ", "!"]],
|
|
594
|
+
[ops.concat, [markers.traverse, [markers.reference, "name"]]],
|
|
595
|
+
]);
|
|
596
|
+
assertParse("expression", "=tag`Hello, ${_}!`", [
|
|
597
|
+
ops.lambda,
|
|
598
|
+
[[ops.literal, "_"]],
|
|
599
|
+
[
|
|
600
|
+
[markers.traverse, [markers.reference, "tag"]],
|
|
601
|
+
[ops.literal, ["Hello, ", "!"]],
|
|
602
|
+
[ops.concat, [markers.traverse, [markers.reference, "_"]]],
|
|
603
|
+
],
|
|
604
|
+
]);
|
|
605
|
+
assertParse("expression", "(post, slug) => fn.js(post, slug)", [
|
|
606
|
+
ops.lambda,
|
|
607
|
+
[
|
|
608
|
+
[ops.literal, "post"],
|
|
609
|
+
[ops.literal, "slug"],
|
|
610
|
+
],
|
|
611
|
+
[
|
|
612
|
+
[markers.traverse, [markers.reference, "fn.js"]],
|
|
613
|
+
[markers.traverse, [markers.reference, "post"]],
|
|
614
|
+
[markers.traverse, [markers.reference, "slug"]],
|
|
615
|
+
],
|
|
616
|
+
]);
|
|
617
|
+
assertParse("expression", "keys(<~>)", [
|
|
618
|
+
[markers.traverse, [markers.reference, "keys"]],
|
|
619
|
+
[markers.traverse, [markers.external, "~"]],
|
|
620
|
+
]);
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
test("complex object", () => {
|
|
624
|
+
assertParse(
|
|
625
|
+
"expression",
|
|
626
|
+
`{
|
|
447
627
|
index.html = index.ori(teamData.yaml)
|
|
448
628
|
thumbnails = map(images, { value: thumbnail.js })
|
|
449
629
|
}`,
|
|
450
|
-
[
|
|
451
|
-
ops.object,
|
|
452
630
|
[
|
|
453
|
-
|
|
631
|
+
ops.object,
|
|
454
632
|
[
|
|
455
|
-
|
|
633
|
+
"index.html",
|
|
456
634
|
[
|
|
457
|
-
|
|
458
|
-
[
|
|
635
|
+
ops.getter,
|
|
636
|
+
[
|
|
637
|
+
[markers.traverse, [markers.reference, "index.ori"]],
|
|
638
|
+
[markers.traverse, [markers.reference, "teamData.yaml"]],
|
|
639
|
+
],
|
|
459
640
|
],
|
|
460
641
|
],
|
|
461
|
-
],
|
|
462
|
-
[
|
|
463
|
-
"thumbnails",
|
|
464
642
|
[
|
|
465
|
-
|
|
643
|
+
"thumbnails",
|
|
466
644
|
[
|
|
467
|
-
|
|
468
|
-
[markers.reference, [ops.literal, "images"]],
|
|
645
|
+
ops.getter,
|
|
469
646
|
[
|
|
470
|
-
|
|
471
|
-
[
|
|
647
|
+
[markers.traverse, [markers.reference, "map"]],
|
|
648
|
+
[markers.traverse, [markers.reference, "images"]],
|
|
649
|
+
[
|
|
650
|
+
ops.object,
|
|
651
|
+
[
|
|
652
|
+
"value",
|
|
653
|
+
[markers.traverse, [markers.reference, "thumbnail.js"]],
|
|
654
|
+
],
|
|
655
|
+
],
|
|
472
656
|
],
|
|
473
657
|
],
|
|
474
658
|
],
|
|
475
|
-
]
|
|
476
|
-
|
|
477
|
-
);
|
|
478
|
-
|
|
479
|
-
// Builtin on its own is the function itself, not a function call
|
|
480
|
-
assertParse("expression", "mdHtml:", [markers.global, "mdHtml:"]);
|
|
481
|
-
|
|
482
|
-
// Consecutive slashes at start of something = comment
|
|
483
|
-
assertParse(
|
|
484
|
-
"expression",
|
|
485
|
-
"x //comment",
|
|
486
|
-
[markers.reference, [ops.literal, "x"]],
|
|
487
|
-
"jse",
|
|
488
|
-
false
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
assertParse("expression", "page.ori(mdHtml:(about.md))", [
|
|
492
|
-
[markers.reference, [ops.literal, "page.ori"]],
|
|
493
|
-
[
|
|
494
|
-
[markers.global, "mdHtml:"],
|
|
495
|
-
[markers.reference, [ops.literal, "about.md"]],
|
|
496
|
-
],
|
|
497
|
-
]);
|
|
498
|
-
|
|
499
|
-
// Slash on its own is the root folder
|
|
500
|
-
assertParse("expression", "keys /", [
|
|
501
|
-
[markers.global, "keys"],
|
|
502
|
-
[ops.rootDirectory],
|
|
503
|
-
]);
|
|
504
|
-
|
|
505
|
-
assertParse("expression", "'Hello' -> test.orit", [
|
|
506
|
-
[markers.reference, [ops.literal, "test.orit"]],
|
|
507
|
-
[ops.literal, "Hello"],
|
|
508
|
-
]);
|
|
509
|
-
assertParse("expression", "obj.json", [
|
|
510
|
-
markers.reference,
|
|
511
|
-
[ops.literal, "obj.json"],
|
|
512
|
-
]);
|
|
513
|
-
assertParse("expression", "(fn a, b, c)", [
|
|
514
|
-
[markers.global, "fn"],
|
|
515
|
-
[markers.reference, [ops.literal, "a"]],
|
|
516
|
-
[markers.reference, [ops.literal, "b"]],
|
|
517
|
-
[markers.reference, [ops.literal, "c"]],
|
|
518
|
-
]);
|
|
519
|
-
assertParse("expression", "foo.bar('hello', 'world')", [
|
|
520
|
-
[markers.reference, [ops.literal, "foo.bar"]],
|
|
521
|
-
[ops.literal, "hello"],
|
|
522
|
-
[ops.literal, "world"],
|
|
523
|
-
]);
|
|
524
|
-
// assertParse("expression", "(key)('a')", [
|
|
525
|
-
// [markers.reference, [ops.literal, "key"]],
|
|
526
|
-
// [ops.literal, "a"],
|
|
527
|
-
// ]);
|
|
528
|
-
assertParse("expression", "1", [ops.literal, 1]);
|
|
529
|
-
assertParse("expression", "{ a: 1, b: 2 }", [
|
|
530
|
-
ops.object,
|
|
531
|
-
["a", [ops.literal, 1]],
|
|
532
|
-
["b", [ops.literal, 2]],
|
|
533
|
-
]);
|
|
534
|
-
assertParse("expression", "serve { index.html: 'hello' }", [
|
|
535
|
-
[markers.global, "serve"],
|
|
536
|
-
[ops.object, ["index.html", [ops.literal, "hello"]]],
|
|
537
|
-
]);
|
|
538
|
-
assertParse("expression", "fn =`x`", [
|
|
539
|
-
[markers.global, "fn"],
|
|
540
|
-
[
|
|
541
|
-
ops.lambda,
|
|
542
|
-
[[ops.literal, "_"]],
|
|
543
|
-
[ops.templateTree, [ops.literal, ["x"]]],
|
|
544
|
-
],
|
|
545
|
-
]);
|
|
546
|
-
assertParse("expression", "copy app.js(formulas), files:snapshot", [
|
|
547
|
-
[markers.global, "copy"],
|
|
548
|
-
[
|
|
549
|
-
[markers.reference, [ops.literal, "app.js"]],
|
|
550
|
-
[markers.reference, [ops.literal, "formulas"]],
|
|
551
|
-
],
|
|
552
|
-
[
|
|
553
|
-
[markers.global, "files:"],
|
|
554
|
-
[ops.literal, "snapshot"],
|
|
555
|
-
],
|
|
556
|
-
]);
|
|
557
|
-
assertParse("expression", "map =`<li>${_}</li>`", [
|
|
558
|
-
[markers.global, "map"],
|
|
559
|
-
[
|
|
560
|
-
ops.lambda,
|
|
561
|
-
[[ops.literal, "_"]],
|
|
562
|
-
[
|
|
563
|
-
ops.templateTree,
|
|
564
|
-
[ops.literal, ["<li>", "</li>"]],
|
|
565
|
-
[markers.reference, [ops.literal, "_"]],
|
|
566
|
-
],
|
|
567
|
-
],
|
|
568
|
-
]);
|
|
569
|
-
assertParse("expression", `https://example.com/about/`, [
|
|
570
|
-
[markers.global, "https:"],
|
|
571
|
-
[ops.literal, "example.com/"],
|
|
572
|
-
[ops.literal, "about/"],
|
|
573
|
-
]);
|
|
574
|
-
assertParse("expression", "tag`Hello, ${name}!`", [
|
|
575
|
-
[markers.global, "tag"],
|
|
576
|
-
[ops.literal, ["Hello, ", "!"]],
|
|
577
|
-
[ops.concat, [markers.reference, [ops.literal, "name"]]],
|
|
578
|
-
]);
|
|
579
|
-
assertParse("expression", "(post, slug) => fn.js(post, slug)", [
|
|
580
|
-
ops.lambda,
|
|
581
|
-
[
|
|
582
|
-
[ops.literal, "post"],
|
|
583
|
-
[ops.literal, "slug"],
|
|
584
|
-
],
|
|
585
|
-
[
|
|
586
|
-
[markers.reference, [ops.literal, "fn.js"]],
|
|
587
|
-
[markers.reference, [ops.literal, "post"]],
|
|
588
|
-
[markers.reference, [ops.literal, "slug"]],
|
|
589
|
-
],
|
|
590
|
-
]);
|
|
591
|
-
assertParse("expression", "keys ~", [
|
|
592
|
-
[markers.global, "keys"],
|
|
593
|
-
[ops.homeDirectory],
|
|
594
|
-
]);
|
|
595
|
-
assertParse("expression", "keys /Users/alice", [
|
|
596
|
-
[markers.global, "keys"],
|
|
597
|
-
[[ops.rootDirectory], [ops.literal, "Users/"], [ops.literal, "alice"]],
|
|
598
|
-
]);
|
|
599
|
-
|
|
600
|
-
// Verify parser treatment of identifiers containing operators
|
|
601
|
-
assertParse("expression", "a + b", [
|
|
602
|
-
ops.addition,
|
|
603
|
-
[markers.reference, [ops.literal, "a"]],
|
|
604
|
-
[markers.reference, [ops.literal, "b"]],
|
|
605
|
-
]);
|
|
606
|
-
assertParse("expression", "a+b", [markers.reference, [ops.literal, "a+b"]]);
|
|
607
|
-
assertParse("expression", "a - b", [
|
|
608
|
-
ops.subtraction,
|
|
609
|
-
[markers.reference, [ops.literal, "a"]],
|
|
610
|
-
[markers.reference, [ops.literal, "b"]],
|
|
611
|
-
]);
|
|
612
|
-
assertParse("expression", "a-b", [markers.reference, [ops.literal, "a-b"]]);
|
|
613
|
-
assertParse("expression", "a&b", [markers.reference, [ops.literal, "a&b"]]);
|
|
614
|
-
assertParse("expression", "a & b", [
|
|
615
|
-
ops.bitwiseAnd,
|
|
616
|
-
[markers.reference, [ops.literal, "a"]],
|
|
617
|
-
[markers.reference, [ops.literal, "b"]],
|
|
618
|
-
]);
|
|
659
|
+
]
|
|
660
|
+
);
|
|
661
|
+
});
|
|
619
662
|
});
|
|
620
663
|
|
|
621
664
|
test("frontMatterExpression", () => {
|
|
@@ -628,7 +671,7 @@ Body`,
|
|
|
628
671
|
[
|
|
629
672
|
ops.lambda,
|
|
630
673
|
[[ops.literal, "name"]],
|
|
631
|
-
[[markers.
|
|
674
|
+
[[markers.traverse, [markers.reference, "_template"]], undefined],
|
|
632
675
|
],
|
|
633
676
|
"jse",
|
|
634
677
|
false
|
|
@@ -637,90 +680,98 @@ Body`,
|
|
|
637
680
|
|
|
638
681
|
test("group", () => {
|
|
639
682
|
assertParse("group", "(hello)", [
|
|
640
|
-
markers.
|
|
641
|
-
[
|
|
683
|
+
markers.traverse,
|
|
684
|
+
[markers.reference, "hello"],
|
|
642
685
|
]);
|
|
643
686
|
assertParse("group", "(((nested)))", [
|
|
644
|
-
markers.
|
|
645
|
-
[
|
|
687
|
+
markers.traverse,
|
|
688
|
+
[markers.reference, "nested"],
|
|
689
|
+
]);
|
|
690
|
+
assertParse("group", "(fn())", [
|
|
691
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
692
|
+
undefined,
|
|
646
693
|
]);
|
|
647
|
-
assertParse("group", "(fn())", [[markers.global, "fn"], undefined]);
|
|
648
694
|
assertParse("group", "(a -> b)", [
|
|
649
|
-
[markers.
|
|
650
|
-
[markers.
|
|
695
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
696
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
651
697
|
]);
|
|
652
698
|
});
|
|
653
699
|
|
|
654
|
-
test("homeDirectory", () => {
|
|
655
|
-
assertParse("homeDirectory", "~", [ops.homeDirectory]);
|
|
656
|
-
});
|
|
657
|
-
|
|
658
700
|
test("host", () => {
|
|
659
701
|
assertParse("host", "abc", [ops.literal, "abc"]);
|
|
660
702
|
assertParse("host", "abc:123", [ops.literal, "abc:123"]);
|
|
661
|
-
assertParse("host", "foo\\ bar", [ops.literal, "foo bar"]);
|
|
662
703
|
});
|
|
663
704
|
|
|
664
705
|
test("identifier", () => {
|
|
665
|
-
assertParse("identifier", "
|
|
666
|
-
assertParse("identifier", "
|
|
667
|
-
|
|
668
|
-
|
|
706
|
+
assertParse("identifier", "foo", "foo", "jse", false);
|
|
707
|
+
assertParse("identifier", "$Δelta", "$Δelta", "jse", false);
|
|
708
|
+
assertThrows(
|
|
709
|
+
"identifier",
|
|
710
|
+
"1stCharacterIsNumber",
|
|
711
|
+
"Expected JavaScript identifier start"
|
|
712
|
+
);
|
|
713
|
+
assertThrows(
|
|
714
|
+
"identifier",
|
|
715
|
+
"has space",
|
|
716
|
+
"Expected JavaScript identifier continuation"
|
|
717
|
+
);
|
|
718
|
+
assertThrows(
|
|
719
|
+
"identifier",
|
|
720
|
+
"foo.bar",
|
|
721
|
+
"Expected JavaScript identifier continuation"
|
|
722
|
+
);
|
|
669
723
|
});
|
|
670
724
|
|
|
671
725
|
test("implicitParenthesesCallExpression", () => {
|
|
672
726
|
assertParse("implicitParenthesesCallExpression", "fn arg", [
|
|
673
|
-
[markers.
|
|
674
|
-
[markers.
|
|
727
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
728
|
+
[markers.traverse, [markers.reference, "arg"]],
|
|
675
729
|
]);
|
|
676
730
|
assertParse("implicitParenthesesCallExpression", "page.ori 'a', 'b'", [
|
|
677
|
-
[markers.
|
|
731
|
+
[markers.traverse, [markers.reference, "page.ori"]],
|
|
678
732
|
[ops.literal, "a"],
|
|
679
733
|
[ops.literal, "b"],
|
|
680
734
|
]);
|
|
681
735
|
assertParse("implicitParenthesesCallExpression", "fn a(b), c", [
|
|
682
|
-
[markers.
|
|
736
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
683
737
|
[
|
|
684
|
-
[markers.
|
|
685
|
-
[markers.
|
|
738
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
739
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
686
740
|
],
|
|
687
|
-
[markers.
|
|
741
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
688
742
|
]);
|
|
689
743
|
assertParse("implicitParenthesesCallExpression", "(fn()) 'arg'", [
|
|
690
|
-
[[markers.
|
|
744
|
+
[[markers.traverse, [markers.reference, "fn"]], undefined],
|
|
691
745
|
[ops.literal, "arg"],
|
|
692
746
|
]);
|
|
693
|
-
assertParse(
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
747
|
+
assertParse(
|
|
748
|
+
"implicitParenthesesCallExpression",
|
|
749
|
+
"tree/key arg",
|
|
750
|
+
[
|
|
751
|
+
[markers.traverse, [markers.reference, "tree/"], [ops.literal, "key"]],
|
|
752
|
+
[markers.traverse, [markers.reference, "arg"]],
|
|
753
|
+
],
|
|
754
|
+
"shell"
|
|
755
|
+
);
|
|
697
756
|
assertParse("implicitParenthesesCallExpression", "foo.js bar.ori 'arg'", [
|
|
698
|
-
[markers.
|
|
757
|
+
[markers.traverse, [markers.reference, "foo.js"]],
|
|
699
758
|
[
|
|
700
|
-
[markers.
|
|
759
|
+
[markers.traverse, [markers.reference, "bar.ori"]],
|
|
701
760
|
[ops.literal, "arg"],
|
|
702
761
|
],
|
|
703
762
|
]);
|
|
704
763
|
});
|
|
705
764
|
|
|
706
|
-
test("
|
|
707
|
-
assertParse("
|
|
708
|
-
assertParse("
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
);
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
"has space",
|
|
717
|
-
"Expected JavaScript identifier continuation"
|
|
718
|
-
);
|
|
719
|
-
assertThrows(
|
|
720
|
-
"jsIdentifier",
|
|
721
|
-
"foo.bar",
|
|
722
|
-
"Expected JavaScript identifier continuation"
|
|
723
|
-
);
|
|
765
|
+
test("key", () => {
|
|
766
|
+
assertParse("key", "a", "a");
|
|
767
|
+
assertParse("key", "_b", "_b");
|
|
768
|
+
assertParse("key", ".ssh", ".ssh");
|
|
769
|
+
assertParse("key", "index.html", "index.html");
|
|
770
|
+
assertParse("key", "404.html", "404.html");
|
|
771
|
+
assertParse("key", "1a2b3c", "1a2b3c");
|
|
772
|
+
assertParse("key", "a~b", "a~b");
|
|
773
|
+
assertParse("key", "foo-bar", "foo-bar");
|
|
774
|
+
assertParse("key", "package-lock.json", "package-lock.json");
|
|
724
775
|
});
|
|
725
776
|
|
|
726
777
|
test("list", () => {
|
|
@@ -755,8 +806,8 @@ Body`,
|
|
|
755
806
|
test("logicalAndExpression", () => {
|
|
756
807
|
assertParse("logicalAndExpression", "true && false", [
|
|
757
808
|
ops.logicalAnd,
|
|
758
|
-
[markers.
|
|
759
|
-
[ops.lambda, [], [markers.
|
|
809
|
+
[markers.traverse, [markers.reference, "true"]],
|
|
810
|
+
[ops.lambda, [], [markers.traverse, [markers.reference, "false"]]],
|
|
760
811
|
]);
|
|
761
812
|
});
|
|
762
813
|
|
|
@@ -768,9 +819,9 @@ Body`,
|
|
|
768
819
|
]);
|
|
769
820
|
assertParse("logicalOrExpression", "false || false || true", [
|
|
770
821
|
ops.logicalOr,
|
|
771
|
-
[markers.
|
|
772
|
-
[ops.lambda, [], [markers.
|
|
773
|
-
[ops.lambda, [], [markers.
|
|
822
|
+
[markers.traverse, [markers.reference, "false"]],
|
|
823
|
+
[ops.lambda, [], [markers.traverse, [markers.reference, "false"]]],
|
|
824
|
+
[ops.lambda, [], [markers.traverse, [markers.reference, "true"]]],
|
|
774
825
|
]);
|
|
775
826
|
assertParse("logicalOrExpression", "1 || 2 && 0", [
|
|
776
827
|
ops.logicalOr,
|
|
@@ -807,32 +858,28 @@ Body`,
|
|
|
807
858
|
]);
|
|
808
859
|
});
|
|
809
860
|
|
|
810
|
-
test("namespace", () => {
|
|
811
|
-
assertParse("namespace", "js:", [markers.global, "js:"]);
|
|
812
|
-
});
|
|
813
|
-
|
|
814
861
|
test("newExpression", () => {
|
|
815
862
|
assertParse("newExpression", "new Foo()", [
|
|
816
863
|
ops.construct,
|
|
817
|
-
[markers.
|
|
864
|
+
[markers.traverse, [markers.reference, "Foo"]],
|
|
818
865
|
]);
|
|
819
866
|
assertParse("newExpression", "new:Foo()", [
|
|
820
867
|
ops.construct,
|
|
821
|
-
[markers.
|
|
868
|
+
[markers.traverse, [markers.reference, "Foo"]],
|
|
822
869
|
]);
|
|
823
870
|
});
|
|
824
871
|
|
|
825
872
|
test("nullishCoalescingExpression", () => {
|
|
826
873
|
assertParse("nullishCoalescingExpression", "a ?? b", [
|
|
827
874
|
ops.nullishCoalescing,
|
|
828
|
-
[markers.
|
|
829
|
-
[ops.lambda, [], [markers.
|
|
875
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
876
|
+
[ops.lambda, [], [markers.traverse, [markers.reference, "b"]]],
|
|
830
877
|
]);
|
|
831
878
|
assertParse("nullishCoalescingExpression", "a ?? b ?? c", [
|
|
832
879
|
ops.nullishCoalescing,
|
|
833
|
-
[markers.
|
|
834
|
-
[ops.lambda, [], [markers.
|
|
835
|
-
[ops.lambda, [], [markers.
|
|
880
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
881
|
+
[ops.lambda, [], [markers.traverse, [markers.reference, "b"]]],
|
|
882
|
+
[ops.lambda, [], [markers.traverse, [markers.reference, "c"]]],
|
|
836
883
|
]);
|
|
837
884
|
});
|
|
838
885
|
|
|
@@ -847,7 +894,7 @@ Body`,
|
|
|
847
894
|
assertParse("objectLiteral", "{ a: 1, b }", [
|
|
848
895
|
ops.object,
|
|
849
896
|
["a", [ops.literal, 1]],
|
|
850
|
-
["b", [markers.reference, "b"]],
|
|
897
|
+
["b", [markers.traverse, [markers.reference, "b"]]],
|
|
851
898
|
]);
|
|
852
899
|
assertParse("objectLiteral", "{ sub: { a: 1 } }", [
|
|
853
900
|
ops.object,
|
|
@@ -864,7 +911,7 @@ Body`,
|
|
|
864
911
|
]);
|
|
865
912
|
assertParse("objectLiteral", "{ a = b, b = 2 }", [
|
|
866
913
|
ops.object,
|
|
867
|
-
["a", [ops.getter, [markers.
|
|
914
|
+
["a", [ops.getter, [markers.traverse, [markers.reference, "b"]]]],
|
|
868
915
|
["b", [ops.literal, 2]],
|
|
869
916
|
]);
|
|
870
917
|
assertParse(
|
|
@@ -875,7 +922,7 @@ Body`,
|
|
|
875
922
|
}`,
|
|
876
923
|
[
|
|
877
924
|
ops.object,
|
|
878
|
-
["a", [ops.getter, [markers.
|
|
925
|
+
["a", [ops.getter, [markers.traverse, [markers.reference, "b"]]]],
|
|
879
926
|
["b", [ops.literal, 2]],
|
|
880
927
|
]
|
|
881
928
|
);
|
|
@@ -891,7 +938,16 @@ Body`,
|
|
|
891
938
|
ops.object,
|
|
892
939
|
[
|
|
893
940
|
"a",
|
|
894
|
-
[
|
|
941
|
+
[
|
|
942
|
+
ops.object,
|
|
943
|
+
[
|
|
944
|
+
"b",
|
|
945
|
+
[
|
|
946
|
+
ops.getter,
|
|
947
|
+
[[markers.traverse, [markers.reference, "fn"]], undefined],
|
|
948
|
+
],
|
|
949
|
+
],
|
|
950
|
+
],
|
|
895
951
|
],
|
|
896
952
|
]);
|
|
897
953
|
assertParse("objectLiteral", "{ x = fn.js('a') }", [
|
|
@@ -901,7 +957,7 @@ Body`,
|
|
|
901
957
|
[
|
|
902
958
|
ops.getter,
|
|
903
959
|
[
|
|
904
|
-
[markers.
|
|
960
|
+
[markers.traverse, [markers.reference, "fn.js"]],
|
|
905
961
|
[ops.literal, "a"],
|
|
906
962
|
],
|
|
907
963
|
],
|
|
@@ -911,13 +967,13 @@ Body`,
|
|
|
911
967
|
[
|
|
912
968
|
ops.object,
|
|
913
969
|
["a", [ops.literal, 1]],
|
|
914
|
-
["c", [markers.
|
|
970
|
+
["c", [markers.traverse, [markers.reference, "a"]]],
|
|
915
971
|
[
|
|
916
972
|
"_result",
|
|
917
973
|
[
|
|
918
974
|
ops.merge,
|
|
919
975
|
[ops.object, ["a", [ops.getter, [[ops.context, 1], "a"]]]],
|
|
920
|
-
[markers.
|
|
976
|
+
[markers.traverse, [markers.reference, "more"]],
|
|
921
977
|
[ops.object, ["c", [ops.getter, [[ops.context, 1], "c"]]]],
|
|
922
978
|
],
|
|
923
979
|
],
|
|
@@ -941,8 +997,8 @@ Body`,
|
|
|
941
997
|
[
|
|
942
998
|
"file.txt",
|
|
943
999
|
[
|
|
944
|
-
|
|
945
|
-
[
|
|
1000
|
+
markers.traverse,
|
|
1001
|
+
[markers.external, "path/"],
|
|
946
1002
|
[ops.literal, "to/"],
|
|
947
1003
|
[ops.literal, "file.txt"],
|
|
948
1004
|
],
|
|
@@ -953,14 +1009,17 @@ Body`,
|
|
|
953
1009
|
});
|
|
954
1010
|
|
|
955
1011
|
test("objectEntry", () => {
|
|
956
|
-
assertParse("objectEntry", "foo", [
|
|
957
|
-
|
|
958
|
-
"
|
|
959
|
-
|
|
1012
|
+
assertParse("objectEntry", "foo", [
|
|
1013
|
+
"foo",
|
|
1014
|
+
[markers.traverse, [markers.reference, "foo"]],
|
|
1015
|
+
]);
|
|
1016
|
+
assertParse("objectEntry", "index.html: x", [
|
|
1017
|
+
"index.html",
|
|
1018
|
+
[markers.traverse, [markers.reference, "x"]],
|
|
960
1019
|
]);
|
|
961
1020
|
assertParse("objectEntry", "a: a", [
|
|
962
1021
|
"a",
|
|
963
|
-
[markers.
|
|
1022
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
964
1023
|
]);
|
|
965
1024
|
assertParse(
|
|
966
1025
|
"objectEntry",
|
|
@@ -968,8 +1027,8 @@ Body`,
|
|
|
968
1027
|
[
|
|
969
1028
|
"file.txt",
|
|
970
1029
|
[
|
|
971
|
-
|
|
972
|
-
[
|
|
1030
|
+
markers.traverse,
|
|
1031
|
+
[markers.external, "path/"],
|
|
973
1032
|
[ops.literal, "to/"],
|
|
974
1033
|
[ops.literal, "file.txt"],
|
|
975
1034
|
],
|
|
@@ -981,15 +1040,15 @@ Body`,
|
|
|
981
1040
|
[
|
|
982
1041
|
ops.lambda,
|
|
983
1042
|
[[ops.literal, "a"]],
|
|
984
|
-
[markers.
|
|
1043
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
985
1044
|
],
|
|
986
1045
|
]);
|
|
987
1046
|
assertParse("objectEntry", "posts/: map(posts, post.ori)", [
|
|
988
1047
|
"posts/",
|
|
989
1048
|
[
|
|
990
|
-
[markers.
|
|
991
|
-
[markers.
|
|
992
|
-
[markers.
|
|
1049
|
+
[markers.traverse, [markers.reference, "map"]],
|
|
1050
|
+
[markers.traverse, [markers.reference, "posts"]],
|
|
1051
|
+
[markers.traverse, [markers.reference, "post.ori"]],
|
|
993
1052
|
],
|
|
994
1053
|
]);
|
|
995
1054
|
});
|
|
@@ -997,15 +1056,15 @@ Body`,
|
|
|
997
1056
|
test("objectGetter", () => {
|
|
998
1057
|
assertParse("objectGetter", "data = obj.json", [
|
|
999
1058
|
"data",
|
|
1000
|
-
[ops.getter, [markers.
|
|
1059
|
+
[ops.getter, [markers.traverse, [markers.reference, "obj.json"]]],
|
|
1001
1060
|
]);
|
|
1002
|
-
assertParse("objectGetter", "
|
|
1003
|
-
"
|
|
1061
|
+
assertParse("objectGetter", "index.html = index.ori(teamData.yaml)", [
|
|
1062
|
+
"index.html",
|
|
1004
1063
|
[
|
|
1005
1064
|
ops.getter,
|
|
1006
1065
|
[
|
|
1007
|
-
[markers.
|
|
1008
|
-
[
|
|
1066
|
+
[markers.traverse, [markers.reference, "index.ori"]],
|
|
1067
|
+
[markers.traverse, [markers.reference, "teamData.yaml"]],
|
|
1009
1068
|
],
|
|
1010
1069
|
],
|
|
1011
1070
|
]);
|
|
@@ -1013,26 +1072,27 @@ Body`,
|
|
|
1013
1072
|
|
|
1014
1073
|
test("objectProperty", () => {
|
|
1015
1074
|
assertParse("objectProperty", "a: 1", ["a", [ops.literal, 1]]);
|
|
1016
|
-
assertParse("objectProperty", "
|
|
1017
|
-
"
|
|
1075
|
+
assertParse("objectProperty", "data.json: 'Alice'", [
|
|
1076
|
+
"data.json",
|
|
1018
1077
|
[ops.literal, "Alice"],
|
|
1019
1078
|
]);
|
|
1020
1079
|
assertParse("objectProperty", "x: fn('a')", [
|
|
1021
1080
|
"x",
|
|
1022
1081
|
[
|
|
1023
|
-
[markers.
|
|
1082
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
1024
1083
|
[ops.literal, "a"],
|
|
1025
1084
|
],
|
|
1026
1085
|
]);
|
|
1027
1086
|
});
|
|
1028
1087
|
|
|
1029
1088
|
test("objectPublicKey", () => {
|
|
1030
|
-
assertParse("objectPublicKey", "a", "a", "
|
|
1031
|
-
assertParse("objectPublicKey", "
|
|
1032
|
-
assertParse("objectPublicKey", "
|
|
1089
|
+
assertParse("objectPublicKey", "a", "a", "shell", false);
|
|
1090
|
+
assertParse("objectPublicKey", "index.html", "index.html", "shell", false);
|
|
1091
|
+
assertParse("objectPublicKey", "markdown/", "markdown/", "shell", false);
|
|
1092
|
+
assertParse("objectPublicKey", `"foo bar"`, "foo bar", "shell", false);
|
|
1033
1093
|
});
|
|
1034
1094
|
|
|
1035
|
-
test("optionalChaining", () => {
|
|
1095
|
+
test.skip("optionalChaining", () => {
|
|
1036
1096
|
assertParse("optionalChaining", "?.key", [
|
|
1037
1097
|
ops.optionalTraverse,
|
|
1038
1098
|
[ops.literal, "key"],
|
|
@@ -1042,27 +1102,53 @@ Body`,
|
|
|
1042
1102
|
test("parenthesesArguments", () => {
|
|
1043
1103
|
assertParse("parenthesesArguments", "()", [undefined]);
|
|
1044
1104
|
assertParse("parenthesesArguments", "(a, b, c)", [
|
|
1045
|
-
[markers.
|
|
1046
|
-
[markers.
|
|
1047
|
-
[markers.
|
|
1105
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
1106
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
1107
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
1048
1108
|
]);
|
|
1049
1109
|
});
|
|
1050
1110
|
|
|
1051
|
-
test("
|
|
1052
|
-
assertParse(
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
[ops.literal, "
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1111
|
+
test("pathKeys", () => {
|
|
1112
|
+
assertParse(
|
|
1113
|
+
"pathKeys",
|
|
1114
|
+
"tree/",
|
|
1115
|
+
[[ops.literal, "tree/"]],
|
|
1116
|
+
undefined,
|
|
1117
|
+
false
|
|
1118
|
+
);
|
|
1119
|
+
assertParse(
|
|
1120
|
+
"pathKeys",
|
|
1121
|
+
"month/12",
|
|
1122
|
+
[
|
|
1123
|
+
[ops.literal, "month/"],
|
|
1124
|
+
[ops.literal, "12"],
|
|
1125
|
+
],
|
|
1126
|
+
undefined,
|
|
1127
|
+
false
|
|
1128
|
+
);
|
|
1129
|
+
assertParse(
|
|
1130
|
+
"pathKeys",
|
|
1131
|
+
"tree/foo/bar",
|
|
1132
|
+
[
|
|
1133
|
+
[ops.literal, "tree/"],
|
|
1134
|
+
[ops.literal, "foo/"],
|
|
1135
|
+
[ops.literal, "bar"],
|
|
1136
|
+
],
|
|
1137
|
+
undefined,
|
|
1138
|
+
false
|
|
1139
|
+
);
|
|
1140
|
+
assertParse(
|
|
1141
|
+
"pathKeys",
|
|
1142
|
+
"a///b",
|
|
1143
|
+
[
|
|
1144
|
+
[ops.literal, "a/"],
|
|
1145
|
+
[ops.literal, "/"],
|
|
1146
|
+
[ops.literal, "/"],
|
|
1147
|
+
[ops.literal, "b"],
|
|
1148
|
+
],
|
|
1149
|
+
undefined,
|
|
1150
|
+
false
|
|
1151
|
+
);
|
|
1066
1152
|
});
|
|
1067
1153
|
|
|
1068
1154
|
test("pathArguments", () => {
|
|
@@ -1077,50 +1163,80 @@ Body`,
|
|
|
1077
1163
|
]);
|
|
1078
1164
|
});
|
|
1079
1165
|
|
|
1166
|
+
test("pathLiteral", () => {
|
|
1167
|
+
assertParse("pathLiteral", "tree", [
|
|
1168
|
+
markers.traverse,
|
|
1169
|
+
[markers.reference, "tree"],
|
|
1170
|
+
]);
|
|
1171
|
+
assertParse("pathLiteral", "tree/", [
|
|
1172
|
+
ops.unpack,
|
|
1173
|
+
[markers.traverse, [markers.reference, "tree/"]],
|
|
1174
|
+
]);
|
|
1175
|
+
assertParse("pathLiteral", "month/12", [
|
|
1176
|
+
markers.traverse,
|
|
1177
|
+
[markers.reference, "month/"],
|
|
1178
|
+
[ops.literal, "12"],
|
|
1179
|
+
]);
|
|
1180
|
+
assertParse("pathLiteral", "a/b/c/", [
|
|
1181
|
+
ops.unpack,
|
|
1182
|
+
[
|
|
1183
|
+
markers.traverse,
|
|
1184
|
+
[markers.reference, "a/"],
|
|
1185
|
+
[ops.literal, "b/"],
|
|
1186
|
+
[ops.literal, "c/"],
|
|
1187
|
+
],
|
|
1188
|
+
]);
|
|
1189
|
+
assertParse("pathLiteral", "~/.cshrc", [
|
|
1190
|
+
markers.traverse,
|
|
1191
|
+
[markers.reference, "~/"],
|
|
1192
|
+
[ops.literal, ".cshrc"],
|
|
1193
|
+
]);
|
|
1194
|
+
});
|
|
1195
|
+
|
|
1080
1196
|
test("pipelineExpression", () => {
|
|
1081
1197
|
assertParse("pipelineExpression", "foo", [
|
|
1082
|
-
markers.
|
|
1083
|
-
[
|
|
1198
|
+
markers.traverse,
|
|
1199
|
+
[markers.reference, "foo"],
|
|
1084
1200
|
]);
|
|
1085
1201
|
assertParse("pipelineExpression", "a -> b", [
|
|
1086
|
-
[markers.
|
|
1087
|
-
[markers.
|
|
1202
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
1203
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
1088
1204
|
]);
|
|
1089
1205
|
assertParse("pipelineExpression", "input → one.js → two.js", [
|
|
1090
|
-
[markers.
|
|
1206
|
+
[markers.traverse, [markers.reference, "two.js"]],
|
|
1091
1207
|
[
|
|
1092
|
-
[markers.
|
|
1093
|
-
[markers.
|
|
1208
|
+
[markers.traverse, [markers.reference, "one.js"]],
|
|
1209
|
+
[markers.traverse, [markers.reference, "input"]],
|
|
1094
1210
|
],
|
|
1095
1211
|
]);
|
|
1096
1212
|
assertParse("pipelineExpression", "fn a -> b", [
|
|
1097
|
-
[markers.
|
|
1213
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
1098
1214
|
[
|
|
1099
|
-
[markers.
|
|
1100
|
-
[markers.
|
|
1215
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
1216
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
1101
1217
|
],
|
|
1102
1218
|
]);
|
|
1103
1219
|
});
|
|
1104
1220
|
|
|
1105
1221
|
test("primary", () => {
|
|
1222
|
+
assertParse("primary", "123", [ops.literal, 123]);
|
|
1223
|
+
assertParse("primary", "123.html", [
|
|
1224
|
+
markers.traverse,
|
|
1225
|
+
[markers.reference, "123.html"],
|
|
1226
|
+
]);
|
|
1106
1227
|
assertParse("primary", "foo.js", [
|
|
1107
|
-
markers.
|
|
1108
|
-
[
|
|
1228
|
+
markers.traverse,
|
|
1229
|
+
[markers.reference, "foo.js"],
|
|
1109
1230
|
]);
|
|
1110
1231
|
assertParse("primary", "[1, 2]", [
|
|
1111
1232
|
ops.array,
|
|
1112
1233
|
[ops.literal, 1],
|
|
1113
1234
|
[ops.literal, 2],
|
|
1114
1235
|
]);
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
"
|
|
1118
|
-
|
|
1119
|
-
[[ops.scope], [ops.literal, "index.html"]],
|
|
1120
|
-
"jse",
|
|
1121
|
-
false
|
|
1122
|
-
);
|
|
1123
|
-
assertThrows("primary", "<index.html>", `but "<" found`, 0, "shell");
|
|
1236
|
+
assertParse("primary", "<index.html>", [
|
|
1237
|
+
markers.traverse,
|
|
1238
|
+
[markers.external, "index.html"],
|
|
1239
|
+
]);
|
|
1124
1240
|
});
|
|
1125
1241
|
|
|
1126
1242
|
test("program", () => {
|
|
@@ -1135,47 +1251,6 @@ Body`,
|
|
|
1135
1251
|
);
|
|
1136
1252
|
});
|
|
1137
1253
|
|
|
1138
|
-
test("protocolExpression", () => {
|
|
1139
|
-
assertParse("protocolExpression", "foo://bar/baz", [
|
|
1140
|
-
[markers.global, "foo:"],
|
|
1141
|
-
[ops.literal, "bar/"],
|
|
1142
|
-
[ops.literal, "baz"],
|
|
1143
|
-
]);
|
|
1144
|
-
assertParse("protocolExpression", "http://example.com", [
|
|
1145
|
-
[markers.global, "http:"],
|
|
1146
|
-
[ops.literal, "example.com"],
|
|
1147
|
-
]);
|
|
1148
|
-
assertParse("protocolExpression", "https://example.com/about/", [
|
|
1149
|
-
[markers.global, "https:"],
|
|
1150
|
-
[ops.literal, "example.com/"],
|
|
1151
|
-
[ops.literal, "about/"],
|
|
1152
|
-
]);
|
|
1153
|
-
assertParse("protocolExpression", "https://example.com/about/index.html", [
|
|
1154
|
-
[markers.global, "https:"],
|
|
1155
|
-
[ops.literal, "example.com/"],
|
|
1156
|
-
[ops.literal, "about/"],
|
|
1157
|
-
[ops.literal, "index.html"],
|
|
1158
|
-
]);
|
|
1159
|
-
assertParse("protocolExpression", "http://localhost:5000/foo", [
|
|
1160
|
-
[markers.global, "http:"],
|
|
1161
|
-
[ops.literal, "localhost:5000/"],
|
|
1162
|
-
[ops.literal, "foo"],
|
|
1163
|
-
]);
|
|
1164
|
-
assertParse("protocolExpression", "files:///foo/bar.txt", [
|
|
1165
|
-
[markers.global, "files:"],
|
|
1166
|
-
[ops.literal, "/"],
|
|
1167
|
-
[ops.literal, "foo/"],
|
|
1168
|
-
[ops.literal, "bar.txt"],
|
|
1169
|
-
]);
|
|
1170
|
-
});
|
|
1171
|
-
|
|
1172
|
-
test("qualifiedReference", () => {
|
|
1173
|
-
assertParse("qualifiedReference", "js:Date", [
|
|
1174
|
-
[markers.global, "js:"],
|
|
1175
|
-
[ops.literal, "Date"],
|
|
1176
|
-
]);
|
|
1177
|
-
});
|
|
1178
|
-
|
|
1179
1254
|
test("regexLiteral", () => {
|
|
1180
1255
|
assertParse("regexLiteral", "/abc+/g", [ops.literal, /abc+/g]);
|
|
1181
1256
|
});
|
|
@@ -1203,17 +1278,6 @@ Body`,
|
|
|
1203
1278
|
]);
|
|
1204
1279
|
});
|
|
1205
1280
|
|
|
1206
|
-
test("scopeReference", () => {
|
|
1207
|
-
assertParse("scopeReference", "keys", [
|
|
1208
|
-
markers.reference,
|
|
1209
|
-
[ops.literal, "keys"],
|
|
1210
|
-
]);
|
|
1211
|
-
assertParse("scopeReference", "greet.js", [
|
|
1212
|
-
markers.reference,
|
|
1213
|
-
[ops.literal, "greet.js"],
|
|
1214
|
-
]);
|
|
1215
|
-
});
|
|
1216
|
-
|
|
1217
1281
|
test("shiftExpression", () => {
|
|
1218
1282
|
assertParse("shiftExpression", "1 << 2", [
|
|
1219
1283
|
ops.shiftLeft,
|
|
@@ -1236,7 +1300,7 @@ Body`,
|
|
|
1236
1300
|
assertParse("shorthandFunction", "=message", [
|
|
1237
1301
|
ops.lambda,
|
|
1238
1302
|
[[ops.literal, "_"]],
|
|
1239
|
-
[markers.
|
|
1303
|
+
[markers.traverse, [markers.reference, "message"]],
|
|
1240
1304
|
]);
|
|
1241
1305
|
assertParse("shorthandFunction", "=`Hello, ${name}.`", [
|
|
1242
1306
|
ops.lambda,
|
|
@@ -1244,14 +1308,14 @@ Body`,
|
|
|
1244
1308
|
[
|
|
1245
1309
|
ops.templateTree,
|
|
1246
1310
|
[ops.literal, ["Hello, ", "."]],
|
|
1247
|
-
[markers.
|
|
1311
|
+
[markers.traverse, [markers.reference, "name"]],
|
|
1248
1312
|
],
|
|
1249
1313
|
]);
|
|
1250
1314
|
assertParse("shorthandFunction", "=indent`hello`", [
|
|
1251
1315
|
ops.lambda,
|
|
1252
1316
|
[[ops.literal, "_"]],
|
|
1253
1317
|
[
|
|
1254
|
-
[markers.
|
|
1318
|
+
[markers.traverse, [markers.reference, "indent"]],
|
|
1255
1319
|
[ops.literal, ["hello"]],
|
|
1256
1320
|
],
|
|
1257
1321
|
]);
|
|
@@ -1264,11 +1328,11 @@ Body`,
|
|
|
1264
1328
|
test("spreadElement", () => {
|
|
1265
1329
|
assertParse("spreadElement", "...a", [
|
|
1266
1330
|
ops.spread,
|
|
1267
|
-
[markers.
|
|
1331
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
1268
1332
|
]);
|
|
1269
1333
|
assertParse("spreadElement", "…a", [
|
|
1270
1334
|
ops.spread,
|
|
1271
|
-
[markers.
|
|
1335
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
1272
1336
|
]);
|
|
1273
1337
|
});
|
|
1274
1338
|
|
|
@@ -1290,7 +1354,7 @@ Body`,
|
|
|
1290
1354
|
assertParse("templateBody", "hello${foo}world", [
|
|
1291
1355
|
ops.templateIndent,
|
|
1292
1356
|
[ops.literal, ["hello", "world"]],
|
|
1293
|
-
[markers.
|
|
1357
|
+
[markers.traverse, [markers.reference, "foo"]],
|
|
1294
1358
|
]);
|
|
1295
1359
|
assertParse("templateBody", "Documents can contain ` backticks", [
|
|
1296
1360
|
ops.templateIndent,
|
|
@@ -1316,7 +1380,8 @@ Body text`,
|
|
|
1316
1380
|
[
|
|
1317
1381
|
ops.object,
|
|
1318
1382
|
["title", [ops.literal, "Title goes here"]],
|
|
1319
|
-
["@text", [ops.templateIndent, [ops.literal, ["Body text"]]]],
|
|
1383
|
+
["(@text)", [ops.templateIndent, [ops.literal, ["Body text"]]]],
|
|
1384
|
+
["_body", [ops.templateIndent, [ops.literal, ["Body text"]]]],
|
|
1320
1385
|
]
|
|
1321
1386
|
);
|
|
1322
1387
|
});
|
|
@@ -1340,10 +1405,38 @@ Body text`,
|
|
|
1340
1405
|
[
|
|
1341
1406
|
ops.templateIndent,
|
|
1342
1407
|
[ops.literal, ["<h1>", "</h1>\n"]],
|
|
1343
|
-
[markers.
|
|
1408
|
+
[markers.traverse, [markers.reference, "title"]],
|
|
1344
1409
|
],
|
|
1345
1410
|
],
|
|
1346
|
-
]
|
|
1411
|
+
],
|
|
1412
|
+
"shell"
|
|
1413
|
+
);
|
|
1414
|
+
});
|
|
1415
|
+
|
|
1416
|
+
test.skip("templateDocument with Origami front matter", () => {
|
|
1417
|
+
assertParse(
|
|
1418
|
+
"templateDocument",
|
|
1419
|
+
`---
|
|
1420
|
+
{
|
|
1421
|
+
title: "Title"
|
|
1422
|
+
_body: _template()
|
|
1423
|
+
}
|
|
1424
|
+
---
|
|
1425
|
+
<h1>\${ title }</h1>
|
|
1426
|
+
`,
|
|
1427
|
+
[
|
|
1428
|
+
ops.object,
|
|
1429
|
+
["title", [ops.literal, "Title"]],
|
|
1430
|
+
[
|
|
1431
|
+
"_body",
|
|
1432
|
+
[
|
|
1433
|
+
ops.templateIndent,
|
|
1434
|
+
[ops.literal, ["<h1>", "</h1>\n"]],
|
|
1435
|
+
[markers.traverse, [markers.reference, "title"]],
|
|
1436
|
+
],
|
|
1437
|
+
],
|
|
1438
|
+
],
|
|
1439
|
+
"jse"
|
|
1347
1440
|
);
|
|
1348
1441
|
});
|
|
1349
1442
|
|
|
@@ -1355,32 +1448,32 @@ Body text`,
|
|
|
1355
1448
|
assertParse(
|
|
1356
1449
|
"templateLiteral",
|
|
1357
1450
|
"`Hello, world.`",
|
|
1358
|
-
[ops.
|
|
1451
|
+
[ops.templateTree, [ops.literal, ["Hello, world."]]],
|
|
1359
1452
|
"jse"
|
|
1360
1453
|
);
|
|
1361
1454
|
assertParse("templateLiteral", "`foo ${x} bar`", [
|
|
1362
1455
|
ops.templateTree,
|
|
1363
1456
|
[ops.literal, ["foo ", " bar"]],
|
|
1364
|
-
[markers.
|
|
1457
|
+
[markers.traverse, [markers.reference, "x"]],
|
|
1365
1458
|
]);
|
|
1366
1459
|
assertParse("templateLiteral", "`${`nested`}`", [
|
|
1367
1460
|
ops.templateTree,
|
|
1368
1461
|
[ops.literal, ["", ""]],
|
|
1369
1462
|
[ops.templateTree, [ops.literal, ["nested"]]],
|
|
1370
1463
|
]);
|
|
1371
|
-
assertParse("templateLiteral", "`${ map
|
|
1464
|
+
assertParse("templateLiteral", "`${ map(people, =`${name}`) }`", [
|
|
1372
1465
|
ops.templateTree,
|
|
1373
1466
|
[ops.literal, ["", ""]],
|
|
1374
1467
|
[
|
|
1375
|
-
[markers.
|
|
1376
|
-
[markers.
|
|
1468
|
+
[markers.traverse, [markers.reference, "map"]],
|
|
1469
|
+
[markers.traverse, [markers.reference, "people"]],
|
|
1377
1470
|
[
|
|
1378
1471
|
ops.lambda,
|
|
1379
1472
|
[[ops.literal, "_"]],
|
|
1380
1473
|
[
|
|
1381
1474
|
ops.templateTree,
|
|
1382
1475
|
[ops.literal, ["", ""]],
|
|
1383
|
-
[markers.
|
|
1476
|
+
[markers.traverse, [markers.reference, "name"]],
|
|
1384
1477
|
],
|
|
1385
1478
|
],
|
|
1386
1479
|
],
|
|
@@ -1391,12 +1484,53 @@ Body text`,
|
|
|
1391
1484
|
assertParse(
|
|
1392
1485
|
"templateSubstitution",
|
|
1393
1486
|
"${foo}",
|
|
1394
|
-
[markers.
|
|
1487
|
+
[markers.traverse, [markers.reference, "foo"]],
|
|
1395
1488
|
"shell",
|
|
1396
1489
|
false
|
|
1397
1490
|
);
|
|
1398
1491
|
});
|
|
1399
1492
|
|
|
1493
|
+
describe("uri", () => {
|
|
1494
|
+
test("with double slashes after colon", () => {
|
|
1495
|
+
assertParse("uri", "foo://bar/baz", [
|
|
1496
|
+
[markers.global, "foo:"],
|
|
1497
|
+
[ops.literal, "bar/"],
|
|
1498
|
+
[ops.literal, "baz"],
|
|
1499
|
+
]);
|
|
1500
|
+
assertParse("uri", "http://example.com", [
|
|
1501
|
+
[markers.global, "http:"],
|
|
1502
|
+
[ops.literal, "example.com"],
|
|
1503
|
+
]);
|
|
1504
|
+
assertParse("uri", "https://example.com/about/", [
|
|
1505
|
+
[markers.global, "https:"],
|
|
1506
|
+
[ops.literal, "example.com/"],
|
|
1507
|
+
[ops.literal, "about/"],
|
|
1508
|
+
]);
|
|
1509
|
+
assertParse("uri", "https://example.com/about/index.html", [
|
|
1510
|
+
[markers.global, "https:"],
|
|
1511
|
+
[ops.literal, "example.com/"],
|
|
1512
|
+
[ops.literal, "about/"],
|
|
1513
|
+
[ops.literal, "index.html"],
|
|
1514
|
+
]);
|
|
1515
|
+
assertParse("uri", "http://localhost:5000/foo", [
|
|
1516
|
+
[markers.global, "http:"],
|
|
1517
|
+
[ops.literal, "localhost:5000/"],
|
|
1518
|
+
[ops.literal, "foo"],
|
|
1519
|
+
]);
|
|
1520
|
+
});
|
|
1521
|
+
|
|
1522
|
+
test("without double slashes after colon", () => {
|
|
1523
|
+
assertParse("uri", "files:build", [
|
|
1524
|
+
[markers.global, "files:"],
|
|
1525
|
+
[ops.literal, "build"],
|
|
1526
|
+
]);
|
|
1527
|
+
});
|
|
1528
|
+
});
|
|
1529
|
+
|
|
1530
|
+
test("uriScheme", () => {
|
|
1531
|
+
assertParse("uriScheme", "https:", [markers.global, "https:"]);
|
|
1532
|
+
});
|
|
1533
|
+
|
|
1400
1534
|
test("whitespace block", () => {
|
|
1401
1535
|
assertParse(
|
|
1402
1536
|
"__",
|
|
@@ -1413,12 +1547,19 @@ Body text`,
|
|
|
1413
1547
|
test("unaryExpression", () => {
|
|
1414
1548
|
assertParse("unaryExpression", "!true", [
|
|
1415
1549
|
ops.logicalNot,
|
|
1416
|
-
[markers.
|
|
1550
|
+
[markers.traverse, [markers.reference, "true"]],
|
|
1417
1551
|
]);
|
|
1418
1552
|
assertParse("unaryExpression", "+1", [ops.unaryPlus, [ops.literal, 1]]);
|
|
1419
1553
|
assertParse("unaryExpression", "-2", [ops.unaryMinus, [ops.literal, 2]]);
|
|
1420
1554
|
assertParse("unaryExpression", "~3", [ops.bitwiseNot, [ops.literal, 3]]);
|
|
1421
1555
|
});
|
|
1556
|
+
|
|
1557
|
+
test("unaryOperator", () => {
|
|
1558
|
+
assertParse("unaryOperator", "!", "!");
|
|
1559
|
+
assertParse("unaryOperator", "+", "+");
|
|
1560
|
+
assertParse("unaryOperator", "-", "-");
|
|
1561
|
+
assertParse("unaryOperator", "~", "~");
|
|
1562
|
+
});
|
|
1422
1563
|
});
|
|
1423
1564
|
|
|
1424
1565
|
function assertParse(
|
|
@@ -1437,7 +1578,7 @@ function assertParse(
|
|
|
1437
1578
|
// Verify that the parser returned a `location` property and that it spans the
|
|
1438
1579
|
// entire source. We skip this check in cases where the source starts or ends
|
|
1439
1580
|
// with a comment; the parser will strip those.
|
|
1440
|
-
if (checkLocation) {
|
|
1581
|
+
if (typeof code === "object" && checkLocation) {
|
|
1441
1582
|
assertCodeLocations(code);
|
|
1442
1583
|
const resultSource = code.location.source.text.slice(
|
|
1443
1584
|
code.location.start.offset,
|
|
@@ -1459,8 +1600,9 @@ function assertCodeLocations(code) {
|
|
|
1459
1600
|
}
|
|
1460
1601
|
|
|
1461
1602
|
function assertThrows(startRule, source, message, position, mode = "shell") {
|
|
1603
|
+
let code;
|
|
1462
1604
|
try {
|
|
1463
|
-
parse(source, {
|
|
1605
|
+
code = parse(source, {
|
|
1464
1606
|
grammarSource: { text: source },
|
|
1465
1607
|
mode,
|
|
1466
1608
|
startRule,
|