@weborigami/origami 0.2.12 → 0.3.1
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 +4 -4
- package/src/help/help.yaml +5 -2
- package/src/origami/csv.js +6 -1
- package/src/tree/filter.js +1 -1
- package/src/tree/map.js +7 -29
- package/src/tree/mask.js +19 -0
- package/src/tree/tree.js +1 -0
- package/src/tree/parseExtensions.js +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/origami",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Web Origami language, CLI, framework, and server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"typescript": "5.8.2"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@weborigami/async-tree": "0.
|
|
21
|
-
"@weborigami/language": "0.
|
|
20
|
+
"@weborigami/async-tree": "0.3.1",
|
|
21
|
+
"@weborigami/language": "0.3.1",
|
|
22
22
|
"@weborigami/json-feed-to-rss": "1.0.0",
|
|
23
|
-
"@weborigami/types": "0.
|
|
23
|
+
"@weborigami/types": "0.3.1",
|
|
24
24
|
"exif-parser": "0.1.12",
|
|
25
25
|
"graphviz-wasm": "3.0.2",
|
|
26
26
|
"highlight.js": "11.11.1",
|
package/src/help/help.yaml
CHANGED
|
@@ -302,8 +302,8 @@ tree:
|
|
|
302
302
|
args: (tree)
|
|
303
303
|
description: The tree's [key, value] pairs
|
|
304
304
|
filter:
|
|
305
|
-
args: (source,
|
|
306
|
-
description: Filter the source tree
|
|
305
|
+
args: (source, options)
|
|
306
|
+
description: Filter the source tree
|
|
307
307
|
first:
|
|
308
308
|
args: (tree)
|
|
309
309
|
description: The first value in the tree
|
|
@@ -352,6 +352,9 @@ tree:
|
|
|
352
352
|
mapReduce:
|
|
353
353
|
args: (tree, valueFn, reduceFn)
|
|
354
354
|
description: Map values and reduce them
|
|
355
|
+
mask:
|
|
356
|
+
args: (source, mask)
|
|
357
|
+
description: Return the source tree with only the keys in the mask
|
|
355
358
|
match:
|
|
356
359
|
args: (pattern, fn, [keys])
|
|
357
360
|
description: Matches simple patterns or regular expressions
|
package/src/origami/csv.js
CHANGED
|
@@ -12,11 +12,16 @@ import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
|
12
12
|
*/
|
|
13
13
|
export default async function csv(object) {
|
|
14
14
|
assertTreeIsDefined(this, "origami:csv");
|
|
15
|
+
object = object ?? this;
|
|
16
|
+
if (object === undefined) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
15
19
|
if (isUnpackable(object)) {
|
|
16
20
|
object = await object.unpack();
|
|
17
21
|
}
|
|
18
22
|
const value = await toPlainValue(object);
|
|
19
|
-
const
|
|
23
|
+
const array = Array.isArray(value) ? value : Object.values(value);
|
|
24
|
+
const text = formatCsv(array);
|
|
20
25
|
return text;
|
|
21
26
|
}
|
|
22
27
|
|
package/src/tree/filter.js
CHANGED
|
@@ -2,7 +2,7 @@ import { filter } from "@weborigami/async-tree";
|
|
|
2
2
|
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Apply a filter to a tree
|
|
5
|
+
* Apply a filter to a tree
|
|
6
6
|
*
|
|
7
7
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
8
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
package/src/tree/map.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
cachedKeyFunctions,
|
|
3
|
-
extensionKeyFunctions,
|
|
4
2
|
isPlainObject,
|
|
5
3
|
isUnpackable,
|
|
6
4
|
map as mapTransform,
|
|
7
5
|
} from "@weborigami/async-tree";
|
|
8
6
|
import getTreeArgument from "../common/getTreeArgument.js";
|
|
9
7
|
import { toFunction } from "../common/utilities.js";
|
|
10
|
-
import parseExtensions from "./parseExtensions.js";
|
|
11
8
|
|
|
12
9
|
/**
|
|
13
10
|
* Map a hierarchical tree of keys and values to a new tree of keys and values.
|
|
@@ -81,12 +78,6 @@ function extendedOptions(context, operation) {
|
|
|
81
78
|
let keyFn = options.key;
|
|
82
79
|
let inverseKeyFn = options.inverseKey;
|
|
83
80
|
|
|
84
|
-
if (extension && (keyFn || inverseKeyFn)) {
|
|
85
|
-
throw new TypeError(
|
|
86
|
-
`map: You can't specify extensions and also a key or inverseKey function`
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
81
|
if (valueFn) {
|
|
91
82
|
// @ts-ignore
|
|
92
83
|
valueFn = toFunction(valueFn);
|
|
@@ -94,36 +85,23 @@ function extendedOptions(context, operation) {
|
|
|
94
85
|
// Origami builtins can be used as value functions.
|
|
95
86
|
// @ts-ignore
|
|
96
87
|
const bound = valueFn.bind(context);
|
|
88
|
+
// Transfer sidecar functions
|
|
97
89
|
// @ts-ignore
|
|
98
90
|
Object.assign(bound, valueFn);
|
|
99
91
|
valueFn = bound;
|
|
100
92
|
}
|
|
101
93
|
|
|
102
|
-
if (extension) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
inverseKeyFn = keyFns.inverseKey;
|
|
108
|
-
} else if (keyFn) {
|
|
109
|
-
// Extend the key function to include a value parameter
|
|
110
|
-
keyFn = extendKeyFn(keyFn);
|
|
111
|
-
} else {
|
|
112
|
-
// Use sidecar key/inverseKey functions if the valueFn defines them
|
|
113
|
-
keyFn = /** @type {any} */ (valueFn)?.key;
|
|
114
|
-
inverseKeyFn = /** @type {any} */ (valueFn)?.inverseKey;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (keyFn && !inverseKeyFn) {
|
|
118
|
-
// Only keyFn was provided, so we need to generate the inverseKeyFn
|
|
119
|
-
const keyFns = cachedKeyFunctions(keyFn, deep);
|
|
120
|
-
keyFn = keyFns.key;
|
|
121
|
-
inverseKeyFn = keyFns.inverseKey;
|
|
94
|
+
if (!extension) {
|
|
95
|
+
if (keyFn) {
|
|
96
|
+
// Extend the key function to include a value parameter
|
|
97
|
+
keyFn = extendKeyFn(keyFn);
|
|
98
|
+
}
|
|
122
99
|
}
|
|
123
100
|
|
|
124
101
|
return {
|
|
125
102
|
deep,
|
|
126
103
|
description,
|
|
104
|
+
extension,
|
|
127
105
|
inverseKey: inverseKeyFn,
|
|
128
106
|
key: keyFn,
|
|
129
107
|
needsSourceValue,
|
package/src/tree/mask.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { mask } from "@weborigami/async-tree";
|
|
2
|
+
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Apply a mask to a tree
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
9
|
+
*
|
|
10
|
+
* @this {AsyncTree|null}
|
|
11
|
+
* @param {Treelike} sourceTreelike
|
|
12
|
+
* @param {Treelike} maskTreelike
|
|
13
|
+
*/
|
|
14
|
+
export default async function maskBuiltin(sourceTreelike, maskTreelike) {
|
|
15
|
+
assertTreeIsDefined(this, "tree:mask");
|
|
16
|
+
const result = mask(sourceTreelike, maskTreelike);
|
|
17
|
+
result.parent = this;
|
|
18
|
+
return result;
|
|
19
|
+
}
|
package/src/tree/tree.js
CHANGED
|
@@ -21,6 +21,7 @@ export { default as inners } from "./inners.js";
|
|
|
21
21
|
export { default as keys } from "./keys.js";
|
|
22
22
|
export { default as length } from "./length.js";
|
|
23
23
|
export { default as map } from "./map.js";
|
|
24
|
+
export { default as mask } from "./mask.js";
|
|
24
25
|
export { default as match } from "./match.js";
|
|
25
26
|
export { default as merge } from "./merge.js";
|
|
26
27
|
export { default as paginate } from "./paginate.js";
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Given a string specifying an extension or a mapping of one extension to another,
|
|
3
|
-
* return the source and result extensions.
|
|
4
|
-
*
|
|
5
|
-
* Syntax:
|
|
6
|
-
* .foo source and result extension are the same
|
|
7
|
-
* .foo→.bar Unicode Rightwards Arrow
|
|
8
|
-
* .foo→ Unicode Rightwards Arrow, no result extension
|
|
9
|
-
* →.bar Unicode Rightwards Arrow, no source extension
|
|
10
|
-
* .foo->.bar hyphen and greater-than sign
|
|
11
|
-
*
|
|
12
|
-
* @param {string} specifier
|
|
13
|
-
*/
|
|
14
|
-
export default function parseExtensions(specifier) {
|
|
15
|
-
const lowercase = specifier?.toLowerCase() ?? "";
|
|
16
|
-
const extensionRegex =
|
|
17
|
-
/^((?<sourceExtension>\/|\.\S*)?\s*(→|->)\s*(?<resultExtension>\/|\.\S*)?)|(?<extension>\/|\.\S*)$/;
|
|
18
|
-
const match = lowercase.match(extensionRegex);
|
|
19
|
-
if (!match) {
|
|
20
|
-
throw new Error(`Invalid file extension specifier "${specifier}".`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// @ts-ignore
|
|
24
|
-
let { extension, resultExtension, sourceExtension } = match.groups;
|
|
25
|
-
if (extension) {
|
|
26
|
-
// foo
|
|
27
|
-
return {
|
|
28
|
-
resultExtension: extension,
|
|
29
|
-
sourceExtension: extension,
|
|
30
|
-
};
|
|
31
|
-
} else {
|
|
32
|
-
// foo→bar
|
|
33
|
-
|
|
34
|
-
if (resultExtension === undefined && sourceExtension === undefined) {
|
|
35
|
-
throw new Error(
|
|
36
|
-
`A file extension mapping must indicate a source or result extension: "${specifier}".`
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
resultExtension ??= "";
|
|
41
|
-
sourceExtension ??= "";
|
|
42
|
-
return { resultExtension, sourceExtension };
|
|
43
|
-
}
|
|
44
|
-
}
|