@weborigami/origami 0.0.45 → 0.0.47

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.
Files changed (70) hide show
  1. package/exports/buildExports.js +13 -9
  2. package/exports/exports.js +17 -16
  3. package/package.json +11 -13
  4. package/src/builtins/@cache.js +2 -6
  5. package/src/builtins/@config.js +12 -5
  6. package/src/builtins/@crawl.js +3 -3
  7. package/src/builtins/@debug.js +9 -2
  8. package/src/builtins/@document.js +3 -5
  9. package/src/builtins/@fnTree.js +5 -2
  10. package/src/builtins/@inline.js +18 -25
  11. package/src/builtins/@inners.js +1 -3
  12. package/src/builtins/@invoke.js +2 -1
  13. package/src/builtins/@json.js +0 -3
  14. package/src/builtins/@keysJson.js +1 -4
  15. package/src/builtins/@map.js +38 -45
  16. package/src/builtins/@mapDeep.js +2 -2
  17. package/src/builtins/@mdHtml.js +10 -11
  18. package/src/builtins/@mkdir.js +3 -0
  19. package/src/builtins/@node.js +2 -1
  20. package/src/builtins/@project.js +22 -14
  21. package/src/builtins/@shuffle.js +1 -6
  22. package/src/builtins/@sitemap.js +2 -2
  23. package/src/builtins/@sort.js +1 -4
  24. package/src/builtins/@static.js +1 -3
  25. package/src/builtins/@tree.js +1 -4
  26. package/src/builtins/@yaml.js +0 -3
  27. package/src/builtins/css_handler.js +7 -0
  28. package/src/builtins/htm_handler.js +2 -0
  29. package/src/builtins/html_handler.js +7 -0
  30. package/src/builtins/jpeg_handler.js +58 -0
  31. package/src/builtins/jpg_handler.js +2 -0
  32. package/src/builtins/js_handler.js +20 -0
  33. package/src/builtins/json_handler.js +19 -0
  34. package/src/builtins/map.d.ts +5 -5
  35. package/src/builtins/md_handler.js +7 -0
  36. package/src/builtins/mjs_handler.js +2 -0
  37. package/src/builtins/ori_handler.js +48 -0
  38. package/src/builtins/txt_handler.js +78 -0
  39. package/src/builtins/wasm_handler.js +17 -0
  40. package/src/builtins/xhtml_handler.js +2 -0
  41. package/src/builtins/yaml_handler.js +29 -0
  42. package/src/builtins/yml_handler.js +2 -0
  43. package/src/common/ExplorableSiteTransform.js +5 -1
  44. package/src/common/addValueKeyToScope.js +3 -2
  45. package/src/common/arrowFunctionsMap.js +5 -5
  46. package/src/common/documentObject.js +33 -0
  47. package/src/common/serialize.d.ts +1 -0
  48. package/src/common/serialize.js +68 -27
  49. package/src/common/utilities.js +9 -7
  50. package/src/misc/getTreeArgument.js +12 -2
  51. package/src/misc/treeDot.js +6 -1
  52. package/src/server/constructResponse.js +18 -5
  53. package/src/server/server.js +5 -4
  54. package/src/builtins/!.js +0 -21
  55. package/src/builtins/@loaders/css.js +0 -2
  56. package/src/builtins/@loaders/htm.js +0 -2
  57. package/src/builtins/@loaders/html.js +0 -2
  58. package/src/builtins/@loaders/jpeg.js +0 -55
  59. package/src/builtins/@loaders/jpg.js +0 -2
  60. package/src/builtins/@loaders/js.js +0 -14
  61. package/src/builtins/@loaders/json.js +0 -14
  62. package/src/builtins/@loaders/md.js +0 -2
  63. package/src/builtins/@loaders/mjs.js +0 -2
  64. package/src/builtins/@loaders/ori.js +0 -45
  65. package/src/builtins/@loaders/txt.js +0 -37
  66. package/src/builtins/@loaders/wasm.js +0 -11
  67. package/src/builtins/@loaders/xhtml.js +0 -2
  68. package/src/builtins/@loaders/yaml.js +0 -23
  69. package/src/builtins/@loaders/yml.js +0 -2
  70. package/src/common/TextDocument.js +0 -58
