@weborigami/origami 0.3.3 → 0.3.4-jse.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 (59) hide show
  1. package/main.js +1 -3
  2. package/package.json +4 -4
  3. package/src/BuiltinsTree.js +18 -0
  4. package/src/builtinsJse.js +67 -0
  5. package/src/builtinsShell.js +52 -0
  6. package/src/cli/getConfig.js +10 -0
  7. package/src/common/documentObject.js +8 -2
  8. package/src/common/fetchAndHandleExtension.js +3 -2
  9. package/src/common/utilities.js +2 -2
  10. package/src/dev/ExplorableSiteTransform.js +2 -2
  11. package/src/dev/crawler/crawlResources.js +1 -1
  12. package/src/dev/crawler/pathsInHtml.js +2 -0
  13. package/src/dev/explore.js +3 -8
  14. package/src/dev/explore.js.inline +2 -2
  15. package/src/dev/explore.ori +6 -6
  16. package/src/handlers/css.handler.js +2 -2
  17. package/src/handlers/handlerBuiltins.js +26 -0
  18. package/src/handlers/handlers.js +36 -40
  19. package/src/handlers/htm.handler.js +1 -1
  20. package/src/handlers/html.handler.js +2 -2
  21. package/src/handlers/jpg.handler.js +1 -1
  22. package/src/handlers/js.handler.js +1 -1
  23. package/src/handlers/jse.handler.js +17 -0
  24. package/src/handlers/jsedocument.handler.js +17 -0
  25. package/src/handlers/md.handler.js +2 -2
  26. package/src/handlers/mjs.handler.js +1 -1
  27. package/src/handlers/ori.handler.js +15 -5
  28. package/src/handlers/oridocument.handler.js +15 -2
  29. package/src/{common → handlers}/processUnpackedContent.js +1 -3
  30. package/src/handlers/ts.handler.js +1 -1
  31. package/src/handlers/txt.handler.js +9 -1
  32. package/src/handlers/wasm.handler.js +1 -1
  33. package/src/handlers/yaml.handler.js +1 -1
  34. package/src/handlers/yml.handler.js +1 -1
  35. package/src/help/help.yaml +1 -11
  36. package/src/origami/config.js +2 -4
  37. package/src/origami/ori.js +17 -4
  38. package/src/origami/origami.js +0 -5
  39. package/src/origami/project.js +66 -56
  40. package/src/origami/regexMatch.js +4 -0
  41. package/src/protocols/files.js +2 -1
  42. package/src/protocols/inherited.js +6 -3
  43. package/src/protocols/new.js +4 -0
  44. package/src/protocols/node.js +13 -0
  45. package/src/protocols/scope.js +3 -3
  46. package/src/site/{index.js → indexPage.js} +1 -1
  47. package/src/site/site.js +1 -1
  48. package/src/site/sitemap.js +3 -4
  49. package/src/site/static.js +1 -1
  50. package/src/text/inline.js +19 -14
  51. package/src/text/mdHtml.js +2 -1
  52. package/src/tree/map.js +1 -1
  53. package/src/builtins.js +0 -58
  54. package/src/builtinsTree.js +0 -36
  55. package/src/calc/calc.js +0 -81
  56. package/src/handlers/handlerExports.js +0 -16
  57. package/src/internal.js +0 -24
  58. package/src/js.js +0 -38
  59. package/src/node.js +0 -22
@@ -1 +1 @@
1
- export { default as default } from "./js.handler.js";
1
+ export { jsHandler as default } from "./handlers.js";
@@ -39,7 +39,8 @@ export default {
39
39
  throw new TypeError("The input to pack must be a JavaScript object.");
40
40
  }
41
41
 
42
- const text = object["@text"] ?? "";
42
+ // TODO: Deprecate @text
43
+ const text = object._body ?? object["@text"] ?? "";
43
44
 
44
45
  /** @type {any} */
45
46
  const dataWithoutText = Object.assign({}, object);
@@ -72,7 +73,14 @@ export default {
72
73
  } else {
73
74
  frontData = parseYaml(frontText);
74
75
  }
76
+ // TODO: Deprecate @text
75
77
  unpacked = Object.assign({}, frontData, { "@text": body });
