@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
@@ -5,7 +5,12 @@
5
5
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
6
6
  */
7
7
 
8
- import { Tree, isPlainObject, isStringLike } from "@weborigami/async-tree";
8
+ import {
9
+ Tree,
10
+ isPlainObject,
11
+ isStringLike,
12
+ isUnpackable,
13
+ } from "@weborigami/async-tree";
9
14
  import { OrigamiTree } from "@weborigami/language";
10
15
  import * as YAMLModule from "yaml";
11
16
  import yamlOrigamiTag from "../misc/yamlOrigamiTag.js";
@@ -90,40 +95,76 @@ export async function toJson(obj) {
90
95
  }
91
96
 
92
97
  /**
93
- * Convert the given object to a corresponding JSON value that can be serialized
94
- * as JSON or YAML.
98
+ * Convert the given object to a corresponding JSON value that can be
99
+ * represented as JSON or YAML.
95
100
  *
96
- * If the object is already a JSON value, it is returned as is.
101
+ * @param {any} object
102
+ * @returns {Promise<JsonValue>}
103
+ */
104
+ export async function toJsonValue(object) {
105
+ return toValue(object, true);
106
+ }
107
+
108
+ /**
109
+ * Convert the given input to the plainest possible JavaScript value. This
110
+ * helper is intended for functions that want to accept an argument from the ori
111
+ * CLI, which could a string, a file buffer, an ArrayBuffer from a URL, or some
112
+ * other kind of JavaScript object.
97
113
  *
98
- * If the object implements the `pack()` method, that method's result will be
99
- * returned.
114
+ * If the input implements the `unpack()` method, the input will be unpacked and
115
+ * before processing.
100
116
  *
101
- * If the object is treelike, it will be converted to a plain JavaScript
102
- * object, recursively traversing the tree and converting all values to native
103
- * types.
117
+ * If the input is treelike, it will be converted to a plain JavaScript object,
118
+ * recursively traversing the tree and converting all values to plain types.
104
119
  *
105
- * If the object has a `valueOf()` or `toString()` method, that method's result
106
- * will be returned.
120
+ * If the input is stringlike, its text will be returned.
107
121
  *
108
- * @param {any} object
109
- * @returns {Promise<JsonValue>}
122
+ * If the input is a Buffer or ArrayBuffer, it will be interpreted as UTF-8
123
+ * text.
124
+ *
125
+ * If the input has a custom class instance, its public properties will be
126
+ * returned as a plain object.
127
+ *
128
+ * The `jsonValuesOnly` parameter can be set to `true` to ensure that the
129
+ * returned value can be represented as JSON. If the input can't be represented
130
+ * as JSON, an error is thrown.
131
+ *
132
+ * @param {any} input
133
+ * @param {boolean} [jsonValuesOnly]
134
+ * @returns {Promise<any>}
110
135
  */
