@weborigami/origami 0.5.4 → 0.5.6
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.
- package/index.ts +0 -4
- package/main.js +2 -9
- package/package.json +4 -5
- package/src/cli/cli.js +10 -8
- package/src/common/documentObject.js +3 -3
- package/src/common/loadJsDom.js +13 -0
- package/src/common/utilities.d.ts +0 -2
- package/src/common/utilities.js +1 -55
- package/src/dev/ExplorableSiteTransform.js +2 -6
- package/src/dev/OriCommandTransform.js +25 -7
- package/src/dev/changes.js +10 -5
- package/src/dev/code.js +1 -6
- package/src/dev/copy.js +4 -8
- package/src/dev/crawler/audit.js +8 -8
- package/src/dev/crawler/crawl.js +3 -5
- package/src/dev/crawler/findPaths.js +9 -3
- package/src/dev/crawler/pathsInHtml.js +4 -3
- package/src/dev/debug.js +4 -7
- package/src/dev/dev.js +4 -2
- package/src/dev/explore.js +17 -39
- package/src/dev/help.js +0 -4
- package/src/dev/help.yaml +18 -14
- package/src/dev/log.js +1 -2
- package/src/dev/serve.js +5 -18
- package/src/dev/svg.js +5 -5
- package/src/dev/treeDot.js +5 -6
- package/src/dev/watch.js +8 -12
- package/src/initializeBuiltins.js +23 -0
- package/src/origami/csv.js +1 -5
- package/src/origami/document.js +2 -5
- package/src/origami/fetch.js +4 -8
- package/src/origami/htmlDom.js +3 -2
- package/src/origami/image/format.js +0 -5
- package/src/origami/image/resize.js +0 -3
- package/src/origami/indexPage.js +4 -4
- package/src/origami/inline.js +4 -10
- package/src/origami/json.js +2 -6
- package/src/origami/jsonKeys.js +4 -10
- package/src/origami/jsonParse.js +1 -1
- package/src/origami/mdHtml.js +5 -9
- package/src/origami/mdOutline.js +3 -3
- package/src/origami/once.js +3 -7
- package/src/origami/ori.js +21 -24
- package/src/origami/origami.js +1 -4
- package/src/origami/pack.js +0 -5
- package/src/origami/post.js +4 -3
- package/src/origami/rss.js +7 -8
- package/src/origami/sitemap.js +7 -9
- package/src/origami/static.js +7 -9
- package/src/origami/string.js +1 -14
- package/src/origami/unpack.js +0 -5
- package/src/origami/yaml.js +1 -5
- package/src/origami/yamlParse.js +1 -1
- package/src/server/constructResponse.js +3 -3
- package/src/server/server.js +8 -59
- package/src/builtinsProgram.js +0 -65
- package/src/builtinsShell.js +0 -18
- package/src/cli/getConfig.js +0 -11
- package/src/common/ConstantTree.js +0 -18
- package/src/common/constructHref.js +0 -20
- package/src/common/constructSiteTree.js +0 -34
- package/src/common/fetchAndHandleExtension.js +0 -27
- package/src/handlers/css.handler.js +0 -7
- package/src/handlers/csv.handler.js +0 -126
- package/src/handlers/handlerBuiltins.js +0 -27
- package/src/handlers/handlers.js +0 -33
- package/src/handlers/htm.handler.js +0 -2
- package/src/handlers/html.handler.js +0 -7
- package/src/handlers/jpeg.handler.js +0 -62
- package/src/handlers/jpg.handler.js +0 -2
- package/src/handlers/js.handler.js +0 -20
- package/src/handlers/json.handler.js +0 -27
- package/src/handlers/md.handler.js +0 -7
- package/src/handlers/mjs.handler.js +0 -2
- package/src/handlers/ori.handler.js +0 -55
- package/src/handlers/oridocument.handler.js +0 -78
- package/src/handlers/parseFrontMatter.js +0 -16
- package/src/handlers/processUnpackedContent.js +0 -35
- package/src/handlers/ts.handler.js +0 -1
- package/src/handlers/txt.handler.js +0 -91
- package/src/handlers/wasm.handler.js +0 -17
- package/src/handlers/xhtml.handler.js +0 -2
- package/src/handlers/yaml.handler.js +0 -36
- package/src/handlers/yml.handler.js +0 -2
- package/src/origami/config.js +0 -18
- package/src/origami/project.js +0 -111
- package/src/protocols/explore.js +0 -19
- package/src/protocols/files.js +0 -31
- package/src/protocols/http.js +0 -18
- package/src/protocols/https.js +0 -18
- package/src/protocols/httpstree.js +0 -19
- package/src/protocols/httptree.js +0 -19
- package/src/protocols/js.js +0 -13
- package/src/protocols/node.js +0 -13
- package/src/protocols/package.js +0 -70
- package/src/tree/addNextPrevious.js +0 -22
- package/src/tree/cache.js +0 -22
- package/src/tree/calendar.js +0 -1
- package/src/tree/clear.js +0 -19
- package/src/tree/concat.js +0 -17
- package/src/tree/constant.js +0 -1
- package/src/tree/deepMap.js +0 -32
- package/src/tree/deepMerge.js +0 -18
- package/src/tree/deepReverse.js +0 -23
- package/src/tree/deepTake.js +0 -26
- package/src/tree/deepValues.js +0 -22
- package/src/tree/defineds.js +0 -30
- package/src/tree/filter.js +0 -19
- package/src/tree/first.js +0 -19
- package/src/tree/fromFn.js +0 -29
- package/src/tree/globKeys.js +0 -19
- package/src/tree/group.js +0 -26
- package/src/tree/inners.js +0 -30
- package/src/tree/keys.js +0 -15
- package/src/tree/length.js +0 -15
- package/src/tree/map.d.ts +0 -11
- package/src/tree/map.js +0 -125
- package/src/tree/mask.js +0 -19
- package/src/tree/match.js +0 -79
- package/src/tree/merge.js +0 -41
- package/src/tree/paginate.js +0 -20
- package/src/tree/parent.js +0 -15
- package/src/tree/plain.js +0 -15
- package/src/tree/regExpKeys.js +0 -19
- package/src/tree/reverse.js +0 -17
- package/src/tree/setDeep.js +0 -49
- package/src/tree/shuffle.js +0 -57
- package/src/tree/sort.js +0 -52
- package/src/tree/take.js +0 -19
- package/src/tree/tree.js +0 -52
- package/src/tree/values.js +0 -15
package/src/origami/ori.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Tree,
|
|
3
3
|
getRealmObjectPrototype,
|
|
4
|
+
isStringlike,
|
|
4
5
|
toString,
|
|
5
6
|
} from "@weborigami/async-tree";
|
|
6
7
|
import { compile } from "@weborigami/language";
|
|
7
|
-
import
|
|
8
|
-
import getConfig from "../cli/getConfig.js";
|
|
9
|
-
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
8
|
+
import projectGlobals from "@weborigami/language/src/project/projectGlobals.js";
|
|
10
9
|
import { toYaml } from "../common/serialize.js";
|
|
10
|
+
import * as dev from "../dev/dev.js";
|
|
11
11
|
|
|
12
12
|
const TypedArray = Object.getPrototypeOf(Uint8Array);
|
|
13
13
|
|
|
@@ -17,50 +17,47 @@ const TypedArray = Object.getPrototypeOf(Uint8Array);
|
|
|
17
17
|
*
|
|
18
18
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
19
19
|
*
|
|
20
|
-
* @this {AsyncTree|null}
|
|
21
20
|
* @param {string} expression
|
|
22
21
|
*/
|
|
23
|
-
export default async function ori(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
) {
|
|
27
|
-
assertTreeIsDefined(this, "ori");
|
|
22
|
+
export default async function ori(expression, options = {}) {
|
|
23
|
+
const parent = options.parent ?? null;
|
|
24
|
+
const formatResult = options.formatResult ?? true;
|
|
28
25
|
|
|
29
26
|
// In case expression has come from a file, cast it to a string.
|
|
27
|
+
if (!isStringlike(expression)) {
|
|
28
|
+
throw new TypeError("ori: The expression is not text.");
|
|
29
|
+
}
|
|
30
|
+
// @ts-ignore
|
|
30
31
|
expression = toString(expression);
|
|
31
32
|
|
|
32
|
-
//
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
? {
|
|
38
|
-
...builtinsShell(),
|
|
39
|
-
...config,
|
|
40
|
-
}
|
|
41
|
-
: builtinsShell();
|
|
33
|
+
// Add Dev builtins as top-level globals
|
|
34
|
+
const globals = {
|
|
35
|
+
...(await projectGlobals()),
|
|
36
|
+
...dev,
|
|
37
|
+
};
|
|
42
38
|
|
|
43
39
|
// Compile the expression. Avoid caching scope references so that, e.g.,
|
|
44
40
|
// passing a function to the `watch` builtin will always look the current
|
|
45
41
|
// value of things in scope.
|
|
46
42
|
const fn = compile.expression(expression, {
|
|
47
43
|
globals,
|
|
48
|
-
mode: "shell",
|
|
49
44
|
enableCaching: false,
|
|
45
|
+
mode: "shell",
|
|
46
|
+
parent,
|
|
50
47
|
});
|
|
51
48
|
|
|
52
49
|
// Execute
|
|
53
|
-
let result = await fn
|
|
50
|
+
let result = await fn();
|
|
54
51
|
|
|
55
52
|
// If result was a function, execute it.
|
|
56
53
|
if (typeof result === "function") {
|
|
57
|
-
result = await result
|
|
54
|
+
result = await result();
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
return
|
|
57
|
+
return formatResult ? await format(result) : result;
|
|
61
58
|
}
|
|
62
59
|
|
|
63
|
-
async function
|
|
60
|
+
async function format(result) {
|
|
64
61
|
if (
|
|
65
62
|
typeof result === "string" ||
|
|
66
63
|
result instanceof ArrayBuffer ||
|
package/src/origami/origami.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export { extension } from "@weborigami/async-tree";
|
|
2
|
-
export { toFunction } from "../common/utilities.js";
|
|
3
2
|
export { default as help } from "../dev/help.js"; // Alias
|
|
4
3
|
export { default as document } from "../origami/document.js";
|
|
5
|
-
export { default as htmlDom } from "../origami/htmlDom.js";
|
|
4
|
+
// export { default as htmlDom } from "../origami/htmlDom.js";
|
|
6
5
|
export { default as indexPage } from "../origami/indexPage.js";
|
|
7
6
|
export { default as inline } from "../origami/inline.js";
|
|
8
7
|
export { default as jsonKeys } from "../origami/jsonKeys.js";
|
|
@@ -13,7 +12,6 @@ export { default as sitemap } from "../origami/sitemap.js";
|
|
|
13
12
|
export { default as slug } from "../origami/slug.js";
|
|
14
13
|
export { default as static } from "../origami/static.js";
|
|
15
14
|
export { default as basename } from "./basename.js";
|
|
16
|
-
export { default as config } from "./config.js";
|
|
17
15
|
export { default as csv } from "./csv.js";
|
|
18
16
|
export { default as fetch } from "./fetch.js";
|
|
19
17
|
export { default as format } from "./image/format.js";
|
|
@@ -27,7 +25,6 @@ export { default as once } from "./once.js";
|
|
|
27
25
|
export { default as ori } from "./ori.js";
|
|
28
26
|
export { default as pack } from "./pack.js";
|
|
29
27
|
export { default as post } from "./post.js";
|
|
30
|
-
export { default as project } from "./project.js";
|
|
31
28
|
export { default as repeat } from "./repeat.js";
|
|
32
29
|
export { default as shell } from "./shell.js";
|
|
33
30
|
export { default as slash } from "./slash.js";
|
package/src/origami/pack.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
5
3
|
*
|
|
6
|
-
* @this {AsyncTree|null}
|
|
7
4
|
* @param {any} obj
|
|
8
|
-
* @returns
|
|
9
5
|
*/
|
|
10
6
|
export default function pack(obj) {
|
|
11
|
-
assertTreeIsDefined(this, "pack");
|
|
12
7
|
return obj?.pack?.();
|
|
13
8
|
}
|
package/src/origami/post.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
isStringlike,
|
|
3
3
|
isUnpackable,
|
|
4
4
|
toPlainValue,
|
|
5
5
|
toString,
|
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
} from "@weborigami/async-tree";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* POST data to the indicated URL.
|
|
11
|
+
*
|
|
11
12
|
* @param {string} url
|
|
12
13
|
* @param {any} data
|
|
13
14
|
*/
|
|
@@ -23,7 +24,7 @@ export default async function post(url, data) {
|
|
|
23
24
|
headers = {
|
|
24
25
|
"Content-Type": "application/json",
|
|
25
26
|
};
|
|
26
|
-
} else if (
|
|
27
|
+
} else if (isStringlike(data)) {
|
|
27
28
|
body = toString(data);
|
|
28
29
|
headers = {
|
|
29
30
|
"Content-Type": "text/plain",
|
package/src/origami/rss.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { Tree } from "@weborigami/async-tree";
|
|
1
|
+
import { getTreeArgument, Tree } from "@weborigami/async-tree";
|
|
2
2
|
import jsonFeedToRss from "@weborigami/json-feed-to-rss";
|
|
3
|
-
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
7
6
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
8
|
-
*
|
|
9
|
-
* @param {Treelike}
|
|
7
|
+
*
|
|
8
|
+
* @param {Treelike} jsonFeed
|
|
10
9
|
* @param {any} options
|
|
11
10
|
*/
|
|
12
|
-
export default async function rss(
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
return jsonFeedToRss(
|
|
11
|
+
export default async function rss(jsonFeed, options = {}) {
|
|
12
|
+
const tree = await getTreeArgument(jsonFeed, "rss");
|
|
13
|
+
const jsonFeedPlain = await Tree.plain(tree);
|
|
14
|
+
return jsonFeedToRss(jsonFeedPlain, options);
|
|
16
15
|
}
|
package/src/origami/sitemap.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { Tree } from "@weborigami/async-tree";
|
|
2
|
-
import
|
|
3
|
-
import getTreeArgument from "../common/getTreeArgument.js";
|
|
4
|
-
import { oriHandler } from "../handlers/handlers.js";
|
|
1
|
+
import { getTreeArgument, Tree } from "@weborigami/async-tree";
|
|
2
|
+
import { ori_handler } from "@weborigami/language/src/handlers/handlers.js";
|
|
5
3
|
|
|
6
4
|
const templateText = `(urls) => \`<?xml version="1.0" encoding="UTF-8"?>
|
|
7
5
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
@@ -15,13 +13,13 @@ const templateText = `(urls) => \`<?xml version="1.0" encoding="UTF-8"?>
|
|
|
15
13
|
/**
|
|
16
14
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
17
15
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
18
|
-
*
|
|
16
|
+
*
|
|
19
17
|
* @param {Treelike} treelike
|
|
20
18
|
* @param {{ assumeSlashes?: boolean, base?: string }} options
|
|
19
|
+
* @returns {Promise<string>}
|
|
21
20
|
*/
|
|
22
21
|
export default async function sitemap(treelike, options = {}) {
|
|
23
|
-
|
|
24
|
-
const tree = await getTreeArgument(this, arguments, treelike, "sitemap");
|
|
22
|
+
const tree = await getTreeArgument(treelike, "sitemap");
|
|
25
23
|
|
|
26
24
|
// We're only interested in keys that end in .html or with no extension.
|
|
27
25
|
function test(key) {
|
|
@@ -47,7 +45,7 @@ export default async function sitemap(treelike, options = {}) {
|
|
|
47
45
|
.filter((path) => path.endsWith(".html"))
|
|
48
46
|
.map((path) => (path.endsWith("index.html") ? path.slice(0, -10) : path));
|
|
49
47
|
|
|
50
|
-
const templateFn = await
|
|
51
|
-
const templateResult = await templateFn
|
|
48
|
+
const templateFn = await ori_handler.unpack(templateText);
|
|
49
|
+
const templateResult = await templateFn(htmlPaths);
|
|
52
50
|
return String(templateResult);
|
|
53
51
|
}
|
package/src/origami/static.js
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import { Tree, jsonKeys } from "@weborigami/async-tree";
|
|
2
|
-
import
|
|
3
|
-
import index from "./indexPage.js";
|
|
1
|
+
import { Tree, getTreeArgument, jsonKeys } from "@weborigami/async-tree";
|
|
2
|
+
import indexPage from "./indexPage.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Expose common static keys (index.html, .keys.json) for a tree.
|
|
7
6
|
*
|
|
8
7
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
8
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
|
-
*
|
|
9
|
+
*
|
|
11
10
|
* @param {Treelike} treelike
|
|
11
|
+
* @returns {Promise<AsyncTree>}
|
|
12
12
|
*/
|
|
13
13
|
export default async function staticBuiltin(treelike) {
|
|
14
|
-
const tree = await getTreeArgument(
|
|
15
|
-
|
|
16
|
-
result.parent = this;
|
|
17
|
-
return result;
|
|
14
|
+
const tree = await getTreeArgument(treelike, "static");
|
|
15
|
+
return staticTree(tree);
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
// The name we'll register as a builtin
|
|
@@ -25,7 +23,7 @@ function staticTree(tree) {
|
|
|
25
23
|
async get(key) {
|
|
26
24
|
let value = await tree.get(key);
|
|
27
25
|
if (value === undefined && key === "index.html") {
|
|
28
|
-
value = await
|
|
26
|
+
value = await indexPage(this);
|
|
29
27
|
} else if (value === undefined && key === ".keys.json") {
|
|
30
28
|
value = await jsonKeys.stringify(this);
|
|
31
29
|
} else if (Tree.isTreelike(value)) {
|
package/src/origami/string.js
CHANGED
|
@@ -1,14 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { toString } from "../common/utilities.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Convert an object to a string.
|
|
6
|
-
*
|
|
7
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
-
* @this {AsyncTree|null}
|
|
9
|
-
* @param {any} object
|
|
10
|
-
*/
|
|
11
|
-
export default function stringBuiltin(object) {
|
|
12
|
-
assertTreeIsDefined(this, "string");
|
|
13
|
-
return toString(object);
|
|
14
|
-
}
|
|
1
|
+
export { toString as default } from "@weborigami/async-tree";
|
package/src/origami/unpack.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Unpack a packed format like a Uint8Array or ArrayBuffer to a usable form like
|
|
5
3
|
* text or a plain JavaScript object.
|
|
6
4
|
*
|
|
7
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
-
* @this {AsyncTree|null}
|
|
9
5
|
* @param {any} obj
|
|
10
6
|
*/
|
|
11
7
|
export default function unpack(obj) {
|
|
12
|
-
assertTreeIsDefined(this, "unpack");
|
|
13
8
|
return obj?.unpack?.() ?? obj;
|
|
14
9
|
}
|
package/src/origami/yaml.js
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
2
|
import { isUnpackable, toPlainValue } from "@weborigami/async-tree";
|
|
3
3
|
import YAML from "yaml";
|
|
4
|
-
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Render the object as text in YAML format.
|
|
8
7
|
*
|
|
9
|
-
* @this {AsyncTree|null}
|
|
10
8
|
* @param {any} [obj]
|
|
11
9
|
*/
|
|
12
|
-
export default async function
|
|
13
|
-
assertTreeIsDefined(this, "yaml");
|
|
10
|
+
export default async function yamlBuiltin(obj) {
|
|
14
11
|
// A fragment of the logic from getTreeArgument.js
|
|
15
12
|
if (arguments.length > 0 && obj === undefined) {
|
|
16
13
|
throw new Error(
|
|
17
14
|
"An Origami function was called with an initial argument, but its value is undefined."
|
|
18
15
|
);
|
|
19
16
|
}
|
|
20
|
-
obj = obj ?? this;
|
|
21
17
|
if (obj === undefined) {
|
|
22
18
|
return undefined;
|
|
23
19
|
}
|
package/src/origami/yamlParse.js
CHANGED
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
extension,
|
|
3
3
|
isPacked,
|
|
4
4
|
isPlainObject,
|
|
5
|
-
|
|
5
|
+
isStringlike,
|
|
6
6
|
SiteTree,
|
|
7
|
+
toString,
|
|
7
8
|
Tree,
|
|
8
9
|
} from "@weborigami/async-tree";
|
|
9
10
|
import * as serialize from "../common/serialize.js";
|
|
10
|
-
import { toString } from "../common/utilities.js";
|
|
11
11
|
import { mediaTypeForExtension } from "./mediaTypes.js";
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -63,7 +63,7 @@ export default async function constructResponse(request, resource) {
|
|
|
63
63
|
|
|
64
64
|
if (
|
|
65
65
|
(mediaType === "application/json" || mediaType === "text/yaml") &&
|
|
66
|
-
!
|
|
66
|
+
!isStringlike(resource)
|
|
67
67
|
) {
|
|
68
68
|
// The request is for a JSON or YAML result, and the resource we got isn't
|
|
69
69
|
// yet a string: convert the resource to JSON or YAML now.
|
package/src/server/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Tree, keysFromPath } from "@weborigami/async-tree";
|
|
2
2
|
import { formatError } from "@weborigami/language";
|
|
3
3
|
import { ServerResponse } from "node:http";
|
|
4
4
|
import constructResponse from "./constructResponse.js";
|
|
@@ -39,32 +39,6 @@ async function copyResponse(constructed, response) {
|
|
|
39
39
|
return true;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
// Extend the tree's scope with the URL's search parameters.
|
|
43
|
-
function extendTreeScopeWithParams(tree, url) {
|
|
44
|
-
// Create a tree that includes the URL's search parameters.
|
|
45
|
-
const params = {};
|
|
46
|
-
for (const [key, value] of url.searchParams) {
|
|
47
|
-
params[key] = value;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (Object.keys(params).length === 0) {
|
|
51
|
-
// No search parameters, so return the tree as is.
|
|
52
|
-
return tree;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const paramTree = new ObjectTree({
|
|
56
|
-
"@params": params,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Create a new tree that's like the original one, but has the parameters in
|
|
60
|
-
// its parent hierarchy.
|
|
61
|
-
const extendedTree = Object.create(tree);
|
|
62
|
-
const realParent = tree.parent;
|
|
63
|
-
paramTree.parent = realParent;
|
|
64
|
-
extendedTree.parent = paramTree;
|
|
65
|
-
return extendedTree;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
42
|
/**
|
|
69
43
|
* Handle a client request.
|
|
70
44
|
*
|
|
@@ -77,17 +51,12 @@ export async function handleRequest(request, response, tree) {
|
|
|
77
51
|
const url = new URL(request.url ?? "", `https://${request.headers.host}`);
|
|
78
52
|
const keys = keysFromUrl(url);
|
|
79
53
|
|
|
80
|
-
const extendedTree =
|
|
81
|
-
url.searchParams && "parent" in tree
|
|
82
|
-
? extendTreeScopeWithParams(tree, url)
|
|
83
|
-
: tree;
|
|
84
|
-
|
|
85
54
|
const data = request.method === "POST" ? await parsePostData(request) : null;
|
|
86
55
|
|
|
87
56
|
// Ask the tree for the resource with those keys.
|
|
88
57
|
let resource;
|
|
89
58
|
try {
|
|
90
|
-
resource = await Tree.traverseOrThrow(
|
|
59
|
+
resource = await Tree.traverseOrThrow(tree, ...keys);
|
|
91
60
|
|
|
92
61
|
// If resource is a function, invoke to get the object we want to return.
|
|
93
62
|
// For a POST request, pass the data to the function.
|
|
@@ -112,35 +81,15 @@ export async function handleRequest(request, response, tree) {
|
|
|
112
81
|
}
|
|
113
82
|
|
|
114
83
|
function keysFromUrl(url) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const parts = url.pathname.split(/\/!/);
|
|
118
|
-
|
|
119
|
-
// Split everything before the first command by slashes and decode those.
|
|
120
|
-
let path = parts.shift();
|
|
121
|
-
if (parts.length > 0) {
|
|
122
|
-
// HACK: Add back trailing slash that was removed by split
|
|
123
|
-
path += "/";
|
|
124
|
-
}
|
|
125
|
-
const pathKeys = keysFromPath(path).map((key) => decodeURIComponent(key));
|
|
126
|
-
if (parts.length > 0 && pathKeys.at(-1) === "") {
|
|
127
|
-
// HACK part 2: Remove empty string that was added for trailing slash
|
|
128
|
-
pathKeys.pop();
|
|
129
|
-
}
|
|
84
|
+
const encodedKeys = keysFromPath(url.pathname);
|
|
85
|
+
const keys = encodedKeys.map((key) => decodeURIComponent(key));
|
|
130
86
|
|
|
131
|
-
// If
|
|
132
|
-
//
|
|
133
|
-
if (
|
|
134
|
-
|
|
87
|
+
// If the path ends with a trailing slash, the final key will be an empty
|
|
88
|
+
// string. Change that to "index.html".
|
|
89
|
+
if (keys.at(-1) === "") {
|
|
90
|
+
keys[keys.length - 1] = "index.html";
|
|
135
91
|
}
|
|
136
92
|
|
|
137
|
-
// Decode the text of the commands, prefix spaces with a backslash, and add
|
|
138
|
-
// back the `!` character.
|
|
139
|
-
const commandKeys = parts.map(
|
|
140
|
-
(command) => `!${decodeURIComponent(command).replace(/ /g, "\\ ")}`
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const keys = [...pathKeys, ...commandKeys];
|
|
144
93
|
return keys;
|
|
145
94
|
}
|
|
146
95
|
|
package/src/builtinsProgram.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { deepText, indent, json, text } from "@weborigami/async-tree";
|
|
2
|
-
import { jsGlobals } from "@weborigami/language";
|
|
3
|
-
import * as dev from "./dev/dev.js";
|
|
4
|
-
import help from "./dev/help.js";
|
|
5
|
-
import handlerBuiltins from "./handlers/handlerBuiltins.js";
|
|
6
|
-
import * as origami from "./origami/origami.js";
|
|
7
|
-
import explore from "./protocols/explore.js";
|
|
8
|
-
import files from "./protocols/files.js";
|
|
9
|
-
import http from "./protocols/http.js";
|
|
10
|
-
import https from "./protocols/https.js";
|
|
11
|
-
import httpstree from "./protocols/httpstree.js";
|
|
12
|
-
import httptree from "./protocols/httptree.js";
|
|
13
|
-
import node from "./protocols/node.js";
|
|
14
|
-
import packageNamespace from "./protocols/package.js";
|
|
15
|
-
import * as tree from "./tree/tree.js";
|
|
16
|
-
|
|
17
|
-
let builtins;
|
|
18
|
-
|
|
19
|
-
export default function builtinsProgram() {
|
|
20
|
-
if (!builtins) {
|
|
21
|
-
const Tree = {
|
|
22
|
-
...tree,
|
|
23
|
-
deepText,
|
|
24
|
-
indent,
|
|
25
|
-
json,
|
|
26
|
-
text,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const Protocol = {
|
|
30
|
-
explore,
|
|
31
|
-
files,
|
|
32
|
-
http,
|
|
33
|
-
https,
|
|
34
|
-
httpstree,
|
|
35
|
-
httptree,
|
|
36
|
-
node,
|
|
37
|
-
package: packageNamespace,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/** @type {any} */
|
|
41
|
-
builtins = {
|
|
42
|
-
...jsGlobals,
|
|
43
|
-
|
|
44
|
-
"explore:": explore,
|
|
45
|
-
"files:": files,
|
|
46
|
-
"help:": help,
|
|
47
|
-
"http:": http,
|
|
48
|
-
"https:": https,
|
|
49
|
-
"httpstree:": httpstree,
|
|
50
|
-
"httptree:": httptree,
|
|
51
|
-
"node:": node,
|
|
52
|
-
"package:": packageNamespace,
|
|
53
|
-
|
|
54
|
-
Dev: dev,
|
|
55
|
-
Tree,
|
|
56
|
-
Origami: origami,
|
|
57
|
-
Protocol,
|
|
58
|
-
|
|
59
|
-
// Handlers need to be exposed at top level
|
|
60
|
-
...handlerBuiltins(),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return builtins;
|
|
65
|
-
}
|
package/src/builtinsShell.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import builtinsProgram from "./builtinsProgram.js";
|
|
2
|
-
import * as dev from "./dev/dev.js";
|
|
3
|
-
|
|
4
|
-
let builtins;
|
|
5
|
-
|
|
6
|
-
export default function builtinsShell() {
|
|
7
|
-
if (!builtins) {
|
|
8
|
-
builtins = {
|
|
9
|
-
// All program builtins
|
|
10
|
-
...builtinsProgram(),
|
|
11
|
-
|
|
12
|
-
// Dev builtins exposed at the top level in shell
|
|
13
|
-
...dev,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return builtins;
|
|
18
|
-
}
|
package/src/cli/getConfig.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
3
|
-
* @implements {AsyncTree}
|
|
4
|
-
*/
|
|
5
|
-
export default class ConstantTree {
|
|
6
|
-
constructor(value) {
|
|
7
|
-
this.value = value;
|
|
8
|
-
this.parent = null;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async get(key) {
|
|
12
|
-
return this.value;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async keys() {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { pathFromKeys } from "@weborigami/async-tree";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Given a protocol, a host, and a list of keys, construct an href.
|
|
5
|
-
*
|
|
6
|
-
* @param {string} protocol
|
|
7
|
-
* @param {string} host
|
|
8
|
-
* @param {string[]} keys
|
|
9
|
-
*/
|
|
10
|
-
export default function constructHref(protocol, host, ...keys) {
|
|
11
|
-
const path = pathFromKeys(keys);
|
|
12
|
-
let href = [host, path].join("/");
|
|
13
|
-
if (!href.startsWith(protocol)) {
|
|
14
|
-
if (!href.startsWith("//")) {
|
|
15
|
-
href = `//${href}`;
|
|
16
|
-
}
|
|
17
|
-
href = `${protocol}${href}`;
|
|
18
|
-
}
|
|
19
|
-
return href;
|
|
20
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { trailingSlash } from "@weborigami/async-tree";
|
|
2
|
-
import { HandleExtensionsTransform } from "@weborigami/language";
|
|
3
|
-
import constructHref from "./constructHref.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Given a protocol, a host, and a list of keys, construct an href.
|
|
7
|
-
*
|
|
8
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
-
*
|
|
10
|
-
* @param {string} protocol
|
|
11
|
-
* @param {import("../../index.ts").Constructor<AsyncTree>} treeClass
|
|
12
|
-
* @param {AsyncTree|null} parent
|
|
13
|
-
* @param {string} host
|
|
14
|
-
* @param {string[]} keys
|
|
15
|
-
*/
|
|
16
|
-
export default function constructSiteTree(
|
|
17
|
-
protocol,
|
|
18
|
-
treeClass,
|
|
19
|
-
parent,
|
|
20
|
-
host,
|
|
21
|
-
...keys
|
|
22
|
-
) {
|
|
23
|
-
// If the last key doesn't end in a slash, remove it for now.
|
|
24
|
-
let lastKey;
|
|
25
|
-
if (keys.length > 0 && keys.at(-1) && !trailingSlash.has(keys.at(-1))) {
|
|
26
|
-
lastKey = keys.pop();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const href = constructHref(protocol, host, ...keys);
|
|
30
|
-
let result = new (HandleExtensionsTransform(treeClass))(href);
|
|
31
|
-
result.parent = parent;
|
|
32
|
-
|
|
33
|
-
return lastKey ? result.get(lastKey) : result;
|
|
34
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { getHandlers, handleExtension } from "@weborigami/language";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Fetch the resource at the given href.
|
|
5
|
-
*
|
|
6
|
-
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
7
|
-
*
|
|
8
|
-
* @this {AsyncTree|null}
|
|
9
|
-
* @param {string} href
|
|
10
|
-
*/
|
|
11
|
-
export default async function fetchAndHandleExtension(href) {
|
|
12
|
-
const response = await fetch(href);
|
|
13
|
-
if (!response.ok) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
let buffer = await response.arrayBuffer();
|
|
17
|
-
|
|
18
|
-
// Attach any loader defined for the file type.
|
|
19
|
-
const url = new URL(href);
|
|
20
|
-
const filename = url.pathname.split("/").pop();
|
|
21
|
-
if (this && filename) {
|
|
22
|
-
const handlers = getHandlers(this);
|
|
23
|
-
buffer = await handleExtension(this, buffer, filename, handlers);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return buffer;
|
|
27
|
-
}
|