@@ -1,6 +1,6 @@
1
1
  /** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
2
- import { keyMapsForExtensions, map } from "@weborigami/async-tree";
3
- import unpackOrigamiTemplate from "../src/builtins/@loaders/ori.js";
2
+ import { keyFunctionsForExtensions, map } from "@weborigami/async-tree";
3
+ import fileTypeOrigami from "../src/builtins/ori_handler.js";
4
4
  import { transformObject } from "../src/common/utilities.js";
5
5
  import PathTransform from "./PathTransform.js";
6
6
 
@@ -22,7 +22,7 @@ const templateText = `=\`// This file is generated by running buildExports.js --
22
22
  // file's export(s) in the top-level export file.
23
23
  export default async function exportFile(src) {
24
24
  const statements = await exportStatements(src);
25
- const templateFn = await unpackOrigamiTemplate(templateText);
25
+ const templateFn = await fileTypeOrigami.unpack(templateText);
26
26
  const result = await templateFn(statements);
27
27
  return result;
28
28
  }
@@ -47,7 +47,8 @@ async function exportStatementForCode(codeBuffer, key) {
47
47
  const pathParts = path.split("/");
48
48
  pathParts.pop(); // Drop key
49
49
 
50
- const exportsDefault = code.match(/^export default /m);
50
+ const exportsDefault =
51
+ code.match(/^export default /m) || code.match(/^export { default } /m);
51
52
  if (!exportsDefault) {
52
53
  // Export everything.
53
54
  return `export * from "../src/${path}";\n`;
@@ -76,12 +77,15 @@ async function exportStatementForCode(codeBuffer, key) {
76
77
  name = specialName;
77
78
  }
78
79
 
80
+ // Split the name into parts based on dots.
81
+ const nameParts = name.split(".");
82
+
79
83
  // Add the name to the parts.
80
- exportIdentifierParts.push(name);
84
+ exportIdentifierParts.push(...nameParts);
81
85
 
82
- // Remove the @ prefix from any parts, if present.
86
+ // Remove characters that can't be in JavaScript identifiers.
83
87
  exportIdentifierParts = exportIdentifierParts.map((part) =>
84
- part.startsWith("@") ? part.slice(1) : part
88
+ part.replace(/[^a-zA-Z0-9]/g, "")
85
89
  );
86
90
 
87
91
  // Join the parts in camelCase to form the identifier.
@@ -101,8 +105,8 @@ function exportStatements(src) {
101
105
  // Map each source file to an export statement.
102
106
  const mapped = map({
103
107
  deep: true,
104
- valueMap: exportStatementForCode,
105
- ...keyMapsForExtensions({ sourceExtension: "js" }),
108
+ value: exportStatementForCode,
109
+ ...keyFunctionsForExtensions({ sourceExtension: "js" }),
106
110
  })(withPaths);
107
111
 
108
112
  return mapped;
@@ -38,27 +38,13 @@ export { default as js } from "../src/builtins/@js.js";
38
38
  export { default as json } from "../src/builtins/@json.js";
39
39
  export { default as keys } from "../src/builtins/@keys.js";
40
40
  export { default as keysJson } from "../src/builtins/@keysJson.js";
41
- export * from "../src/builtins/@loaders/css.js";
42
- export * from "../src/builtins/@loaders/htm.js";
43
- export * from "../src/builtins/@loaders/html.js";
44
- export { default as loadersJpeg } from "../src/builtins/@loaders/jpeg.js";
45
- export * from "../src/builtins/@loaders/jpg.js";
46
- export { default as loadersJs } from "../src/builtins/@loaders/js.js";
47
- export { default as loadersJson } from "../src/builtins/@loaders/json.js";
48
- export * from "../src/builtins/@loaders/md.js";
49
- export * from "../src/builtins/@loaders/mjs.js";
50
- export { default as loadersOri } from "../src/builtins/@loaders/ori.js";
51
- export { default as loadersTxt } from "../src/builtins/@loaders/txt.js";
52
- export { default as loadersWasm } from "../src/builtins/@loaders/wasm.js";
53
- export * from "../src/builtins/@loaders/xhtml.js";
54
- export { default as loadersYaml } from "../src/builtins/@loaders/yaml.js";
55
- export * from "../src/builtins/@loaders/yml.js";
56
41
  export { default as map } from "../src/builtins/@map.js";
57
42
  export { default as mapDeep } from "../src/builtins/@mapDeep.js";
58
43
  export { default as match } from "../src/builtins/@match.js";
59
44
  export { default as mdHtml } from "../src/builtins/@mdHtml.js";
60
45
  export { default as merge } from "../src/builtins/@merge.js";
61
46
  export { default as mergeDeep } from "../src/builtins/@mergeDeep.js";
47
+ export { default as mkdir } from "../src/builtins/@mkdir.js";
62
48
  export { default as node } from "../src/builtins/@node.js";
63
49
  export { default as not } from "../src/builtins/@not.js";
64
50
  export { default as once } from "../src/builtins/@once.js";
@@ -103,19 +89,34 @@ export { default as watch } from "../src/builtins/@watch.js";
103
89
  export { default as with } from "../src/builtins/@with.js";
104
90
  export { default as yaml } from "../src/builtins/@yaml.js";
105
91
  export { default as homeFiles } from "../src/builtins/~.js";
92
+ export { default as csshandler } from "../src/builtins/css_handler.js";
93
+ export { default as htmhandler } from "../src/builtins/htm_handler.js";
94
+ export { default as htmlhandler } from "../src/builtins/html_handler.js";
95
+ export { default as jpeghandler } from "../src/builtins/jpeg_handler.js";
96
+ export { default as jpghandler } from "../src/builtins/jpg_handler.js";
97
+ export { default as jshandler } from "../src/builtins/js_handler.js";
98
+ export { default as jsonhandler } from "../src/builtins/json_handler.js";
99
+ export { default as mdhandler } from "../src/builtins/md_handler.js";
100
+ export { default as mjshandler } from "../src/builtins/mjs_handler.js";
101
+ export { default as orihandler } from "../src/builtins/ori_handler.js";
102
+ export { default as txthandler } from "../src/builtins/txt_handler.js";
103
+ export { default as wasmhandler } from "../src/builtins/wasm_handler.js";
104
+ export { default as xhtmlhandler } from "../src/builtins/xhtml_handler.js";
105
+ export { default as yamlhandler } from "../src/builtins/yaml_handler.js";
106
+ export { default as ymlhandler } from "../src/builtins/yml_handler.js";
106
107
  export { default as defaultModuleExport } from "../src/cli/defaultModuleExport.js";
107
108
  export { default as showUsage } from "../src/cli/showUsage.js";
108
109
  export { default as addValueKeyToScope } from "../src/common/addValueKeyToScope.js";
109
110
  export { default as arrowFunctionsMap } from "../src/common/arrowFunctionsMap.js";
110
111
  export { default as CommandModulesTransform } from "../src/common/CommandModulesTransform.js";
111
112
  export { default as ConstantTree } from "../src/common/ConstantTree.js";
113
+ export { default as documentObject } from "../src/common/documentObject.js";
112
114
  export { default as ExplorableSiteTransform } from "../src/common/ExplorableSiteTransform.js";
113
115
  export { default as FilterTree } from "../src/common/FilterTree.js";
114
116
  export { default as GlobTree } from "../src/common/GlobTree.js";
115
117
  export { default as processUnpackedContent } from "../src/common/processUnpackedContent.js";
116
118
  export * from "../src/common/serialize.js";
117
119
  export { default as ShuffleTransform } from "../src/common/ShuffleTransform.js";
118
- export { default as TextDocument } from "../src/common/TextDocument.js";
119
120
  export * from "../src/common/utilities.js";
120
121
  export { default as assertScopeIsDefined } from "../src/misc/assertScopeIsDefined.js";
121
122
  export { default as getTreeArgument } from "../src/misc/getTreeArgument.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/origami",
3
- "version": "0.0.45",
3
+ "version": "0.0.47",
4
4
  "description": "Web Origami language, CLI, framework, and server",
5
5
  "type": "module",
6
6
  "repository": {
@@ -13,24 +13,22 @@
13
13
  "main": "./exports/exports.js",
14
14
  "types": "./index.ts",
15
15
  "devDependencies": {
16
- "@types/chai": "4.3.11",
17
- "@types/mocha": "10.0.6",
18
- "@types/node": "20.11.7",
19
- "typescript": "5.3.3"
16
+ "@types/node": "20.11.27",
17
+ "typescript": "5.4.2"
20
18
  },
21
19
  "dependencies": {
22
- "@weborigami/async-tree": "0.0.45",
23
- "@weborigami/language": "0.0.45",
24
- "@weborigami/types": "0.0.45",
20
+ "@weborigami/async-tree": "0.0.47",
21
+ "@weborigami/language": "0.0.47",
22
+ "@weborigami/types": "0.0.47",
25
23
  "exif-parser": "0.1.12",
26
24
  "graphviz-wasm": "3.0.1",
27
25
  "highlight.js": "11.9.0",
28
- "marked": "11.1.1",
29
- "marked-gfm-heading-id": "3.1.2",
30
- "marked-highlight": "2.1.0",
31
- "marked-smartypants": "1.1.5",
26
+ "marked": "12.0.1",
27
+ "marked-gfm-heading-id": "3.1.3",
28
+ "marked-highlight": "2.1.1",
29
+ "marked-smartypants": "1.1.6",
32
30
  "sharp": "0.33.2",
33
- "yaml": "2.3.4"
31
+ "yaml": "2.4.1"
34
32
  },
35
33
  "scripts": {
36
34
  "build": "ori exports/buildExports.js src > exports/exports.js",
@@ -1,4 +1,4 @@
1
- import { cache, Tree } from "@weborigami/async-tree";
1
+ import { Tree, cache } from "@weborigami/async-tree";
2
2
  import { Scope } from "@weborigami/language";
3
3
  import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
4
4
 
@@ -19,14 +19,10 @@ export default async function cacheBuiltin(
19
19
  filterTreelike
20
20
  ) {
21
21
  assertScopeIsDefined(this, "cache");
22
-
23
- const sourceTree = Tree.from(sourceTreelike);
24
22
  /** @type {any} */