111
- export async function toJsonValue(object) {
112
- if (isJsonValue(object)) {
113
- return object;
114
- } else if (object && typeof object.pack === "function") {
115
- return object.pack();
116
- } else if (isStringLike(object) && !(object instanceof Array)) {
117
- return String(object);
118
- } else if (Tree.isTreelike(object)) {
119
- const mapped = await Tree.map(object, (value) => toJsonValue(value));
136
+ export async function toValue(input, jsonValuesOnly = false) {
137
+ if (input instanceof Promise) {
138
+ // Resolve promise before processing.
139
+ return toValue(await input, jsonValuesOnly);
140
+ } else if (isJsonValue(input)) {
141
+ return input;
142
+ } else if (typeof input !== "object") {
143
+ if (jsonValuesOnly) {
144
+ throw new TypeError(`Couldn't serialize value to JSON: ${input}`);
145
+ } else {
146
+ return input;
147
+ }
148
+ } else if (isUnpackable(input)) {
149
+ // Unpack first, then convert to JSON value.
150
+ const unpacked = await input.unpack();
151
+ return toValue(unpacked);
152
+ } else if (isStringLike(input) && !(input instanceof Array)) {
153
+ return String(input);
154
+ } else if (Tree.isTreelike(input)) {
155
+ const mapped = await Tree.map(input, (value) => toValue(value));
120
156
  return Tree.plain(mapped);
121
- } else if (object instanceof ArrayBuffer || object instanceof TypedArray) {
122
- // Serialize data as UTF-8.
123
- return textDecoder.decode(object);
157
+ } else if (input instanceof ArrayBuffer || input instanceof TypedArray) {
158
+ // Interpret input as UTF-8 text.
159
+ return textDecoder.decode(input);
160
+ } else {
161
+ // Some other kind of class instance; return its public properties.
162
+ const plain = {};
163
+ for (const [key, value] of Object.entries(input)) {
164
+ plain[key] = await toValue(value);
165
+ }
166
+ return plain;
124
167
  }
125
-
126
- throw new TypeError("Couldn't serialize object");
127
168
  }
128
169
 
129
170
  /**
@@ -1,4 +1,9 @@
1
- import { Tree, isPlainObject, isStringLike } from "@weborigami/async-tree";
1
+ import {
2
+ Tree,
3
+ isPlainObject,
4
+ isStringLike,
5
+ isUnpackable,
6
+ } from "@weborigami/async-tree";
2
7
 
3
8
  const textDecoder = new TextDecoder();
4
9
  const TypedArray = Object.getPrototypeOf(Uint8Array);
@@ -57,16 +62,13 @@ export function toFunction(obj) {
57
62
  if (typeof obj === "function") {
58
63
  // Return a function as is.
59
64
  return obj;
60
- } else if (
61
- typeof obj === "object" &&
62
- typeof (/** @type {any} */ (obj)?.unpack) === "function"
63
- ) {
65
+ } else if (isUnpackable(obj)) {
64
66
  // Extract the contents of the object and convert that to a function.
65
67
  let fn;
66
68
  /** @this {any} */
67
69
  return async function (...args) {
68
70
  if (!fn) {
69
- const content = await /** @type {any} */ (obj).unpack();
71
+ const content = await obj.unpack();
70
72
  fn = toFunction(content);
71
73
  }
72
74
  return fn.call(this, ...args);
@@ -100,7 +102,7 @@ export function toString(object) {
100
102
  if (isPlainObject(object) && "@text" in object) {
101
103
  return object["@text"];
102
104
  } else if (object instanceof ArrayBuffer || object instanceof TypedArray) {
103
- // Serialize data as UTF-8.
105
+ // Treat the buffer as UTF-8 text.
104
106
  const decoded = textDecoder.decode(object);
105
107
  // If the result has non-printable characters, it's probably not a string.
106
108
  return hasNonPrintableCharacters(decoded) ? null : decoded;
@@ -1,5 +1,6 @@
1
- import { Tree } from "@weborigami/async-tree";
1
+ import { Tree, isUnpackable } from "@weborigami/async-tree";
2
2
  import { isTreelike } from "@weborigami/async-tree/src/Tree.js";
3
+ import { Scope } from "@weborigami/language";
3
4
  import assertScopeIsDefined from "./assertScopeIsDefined.js";
4
5
 
5
6
  /**
@@ -29,8 +30,17 @@ export default async function getTreeArgument(
29
30
  assertScopeIsDefined(scope);
30
31
 
31
32
  if (treelike !== undefined) {
33
+ if (isUnpackable(treelike)) {
34
+ treelike = await treelike.unpack();
35
+ }
32
36
  if (isTreelike(treelike)) {
33
- return Tree.from(treelike);
37
+ let tree = Tree.from(treelike);
38
+ // If the tree was created from a treelike object and does not yet have a
39
+ // parent or scope, put it in the current scope.
40
+ if (!tree.parent && !(/** @type {any} */ (tree).scope)) {
41
+ tree = Scope.treeWithScope(tree, scope);
42
+ }
43
+ return tree;
34
44
  }
35
45
  throw new Error(
36
46
  `${methodName}: The first argument must be a tree, like an array, object, or files.`
@@ -78,7 +78,12 @@ async function statements(tree, nodePath, nodeLabel, options) {
78
78
  } else {
79
79
  const label = isStringLike(value)
80
80
  ? String(value)
81
- : await serialize.toYaml(value);
81
+ : value != null
82
+ ? await serialize.toYaml(value)
83
+ : "";
84
+ if (value == null) {
85
+ isError = true;
86
+ }
82
87
  nodes[key] = { label };
83
88
  if (isError) {
84
89
  nodes[key].isError = true;
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  SiteTree,
3
3
  Tree,
4
+ isPacked,
4
5
  isPlainObject,
5
6
  isStringLike,
6
7
  } from "@weborigami/async-tree";
@@ -30,8 +31,16 @@ export default async function constructResponse(request, resource) {
30
31
 
31
32
  // Determine media type, what data we'll send, and encoding.
32
33
  const url = new URL(request.url ?? "", `https://${request.headers.host}`);
33
- const extension = extname(url.pathname).toLowerCase();
34
- let mediaType = extension ? mediaTypeForExtension[extension] : undefined;
34
+
35
+ let mediaType;
36
+ if (resource.mediaType) {
37
+ // Resource indicates its own media type.
38
+ mediaType = resource.mediaType;
39
+ } else {
40
+ // Infer expected media type from file extension on request URL.
41
+ const extension = extname(url.pathname).toLowerCase();
42
+ mediaType = extension ? mediaTypeForExtension[extension] : undefined;
43
+ }
35
44
 
36
45
  if (
37
46
  mediaType === undefined &&
@@ -50,12 +59,16 @@ export default async function constructResponse(request, resource) {
50
59
  });
51
60
  }
52
61
 
53
- // If the request is for a JSON or YAML result, and the resource we got
54
- // isn't yet a string or Buffer, convert the resource to JSON or YAML now.
62
+ if (!isPacked(resource) && typeof resource.pack === "function") {
63
+ resource = await resource.pack();
64
+ }
65
+
55
66
  if (
56
67
  (mediaType === "application/json" || mediaType === "text/yaml") &&
57
68
  !isStringLike(resource)
58
69
  ) {
70
+ // The request is for a JSON or YAML result, and the resource we got isn't
71
+ // yet a string or Buffer: convert the resource to JSON or YAML now.
59
72
  const tree = Tree.from(resource);
60
73
  resource =
61
74
  mediaType === "text/yaml"
@@ -92,7 +105,7 @@ export default async function constructResponse(request, resource) {
92
105
 
93
106
  // If we didn't get back some kind of data that response.write() accepts,
94
107
  // assume it was an error.
95
- const validResponse = typeof body === "string" || body instanceof TypedArray;
108
+ const validResponse = isPacked(body);
96
109
  if (!validResponse) {
97
110
  const typeName = body?.constructor?.name ?? typeof body;
98
111
  console.error(
@@ -1,4 +1,4 @@
1
- import { ObjectTree, Tree, keysFromPath } from "@weborigami/async-tree";
1
+ import { DeepObjectTree, Tree, keysFromPath } from "@weborigami/async-tree";
2
2
  import { Scope, formatError } from "@weborigami/language";
3
3
  import { ServerResponse } from "node:http";
4
4
  import constructResponse from "./constructResponse.js";
@@ -50,15 +50,16 @@ function extendTreeScopeWithParams(tree, url) {
50
50
  return tree;
51
51
  }
52
52
 
53
- const paramTree = new ObjectTree({
53
+ const paramTree = new DeepObjectTree({
54
54
  "@params": params,
55
55
  });
56
56
 
57
57
  // Create a new scope that includes search parameter tree.
58
- const newScope = new Scope(paramTree, tree.parent);
58
+ const scope = Scope.getScope(tree);
59
+ const extendedScope = new Scope(paramTree, scope);
59
60
 
60
61
  // Create a new tree that extends the prototype chain of the supplied tree.
61
- const extendedTree = Scope.treeWithScope(tree, newScope);
62
+ const extendedTree = Scope.treeWithScope(tree, extendedScope);
62
63
 
63
64
  return extendedTree;
64
65
  }
package/src/builtins/!.js DELETED
@@ -1,21 +0,0 @@
1
- /**
2
- * The `!` built-in returns `undefined`, and is intended for force function
3
- * invocation in the shell without requiring the use of parentheses. Parentheses
4
- * can't be used in the shell without quoting them, which is inconvenient.
5
- *
6
- * This parentheses form:
7
- *
8
- * ```
9
- * $ ori "fn1.js(fn2.js())"
10
- * ```
11
- *
12
- * Can be written as:
13
- *
14
- * ```
15
- * $ ori fn1.js fn2.js !
16
- * ```
17
- *
18
- * This forces the invocation of `fn2.js`, passing `undefined` as the argument.
19
- * The result of that invocation is then passed to `fn1.js`.
20
- */
21
- export default undefined;
@@ -1,2 +0,0 @@
1
- // .css files use the .txt loader
2
- export { default } from "./txt.js";
@@ -1,2 +0,0 @@
1
- // .htm files use the .txt loader
2
- export { default } from "./txt.js";
@@ -1,2 +0,0 @@
1
- // .html files use the .txt loader
2
- export { default } from "./txt.js";
@@ -1,55 +0,0 @@
1
- import exifParser from "exif-parser";
2
-
3
- const exifDateTags = [
4
- "ModifyDate",
5
- "MDPrepDate",
6
- "DateTimeOriginal",
7
- "CreateDate",
8
- "PreviewDateTime",
9
- "GPSDateStamp",
10
- ];
11
-
12
- /**
13
- * Load Exif data from a JPEG file.
14
- *
15
- * @type {import("@weborigami/language").FileUnpackFunction}
16
- */
17
- export default async function unpackJpeg(buffer, options) {
18
- const parser = exifParser.create(buffer);
19
- parser.enableTagNames(true);
20
- parser.enableSimpleValues(true);
21
- const parsed = await parser.parse();
22
-
23
- // The exif-parser `enableSimpleValues` option should convert dates to
24
- // JavaScript Date objects, but that doesn't seem to work. Ensure dates are
25
- // Date objects.
26
- const exif = parsed.tags;
27
- for (const tag of exifDateTags) {
28
- if (typeof exif[tag] === "number") {
29
- exif[tag] = new Date(exif[tag] * 1000);
30
- }
31
- }
32
-
33
- const result = {
34
- height: parsed.imageSize.height,
35
- width: parsed.imageSize.width,
36
- exif,
37
- };
38
-
39
- // Promote some Exif properties to the top level.
40
- const tagsToPromote = {
41
- ImageDescription: "caption",
42
- ModifyDate: "modified",
43
- Orientation: "orientation",
44
- };
45
- for (const [tag, key] of Object.entries(tagsToPromote)) {
46
- if (exif[tag] !== undefined) {
47
- result[key] = exif[tag];
48
- }
49
- }
50
-
51
- // Add aspect ratio for use with `aspect-ratio` CSS.
52
- result.aspectRatio = result.width / result.height;
53
-
54
- return result;
55
- }
@@ -1,2 +0,0 @@
1
- // .jpg extension is a synonym for .jpeg
2
- export { default } from "./jpeg.js";
@@ -1,14 +0,0 @@
1
- import processUnpackedContent from "../../common/processUnpackedContent.js";
2
-
3
- /**
4
- * Load a .js file as module's default export or exports.
5
- *
6
- * @type {import("@weborigami/language").FileUnpackFunction}
7
- */
8
- export default async function unpackModule(input, options = {}) {
9
- const { key, parent } = options;
10
- if (parent && "import" in parent) {
11
- const content = await /** @type {any} */ (parent).import?.(key);
12
- return processUnpackedContent(content, parent);
13
- }
14
- }
@@ -1,14 +0,0 @@
1
- import * as utilities from "../../common/utilities.js";
2
-
3
- /**
4
- * Load a file as JSON.
5
- *
6
- * @type {import("@weborigami/language").FileUnpackFunction}
7
- */
8
- export default function unpackJson(input) {
9
- const json = utilities.toString(input);
10
- if (!json) {
11
- throw new Error("Tried to parse something as JSON but it wasn't text.");
12
- }
13
- return JSON.parse(json);
14
- }
@@ -1,2 +0,0 @@
1
- // .md files use the .txt loader
2
- export { default } from "./txt.js";
@@ -1,2 +0,0 @@
1
- // .mjs files use the .js loader
2
- export { default } from "./js.js";
@@ -1,45 +0,0 @@
1
- import { Scope, compile, symbols } from "@weborigami/language";
2
- import processUnpackedContent from "../../common/processUnpackedContent.js";
3
- import * as utilities from "../../common/utilities.js";
4
- import builtins from "../@builtins.js";
5
-
6
- /**
7
- * Load and evaluate an Origami expression from a file.
8
- *
9
- * @type {import("@weborigami/language").FileUnpackFunction}
10
- */
11
- export default async function unpackOrigamiExpression(
12
- inputDocument,
13
- options = {}
14
- ) {
15
- const attachedData = options.attachedData;
16
- const parent =
17
- options.parent ??
18
- /** @type {any} */ (inputDocument).parent ??
19
- /** @type {any} */ (inputDocument)[symbols.parent];
20
-
21
- // Construct an object to represent the source code.
22
- const sourceName = options.key;
23
- let url;
24
- if (sourceName && parent?.url) {
25
- let parentHref = parent.url.href;
26
- if (!parentHref.endsWith("/")) {
27
- parentHref += "/";
28
- }
29
- url = new URL(sourceName, parentHref);
30
- }
31
-
32
- const source = {
33
- text: utilities.toString(inputDocument),
34
- name: options.key,
35
- url,
36
- };
37
-
38
- // Compile the source code as an Origami expression and evaluate it.
39
- const compiler = options.compiler ?? compile.expression;
40
- const fn = compiler(source);
41
- const parentScope = parent ? Scope.getScope(parent) : builtins;
42
- let content = await fn.call(parentScope);
43
-
44
- return processUnpackedContent(content, parent, attachedData);
45
- }
@@ -1,37 +0,0 @@
1
- import TextDocument from "../../common/TextDocument.js";
2
- import { evaluateYaml } from "../../common/serialize.js";
3
- import * as utilities from "../../common/utilities.js";
4
-
5
- /**
6
- * Load a file as text document with possible front matter.
7
- *
8
- * This process will parse out any YAML or JSON front matter and attach it to
9
- * the document as data. The first line of the text must be "---", followed by a
10
- * block of JSON or YAML, followed by another line of "---". Any lines following
11
- * will be treated as the document text.
12
- *
13
- * Any Origami expressions in the front matter will be evaluated and the results
14
- * incorporated into the document data.
15
- *
16
- * @type {import("@weborigami/language").FileUnpackFunction}
17
- */
18
- export default async function unpackText(input, options = {}) {
19
- const parent = options.parent ?? null;
20
- const text = utilities.toString(input);
21
- if (!text) {
22
- throw new Error("Tried to treat something as text but it wasn't text.");
23
- }
24
- const regex =
25
- /^(---\r?\n(?<frontText>[\s\S]*?\r?\n)---\r?\n)(?<body>[\s\S]*$)/;
26
- const match = regex.exec(text);
27
-
28
- const body = match?.groups?.body ?? text;
29
-
30
- const frontData = match?.groups
31
- ? await evaluateYaml(match.groups.frontText, parent)
32
- : null;
33
-
34
- const object = Object.assign({}, frontData, { "@text": body });
35
-
36
- return new TextDocument(object, options.parent);
37
- }
@@ -1,11 +0,0 @@
1
- import processUnpackedContent from "../../common/processUnpackedContent.js";
2
-
3
- /**
4
- * Load a .js file as module's default export or exports.
5
- *
6
- * @type {import("@weborigami/language").FileUnpackFunction}
7
- */
8
- export default async function unpackWasm(buffer, options = {}) {
9
- const wasmModule = await WebAssembly.instantiate(buffer);
10
- return processUnpackedContent(wasmModule.instance.exports, options.parent);
11
- }
@@ -1,2 +0,0 @@
1
- // .xhtml files use the .txt loader
2
- export { default } from "./txt.js";
@@ -1,23 +0,0 @@
1
- import * as YAMLModule from "yaml";
2
- import processUnpackedContent from "../../common/processUnpackedContent.js";
3
- import { evaluateYaml } from "../../common/serialize.js";
4
- import * as utilities from "../../common/utilities.js";
5
-
6
- // See notes at serialize.js
7
- // @ts-ignore
8
- const YAML = YAMLModule.default ?? YAMLModule.YAML;
9
-
10
- /**
11
- * Load a file as YAML.
12
- *
13
- * @type {import("@weborigami/language").FileUnpackFunction}
14
- */
15
- export default async function unpackYaml(input, options = {}) {
16
- const parent = options.parent ?? null;
17
- const yaml = utilities.toString(input);
18
- if (!yaml) {
19
- throw new Error("Tried to parse something as YAML but it wasn't text.");
20
- }
21
- const data = await evaluateYaml(yaml, options.parent);
22
- return processUnpackedContent(data, parent);
23
- }
@@ -1,2 +0,0 @@
1
- // .yml extension is a synonym for .yaml
2
- export { default } from "./yaml.js";
@@ -1,58 +0,0 @@
1
- import { isStringLike } from "@weborigami/async-tree";
2
- import { symbols } from "@weborigami/language";
3
- import { toYaml } from "./serialize.js";
4
- import * as utilities from "./utilities.js";
5
-
6
- /**
7
- * A text document is any object with a `@text` property and a `toString()`
8
- * method that returns that text. This class is a helper for constructing such
9
- * text documents.
10
- */
11
- export default class TextDocument {
12
- /**
13
- * The `input` parameter can be anything that can be converted to a string.
14
- * The optional `data` parameter can be any object; if the object is a plain
15
- * object, its properties will be copied to the new document; otherwise, that
16
- * parameter is ignored.
17
- *
18
- * @typedef {import("@weborigami/types").AsyncTree|null} AsyncTree
19
- *
20
- * @param {any} [data]
21
- * @param {AsyncTree} [parent]
22
- */
23
- constructor(data, parent) {
24
- Object.assign(this, data);
25
- if (parent) {
26
- this[symbols.parent] = parent;
27
- }
28
- }
29
-
30
- static from(input, parent) {
31
- if (input["@text"]) {
32
- return input;
33
- } else if (isStringLike(input)) {
34
- const text = utilities.toString(input);
35
- return new TextDocument({ "@text": text }, parent);
36
- }
37
- }
38
-
39
- /**
40
- * Render the text and data as a document with YAML front matter.
41
- */
42
- async pack() {
43
- const text = this["@text"];
44
- /** @type {any} */
45
- const dataWithoutText = Object.assign({}, this);
46
- delete dataWithoutText["@text"];
47
- if (Object.keys(dataWithoutText).length > 0) {
48
- const frontMatter = (await toYaml(dataWithoutText)).trimEnd();
49
- return `---\n${frontMatter}\n---\n${text}`;
50
- } else {
51
- return text;
52
- }
53
- }
54
-
55
- toString() {
56
- return this["@text"];
57
- }
58
- }