@weborigami/origami 0.0.48 → 0.0.50
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/buildExports.js +2 -2
- package/exports/exports.js +29 -13
- package/index.ts +0 -3
- package/package.json +10 -10
- package/src/builtins/@addNextPrevious.js +58 -0
- package/src/builtins/{@arrows.js → @arrowsMap.js} +7 -7
- package/src/builtins/@changes.js +46 -0
- package/src/builtins/@clean.js +19 -0
- package/src/builtins/@constructor.js +17 -0
- package/src/builtins/@crawl.js +2 -2
- package/src/builtins/@debug.js +17 -19
- package/src/builtins/@deepMap.js +19 -0
- package/src/builtins/@deepMapFn.js +25 -0
- package/src/builtins/{@mergeDeep.js → @deepMerge.js} +7 -7
- package/src/builtins/@deepTake.js +21 -0
- package/src/builtins/@deepTakeFn.js +22 -0
- package/src/builtins/{@valuesDeep.js → @deepValues.js} +6 -5
- package/src/builtins/@document.js +1 -2
- package/src/builtins/@files.js +14 -1
- package/src/builtins/@group.js +20 -0
- package/src/builtins/@groupFn.js +30 -0
- package/src/builtins/@if.js +2 -1
- package/src/builtins/@image/format.js +10 -31
- package/src/builtins/@image/formatFn.js +15 -0
- package/src/builtins/@image/resize.js +7 -28
- package/src/builtins/@image/resizeFn.js +14 -0
- package/src/builtins/@inline.js +8 -2
- package/src/builtins/@invoke.js +1 -1
- package/src/builtins/@json.js +5 -1
- package/src/builtins/@jsonParse.js +9 -0
- package/src/builtins/@map.js +10 -170
- package/src/builtins/@mapFn.js +143 -0
- package/src/builtins/@mdHtml.js +2 -0
- package/src/builtins/@mdTree.js +69 -0
- package/src/builtins/@naturalOrder.js +1 -0
- package/src/builtins/@ori.js +1 -1
- package/src/builtins/@paginate.js +18 -0
- package/src/builtins/@paginateFn.js +61 -0
- package/src/builtins/@perf.js +1 -1
- package/src/builtins/@redirect.js +10 -1
- package/src/builtins/@regexParse.js +5 -0
- package/src/builtins/@regexParseFn.js +9 -0
- package/src/builtins/@rss.js +8 -4
- package/src/builtins/@sitemap.js +4 -4
- package/src/builtins/@slug.js +15 -0
- package/src/builtins/@sort.js +10 -7
- package/src/builtins/@sortFn.js +58 -0
- package/src/builtins/@take.js +3 -17
- package/src/builtins/@takeFn.js +21 -0
- package/src/builtins/@tree.js +2 -14
- package/src/builtins/@yaml.js +4 -0
- package/src/builtins/@yamlParse.js +10 -0
- package/src/builtins/map.d.ts +6 -7
- package/src/common/ExplorableSiteTransform.js +16 -10
- package/src/common/ShuffleTransform.js +3 -3
- package/src/common/{arrowFunctionsMap.js → arrowsMapFn.js} +3 -3
- package/src/common/documentObject.js +18 -9
- package/src/common/serialize.js +1 -10
- package/src/common/utilities.js +5 -2
- package/src/misc/OriCommandTransform.js +2 -7
- package/src/misc/explore.ori +7 -7
- package/src/server/constructResponse.js +3 -9
- package/src/server/server.js +5 -2
- package/src/builtins/@apply.js +0 -6
- package/src/builtins/@groupBy.js +0 -37
- package/src/builtins/@isAsyncTree.js +0 -17
- package/src/builtins/@mapDeep.js +0 -22
- package/src/builtins/@new.js +0 -6
- package/src/builtins/@parse/json.js +0 -6
- package/src/builtins/@parse/yaml.js +0 -8
- package/src/builtins/@sortBy.js +0 -37
- package/src/builtins/@with.js +0 -22
package/exports/buildExports.js
CHANGED
|
@@ -103,11 +103,11 @@ function exportStatements(src) {
|
|
|
103
103
|
const withPaths = transformObject(PathTransform, src);
|
|
104
104
|
|
|
105
105
|
// Map each source file to an export statement.
|
|
106
|
-
const mapped = map({
|
|
106
|
+
const mapped = map(withPaths, {
|
|
107
107
|
deep: true,
|
|
108
108
|
value: exportStatementForCode,
|
|
109
109
|
...keyFunctionsForExtensions({ sourceExtension: "js" }),
|
|
110
|
-
})
|
|
110
|
+
});
|
|
111
111
|
|
|
112
112
|
return mapped;
|
|
113
113
|
}
|
package/exports/exports.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
// This file is generated by running buildExports.js -- do not edit by hand.
|
|
2
|
-
export { default as
|
|
3
|
-
export { default as
|
|
2
|
+
export { default as addNextPrevious } from "../src/builtins/@addNextPrevious.js";
|
|
3
|
+
export { default as arrowsMap } from "../src/builtins/@arrowsMap.js";
|
|
4
4
|
export { default as basename } from "../src/builtins/@basename.js";
|
|
5
5
|
export { default as builtins } from "../src/builtins/@builtins.js";
|
|
6
6
|
export { default as cache } from "../src/builtins/@cache.js";
|
|
7
|
+
export { default as changes } from "../src/builtins/@changes.js";
|
|
8
|
+
export { default as clean } from "../src/builtins/@clean.js";
|
|
7
9
|
export { default as concat } from "../src/builtins/@concat.js";
|
|
8
10
|
export { default as config } from "../src/builtins/@config.js";
|
|
11
|
+
export { default as constructor } from "../src/builtins/@constructor.js";
|
|
9
12
|
export { default as copy } from "../src/builtins/@copy.js";
|
|
10
13
|
export { default as count } from "../src/builtins/@count.js";
|
|
11
14
|
export { default as crawl } from "../src/builtins/@crawl.js";
|
|
12
15
|
export { default as debug } from "../src/builtins/@debug.js";
|
|
16
|
+
export { default as deepMap } from "../src/builtins/@deepMap.js";
|
|
17
|
+
export { default as deepMapFn } from "../src/builtins/@deepMapFn.js";
|
|
18
|
+
export { default as deepMerge } from "../src/builtins/@deepMerge.js";
|
|
19
|
+
export { default as deepTake } from "../src/builtins/@deepTake.js";
|
|
20
|
+
export { default as deepTakeFn } from "../src/builtins/@deepTakeFn.js";
|
|
21
|
+
export { default as deepValues } from "../src/builtins/@deepValues.js";
|
|
13
22
|
export { default as defineds } from "../src/builtins/@defineds.js";
|
|
14
23
|
export { default as document } from "../src/builtins/@document.js";
|
|
15
24
|
export { default as equals } from "../src/builtins/@equals.js";
|
|
@@ -21,30 +30,34 @@ export { default as filter } from "../src/builtins/@filter.js";
|
|
|
21
30
|
export { default as first } from "../src/builtins/@first.js";
|
|
22
31
|
export { default as fnTree } from "../src/builtins/@fnTree.js";
|
|
23
32
|
export { default as globs } from "../src/builtins/@globs.js";
|
|
24
|
-
export { default as
|
|
33
|
+
export { default as group } from "../src/builtins/@group.js";
|
|
34
|
+
export { default as groupFn } from "../src/builtins/@groupFn.js";
|
|
25
35
|
export { default as help } from "../src/builtins/@help.js";
|
|
26
36
|
export { default as http } from "../src/builtins/@http.js";
|
|
27
37
|
export { default as https } from "../src/builtins/@https.js";
|
|
28
38
|
export { default as if } from "../src/builtins/@if.js";
|
|
29
39
|
export { default as imageFormat } from "../src/builtins/@image/format.js";
|
|
40
|
+
export { default as imageFormatFn } from "../src/builtins/@image/formatFn.js";
|
|
30
41
|
export { default as imageResize } from "../src/builtins/@image/resize.js";
|
|
42
|
+
export { default as imageResizeFn } from "../src/builtins/@image/resizeFn.js";
|
|
31
43
|
export { default as index } from "../src/builtins/@index.js";
|
|
32
44
|
export { default as inherited } from "../src/builtins/@inherited.js";
|
|
33
45
|
export { default as inline } from "../src/builtins/@inline.js";
|
|
34
46
|
export { default as inners } from "../src/builtins/@inners.js";
|
|
35
47
|
export { default as invoke } from "../src/builtins/@invoke.js";
|
|
36
|
-
export { default as isAsyncTree } from "../src/builtins/@isAsyncTree.js";
|
|
37
48
|
export { default as js } from "../src/builtins/@js.js";
|
|
38
49
|
export { default as json } from "../src/builtins/@json.js";
|
|
50
|
+
export { default as jsonParse } from "../src/builtins/@jsonParse.js";
|
|
39
51
|
export { default as keys } from "../src/builtins/@keys.js";
|
|
40
52
|
export { default as keysJson } from "../src/builtins/@keysJson.js";
|
|
41
53
|
export { default as map } from "../src/builtins/@map.js";
|
|
42
|
-
export { default as
|
|
54
|
+
export { default as mapFn } from "../src/builtins/@mapFn.js";
|
|
43
55
|
export { default as match } from "../src/builtins/@match.js";
|
|
44
56
|
export { default as mdHtml } from "../src/builtins/@mdHtml.js";
|
|
57
|
+
export { default as mdTree } from "../src/builtins/@mdTree.js";
|
|
45
58
|
export { default as merge } from "../src/builtins/@merge.js";
|
|
46
|
-
export { default as mergeDeep } from "../src/builtins/@mergeDeep.js";
|
|
47
59
|
export { default as mkdir } from "../src/builtins/@mkdir.js";
|
|
60
|
+
export * from "../src/builtins/@naturalOrder.js";
|
|
48
61
|
export { default as node } from "../src/builtins/@node.js";
|
|
49
62
|
export { default as not } from "../src/builtins/@not.js";
|
|
50
63
|
export { default as once } from "../src/builtins/@once.js";
|
|
@@ -52,14 +65,16 @@ export { default as or } from "../src/builtins/@or.js";
|
|
|
52
65
|
export { default as ori } from "../src/builtins/@ori.js";
|
|
53
66
|
export { default as pack } from "../src/builtins/@pack.js";
|
|
54
67
|
export { default as package } from "../src/builtins/@package.js";
|
|
68
|
+
export { default as paginate } from "../src/builtins/@paginate.js";
|
|
69
|
+
export { default as paginateFn } from "../src/builtins/@paginateFn.js";
|
|
55
70
|
export { default as parent } from "../src/builtins/@parent.js";
|
|
56
|
-
export { default as parseJson } from "../src/builtins/@parse/json.js";
|
|
57
|
-
export { default as parseYaml } from "../src/builtins/@parse/yaml.js";
|
|
58
71
|
export { default as paths } from "../src/builtins/@paths.js";
|
|
59
72
|
export { default as perf } from "../src/builtins/@perf.js";
|
|
60
73
|
export { default as plain } from "../src/builtins/@plain.js";
|
|
61
74
|
export { default as project } from "../src/builtins/@project.js";
|
|
62
75
|
export { default as redirect } from "../src/builtins/@redirect.js";
|
|
76
|
+
export { default as regexParse } from "../src/builtins/@regexParse.js";
|
|
77
|
+
export { default as regexParseFn } from "../src/builtins/@regexParseFn.js";
|
|
63
78
|
export { default as repeat } from "../src/builtins/@repeat.js";
|
|
64
79
|
export { default as reverse } from "../src/builtins/@reverse.js";
|
|
65
80
|
export { default as rss } from "../src/builtins/@rss.js";
|
|
@@ -72,23 +87,24 @@ export { default as setDeep } from "../src/builtins/@setDeep.js";
|
|
|
72
87
|
export { default as shell } from "../src/builtins/@shell.js";
|
|
73
88
|
export { default as shuffle } from "../src/builtins/@shuffle.js";
|
|
74
89
|
export { default as sitemap } from "../src/builtins/@sitemap.js";
|
|
90
|
+
export { default as slug } from "../src/builtins/@slug.js";
|
|
75
91
|
export { default as sort } from "../src/builtins/@sort.js";
|
|
76
|
-
export { default as
|
|
92
|
+
export { default as sortFn } from "../src/builtins/@sortFn.js";
|
|
77
93
|
export { default as static } from "../src/builtins/@static.js";
|
|
78
94
|
export { default as stdin } from "../src/builtins/@stdin.js";
|
|
79
95
|
export { default as string } from "../src/builtins/@string.js";
|
|
80
96
|
export { default as svg } from "../src/builtins/@svg.js";
|
|
81
97
|
export { default as table } from "../src/builtins/@table.js";
|
|
82
98
|
export { default as take } from "../src/builtins/@take.js";
|
|
83
|
-
export { default as
|
|
99
|
+
export { default as takeFn } from "../src/builtins/@takeFn.js";
|
|
100
|
+
export * from "../src/builtins/@tree.js";
|
|
84
101
|
export { default as treeHttp } from "../src/builtins/@treeHttp.js";
|
|
85
102
|
export { default as treeHttps } from "../src/builtins/@treeHttps.js";
|
|
86
103
|
export { default as unpack } from "../src/builtins/@unpack.js";
|
|
87
104
|
export { default as values } from "../src/builtins/@values.js";
|
|
88
|
-
export { default as valuesDeep } from "../src/builtins/@valuesDeep.js";
|
|
89
105
|
export { default as watch } from "../src/builtins/@watch.js";
|
|
90
|
-
export { default as with } from "../src/builtins/@with.js";
|
|
91
106
|
export { default as yaml } from "../src/builtins/@yaml.js";
|
|
107
|
+
export { default as yamlParse } from "../src/builtins/@yamlParse.js";
|
|
92
108
|
export { default as homeFiles } from "../src/builtins/~.js";
|
|
93
109
|
export { default as csshandler } from "../src/builtins/css_handler.js";
|
|
94
110
|
export { default as htmhandler } from "../src/builtins/htm_handler.js";
|
|
@@ -108,7 +124,7 @@ export { default as ymlhandler } from "../src/builtins/yml_handler.js";
|
|
|
108
124
|
export { default as defaultModuleExport } from "../src/cli/defaultModuleExport.js";
|
|
109
125
|
export { default as showUsage } from "../src/cli/showUsage.js";
|
|
110
126
|
export { default as addValueKeyToScope } from "../src/common/addValueKeyToScope.js";
|
|
111
|
-
export { default as
|
|
127
|
+
export { default as arrowsMapFn } from "../src/common/arrowsMapFn.js";
|
|
112
128
|
export { default as CommandModulesTransform } from "../src/common/CommandModulesTransform.js";
|
|
113
129
|
export { default as ConstantTree } from "../src/common/ConstantTree.js";
|
|
114
130
|
export { default as documentObject } from "../src/common/documentObject.js";
|
package/index.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Treelike, Unpackable } from "@weborigami/async-tree";
|
|
7
|
-
import { AsyncTree } from "@weborigami/types";
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* A class constructor is an object with a `new` method that returns an
|
|
@@ -21,5 +20,3 @@ export interface JsonObject {
|
|
|
21
20
|
export type JsonValue = boolean | number | string | Date | JsonObject | JsonValue[] | null;
|
|
22
21
|
|
|
23
22
|
export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
|
|
24
|
-
|
|
25
|
-
export type TreelikeTransform = (value: Treelike) => AsyncTree;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/origami",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.50",
|
|
4
4
|
"description": "Web Origami language, CLI, framework, and server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -13,22 +13,22 @@
|
|
|
13
13
|
"main": "./exports/exports.js",
|
|
14
14
|
"types": "./index.ts",
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@types/node": "20.
|
|
17
|
-
"typescript": "5.4.
|
|
16
|
+
"@types/node": "20.12.7",
|
|
17
|
+
"typescript": "5.4.5"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@weborigami/async-tree": "0.0.
|
|
21
|
-
"@weborigami/language": "0.0.
|
|
22
|
-
"@weborigami/types": "0.0.
|
|
20
|
+
"@weborigami/async-tree": "0.0.50",
|
|
21
|
+
"@weborigami/language": "0.0.50",
|
|
22
|
+
"@weborigami/types": "0.0.50",
|
|
23
23
|
"exif-parser": "0.1.12",
|
|
24
|
-
"graphviz-wasm": "3.0.
|
|
24
|
+
"graphviz-wasm": "3.0.2",
|
|
25
25
|
"highlight.js": "11.9.0",
|
|
26
|
-
"marked": "12.0.
|
|
26
|
+
"marked": "12.0.2",
|
|
27
27
|
"marked-gfm-heading-id": "3.1.3",
|
|
28
28
|
"marked-highlight": "2.1.1",
|
|
29
29
|
"marked-smartypants": "1.1.6",
|
|
30
|
-
"sharp": "0.33.
|
|
31
|
-
"yaml": "2.4.
|
|
30
|
+
"sharp": "0.33.3",
|
|
31
|
+
"yaml": "2.4.2"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "ori exports/buildExports.js src > exports/exports.js",
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Tree } from "@weborigami/async-tree";
|
|
2
|
+
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Add nextKey/previousKey properties to values.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
+
*
|
|
9
|
+
* @this {AsyncTree|null}
|
|
10
|
+
* @param {import("@weborigami/async-tree").Treelike} treelike
|
|
11
|
+
*/
|
|
12
|
+
export default async function addNextPrevious(treelike) {
|
|
13
|
+
const tree = await getTreeArgument(this, arguments, treelike, "@sequence");
|
|
14
|
+
let keys;
|
|
15
|
+
return Object.create(tree, {
|
|
16
|
+
get: {
|
|
17
|
+
value: async (key) => {
|
|
18
|
+
let value = await tree.get(key);
|
|
19
|
+
|
|
20
|
+
if (value === undefined) {
|
|
21
|
+
return undefined;
|
|
22
|
+
} else if (Tree.isTreelike(value)) {
|
|
23
|
+
value = await Tree.plain(value);
|
|
24
|
+
} else if (typeof value === "object") {
|
|
25
|
+
// Clone value to avoid modifying the original object.
|
|
26
|
+
value = { ...value };
|
|
27
|
+
} else if (typeof value === "string") {
|
|
28
|
+
// Upgrade text nodes to objects.
|
|
29
|
+
value = { "@text": value };
|
|
30
|
+
} else {
|
|
31
|
+
// Upgrade other scalar types to objects.
|
|
32
|
+
value = { "@data": value };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (keys === undefined) {
|
|
36
|
+
keys = Array.from(await tree.keys());
|
|
37
|
+
}
|
|
38
|
+
const index = keys.indexOf(key);
|
|
39
|
+
if (index === -1) {
|
|
40
|
+
// Key is supported but not published in `keys`
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Extend value with nextKey/previousKey properties.
|
|
45
|
+
const nextKey = keys[index + 1];
|
|
46
|
+
if (nextKey) {
|
|
47
|
+
value.nextKey = nextKey;
|
|
48
|
+
}
|
|
49
|
+
const previousKey = keys[index - 1];
|
|
50
|
+
if (previousKey) {
|
|
51
|
+
value.previousKey = previousKey;
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
},
|
|
55
|
+
writable: true,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Scope, functionResultsMap } from "@weborigami/language";
|
|
2
|
-
import
|
|
2
|
+
import arrowsMapFn from "../common/arrowsMapFn.js";
|
|
3
3
|
import { keySymbol } from "../common/utilities.js";
|
|
4
4
|
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
5
5
|
import builtins from "./@builtins.js";
|
|
@@ -12,14 +12,14 @@ import builtins from "./@builtins.js";
|
|
|
12
12
|
* @this {AsyncTree|null}
|
|
13
13
|
* @param {Treelike} [treelike]
|
|
14
14
|
*/
|
|
15
|
-
export default async function
|
|
16
|
-
const tree = await getTreeArgument(this, arguments, treelike, "
|
|
17
|
-
const mapped = functionResultsMap(
|
|
15
|
+
export default async function arrowsMap(treelike) {
|
|
16
|
+
const tree = await getTreeArgument(this, arguments, treelike, "arrowsMap");
|
|
17
|
+
const mapped = functionResultsMap(arrowsMapFn()(tree));
|
|
18
18
|
const scope = this ?? builtins;
|
|
19
19
|
const scoped = Scope.treeWithScope(mapped, scope);
|
|
20
|
-
scoped[keySymbol] = "@
|
|
20
|
+
scoped[keySymbol] = "@arrowsMap";
|
|
21
21
|
return scoped;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
arrowsMap.usage = `@arrowsMap <obj>\tInterpret arrow keys in the tree as function calls`;
|
|
25
|
+
arrowsMap.documentation = "https://weborigami.org/language/@arrowsMap.html";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Tree } from "@weborigami/async-tree";
|
|
2
|
+
|
|
3
|
+
// Given an old tree and a new tree, return a tree of changes indicated
|
|
4
|
+
// by the values: "added", "changed", or "deleted".
|
|
5
|
+
export default async function changes(oldTreelike, newTreelike) {
|
|
6
|
+
const oldTree = Tree.from(oldTreelike);
|
|
7
|
+
const newTree = Tree.from(newTreelike);
|
|
8
|
+
|
|
9
|
+
const oldKeys = Array.from(await oldTree.keys());
|
|
10
|
+
const newKeys = Array.from(await newTree.keys());
|
|
11
|
+
|
|
12
|
+
const result = {};
|
|
13
|
+
|
|
14
|
+
for (const key of oldKeys) {
|
|
15
|
+
if (!newKeys.includes(key)) {
|
|
16
|
+
result[key] = "deleted";
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const oldValue = await oldTree.get(key);
|
|
21
|
+
const newValue = await newTree.get(key);
|
|
22
|
+
|
|
23
|
+
if (Tree.isAsyncTree(oldValue) && Tree.isAsyncTree(newValue)) {
|
|
24
|
+
const treeChanges = await changes(oldValue, newValue);
|
|
25
|
+
if (Object.keys(treeChanges).length > 0) {
|
|
26
|
+
result[key] = treeChanges;
|
|
27
|
+
}
|
|
28
|
+
} else if (oldValue?.toString && newValue?.toString) {
|
|
29
|
+
const oldText = oldValue.toString();
|
|
30
|
+
const newText = newValue.toString();
|
|
31
|
+
if (oldText !== newText) {
|
|
32
|
+
result[key] = "changed";
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
result[key] = "changed";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (const key of newKeys) {
|
|
40
|
+
if (!oldKeys.includes(key)) {
|
|
41
|
+
result[key] = "added";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Tree } from "@weborigami/async-tree";
|
|
2
|
+
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
6
|
+
*
|
|
7
|
+
* @this {AsyncTree|null}
|
|
8
|
+
* @param {import("@weborigami/async-tree").Treelike} treelike
|
|
9
|
+
*/
|
|
10
|
+
export default async function clean(treelike) {
|
|
11
|
+
const tree = await getTreeArgument(this, arguments, treelike, "@sequence");
|
|
12
|
+
if (!Tree.isAsyncMutableTree(tree)) {
|
|
13
|
+
throw new TypeError("@clean: the given tree is read-only.");
|
|
14
|
+
}
|
|
15
|
+
const keys = Array.from(await tree.keys());
|
|
16
|
+
const promises = keys.map((key) => tree.set(key, undefined));
|
|
17
|
+
await Promise.all(promises);
|
|
18
|
+
return tree;
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ops } from "@weborigami/language";
|
|
2
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
6
|
+
*
|
|
7
|
+
* @this {AsyncTree|null}
|
|
8
|
+
* @param {...any} keys
|
|
9
|
+
*/
|
|
10
|
+
export default function constructor(...keys) {
|
|
11
|
+
assertScopeIsDefined(this, "constructor");
|
|
12
|
+
const scope = this;
|
|
13
|
+
if (!scope) {
|
|
14
|
+
throw new Error("@constructor requires a non-null scope.");
|
|
15
|
+
}
|
|
16
|
+
return ops.constructor.call(scope, ...keys);
|
|
17
|
+
}
|
package/src/builtins/@crawl.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DeepObjectTree,
|
|
3
3
|
Tree,
|
|
4
|
+
deepMerge,
|
|
4
5
|
isPlainObject,
|
|
5
6
|
keysFromPath,
|
|
6
|
-
mergeDeep,
|
|
7
7
|
} from "@weborigami/async-tree";
|
|
8
8
|
import { InvokeFunctionsTransform, Scope, extname } from "@weborigami/language";
|
|
9
9
|
import * as utilities from "../common/utilities.js";
|
|
@@ -93,7 +93,7 @@ export default async function crawl(treelike, baseHref) {
|
|
|
93
93
|
// for something already, that's better than a function that will get that
|
|
94
94
|
// value.
|
|
95
95
|
/** @type {AsyncTree} */
|
|
96
|
-
let result =
|
|
96
|
+
let result = deepMerge(
|
|
97
97
|
new DeepObjectTree(cache),
|
|
98
98
|
new (InvokeFunctionsTransform(DeepObjectTree))(resources)
|
|
99
99
|
);
|
package/src/builtins/@debug.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Tree
|
|
1
|
+
import { Tree } from "@weborigami/async-tree";
|
|
2
2
|
import { Scope } from "@weborigami/language";
|
|
3
3
|
import ExplorableSiteTransform from "../common/ExplorableSiteTransform.js";
|
|
4
4
|
import { isTransformApplied, transformObject } from "../common/utilities.js";
|
|
@@ -19,12 +19,13 @@ export default async function debug(treelike) {
|
|
|
19
19
|
// apply its own scope to the tree.
|
|
20
20
|
let tree = await getTreeArgument(this, arguments, treelike, "@debug");
|
|
21
21
|
|
|
22
|
+
if (!isTransformApplied(DebugTransform, tree)) {
|
|
23
|
+
tree = transformObject(DebugTransform, tree);
|
|
24
|
+
}
|
|
22
25
|
if (!isTransformApplied(ExplorableSiteTransform, tree)) {
|
|
23
26
|
tree = transformObject(ExplorableSiteTransform, tree);
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
tree = transformObject(DebugTransform, tree);
|
|
27
|
-
|
|
28
29
|
return tree;
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -36,20 +37,19 @@ function DebugTransform(Base) {
|
|
|
36
37
|
return class Debug extends OriCommandTransform(Base) {
|
|
37
38
|
async get(key) {
|
|
38
39
|
let value = await super.get(key);
|
|
40
|
+
const scope = Scope.getScope(this);
|
|
39
41
|
|
|
40
|
-
// Since this transform is for diagnostic purposes, cast
|
|
41
|
-
//
|
|
42
|
-
if (
|
|
42
|
+
// Since this transform is for diagnostic purposes, cast any treelike
|
|
43
|
+
// result to a tree so we can debug the result too.
|
|
44
|
+
if (Tree.isTreelike(value)) {
|
|
43
45
|
value = Tree.from(value);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (value?.unpack) {
|
|
46
|
+
if (!value.parent && !value.scope) {
|
|
47
|
+
value = Scope.treeWithScope(value, scope);
|
|
48
|
+
}
|
|
49
|
+
if (!isTransformApplied(DebugTransform, value)) {
|
|
50
|
+
value = transformObject(DebugTransform, value);
|
|
51
|
+
}
|
|
52
|
+
} else if (value?.unpack) {
|
|
53
53
|
// If the value isn't a tree, but has a tree attached via an `unpack`
|
|
54
54
|
// method, wrap the unpack method to provide debug support for it.
|
|
55
55
|
const original = value.unpack.bind(value);
|
|
@@ -61,13 +61,11 @@ function DebugTransform(Base) {
|
|
|
61
61
|
/** @type {any} */
|
|
62
62
|
let tree = Tree.from(content);
|
|
63
63
|
if (!tree.parent && !tree.scope) {
|
|
64
|
-
const scope = Scope.getScope(this);
|
|
65
64
|
tree = Scope.treeWithScope(tree, scope);
|
|
66
65
|
}
|
|
67
|
-
if (!isTransformApplied(
|
|
68
|
-
tree = transformObject(
|
|
66
|
+
if (!isTransformApplied(DebugTransform, tree)) {
|
|
67
|
+
tree = transformObject(DebugTransform, tree);
|
|
69
68
|
}
|
|
70
|
-
tree = transformObject(DebugTransform, tree);
|
|
71
69
|
return tree;
|
|
72
70
|
};
|
|
73
71
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
2
|
+
import deepMapFn from "./@deepMapFn.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shorthand for calling `@map` with `deep: true` option.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").ValueKeyFn} ValueKeyFn
|
|
10
|
+
* @typedef {import("./map.d.ts").TreeMapOptions} TreeMapOptions
|
|
11
|
+
*
|
|
12
|
+
* @this {AsyncTree|null}
|
|
13
|
+
* @param {Treelike} source
|
|
14
|
+
* @param {ValueKeyFn|TreeMapOptions} operation
|
|
15
|
+
*/
|
|
16
|
+
export default function deepMap(source, operation) {
|
|
17
|
+
assertScopeIsDefined(this, "deepMap");
|
|
18
|
+
return deepMapFn.call(this, operation)(source);
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { isPlainObject } from "@weborigami/async-tree";
|
|
2
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
3
|
+
import mapFn from "./@mapFn.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shorthand for calling `@mapFn` with `deep: true` option.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
|
+
* @typedef {import("@weborigami/async-tree").ValueKeyFn} ValueKeyFn
|
|
11
|
+
* @typedef {import("./map.d.ts").TreeMapOptions} TreeMapOptions
|
|
12
|
+
*
|
|
13
|
+
* @this {AsyncTree|null}
|
|
14
|
+
* @param {ValueKeyFn|TreeMapOptions} operation
|
|
15
|
+
*/
|
|
16
|
+
export default function deepMapFn(operation) {
|
|
17
|
+
assertScopeIsDefined(this, "deepMap");
|
|
18
|
+
/** @type {TreeMapOptions} */
|
|
19
|
+
const options = isPlainObject(operation)
|
|
20
|
+
? // Dictionary
|
|
21
|
+
{ ...operation, deep: true }
|
|
22
|
+
: // Function
|
|
23
|
+
{ deep: true, value: operation };
|
|
24
|
+
return mapFn.call(this, options);
|
|
25
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { deepMerge } from "@weborigami/async-tree";
|
|
2
2
|
import { Scope } from "@weborigami/language";
|
|
3
3
|
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
4
|
|
|
@@ -10,8 +10,8 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
10
10
|
* @this {AsyncTree|null}
|
|
11
11
|
* @param {Treelike[]} trees
|
|
12
12
|
*/
|
|
13
|
-
export default async function
|
|
14
|
-
assertScopeIsDefined(this, "
|
|
13
|
+
export default async function treedeepMerge(...trees) {
|
|
14
|
+
assertScopeIsDefined(this, "deepMerge");
|
|
15
15
|
// Filter out null or undefined trees.
|
|
16
16
|
const filtered = trees.filter((tree) => tree);
|
|
17
17
|
|
|
@@ -30,7 +30,7 @@ export default async function treeMergeDeep(...trees) {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
// Merge the trees.
|
|
33
|
-
const result =
|
|
33
|
+
const result = deepMerge(...scopedTrees);
|
|
34
34
|
|
|
35
35
|
// Give the overall mixed tree a scope that includes the component trees and
|
|
36
36
|
// the current scope.
|
|
@@ -39,6 +39,6 @@ export default async function treeMergeDeep(...trees) {
|
|
|
39
39
|
return result;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"https://weborigami.org/cli/builtins.html#
|
|
42
|
+
treedeepMerge.usage = `@deepMerge <...trees>\tMerge the given trees deeply`;
|
|
43
|
+
treedeepMerge.documentation =
|
|
44
|
+
"https://weborigami.org/cli/builtins.html#deepMerge";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
2
|
+
import deepTakeFn from "./@deepTakeFn.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns a function that traverses a tree deeply and returns the values of the
|
|
6
|
+
* first `count` keys.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
|
+
*
|
|
11
|
+
* @this {AsyncTree|null}
|
|
12
|
+
* @param {Treelike} treelike
|
|
13
|
+
* @param {number} n
|
|
14
|
+
*/
|
|
15
|
+
export default async function deepTake(treelike, n) {
|
|
16
|
+
const tree = await getTreeArgument(this, arguments, treelike, "@deepTake");
|
|
17
|
+
return deepTakeFn.call(this, n)(tree);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
deepTake.usage = `@deepTake tree, n\tReturn the first n values from the deep tree`;
|
|
21
|
+
deepTake.documentation = "https://weborigami.org/builtins/deepTake.html";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { deepTakeFn } from "@weborigami/async-tree";
|
|
2
|
+
import { Scope } from "@weborigami/language";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a function that traverses a tree deeply and returns the values of the
|
|
7
|
+
* first `count` keys.
|
|
8
|
+
*
|
|
9
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
10
|
+
*
|
|
11
|
+
* @this {AsyncTree|null}
|
|
12
|
+
* @param {number} count
|
|
13
|
+
*/
|
|
14
|
+
export default function deepTakeFnBuiltin(count) {
|
|
15
|
+
assertScopeIsDefined(this, "deepTakeFn");
|
|
16
|
+
const scope = this;
|
|
17
|
+
return async (treelike) => {
|
|
18
|
+
const taken = await deepTakeFn(count)(treelike);
|
|
19
|
+
const scoped = Scope.treeWithScope(taken, scope);
|
|
20
|
+
return scoped;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { deepValues } from "@weborigami/async-tree";
|
|
2
2
|
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -6,14 +6,15 @@ import getTreeArgument from "../misc/getTreeArgument.js";
|
|
|
6
6
|
*
|
|
7
7
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
8
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
9
|
+
*
|
|
9
10
|
* @this {AsyncTree|null}
|
|
10
11
|
* @param {Treelike} [treelike]
|
|
11
12
|
*/
|
|
12
|
-
export default async function
|
|
13
|
+
export default async function deepValuesBuiltin(treelike) {
|
|
13
14
|
const tree = await getTreeArgument(this, arguments, treelike, "@valuesDeep");
|
|
14
|
-
return
|
|
15
|
+
return deepValues(tree);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
deepValuesBuiltin.usage = `@valuesDeep <tree>\tThe in-order tree values as a flat array`;
|
|
19
|
+
deepValuesBuiltin.documentation =
|
|
19
20
|
"https://weborigami.org/cli/builtins.html#valuesDeep";
|
|
@@ -8,9 +8,8 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
8
8
|
* @this {AsyncTree|null}
|
|
9
9
|
* @param {StringLike} text
|
|
10
10
|
* @param {any} [data]
|
|
11
|
-
* @returns
|
|
12
11
|
*/
|
|
13
|
-
export default function documentBuiltin(text, data) {
|
|
12
|
+
export default async function documentBuiltin(text, data) {
|
|
14
13
|
assertScopeIsDefined(this, "document");
|
|
15
14
|
return documentObject(text, data);
|
|
16
15
|
}
|
package/src/builtins/@files.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { OrigamiFiles, Scope } from "@weborigami/language";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import process from "node:process";
|
|
4
5
|
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
@@ -11,7 +12,19 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
|
11
12
|
*/
|
|
12
13
|
export default async function files(...keys) {
|
|
13
14
|
assertScopeIsDefined(this, "files");
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
// If path begins with `~`, treat it relative to the home directory.
|
|
17
|
+
// Otherwise, treat it relative to the current working directory.
|
|
18
|
+
let relativePath = keys.join(path.sep);
|
|
19
|
+
let basePath;
|
|
20
|
+
if (relativePath.startsWith("~")) {
|
|
21
|
+
basePath = os.homedir();
|
|
22
|
+
relativePath = relativePath.slice(2);
|
|
23
|
+
} else {
|
|
24
|
+
basePath = process.cwd();
|
|
25
|
+
}
|
|
26
|
+
const resolved = path.resolve(basePath, relativePath);
|
|
27
|
+
|
|
15
28
|
/** @type {AsyncTree} */
|
|
16
29
|
let result = new OrigamiFiles(resolved);
|
|
17
30
|
result = Scope.treeWithScope(result, this);
|