@weborigami/async-tree 0.0.66-beta.1 → 0.0.66
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 +2 -0
- package/package.json +4 -4
- package/src/BrowserFileTree.js +28 -6
- package/src/DeepMapTree.js +2 -2
- package/src/DeepObjectTree.js +6 -9
- package/src/DeferredTree.js +4 -2
- package/src/ExplorableSiteTree.js +52 -0
- package/src/FileTree.js +14 -10
- package/src/MapTree.js +27 -4
- package/src/ObjectTree.js +53 -6
- package/src/SetTree.js +0 -6
- package/src/SiteTree.js +32 -85
- package/src/Tree.d.ts +0 -1
- package/src/Tree.js +24 -41
- package/src/jsonKeys.js +4 -37
- package/src/operations/cache.js +0 -4
- package/src/operations/deepMerge.js +7 -10
- package/src/operations/merge.js +7 -10
- package/src/trailingSlash.js +54 -0
- package/src/transforms/cachedKeyFunctions.js +72 -34
- package/src/transforms/keyFunctionsForExtensions.js +24 -10
- package/src/transforms/mapFn.js +11 -17
- package/src/transforms/regExpKeys.js +17 -12
- package/src/utilities.js +34 -6
- package/test/BrowserFileTree.test.js +28 -5
- package/test/DeepMapTree.test.js +17 -0
- package/test/DeepObjectTree.test.js +17 -7
- package/test/ExplorableSiteTree.test.js +113 -0
- package/test/FileTree.test.js +14 -7
- package/test/MapTree.test.js +21 -0
- package/test/ObjectTree.test.js +16 -12
- package/test/SiteTree.test.js +14 -49
- package/test/Tree.test.js +19 -39
- package/test/browser/assert.js +9 -0
- package/test/browser/index.html +4 -4
- package/test/calendarTree.test.js +1 -1
- package/test/fixtures/markdown/subfolder/README.md +1 -0
- package/test/jsonKeys.test.js +0 -9
- package/test/operations/cache.test.js +1 -1
- package/test/operations/merge.test.js +20 -1
- package/test/trailingSlash.test.js +36 -0
- package/test/transforms/cachedKeyFunctions.test.js +90 -0
- package/test/transforms/keyFunctionsForExtensions.test.js +7 -3
- package/test/transforms/mapFn.test.js +29 -20
- package/test/utilities.test.js +6 -2
- package/test/transforms/cachedKeyMaps.test.js +0 -41
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import { toPlainValue } from "../main.js";
|
|
4
3
|
import calendarTree from "../src/calendarTree.js";
|
|
4
|
+
import { toPlainValue } from "../src/utilities.js";
|
|
5
5
|
|
|
6
6
|
describe("calendarTree", () => {
|
|
7
7
|
test("without a start or end, returns a tree for today", async () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This file exists to force the creation of the parent folder.
|
package/test/jsonKeys.test.js
CHANGED
|
@@ -4,15 +4,6 @@ import { describe, test } from "node:test";
|
|
|
4
4
|
import * as jsonKeys from "../src/jsonKeys.js";
|
|
5
5
|
|
|
6
6
|
describe("jsonKeys", () => {
|
|
7
|
-
test("parses JSON Keys", async () => {
|
|
8
|
-
const json = '["index.html","about/"]';
|
|
9
|
-
const parsed = jsonKeys.parse(json);
|
|
10
|
-
assert.deepStrictEqual(parsed, {
|
|
11
|
-
"index.html": false,
|
|
12
|
-
about: true,
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
7
|
test("stringifies JSON Keys", async () => {
|
|
17
8
|
const tree = new DeepObjectTree({
|
|
18
9
|
about: {},
|
|
@@ -19,7 +19,7 @@ describe("cache", () => {
|
|
|
19
19
|
);
|
|
20
20
|
|
|
21
21
|
const keys = [...(await fixture.keys())];
|
|
22
|
-
assert.deepEqual(keys, ["a", "b", "c", "more"]);
|
|
22
|
+
assert.deepEqual(keys, ["a", "b", "c", "more/"]);
|
|
23
23
|
|
|
24
24
|
assert.equal(await objectCache.get("a"), undefined);
|
|
25
25
|
assert.equal(await fixture.get("a"), 1);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import { Tree } from "../../src/internal.js";
|
|
3
|
+
import { DeepObjectTree, ObjectTree, Tree } from "../../src/internal.js";
|
|
4
4
|
import merge from "../../src/operations/merge.js";
|
|
5
5
|
import * as symbols from "../../src/symbols.js";
|
|
6
6
|
|
|
@@ -42,4 +42,23 @@ describe("merge", () => {
|
|
|
42
42
|
const b = await fixture.get("b");
|
|
43
43
|
assert.equal(b[symbols.parent], fixture);
|
|
44
44
|
});
|
|
45
|
+
|
|
46
|
+
test("subtree can overwrite a leaf node", async () => {
|
|
47
|
+
const fixture = merge(
|
|
48
|
+
new ObjectTree({
|
|
49
|
+
a: 1,
|
|
50
|
+
}),
|
|
51
|
+
new DeepObjectTree({
|
|
52
|
+
a: {
|
|
53
|
+
b: 2,
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
assert.deepEqual([...(await fixture.keys())], ["a/"]);
|
|
58
|
+
assert.deepEqual(await Tree.plain(fixture), {
|
|
59
|
+
a: {
|
|
60
|
+
b: 2,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
});
|
|
45
64
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import { add, has, remove, toggle } from "../src/trailingSlash.js";
|
|
4
|
+
|
|
5
|
+
describe("trailingSlash", () => {
|
|
6
|
+
test("add adds a trailing slash to a string key for a truthy value", () => {
|
|
7
|
+
assert.equal(add("key"), "key/");
|
|
8
|
+
assert.equal(add("key/"), "key/");
|
|
9
|
+
assert.equal(add(1), 1);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("has returns true if a string key has a trailing slash", () => {
|
|
13
|
+
assert.equal(has("key/"), true);
|
|
14
|
+
assert.equal(has("key"), false);
|
|
15
|
+
assert.equal(has(1), false);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("remove removes a trailing slash from a string key", () => {
|
|
19
|
+
assert.equal(remove("key/"), "key");
|
|
20
|
+
assert.equal(remove("key"), "key");
|
|
21
|
+
assert.equal(remove(1), 1);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("toggle removes a slash if present, adds one if not", () => {
|
|
25
|
+
assert.equal(toggle("key/"), "key");
|
|
26
|
+
assert.equal(toggle("key"), "key/");
|
|
27
|
+
assert.equal(toggle(1), 1);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("toggle can force toggling on or off", () => {
|
|
31
|
+
assert.equal(toggle("key/", false), "key");
|
|
32
|
+
assert.equal(toggle("key/", true), "key/");
|
|
33
|
+
assert.equal(toggle("key", false), "key");
|
|
34
|
+
assert.equal(toggle("key", true), "key/");
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import { DeepObjectTree, ObjectTree } from "../../src/internal.js";
|
|
4
|
+
import cachedKeyFunctions from "../../src/transforms/cachedKeyFunctions.js";
|
|
5
|
+
|
|
6
|
+
describe("cachedKeyFunctions", () => {
|
|
7
|
+
test("maps keys with caching", async () => {
|
|
8
|
+
const tree = new ObjectTree({
|
|
9
|
+
a: "letter a",
|
|
10
|
+
b: "letter b",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
let callCount = 0;
|
|
14
|
+
const addUnderscore = async (sourceKey, tree) => {
|
|
15
|
+
callCount++;
|
|
16
|
+
return `_${sourceKey}`;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const { inverseKey, key } = cachedKeyFunctions(addUnderscore);
|
|
20
|
+
|
|
21
|
+
assert.equal(await inverseKey("_a", tree), "a"); // Cache miss
|
|
22
|
+
assert.equal(callCount, 1);
|
|
23
|
+
assert.equal(await inverseKey("_a", tree), "a");
|
|
24
|
+
assert.equal(callCount, 1);
|
|
25
|
+
assert.equal(await inverseKey("_b", tree), "b"); // Cache miss
|
|
26
|
+
assert.equal(callCount, 2);
|
|
27
|
+
|
|
28
|
+
assert.equal(await key("a", tree), "_a");
|
|
29
|
+
assert.equal(await key("a", tree), "_a");
|
|
30
|
+
assert.equal(await key("b", tree), "_b");
|
|
31
|
+
assert.equal(callCount, 2);
|
|
32
|
+
|
|
33
|
+
// `c` isn't in tree, so we should get undefined.
|
|
34
|
+
assert.equal(await inverseKey("_c", tree), undefined);
|
|
35
|
+
// But key mapping is still possible.
|
|
36
|
+
assert.equal(await key("c", tree), "_c");
|
|
37
|
+
// And now we have a cache hit.
|
|
38
|
+
assert.equal(await inverseKey("_c", tree), "c");
|
|
39
|
+
assert.equal(callCount, 3);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("maps keys with caching and deep option", async () => {
|
|
43
|
+
const tree = new DeepObjectTree({
|
|
44
|
+
a: "letter a",
|
|
45
|
+
b: {
|
|
46
|
+
c: "letter c",
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
let callCount = 0;
|
|
51
|
+
const addUnderscore = async (sourceKey, tree) => {
|
|
52
|
+
callCount++;
|
|
53
|
+
return `_${sourceKey}`;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const { inverseKey, key } = cachedKeyFunctions(addUnderscore, true);
|
|
57
|
+
|
|
58
|
+
assert.equal(await inverseKey("_a", tree), "a"); // Cache miss
|
|
59
|
+
assert.equal(await inverseKey("_a", tree), "a");
|
|
60
|
+
assert.equal(callCount, 1);
|
|
61
|
+
|
|
62
|
+
// Subtree key left alone
|
|
63
|
+
assert.equal(await inverseKey("_b", tree), undefined);
|
|
64
|
+
assert.equal(await inverseKey("b", tree), "b");
|
|
65
|
+
assert.equal(await inverseKey("b/", tree), "b/");
|
|
66
|
+
assert.equal(callCount, 1);
|
|
67
|
+
|
|
68
|
+
assert.equal(await key("a", tree), "_a");
|
|
69
|
+
assert.equal(await key("a", tree), "_a");
|
|
70
|
+
assert.equal(callCount, 1);
|
|
71
|
+
|
|
72
|
+
assert.equal(await key("b/", tree), "b/");
|
|
73
|
+
assert.equal(await key("b", tree), "b");
|
|
74
|
+
assert.equal(callCount, 1);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("preserves trailing slashes", async () => {
|
|
78
|
+
const tree = new ObjectTree({
|
|
79
|
+
a: "letter a",
|
|
80
|
+
});
|
|
81
|
+
const addUnderscore = async (sourceKey) => `_${sourceKey}`;
|
|
82
|
+
const { inverseKey, key } = cachedKeyFunctions(addUnderscore);
|
|
83
|
+
|
|
84
|
+
assert.equal(await key("a/", tree), "_a/");
|
|
85
|
+
assert.equal(await key("a", tree), "_a");
|
|
86
|
+
|
|
87
|
+
assert.equal(await inverseKey("_a/", tree), "a/");
|
|
88
|
+
assert.equal(await inverseKey("_a", tree), "a");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -10,18 +10,22 @@ describe("keyMapsForExtensions", () => {
|
|
|
10
10
|
sourceExtension: "txt",
|
|
11
11
|
});
|
|
12
12
|
assert.equal(await inverseKey("file.txt"), "file.txt");
|
|
13
|
+
assert.equal(await inverseKey("file.txt/"), "file.txt");
|
|
13
14
|
assert.equal(await key("file.txt"), "file.txt");
|
|
15
|
+
assert.equal(await key("file.txt/"), "file.txt/");
|
|
14
16
|
assert.equal(await inverseKey("file.foo"), undefined);
|
|
15
17
|
assert.equal(await key("file.foo"), undefined);
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
test("returns key functions that can map extensions", async () => {
|
|
19
21
|
const { inverseKey, key } = keyFunctionsForExtensions({
|
|
20
|
-
resultExtension: "
|
|
22
|
+
resultExtension: "json",
|
|
21
23
|
sourceExtension: "md",
|
|
22
24
|
});
|
|
23
|
-
assert.equal(await inverseKey("file.
|
|
24
|
-
assert.equal(await
|
|
25
|
+
assert.equal(await inverseKey("file.json"), "file.md");
|
|
26
|
+
assert.equal(await inverseKey("file.json/"), "file.md");
|
|
27
|
+
assert.equal(await key("file.md"), "file.json");
|
|
28
|
+
assert.equal(await key("file.md/"), "file.json/");
|
|
25
29
|
assert.equal(await inverseKey("file.foo"), undefined);
|
|
26
30
|
assert.equal(await key("file.foo"), undefined);
|
|
27
31
|
});
|
|
@@ -2,6 +2,7 @@ import assert from "node:assert";
|
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
import FunctionTree from "../../src/FunctionTree.js";
|
|
4
4
|
import { DeepObjectTree, ObjectTree, Tree } from "../../src/internal.js";
|
|
5
|
+
import * as trailingSlash from "../../src/trailingSlash.js";
|
|
5
6
|
import mapFn from "../../src/transforms/mapFn.js";
|
|
6
7
|
|
|
7
8
|
describe("mapFn", () => {
|
|
@@ -59,11 +60,11 @@ describe("mapFn", () => {
|
|
|
59
60
|
a: "letter a",
|
|
60
61
|
b: "letter b",
|
|
61
62
|
};
|
|
62
|
-
const
|
|
63
|
-
key:
|
|
64
|
-
inverseKey:
|
|
63
|
+
const underscopeKeys = mapFn({
|
|
64
|
+
key: addUnderscore,
|
|
65
|
+
inverseKey: removeUnderscore,
|
|
65
66
|
});
|
|
66
|
-
const mapped =
|
|
67
|
+
const mapped = underscopeKeys(tree);
|
|
67
68
|
assert.deepEqual(await Tree.plain(mapped), {
|
|
68
69
|
_a: "letter a",
|
|
69
70
|
_b: "letter b",
|
|
@@ -75,12 +76,12 @@ describe("mapFn", () => {
|
|
|
75
76
|
a: "letter a",
|
|
76
77
|
b: "letter b",
|
|
77
78
|
};
|
|
78
|
-
const
|
|
79
|
-
key:
|
|
80
|
-
inverseKey:
|
|
79
|
+
const underscoreKeysUppercaseValues = mapFn({
|
|
80
|
+
key: addUnderscore,
|
|
81
|
+
inverseKey: removeUnderscore,
|
|
81
82
|
value: async (sourceValue, sourceKey, tree) => sourceValue.toUpperCase(),
|
|
82
83
|
});
|
|
83
|
-
const mapped =
|
|
84
|
+
const mapped = underscoreKeysUppercaseValues(tree);
|
|
84
85
|
assert.deepEqual(await Tree.plain(mapped), {
|
|
85
86
|
_a: "LETTER A",
|
|
86
87
|
_b: "LETTER B",
|
|
@@ -94,12 +95,12 @@ describe("mapFn", () => {
|
|
|
94
95
|
b: "letter b",
|
|
95
96
|
},
|
|
96
97
|
};
|
|
97
|
-
const
|
|
98
|
+
const underscopeKeys = mapFn({
|
|
98
99
|
key: async (sourceKey, tree) => `_${sourceKey}`,
|
|
99
100
|
inverseKey: async (resultKey, tree) => resultKey.slice(1),
|
|
100
101
|
value: async (sourceValue, sourceKey, tree) => sourceKey,
|
|
101
102
|
});
|
|
102
|
-
const mapped =
|
|
103
|
+
const mapped = underscopeKeys(tree);
|
|
103
104
|
assert.deepEqual(await Tree.plain(mapped), {
|
|
104
105
|
_a: "a",
|
|
105
106
|
_more: "more",
|
|
@@ -108,8 +109,8 @@ describe("mapFn", () => {
|
|
|
108
109
|
|
|
109
110
|
test("value can provide a default key and inverse key functions", async () => {
|
|
110
111
|
const uppercase = (s) => s.toUpperCase();
|
|
111
|
-
uppercase.key =
|
|
112
|
-
uppercase.inverseKey =
|
|
112
|
+
uppercase.key = addUnderscore;
|
|
113
|
+
uppercase.inverseKey = removeUnderscore;
|
|
113
114
|
const tree = {
|
|
114
115
|
a: "letter a",
|
|
115
116
|
b: "letter b",
|
|
@@ -148,12 +149,12 @@ describe("mapFn", () => {
|
|
|
148
149
|
b: "letter b",
|
|
149
150
|
},
|
|
150
151
|
});
|
|
151
|
-
const
|
|
152
|
+
const underscoreKeys = mapFn({
|
|
152
153
|
deep: true,
|
|
153
|
-
key:
|
|
154
|
-
inverseKey:
|
|
154
|
+
key: addUnderscore,
|
|
155
|
+
inverseKey: removeUnderscore,
|
|
155
156
|
});
|
|
156
|
-
const mapped =
|
|
157
|
+
const mapped = underscoreKeys(tree);
|
|
157
158
|
assert.deepEqual(await Tree.plain(mapped), {
|
|
158
159
|
_a: "letter a",
|
|
159
160
|
more: {
|
|
@@ -169,13 +170,13 @@ describe("mapFn", () => {
|
|
|
169
170
|
b: "letter b",
|
|
170
171
|
},
|
|
171
172
|
});
|
|
172
|
-
const
|
|
173
|
+
const underscoreKeysUppercaseValues = mapFn({
|
|
173
174
|
deep: true,
|
|
174
|
-
key:
|
|
175
|
-
inverseKey:
|
|
175
|
+
key: addUnderscore,
|
|
176
|
+
inverseKey: removeUnderscore,
|
|
176
177
|
value: async (sourceValue, sourceKey, tree) => sourceValue.toUpperCase(),
|
|
177
178
|
});
|
|
178
|
-
const mapped =
|
|
179
|
+
const mapped = underscoreKeysUppercaseValues(tree);
|
|
179
180
|
assert.deepEqual(await Tree.plain(mapped), {
|
|
180
181
|
_a: "LETTER A",
|
|
181
182
|
more: {
|
|
@@ -201,3 +202,11 @@ describe("mapFn", () => {
|
|
|
201
202
|
assert(!flag);
|
|
202
203
|
});
|
|
203
204
|
});
|
|
205
|
+
|
|
206
|
+
function addUnderscore(key) {
|
|
207
|
+
return `_${key}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function removeUnderscore(key) {
|
|
211
|
+
return trailingSlash.has(key) ? key : key.slice(1);
|
|
212
|
+
}
|
package/test/utilities.test.js
CHANGED
|
@@ -41,8 +41,12 @@ describe("utilities", () => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
test("keysFromPath() returns the keys from a slash-separated path", () => {
|
|
44
|
-
assert.deepEqual(utilities.keysFromPath("
|
|
45
|
-
assert.deepEqual(utilities.keysFromPath("
|
|
44
|
+
assert.deepEqual(utilities.keysFromPath(""), []);
|
|
45
|
+
assert.deepEqual(utilities.keysFromPath("/"), []);
|
|
46
|
+
assert.deepEqual(utilities.keysFromPath("a/b/c"), ["a/", "b/", "c"]);
|
|
47
|
+
assert.deepEqual(utilities.keysFromPath("a/b/c/"), ["a/", "b/", "c/"]);
|
|
48
|
+
assert.deepEqual(utilities.keysFromPath("/foo/"), ["foo/"]);
|
|
49
|
+
assert.deepEqual(utilities.keysFromPath("a///b"), ["a/", "b"]);
|
|
46
50
|
});
|
|
47
51
|
|
|
48
52
|
test("naturalOrder compares strings in natural order", () => {
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import { describe, test } from "node:test";
|
|
3
|
-
import { ObjectTree } from "../../src/internal.js";
|
|
4
|
-
import cachedKeyFunctions from "../../src/transforms/cachedKeyFunctions.js";
|
|
5
|
-
|
|
6
|
-
describe("cachedKeyFunctions", () => {
|
|
7
|
-
test("maps keys with caching", async () => {
|
|
8
|
-
const tree = new ObjectTree({
|
|
9
|
-
a: "letter a",
|
|
10
|
-
b: "letter b",
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
let callCount = 0;
|
|
14
|
-
const underscoreKeys = async (sourceKey, tree) => {
|
|
15
|
-
callCount++;
|
|
16
|
-
return `_${sourceKey}`;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const { inverseKey, key } = cachedKeyFunctions(underscoreKeys);
|
|
20
|
-
|
|
21
|
-
assert.equal(await inverseKey("_a", tree), "a"); // Cache miss
|
|
22
|
-
assert.equal(callCount, 1);
|
|
23
|
-
assert.equal(await inverseKey("_a", tree), "a");
|
|
24
|
-
assert.equal(callCount, 1);
|
|
25
|
-
assert.equal(await inverseKey("_b", tree), "b"); // Cache miss
|
|
26
|
-
assert.equal(callCount, 2);
|
|
27
|
-
|
|
28
|
-
assert.equal(await key("a", tree), "_a");
|
|
29
|
-
assert.equal(await key("a", tree), "_a");
|
|
30
|
-
assert.equal(await key("b", tree), "_b");
|
|
31
|
-
assert.equal(callCount, 2);
|
|
32
|
-
|
|
33
|
-
// `c` isn't in tree, so we should get undefined.
|
|
34
|
-
assert.equal(await inverseKey("_c", tree), undefined);
|
|
35
|
-
// But key mapping is still possible.
|
|
36
|
-
assert.equal(await key("c", tree), "_c");
|
|
37
|
-
// And now we have a cache hit.
|
|
38
|
-
assert.equal(await inverseKey("_c", tree), "c");
|
|
39
|
-
assert.equal(callCount, 3);
|
|
40
|
-
});
|
|
41
|
-
});
|