@weborigami/origami 0.3.0 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/origami",
3
- "version": "0.3.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.3.0",
21
- "@weborigami/language": "0.3.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.3.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",
@@ -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 text = formatCsv(value);
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/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
- // Generate key/inverseKey functions from the extension
104
- let { resultExtension, sourceExtension } = parseExtensions(extension);
105
- const keyFns = extensionKeyFunctions(sourceExtension, resultExtension);
106
- keyFn = keyFns.key;
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,
@@ -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
- }