78
+ Object.defineProperty(unpacked, "_body", {
79
+ configurable: true,
80
+ value: body,
81
+ enumerable: false, // TODO: Make enumerable
82
+ writable: true,
83
+ });
76
84
  } else {
77
85
  // Plain text
78
86
  unpacked = new String(text);
@@ -1,4 +1,4 @@
1
- import { processUnpackedContent } from "../internal.js";
1
+ import processUnpackedContent from "./processUnpackedContent.js";
2
2
 
3
3
  /**
4
4
  * A WebAssembly module
@@ -2,7 +2,7 @@ import { symbols } from "@weborigami/async-tree";
2
2
  import * as YAMLModule from "yaml";
3
3
  import { parseYaml } from "../common/serialize.js";
4
4
  import * as utilities from "../common/utilities.js";
5
- import { processUnpackedContent } from "../internal.js";
5
+ import processUnpackedContent from "./processUnpackedContent.js";
6
6
 
7
7
  // See notes at serialize.js
8
8
  // @ts-ignore
@@ -1,2 +1,2 @@
1
1
  // .yml is a synonym for .yaml
2
- export { yamlHandler as default } from "../internal.js";
2
+ export { default } from "./yaml.handler.js";
@@ -135,17 +135,7 @@ new:
135
135
  description: Create instances of JavaScript classes
136
136
 
137
137
  node:
138
- description: Node.js classes and modules
139
- collection: true
140
- commands:
141
- Buffer:
142
- description: Node.js Buffer class
143
- path:
144
- description: Node.js path module
145
- process:
146
- description: Node.js process object
147
- url:
148
- description: Node.js URL module
138
+ description: Node.js modules
149
139
 
150
140
  origami:
151
141
  description: Perform general Origami language functions
@@ -13,8 +13,6 @@ import project from "./project.js";
13
13
  */
14
14
  export default async function config(key) {
15
15
  const projectTree = await project.call(this);
16
- // HACK: We use specific knowledge of how @project returns a tree to get the
17
- // config. The config is always the parent of the project folder.
18
- const parent = projectTree.parent;
19
- return key === undefined ? parent : parent.get(key);
16
+ const projectConfig = projectTree.config;
17
+ return key === undefined ? projectConfig : projectConfig[key];
20
18
  }
@@ -4,7 +4,8 @@ import {
4
4
  toString,
5
5
  } from "@weborigami/async-tree";
6
6
  import { compile } from "@weborigami/language";
7
- import builtinsTree from "../builtinsTree.js";
7
+ import builtinsShell from "../builtinsShell.js";
8
+ import getConfig from "../cli/getConfig.js";
8
9
  import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
9
10
  import { toYaml } from "../common/serialize.js";
10
11
 
@@ -28,13 +29,25 @@ export default async function ori(
28
29
  // In case expression has come from a file, cast it to a string.
29
30
  expression = toString(expression);
30
31
 
31
- // Run in the context of `this` if defined, otherwise use the builtins.
32
- const tree = this ?? builtinsTree;
32
+ // Run in the context of `this` if defined
33
+ const tree = this;
34
+
35
+ const config = getConfig(tree);
36
+ const globals = config
37
+ ? {
38
+ ...builtinsShell(),
39
+ ...config,
40
+ }
41
+ : builtinsShell();
33
42
 
34
43
  // Compile the expression. Avoid caching scope references so that, e.g.,
35
44
  // passing a function to the `watch` builtin will always look the current
36
45
  // value of things in scope.
37
- const fn = compile.expression(expression, { scopeCaching: false });
46
+ const fn = compile.expression(expression, {
47
+ globals,
48
+ mode: "shell",
49
+ scopeCaching: false,
50
+ });
38
51
 
39
52
  // Execute
40
53
  let result = await fn.call(tree);
@@ -1,8 +1,3 @@
1
- // Use a dynamic import to avoid circular dependencies
2
- export const builtins = import("../internal.js").then(
3
- (internal) => internal.builtinsTree
4
- );
5
-
6
1
  export { extension } from "@weborigami/async-tree";
7
2
  export { toFunction } from "../common/utilities.js";
8
3
 
@@ -1,13 +1,16 @@
1
1
  /** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
2
- import { Tree } from "@weborigami/async-tree";
3
2
  import { OrigamiFiles } from "@weborigami/language";
4
3
  import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
5
- import { builtinsTree, oriHandler } from "../internal.js";
4
+ import handlerBuiltins from "../handlers/handlerBuiltins.js";
5
+ import { oriHandler } from "../handlers/handlers.js";
6
6
 
7
7
  const configFileName = "config.ori";
8
8
 
9
9
  /**
10
- * Return the tree for the current project's root folder.
10
+ * Return an object for the current project including
11
+ *
12
+ * `config`: the evaluated config.ori file
13
+ * `root`: the project's root folder
11
14
  *
12
15
  * This searches the current directory and its ancestors for an Origami file
13
16
  * called `config.ori`. If an Origami configuration file is found, the
@@ -19,81 +22,88 @@ const configFileName = "config.ori";
19
22
  * returned as a tree, with the builtins as its parent.
20
23
  *
21
24
  * @this {AsyncTree|null}
22
- * @param {any} [key]
23
25
  */
24
- export default async function project(key) {
26
+ export default async function project() {
25
27
  assertTreeIsDefined(this, "origami:project");
26
28
 
27
29
  const dirname = process.cwd();
28
30
  const currentTree = new OrigamiFiles(dirname);
29
- currentTree.parent = builtinsTree;
31
+ let config;
30
32
 
31
33
  // Search up the tree for the configuration file or package.json to determine
32
34
  // the project root.
33
- const configContainer =
34
- (await findAncestorFile(currentTree, configFileName)) ??
35
- (await findAncestorFile(currentTree, "package.json"));
36
-
37
- let projectRoot;
38
- if (!configContainer) {
39
- // No configuration file or package.json found; use the current directory.
40
- projectRoot = currentTree;
35
+ let root;
36
+ const foundConfig = await findAncestorFile(currentTree, configFileName);
37
+ if (foundConfig) {
38
+ root = foundConfig.container;
39
+ // Unpack Origami configuration file
40
+ const buffer = foundConfig.value;
41
+ config = await oriHandler.unpack(buffer, {
42
+ key: configFileName,
43
+ parent: root,
44
+ });
45
+ root.config = config;
41
46
  } else {
42
- // Load the configuration file if one exists.
43
- const buffer = await configContainer.get(configFileName);
44
- if (!buffer) {
45
- // Project root defined by package.json
46
- projectRoot = configContainer;
47
+ // No Origami configuration file, look for package.json
48
+ const foundPackageJson = await findAncestorFile(
49
+ currentTree,
50
+ "package.json"
51
+ );
52
+ if (foundPackageJson) {
53
+ // Found package.json; use its parent as the project root
54
+ root = foundPackageJson.container;
47
55
  } else {
48
- // Load Origami configuration file
49
- const config = await oriHandler.unpack(buffer, {
50
- key: configFileName,
51
- parent: configContainer,
52
- });
53
- if (!config) {
54
- const configPath = /** @type {any} */ (configContainer).path;
55
- throw new Error(
56
- `Couldn't load the Origami configuration in ${configPath}/${configFileName}`
57
- );
58
- }
59
-
60
- // The config tree may refer to the container tree *and vice versa*. To
61
- // support this, we put the container in the tree twice. The chain will
62
- // be: projectRoot -> configTree -> configContainer -> builtins, where
63
- // the projectRoot and configContainer are the same folder.
64
- const configTree = Tree.from(config);
65
- projectRoot = new OrigamiFiles(configContainer.path);
66
- projectRoot.parent = configTree;
67
- configTree.parent = configContainer;
68
- configContainer.parent = builtinsTree;
56
+ // No package.json found; use the current directory as root
57
+ root = currentTree;
69
58
  }
70
59
  }
71
60
 
72
- return key === undefined ? projectRoot : projectRoot.get(key);
61
+ // Merge config if present into handlers
62
+ root.handlers = config
63
+ ? {
64
+ ...handlerBuiltins(),
65
+ ...configHandlers(config),
66
+ }
67
+ : handlerBuiltins();
68
+
69
+ return root;
73
70
  }
74
71
 
75
- // Return the first ancestor of the given tree that contains a file with the
76
- // given name.
72
+ // Find the first ancestor of the given folder that contains a file with the
73
+ // given name. Return the container and the file contents.
77
74
  async function findAncestorFile(start, fileName) {
78
- let current = start;
79
- while (current) {
80
- const value = await current.get(fileName);
75
+ let container = start;
76
+ while (container) {
77
+ const value = await container.get(fileName);
81
78
  if (value) {
82
- // Found the desired file; its container is the project root. Set the
83
- // parent to the builtins; in the context of this project, there's nothing
84
- // higher up.
85
- current.parent = builtinsTree;
86
- return current;
79
+ // Found the desired file
80
+ return {
81
+ container,
82
+ value,
83
+ };
87
84
  }
88
- // Not found; try the parent.
89
- const parent = await current.get("..");
85
+ // Not found; try the parent
86
+ const parent = await container.get("..");
90
87
  if (
91
88
  !parent ||
92
- (parent.path && current.path && parent.path === current.path)
89
+ (parent.path && container.path && parent.path === container.path)
93
90
  ) {
94
91
  break;
95
92
  }
96
- current = parent;
93
+ container = parent;
94
+ }
95
+
96
+ // Not found
97
+ return null;
98
+ }
99
+
100
+ // Return an object with all `.handler` keys from the config
101
+ function configHandlers(config) {
102
+ const handlers = {};
103
+ for (const key in config) {
104
+ if (key.endsWith(".handler")) {
105
+ handlers[key] = config[key];
106
+ }
97
107
  }
98
- return undefined;
108
+ return handlers;
99
109
  }
@@ -1,6 +1,10 @@
1
1
  const parsers = {};
2
2
 
3
+ // TODO: Remove this deprecated function
3
4
  export default function regexMatch(text, regex) {
5
+ console.warn(
6
+ "warning: regexMatch is deprecated, use a JavaScript regular expression instead."
7
+ );
4
8
  if (!parsers[regex]) {
5
9
  const regexp = new RegExp(regex);
6
10
  parsers[regex] = (input) => input.match(regexp)?.groups;
@@ -1,4 +1,4 @@
1
- import { OrigamiFiles } from "@weborigami/language";
1
+ import { OrigamiFiles, getHandlers } from "@weborigami/language";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import process from "node:process";
@@ -26,5 +26,6 @@ export default async function files(...keys) {
26
26
  const resolved = path.resolve(basePath, relativePath);
27
27
 
28
28
  const result = new OrigamiFiles(resolved);
29
+ result.handlers = getHandlers(this);
29
30
  return result;
30
31
  }
@@ -1,5 +1,4 @@
1
- import { Tree } from "@weborigami/async-tree";
2
- import { ops } from "@weborigami/language";
1
+ import { scope, Tree } from "@weborigami/async-tree";
3
2
  import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
4
3
 
5
4
  /**
@@ -13,6 +12,10 @@ import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
13
12
  export default async function inherited(...keys) {
14
13
  assertTreeIsDefined(this, "inherited:");
15
14
  const key = keys.shift();
16
- const value = await ops.inherited.call(this, key);
15
+ if (!this?.parent) {
16
+ return undefined;
17
+ }
18
+ const parentScope = scope(this.parent);
19
+ const value = await parentScope.get(key);
17
20
  return keys.length > 0 ? await Tree.traverse(value, ...keys) : value;
18
21
  }
@@ -13,12 +13,16 @@ import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
13
13
  export default async function instantiate(...keys) {
14
14
  assertTreeIsDefined(this, "new:");
15
15
  let constructor;
16
+
16
17
  const scope = this ? scopeFn(this) : null;
17
18
  if (
18
19
  keys.length === 1 &&
19
20
  (typeof keys[0] === "object" || typeof keys[0] === "function")
20
21
  ) {
21
22
  constructor = keys[0];
23
+ } else if (globalThis[keys[0]]) {
24
+ // Backward compat
25
+ constructor = globalThis[keys[0]];
22
26
  } else if (scope) {
23
27
  constructor = await Tree.traverseOrThrow(scope, ...keys);
24
28
  } else {
@@ -0,0 +1,13 @@
1
+ import { trailingSlash, Tree } from "@weborigami/async-tree";
2
+
3
+ /**
4
+ * The node: protocol does a dynamic import from the `node:` namespace.
5
+ *
6
+ * @param {string[]} keys
7
+ */
8
+ export default async function node(...keys) {
9
+ const key = keys.shift();
10
+ const normalized = trailingSlash.remove(key);
11
+ const module = await import(`node:${normalized}`);
12
+ return keys.length > 0 ? Tree.traverse(module, ...keys) : module;
13
+ }
@@ -1,5 +1,4 @@
1
- import { Tree } from "@weborigami/async-tree";
2
- import { ops } from "@weborigami/language";
1
+ import { Tree, scope as scopeFn } from "@weborigami/async-tree";
3
2
 
4
3
  /**
5
4
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
@@ -12,7 +11,8 @@ export default async function scope(...keys) {
12
11
  let value;
13
12
  try {
14
13
  // Look up key in scope but don't throw if it's undefined
15
- value = await ops.scope.call(this, key);
14
+ const thisScope = scopeFn(this);
15
+ value = await thisScope.get(key);
16
16
  } catch (error) {
17
17
  if (error instanceof ReferenceError) {
18
18
  value = undefined;
@@ -10,7 +10,7 @@ import { getDescriptor } from "../common/utilities.js";
10
10
  * @param {Treelike} [treelike]
11
11
  * @param {string} [basePath]
12
12
  */
13
- export default async function index(treelike, basePath) {
13
+ export default async function indexPage(treelike, basePath) {
14
14
  const tree = await getTreeArgument(this, arguments, treelike, "site:index");
15
15
  const keys = Array.from(await tree.keys());
16
16
 
package/src/site/site.js CHANGED
@@ -1,4 +1,4 @@
1
- export { default as index } from "./index.js";
1
+ export { default as indexPage } from "./indexPage.js";
2
2
  export { default as jsonKeys } from "./jsonKeys.js";
3
3
  export { default as redirect } from "./redirect.js";
4
4
  export { default as rss } from "./rss.js";
@@ -1,11 +1,11 @@
1
1
  import { Tree } from "@weborigami/async-tree";
2
2
  import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
3
3
  import getTreeArgument from "../common/getTreeArgument.js";
4
- import { builtinsTree, oriHandler } from "../internal.js";
4
+ import { oriHandler } from "../handlers/handlers.js";
5
5
 
6
6
  const templateText = `(urls) => \`<?xml version="1.0" encoding="UTF-8"?>
7
7
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
8
- \${ map(urls, (url) => \` <url>
8
+ \${ Tree.map(urls, (url) => \` <url>
9
9
  <loc>\${ url }</loc>
10
10
  </url>
11
11
  \`) }</urlset>
@@ -48,7 +48,6 @@ export default async function sitemap(treelike, baseHref = "") {
48
48
  .map((path) => (path.endsWith("index.html") ? path.slice(0, -10) : path));
49
49
 
50
50
  const templateFn = await oriHandler.unpack(templateText);
51
- const target = this ?? builtinsTree;
52
- const templateResult = await templateFn.call(target, htmlPaths);
51
+ const templateResult = await templateFn.call(this, htmlPaths);
53
52
  return String(templateResult);
54
53
  }
@@ -1,7 +1,7 @@
1
1
  import { Tree, jsonKeys } from "@weborigami/async-tree";
2
2
  import getTreeArgument from "../common/getTreeArgument.js";
3
3
  import { transformObject } from "../common/utilities.js";
4
- import index from "./index.js";
4
+ import index from "./indexPage.js";
5
5
 
6
6
  /**
7
7
  * Expose common static keys (index.html, .keys.json) for a tree.
@@ -1,12 +1,7 @@
1
- import {
2
- isUnpackable,
3
- ObjectTree,
4
- symbols,
5
- toString,
6
- } from "@weborigami/async-tree";
1
+ import { isUnpackable, symbols, toString } from "@weborigami/async-tree";
7
2
  import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
8
3
  import documentObject from "../common/documentObject.js";
9
- import { oridocumentHandler } from "../internal.js";
4
+ import { jsedocumentHandler } from "../handlers/handlers.js";
10
5
 
11
6
  /**
12
7
  * Inline any Origami expressions found inside ${...} placeholders in the input
@@ -25,8 +20,11 @@ export default async function inline(input) {
25
20
  if (isUnpackable(input)) {
26
21
  input = await input.unpack();
27
22
  }
28
- const inputIsDocument = input["@text"] !== undefined;
29
- const origami = inputIsDocument ? input["@text"] : toString(input);
23
+ const inputIsDocument =
24
+ input["@text"] !== undefined || input._body !== undefined;
25
+ const origami = inputIsDocument
26
+ ? input["@text"] ?? input._body
27
+ : toString(input);
30
28
  if (origami === null) {
31
29
  return undefined;
32
30
  }
@@ -36,15 +34,22 @@ export default async function inline(input) {
36
34
  /** @type {any} */ (input)[symbols.parent] ??
37
35
  this;
38
36
 
39
- let extendedParent = parent;
37
+ let front;
40
38
  if (inputIsDocument) {
41
- extendedParent = new ObjectTree(input);
42
- extendedParent.parent = parent;
39
+ // Collect all document properties except the body
40
+ front = Object.fromEntries(
41
+ Object.entries(input).filter(
42
+ ([key]) => key !== "@text" && key !== "_body"
43
+ )
44
+ );
45
+ } else {
46
+ front = null;
43
47
  }
44
48
 
45
49
  // @ts-ignore
46
- let result = await oridocumentHandler.unpack(input, {
47
- parent: extendedParent,
50
+ let result = await jsedocumentHandler.unpack(origami, {
51
+ front,
52
+ parent,
48
53
  });
49
54
 
50
55
  if (result instanceof Function) {
@@ -47,7 +47,8 @@ export default async function mdHtml(input) {
47
47
  if (isUnpackable(input)) {
48
48
  input = await input.unpack();
49
49
  }
50
- const inputIsDocument = input["@text"] !== undefined;
50
+ const inputIsDocument =
51
+ input["@text"] !== undefined || input._body !== undefined;
51
52
  const markdown = toString(input);
52
53
  if (markdown === null) {
53
54
  throw new Error("mdHtml: The provided input couldn't be treated as text.");
package/src/tree/map.js CHANGED
@@ -69,7 +69,7 @@ function extendedOptions(context, operation) {
69
69
  options = {};
70
70
  } else {
71
71
  throw new TypeError(
72
- `map: You must specify a value function or options dictionary as the first parameter.`
72
+ `map: You must specify a value function or options dictionary as the second parameter.`
73
73
  );
74
74
  }
75
75
 
package/src/builtins.js DELETED
@@ -1,58 +0,0 @@
1
- import * as calc from "./calc/calc.js";
2
- import * as dev from "./dev/dev.js";
3
- import * as handlers from "./handlers/handlers.js";
4
- import help from "./help/help.js";
5
- import * as image from "./image/image.js";
6
- import js from "./js.js";
7
- import node from "./node.js";
8
- import * as origami from "./origami/origami.js";
9
- import explore from "./protocols/explore.js";
10
- import files from "./protocols/files.js";
11
- import http from "./protocols/http.js";
12
- import https from "./protocols/https.js";
13
- import httpstree from "./protocols/httpstree.js";
14
- import httptree from "./protocols/httptree.js";
15
- import inherited from "./protocols/inherited.js";
16
- import instantiate from "./protocols/new.js";
17
- import packageNamespace from "./protocols/package.js";
18
- import scope from "./protocols/scope.js";
19
- import * as site from "./site/site.js";
20
- import * as text from "./text/text.js";
21
- import * as tree from "./tree/tree.js";
22
-
23
- /** @type {any} */
24
- export default {
25
- "calc:": adjustReservedWords(calc),
26
- "dev:": dev,
27
- "explore:": explore,
28
- "files:": files,
29
- "help:": help,
30
- "http:": http,
31
- "https:": https,
32
- "httpstree:": httpstree,
33
- "httptree:": httptree,
34
- "image:": image,
35
- "inherited:": inherited,
36
- "js:": js,
37
- "new:": instantiate,
38
- "node:": node,
39
- "origami:": origami,
40
- "package:": packageNamespace,
41
- "scope:": scope,
42
- "site:": adjustReservedWords(site),
43
- "text:": text,
44
- "tree:": tree,
45
-
46
- // Some builtins need to be exposed at top level
47
- ...handlers.default,
48
- };
49
-
50
- // Handle cases where a builtin name conflicts with a JS reserved word
51
- function adjustReservedWords(obj) {
52
- const result = {};
53
- for (const [key, value] of Object.entries(obj)) {
54
- const name = value.key ?? key;
55
- result[name] = value;
56
- }
57
- return result;
58
- }
@@ -1,36 +0,0 @@
1
- import { trailingSlash } from "@weborigami/async-tree";
2
- import builtins from "./builtins.js";
3
-
4
- const expanded = { ...builtins };
5
-
6
- // For all builtins like `tree:keys`, add a shorthand `keys`.
7
- for (const [key, value] of Object.entries(expanded)) {
8
- const isNamespace = key.endsWith(":");
9
- if (isNamespace) {
10
- for (const [subKey, subValue] of Object.entries(value)) {
11
- // HACK: Skip description keys until we can make them all non-enumerable.
12
- if (subKey === "description") {
13
- continue;
14
- }
15
- if (subKey in expanded) {
16
- throw new Error(`Internal Origami error: Duplicate key: ${subKey}`);
17
- }
18
- expanded[subKey] = subValue;
19
- }
20
- }
21
- }
22
-
23
- // We create our own tree instead of using ObjectTree, since that binds the
24
- // functions would be bound to the object. We want to leave them unbound.
25
- class BuiltinsTree {
26
- async get(key) {
27
- const normalizedKey = trailingSlash.remove(key);
28
- return expanded[normalizedKey];
29
- }
30
-
31
- async keys() {
32
- return Object.keys(expanded);
33
- }
34
- }
35
-
36
- export default new BuiltinsTree();