@weborigami/origami 0.5.4 → 0.5.5

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 (90) hide show
  1. package/index.ts +0 -4
  2. package/main.js +20 -3
  3. package/package.json +4 -4
  4. package/src/builtinsProgram.js +1 -10
  5. package/src/common/documentObject.js +2 -2
  6. package/src/common/loadJsDom.js +13 -0
  7. package/src/common/utilities.d.ts +0 -1
  8. package/src/common/utilities.js +0 -36
  9. package/src/dev/ExplorableSiteTransform.js +0 -4
  10. package/src/dev/changes.js +10 -5
  11. package/src/dev/code.js +1 -6
  12. package/src/dev/copy.js +4 -8
  13. package/src/dev/crawler/audit.js +8 -8
  14. package/src/dev/crawler/crawl.js +3 -5
  15. package/src/dev/crawler/findPaths.js +9 -3
  16. package/src/dev/crawler/pathsInHtml.js +4 -3
  17. package/src/dev/debug.js +4 -7
  18. package/src/dev/dev.js +4 -2
  19. package/src/dev/explore.js +4 -3
  20. package/src/dev/help.js +0 -4
  21. package/src/dev/help.yaml +14 -13
  22. package/src/dev/log.js +1 -2
  23. package/src/dev/serve.js +5 -18
  24. package/src/dev/treeDot.js +5 -6
  25. package/src/dev/watch.js +8 -12
  26. package/src/handlers/csv.handler.js +3 -0
  27. package/src/handlers/oridocument.handler.js +1 -1
  28. package/src/origami/csv.js +1 -5
  29. package/src/origami/document.js +2 -5
  30. package/src/origami/htmlDom.js +3 -2
  31. package/src/origami/image/format.js +0 -5
  32. package/src/origami/image/resize.js +0 -3
  33. package/src/origami/inline.js +3 -8
  34. package/src/origami/json.js +2 -6
  35. package/src/origami/jsonKeys.js +4 -10
  36. package/src/origami/mdHtml.js +5 -5
  37. package/src/origami/once.js +3 -7
  38. package/src/origami/ori.js +5 -0
  39. package/src/origami/origami.js +1 -2
  40. package/src/origami/pack.js +0 -5
  41. package/src/origami/post.js +4 -3
  42. package/src/origami/rss.js +7 -8
  43. package/src/origami/sitemap.js +5 -7
  44. package/src/origami/static.js +5 -7
  45. package/src/origami/string.js +0 -4
  46. package/src/origami/unpack.js +0 -5
  47. package/src/protocols/explore.js +0 -2
  48. package/src/protocols/httpstree.js +0 -2
  49. package/src/protocols/httptree.js +0 -2
  50. package/src/protocols/package.js +2 -2
  51. package/src/server/constructResponse.js +2 -2
  52. package/src/server/server.js +2 -33
  53. package/src/common/ConstantTree.js +0 -18
  54. package/src/protocols/js.js +0 -13
  55. package/src/tree/addNextPrevious.js +0 -22
  56. package/src/tree/cache.js +0 -22
  57. package/src/tree/calendar.js +0 -1
  58. package/src/tree/clear.js +0 -19
  59. package/src/tree/concat.js +0 -17
  60. package/src/tree/constant.js +0 -1
  61. package/src/tree/deepMap.js +0 -32
  62. package/src/tree/deepMerge.js +0 -18
  63. package/src/tree/deepReverse.js +0 -23
  64. package/src/tree/deepTake.js +0 -26
  65. package/src/tree/deepValues.js +0 -22
  66. package/src/tree/defineds.js +0 -30
  67. package/src/tree/filter.js +0 -19
  68. package/src/tree/first.js +0 -19
  69. package/src/tree/fromFn.js +0 -29
  70. package/src/tree/globKeys.js +0 -19
  71. package/src/tree/group.js +0 -26
  72. package/src/tree/inners.js +0 -30
  73. package/src/tree/keys.js +0 -15
  74. package/src/tree/length.js +0 -15
  75. package/src/tree/map.d.ts +0 -11
  76. package/src/tree/map.js +0 -125
  77. package/src/tree/mask.js +0 -19
  78. package/src/tree/match.js +0 -79
  79. package/src/tree/merge.js +0 -41
  80. package/src/tree/paginate.js +0 -20
  81. package/src/tree/parent.js +0 -15
  82. package/src/tree/plain.js +0 -15
  83. package/src/tree/regExpKeys.js +0 -19
  84. package/src/tree/reverse.js +0 -17
  85. package/src/tree/setDeep.js +0 -49
  86. package/src/tree/shuffle.js +0 -57
  87. package/src/tree/sort.js +0 -52
  88. package/src/tree/take.js +0 -19
  89. package/src/tree/tree.js +0 -52
  90. package/src/tree/values.js +0 -15