25
23
  const cacheTree = cacheTreelike ? Tree.from(cacheTreelike) : undefined;
26
- const filterTree = filterTreelike ? Tree.from(filterTreelike) : undefined;
27
-
28
24
  /** @type {AsyncTree} */
29
- let result = cache(sourceTree, cacheTree, filterTree);
25
+ let result = cache(sourceTreelike, cacheTree, filterTreelike);
30
26
  result = Scope.treeWithScope(result, this);
31
27
  return result;
32
28
  }
@@ -1,11 +1,11 @@
1
+ import { Scope } from "@weborigami/language";
1
2
  import project from "./@project.js";
2
3
 
3
4
  /**
4
5
  * Return the configuration for the current project.
5
6
  *
6
- * If the project's root defines an ori.config.js file, the configuration is
7
- * the default export of that file. Otherwise, the configuration is the set of
8
- * built-in functions.
7
+ * The configuration is the project's config.ori file (if defined in the project
8
+ * root) plus the Origami builtins.
9
9
  *
10
10
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
11
11
  *
@@ -14,10 +14,17 @@ import project from "./@project.js";
14
14
  */
15
15
  export default async function config(key) {
16
16
  const projectTree = await project.call(this);
17
- const scope = projectTree?.parent;
18
- if (!scope) {
17
+ // HACK: We use specific knowledge of how @project returns a tree to get the
18
+ // config. We get the scope of the project's root folder, then remove that
19
+ // folder from the scope, leaving config + builtins.
20
+ /** @type {any} */
21
+ const projectTreeScope = Scope.getScope(projectTree);
22
+ const trees = projectTreeScope?.trees;
23
+ if (!trees) {
19
24
  return undefined;
20
25
  }
26
+ trees.shift();
27
+ const scope = new Scope(...trees);
21
28
  return key === undefined ? scope : scope.get(key);
22
29
  }
23
30
 
@@ -1,5 +1,5 @@
1
1
  import {
2
- ObjectTree,
2
+ DeepObjectTree,
3
3
  Tree,
4
4
  isPlainObject,
5
5
  keysFromPath,
@@ -94,8 +94,8 @@ export default async function crawl(treelike, baseHref) {
94
94
  // value.
95
95
  /** @type {AsyncTree} */
96
96
  let result = mergeDeep(
97
- new ObjectTree(cache),
98
- new (InvokeFunctionsTransform(ObjectTree))(resources)
97
+ new DeepObjectTree(cache),
98
+ new (InvokeFunctionsTransform(DeepObjectTree))(resources)
99
99
  );
100
100
  result = Scope.treeWithScope(result, this);
101
101
  return result;
@@ -1,4 +1,5 @@
1
1
  import { Tree, isPlainObject } from "@weborigami/async-tree";
2
+ import { Scope } from "@weborigami/language";
2
3
  import ExplorableSiteTransform from "../common/ExplorableSiteTransform.js";
3
4
  import { isTransformApplied, transformObject } from "../common/utilities.js";
4
5
  import OriCommandTransform from "../misc/OriCommandTransform.js";
@@ -54,12 +55,18 @@ function DebugTransform(Base) {
54
55
  const original = value.unpack.bind(value);
55
56
  value.unpack = async () => {
56
57
  let content = await original();
57
- if (!Tree.isTreelike(content)) {
58
+ if (!Tree.isTraversable(content)) {
58
59
  return content;
59
60
  }
60
61
  /** @type {any} */
61
62
  let tree = Tree.from(content);
62
- tree = transformObject(ExplorableSiteTransform, tree);
63
+ if (!tree.parent && !tree.scope) {
64
+ const scope = Scope.getScope(this);
65
+ tree = Scope.treeWithScope(tree, scope);
66
+ }
67
+ if (!isTransformApplied(ExplorableSiteTransform, tree)) {
68
+ tree = transformObject(ExplorableSiteTransform, tree);
69
+ }
63
70
  tree = transformObject(DebugTransform, tree);
64
71
  return tree;
65
72
  };
@@ -1,4 +1,4 @@
1
- import TextDocument from "../common/TextDocument.js";
1
+ import documentObject from "../common/documentObject.js";
2
2
  import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
3
3
 
4
4
  /**
@@ -8,11 +8,9 @@ import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
8
8
  * @this {AsyncTree|null}
9
9
  * @param {StringLike} text
10
10
  * @param {any} [data]
11
- * @param {AsyncTree|null} [parent]
12
11
  * @returns
13
12
  */
14
- export default function document(text, data, parent) {
13
+ export default function documentBuiltin(text, data) {
15
14
  assertScopeIsDefined(this, "document");
16
- const merged = Object.assign({}, data, { "@text": text });
17
- return new TextDocument(merged, parent ?? this);
15
+ return documentObject(text, data);
18
16
  }
@@ -1,4 +1,4 @@
1
- import { FunctionTree } from "@weborigami/async-tree";
1
+ import { FunctionTree, ObjectTree } from "@weborigami/async-tree";
2
2
  import { Scope } from "@weborigami/language";
3
3
  import { toFunction } from "../common/utilities.js";
4
4
  import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
@@ -29,7 +29,10 @@ export default async function fnTree(invocable, keys = []) {
29
29
 
30
30
  /** @this {AsyncTree|null} */
31
31
  async function extendedFn(key) {
32
- const ambientsTree = Scope.treeWithScope({ "@key": key }, this);
32
+ const ambientsTree = Scope.treeWithScope(
33
+ new ObjectTree({ "@key": key }),
34
+ this
35
+ );
33
36
  return invocableFn.call(ambientsTree, key);
34
37
  }
35
38
 
@@ -1,8 +1,9 @@
1
- import { Tree, isPlainObject } from "@weborigami/async-tree";
1
+ import { isUnpackable, symbols } from "@weborigami/async-tree";
2
2
  import { compile } from "@weborigami/language";
3
- import unpackText from "../builtins/@loaders/txt.js";
3
+ import documentObject from "../common/documentObject.js";
4
+ import { toString } from "../common/utilities.js";
4
5
  import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
5
- import unpackOrigamiExpression from "./@loaders/ori.js";
6
+ import fileTypeOrigami from "./ori_handler.js";
6
7
 
7
8
  /**
8
9
  * Inline any Origami expressions found inside ${...} placeholders in the input
@@ -18,33 +19,25 @@ export default async function inline(input) {
18
19
  assertScopeIsDefined(this, "inline");
19
20
 
20
21
  // Get the input text and any attached front matter.
21
- let inputDocument;
22
- if (input["@text"]) {
23
- inputDocument = input;
24
- } else if (/** @type {any} */ (input).unpack) {
25
- // Have the input unpack itself.
26
- inputDocument = await /** @type {any} */ (input).unpack();
27
- } else {
28
- // Unpack the input as a text document with possible front matter.
29
- inputDocument = await unpackText(input);
22
+ if (isUnpackable(input)) {
23
+ input = await input.unpack();
30
24
  }
25
+ const inputIsDocument = input["@text"] !== undefined;
26
+ const origami = inputIsDocument ? input["@text"] : toString(input);
27
+ const parent = input.parent ?? input[symbols.parent];
31
28
 
32
- // If the input document is a plain object or AsyncTree, we'll have it
33
- // included in scope for the evaluated expression. We ignore other kinds of
34
- // treelike inputs for this test: in particular, a Buffer will be interpreted
35
- // as a tree, but we don't want to put a Buffer in scope.
36
- const attachedData =
37
- isPlainObject(inputDocument) || Tree.isAsyncTree(inputDocument)
38
- ? inputDocument
39
- : null;
29
+ // If the input document is a plain object, include it in scope for the
30
+ // evaluated expression.
31
+ const inputData = inputIsDocument ? input : null;
40
32
 
41
- const templateFn = await unpackOrigamiExpression(inputDocument, {
42
- attachedData,
33
+ const templateFn = await fileTypeOrigami.unpack(origami, {
34
+ attachedData: inputData,
43
35
  compiler: compile.templateDocument,
36
+ parent,
44
37
  });
45
- const templateResult = await templateFn(inputDocument);
46
- return inputDocument
47
- ? Object.assign({}, inputDocument, { "@text": String(templateResult) })
38
+ const templateResult = await templateFn(inputData);
39
+ return inputIsDocument
40
+ ? documentObject(templateResult, inputData)
48
41
  : templateResult;
49
42
  }
50
43
 
@@ -1,5 +1,4 @@
1
1
  import { Tree } from "@weborigami/async-tree";
2
- import { Scope } from "@weborigami/language";
3
2
  import getTreeArgument from "../misc/getTreeArgument.js";
4
3
 
5
4
  /**
@@ -14,7 +13,7 @@ export default async function inners(treelike) {
14
13
  const tree = await getTreeArgument(this, arguments, treelike, "@inners");
15
14
 
16
15
  /** @type {AsyncTree} */
17
- let result = {
16
+ const result = {
18
17
  async get(key) {
19
18
  const value = await tree.get(key);
20
19
  return Tree.isAsyncTree(value) ? inners.call(this, value) : undefined;
@@ -31,7 +30,6 @@ export default async function inners(treelike) {
31
30
  },
32
31
  };
33
32
 
34
- result = Scope.treeWithScope(result, this);
35
33
  return result;
36
34
  }
37
35
 
@@ -1,3 +1,4 @@
1
+ import { isUnpackable } from "@weborigami/async-tree";
1
2
  import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
2
3
  import builtins from "./@builtins.js";
3
4
 
@@ -30,7 +31,7 @@ export default async function invoke(fn) {
30
31
  "An Origami function was called with an initial argument, but its value is undefined."
31
32
  );
32
33
  }
33
- if (typeof fn !== "function" && fn.unpack) {
34
+ if (isUnpackable(fn)) {
34
35
  fn = await fn.unpack();
35
36
  }
36
37
  const scope = (await this?.get("@current")) ?? builtins;
@@ -20,9 +20,6 @@ export default async function json(obj) {
20
20
  if (obj === undefined) {
21
21
  return undefined;
22
22
  }
23
- if (typeof obj.unpack === "function") {
24
- obj = await obj.unpack();
25
- }
26
23
  const value = await serialize.toJsonValue(obj);
27
24
  return JSON.stringify(value, null, 2);
28
25
  }
@@ -1,5 +1,4 @@
1
1
  import { Tree, keysJson } from "@weborigami/async-tree";
2
- import { Scope } from "@weborigami/language";
3
2
  import { transformObject } from "../common/utilities.js";
4
3
  import getTreeArgument from "../misc/getTreeArgument.js";
5
4
 
@@ -13,9 +12,7 @@ import getTreeArgument from "../misc/getTreeArgument.js";
13
12
  */
14
13
  export default async function treeKeysJson(treelike) {
15
14
  const tree = await getTreeArgument(this, arguments, treelike, "@keysJson");
16
- let result = transformObject(KeysJsonTransform, tree);
17
- result = Scope.treeWithScope(result, this);
18
- return result;
15
+ return transformObject(KeysJsonTransform, tree);
19
16
  }
20
17
 
21
18
  function KeysJsonTransform(Base) {
@@ -1,8 +1,7 @@
1
1
  import {
2
- cachedKeyMaps,
3
- keyMapsForExtensions,
2
+ cachedKeyFunctions,
3
+ keyFunctionsForExtensions,
4
4
  map,
5
- Tree,
6
5
  } from "@weborigami/async-tree";
7
6
  import { Scope } from "@weborigami/language";
8
7
  import addValueKeyToScope from "../common/addValueKeyToScope.js";
@@ -18,9 +17,9 @@ import { toFunction } from "../common/utilities.js";
18
17
  * @typedef {import("../../index.ts").TreelikeTransform} TreelikeTransform
19
18
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
20
19
  *
21
- * @typedef {{ deep?: boolean, description?: string, extensions?: string,
22
- * inverseKeyMap?: KeyFn, keyMap?: ValueKeyFn, valueMap?: ValueKeyFn }}
23
- * TreeMapOptions
20
+ * @typedef {{ deep?: boolean, description?: string, extension?: string,
21
+ * extensions?: string, inverseKey?: KeyFn, key?: ValueKeyFn, keyMap?:
22
+ * ValueKeyFn, value?: ValueKeyFn, valueFn?: ValueKeyFn }} TreeMapOptions
24
23
  *
25
24
  * @this {import("@weborigami/types").AsyncTree|null}
26
25
  *
@@ -43,7 +42,7 @@ import { toFunction } from "../common/utilities.js";
43
42
  * @returns {AsyncTree}
44
43
  */
45
44
  export default function treeMap(param1, param2) {
46
- // Identify whether the valueMap/options are the first parameter
45
+ // Identify whether the valueFn/options are the first parameter
47
46
  // or the second.
48
47
  let source;
49
48
  let options;
@@ -62,37 +61,32 @@ export default function treeMap(param1, param2) {
62
61
  options = param2;
63
62
  }
64
63
 
65
- // Identify whether the valueMap/options is a valueMap function
64
+ // Identify whether the valueFn/options is a valueFn function
66
65
  // or an options dictionary.
67
- let valueMap;
66
+ let valueFn;
68
67
  if (
69
68
  typeof options === "function" ||
70
69
  typeof (/** @type {any} */ (options)?.unpack) === "function"
71
70
  ) {
72
- valueMap = options;
71
+ valueFn = options;
73
72
  options = {};
74
73
  } else if (!options) {
75
74
  throw new TypeError(
76
- `@map: You must specify a valueMap function or options dictionary.`
75
+ `@map: You must specify a value function or options dictionary.`
77
76
  );
78
77
  } else {
79
- valueMap = options.valueMap;
78
+ valueFn = options.value ?? options.valueMap;
80
79
  }
81
80
 
82
- let {
83
- deep,
84
- description,
85
- extensions,
86
- inverseKeyMap,
87
- keyMap,
88
- needsSourceValue,
89
- } = options;
81
+ let { deep, description, inverseKey, needsSourceValue } = options;
82
+ let extension = options.extension ?? options.extensions;
83
+ let keyFn = options.keyMap ?? options.key;
90
84
 
91
- description ??= `@map ${extensions ?? ""}`;
85
+ description ??= `@map ${extension ?? ""}`;
92
86
 
93
- if (extensions && (keyMap || inverseKeyMap)) {
87
+ if (extension && (keyFn || inverseKey)) {
94
88
  throw new TypeError(
95
- `@map: You can't specify both extensions and a keyMap or inverseKeyMap`
89
+ `@map: You can't specify extensions and also a key or inverseKey function`
96
90
  );
97
91
  }
98
92
 
@@ -100,8 +94,8 @@ export default function treeMap(param1, param2) {
100
94
 
101
95
  // Extend the value function to include the value and key in scope.
102
96
  let extendedValueFn;
103
- if (valueMap) {
104
- const resolvedValueFn = toFunction(valueMap);
97
+ if (valueFn) {
98
+ const resolvedValueFn = toFunction(valueFn);
105
99
  extendedValueFn = function (sourceValue, sourceKey, tree) {
106
100
  const scope = addValueKeyToScope(baseScope, sourceValue, sourceKey);
107
101
  return resolvedValueFn.call(scope, sourceValue, sourceKey, tree);
@@ -109,18 +103,18 @@ export default function treeMap(param1, param2) {
109
103
  }
110
104
 
111
105
  // Extend the key function to include the value and key in scope.
112
- let extendedKeyMap;
113
- let extendedInverseKeyMap;
114
- if (extensions) {
115
- let { resultExtension, sourceExtension } = parseExtensions(extensions);
116
- const keyFns = keyMapsForExtensions({
106
+ let extendedKeyFn;
107
+ let extendedInverseKeyFn;
108
+ if (extension) {
109
+ let { resultExtension, sourceExtension } = parseExtensions(extension);
110
+ const keyFns = keyFunctionsForExtensions({
117
111
  resultExtension,
118
112
  sourceExtension,
119
113
  });
120
- extendedKeyMap = keyFns.keyMap;
121
- extendedInverseKeyMap = keyFns.inverseKeyMap;
122
- } else if (keyMap) {
123
- const resolvedKeyFn = toFunction(keyMap);
114
+ extendedKeyFn = keyFns.key;
115
+ extendedInverseKeyFn = keyFns.inverseKey;
116
+ } else if (keyFn) {
117
+ const resolvedKeyFn = toFunction(keyFn);
124
118
  async function scopedKeyFn(sourceKey, tree) {
125
119
  const sourceValue = await tree.get(sourceKey);
126
120
  const scope = addValueKeyToScope(baseScope, sourceValue, sourceKey);
@@ -132,25 +126,24 @@ export default function treeMap(param1, param2) {
132
126
  );
133
127
  return resultKey;
134
128
  }
135
- const keyFns = cachedKeyMaps(scopedKeyFn);
136
- extendedKeyMap = keyFns.keyMap;
137
- extendedInverseKeyMap = keyFns.inverseKeyMap;
129
+ const keyFns = cachedKeyFunctions(scopedKeyFn);
130
+ extendedKeyFn = keyFns.key;
131
+ extendedInverseKeyFn = keyFns.inverseKey;
138
132
  } else {
139
- // Use sidecar keyMap/inverseKeyMap functions if the valueMap defines them.
140
- extendedKeyMap = valueMap?.keyMap;
141
- extendedInverseKeyMap = valueMap?.inverseKeyMap;
133
+ // Use sidecar keyFn/inverseKey functions if the valueFn defines them.
134
+ extendedKeyFn = valueFn?.key;
135
+ extendedInverseKeyFn = valueFn?.inverseKey;
142
136
  }
143
137
 
144
138
  const transform = function mapTreelike(treelike) {
145
- const tree = Tree.from(treelike);
146
139
  return map({
147
140
  deep,
148
141
  description,
149
- inverseKeyMap: extendedInverseKeyMap,
150
- keyMap: extendedKeyMap,
142
+ inverseKey: extendedInverseKeyFn,
143
+ key: extendedKeyFn,
151
144
  needsSourceValue,
152
- valueMap: extendedValueFn,
153
- })(tree);
145
+ value: extendedValueFn,
146
+ })(treelike);
154
147
  };
155
148
 
156
149
  return source ? transform(source) : transform;
@@ -2,7 +2,7 @@ import { isPlainObject } from "@weborigami/async-tree";
2
2
  import treeMap from "./@map.js";
3
3
 
4
4
  export default function mapDeep(param1, param2) {
5
- // Identify whether the valueMap/options are the first parameter
5
+ // Identify whether the valueFn/options are the first parameter
6
6
  // or the second.
7
7
  let source;
8
8
  let options;
@@ -13,7 +13,7 @@ export default function mapDeep(param1, param2) {
13
13
  if (isPlainObject(param2)) {
14
14
  options = param2;
15
15
  } else {
16
- options = { valueMap: param2 };
16
+ options = { value: param2 };
17
17
  }
18
18
  }
19
19
 
@@ -1,9 +1,11 @@
1
+ import { isUnpackable } from "@weborigami/async-tree";
1
2
  import highlight from "highlight.js";
2
3
  import { marked } from "marked";
3
4
  import { gfmHeadingId as markedGfmHeadingId } from "marked-gfm-heading-id";
4
5
  import { markedHighlight } from "marked-highlight";
5
6
  import { markedSmartypants } from "marked-smartypants";
6
- import { replaceExtension } from "../common/utilities.js";
7
+ import documentObject from "../common/documentObject.js";
8
+ import { replaceExtension, toString } from "../common/utilities.js";
7
9
 
8
10
  marked.use(
9
11
  markedGfmHeadingId(),
@@ -31,20 +33,17 @@ marked.use(
31
33
  * @param {StringLike|UnpackableStringlike} input
32
34
  */
33
35
  export default async function mdHtml(input) {
34
- if (/** @type {any} */ (input).unpack) {
35
- input = await /** @type {any} */ (input).unpack();
36
+ if (isUnpackable(input)) {
37
+ input = await input.unpack();
36
38
  }
37
- const inputDocument = input["@text"] ? input : null;
38
- const markdown = inputDocument?.["@text"] ?? String(input);
39
+ const inputIsDocument = input["@text"] !== undefined;
40
+ const markdown = inputIsDocument ? input["@text"] : toString(input);
39
41
  const html = marked(markdown);
40
- return inputDocument
41
- ? Object.assign({}, inputDocument, { "@text": html })
42
- : html;
42
+ return inputIsDocument ? documentObject(html, input) : html;
43
43
  }
44
44
 
45
- mdHtml.keyMap = (sourceKey) => replaceExtension(sourceKey, ".md", ".html");
46
- mdHtml.inverseKeyMap = (resultKey) =>
47
- replaceExtension(resultKey, ".html", ".md");
45
+ mdHtml.key = (sourceKey) => replaceExtension(sourceKey, ".md", ".html");
46
+ mdHtml.inverseKey = (resultKey) => replaceExtension(resultKey, ".html", ".md");
48
47
 
49
48
  mdHtml.usage = `@mdHtml <markdown>\tRender the markdown text as HTML`;
50
49
  mdHtml.documentation = "https://weborigami.org/language/@mdHtml.html";