@weborigami/language 0.3.3-jse.2 → 0.3.3
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/main.js +1 -1
- package/package.json +3 -3
- package/src/compiler/compile.js +0 -2
- package/src/compiler/origami.pegjs +28 -118
- package/src/compiler/parse.js +818 -1502
- package/src/compiler/parserHelpers.js +12 -13
- package/src/runtime/handlers.js +1 -4
- package/src/runtime/ops.js +10 -34
- package/src/runtime/{templateIndent.js → taggedTemplateIndent.js} +2 -2
- package/test/compiler/parse.test.js +24 -142
- package/test/runtime/ops.test.js +2 -11
- package/test/runtime/taggedTemplateIndent.test.js +1 -1
- package/src/runtime/templateStandard.js +0 -13
- package/test/runtime/templateText.test.js +0 -18
|
@@ -204,8 +204,7 @@ export function makeCall(target, args) {
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
let fnCall;
|
|
207
|
-
|
|
208
|
-
if (op === ops.traverse || op === ops.optionalTraverse) {
|
|
207
|
+
if (args[0] === ops.traverse) {
|
|
209
208
|
let tree = target;
|
|
210
209
|
|
|
211
210
|
if (tree[0] === undetermined) {
|
|
@@ -220,12 +219,12 @@ export function makeCall(target, args) {
|
|
|
220
219
|
if (args.length > 1) {
|
|
221
220
|
// Regular traverse
|
|
222
221
|
const keys = args.slice(1);
|
|
223
|
-
fnCall = [
|
|
222
|
+
fnCall = [ops.traverse, tree, ...keys];
|
|
224
223
|
} else {
|
|
225
224
|
// Traverse without arguments equates to unpack
|
|
226
225
|
fnCall = [ops.unpack, tree];
|
|
227
226
|
}
|
|
228
|
-
} else if (
|
|
227
|
+
} else if (args[0] === ops.template) {
|
|
229
228
|
// Tagged template
|
|
230
229
|
const strings = args[1];
|
|
231
230
|
const values = args.slice(2);
|
|
@@ -276,15 +275,6 @@ export function makeDeferredArguments(args) {
|
|
|
276
275
|
});
|
|
277
276
|
}
|
|
278
277
|
|
|
279
|
-
export function makeJsPropertyAccess(expression, property) {
|
|
280
|
-
const location = {
|
|
281
|
-
source: expression.location.source,
|
|
282
|
-
start: expression.location.start,
|
|
283
|
-
end: property.location.end,
|
|
284
|
-
};
|
|
285
|
-
return annotate([expression, property], location);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
278
|
/**
|
|
289
279
|
* Make an object.
|
|
290
280
|
*
|
|
@@ -374,6 +364,15 @@ export function makeProperty(key, value) {
|
|
|
374
364
|
return [key, modified];
|
|
375
365
|
}
|
|
376
366
|
|
|
367
|
+
export function makeJsPropertyAccess(expression, property) {
|
|
368
|
+
const location = {
|
|
369
|
+
source: expression.location.source,
|
|
370
|
+
start: expression.location.start,
|
|
371
|
+
end: property.location.end,
|
|
372
|
+
};
|
|
373
|
+
return annotate([expression, property], location);
|
|
374
|
+
}
|
|
375
|
+
|
|
377
376
|
export function makeReference(identifier) {
|
|
378
377
|
// We can't know for sure that an identifier is a builtin reference until we
|
|
379
378
|
// see whether it's being called as a function.
|
package/src/runtime/handlers.js
CHANGED
|
@@ -74,12 +74,9 @@ export async function handleExtension(parent, value, key) {
|
|
|
74
74
|
key = trailingSlash.remove(key);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
// Special
|
|
78
|
-
// `.jse.<ext>` are JSE documents.
|
|
77
|
+
// Special case: `.ori.<ext>` extensions are Origami documents.
|
|
79
78
|
const extname = key.match(/\.ori\.\S+$/)
|
|
80
79
|
? ".oridocument"
|
|
81
|
-
: key.match(/\.jse\.\S+$/)
|
|
82
|
-
? ".jsedocument"
|
|
83
80
|
: extension.extname(key);
|
|
84
81
|
if (extname) {
|
|
85
82
|
const handler = await getExtensionHandler(parent, extname);
|
package/src/runtime/ops.js
CHANGED
|
@@ -12,17 +12,16 @@ import {
|
|
|
12
12
|
isUnpackable,
|
|
13
13
|
scope as scopeFn,
|
|
14
14
|
setParent,
|
|
15
|
-
|
|
15
|
+
concat as treeConcat,
|
|
16
16
|
} from "@weborigami/async-tree";
|
|
17
17
|
import os from "node:os";
|
|
18
|
+
import taggedTemplateIndent from "../../src/runtime/taggedTemplateIndent.js";
|
|
18
19
|
import { builtinReferenceError, scopeReferenceError } from "./errors.js";
|
|
19
20
|
import expressionObject from "./expressionObject.js";
|
|
20
21
|
import { evaluate } from "./internal.js";
|
|
21
22
|
import mergeTrees from "./mergeTrees.js";
|
|
22
23
|
import OrigamiFiles from "./OrigamiFiles.js";
|
|
23
24
|
import { codeSymbol } from "./symbols.js";
|
|
24
|
-
import templateFunctionIndent from "./templateIndent.js";
|
|
25
|
-
import templateFunctionStandard from "./templateStandard.js";
|
|
26
25
|
|
|
27
26
|
function addOpLabel(op, label) {
|
|
28
27
|
Object.defineProperty(op, "toString", {
|
|
@@ -106,7 +105,7 @@ addOpLabel(comma, "«ops.comma»");
|
|
|
106
105
|
* @param {any[]} args
|
|
107
106
|
*/
|
|
108
107
|
export async function concat(...args) {
|
|
109
|
-
return
|
|
108
|
+
return treeConcat.call(this, args);
|
|
110
109
|
}
|
|
111
110
|
addOpLabel(concat, "«ops.concat»");
|
|
112
111
|
|
|
@@ -115,13 +114,6 @@ export async function conditional(condition, truthy, falsy) {
|
|
|
115
114
|
return value instanceof Function ? await value() : value;
|
|
116
115
|
}
|
|
117
116
|
|
|
118
|
-
export async function construct(constructor, ...args) {
|
|
119
|
-
if (isUnpackable(constructor)) {
|
|
120
|
-
constructor = await constructor.unpack();
|
|
121
|
-
}
|
|
122
|
-
return Reflect.construct(constructor, args);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
117
|
/**
|
|
126
118
|
* Construct a document object by invoking the body code (a lambda) and adding
|
|
127
119
|
* the resulting text to the front data.
|
|
@@ -480,14 +472,6 @@ export async function object(...entries) {
|
|
|
480
472
|
addOpLabel(object, "«ops.object»");
|
|
481
473
|
object.unevaluatedArgs = true;
|
|
482
474
|
|
|
483
|
-
export function optionalTraverse(treelike, key) {
|
|
484
|
-
if (!treelike) {
|
|
485
|
-
return undefined;
|
|
486
|
-
}
|
|
487
|
-
return Tree.traverseOrThrow(treelike, key);
|
|
488
|
-
}
|
|
489
|
-
addOpLabel(optionalTraverse, "«ops.optionalTraverse");
|
|
490
|
-
|
|
491
475
|
export function remainder(a, b) {
|
|
492
476
|
return a % b;
|
|
493
477
|
}
|
|
@@ -562,29 +546,21 @@ export function subtraction(a, b) {
|
|
|
562
546
|
}
|
|
563
547
|
addOpLabel(subtraction, "«ops.subtraction»");
|
|
564
548
|
|
|
565
|
-
/**
|
|
566
|
-
* Apply the tree indent tagged template function.
|
|
567
|
-
*/
|
|
568
|
-
export async function templateIndent(strings, ...values) {
|
|
569
|
-
return templateFunctionIndent(strings, ...values);
|
|
570
|
-
}
|
|
571
|
-
addOpLabel(templateIndent, "«ops.templateIndent»");
|
|
572
|
-
|
|
573
549
|
/**
|
|
574
550
|
* Apply the default tagged template function.
|
|
575
551
|
*/
|
|
576
|
-
export function
|
|
577
|
-
return
|
|
552
|
+
export async function template(strings, ...values) {
|
|
553
|
+
return deepText(strings, ...values);
|
|
578
554
|
}
|
|
579
|
-
addOpLabel(
|
|
555
|
+
addOpLabel(template, "«ops.template»");
|
|
580
556
|
|
|
581
557
|
/**
|
|
582
|
-
* Apply the
|
|
558
|
+
* Apply the tagged template indent function.
|
|
583
559
|
*/
|
|
584
|
-
export async function
|
|
585
|
-
return
|
|
560
|
+
export async function templateIndent(strings, ...values) {
|
|
561
|
+
return taggedTemplateIndent(strings, ...values);
|
|
586
562
|
}
|
|
587
|
-
addOpLabel(
|
|
563
|
+
addOpLabel(templateIndent, "«ops.templateIndent");
|
|
588
564
|
|
|
589
565
|
/**
|
|
590
566
|
* Traverse a path of keys through a tree.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { concat, toString, Tree } from "@weborigami/async-tree";
|
|
2
2
|
|
|
3
3
|
const lastLineWhitespaceRegex = /\n(?<indent>[ \t]*)$/;
|
|
4
4
|
|
|
@@ -19,7 +19,7 @@ export default async function indent(strings, ...values) {
|
|
|
19
19
|
}
|
|
20
20
|
const { blockIndentations, strings: modifiedStrings } = modified;
|
|
21
21
|
const valueTexts = await Promise.all(
|
|
22
|
-
values.map((value) => (Tree.isTreelike(value) ?
|
|
22
|
+
values.map((value) => (Tree.isTreelike(value) ? concat(value) : value))
|
|
23
23
|
);
|
|
24
24
|
return joinBlocks(modifiedStrings, valueTexts, blockIndentations);
|
|
25
25
|
}
|
|
@@ -19,46 +19,6 @@ describe("Origami parser", () => {
|
|
|
19
19
|
]);
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
test("angleBracketLiteral", () => {
|
|
23
|
-
assertParse(
|
|
24
|
-
"angleBracketLiteral",
|
|
25
|
-
"<index.html>",
|
|
26
|
-
[ops.scope, "index.html"],
|
|
27
|
-
"jse",
|
|
28
|
-
false
|
|
29
|
-
);
|
|
30
|
-
assertParse(
|
|
31
|
-
"angleBracketLiteral",
|
|
32
|
-
"<foo/bar/baz>",
|
|
33
|
-
[
|
|
34
|
-
ops.traverse,
|
|
35
|
-
[ops.scope, "foo/"],
|
|
36
|
-
[ops.literal, "bar/"],
|
|
37
|
-
[ops.literal, "baz"],
|
|
38
|
-
],
|
|
39
|
-
"jse",
|
|
40
|
-
false
|
|
41
|
-
);
|
|
42
|
-
assertParse("angleBracketLiteral", "<files:src/assets>", [
|
|
43
|
-
ops.traverse,
|
|
44
|
-
[
|
|
45
|
-
[ops.builtin, "files:"],
|
|
46
|
-
[ops.literal, "src/"],
|
|
47
|
-
],
|
|
48
|
-
[ops.literal, "assets"],
|
|
49
|
-
]);
|
|
50
|
-
assertParse(
|
|
51
|
-
"angleBracketLiteral",
|
|
52
|
-
"<https://example.com/>",
|
|
53
|
-
[
|
|
54
|
-
[ops.builtin, "https:"],
|
|
55
|
-
[ops.literal, "example.com/"],
|
|
56
|
-
],
|
|
57
|
-
"jse",
|
|
58
|
-
false
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
22
|
test("arrayLiteral", () => {
|
|
63
23
|
assertParse("arrayLiteral", "[]", [ops.array]);
|
|
64
24
|
assertParse("arrayLiteral", "[1, 2, 3]", [
|
|
@@ -439,8 +399,7 @@ Body`,
|
|
|
439
399
|
]);
|
|
440
400
|
|
|
441
401
|
// Consecutive slashes at start of something = comment
|
|
442
|
-
assertParse("expression", "
|
|
443
|
-
|
|
402
|
+
assertParse("expression", "path //comment", [ops.scope, "path"], false);
|
|
444
403
|
assertParse("expression", "page.ori(mdHtml:(about.md))", [
|
|
445
404
|
[ops.scope, "page.ori"],
|
|
446
405
|
[
|
|
@@ -487,11 +446,7 @@ Body`,
|
|
|
487
446
|
]);
|
|
488
447
|
assertParse("expression", "fn =`x`", [
|
|
489
448
|
[ops.builtin, "fn"],
|
|
490
|
-
[
|
|
491
|
-
ops.lambda,
|
|
492
|
-
[[ops.literal, "_"]],
|
|
493
|
-
[ops.templateTree, [ops.literal, ["x"]]],
|
|
494
|
-
],
|
|
449
|
+
[ops.lambda, [[ops.literal, "_"]], [ops.template, [ops.literal, ["x"]]]],
|
|
495
450
|
]);
|
|
496
451
|
assertParse("expression", "copy app.js(formulas), files:snapshot", [
|
|
497
452
|
[ops.builtin, "copy"],
|
|
@@ -509,7 +464,7 @@ Body`,
|
|
|
509
464
|
[
|
|
510
465
|
ops.lambda,
|
|
511
466
|
[[ops.literal, "_"]],
|
|
512
|
-
[ops.
|
|
467
|
+
[ops.template, [ops.literal, ["<li>", "</li>"]], [ops.scope, "_"]],
|
|
513
468
|
],
|
|
514
469
|
]);
|
|
515
470
|
assertParse("expression", `https://example.com/about/`, [
|
|
@@ -568,23 +523,6 @@ Body`,
|
|
|
568
523
|
]);
|
|
569
524
|
});
|
|
570
525
|
|
|
571
|
-
test("frontMatterExpression", () => {
|
|
572
|
-
assertParse(
|
|
573
|
-
"frontMatterExpression",
|
|
574
|
-
`---
|
|
575
|
-
(name) => _template()
|
|
576
|
-
---
|
|
577
|
-
`,
|
|
578
|
-
[
|
|
579
|
-
ops.lambda,
|
|
580
|
-
[[ops.literal, "name"]],
|
|
581
|
-
[[ops.scope, "_template"], undefined],
|
|
582
|
-
],
|
|
583
|
-
"jse",
|
|
584
|
-
false
|
|
585
|
-
);
|
|
586
|
-
});
|
|
587
|
-
|
|
588
526
|
test("group", () => {
|
|
589
527
|
assertParse("group", "(hello)", [ops.scope, "hello"]);
|
|
590
528
|
assertParse("group", "(((nested)))", [ops.scope, "nested"]);
|
|
@@ -606,10 +544,10 @@ Body`,
|
|
|
606
544
|
});
|
|
607
545
|
|
|
608
546
|
test("identifier", () => {
|
|
609
|
-
assertParse("identifier", "abc", "abc",
|
|
610
|
-
assertParse("identifier", "index.html", "index.html",
|
|
611
|
-
assertParse("identifier", "foo\\ bar", "foo bar",
|
|
612
|
-
assertParse("identifier", "x-y-z", "x-y-z",
|
|
547
|
+
assertParse("identifier", "abc", "abc", false);
|
|
548
|
+
assertParse("identifier", "index.html", "index.html", false);
|
|
549
|
+
assertParse("identifier", "foo\\ bar", "foo bar", false);
|
|
550
|
+
assertParse("identifier", "x-y-z", "x-y-z", false);
|
|
613
551
|
});
|
|
614
552
|
|
|
615
553
|
test("implicitParenthesesCallExpression", () => {
|
|
@@ -648,8 +586,8 @@ Body`,
|
|
|
648
586
|
});
|
|
649
587
|
|
|
650
588
|
test("jsIdentifier", () => {
|
|
651
|
-
assertParse("jsIdentifier", "foo", "foo",
|
|
652
|
-
assertParse("jsIdentifier", "$Δelta", "$Δelta",
|
|
589
|
+
assertParse("jsIdentifier", "foo", "foo", false);
|
|
590
|
+
assertParse("jsIdentifier", "$Δelta", "$Δelta", false);
|
|
653
591
|
assertThrows(
|
|
654
592
|
"jsIdentifier",
|
|
655
593
|
"1stCharacterIsNumber",
|
|
@@ -689,7 +627,6 @@ Body`,
|
|
|
689
627
|
[ops.literal, 2],
|
|
690
628
|
[ops.literal, 3],
|
|
691
629
|
]);
|
|
692
|
-
assertThrows("list", "1\n2\n3", `but "\\n" found`, 0, "jse");
|
|
693
630
|
assertParse("list", "'a' , 'b' , 'c'", [
|
|
694
631
|
[ops.literal, "a"],
|
|
695
632
|
[ops.literal, "b"],
|
|
@@ -725,13 +662,7 @@ Body`,
|
|
|
725
662
|
});
|
|
726
663
|
|
|
727
664
|
test("multiLineComment", () => {
|
|
728
|
-
assertParse(
|
|
729
|
-
"multiLineComment",
|
|
730
|
-
"/*\nHello, world!\n*/",
|
|
731
|
-
null,
|
|
732
|
-
"jse",
|
|
733
|
-
false
|
|
734
|
-
);
|
|
665
|
+
assertParse("multiLineComment", "/*\nHello, world!\n*/", null, false);
|
|
735
666
|
});
|
|
736
667
|
|
|
737
668
|
test("multiplicativeExpression", () => {
|
|
@@ -756,13 +687,6 @@ Body`,
|
|
|
756
687
|
assertParse("namespace", "js:", [ops.builtin, "js:"]);
|
|
757
688
|
});
|
|
758
689
|
|
|
759
|
-
test("newExpression", () => {
|
|
760
|
-
assertParse("newExpression", "new Foo()", [
|
|
761
|
-
ops.construct,
|
|
762
|
-
[ops.scope, "Foo"],
|
|
763
|
-
]);
|
|
764
|
-
});
|
|
765
|
-
|
|
766
690
|
test("nullishCoalescingExpression", () => {
|
|
767
691
|
assertParse("nullishCoalescingExpression", "a ?? b", [
|
|
768
692
|
ops.nullishCoalescing,
|
|
@@ -915,16 +839,9 @@ Body`,
|
|
|
915
839
|
});
|
|
916
840
|
|
|
917
841
|
test("objectPublicKey", () => {
|
|
918
|
-
assertParse("objectPublicKey", "a", "a",
|
|
919
|
-
assertParse("objectPublicKey", "markdown/", "markdown/",
|
|
920
|
-
assertParse("objectPublicKey", "foo\\ bar", "foo bar",
|
|
921
|
-
});
|
|
922
|
-
|
|
923
|
-
test("optionalChaining", () => {
|
|
924
|
-
assertParse("optionalChaining", "?.key", [
|
|
925
|
-
ops.optionalTraverse,
|
|
926
|
-
[ops.literal, "key"],
|
|
927
|
-
]);
|
|
842
|
+
assertParse("objectPublicKey", "a", "a", false);
|
|
843
|
+
assertParse("objectPublicKey", "markdown/", "markdown/", false);
|
|
844
|
+
assertParse("objectPublicKey", "foo\\ bar", "foo bar", false);
|
|
928
845
|
});
|
|
929
846
|
|
|
930
847
|
test("parenthesesArguments", () => {
|
|
@@ -994,15 +911,6 @@ Body`,
|
|
|
994
911
|
[ops.literal, 1],
|
|
995
912
|
[ops.literal, 2],
|
|
996
913
|
]);
|
|
997
|
-
// Only in JSE
|
|
998
|
-
assertParse(
|
|
999
|
-
"primary",
|
|
1000
|
-
"<index.html>",
|
|
1001
|
-
[ops.scope, "index.html"],
|
|
1002
|
-
"jse",
|
|
1003
|
-
false
|
|
1004
|
-
);
|
|
1005
|
-
assertThrows("primary", "<index.html>", `but "<" found`, 0, "shell");
|
|
1006
914
|
});
|
|
1007
915
|
|
|
1008
916
|
test("program", () => {
|
|
@@ -1012,7 +920,6 @@ Body`,
|
|
|
1012
920
|
'Hello'
|
|
1013
921
|
`,
|
|
1014
922
|
[ops.literal, "Hello"],
|
|
1015
|
-
"jse",
|
|
1016
923
|
false
|
|
1017
924
|
);
|
|
1018
925
|
});
|
|
@@ -1057,10 +964,6 @@ Body`,
|
|
|
1057
964
|
]);
|
|
1058
965
|
});
|
|
1059
966
|
|
|
1060
|
-
test("regexLiteral", () => {
|
|
1061
|
-
assertParse("regexLiteral", "/abc+/g", [ops.literal, /abc+/g]);
|
|
1062
|
-
});
|
|
1063
|
-
|
|
1064
967
|
test("relationalExpression", () => {
|
|
1065
968
|
assertParse("relationalExpression", "1 < 2", [
|
|
1066
969
|
ops.lessThan,
|
|
@@ -1122,7 +1025,7 @@ Body`,
|
|
|
1122
1025
|
assertParse("shorthandFunction", "=`Hello, ${name}.`", [
|
|
1123
1026
|
ops.lambda,
|
|
1124
1027
|
[[ops.literal, "_"]],
|
|
1125
|
-
[ops.
|
|
1028
|
+
[ops.template, [ops.literal, ["Hello, ", "."]], [ops.scope, "name"]],
|
|
1126
1029
|
]);
|
|
1127
1030
|
assertParse("shorthandFunction", "=indent`hello`", [
|
|
1128
1031
|
ops.lambda,
|
|
@@ -1135,7 +1038,7 @@ Body`,
|
|
|
1135
1038
|
});
|
|
1136
1039
|
|
|
1137
1040
|
test("singleLineComment", () => {
|
|
1138
|
-
assertParse("singleLineComment", "// Hello, world!", null,
|
|
1041
|
+
assertParse("singleLineComment", "// Hello, world!", null, false);
|
|
1139
1042
|
});
|
|
1140
1043
|
|
|
1141
1044
|
test("spreadElement", () => {
|
|
@@ -1239,27 +1142,21 @@ Body text`,
|
|
|
1239
1142
|
|
|
1240
1143
|
test("templateLiteral", () => {
|
|
1241
1144
|
assertParse("templateLiteral", "`Hello, world.`", [
|
|
1242
|
-
ops.
|
|
1145
|
+
ops.template,
|
|
1243
1146
|
[ops.literal, ["Hello, world."]],
|
|
1244
1147
|
]);
|
|
1245
|
-
assertParse(
|
|
1246
|
-
"templateLiteral",
|
|
1247
|
-
"`Hello, world.`",
|
|
1248
|
-
[ops.templateStandard, [ops.literal, ["Hello, world."]]],
|
|
1249
|
-
"jse"
|
|
1250
|
-
);
|
|
1251
1148
|
assertParse("templateLiteral", "`foo ${x} bar`", [
|
|
1252
|
-
ops.
|
|
1149
|
+
ops.template,
|
|
1253
1150
|
[ops.literal, ["foo ", " bar"]],
|
|
1254
1151
|
[ops.scope, "x"],
|
|
1255
1152
|
]);
|
|
1256
1153
|
assertParse("templateLiteral", "`${`nested`}`", [
|
|
1257
|
-
ops.
|
|
1154
|
+
ops.template,
|
|
1258
1155
|
[ops.literal, ["", ""]],
|
|
1259
|
-
[ops.
|
|
1156
|
+
[ops.template, [ops.literal, ["nested"]]],
|
|
1260
1157
|
]);
|
|
1261
1158
|
assertParse("templateLiteral", "`${ map:(people, =`${name}`) }`", [
|
|
1262
|
-
ops.
|
|
1159
|
+
ops.template,
|
|
1263
1160
|
[ops.literal, ["", ""]],
|
|
1264
1161
|
[
|
|
1265
1162
|
[ops.builtin, "map:"],
|
|
@@ -1267,20 +1164,14 @@ Body text`,
|
|
|
1267
1164
|
[
|
|
1268
1165
|
ops.lambda,
|
|
1269
1166
|
[[ops.literal, "_"]],
|
|
1270
|
-
[ops.
|
|
1167
|
+
[ops.template, [ops.literal, ["", ""]], [ops.scope, "name"]],
|
|
1271
1168
|
],
|
|
1272
1169
|
],
|
|
1273
1170
|
]);
|
|
1274
1171
|
});
|
|
1275
1172
|
|
|
1276
1173
|
test("templateSubtitution", () => {
|
|
1277
|
-
assertParse(
|
|
1278
|
-
"templateSubstitution",
|
|
1279
|
-
"${foo}",
|
|
1280
|
-
[ops.scope, "foo"],
|
|
1281
|
-
"shell",
|
|
1282
|
-
false
|
|
1283
|
-
);
|
|
1174
|
+
assertParse("templateSubstitution", "${foo}", [ops.scope, "foo"], false);
|
|
1284
1175
|
});
|
|
1285
1176
|
|
|
1286
1177
|
test("whitespace block", () => {
|
|
@@ -1291,7 +1182,6 @@ Body text`,
|
|
|
1291
1182
|
// Second comment
|
|
1292
1183
|
`,
|
|
1293
1184
|
null,
|
|
1294
|
-
"jse",
|
|
1295
1185
|
false
|
|
1296
1186
|
);
|
|
1297
1187
|
});
|
|
@@ -1307,16 +1197,9 @@ Body text`,
|
|
|
1307
1197
|
});
|
|
1308
1198
|
});
|
|
1309
1199
|
|
|
1310
|
-
function assertParse(
|
|
1311
|
-
startRule,
|
|
1312
|
-
source,
|
|
1313
|
-
expected,
|
|
1314
|
-
mode = "shell",
|
|
1315
|
-
checkLocation = true
|
|
1316
|
-
) {
|
|
1200
|
+
function assertParse(startRule, source, expected, checkLocation = true) {
|
|
1317
1201
|
const code = parse(source, {
|
|
1318
1202
|
grammarSource: { text: source },
|
|
1319
|
-
mode,
|
|
1320
1203
|
startRule,
|
|
1321
1204
|
});
|
|
1322
1205
|
|
|
@@ -1344,11 +1227,10 @@ function assertCodeLocations(code) {
|
|
|
1344
1227
|
}
|
|
1345
1228
|
}
|
|
1346
1229
|
|
|
1347
|
-
function assertThrows(startRule, source, message, position
|
|
1230
|
+
function assertThrows(startRule, source, message, position) {
|
|
1348
1231
|
try {
|
|
1349
1232
|
parse(source, {
|
|
1350
1233
|
grammarSource: { text: source },
|
|
1351
|
-
mode,
|
|
1352
1234
|
startRule,
|
|
1353
1235
|
});
|
|
1354
1236
|
} catch (/** @type {any} */ error) {
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -80,11 +80,7 @@ describe("ops", () => {
|
|
|
80
80
|
assert.strictEqual(await ops.conditional(false, errorFn, trueFn), true);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
test("ops.
|
|
84
|
-
assert.equal(await ops.construct(String, "hello"), "hello");
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("ops.document", async () => {
|
|
83
|
+
test("ops.documentFunction", async () => {
|
|
88
84
|
const code = createCode([
|
|
89
85
|
ops.document,
|
|
90
86
|
{
|
|
@@ -94,7 +90,7 @@ describe("ops", () => {
|
|
|
94
90
|
ops.lambda,
|
|
95
91
|
[["_"]],
|
|
96
92
|
[
|
|
97
|
-
ops.
|
|
93
|
+
ops.template,
|
|
98
94
|
[ops.literal, ["a = ", ""]],
|
|
99
95
|
[ops.concat, [ops.scope, "a"]],
|
|
100
96
|
],
|
|
@@ -297,11 +293,6 @@ describe("ops", () => {
|
|
|
297
293
|
assert.strictEqual(ops.multiplication("foo", 2), NaN);
|
|
298
294
|
});
|
|
299
295
|
|
|
300
|
-
test("ops.optionalTraverse", async () => {
|
|
301
|
-
assert.equal(await ops.optionalTraverse(null, "a"), undefined);
|
|
302
|
-
assert.equal(await ops.optionalTraverse({ a: 1 }, "a"), 1);
|
|
303
|
-
});
|
|
304
|
-
|
|
305
296
|
test("ops.notEqual", () => {
|
|
306
297
|
assert(!ops.notEqual(1, 1));
|
|
307
298
|
assert(ops.notEqual(1, 2));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import indent from "../../src/runtime/
|
|
3
|
+
import indent from "../../src/runtime/taggedTemplateIndent.js";
|
|
4
4
|
|
|
5
5
|
describe("taggedTemplateIndent", () => {
|
|
6
6
|
test("joins strings and values together if template isn't a block template", async () => {
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Concatenate the strings with a standard tagged template function that works
|
|
3
|
-
* just like normal JavaScript templates. This is: a) synchronous, b) does not
|
|
4
|
-
* convert treelike objects to strings.
|
|
5
|
-
*/
|
|
6
|
-
export default function standardTemplate(strings, ...values) {
|
|
7
|
-
let result = strings[0];
|
|
8
|
-
for (let i = 0; i < values.length; i++) {
|
|
9
|
-
result += values[i];
|
|
10
|
-
result += strings[i + 1];
|
|
11
|
-
}
|
|
12
|
-
return result;
|
|
13
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import { describe, test } from "node:test";
|
|
3
|
-
import templateText from "../../src/runtime/templateStandard.js";
|
|
4
|
-
|
|
5
|
-
describe("templateText", () => {
|
|
6
|
-
test("joins strings and values together like JavaScript", async () => {
|
|
7
|
-
const a = 1;
|
|
8
|
-
const b = 2;
|
|
9
|
-
const result = await templateText`-${a} ${b}-`;
|
|
10
|
-
assert.equal(result, "-1 2-");
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test("renders an object like JavaScript", async () => {
|
|
14
|
-
const object = { a: 1 };
|
|
15
|
-
const result = await templateText`-${object}-`;
|
|
16
|
-
assert.equal(result, "-[object Object]-");
|
|
17
|
-
});
|
|
18
|
-
});
|