@weborigami/language 0.0.61 → 0.0.63

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.
@@ -1,4 +0,0 @@
1
- import { ExpressionTree } from "./internal.js";
2
- import OrigamiTransform from "./OrigamiTransform.js";
3
-
4
- export default class OrigamiTree extends OrigamiTransform(ExpressionTree) {}
@@ -1,20 +0,0 @@
1
- /**
2
- * If the given path ends in an extension, return it. Otherwise, return the
3
- * empty string.
4
- *
5
- * This is meant as a basic replacement for the standard Node `path.extname`.
6
- * That standard function inaccurately returns an extension for a path that
7
- * includes a near-final extension but ends in a final slash, like "foo.txt/".
8
- * Node thinks that path has a ".txt" extension, but for our purposes it
9
- * doesn't.
10
- *
11
- * @param {string} path
12
- */
13
- export default function extname(path) {
14
- // We want at least one character before the dot, then a dot, then a non-empty
15
- // sequence of characters after the dot that aren't slahes or dots.
16
- const extnameRegex = /[^/](?<ext>\.[^/\.]+)$/;
17
- const match = String(path).match(extnameRegex);
18
- const extension = match?.groups?.ext.toLowerCase() ?? "";
19
- return extension;
20
- }
@@ -1,56 +0,0 @@
1
- import { isUnpackable, scope, symbols } from "@weborigami/async-tree";
2
- import extname from "./extname.js";
3
-
4
- /**
5
- * Given a value that was retrieved using the given key, search in scope for a
6
- * handler for the file extension on the key (if present). If a handler is
7
- * found, attach information from it to the value and return the modified value.
8
- *
9
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
10
- *
11
- * @param {AsyncTree} parent
12
- * @param {any} key
13
- * @param {any} value
14
- */
15
- export default async function handleExtension(parent, key, value) {
16
- const extension = extname(key);
17
- let result = value;
18
- if (extension) {
19
- const handlerName = `${extension.slice(1)}_handler`;
20
- const parentScope = scope(parent);
21
- /** @type {import("../../index.ts").ExtensionHandler} */
22
- let extensionHandler = await parentScope?.get(handlerName);
23
- if (isUnpackable(extensionHandler)) {
24
- // The extension handler itself needs to be unpacked. E.g., if it's a
25
- // buffer containing JavaScript file, we need to unpack it to get its
26
- // default export.
27
- // @ts-ignore
28
- extensionHandler = await extensionHandler.unpack();
29
- }
30
- if (extensionHandler) {
31
- const input = value;
32
-
33
- // If the result is a plain string, box it as a String so we can attach
34
- // data to it.
35
- if (typeof result === "string") {
36
- result = new String(result);
37
- }
38
-
39
- if (extensionHandler.mediaType) {
40
- result.mediaType = extensionHandler.mediaType;
41
- }
42
- result[symbols.parent] = parent;
43
-
44
- const unpack = extensionHandler.unpack;
45
- if (unpack) {
46
- // Wrap the unpack function so its only called once per value.
47
- let loaded;
48
- result.unpack = async () => {
49
- loaded ??= await unpack(input, { key, parent });
50
- return loaded;
51
- };
52
- }
53
- }
54
- }
55
- return result;
56
- }
@@ -1,27 +0,0 @@
1
- import assert from "node:assert";
2
- import { describe, test } from "node:test";
3
-
4
- import { Tree } from "@weborigami/async-tree";
5
- import {
6
- ExpressionTree,
7
- expressionFunction,
8
- ops,
9
- } from "../../src/runtime/internal.js";
10
-
11
- describe("ExpressionTree", () => {
12
- test("evaluates expressions, returns other values as is", async () => {
13
- const tree = new ExpressionTree({
14
- name: "Alice",
15
- message: expressionFunction.createExpressionFunction([
16
- ops.concat,
17
- "Hello, ",
18
- [ops.scope, "name"],
19
- "!",
20
- ]),
21
- });
22
- assert.deepEqual(await Tree.plain(tree), {
23
- name: "Alice",
24
- message: "Hello, Alice!",
25
- });
26
- });
27
- });
@@ -1,40 +0,0 @@
1
- import { ObjectTree, Tree } from "@weborigami/async-tree";
2
- import assert from "node:assert";
3
- import { describe, test } from "node:test";
4
- import HandleExtensionsTransform from "../../src/runtime/HandleExtensionsTransform.js";
5
-
6
- describe("HandleExtensionsTransform", () => {
7
- test("invokes an appropriate loader for a .json file extension", async () => {
8
- const fixture = createFixture();
9
- const numberValue = await fixture.get("foo");
10
- assert(typeof numberValue === "number");
11
- assert.equal(numberValue, 1);
12
- const jsonFile = await fixture.get("bar.json");
13
- assert.equal(String(jsonFile), `{ "bar": 2 }`);
14
- const data = await jsonFile.unpack();
15
- assert.deepEqual(data, { bar: 2 });
16
- });
17
-
18
- test("input that isn't string-like is returned as is", async () => {
19
- const obj = { bar: 2 };
20
- const fixture = createFixture();
21
- const jsonFile = await fixture.get("bar.json");
22
- assert.deepEqual(await Tree.plain(jsonFile), obj);
23
- });
24
- });
25
-
26
- function createFixture() {
27
- /** @type {any} */
28
- const parent = new ObjectTree({
29
- json_handler: {
30
- unpack: (buffer) => JSON.parse(String(buffer)),
31
- },
32
- });
33
- /** @type {import("@weborigami/types").AsyncTree} */
34
- let tree = new (HandleExtensionsTransform(ObjectTree))({
35
- foo: 1, // No extension, should be left alone
36
- "bar.json": `{ "bar": 2 }`,
37
- });
38
- tree.parent = parent;
39
- return tree;
40
- }