@weborigami/origami 0.2.3 → 0.2.5
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 -0
- package/package.json +4 -4
- package/src/dev/watch.js +2 -1
- package/src/handlers/getParent.js +29 -0
- package/src/handlers/ori.handler.js +4 -7
- package/src/handlers/oridocument.handler.js +4 -7
- package/src/help/help.yaml +11 -2
- package/src/js.js +1 -0
- package/src/origami/once.js +18 -2
- package/src/server/constructResponse.js +3 -0
- package/src/server/server.js +2 -1
- package/src/tree/cache.js +2 -7
- package/src/tree/constant.js +1 -0
- package/src/tree/deepMerge.js +2 -10
- package/src/tree/filter.js +4 -6
- package/src/tree/{globs.js → globKeys.js} +5 -3
- package/src/tree/map.js +11 -5
- package/src/tree/regExpKeys.js +19 -0
- package/src/tree/tree.js +3 -1
- package/src/tree/FilterTree.js +0 -61
- package/src/tree/GlobTree.js +0 -76
package/main.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./src/handlers/handlers.js";
|
|
|
7
7
|
export * from "./src/image/image.js";
|
|
8
8
|
export { builtinsTree } from "./src/internal.js";
|
|
9
9
|
export * from "./src/origami/origami.js";
|
|
10
|
+
export * from "./src/server/server.js";
|
|
10
11
|
export * from "./src/site/site.js";
|
|
11
12
|
export * from "./src/text/text.js";
|
|
12
13
|
export * from "./src/tree/tree.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/origami",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Web Origami language, CLI, framework, and server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"typescript": "5.7.2"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@weborigami/async-tree": "0.2.
|
|
21
|
-
"@weborigami/language": "0.2.
|
|
22
|
-
"@weborigami/types": "0.2.
|
|
20
|
+
"@weborigami/async-tree": "0.2.5",
|
|
21
|
+
"@weborigami/language": "0.2.5",
|
|
22
|
+
"@weborigami/types": "0.2.5",
|
|
23
23
|
"exif-parser": "0.1.12",
|
|
24
24
|
"graphviz-wasm": "3.0.2",
|
|
25
25
|
"highlight.js": "11.11.0",
|
package/src/dev/watch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tree } from "@weborigami/async-tree";
|
|
2
|
-
import { formatError } from "@weborigami/language";
|
|
2
|
+
import { formatError, moduleCache } from "@weborigami/language";
|
|
3
3
|
import ConstantTree from "../common/ConstantTree.js";
|
|
4
4
|
import getTreeArgument from "../common/getTreeArgument.js";
|
|
5
5
|
|
|
@@ -42,6 +42,7 @@ export default async function watch(treelike, fn) {
|
|
|
42
42
|
// Reevaluate the function whenever the tree changes.
|
|
43
43
|
container.addEventListener?.("change", async () => {
|
|
44
44
|
const tree = await evaluateTree(container, fn);
|
|
45
|
+
moduleCache.resetTimestamp();
|
|
45
46
|
updateIndirectPointer(handle, tree);
|
|
46
47
|
});
|
|
47
48
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { symbols } from "@weborigami/async-tree";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return a suitable parent for the packed file.
|
|
5
|
+
*
|
|
6
|
+
* @param {any} packed
|
|
7
|
+
* @param {any} options
|
|
8
|
+
* @returns {import("@weborigami/types").AsyncTree|null}
|
|
9
|
+
*/
|
|
10
|
+
export default function getParent(packed, options) {
|
|
11
|
+
// Prefer parent set on options
|
|
12
|
+
if (options?.parent) {
|
|
13
|
+
return options.parent;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// If the packed object has a `parent` property, use that. Exception: Node
|
|
17
|
+
// Buffer objects have a `parent` property that we ignore.
|
|
18
|
+
if (packed.parent && !(packed instanceof Buffer)) {
|
|
19
|
+
return packed.parent;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// If the packed object has a parent symbol, use that.
|
|
23
|
+
if (packed[symbols.parent]) {
|
|
24
|
+
return packed[symbols.parent];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Otherwise, return null.
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { symbols } from "@weborigami/async-tree";
|
|
2
1
|
import { compile } from "@weborigami/language";
|
|
3
2
|
import * as utilities from "../common/utilities.js";
|
|
4
3
|
import { builtinsTree, processUnpackedContent } from "../internal.js";
|
|
4
|
+
import getParent from "./getParent.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* An Origami expression file
|
|
@@ -13,16 +13,13 @@ export default {
|
|
|
13
13
|
|
|
14
14
|
/** @type {import("@weborigami/language").UnpackFunction} */
|
|
15
15
|
async unpack(packed, options = {}) {
|
|
16
|
-
const parent =
|
|
17
|
-
options.parent ??
|
|
18
|
-
/** @type {any} */ (packed).parent ??
|
|
19
|
-
/** @type {any} */ (packed)[symbols.parent];
|
|
16
|
+
const parent = getParent(packed, options);
|
|
20
17
|
|
|
21
18
|
// Construct an object to represent the source code.
|
|
22
19
|
const sourceName = options.key;
|
|
23
20
|
let url;
|
|
24
|
-
if (sourceName && parent?.url) {
|
|
25
|
-
let parentHref = parent.url.href;
|
|
21
|
+
if (sourceName && /** @type {any} */ (parent)?.url) {
|
|
22
|
+
let parentHref = /** @type {any} */ (parent).url.href;
|
|
26
23
|
if (!parentHref.endsWith("/")) {
|
|
27
24
|
parentHref += "/";
|
|
28
25
|
}
|
|
@@ -8,6 +8,7 @@ import { compile } from "@weborigami/language";
|
|
|
8
8
|
import { parseYaml } from "../common/serialize.js";
|
|
9
9
|
import { toString } from "../common/utilities.js";
|
|
10
10
|
import { processUnpackedContent } from "../internal.js";
|
|
11
|
+
import getParent from "./getParent.js";
|
|
11
12
|
import parseFrontMatter from "./parseFrontMatter.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -19,11 +20,7 @@ export default {
|
|
|
19
20
|
|
|
20
21
|
/** @type {import("@weborigami/language").UnpackFunction} */
|
|
21
22
|
async unpack(packed, options = {}) {
|
|
22
|
-
const parent =
|
|
23
|
-
options.parent ??
|
|
24
|
-
/** @type {any} */ (packed).parent ??
|
|
25
|
-
/** @type {any} */ (packed)[symbols.parent] ??
|
|
26
|
-
null;
|
|
23
|
+
const parent = getParent(packed, options);
|
|
27
24
|
|
|
28
25
|
// Unpack as a text document
|
|
29
26
|
const unpacked = toString(packed);
|
|
@@ -31,8 +28,8 @@ export default {
|
|
|
31
28
|
// See if we can construct a URL to use in error messages
|
|
32
29
|
const key = options.key;
|
|
33
30
|
let url;
|
|
34
|
-
if (key && parent?.url) {
|
|
35
|
-
let parentHref = parent.url.href;
|
|
31
|
+
if (key && /** @type {any} */ (parent)?.url) {
|
|
32
|
+
let parentHref = /** @type {any} */ (parent).url.href;
|
|
36
33
|
if (!parentHref.endsWith("/")) {
|
|
37
34
|
parentHref += "/";
|
|
38
35
|
}
|
package/src/help/help.yaml
CHANGED
|
@@ -274,6 +274,9 @@ tree:
|
|
|
274
274
|
concat:
|
|
275
275
|
args: (...objs)
|
|
276
276
|
description: Concatenate text and/or trees of text
|
|
277
|
+
constant:
|
|
278
|
+
args: (value)
|
|
279
|
+
description: Return a deep tree with a single constant value
|
|
277
280
|
copy:
|
|
278
281
|
args: (source, target)
|
|
279
282
|
description: Copy the source tree to the target
|
|
@@ -298,6 +301,9 @@ tree:
|
|
|
298
301
|
entries:
|
|
299
302
|
args: (tree)
|
|
300
303
|
description: The tree's [key, value] pairs
|
|
304
|
+
filter:
|
|
305
|
+
args: (source, filter)
|
|
306
|
+
description: Filter the source tree using the filter tree
|
|
301
307
|
first:
|
|
302
308
|
args: (tree)
|
|
303
309
|
description: The first value in the tree
|
|
@@ -310,9 +316,9 @@ tree:
|
|
|
310
316
|
fromFn:
|
|
311
317
|
args: (fn, [keys])
|
|
312
318
|
description: A tree defined by a value function
|
|
313
|
-
|
|
319
|
+
globKeys:
|
|
314
320
|
args: (patterns)
|
|
315
|
-
description: A tree whose keys can include wildcard patterns
|
|
321
|
+
description: A tree whose keys can include glob wildcard patterns
|
|
316
322
|
group:
|
|
317
323
|
args: (tree, fn)
|
|
318
324
|
description: A new tree with values grouped by the function
|
|
@@ -364,6 +370,9 @@ tree:
|
|
|
364
370
|
plain:
|
|
365
371
|
args: (tree)
|
|
366
372
|
description: Render the tree as a plain JavaScript object
|
|
373
|
+
regExpKeys:
|
|
374
|
+
args: (tree)
|
|
375
|
+
description: A tree whose keys are regular expression strings
|
|
367
376
|
remove:
|
|
368
377
|
args: (tree, key)
|
|
369
378
|
description: Remove the value for the key from tree
|
package/src/js.js
CHANGED
package/src/origami/once.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
2
2
|
|
|
3
|
-
const fnPromiseMap = new
|
|
3
|
+
const fnPromiseMap = new Map();
|
|
4
|
+
const codePromiseMap = new Map();
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Evaluate the given function only once and cache the result.
|
|
@@ -11,8 +12,23 @@ const fnPromiseMap = new WeakMap();
|
|
|
11
12
|
*/
|
|
12
13
|
export default async function once(fn) {
|
|
13
14
|
assertTreeIsDefined(this, "origami:once");
|
|
15
|
+
|
|
16
|
+
const code = /** @type {any} */ (fn).code;
|
|
17
|
+
if (code) {
|
|
18
|
+
// Origami function, cache by code
|
|
19
|
+
if (!codePromiseMap.has(code)) {
|
|
20
|
+
// Don't wait for promise to resolve
|
|
21
|
+
const promise = fn.call(this);
|
|
22
|
+
codePromiseMap.set(code, promise);
|
|
23
|
+
}
|
|
24
|
+
return codePromiseMap.get(code);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Regular function, cache by function
|
|
14
28
|
if (!fnPromiseMap.has(fn)) {
|
|
15
|
-
|
|
29
|
+
// Don't wait for promise to resolve
|
|
30
|
+
const promise = fn.call(this);
|
|
31
|
+
fnPromiseMap.set(fn, promise);
|
|
16
32
|
}
|
|
17
33
|
return fnPromiseMap.get(fn);
|
|
18
34
|
}
|
package/src/server/server.js
CHANGED
|
@@ -193,7 +193,8 @@ ${message}
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// Asynchronous tree router as Express middleware.
|
|
196
|
-
export function treeRouter(
|
|
196
|
+
export function treeRouter(treelike) {
|
|
197
|
+
const tree = Tree.from(treelike, { deep: true });
|
|
197
198
|
// Return a router for the tree source.
|
|
198
199
|
return async function (request, response, next) {
|
|
199
200
|
const handled = await handleRequest(request, response, tree);
|
package/src/tree/cache.js
CHANGED
|
@@ -9,19 +9,14 @@ import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
|
9
9
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
10
|
* @param {Treelike} sourceTreelike
|
|
11
11
|
* @param {Treelike} [cacheTreelike]
|
|
12
|
-
* @param {Treelike} [filterTreelike]
|
|
13
12
|
* @this {AsyncTree|null}
|
|
14
13
|
*/
|
|
15
|
-
export default async function cacheBuiltin(
|
|
16
|
-
sourceTreelike,
|
|
17
|
-
cacheTreelike,
|
|
18
|
-
filterTreelike
|
|
19
|
-
) {
|
|
14
|
+
export default async function cacheBuiltin(sourceTreelike, cacheTreelike) {
|
|
20
15
|
assertTreeIsDefined(this, "tree:cache");
|
|
21
16
|
/** @type {any} */
|
|
22
17
|
const cacheTree = cacheTreelike
|
|
23
18
|
? Tree.from(cacheTreelike, { parent: this })
|
|
24
19
|
: undefined;
|
|
25
|
-
const result = cache(sourceTreelike, cacheTree
|
|
20
|
+
const result = cache(sourceTreelike, cacheTree);
|
|
26
21
|
return result;
|
|
27
22
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { constantTree as default } from "@weborigami/async-tree";
|
package/src/tree/deepMerge.js
CHANGED
|
@@ -11,16 +11,8 @@ import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
|
11
11
|
*/
|
|
12
12
|
export default async function treeDeepMerge(...trees) {
|
|
13
13
|
assertTreeIsDefined(this, "tree:deepMerge");
|
|
14
|
-
|
|
15
|
-
// Filter out null or undefined trees.
|
|
16
|
-
const filtered = trees.filter((tree) => tree);
|
|
17
|
-
|
|
18
|
-
if (filtered.length === 1) {
|
|
19
|
-
// Only one tree, no need to merge.
|
|
20
|
-
return filtered[0];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
14
|
// Merge the trees.
|
|
24
|
-
const result = deepMerge(...
|
|
15
|
+
const result = deepMerge(...trees);
|
|
16
|
+
result.parent = this;
|
|
25
17
|
return result;
|
|
26
18
|
}
|
package/src/tree/filter.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { filter } from "@weborigami/async-tree";
|
|
2
2
|
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
3
|
-
import FilterTree from "./FilterTree.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Apply a filter to a tree.
|
|
7
6
|
*
|
|
8
7
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
8
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
9
|
+
*
|
|
10
10
|
* @this {AsyncTree|null}
|
|
11
11
|
* @param {Treelike} sourceTreelike
|
|
12
12
|
* @param {Treelike} filterTreelike
|
|
13
13
|
*/
|
|
14
|
-
export default async function
|
|
14
|
+
export default async function filterBuiltin(sourceTreelike, filterTreelike) {
|
|
15
15
|
assertTreeIsDefined(this, "tree:filter");
|
|
16
|
-
const
|
|
17
|
-
const filterTree = Tree.from(filterTreelike, { deep: true, parent: this });
|
|
18
|
-
const result = new FilterTree(sourceTree, filterTree);
|
|
16
|
+
const result = filter(sourceTreelike, filterTreelike);
|
|
19
17
|
result.parent = this;
|
|
20
18
|
return result;
|
|
21
19
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { setParent } from "@weborigami/async-tree";
|
|
2
|
+
import globKeys from "@weborigami/async-tree/src/operations/globKeys.js";
|
|
1
3
|
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
2
|
-
import GlobTree from "./GlobTree.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Define a tree whose keys are globs.
|
|
@@ -10,8 +11,9 @@ import GlobTree from "./GlobTree.js";
|
|
|
10
11
|
* @param {Treelike} tree
|
|
11
12
|
* @this {AsyncTree|null}
|
|
12
13
|
*/
|
|
13
|
-
export default async function
|
|
14
|
+
export default async function globKeysBuiltin(tree) {
|
|
14
15
|
assertTreeIsDefined(this, "tree:globs");
|
|
15
|
-
const result =
|
|
16
|
+
const result = globKeys(tree);
|
|
17
|
+
setParent(this, result);
|
|
16
18
|
return result;
|
|
17
19
|
}
|
package/src/tree/map.js
CHANGED
|
@@ -21,16 +21,22 @@ import { toFunction } from "../common/utilities.js";
|
|
|
21
21
|
* @param {ValueKeyFn|TreeMapOptions} operation
|
|
22
22
|
*/
|
|
23
23
|
export default async function map(treelike, operation) {
|
|
24
|
-
// The tree we're going to map
|
|
25
|
-
const source = await getTreeArgument(this, arguments, treelike, "tree:map");
|
|
26
|
-
// The tree in which the map operation happens
|
|
27
|
-
const context = this;
|
|
28
|
-
|
|
29
24
|
if (isUnpackable(operation)) {
|
|
30
25
|
operation = await operation.unpack();
|
|
31
26
|
}
|
|
27
|
+
// The tree in which the map operation happens
|
|
28
|
+
const context = this;
|
|
32
29
|
const options = extendedOptions(context, operation);
|
|
33
30
|
|
|
31
|
+
// The tree we're going to map
|
|
32
|
+
const source = await getTreeArgument(
|
|
33
|
+
this,
|
|
34
|
+
arguments,
|
|
35
|
+
treelike,
|
|
36
|
+
"tree:map",
|
|
37
|
+
options?.deep
|
|
38
|
+
);
|
|
39
|
+
|
|
34
40
|
const mapped = mapTransform(source, options);
|
|
35
41
|
mapped.parent = context;
|
|
36
42
|
return mapped;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { setParent } from "@weborigami/async-tree";
|
|
2
|
+
import regExpKeys from "@weborigami/async-tree/src/operations/regExpKeys.js";
|
|
3
|
+
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Define a tree whose keys are regular expression strings.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
|
+
*
|
|
11
|
+
* @param {Treelike} tree
|
|
12
|
+
* @this {AsyncTree|null}
|
|
13
|
+
*/
|
|
14
|
+
export default async function regExpKeysBuiltin(tree) {
|
|
15
|
+
assertTreeIsDefined(this, "tree:globs");
|
|
16
|
+
const result = regExpKeys(tree);
|
|
17
|
+
setParent(this, result);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
package/src/tree/tree.js
CHANGED
|
@@ -4,6 +4,7 @@ export { default as cache } from "./cache.js";
|
|
|
4
4
|
export { default as calendar } from "./calendar.js";
|
|
5
5
|
export { default as clear } from "./clear.js";
|
|
6
6
|
export { default as concat } from "./concat.js";
|
|
7
|
+
export { default as constant } from "./constant.js";
|
|
7
8
|
export { default as copy } from "./copy.js";
|
|
8
9
|
export { default as deepMap } from "./deepMap.js";
|
|
9
10
|
export { default as deepMerge } from "./deepMerge.js";
|
|
@@ -14,7 +15,7 @@ export { default as defineds } from "./defineds.js";
|
|
|
14
15
|
export { default as filter } from "./filter.js";
|
|
15
16
|
export { default as first } from "./first.js";
|
|
16
17
|
export { default as fromFn } from "./fromFn.js";
|
|
17
|
-
export { default as
|
|
18
|
+
export { default as globKeys } from "./globKeys.js";
|
|
18
19
|
export { default as group } from "./group.js";
|
|
19
20
|
export { default as inners } from "./inners.js";
|
|
20
21
|
export { default as keys } from "./keys.js";
|
|
@@ -25,6 +26,7 @@ export { default as merge } from "./merge.js";
|
|
|
25
26
|
export { default as paginate } from "./paginate.js";
|
|
26
27
|
export { default as parent } from "./parent.js";
|
|
27
28
|
export { default as plain } from "./plain.js";
|
|
29
|
+
export { default as regExpKeys } from "./regExpKeys.js";
|
|
28
30
|
export { default as reverse } from "./reverse.js";
|
|
29
31
|
export { default as setDeep } from "./setDeep.js";
|
|
30
32
|
export { default as shuffle } from "./shuffle.js";
|
package/src/tree/FilterTree.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { trailingSlash, Tree } from "@weborigami/async-tree";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
5
|
-
* @implements {AsyncTree}
|
|
6
|
-
*/
|
|
7
|
-
export default class FilterTree {
|
|
8
|
-
constructor(tree, filter) {
|
|
9
|
-
this.tree = Tree.from(tree);
|
|
10
|
-
this.filter = Tree.from(filter, { deep: true });
|
|
11
|
-
this.parent = null;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async get(key) {
|
|
15
|
-
let value = await this.tree.get(key);
|
|
16
|
-
|
|
17
|
-
let filterValue = await this.filter.get(key);
|
|
18
|
-
if (!Tree.isAsyncTree(value)) {
|
|
19
|
-
if (filterValue === undefined) {
|
|
20
|
-
value = undefined;
|
|
21
|
-
} else if (Tree.isAsyncTree(filterValue)) {
|
|
22
|
-
value = undefined;
|
|
23
|
-
}
|
|
24
|
-
} else if (Tree.isAsyncTree(filterValue)) {
|
|
25
|
-
// Wrap value with corresponding filter.
|
|
26
|
-
value = Reflect.construct(this.constructor, [value, filterValue]);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return value;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async keys() {
|
|
33
|
-
const keys = new Set();
|
|
34
|
-
|
|
35
|
-
// Enumerate all keys in the tree that can be found in the filter tree.
|
|
36
|
-
for (const key of await this.tree.keys()) {
|
|
37
|
-
const filterValue = await this.filter.get(key);
|
|
38
|
-
const isFilterValueTree = Tree.isAsyncTree(filterValue);
|
|
39
|
-
// If the filter value is a tree, the corresponding value in the tree
|
|
40
|
-
// must be a tree too.
|
|
41
|
-
const match =
|
|
42
|
-
(!isFilterValueTree && filterValue) ||
|
|
43
|
-
(isFilterValueTree && trailingSlash.has(key));
|
|
44
|
-
if (match) {
|
|
45
|
-
keys.add(key);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Also include any keys in the filter that are found in the tree. This
|
|
50
|
-
// lets the filter "pull" values from a tree that, e.g., is defined by a
|
|
51
|
-
// function without an explicit domain.
|
|
52
|
-
// for (const key of await this.filter.keys()) {
|
|
53
|
-
// const value = await this.tree.get(key);
|
|
54
|
-
// if (value !== undefined) {
|
|
55
|
-
// keys.add(key);
|
|
56
|
-
// }
|
|
57
|
-
// }
|
|
58
|
-
|
|
59
|
-
return keys;
|
|
60
|
-
}
|
|
61
|
-
}
|
package/src/tree/GlobTree.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { ObjectTree, Tree, merge, trailingSlash } from "@weborigami/async-tree";
|
|
2
|
-
|
|
3
|
-
const globstar = "**";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
7
|
-
* @implements {AsyncTree}
|
|
8
|
-
*/
|
|
9
|
-
export default class GlobTree {
|
|
10
|
-
constructor(globs) {
|
|
11
|
-
this.globs = Tree.from(globs, { deep: true });
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async get(key) {
|
|
15
|
-
if (typeof key !== "string") {
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Remove trailing slash if it exists
|
|
20
|
-
key = trailingSlash.remove(key);
|
|
21
|
-
|
|
22
|
-
let value = await matchGlobs(this.globs, key);
|
|
23
|
-
if (Tree.isAsyncTree(value)) {
|
|
24
|
-
value = Reflect.construct(this.constructor, [value]);
|
|
25
|
-
}
|
|
26
|
-
return value;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async keys() {
|
|
30
|
-
return this.globs.keys();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Convert the glob to a regular expression
|
|
35
|
-
function matchGlob(glob, text) {
|
|
36
|
-
const regexText = glob
|
|
37
|
-
// Escape special regex characters
|
|
38
|
-
.replace(/[+?^${}()|\[\]\\]/g, "\\$&")
|
|
39
|
-
// Replace the glob wildcards with regex wildcards
|
|
40
|
-
.replace(/\*/g, ".+")
|
|
41
|
-
.replace(/\?/g, ".");
|
|
42
|
-
const regex = new RegExp(`^${regexText}$`);
|
|
43
|
-
return regex.test(text);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function matchGlobs(globs, text) {
|
|
47
|
-
let value;
|
|
48
|
-
for (let glob of await globs.keys()) {
|
|
49
|
-
if (typeof glob !== "string") {
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Remove trailing slash if it exists
|
|
54
|
-
glob = trailingSlash.remove(glob);
|
|
55
|
-
|
|
56
|
-
if (glob !== globstar && matchGlob(glob, text)) {
|
|
57
|
-
value = await globs.get(glob);
|
|
58
|
-
if (value !== undefined) {
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const globstarGlobs = await globs.get(globstar);
|
|
65
|
-
if (globstarGlobs) {
|
|
66
|
-
const globstarTree = new ObjectTree({ [globstar]: globstarGlobs });
|
|
67
|
-
if (value === undefined) {
|
|
68
|
-
const globstarValue = await matchGlobs(globstarGlobs, text);
|
|
69
|
-
value = globstarValue !== undefined ? globstarValue : globstarTree;
|
|
70
|
-
} else if (Tree.isAsyncTree(value)) {
|
|
71
|
-
value = merge(value, globstarTree);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return value;
|
|
76
|
-
}
|