@weborigami/origami 0.0.59 → 0.0.60
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/exports/exports.js +2 -6
- package/package.json +4 -4
- package/src/builtins/@arrowsMap.js +4 -5
- package/src/builtins/@breakpoint.js +12 -0
- package/src/builtins/@cache.js +3 -6
- package/src/builtins/@concat.js +3 -4
- package/src/builtins/@config.js +3 -12
- package/src/builtins/@constructor.js +3 -7
- package/src/builtins/@copy.js +2 -2
- package/src/builtins/@crawl.js +4 -6
- package/src/builtins/@debug.js +5 -6
- package/src/builtins/@deepMap.js +2 -2
- package/src/builtins/@deepMapFn.js +2 -2
- package/src/builtins/@deepMerge.js +3 -18
- package/src/builtins/@deepReverse.js +1 -3
- package/src/builtins/@deepTakeFn.js +5 -6
- package/src/builtins/@defineds.js +4 -7
- package/src/builtins/@document.js +2 -2
- package/src/builtins/@exceptions.js +1 -5
- package/src/builtins/@explore.js +15 -14
- package/src/builtins/@files.js +4 -6
- package/src/builtins/@filter.js +3 -6
- package/src/builtins/@fnTree.js +8 -22
- package/src/builtins/@globs.js +3 -6
- package/src/builtins/@groupFn.js +7 -8
- package/src/builtins/@help.js +2 -2
- package/src/builtins/@http.js +2 -2
- package/src/builtins/@https.js +2 -2
- package/src/builtins/@if.js +2 -2
- package/src/builtins/@image/format.js +2 -2
- package/src/builtins/@image/formatFn.js +6 -3
- package/src/builtins/@image/resize.js +2 -2
- package/src/builtins/@image/resizeFn.js +6 -3
- package/src/builtins/@inherited.js +2 -2
- package/src/builtins/@inline.js +5 -9
- package/src/builtins/@inners.js +0 -1
- package/src/builtins/@invoke.js +4 -7
- package/src/builtins/@json.js +3 -3
- package/src/builtins/@map.js +2 -2
- package/src/builtins/@mapFn.js +9 -10
- package/src/builtins/@match.js +17 -16
- package/src/builtins/@mdHtml.js +4 -1
- package/src/builtins/@merge.js +3 -18
- package/src/builtins/@once.js +2 -2
- package/src/builtins/@ori.js +6 -6
- package/src/builtins/@pack.js +2 -2
- package/src/builtins/@package.js +4 -8
- package/src/builtins/@paginateFn.js +1 -6
- package/src/builtins/@perf.js +2 -2
- package/src/builtins/@project.js +31 -22
- package/src/builtins/@reverse.js +1 -3
- package/src/builtins/@rss.js +2 -2
- package/src/builtins/@serve.js +2 -2
- package/src/builtins/@sitemap.js +4 -1
- package/src/builtins/@sortFn.js +6 -7
- package/src/builtins/@string.js +2 -2
- package/src/builtins/@takeFn.js +5 -6
- package/src/builtins/@treeHttp.js +2 -2
- package/src/builtins/@treeHttps.js +2 -2
- package/src/builtins/@unpack.js +2 -2
- package/src/builtins/@watch.js +5 -12
- package/src/builtins/@yaml.js +3 -3
- package/src/builtins/ori_handler.js +3 -3
- package/src/builtins/~.js +3 -3
- package/src/cli/cli.js +6 -19
- package/src/common/ConstantTree.js +1 -0
- package/src/common/ExplorableSiteTransform.js +9 -12
- package/src/common/documentObject.js +2 -2
- package/src/common/processUnpackedContent.js +12 -18
- package/src/misc/OriCommandTransform.js +1 -9
- package/src/misc/assertTreeIsDefined.d.ts +1 -0
- package/src/misc/assertTreeIsDefined.js +7 -0
- package/src/misc/getTreeArgument.js +11 -12
- package/src/server/server.js +3 -10
- package/src/builtins/@scope/extend.js +0 -22
- package/src/builtins/@scope/get.js +0 -25
- package/src/builtins/@scope/invoke.js +0 -22
- package/src/builtins/@scope/set.js +0 -25
- package/src/common/addValueKeyToScope.js +0 -23
- package/src/misc/assertScopeIsDefined.js +0 -7
package/src/builtins/@project.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { merge } from "@weborigami/async-tree";
|
|
3
|
+
import { OrigamiFiles } from "@weborigami/language";
|
|
4
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
4
5
|
import builtins from "./@builtins.js";
|
|
5
6
|
import fileTypeOrigami from "./ori_handler.js";
|
|
6
7
|
|
|
@@ -22,43 +23,48 @@ const configFileName = "config.ori";
|
|
|
22
23
|
* @param {any} [key]
|
|
23
24
|
*/
|
|
24
25
|
export default async function project(key) {
|
|
25
|
-
|
|
26
|
+
assertTreeIsDefined(this, "project");
|
|
26
27
|
|
|
27
28
|
const dirname = process.cwd();
|
|
28
29
|
const currentTree = new OrigamiFiles(dirname);
|
|
30
|
+
currentTree.parent = builtins;
|
|
29
31
|
|
|
30
32
|
// Search up the tree for the configuration file or package.json to determine
|
|
31
33
|
// the project root.
|
|
32
|
-
|
|
34
|
+
const configContainer =
|
|
33
35
|
(await findAncestorFile(currentTree, configFileName)) ??
|
|
34
36
|
(await findAncestorFile(currentTree, "package.json"));
|
|
35
37
|
|
|
36
|
-
let
|
|
37
|
-
if (
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
let projectRoot;
|
|
39
|
+
if (!configContainer) {
|
|
40
|
+
// No configuration file or package.json found; use the current directory.
|
|
41
|
+
projectRoot = currentTree;
|
|
42
|
+
} else {
|
|
43
|
+
// Load the configuration file if one exists.
|
|
44
|
+
const buffer = await configContainer.get(configFileName);
|
|
45
|
+
if (!buffer) {
|
|
46
|
+
// Project root defined by package.json
|
|
47
|
+
projectRoot = configContainer;
|
|
48
|
+
} else {
|
|
49
|
+
// Load Origami configuration file
|
|
50
|
+
const configTree = await fileTypeOrigami.unpack(buffer, {
|
|
44
51
|
key: configFileName,
|
|
45
|
-
parent:
|
|
52
|
+
parent: configContainer,
|
|
46
53
|
});
|
|
47
|
-
if (!
|
|
48
|
-
const configPath = /** @type {any} */ (
|
|
54
|
+
if (!configTree) {
|
|
55
|
+
const configPath = /** @type {any} */ (configContainer).path;
|
|
49
56
|
throw new Error(
|
|
50
57
|
`Couldn't load the Origami configuration in ${configPath}/${configFileName}`
|
|
51
58
|
);
|
|
52
59
|
}
|
|
60
|
+
projectRoot = merge(configTree, configContainer);
|
|
61
|
+
// HACK so cli.js can get a path
|
|
62
|
+
/** @type {any} */ (projectRoot).path = configContainer.path;
|
|
63
|
+
projectRoot.parent = builtins;
|
|
53
64
|
}
|
|
54
|
-
} else {
|
|
55
|
-
rootTree = currentTree;
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
|
|
59
|
-
const scope = new Scope(config, builtins);
|
|
60
|
-
const result = Scope.treeWithScope(rootTree, scope);
|
|
61
|
-
return key === undefined ? result : result.get(key);
|
|
67
|
+
return key === undefined ? projectRoot : projectRoot.get(key);
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
// Return the first ancestor of the given tree that contains a file with the
|
|
@@ -68,7 +74,10 @@ async function findAncestorFile(start, fileName) {
|
|
|
68
74
|
while (current) {
|
|
69
75
|
const value = await current.get(fileName);
|
|
70
76
|
if (value) {
|
|
71
|
-
// Found the desired file; its container is the project root.
|
|
77
|
+
// Found the desired file; its container is the project root. Set the
|
|
78
|
+
// parent to the builtins; in the context of this project, there's nothing
|
|
79
|
+
// higher up.
|
|
80
|
+
current.parent = builtins;
|
|
72
81
|
return current;
|
|
73
82
|
}
|
|
74
83
|
// Not found; try the parent.
|
package/src/builtins/@reverse.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { reverse } from "@weborigami/async-tree";
|
|
2
|
-
import { Scope } from "@weborigami/language";
|
|
3
2
|
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
@@ -13,8 +12,7 @@ import getTreeArgument from "../misc/getTreeArgument.js";
|
|
|
13
12
|
*/
|
|
14
13
|
export default async function reverseBuiltin(treelike) {
|
|
15
14
|
const tree = await getTreeArgument(this, arguments, treelike, "@reverse");
|
|
16
|
-
|
|
17
|
-
reversed = Scope.treeWithScope(reversed, this);
|
|
15
|
+
const reversed = reverse(tree);
|
|
18
16
|
return reversed;
|
|
19
17
|
}
|
|
20
18
|
|
package/src/builtins/@rss.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tree } from "@weborigami/async-tree";
|
|
2
|
-
import
|
|
2
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
@@ -8,7 +8,7 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
8
8
|
* @param {Treelike} jsonFeedTree
|
|
9
9
|
*/
|
|
10
10
|
export default async function rss(jsonFeedTree) {
|
|
11
|
-
|
|
11
|
+
assertTreeIsDefined(this, "rss");
|
|
12
12
|
const jsonFeed = await Tree.plain(jsonFeedTree);
|
|
13
13
|
const { description, home_page_url, items, feed_url, title } = jsonFeed;
|
|
14
14
|
|
package/src/builtins/@serve.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createServer } from "node:net";
|
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import ExplorableSiteTransform from "../common/ExplorableSiteTransform.js";
|
|
6
6
|
import { isTransformApplied, transformObject } from "../common/utilities.js";
|
|
7
|
-
import
|
|
7
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
8
8
|
import { requestListener } from "../server/server.js";
|
|
9
9
|
import debug from "./@debug.js";
|
|
10
10
|
import watch from "./@watch.js";
|
|
@@ -22,7 +22,7 @@ const defaultPort = 5000;
|
|
|
22
22
|
* @this {AsyncTree|null}
|
|
23
23
|
*/
|
|
24
24
|
export default async function serve(treelike, port) {
|
|
25
|
-
|
|
25
|
+
assertTreeIsDefined(this, "serve");
|
|
26
26
|
let tree;
|
|
27
27
|
if (treelike) {
|
|
28
28
|
tree = Tree.from(treelike);
|
package/src/builtins/@sitemap.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
1
2
|
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
2
3
|
import builtins from "./@builtins.js";
|
|
3
4
|
import paths from "./@paths.js";
|
|
@@ -22,6 +23,7 @@ const templateText = `(urls) => \`<?xml version="1.0" encoding="UTF-8"?>
|
|
|
22
23
|
* @param {string} [baseHref ]
|
|
23
24
|
*/
|
|
24
25
|
export default async function sitemap(treelike, baseHref = "") {
|
|
26
|
+
assertTreeIsDefined(this, "sitemap");
|
|
25
27
|
const tree = await getTreeArgument(this, arguments, treelike, "@sitemap");
|
|
26
28
|
|
|
27
29
|
// We're only interested in keys that end in .html or with no extension.
|
|
@@ -49,7 +51,8 @@ export default async function sitemap(treelike, baseHref = "") {
|
|
|
49
51
|
.map((path) => (path.endsWith("index.html") ? path.slice(0, -10) : path));
|
|
50
52
|
|
|
51
53
|
const templateFn = await fileTypeOrigami.unpack(templateText);
|
|
52
|
-
const
|
|
54
|
+
const target = this ?? builtins;
|
|
55
|
+
const templateResult = await templateFn.call(target, htmlPaths);
|
|
53
56
|
return String(templateResult);
|
|
54
57
|
}
|
|
55
58
|
|
package/src/builtins/@sortFn.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { sortFn } from "@weborigami/async-tree";
|
|
2
|
-
import { Scope } from "@weborigami/language";
|
|
3
2
|
import { toFunction } from "../common/utilities.js";
|
|
4
|
-
import
|
|
3
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Return a transform function that sorts a tree's keys using a comparison
|
|
@@ -23,8 +22,8 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
23
22
|
* @param {ValueKeyFn|SortOptions} [options]
|
|
24
23
|
*/
|
|
25
24
|
export default function sortFnBuiltin(options) {
|
|
26
|
-
|
|
27
|
-
const
|
|
25
|
+
assertTreeIsDefined(this, "sortFn");
|
|
26
|
+
const parent = this;
|
|
28
27
|
|
|
29
28
|
if (typeof options === "function") {
|
|
30
29
|
// Take the function as the `sortKey` option
|
|
@@ -37,7 +36,7 @@ export default function sortFnBuiltin(options) {
|
|
|
37
36
|
const originalSortKey = toFunction(options?.sortKey);
|
|
38
37
|
extendedSortKeyFn = async (key, tree) => {
|
|
39
38
|
const value = await tree.get(key);
|
|
40
|
-
const sortKey = await originalSortKey.call(
|
|
39
|
+
const sortKey = await originalSortKey.call(parent, value, key);
|
|
41
40
|
return sortKey;
|
|
42
41
|
};
|
|
43
42
|
}
|
|
@@ -49,8 +48,8 @@ export default function sortFnBuiltin(options) {
|
|
|
49
48
|
|
|
50
49
|
return (treelike) => {
|
|
51
50
|
const sorted = fn(treelike);
|
|
52
|
-
|
|
53
|
-
return
|
|
51
|
+
sorted.parent = parent;
|
|
52
|
+
return sorted;
|
|
54
53
|
};
|
|
55
54
|
}
|
|
56
55
|
|
package/src/builtins/@string.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toString } from "../common/utilities.js";
|
|
2
|
-
import
|
|
2
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Convert an object to a string.
|
|
@@ -9,6 +9,6 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
9
9
|
* @param {any} object
|
|
10
10
|
*/
|
|
11
11
|
export default function stringBuiltin(object) {
|
|
12
|
-
|
|
12
|
+
assertTreeIsDefined(this, "string");
|
|
13
13
|
return toString(object);
|
|
14
14
|
}
|
package/src/builtins/@takeFn.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { takeFn } from "@weborigami/async-tree";
|
|
2
|
-
import
|
|
3
|
-
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
2
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Limit the number of keys to the indicated count.
|
|
@@ -11,11 +10,11 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
11
10
|
* @param {number} count
|
|
12
11
|
*/
|
|
13
12
|
export default function takeFnBuiltin(count) {
|
|
14
|
-
|
|
15
|
-
const
|
|
13
|
+
assertTreeIsDefined(this, "takeFn");
|
|
14
|
+
const parent = this;
|
|
16
15
|
return (treelike) => {
|
|
17
16
|
const taken = takeFn(count)(treelike);
|
|
18
|
-
|
|
19
|
-
return
|
|
17
|
+
taken.parent = parent;
|
|
18
|
+
return taken;
|
|
20
19
|
};
|
|
21
20
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ops } from "@weborigami/language";
|
|
2
|
-
import
|
|
2
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
@@ -11,7 +11,7 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
11
11
|
* @param {...string|Symbol} keys
|
|
12
12
|
*/
|
|
13
13
|
export default function treeHttp(host, ...keys) {
|
|
14
|
-
|
|
14
|
+
assertTreeIsDefined(this, "treeHttp");
|
|
15
15
|
return ops.treeHttp.call(this, host, ...keys);
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ops } from "@weborigami/language";
|
|
2
|
-
import
|
|
2
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
@@ -11,7 +11,7 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
11
11
|
* @param {...string|Symbol} keys
|
|
12
12
|
*/
|
|
13
13
|
export default function treeHttps(host, ...keys) {
|
|
14
|
-
|
|
14
|
+
assertTreeIsDefined(this, "treeHttps");
|
|
15
15
|
return ops.treeHttps.call(this, host, ...keys);
|
|
16
16
|
}
|
|
17
17
|
|
package/src/builtins/@unpack.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Unpack a packed format like a Uint8Array or ArrayBuffer to a usable form like
|
|
@@ -9,6 +9,6 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
9
9
|
* @param {any} obj
|
|
10
10
|
*/
|
|
11
11
|
export default function unpack(obj) {
|
|
12
|
-
|
|
12
|
+
assertTreeIsDefined(this, "unpack");
|
|
13
13
|
return obj?.unpack?.();
|
|
14
14
|
}
|
package/src/builtins/@watch.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Tree } from "@weborigami/async-tree";
|
|
2
|
-
import { Scope } from "@weborigami/language";
|
|
3
2
|
import ConstantTree from "../common/ConstantTree.js";
|
|
4
3
|
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
5
4
|
|
|
@@ -21,16 +20,12 @@ export default async function watch(treelike, fn) {
|
|
|
21
20
|
// Watch the indicated tree.
|
|
22
21
|
await /** @type {any} */ (container).watch?.();
|
|
23
22
|
|
|
24
|
-
// // Watch trees in scope.
|
|
25
|
-
// const scope = /** @type {any} */ (container).scope;
|
|
26
|
-
// await scope?.watch?.();
|
|
27
|
-
|
|
28
23
|
if (fn === undefined) {
|
|
29
24
|
return container;
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
// The caller supplied a function to reevaluate whenever the tree changes.
|
|
33
|
-
let tree = await evaluateTree(container
|
|
28
|
+
let tree = await evaluateTree(container, fn);
|
|
34
29
|
|
|
35
30
|
// We want to return a stable reference to the tree, so we'll use a prototype
|
|
36
31
|
// chain that will always point to the latest tree. We'll extend the tree's
|
|
@@ -40,19 +35,19 @@ export default async function watch(treelike, fn) {
|
|
|
40
35
|
|
|
41
36
|
// Reevaluate the function whenever the tree changes.
|
|
42
37
|
container.addEventListener?.("change", async () => {
|
|
43
|
-
const tree = await evaluateTree(container
|
|
38
|
+
const tree = await evaluateTree(container, fn);
|
|
44
39
|
updateIndirectPointer(handle, tree);
|
|
45
40
|
});
|
|
46
41
|
|
|
47
42
|
return handle;
|
|
48
43
|
}
|
|
49
44
|
|
|
50
|
-
async function evaluateTree(
|
|
45
|
+
async function evaluateTree(container, fn) {
|
|
51
46
|
let tree;
|
|
52
47
|
let message;
|
|
53
48
|
let result;
|
|
54
49
|
try {
|
|
55
|
-
result = await fn.call(
|
|
50
|
+
result = await fn.call(container);
|
|
56
51
|
} catch (error) {
|
|
57
52
|
message = messageForError(error);
|
|
58
53
|
}
|
|
@@ -65,9 +60,7 @@ async function evaluateTree(scope, fn) {
|
|
|
65
60
|
}
|
|
66
61
|
console.warn(message);
|
|
67
62
|
tree = new ConstantTree(message);
|
|
68
|
-
|
|
69
|
-
tree = Scope.treeWithScope(tree, scope);
|
|
70
|
-
}
|
|
63
|
+
tree.parent = container;
|
|
71
64
|
return tree;
|
|
72
65
|
}
|
|
73
66
|
|
package/src/builtins/@yaml.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
2
|
import { isUnpackable, toPlainValue } from "@weborigami/async-tree";
|
|
3
3
|
import YAML from "yaml";
|
|
4
|
-
import
|
|
4
|
+
import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Render the object as text in YAML format.
|
|
@@ -10,14 +10,14 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
10
10
|
* @param {any} [obj]
|
|
11
11
|
*/
|
|
12
12
|
export default async function toYaml(obj) {
|
|
13
|
-
|
|
13
|
+
assertTreeIsDefined(this, "yaml");
|
|
14
14
|
// A fragment of the logic from getTreeArgument.js
|
|
15
15
|
if (arguments.length > 0 && obj === undefined) {
|
|
16
16
|
throw new Error(
|
|
17
17
|
"An Origami function was called with an initial argument, but its value is undefined."
|
|
18
18
|
);
|
|
19
19
|
}
|
|
20
|
-
obj = obj ??
|
|
20
|
+
obj = obj ?? this;
|
|
21
21
|
if (obj === undefined) {
|
|
22
22
|
return undefined;
|
|
23
23
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { symbols } from "@weborigami/async-tree";
|
|
2
|
-
import {
|
|
2
|
+
import { compile } from "@weborigami/language";
|
|
3
3
|
import processUnpackedContent from "../common/processUnpackedContent.js";
|
|
4
4
|
import * as utilities from "../common/utilities.js";
|
|
5
5
|
import builtins from "./@builtins.js";
|
|
@@ -40,8 +40,8 @@ export default {
|
|
|
40
40
|
// Compile the source code as an Origami expression and evaluate it.
|
|
41
41
|
const compiler = options.compiler ?? compile.expression;
|
|
42
42
|
const fn = compiler(source);
|
|
43
|
-
const
|
|
44
|
-
let content = await fn.call(
|
|
43
|
+
const target = parent ?? builtins;
|
|
44
|
+
let content = await fn.call(target);
|
|
45
45
|
|
|
46
46
|
return processUnpackedContent(content, parent, attachedData);
|
|
47
47
|
},
|
package/src/builtins/~.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { OrigamiFiles
|
|
1
|
+
import { OrigamiFiles } from "@weborigami/language";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import builtins from "./@builtins.js";
|
|
4
4
|
|
|
5
5
|
/** @type {import("@weborigami/types").AsyncTree} */
|
|
6
|
-
|
|
7
|
-
tree =
|
|
6
|
+
const tree = new OrigamiFiles(os.homedir());
|
|
7
|
+
tree.parent = builtins;
|
|
8
8
|
|
|
9
9
|
export default tree;
|
package/src/cli/cli.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { Tree } from "@weborigami/async-tree";
|
|
4
|
+
import { formatError } from "@weborigami/language";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import process, { stdout } from "node:process";
|
|
7
7
|
import ori from "../builtins/@ori.js";
|
|
8
8
|
import project from "../builtins/@project.js";
|
|
9
|
-
import { keySymbol } from "../common/utilities.js";
|
|
10
9
|
import showUsage from "./showUsage.js";
|
|
11
10
|
|
|
12
11
|
const TypedArray = Object.getPrototypeOf(Uint8Array);
|
|
@@ -17,32 +16,20 @@ async function main(...args) {
|
|
|
17
16
|
// Find the project root.
|
|
18
17
|
const projectTree = await project.call(null);
|
|
19
18
|
|
|
20
|
-
// HACK: get the configuration via the project.
|
|
21
|
-
const config = new Scope(...projectTree.scope.trees.slice(1));
|
|
22
|
-
|
|
23
19
|
// If no arguments were passed, show usage.
|
|
24
20
|
if (!expression) {
|
|
21
|
+
// HACK: the config is the parent of the project tree.
|
|
22
|
+
const config = projectTree.parent;
|
|
25
23
|
await showUsage(config);
|
|
26
24
|
return;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
// Splice ambients tree into project tree scope.
|
|
30
|
-
const ambients = new ObjectTree({});
|
|
31
|
-
ambients[keySymbol] = "Origami CLI";
|
|
32
|
-
let tree = Scope.treeWithScope(projectTree, new Scope(ambients, config));
|
|
33
|
-
|
|
34
27
|
// Traverse from the project root to the current directory.
|
|
35
28
|
const currentDirectory = process.cwd();
|
|
36
29
|
const relative = path.relative(projectTree.path, currentDirectory);
|
|
37
|
-
|
|
38
|
-
tree = await Tree.traversePath(tree, relative);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Add ambient property for the current tree.
|
|
42
|
-
await ambients.set("@current", tree);
|
|
30
|
+
const tree = await Tree.traversePath(projectTree, relative);
|
|
43
31
|
|
|
44
|
-
const
|
|
45
|
-
const result = await ori.call(scope, expression);
|
|
32
|
+
const result = await ori.call(tree, expression);
|
|
46
33
|
if (result !== undefined) {
|
|
47
34
|
const output =
|
|
48
35
|
result instanceof ArrayBuffer
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Tree, keysJson } from "@weborigami/async-tree";
|
|
2
|
-
import { Scope } from "@weborigami/language";
|
|
3
2
|
import index from "../builtins/@index.js";
|
|
4
3
|
import { isTransformApplied, transformObject } from "../common/utilities.js";
|
|
5
4
|
|
|
@@ -33,16 +32,14 @@ export default function ExplorableSiteTransform(Base) {
|
|
|
33
32
|
|
|
34
33
|
// Ask the tree if it has the key.
|
|
35
34
|
let value = await super.get(key);
|
|
36
|
-
const scope = Scope.getScope(this);
|
|
37
35
|
|
|
38
36
|
if (value === undefined) {
|
|
39
37
|
// The tree doesn't have the key; try the defaults.
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
38
|
+
if (key === "index.html") {
|
|
39
|
+
// This tree is both the function call target and the parameter.
|
|
40
|
+
value = await index.call(this, this);
|
|
41
|
+
} else if (key === ".keys.json") {
|
|
42
|
+
value = await keysJson.stringify(this);
|
|
46
43
|
}
|
|
47
44
|
}
|
|
48
45
|
|
|
@@ -55,12 +52,13 @@ export default function ExplorableSiteTransform(Base) {
|
|
|
55
52
|
|
|
56
53
|
if (key.endsWith?.("/")) {
|
|
57
54
|
// Instead of return the tree directly, return an index for it.
|
|
58
|
-
value = await index.call(
|
|
55
|
+
value = await index.call(this, value);
|
|
59
56
|
}
|
|
60
57
|
} else if (value?.unpack) {
|
|
61
58
|
// If the value isn't a tree, but has a tree attached via an `unpack`
|
|
62
59
|
// method, wrap the unpack method to add this transform.
|
|
63
60
|
const original = value.unpack.bind(value);
|
|
61
|
+
const parent = this;
|
|
64
62
|
value.unpack = async () => {
|
|
65
63
|
const content = await original();
|
|
66
64
|
if (!Tree.isTraversable(content)) {
|
|
@@ -68,9 +66,8 @@ export default function ExplorableSiteTransform(Base) {
|
|
|
68
66
|
}
|
|
69
67
|
/** @type {any} */
|
|
70
68
|
let tree = Tree.from(content);
|
|
71
|
-
if (!tree.parent
|
|
72
|
-
|
|
73
|
-
tree = Scope.treeWithScope(tree, scope);
|
|
69
|
+
if (!tree.parent) {
|
|
70
|
+
tree.parent = parent;
|
|
74
71
|
}
|
|
75
72
|
if (!isTransformApplied(ExplorableSiteTransform, tree)) {
|
|
76
73
|
tree = transformObject(ExplorableSiteTransform, tree);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPlainObject, isUnpackable } from "@weborigami/async-tree";
|
|
1
|
+
import { isPlainObject, isUnpackable, toString } from "@weborigami/async-tree";
|
|
2
2
|
// import txtHandler from "../builtins/txt_handler.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -25,7 +25,7 @@ export default async function documentObject(input, data) {
|
|
|
25
25
|
text = input["@text"];
|
|
26
26
|
inputData = input;
|
|
27
27
|
} else {
|
|
28
|
-
text =
|
|
28
|
+
text = toString(input);
|
|
29
29
|
inputData = null;
|
|
30
30
|
}
|
|
31
31
|
// TODO: Either restore this code, or move responsibility for packing a
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Tree } from "@weborigami/async-tree";
|
|
2
|
-
import { Scope } from "@weborigami/language";
|
|
3
2
|
import builtins from "../builtins/@builtins.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
@@ -15,23 +14,18 @@ import builtins from "../builtins/@builtins.js";
|
|
|
15
14
|
*/
|
|
16
15
|
export default function processUnpackedContent(content, parent, attachedData) {
|
|
17
16
|
if (typeof content === "function") {
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return boundFn;
|
|
31
|
-
} else if (
|
|
32
|
-
Tree.isAsyncTree(content) &&
|
|
33
|
-
!(/** @type {any} */ (content).scope)
|
|
34
|
-
) {
|
|
17
|
+
// Bind the function to a target that's the attached data (if it exists) or
|
|
18
|
+
// the parent.
|
|
19
|
+
const base = parent ?? builtins;
|
|
20
|
+
let target;
|
|
21
|
+
if (attachedData) {
|
|
22
|
+
target = Tree.from(attachedData);
|
|
23
|
+
target.parent = base;
|
|
24
|
+
} else {
|
|
25
|
+
target = base;
|
|
26
|
+
}
|
|
27
|
+
return content.bind(target);
|
|
28
|
+
} else if (Tree.isAsyncTree(content) && !content.parent) {
|
|
35
29
|
const result = Object.create(content);
|
|
36
30
|
result.parent = parent;
|
|
37
31
|
return result;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
|
-
import { ObjectTree } from "@weborigami/async-tree";
|
|
3
|
-
import { Scope } from "@weborigami/language";
|
|
4
2
|
import ori from "../builtins/@ori.js";
|
|
5
|
-
import { keySymbol } from "../common/utilities.js";
|
|
6
3
|
|
|
7
4
|
/**
|
|
8
5
|
* Add support for commands prefixed with `!`.
|
|
@@ -27,13 +24,8 @@ export default function OriCommandTransform(Base) {
|
|
|
27
24
|
return undefined;
|
|
28
25
|
}
|
|
29
26
|
// Key is an Origami command; invoke it.
|
|
30
|
-
const ambientsTree = new ObjectTree({
|
|
31
|
-
"@current": this,
|
|
32
|
-
});
|
|
33
|
-
ambientsTree[keySymbol] = "ori command";
|
|
34
|
-
const extendedScope = new Scope(ambientsTree, Scope.getScope(this));
|
|
35
27
|
const source = key.slice(1).trim();
|
|
36
|
-
value = await ori.call(
|
|
28
|
+
value = await ori.call(this, source, { formatResult: false });
|
|
37
29
|
}
|
|
38
30
|
|
|
39
31
|
return value;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function assertTreeIsDefined(tree: any, methodName: string): asserts tree is object
|