@weborigami/language 0.5.5 → 0.5.7
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/index.ts +16 -6
- package/main.js +9 -4
- package/package.json +4 -3
- package/src/compiler/compile.js +10 -4
- package/src/compiler/optimize.js +115 -97
- package/src/compiler/origami.pegjs +1 -4
- package/src/compiler/parse.js +568 -588
- package/src/compiler/parserHelpers.js +2 -2
- package/src/handlers/css_handler.js +7 -0
- package/src/handlers/csv_handler.js +129 -0
- package/src/handlers/handlers.js +33 -0
- package/src/handlers/htm_handler.js +2 -0
- package/src/handlers/html_handler.js +7 -0
- package/src/handlers/jpeg_handler.js +62 -0
- package/src/handlers/jpg_handler.js +2 -0
- package/src/handlers/js_handler.js +51 -0
- package/src/handlers/json_handler.js +26 -0
- package/src/handlers/md_handler.js +7 -0
- package/src/handlers/mjs_handler.js +2 -0
- package/src/handlers/ori_handler.js +52 -0
- package/src/handlers/oridocument_handler.js +77 -0
- package/src/handlers/parseFrontMatter.js +16 -0
- package/src/handlers/ts_handler.js +1 -0
- package/src/handlers/txt_handler.js +108 -0
- package/src/handlers/wasm_handler.js +15 -0
- package/src/handlers/xhtml_handler.js +2 -0
- package/src/handlers/yaml_handler.js +33 -0
- package/src/handlers/yml_handler.js +2 -0
- package/src/project/builtins.js +5 -0
- package/src/project/coreGlobals.js +17 -0
- package/src/{runtime → project}/jsGlobals.js +3 -1
- package/src/project/projectConfig.js +36 -0
- package/src/project/projectGlobals.js +19 -0
- package/src/project/projectRoot.js +59 -0
- package/src/protocols/constructHref.js +20 -0
- package/src/protocols/constructSiteTree.js +26 -0
- package/src/protocols/explore.js +14 -0
- package/src/protocols/fetchAndHandleExtension.js +25 -0
- package/src/protocols/files.js +26 -0
- package/src/protocols/http.js +15 -0
- package/src/protocols/https.js +15 -0
- package/src/protocols/httpstree.js +14 -0
- package/src/protocols/httptree.js +14 -0
- package/src/protocols/node.js +13 -0
- package/src/protocols/package.js +67 -0
- package/src/protocols/protocolGlobals.js +12 -0
- package/src/protocols/protocols.js +8 -0
- package/src/runtime/EventTargetMixin.js +1 -1
- package/src/runtime/HandleExtensionsTransform.js +3 -12
- package/src/runtime/ImportModulesMixin.js +4 -10
- package/src/runtime/InvokeFunctionsTransform.js +1 -1
- package/src/runtime/evaluate.js +15 -8
- package/src/runtime/expressionFunction.js +5 -7
- package/src/runtime/expressionObject.js +10 -20
- package/src/runtime/functionResultsMap.js +1 -3
- package/src/runtime/{handlers.js → handleExtension.js} +13 -11
- package/src/runtime/mergeTrees.js +1 -8
- package/src/runtime/ops.js +83 -90
- package/test/compiler/compile.test.js +20 -19
- package/test/compiler/optimize.test.js +60 -25
- package/test/compiler/parse.test.js +4 -4
- package/test/generator/oriEval.js +4 -5
- package/test/handlers/csv.handler.test.js +36 -0
- package/test/handlers/fixtures/add.wasm +0 -0
- package/test/handlers/fixtures/exif.jpeg +0 -0
- package/test/handlers/fixtures/frontMatter.md +5 -0
- package/test/handlers/fixtures/list.js +4 -0
- package/test/handlers/fixtures/multiple.js +4 -0
- package/test/handlers/fixtures/obj.js +3 -0
- package/test/handlers/fixtures/site.ori +5 -0
- package/test/handlers/fixtures/string.js +1 -0
- package/test/handlers/fixtures/tag.yaml +5 -0
- package/test/handlers/fixtures/test.ori +9 -0
- package/test/handlers/jpeg.handler.test.js +18 -0
- package/test/handlers/js.handler.test.js +46 -0
- package/test/handlers/json.handler.test.js +14 -0
- package/test/handlers/ori.handler.test.js +87 -0
- package/test/handlers/oridocument.handler.test.js +68 -0
- package/test/handlers/txt.handler.test.js +41 -0
- package/test/handlers/wasm.handler.test.js +20 -0
- package/test/handlers/yaml.handler.test.js +17 -0
- package/test/project/fixtures/withConfig/config.ori +4 -0
- package/test/project/fixtures/withConfig/subfolder/greet.js +1 -0
- package/test/project/fixtures/withPackageJson/package.json +0 -0
- package/test/project/jsGlobals.test.js +21 -0
- package/test/project/projectConfig.test.js +28 -0
- package/test/project/projectRoot.test.js +40 -0
- package/test/protocols/package.test.js +11 -0
- package/test/runtime/evaluate.test.js +26 -42
- package/test/runtime/expressionObject.test.js +16 -20
- package/test/runtime/{handlers.test.js → handleExtension.test.js} +4 -20
- package/test/runtime/jsGlobals.test.js +4 -6
- package/test/runtime/mergeTrees.test.js +2 -4
- package/test/runtime/ops.test.js +66 -68
- package/src/runtime/getHandlers.js +0 -10
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { ObjectTree } from "@weborigami/async-tree";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
import * as compile from "../../src/compiler/compile.js";
|
|
4
|
-
import
|
|
4
|
+
import {
|
|
5
|
+
REFERENCE_INHERITED,
|
|
6
|
+
REFERENCE_PARAM,
|
|
7
|
+
default as optimize,
|
|
8
|
+
} from "../../src/compiler/optimize.js";
|
|
5
9
|
import { markers } from "../../src/compiler/parserHelpers.js";
|
|
6
10
|
import { ops } from "../../src/runtime/internal.js";
|
|
7
11
|
import {
|
|
@@ -24,11 +28,17 @@ describe("optimize", () => {
|
|
|
24
28
|
[
|
|
25
29
|
"a",
|
|
26
30
|
[
|
|
27
|
-
[ops.
|
|
31
|
+
[ops.params, 0],
|
|
28
32
|
[ops.literal, "name"],
|
|
29
33
|
],
|
|
30
34
|
],
|
|
31
|
-
[
|
|
35
|
+
[
|
|
36
|
+
"b",
|
|
37
|
+
[
|
|
38
|
+
[ops.inherited, 0],
|
|
39
|
+
[ops.literal, "a"],
|
|
40
|
+
],
|
|
41
|
+
],
|
|
32
42
|
],
|
|
33
43
|
];
|
|
34
44
|
assertCompile(expression, expected);
|
|
@@ -54,7 +64,7 @@ describe("optimize", () => {
|
|
|
54
64
|
[
|
|
55
65
|
"a",
|
|
56
66
|
[
|
|
57
|
-
[ops.
|
|
67
|
+
[ops.inherited, 1],
|
|
58
68
|
[ops.literal, "a"],
|
|
59
69
|
],
|
|
60
70
|
],
|
|
@@ -81,7 +91,7 @@ describe("optimize", () => {
|
|
|
81
91
|
[
|
|
82
92
|
"name",
|
|
83
93
|
[
|
|
84
|
-
[ops.
|
|
94
|
+
[ops.inherited, 1],
|
|
85
95
|
[ops.literal, "name"],
|
|
86
96
|
],
|
|
87
97
|
],
|
|
@@ -99,14 +109,18 @@ describe("optimize", () => {
|
|
|
99
109
|
markers.traverse,
|
|
100
110
|
[markers.reference, "folder"],
|
|
101
111
|
]);
|
|
112
|
+
const parent = {};
|
|
102
113
|
const expected = [
|
|
103
114
|
ops.cache,
|
|
104
115
|
{},
|
|
105
116
|
"folder",
|
|
106
|
-
[
|
|
117
|
+
[
|
|
118
|
+
[ops.scope, parent],
|
|
119
|
+
[ops.literal, "folder"],
|
|
120
|
+
],
|
|
107
121
|
];
|
|
108
122
|
const globals = {};
|
|
109
|
-
assertCodeEqual(optimize(code, { globals }), expected);
|
|
123
|
+
assertCodeEqual(optimize(code, { globals, parent }), expected);
|
|
110
124
|
});
|
|
111
125
|
|
|
112
126
|
test("external reference", () => {
|
|
@@ -115,14 +129,18 @@ describe("optimize", () => {
|
|
|
115
129
|
markers.traverse,
|
|
116
130
|
[markers.reference, "index.html"],
|
|
117
131
|
]);
|
|
132
|
+
const parent = {};
|
|
118
133
|
const expected = [
|
|
119
134
|
ops.cache,
|
|
120
135
|
{},
|
|
121
136
|
"index.html",
|
|
122
|
-
[
|
|
137
|
+
[
|
|
138
|
+
[ops.scope, parent],
|
|
139
|
+
[ops.literal, "index.html"],
|
|
140
|
+
],
|
|
123
141
|
];
|
|
124
142
|
const globals = {};
|
|
125
|
-
assertCodeEqual(optimize(code, { globals }), expected);
|
|
143
|
+
assertCodeEqual(optimize(code, { globals, parent }), expected);
|
|
126
144
|
});
|
|
127
145
|
|
|
128
146
|
test("external reference inside object with matching key", () => {
|
|
@@ -134,6 +152,7 @@ describe("optimize", () => {
|
|
|
134
152
|
[ops.getter, [markers.traverse, [markers.reference, "posts.txt"]]],
|
|
135
153
|
],
|
|
136
154
|
]);
|
|
155
|
+
const parent = {};
|
|
137
156
|
const expected = [
|
|
138
157
|
ops.object,
|
|
139
158
|
[
|
|
@@ -145,7 +164,7 @@ describe("optimize", () => {
|
|
|
145
164
|
{},
|
|
146
165
|
"posts.txt",
|
|
147
166
|
[
|
|
148
|
-
[ops.scope,
|
|
167
|
+
[ops.scope, parent],
|
|
149
168
|
[ops.literal, "posts.txt"],
|
|
150
169
|
],
|
|
151
170
|
],
|
|
@@ -153,7 +172,7 @@ describe("optimize", () => {
|
|
|
153
172
|
],
|
|
154
173
|
];
|
|
155
174
|
const globals = {};
|
|
156
|
-
assertCodeEqual(optimize(code, { globals }), expected);
|
|
175
|
+
assertCodeEqual(optimize(code, { globals, parent }), expected);
|
|
157
176
|
});
|
|
158
177
|
|
|
159
178
|
test("global reference", () => {
|
|
@@ -176,27 +195,37 @@ describe("optimize", () => {
|
|
|
176
195
|
});
|
|
177
196
|
|
|
178
197
|
test("local reference", () => {
|
|
179
|
-
// Compilation of `post` where post is a local
|
|
198
|
+
// Compilation of `post` where post is a local parameter
|
|
180
199
|
const code = createCode([markers.traverse, [markers.reference, "post"]]);
|
|
181
200
|
const globals = { post: {} }; // local should take precedence
|
|
182
|
-
const locals = [["post"]];
|
|
201
|
+
const locals = [{ type: REFERENCE_PARAM, names: ["post"] }];
|
|
183
202
|
const actual = optimize(code, { globals, locals });
|
|
184
|
-
const expected = [
|
|
203
|
+
const expected = [
|
|
204
|
+
[ops.params, 0],
|
|
205
|
+
[ops.literal, "post"],
|
|
206
|
+
];
|
|
185
207
|
assertCodeEqual(actual, expected);
|
|
186
208
|
});
|
|
187
209
|
|
|
188
210
|
test("local reference and property", () => {
|
|
189
|
-
// Compilation of `post.author.name` where `post` is a local
|
|
211
|
+
// Compilation of `post.author.name` where `post` is a local inherited property
|
|
190
212
|
const code = createCode([
|
|
191
213
|
markers.traverse,
|
|
192
214
|
[markers.reference, "post.author.name"],
|
|
193
215
|
]);
|
|
194
216
|
const globals = { post: {} }; // local should take precedence
|
|
195
|
-
const locals = [["post"]];
|
|
217
|
+
const locals = [{ type: REFERENCE_INHERITED, names: ["post"] }];
|
|
196
218
|
const actual = optimize(code, { globals, locals });
|
|
197
219
|
const expected = [
|
|
198
220
|
ops.property,
|
|
199
|
-
[
|
|
221
|
+
[
|
|
222
|
+
ops.property,
|
|
223
|
+
[
|
|
224
|
+
[ops.inherited, 0],
|
|
225
|
+
[ops.literal, "post"],
|
|
226
|
+
],
|
|
227
|
+
"author",
|
|
228
|
+
],
|
|
200
229
|
"name",
|
|
201
230
|
];
|
|
202
231
|
assertCodeEqual(actual, expected);
|
|
@@ -226,18 +255,19 @@ describe("optimize", () => {
|
|
|
226
255
|
[ops.literal, "to/"],
|
|
227
256
|
[ops.literal, "file"],
|
|
228
257
|
]);
|
|
258
|
+
const parent = {};
|
|
229
259
|
const expected = [
|
|
230
260
|
ops.cache,
|
|
231
261
|
{},
|
|
232
262
|
"path/to/file",
|
|
233
263
|
[
|
|
234
|
-
[ops.scope],
|
|
264
|
+
[ops.scope, parent],
|
|
235
265
|
[ops.literal, "path/"],
|
|
236
266
|
[ops.literal, "to/"],
|
|
237
267
|
[ops.literal, "file"],
|
|
238
268
|
],
|
|
239
269
|
];
|
|
240
|
-
assertCodeEqual(optimize(code), expected);
|
|
270
|
+
assertCodeEqual(optimize(code, { parent }), expected);
|
|
241
271
|
});
|
|
242
272
|
|
|
243
273
|
test("implicit external path", () => {
|
|
@@ -248,27 +278,32 @@ describe("optimize", () => {
|
|
|
248
278
|
[ops.literal, "name"],
|
|
249
279
|
]);
|
|
250
280
|
const globals = {};
|
|
281
|
+
const parent = {};
|
|
251
282
|
const expected = [
|
|
252
283
|
ops.cache,
|
|
253
284
|
{},
|
|
254
285
|
"package.json/name",
|
|
255
|
-
[
|
|
286
|
+
[
|
|
287
|
+
[ops.scope, parent],
|
|
288
|
+
[ops.literal, "package.json/"],
|
|
289
|
+
[ops.literal, "name"],
|
|
290
|
+
],
|
|
256
291
|
];
|
|
257
|
-
assertCodeEqual(optimize(code, { globals }), expected);
|
|
292
|
+
assertCodeEqual(optimize(code, { globals, parent }), expected);
|
|
258
293
|
});
|
|
259
294
|
|
|
260
295
|
test("local path", () => {
|
|
261
|
-
// Compilation of `page/title` where page is a local
|
|
296
|
+
// Compilation of `page/title` where page is a local parameter
|
|
262
297
|
const code = createCode([
|
|
263
298
|
markers.traverse,
|
|
264
299
|
[markers.reference, "page/"],
|
|
265
300
|
[ops.literal, "title"],
|
|
266
301
|
]);
|
|
267
302
|
const globals = {};
|
|
268
|
-
const locals = [["page"]];
|
|
303
|
+
const locals = [{ type: REFERENCE_PARAM, names: ["page"] }];
|
|
269
304
|
const actual = optimize(code, { globals, locals });
|
|
270
305
|
const expected = [
|
|
271
|
-
[ops.
|
|
306
|
+
[ops.params, 0],
|
|
272
307
|
[ops.literal, "page/"],
|
|
273
308
|
[ops.literal, "title"],
|
|
274
309
|
];
|
|
@@ -279,7 +314,7 @@ describe("optimize", () => {
|
|
|
279
314
|
|
|
280
315
|
function assertCompile(expression, expected, mode = "shell") {
|
|
281
316
|
const parent = new ObjectTree({});
|
|
282
|
-
const globals =
|
|
317
|
+
const globals = {};
|
|
283
318
|
const fn = compile.expression(expression, { globals, mode, parent });
|
|
284
319
|
const actual = fn.code;
|
|
285
320
|
assertCodeLocations(actual);
|
|
@@ -347,10 +347,10 @@ describe("Origami parser", () => {
|
|
|
347
347
|
[ops.lambda, [], [ops.lambda, [], [ops.literal, 1]]],
|
|
348
348
|
[ops.literal, 0],
|
|
349
349
|
]);
|
|
350
|
-
assertParse("conditionalExpression", "false ?
|
|
350
|
+
assertParse("conditionalExpression", "false ? () => 1 : 0", [
|
|
351
351
|
ops.conditional,
|
|
352
352
|
[markers.traverse, [markers.reference, "false"]],
|
|
353
|
-
[ops.lambda, [], [ops.lambda, [
|
|
353
|
+
[ops.lambda, [], [ops.lambda, [], [ops.literal, 1]]],
|
|
354
354
|
[ops.literal, 0],
|
|
355
355
|
]);
|
|
356
356
|
});
|
|
@@ -1008,9 +1008,9 @@ Body`,
|
|
|
1008
1008
|
"_result",
|
|
1009
1009
|
[
|
|
1010
1010
|
ops.merge,
|
|
1011
|
-
[ops.object, ["a", [ops.getter, [[ops.
|
|
1011
|
+
[ops.object, ["a", [ops.getter, [[ops.inherited, 1], "a"]]]],
|
|
1012
1012
|
[markers.traverse, [markers.reference, "more"]],
|
|
1013
|
-
[ops.object, ["c", [ops.getter, [[ops.
|
|
1013
|
+
[ops.object, ["c", [ops.getter, [[ops.inherited, 1], "c"]]]],
|
|
1014
1014
|
],
|
|
1015
1015
|
],
|
|
1016
1016
|
],
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { ObjectTree } from "@weborigami/async-tree";
|
|
2
1
|
import * as compile from "../../src/compiler/compile.js";
|
|
3
2
|
|
|
4
3
|
export default async function oriEval(source) {
|
|
5
|
-
const
|
|
4
|
+
const globals = {
|
|
6
5
|
false: false,
|
|
7
6
|
NaN: NaN,
|
|
8
7
|
null: null,
|
|
9
8
|
true: true,
|
|
10
9
|
undefined: undefined,
|
|
11
|
-
}
|
|
12
|
-
const compiled = compile.program(source);
|
|
13
|
-
const result = await compiled
|
|
10
|
+
};
|
|
11
|
+
const compiled = compile.program(source, { globals });
|
|
12
|
+
const result = await compiled();
|
|
14
13
|
return result;
|
|
15
14
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import csv_handler from "../../src/handlers/csv_handler.js";
|
|
4
|
+
|
|
5
|
+
describe(".csv handler", () => {
|
|
6
|
+
test("parses CSV text into array of objects", () => {
|
|
7
|
+
const csvText = `name,age,city
|
|
8
|
+
Alice,30,"New York, NY"
|
|
9
|
+
Bob,25,Los Angeles
|
|
10
|
+
"Carol ""CJ""",22,Chicago`;
|
|
11
|
+
const result = csv_handler.unpack(csvText);
|
|
12
|
+
assert.deepStrictEqual(result, [
|
|
13
|
+
{ name: "Alice", age: "30", city: "New York, NY" },
|
|
14
|
+
{ name: "Bob", age: "25", city: "Los Angeles" },
|
|
15
|
+
{ name: 'Carol "CJ"', age: "22", city: "Chicago" },
|
|
16
|
+
]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("handles CRLF line endings", () => {
|
|
20
|
+
const textCRLF = `name,age,city\r\nAlice,30,"New York, NY"\r\nBob,25,Los Angeles\r\n`;
|
|
21
|
+
const expected = [
|
|
22
|
+
{ name: "Alice", age: "30", city: "New York, NY" },
|
|
23
|
+
{ name: "Bob", age: "25", city: "Los Angeles" },
|
|
24
|
+
];
|
|
25
|
+
const result = csv_handler.unpack(textCRLF);
|
|
26
|
+
assert.deepStrictEqual(result, expected);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("throws an error for unmatched quotes", () => {
|
|
30
|
+
// Provide a CSV string with an unmatched quote.
|
|
31
|
+
const badCSV = `name,age\r\nAlice,30\r\nBob,"25\r\n`;
|
|
32
|
+
assert.throws(() => {
|
|
33
|
+
csv_handler.unpack(badCSV);
|
|
34
|
+
}, /unmatched quote/);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default "This is a string.";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { describe, test } from "node:test";
|
|
4
|
+
import jpeg_handler from "../../src/handlers/jpeg_handler.js";
|
|
5
|
+
|
|
6
|
+
describe(".jpeg handler", () => {
|
|
7
|
+
test("loads Exif metadata", async () => {
|
|
8
|
+
const fixturePath = new URL("fixtures/exif.jpeg", import.meta.url);
|
|
9
|
+
const image = await fs.readFile(fixturePath);
|
|
10
|
+
const data = await jpeg_handler.unpack(image);
|
|
11
|
+
assert.equal(data.exif.LensMake, "Apple");
|
|
12
|
+
assert.equal(
|
|
13
|
+
data.exif.ModifyDate.toISOString(),
|
|
14
|
+
"2023-11-13T18:44:11.000Z"
|
|
15
|
+
);
|
|
16
|
+
assert.equal(data.exif.Orientation, 1);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { FileTree } from "@weborigami/async-tree";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { describe, test } from "node:test";
|
|
4
|
+
import js_handler from "../../src/handlers/js_handler.js";
|
|
5
|
+
import ImportModulesMixin from "../../src/runtime/ImportModulesMixin.js";
|
|
6
|
+
|
|
7
|
+
const fixturesUrl = new URL("fixtures", import.meta.url);
|
|
8
|
+
const fixturesTree = new (ImportModulesMixin(FileTree))(fixturesUrl);
|
|
9
|
+
|
|
10
|
+
describe(".js handler", () => {
|
|
11
|
+
test("loads .js file that exports a string", async () => {
|
|
12
|
+
const buffer = await fixturesTree.get("string.js");
|
|
13
|
+
const text = await js_handler.unpack(buffer, {
|
|
14
|
+
key: "string.js",
|
|
15
|
+
parent: fixturesTree,
|
|
16
|
+
});
|
|
17
|
+
assert.equal(text, "This is a string.");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("loads .js file that exports a function", async () => {
|
|
21
|
+
const buffer = await fixturesTree.get("list.js");
|
|
22
|
+
const list = await js_handler.unpack(buffer, {
|
|
23
|
+
key: "list.js",
|
|
24
|
+
parent: fixturesTree,
|
|
25
|
+
});
|
|
26
|
+
assert.equal(await list("a", "b", "c"), "a,b,c");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("loads .js file that exports an object", async () => {
|
|
30
|
+
const buffer = await fixturesTree.get("obj.js");
|
|
31
|
+
const obj = await js_handler.unpack(buffer, {
|
|
32
|
+
key: "obj.js",
|
|
33
|
+
parent: fixturesTree,
|
|
34
|
+
});
|
|
35
|
+
assert.deepEqual(obj, { a: 1 });
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("returns multiple exports as an object", async () => {
|
|
39
|
+
const buffer = await fixturesTree.get("multiple.js");
|
|
40
|
+
const obj = await js_handler.unpack(buffer, {
|
|
41
|
+
key: "multiple.js",
|
|
42
|
+
parent: fixturesTree,
|
|
43
|
+
});
|
|
44
|
+
assert.deepEqual(obj, { n: 1, s: "string" });
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import json_handler from "../../src/handlers/json_handler.js";
|
|
4
|
+
|
|
5
|
+
describe(".json handler", () => {
|
|
6
|
+
test("loads input as a JSON file", async () => {
|
|
7
|
+
const text = `{ "a": 1, "b": 2 }`;
|
|
8
|
+
const obj = await json_handler.unpack(text);
|
|
9
|
+
assert.deepEqual(obj, {
|
|
10
|
+
a: 1,
|
|
11
|
+
b: 2,
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { ObjectTree, Tree } from "@weborigami/async-tree";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { describe, test } from "node:test";
|
|
4
|
+
import ori_handler from "../../src/handlers/ori_handler.js";
|
|
5
|
+
import OrigamiFiles from "../../src/runtime/OrigamiFiles.js";
|
|
6
|
+
|
|
7
|
+
const fixturesUrl = new URL("fixtures", import.meta.url);
|
|
8
|
+
const fixtures = new OrigamiFiles(fixturesUrl);
|
|
9
|
+
|
|
10
|
+
describe(".ori handler", async () => {
|
|
11
|
+
test("loads a string expression", async () => {
|
|
12
|
+
const source = `"Hello"`;
|
|
13
|
+
const text = await ori_handler.unpack(source);
|
|
14
|
+
assert.equal(text, "Hello");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("loads a tree expression", async () => {
|
|
18
|
+
const parent = new ObjectTree({
|
|
19
|
+
name: "world",
|
|
20
|
+
});
|
|
21
|
+
const source = `{
|
|
22
|
+
message = \`Hello, \${name}!\`
|
|
23
|
+
}`;
|
|
24
|
+
const tree = await ori_handler.unpack(source, { parent });
|
|
25
|
+
assert.deepEqual(await Tree.plain(tree), {
|
|
26
|
+
message: "Hello, world!",
|
|
27
|
+
});
|
|
28
|
+
assert.equal(await tree.message, "Hello, world!");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("loads a tree with a nested tree", async () => {
|
|
32
|
+
const source = `{
|
|
33
|
+
name = "world",
|
|
34
|
+
public = {
|
|
35
|
+
message = \`Hello, \${name}!\`
|
|
36
|
+
}
|
|
37
|
+
}`;
|
|
38
|
+
const tree = await ori_handler.unpack(source);
|
|
39
|
+
assert.deepEqual(
|
|
40
|
+
await Tree.traverse(tree, "public", "message"),
|
|
41
|
+
"Hello, world!"
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("loads an object containing an object shorthand", async () => {
|
|
46
|
+
const assets = new ObjectTree({});
|
|
47
|
+
const parent = new ObjectTree({ assets });
|
|
48
|
+
const source = `{ assets }`;
|
|
49
|
+
const object = await ori_handler.unpack(source, { parent });
|
|
50
|
+
assert.equal(object.assets, assets);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("loads a template literal", async () => {
|
|
54
|
+
const scope = new ObjectTree({
|
|
55
|
+
name: "Alice",
|
|
56
|
+
});
|
|
57
|
+
const source = `\`Hello, \${name}!\``;
|
|
58
|
+
const unpackedText = await ori_handler.unpack(source, {
|
|
59
|
+
parent: scope,
|
|
60
|
+
});
|
|
61
|
+
assert.deepEqual(unpackedText, "Hello, Alice!");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("loads a template lambda that reads from parent scope", async () => {
|
|
65
|
+
const parent = new ObjectTree({
|
|
66
|
+
name: "Alice",
|
|
67
|
+
});
|
|
68
|
+
const source = `() => \`Hello, \${name}!\``;
|
|
69
|
+
const templateFn = await ori_handler.unpack(source, { parent });
|
|
70
|
+
const value = await templateFn();
|
|
71
|
+
assert.equal(value, "Hello, Alice!");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("loads a template lambda that accepts input", async () => {
|
|
75
|
+
const source = `(_) => \`Hello, \${ _.name }!\``;
|
|
76
|
+
const templateFn = await ori_handler.unpack(source);
|
|
77
|
+
const value = await templateFn({ name: "Alice" });
|
|
78
|
+
assert.deepEqual(value, "Hello, Alice!");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("loads a tree that includes a template", async () => {
|
|
82
|
+
const source = await fixtures.get("site.ori");
|
|
83
|
+
const tree = await ori_handler.unpack(source);
|
|
84
|
+
const indexHtml = await tree["index.html"];
|
|
85
|
+
assert.equal(indexHtml, "Hello, world!");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ObjectTree } from "@weborigami/async-tree";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { describe, test } from "node:test";
|
|
4
|
+
import oridocument_handler from "../../src/handlers/oridocument_handler.js";
|
|
5
|
+
|
|
6
|
+
describe("Origami document handler", () => {
|
|
7
|
+
test("unpacks text with Origami expressions", async () => {
|
|
8
|
+
const parent = new ObjectTree({
|
|
9
|
+
name: "world",
|
|
10
|
+
});
|
|
11
|
+
const text = "Hello, ${ name }!";
|
|
12
|
+
const fn = await oridocument_handler.unpack(text, {
|
|
13
|
+
key: "test.ori.txt",
|
|
14
|
+
parent,
|
|
15
|
+
});
|
|
16
|
+
const result = await fn();
|
|
17
|
+
assert.equal(result, "Hello, world!");
|
|
18
|
+
|
|
19
|
+
// Test sidecar keyFn
|
|
20
|
+
assert.equal(fn.key(null, "data.json"), "data.txt");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("Argument to template document available as underscore", async () => {
|
|
24
|
+
const text = "<h1>${ _ }</h1>";
|
|
25
|
+
const fn = await oridocument_handler.unpack(text);
|
|
26
|
+
const result = await fn("Home");
|
|
27
|
+
assert.equal(result, "<h1>Home</h1>");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("YAML front matter is returned with _body", async () => {
|
|
31
|
+
const parent = new ObjectTree({
|
|
32
|
+
message: "Hello",
|
|
33
|
+
});
|
|
34
|
+
const text = `---
|
|
35
|
+
name: world
|
|
36
|
+
---
|
|
37
|
+
\${ message }, \${ name }!`;
|
|
38
|
+
const result = await oridocument_handler.unpack(text, { parent });
|
|
39
|
+
assert.deepEqual(result.name, "world");
|
|
40
|
+
assert.equal(result._body, "Hello, world!");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("unpacks a document with Origami front matter", async () => {
|
|
44
|
+
const text = `---
|
|
45
|
+
{
|
|
46
|
+
sum: 1 + 1
|
|
47
|
+
_body: _template()
|
|
48
|
+
}
|
|
49
|
+
---
|
|
50
|
+
Body text`;
|
|
51
|
+
const result = await oridocument_handler.unpack(text);
|
|
52
|
+
assert.deepEqual(result, {
|
|
53
|
+
sum: 2,
|
|
54
|
+
_body: "Body text",
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("Origami front matter can refer to _template as a macro", async () => {
|
|
59
|
+
const text = `---
|
|
60
|
+
(name) => _template()
|
|
61
|
+
---
|
|
62
|
+
Hello, \${ name }!
|
|
63
|
+
`;
|
|
64
|
+
const fn = await oridocument_handler.unpack(text);
|
|
65
|
+
const result = await fn("world");
|
|
66
|
+
assert.equal(result, "Hello, world!\n");
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import txt_handler from "../../src/handlers/txt_handler.js";
|
|
4
|
+
|
|
5
|
+
describe("text handler", () => {
|
|
6
|
+
test("packs an object as YAML with front matter", async () => {
|
|
7
|
+
const object = {
|
|
8
|
+
_body: "Body text",
|
|
9
|
+
a: 1,
|
|
10
|
+
};
|
|
11
|
+
const packed = await txt_handler.pack(object);
|
|
12
|
+
assert.equal(packed, "---\na: 1\n---\nBody text");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("unpacks text without data", async () => {
|
|
16
|
+
const text = "Body text";
|
|
17
|
+
const result = await txt_handler.unpack(text);
|
|
18
|
+
assert.equal(result, text);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("unpacks a document with YAML/JSON front matter", async () => {
|
|
22
|
+
const text = "---\na: 1\n---\nBody text";
|
|
23
|
+
const document = await txt_handler.unpack(text);
|
|
24
|
+
assert.deepEqual(document, {
|
|
25
|
+
a: 1,
|
|
26
|
+
_body: "Body text",
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("unpacks a document with Origami front matter", async () => {
|
|
31
|
+
const text = `---
|
|
32
|
+
{ sum: 1 + 1 }
|
|
33
|
+
---
|
|
34
|
+
Body text`;
|
|
35
|
+
const document = await txt_handler.unpack(text);
|
|
36
|
+
assert.deepEqual(document, {
|
|
37
|
+
sum: 2,
|
|
38
|
+
_body: "Body text",
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FileTree } from "@weborigami/async-tree";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { describe, test } from "node:test";
|
|
4
|
+
import wasm_handler from "../../src/handlers/wasm_handler.js";
|
|
5
|
+
import ImportModulesMixin from "../../src/runtime/ImportModulesMixin.js";
|
|
6
|
+
|
|
7
|
+
const fixturesUrl = new URL("fixtures", import.meta.url);
|
|
8
|
+
const fixturesTree = new (ImportModulesMixin(FileTree))(fixturesUrl);
|
|
9
|
+
|
|
10
|
+
describe(".wasm handler", () => {
|
|
11
|
+
test("loads .wasm file that exports a function", async () => {
|
|
12
|
+
const buffer = await fixturesTree.get("add.wasm");
|
|
13
|
+
const { add } = await wasm_handler.unpack(buffer, {
|
|
14
|
+
key: "add.wasm",
|
|
15
|
+
parent: fixturesTree,
|
|
16
|
+
});
|
|
17
|
+
const sum = add(1, 2);
|
|
18
|
+
assert.strictEqual(sum, 3);
|
|
19
|
+
});
|
|
20
|
+
});
|