package/index.ts CHANGED
@@ -3,16 +3,12 @@
3
3
  * tool to confirm our code is type safe.
4
4
  */
5
5
 
6
- import { Treelike, Unpackable } from "@weborigami/async-tree";
7
-
8
6
  /**
9
7
  * A class constructor is an object with a `new` method that returns an
10
8
  * instance of the indicated type.
11
9
  */
12
10
  export type Constructor<T> = new (...args: any[]) => T;
13
11
 
14
- export type Invocable = Function | Unpackable<Function|Treelike> | Treelike;
15
-
16
12
  export interface JsonObject {
17
13
  [key: string]: JsonValue;
18
14
  }
package/main.js CHANGED
@@ -1,6 +1,5 @@
1
1
  export { default as documentObject } from "./src/common/documentObject.js";
2
2
  export { toString } from "./src/common/utilities.js";
3
- export * from "./src/dev/dev.js";
4
3
  export { default as handlerBuiltins } from "./src/handlers/handlerBuiltins.js";
5
4
  export * from "./src/handlers/handlers.js";
6
5
  export * from "./src/origami/origami.js";
@@ -8,5 +7,23 @@ export { default as origamiHighlightDefinition } from "./src/origami/origamiHigh
8
7
  export { default as package } from "./src/protocols/package.js";
9
8
  export * from "./src/server/server.js";
10
9
 
11
- // TODO: Remove once these async-tree owns sole copy of all tree builtins
12
- export * from "./src/tree/tree.js";
10
+ // Export only those dev exports that aren't tree exports
11
+ export {
12
+ audit,
13
+ breakpoint,
14
+ changes,
15
+ code,
16
+ copy,
17
+ crawl,
18
+ debug,
19
+ explore,
20
+ help,
21
+ indexPage,
22
+ log,
23
+ serve,
24
+ stdin,
25
+ svg,
26
+ version,
27
+ watch,
28
+ yaml,
29
+ } from "./src/dev/dev.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/origami",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
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.9.2"
18
18
  },
