@weborigami/language 0.6.13 → 0.6.14
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/language",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.14",
|
|
4
4
|
"description": "Web Origami expression language compiler and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./main.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"typescript": "5.9.3"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@weborigami/async-tree": "0.6.
|
|
14
|
+
"@weborigami/async-tree": "0.6.14",
|
|
15
15
|
"exif-parser": "0.1.12",
|
|
16
16
|
"watcher": "2.3.1",
|
|
17
17
|
"yaml": "2.8.2"
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isPlainObject,
|
|
3
|
+
isUnpackable,
|
|
4
|
+
symbols,
|
|
5
|
+
trailingSlash,
|
|
6
|
+
Tree,
|
|
7
|
+
} from "@weborigami/async-tree";
|
|
2
8
|
import assignPropertyDescriptors from "./assignPropertyDescriptors.js";
|
|
3
9
|
|
|
4
10
|
/**
|
|
@@ -28,11 +34,48 @@ export default async function mergeTrees(...trees) {
|
|
|
28
34
|
|
|
29
35
|
// If all trees are plain objects, return a plain object.
|
|
30
36
|
if (unpacked.every((tree) => isPlainObject(tree) && !Tree.isMap(tree))) {
|
|
31
|
-
|
|
32
|
-
return assignPropertyDescriptors({}, ...unpacked);
|
|
37
|
+
return mergePlainObjects(...unpacked);
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
// Merge the trees.
|
|
36
41
|
const result = Tree.merge(...unpacked);
|
|
37
42
|
return result;
|
|
38
43
|
}
|
|
44
|
+
|
|
45
|
+
// Return the merged keys for the given objects, respecting any keys method on
|
|
46
|
+
// objects that were created using Origami object literals. This preserves
|
|
47
|
+
// trailing slashes.
|
|
48
|
+
function mergeObjectKeys(objects) {
|
|
49
|
+
const mergedKeys = new Set();
|
|
50
|
+
for (const obj of objects) {
|
|
51
|
+
const objectKeys =
|
|
52
|
+
typeof obj[symbols.keys] === "function"
|
|
53
|
+
? obj[symbols.keys]()
|
|
54
|
+
: Object.keys(obj);
|
|
55
|
+
for (const key of objectKeys) {
|
|
56
|
+
const alternateKey = trailingSlash.toggle(key);
|
|
57
|
+
if (mergedKeys.has(alternateKey)) {
|
|
58
|
+
// The new key differs from a key from an earlier object key only by the
|
|
59
|
+
// presence or absence of a trailing slash. Replace that old key.
|
|
60
|
+
mergedKeys.delete(alternateKey);
|
|
61
|
+
}
|
|
62
|
+
mergedKeys.add(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return Array.from(mergedKeys);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function mergePlainObjects(...objects) {
|
|
69
|
+
// Use our Object.assign variation that avoids invoking property getters.
|
|
70
|
+
const result = assignPropertyDescriptors({}, ...objects);
|
|
71
|
+
|
|
72
|
+
// Attach a keys method
|
|
73
|
+
Object.defineProperty(result, symbols.keys, {
|
|
74
|
+
configurable: true,
|
|
75
|
+
enumerable: false,
|
|
76
|
+
value: () => mergeObjectKeys(objects),
|
|
77
|
+
writable: true,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return result;
|
|
81
|
+
}
|
package/src/runtime/ops.js
CHANGED
|
@@ -173,12 +173,12 @@ export function exponentiation(a, b) {
|
|
|
173
173
|
addOpLabel(exponentiation, "«ops.exponentiation»");
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
|
-
* Flatten the values of the given trees
|
|
176
|
+
* Flatten the values of the given trees by one level.
|
|
177
177
|
*
|
|
178
178
|
* @param {...any} args
|
|
179
179
|
*/
|
|
180
180
|
export async function flat(...args) {
|
|
181
|
-
return Tree.flat(args
|
|
181
|
+
return Tree.flat(args);
|
|
182
182
|
}
|
|
183
183
|
addOpLabel(flat, "«ops.flat»");
|
|
184
184
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ObjectMap, Tree } from "@weborigami/async-tree";
|
|
1
|
+
import { ObjectMap, symbols, Tree } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
import mergeTrees from "../../src/runtime/mergeTrees.js";
|
|
@@ -23,7 +23,7 @@ describe("mergeTrees", () => {
|
|
|
23
23
|
calledBar = true;
|
|
24
24
|
return true;
|
|
25
25
|
},
|
|
26
|
-
}
|
|
26
|
+
},
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
// Shouldn't call functions when just getting keys
|
|
@@ -40,6 +40,22 @@ describe("mergeTrees", () => {
|
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
test("respects trailing slashes in keys", async () => {
|
|
44
|
+
const result = await mergeTrees(
|
|
45
|
+
{
|
|
46
|
+
"a/": 1, // key will be overwritten
|
|
47
|
+
b: 2, // key will be overwritten
|
|
48
|
+
c: 3,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
a: 4,
|
|
52
|
+
"b/": 5,
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
const keys = result[symbols.keys]();
|
|
56
|
+
assert.deepEqual(keys, ["c", "a", "b/"]);
|
|
57
|
+
});
|
|
58
|
+
|
|
43
59
|
test("merges heterogenous arguments as trees", async () => {
|
|
44
60
|
const tree = await mergeTrees(
|
|
45
61
|
new ObjectMap({
|
|
@@ -49,7 +65,7 @@ describe("mergeTrees", () => {
|
|
|
49
65
|
{
|
|
50
66
|
b: 3,
|
|
51
67
|
c: 4,
|
|
52
|
-
}
|
|
68
|
+
},
|
|
53
69
|
);
|
|
54
70
|
assert.deepEqual(await Tree.plain(tree), {
|
|
55
71
|
a: 1,
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -159,7 +159,14 @@ describe("ops", () => {
|
|
|
159
159
|
});
|
|
160
160
|
const array = [5, 6];
|
|
161
161
|
const result = await ops.flat(object, tree, array);
|
|
162
|
-
assert.deepEqual(result,
|
|
162
|
+
assert.deepEqual(await Tree.plain(result), {
|
|
163
|
+
a: 1,
|
|
164
|
+
b: 2,
|
|
165
|
+
c: 3,
|
|
166
|
+
d: 4,
|
|
167
|
+
0: 5,
|
|
168
|
+
1: 6,
|
|
169
|
+
});
|
|
163
170
|
});
|
|
164
171
|
});
|
|
165
172
|
|