19
19
  "dependencies": {
20
- "@weborigami/async-tree": "0.5.4",
20
+ "@weborigami/async-tree": "0.5.5",
21
21
  "@weborigami/json-feed-to-rss": "1.0.0",
22
- "@weborigami/language": "0.5.4",
23
- "@weborigami/types": "0.5.4",
22
+ "@weborigami/language": "0.5.5",
23
+ "@weborigami/types": "0.5.5",
24
24
  "css-tree": "3.1.0",
25
25
  "exif-parser": "0.1.12",
26
26
  "graphviz-wasm": "3.0.2",
@@ -1,4 +1,4 @@
1
- import { deepText, indent, json, text } from "@weborigami/async-tree";
1
+ import { Tree } from "@weborigami/async-tree";
2
2
  import { jsGlobals } from "@weborigami/language";
3
3
  import * as dev from "./dev/dev.js";
4
4
  import help from "./dev/help.js";
@@ -12,20 +12,11 @@ import httpstree from "./protocols/httpstree.js";
12
12
  import httptree from "./protocols/httptree.js";
13
13
  import node from "./protocols/node.js";
14
14
  import packageNamespace from "./protocols/package.js";
15
- import * as tree from "./tree/tree.js";
16
15
 
17
16
  let builtins;
18
17
 
19
18
  export default function builtinsProgram() {
20
19
  if (!builtins) {
21
- const Tree = {
22
- ...tree,
23
- deepText,
24
- indent,
25
- json,
26
- text,
27
- };
28
-
29
20
  const Protocol = {
30
21
  explore,
31
22
  files,
@@ -4,10 +4,10 @@ import { isPlainObject, isUnpackable, toString } from "@weborigami/async-tree";
4
4
  * In Origami, a text document object is any object with a `_body` property.
5
5
  * This function is a helper for constructing such text document objects.
6
6
  *
7
- * @typedef {import("@weborigami/async-tree").StringLike} StringLike
7
+ * @typedef {import("@weborigami/async-tree").Stringlike} Stringlike
8
8
  * @typedef {import("@weborigami/async-tree").PlainObject} PlainObject
9
9
  *
10
- * @param {StringLike|PlainObject} input
10
+ * @param {Stringlike|PlainObject} input
11
11
  * @param {any} [data]
12
12
  */
13
13
  export default async function documentObject(input, data) {
@@ -0,0 +1,13 @@
1
+ let promise;
2
+
3
+ /**
4
+ * Lazy-load the jsdom library.
5
+ *
6
+ * Statically loading jsdom is slightly annoying. It's a large library that's
7
+ * rarely used. It also executes non-trivial code at load time. That includes a
8
+ * runtime test that (always?) throws an exception, which complicates debugging.
9
+ */
10
+ export default async function loadJsDom() {
11
+ promise ??= await import("jsdom");
12
+ return promise;
13
+ }
@@ -2,6 +2,5 @@
2
2
  export function getDescriptor(object: any): string;
3
3
  export function hasNonPrintableCharacters(text: string): boolean;
4
4
  export function isTransformApplied(Transform: Function, object: any): boolean;
5
- export function toFunction(object: any): Function;
6
5
  export function toString(object: any): string|null;
7
6
  export function transformObject(Transform: Function, object: any): any;
@@ -1,8 +1,6 @@
1
1
  import {
2
- Tree,
3
2
  toString as asyncTreeToString,
4
3
  isPlainObject,
5
- isUnpackable,
6
4
  trailingSlash,
7
5
  } from "@weborigami/async-tree";
8
6
  import { symbols } from "@weborigami/language";
@@ -52,40 +50,6 @@ export function isTransformApplied(Transform, obj) {
52
50
  return false;
53
51
  }
54
52
 
55
- /**
56
- * Convert the given object to a function.
57
- *
58
- * @typedef {import("../../index.ts").Invocable} Invocable
59
- * @param {any} obj
60
- * @returns {Function|null}
61
- */
62
- export function toFunction(obj) {
63
- if (typeof obj === "function") {
64
- // Return a function as is.
65
- return obj;
66
- } else if (isUnpackable(obj)) {
67
- // Extract the contents of the object and convert that to a function.
68
- let fnPromise;
69
- /** @this {any} */
70
- return async function (...args) {
71
- if (!fnPromise) {
72
- // unpack() may return a function or a promise for a function; normalize
73
- // to a promise for a function
74
- const unpackPromise = Promise.resolve(obj.unpack());
75
- fnPromise = unpackPromise.then((content) => toFunction(content));
76
- }
77
- const fn = await fnPromise;
78
- return fn.call(this, ...args);
79
- };
80
- } else if (Tree.isTreelike(obj)) {
81
- // Return a function that invokes the tree's getter.
82
- return Tree.toFunction(obj);
83
- } else {
84
- // Not a function
85
- return null;
86
- }
87
- }
88
-
89
53
  /**
90
54
  * Extend the async-tree toString method: objects that have a `_body` property
91
55
  * will return the value of that property as a string.
@@ -48,7 +48,6 @@ export default function ExplorableSiteTransform(Base) {
48
48
  // If the value isn't a tree, but has a tree attached via an `unpack`
49
49
  // method, wrap the unpack method to add this transform.
50
50
  const original = value.unpack.bind(value);
51
- const parent = this;
52
51
  value.unpack = async () => {
53
52
  const content = await original();
54
53
  // See function notes at @debug
@@ -57,9 +56,6 @@ export default function ExplorableSiteTransform(Base) {
57
56
  }
58
57
  /** @type {any} */
59
58
  let tree = Tree.from(content);
60
- if (!tree.parent) {
61
- tree.parent = parent;
62
- }
63
59
  if (!isTransformApplied(ExplorableSiteTransform, tree)) {
64
60
  tree = transformObject(ExplorableSiteTransform, tree);
65
61
  }
@@ -1,4 +1,4 @@
1
- import { trailingSlash, Tree } from "@weborigami/async-tree";
1
+ import { getTreeArgument, trailingSlash, Tree } from "@weborigami/async-tree";
2
2
 
3
3
  /**
4
4
  * Given an old tree and a new tree, return a tree of changes indicated
@@ -6,13 +6,18 @@ import { trailingSlash, Tree } from "@weborigami/async-tree";
6
6
  *
7
7
  * @typedef {import("@weborigami/async-tree").Treelike} Treelike
8
8
  *
9
- * @this {import("@weborigami/types").AsyncTree|null}
10
9
  * @param {Treelike} oldTreelike
11
10
  * @param {Treelike} newTreelike
12
11
  */
13
12
  export default async function changes(oldTreelike, newTreelike) {
14
- const oldTree = Tree.from(oldTreelike, { deep: true, parent: this });
15
- const newTree = Tree.from(newTreelike, { deep: true, parent: this });
13
+ const oldTree = await getTreeArgument(oldTreelike, "changes", {
14
+ deep: true,
15
+ position: 0,
16
+ });
17
+ const newTree = await getTreeArgument(newTreelike, "changes", {
18
+ deep: true,
19
+ position: 1,
20
+ });
16
21
 
17
22
  const oldKeys = Array.from(await oldTree.keys());
18
23
  const newKeys = Array.from(await newTree.keys());
@@ -34,7 +39,7 @@ export default async function changes(oldTreelike, newTreelike) {
34
39
  const newValue = await newTree.get(oldKey);
35
40
 
36
41
  if (Tree.isAsyncTree(oldValue) && Tree.isAsyncTree(newValue)) {
37
- const treeChanges = await changes.call(this, oldValue, newValue);
42
+ const treeChanges = await changes(oldValue, newValue);
38
43
  if (treeChanges && Object.keys(treeChanges).length > 0) {
39
44
  result ??= {};
40
45
  result[oldKey] = treeChanges;
package/src/dev/code.js CHANGED
@@ -1,17 +1,12 @@
1
1
  import { toString } from "@weborigami/async-tree";
2
2
  import { compile } from "@weborigami/language";
3
- import getTreeArgument from "../common/getTreeArgument.js";
4
3
 
5
4
  /**
6
5
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
7
6
  *
8
- * @this {AsyncTree|null}
9
- * @param {import("@weborigami/async-tree").StringLike} input
7
+ * @param {import("@weborigami/async-tree").Stringlike} input
10
8
  */
11
9
  export default async function code(input) {
12
- if (input === undefined) {
13
- input = await getTreeArgument(this, arguments, input, "code");
14
- }
15
10
  if (input === undefined) {
16
11
  return undefined;
17
12
  }
package/src/dev/copy.js CHANGED
@@ -1,22 +1,18 @@
1
- import { Tree } from "@weborigami/async-tree";
1
+ import { getTreeArgument, Tree } from "@weborigami/async-tree";
2
2
  import { formatError } from "@weborigami/language";
3
3
  import process, { stdout } from "node:process";
4
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
5
4
  import { transformObject } from "../common/utilities.js";
6
- import setDeep from "../tree/setDeep.js";
7
5
 
8
6
  /**
9
7
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
10
8
  * @typedef {import("@weborigami/async-tree").Treelike} Treelike
11
9
  *
12
- * @this {AsyncTree|null}
13
10
  * @param {Treelike} source
14
11
  * @param {Treelike} target
15
12
  */
16
13
  export default async function copy(source, target) {
17
- assertTreeIsDefined(this, "copy");
18
- const sourceTree = Tree.from(source, { parent: this });
19
- /** @type {any} */ let targetTree = Tree.from(target, { parent: this });
14
+ const sourceTree = await getTreeArgument(source, "copy", { position: 0 });
15
+ let targetTree = await getTreeArgument(target, "copy", { position: 1 });
20
16
 
21
17
  if (stdout.isTTY) {
22
18
  targetTree = transformObject(ProgressTransform, targetTree);
@@ -25,7 +21,7 @@ export default async function copy(source, target) {
25
21
  countCopied = 0;
26
22
  }
27
23
 
28
- await setDeep.call(this, targetTree, sourceTree);
24
+ await Tree.assign(targetTree, sourceTree);
29
25
 
30
26
  if (stdout.isTTY) {
31
27
  process.stdout.clearLine(0);
@@ -1,5 +1,9 @@
1
- import { pathFromKeys, symbols, Tree } from "@weborigami/async-tree";
2
- import getTreeArgument from "../../common/getTreeArgument.js";
1
+ import {
2
+ getTreeArgument,
3
+ pathFromKeys,
4
+ symbols,
5
+ Tree,
6
+ } from "@weborigami/async-tree";
3
7
  import crawlResources from "./crawlResources.js";
4
8
  import { getBaseUrl } from "./utilities.js";
5
9
 
@@ -10,12 +14,11 @@ import { getBaseUrl } from "./utilities.js";
10
14
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
11
15
  * @typedef {import("@weborigami/async-tree").Treelike} Treelike
12
16
  *
13
- * @this {AsyncTree|null}
14
17
  * @param {Treelike} treelike
15
18
  * @param {string} [baseHref]
16
19
  */
17
20
  export default async function audit(treelike, baseHref) {
18
- const tree = await getTreeArgument(this, arguments, treelike, "audit");
21
+ const tree = await getTreeArgument(treelike, "audit");
19
22
  const baseUrl = getBaseUrl(baseHref, treelike);
20
23
 
21
24
  let errors = {};
@@ -73,13 +76,10 @@ export default async function audit(treelike, baseHref) {
73
76
  return undefined;
74
77
  }
75
78
 
76
- Object.defineProperty(errors, symbols.parent, {
77
- enumerable: false,
78
- value: this,
79
- });
80
79
  Object.defineProperty(errors, symbols.deep, {
81
80
  enumerable: false,
82
81
  value: true,
83
82
  });
83
+
84
84
  return errors;
85
85
  }
@@ -1,11 +1,10 @@
1
1
  import {
2
2
  DeepObjectTree,
3
3
  Tree,
4
- deepMerge,
4
+ getTreeArgument,
5
5
  keysFromPath,
6
6
  } from "@weborigami/async-tree";
7
7
  import { InvokeFunctionsTransform } from "@weborigami/language";
8
- import getTreeArgument from "../../common/getTreeArgument.js";
9
8
  import crawlResources from "./crawlResources.js";
10
9
  import { addValueToObject, getBaseUrl } from "./utilities.js";
11
10
 
@@ -20,13 +19,12 @@ import { addValueToObject, getBaseUrl } from "./utilities.js";
20
19
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
21
20
  * @typedef {import("@weborigami/async-tree").Treelike} Treelike
22
21
  *
23
- * @this {AsyncTree|null}
24
22
  * @param {Treelike} treelike
25
23
  * @param {string} [baseHref]
26
24
  * @returns {Promise<AsyncTree>}
27
25
  */
28
26
  export default async function crawlBuiltin(treelike, baseHref) {
29
- const tree = await getTreeArgument(this, arguments, treelike, "crawl");
27
+ const tree = await getTreeArgument(treelike, "crawl");
30
28
  const baseUrl = getBaseUrl(baseHref, treelike);
31
29
 
32
30
  const cache = {};
@@ -55,7 +53,7 @@ export default async function crawlBuiltin(treelike, baseHref) {
55
53
  // Merge the cache on top of the resources tree. If we have an actual value
56
54
  // for something already, that's better than a function that will get that
57
55
  // value.
58
- const result = deepMerge(
56
+ const result = Tree.deepMerge(
59
57
  new DeepObjectTree(cache),
60
58
  new (InvokeFunctionsTransform(DeepObjectTree))(resources)
61
59
  );
@@ -41,15 +41,21 @@ function filterPaths(paths, baseUrl, localPath) {
41
41
  * Given a value retrieved from a site using a given key (name), determine what
42
42
  * kind of file it is and, based on that, find the paths it references.
43
43
  */
44
- export default function findPaths(value, key, baseUrl, localPath) {
44
+ export default async function findPaths(value, key, baseUrl, localPath) {
45
45
  const text = toString(value);
46
+ if (text === null) {
47
+ return {
48
+ crawlablePaths: [],
49
+ resourcePaths: [],
50
+ };
51
+ }
46
52
 
47
53
  // We guess the value is HTML is if its key has an .html extension or
48
54
  // doesn't have an extension, or the value starts with `<`.
49
55
  const ext = key ? extension.extname(key).toLowerCase() : "";
50
56
  let foundPaths;
51
57
  if (ext === ".html" || ext === ".htm" || ext === ".xhtml") {
52
- foundPaths = pathsInHtml(text);
58
+ foundPaths = await pathsInHtml(text);
53
59
  } else if (ext === ".css") {
54
60
  foundPaths = pathsInCss(text);
55
61
  } else if (ext === ".js") {
@@ -62,7 +68,7 @@ export default function findPaths(value, key, baseUrl, localPath) {
62
68
  foundPaths = pathsInSitemap(text);
63
69
  } else if (ext === "" && text?.trim().startsWith("<")) {
64
70
  // Probably HTML
65
- foundPaths = pathsInHtml(text);
71
+ foundPaths = await pathsInHtml(text);
66
72
  } else {
67
73
  // Doesn't have an extension we want to process
68
74
  return {
@@ -1,9 +1,10 @@
1
- import { JSDOM, VirtualConsole } from "jsdom";
1
+ import loadJsDom from "../../common/loadJsDom.js";
2
2
  import pathsInCss from "./pathsInCss.js";
3
3
  import pathsInJs from "./pathsInJs.js";
4
4
  import { addHref } from "./utilities.js";
5
5
 
6
- export default function pathsInHtml(html) {
6
+ export default async function pathsInHtml(html) {
7
+ const { JSDOM, VirtualConsole } = await loadJsDom();
7
8
  const paths = {
8
9
  /** @type {string[]} */
9
10
  crawlablePaths: [],
@@ -153,7 +154,7 @@ export default function pathsInHtml(html) {
153
154
  while ((match = noframesRegex.exec(html))) {
154
155
  const noframesHtml = match.groups?.html;
155
156
  if (noframesHtml) {
156
- const noframesPaths = pathsInHtml(noframesHtml);
157
+ const noframesPaths = await pathsInHtml(noframesHtml);
157
158
  paths.crawlablePaths.push(...noframesPaths.crawlablePaths);
158
159
  paths.resourcePaths.push(...noframesPaths.resourcePaths);
159
160
  }
package/src/dev/debug.js CHANGED
@@ -1,5 +1,4 @@
1
- import { Tree } from "@weborigami/async-tree";
2
- import getTreeArgument from "../common/getTreeArgument.js";
1
+ import { getTreeArgument, Tree } from "@weborigami/async-tree";
3
2
  import { isTransformApplied, transformObject } from "../common/utilities.js";
4
3
  import ExplorableSiteTransform from "./ExplorableSiteTransform.js";
5
4
  import OriCommandTransform from "./OriCommandTransform.js";
@@ -10,13 +9,11 @@ import OriCommandTransform from "./OriCommandTransform.js";
10
9
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
11
10
  * @typedef {import("@weborigami/async-tree").Treelike} Treelike
12
11
  *
13
- * @this {AsyncTree|null}
14
- * @param {Treelike} [treelike]
12
+ * @param {Treelike} treelike
13
+ * @returns {Promise<AsyncTree>}
15
14
  */
16
15
  export default async function debug(treelike) {
17
- // The debug command leaves the tree's existing scope intact; it does not
18
- // apply its own scope to the tree.
19
- let tree = await getTreeArgument(this, arguments, treelike, "debug");
16
+ let tree = await getTreeArgument(treelike, "debug");
20
17
 
21
18
  if (!isTransformApplied(DebugTransform, tree)) {
22
19
  tree = transformObject(DebugTransform, tree);
package/src/dev/dev.js CHANGED
@@ -1,7 +1,9 @@
1
+ import { Tree } from "@weborigami/async-tree";
2
+ export const clear = Tree.clear;
3
+ export const keys = Tree.keys;
4
+
1
5
  export { default as indexPage } from "../origami/indexPage.js";
2
6
  export { default as yaml } from "../origami/yaml.js";
3
- export { default as clear } from "../tree/clear.js";
4
- export { default as keys } from "../tree/keys.js";
5
7
  export { default as breakpoint } from "./breakpoint.js";
6
8
  export { default as changes } from "./changes.js";
7
9
  export { default as code } from "./code.js";
@@ -1,5 +1,5 @@
1
1
  /** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
2
- import { Tree, scope } from "@weborigami/async-tree";
2
+ import { Tree } from "@weborigami/async-tree";
3
3
  import { OrigamiFiles } from "@weborigami/language";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
@@ -29,7 +29,7 @@ export default async function explore(...keys) {
29
29
  if (!debugTree) {
30
30
  return undefined;
31
31
  }
32
- const debugScope = scope(debugTree);
32
+ const debugScope = await Tree.scope(debugTree);
33
33
  // HACK: reproduce logic of ExplorableSiteTransform that turns a trailing
34
34
  // slash into index.html. Calling `debug` applies that transform and the
35
35
  // transform should handle that logic, but unfortunately the `traverse`
@@ -41,7 +41,8 @@ export default async function explore(...keys) {
41
41
  result = await Tree.traverse(debugScope, ...keys);
42
42
  } else {
43
43
  // Return the Explore page for the current scope.
44
- const data = await getScopeData(scope(tree));
44
+ const scope = await Tree.scope(tree);
45
+ const data = await getScopeData(scope);
45
46
  templatePromise ??= loadTemplate();
46
47
  const template = await templatePromise;
47
48
  const text = await template.call(this, data);
package/src/dev/help.js CHANGED
@@ -2,18 +2,14 @@ import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "url";
4
4
  import YAML from "yaml";
5
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
6
5
  import version from "./version.js";
7
6
 
8
7
  /**
9
8
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
10
9
  *
11
- * @this {AsyncTree|null}
12
10
  * @param {string} [key]
13
11
  */
14
12
  export default async function help(key) {
15
- assertTreeIsDefined(this, "help");
16
-
17
13
  const helpFilename = path.resolve(
18
14
  fileURLToPath(import.meta.url),
19
15
  "../help.yaml"
package/src/dev/help.yaml CHANGED
@@ -175,12 +175,12 @@ Tree:
175
175
  cache:
176
176
  args: (tree, [cache])
177
177
  description: Caches values from the tree
178
+ calendar:
179
+ args: (options)
180
+ description: Return a tree structure for years/months/days
178
181
  clear:
179
182
  args: (tree)
180
183
  description: Remove all values from the tree
181
- concat:
182
- args: (...objs)
183
- description: Concatenate text and/or trees of text
184
184
  constant:
185
185
  args: (value)
186
186
  description: Return a deep tree with a single constant value
@@ -202,9 +202,9 @@ Tree:
202
202
  deepValues:
203
203
  args: (tree)
204
204
  description: The in-order leaf values of the tree
205
- defineds:
206
- args: (tree)
207
- description: Only the defined values of the tree
205
+ delete:
206
+ args: (tree, key)
207
+ description: Delete the value for the key from tree
208
208
  entries:
209
209
  args: (tree)
210
210
  description: The tree's [key, value] pairs
@@ -220,9 +220,6 @@ Tree:
220
220
  from:
221
221
  args: (object, options)
222
222
  description: Create a tree from an object
223
- fromFn:
224
- args: (fn, [keys])
225
- description: A tree defined by a value function
226
223
  globKeys:
227
224
  args: (patterns)
228
225
  description: A tree whose keys can include glob wildcard patterns
@@ -233,6 +230,7 @@ Tree:
233
230
  args: (tree, key)
234
231
  description: True if key exists in tree
235
232
  indent:
233
+ args: "`…`"
236
234
  description: Tagged template literal for normalizing indentation
237
235
  inners:
238
236
  args: (tree)
@@ -262,7 +260,7 @@ Tree:
262
260
  args: (tree, options)
263
261
  description: Create a new tree by mapping keys and/or values
264
262
  mapReduce:
265
- args: (tree, valueFn, reduceFn)
263
+ args: (tree, mapFn, reduceFn)
266
264
  description: Map values and reduce them
267
265
  mask:
268
266
  args: (source, mask)
@@ -288,9 +286,6 @@ Tree:
288
286
  regExpKeys:
289
287
  args: (tree)
290
288
  description: A tree whose keys are regular expression strings
291
- remove:
292
- args: (tree, key)
293
- description: Remove the value for the key from tree
294
289
  reverse:
295
290
  args: (tree)
296
291
  description: Reverse the order of the tree's keys
@@ -309,6 +304,9 @@ Tree:
309
304
  take:
310
305
  args: (tree, n)
311
306
  description: The first n values in the tree
307
+ text:
308
+ args: "`…`"
309
+ description: Tagged template literal for rendering trees
312
310
  traverse:
313
311
  args: (tree, ...keys)
314
312
  description: Return the value at the path of keys
@@ -321,3 +319,6 @@ Tree:
321
319
  values:
322
320
  args: (tree)
323
321
  description: The tree's values
322
+ withKeys:
323
+ args: (tree, keys)
324
+ description: Use the given keys for the tree
package/src/dev/log.js CHANGED
@@ -4,12 +4,11 @@ import yaml from "../origami/yaml.js";
4
4
  * Log the first argument to the console as a side effect and return the second
5
5
  * argument. If no second argument is provided, return the first argument.
6
6
  *
7
- * @this {import("@weborigami/types").AsyncTree|null}
8
7
  * @param {any} object
9
8
  * @param {any} [result]
10
9
  */
11
10
  export default async function log(result, object = result) {
12
- let text = object !== undefined ? await yaml.call(this, object) : "undefined";
11
+ let text = object !== undefined ? await yaml.call(null, object) : "undefined";
13
12
  text = text?.trim();
14
13
  console.log(text);
15
14
  return result;
package/src/dev/serve.js CHANGED
@@ -1,13 +1,10 @@
1
- import { Tree } from "@weborigami/async-tree";
1
+ import { getTreeArgument } from "@weborigami/async-tree";
2
2
  import http from "node:http";
3
3
  import { createServer } from "node:net";
4
4
  import process from "node:process";
5
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
6
5
  import { isTransformApplied, transformObject } from "../common/utilities.js";
7
6
  import { requestListener } from "../server/server.js";
8
- import debug from "./debug.js";
9
7
  import ExplorableSiteTransform from "./ExplorableSiteTransform.js";
10
- import watch from "./watch.js";
11
8
 
12
9
  const defaultPort = 5000;
13
10
 
@@ -19,22 +16,12 @@ const defaultPort = 5000;
19
16
  *
20
17
  * @param {Treelike} treelike
21
18
  * @param {number} [port]
22
- * @this {AsyncTree|null}
23
19
  */
24
20
  export default async function serve(treelike, port) {
25
- assertTreeIsDefined(this, "serve");
26
- let tree;
27
- if (treelike) {
28
- tree = Tree.from(treelike, { parent: this });
29
- if (!isTransformApplied(ExplorableSiteTransform, tree)) {
30
- tree = transformObject(ExplorableSiteTransform, tree);
31
- }
32
- } else if (arguments.length === 0) {
33
- // By default, watch the default tree and add default pages.
34
- const withDefaults = await debug.call(this);
35
- tree = await watch.call(this, withDefaults);
36
- } else {
37
- throw new Error("serve: no tree was provided to serve");
21
+ let tree = await getTreeArgument(treelike, "serve");
22
+
23
+ if (!isTransformApplied(ExplorableSiteTransform, tree)) {
24
+ tree = transformObject(ExplorableSiteTransform, tree);
38
25
  }
39
26
 
40
27
  if (port === undefined) {