@weborigami/origami 0.0.35
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/LICENSE +21 -0
- package/ReadMe.md +3 -0
- package/exports/PathTransform.d.ts +5 -0
- package/exports/PathTransform.js +18 -0
- package/exports/buildExports.js +109 -0
- package/exports/exports.js +121 -0
- package/index.ts +25 -0
- package/package.json +40 -0
- package/src/builtins/!.js +21 -0
- package/src/builtins/@apply.js +6 -0
- package/src/builtins/@arrows.js +34 -0
- package/src/builtins/@builtins.js +18 -0
- package/src/builtins/@cache.js +36 -0
- package/src/builtins/@config.js +25 -0
- package/src/builtins/@copy.js +71 -0
- package/src/builtins/@crawl.js +507 -0
- package/src/builtins/@debug.js +89 -0
- package/src/builtins/@document.js +18 -0
- package/src/builtins/@equals.js +6 -0
- package/src/builtins/@explore.js +68 -0
- package/src/builtins/@false.js +1 -0
- package/src/builtins/@files.js +22 -0
- package/src/builtins/@filter.js +23 -0
- package/src/builtins/@globs.js +23 -0
- package/src/builtins/@help.js +49 -0
- package/src/builtins/@http.js +19 -0
- package/src/builtins/@https.js +19 -0
- package/src/builtins/@if.js +27 -0
- package/src/builtins/@image/format.js +5 -0
- package/src/builtins/@image/resize.js +5 -0
- package/src/builtins/@index.js +72 -0
- package/src/builtins/@inherited.js +17 -0
- package/src/builtins/@inline.js +29 -0
- package/src/builtins/@invoke.js +30 -0
- package/src/builtins/@js.js +33 -0
- package/src/builtins/@json.js +22 -0
- package/src/builtins/@loaders/css.js +4 -0
- package/src/builtins/@loaders/htm.js +4 -0
- package/src/builtins/@loaders/html.js +4 -0
- package/src/builtins/@loaders/js.js +14 -0
- package/src/builtins/@loaders/json.js +8 -0
- package/src/builtins/@loaders/md.js +4 -0
- package/src/builtins/@loaders/mjs.js +4 -0
- package/src/builtins/@loaders/ori.js +21 -0
- package/src/builtins/@loaders/orit.js +48 -0
- package/src/builtins/@loaders/txt.js +33 -0
- package/src/builtins/@loaders/xhtml.js +4 -0
- package/src/builtins/@loaders/yaml.js +18 -0
- package/src/builtins/@loaders/yml.js +4 -0
- package/src/builtins/@map.js +182 -0
- package/src/builtins/@match.js +92 -0
- package/src/builtins/@mdHtml.js +45 -0
- package/src/builtins/@new.js +6 -0
- package/src/builtins/@node.js +15 -0
- package/src/builtins/@not.js +6 -0
- package/src/builtins/@or.js +6 -0
- package/src/builtins/@ori.js +83 -0
- package/src/builtins/@pack.js +13 -0
- package/src/builtins/@parse/json.js +7 -0
- package/src/builtins/@parse/yaml.js +9 -0
- package/src/builtins/@project.js +71 -0
- package/src/builtins/@repeat.js +8 -0
- package/src/builtins/@rss.js +49 -0
- package/src/builtins/@scope/extend.js +22 -0
- package/src/builtins/@scope/get.js +25 -0
- package/src/builtins/@scope/invoke.js +22 -0
- package/src/builtins/@scope/set.js +25 -0
- package/src/builtins/@serve.js +74 -0
- package/src/builtins/@shell.js +16 -0
- package/src/builtins/@stdin.js +26 -0
- package/src/builtins/@svg.js +42 -0
- package/src/builtins/@tree/concat.js +21 -0
- package/src/builtins/@tree/count.js +24 -0
- package/src/builtins/@tree/defineds.js +37 -0
- package/src/builtins/@tree/dot.js +201 -0
- package/src/builtins/@tree/exceptions.js +50 -0
- package/src/builtins/@tree/first.js +28 -0
- package/src/builtins/@tree/flowSvg.js +55 -0
- package/src/builtins/@tree/fn.js +34 -0
- package/src/builtins/@tree/from.js +27 -0
- package/src/builtins/@tree/fromJson.js +6 -0
- package/src/builtins/@tree/fromYaml.js +24 -0
- package/src/builtins/@tree/groupBy.js +39 -0
- package/src/builtins/@tree/inners.js +44 -0
- package/src/builtins/@tree/isAsyncTree.js +17 -0
- package/src/builtins/@tree/keys.js +24 -0
- package/src/builtins/@tree/keysJson.js +44 -0
- package/src/builtins/@tree/map.d.ts +19 -0
- package/src/builtins/@tree/merge.js +47 -0
- package/src/builtins/@tree/mergeDeep.js +44 -0
- package/src/builtins/@tree/nextKey.js +29 -0
- package/src/builtins/@tree/parent.js +24 -0
- package/src/builtins/@tree/paths.js +35 -0
- package/src/builtins/@tree/plain.js +22 -0
- package/src/builtins/@tree/previousKey.js +29 -0
- package/src/builtins/@tree/reverse.js +51 -0
- package/src/builtins/@tree/setDeep.js +45 -0
- package/src/builtins/@tree/shuffle.js +31 -0
- package/src/builtins/@tree/sitemap.js +59 -0
- package/src/builtins/@tree/sort.js +25 -0
- package/src/builtins/@tree/sortBy.js +40 -0
- package/src/builtins/@tree/static.js +51 -0
- package/src/builtins/@tree/table.js +74 -0
- package/src/builtins/@tree/take.js +40 -0
- package/src/builtins/@tree/values.js +23 -0
- package/src/builtins/@tree/valuesDeep.js +23 -0
- package/src/builtins/@treeHttp.js +19 -0
- package/src/builtins/@treeHttps.js +19 -0
- package/src/builtins/@true.js +1 -0
- package/src/builtins/@unpack.js +13 -0
- package/src/builtins/@watch.js +108 -0
- package/src/builtins/@with.js +22 -0
- package/src/builtins/@yaml.js +23 -0
- package/src/builtins/~.js +9 -0
- package/src/cli/cli.js +86 -0
- package/src/cli/defaultModuleExport.js +16 -0
- package/src/cli/showUsage.js +86 -0
- package/src/common/CommandModulesTransform.d.ts +5 -0
- package/src/common/CommandModulesTransform.js +37 -0
- package/src/common/ConstantTree.js +17 -0
- package/src/common/ExplorableSiteTransform.d.ts +5 -0
- package/src/common/ExplorableSiteTransform.js +77 -0
- package/src/common/FilterTree.js +60 -0
- package/src/common/GlobTree.js +67 -0
- package/src/common/ShuffleTransform.js +29 -0
- package/src/common/TextDocument.js +57 -0
- package/src/common/addValueKeyToScope.js +30 -0
- package/src/common/arrowFunctionsMap.js +35 -0
- package/src/common/processUnpackedContent.js +39 -0
- package/src/common/serialize.d.ts +8 -0
- package/src/common/serialize.js +138 -0
- package/src/common/utilities.d.ts +7 -0
- package/src/common/utilities.js +132 -0
- package/src/misc/OriCommandTransform.d.ts +5 -0
- package/src/misc/OriCommandTransform.js +54 -0
- package/src/misc/assertScopeIsDefined.js +7 -0
- package/src/misc/explore.orit +241 -0
- package/src/misc/yamlOrigamiTag.js +17 -0
- package/src/server/mediaTypes.js +97 -0
- package/src/server/server.js +258 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { OrigamiFiles, Scope } from "@weborigami/language";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
+
*
|
|
9
|
+
* @this {AsyncTree|null}
|
|
10
|
+
* @param {string[]} keys
|
|
11
|
+
*/
|
|
12
|
+
export default async function files(...keys) {
|
|
13
|
+
assertScopeIsDefined(this);
|
|
14
|
+
const resolved = path.resolve(process.cwd(), ...keys);
|
|
15
|
+
/** @type {AsyncTree} */
|
|
16
|
+
let result = new OrigamiFiles(resolved);
|
|
17
|
+
result = Scope.treeWithScope(result, this);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
files.usage = `@files [path]\tTree of files at the given path`;
|
|
22
|
+
files.documentation = "https://graphorigami.org/language/@files.html";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Scope } from "@weborigami/language";
|
|
2
|
+
import FilterTree from "../common/FilterTree.js";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Apply a filter to a tree.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
|
+
* @this {AsyncTree|null}
|
|
11
|
+
* @param {Treelike} treelike
|
|
12
|
+
* @param {Treelike} filterVariant
|
|
13
|
+
*/
|
|
14
|
+
export default async function filter(treelike, filterVariant) {
|
|
15
|
+
assertScopeIsDefined(this);
|
|
16
|
+
/** @type {AsyncTree} */
|
|
17
|
+
let result = new FilterTree(treelike, filterVariant);
|
|
18
|
+
result = Scope.treeWithScope(result, this);
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
filter.usage = `@filter <tree>, <filter>\tOnly returns values whose keys match the filter`;
|
|
23
|
+
filter.documentation = "https://graphorigami.org/language/@filter.html";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Scope } from "@weborigami/language";
|
|
2
|
+
import GlobTree from "../common/GlobTree.js";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Define a tree whose keys are globs.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
|
+
*
|
|
11
|
+
* @param {Treelike} tree
|
|
12
|
+
* @this {AsyncTree|null}
|
|
13
|
+
*/
|
|
14
|
+
export default async function globs(tree) {
|
|
15
|
+
assertScopeIsDefined(this);
|
|
16
|
+
/** @type {AsyncTree} */
|
|
17
|
+
let result = new GlobTree(tree);
|
|
18
|
+
result = Scope.treeWithScope(result, this);
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
globs.usage = `@globs <patterns>\tDefine a tree whose keys can include wildcard globs`;
|
|
23
|
+
globs.documentation = "https://graphorigami.org/language/@globs.html";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
|
+
import child_process from "node:child_process";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
const groupUrls = {
|
|
6
|
+
"@cache": "https://graphorigami.org/language/@cache.html",
|
|
7
|
+
"@tree": "https://graphorigami.org/language/@tree.html",
|
|
8
|
+
"@image": "https://graphorigami.org/language/@image.html",
|
|
9
|
+
"@parse": "https://graphorigami.org/language/@parse.html",
|
|
10
|
+
"@scope": "https://graphorigami.org/language/@scope.html",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @this {AsyncTree|null}
|
|
15
|
+
* @param {string} [name]
|
|
16
|
+
*/
|
|
17
|
+
export default async function help(name) {
|
|
18
|
+
assertScopeIsDefined(this);
|
|
19
|
+
let url;
|
|
20
|
+
const scope = this;
|
|
21
|
+
if (scope && name) {
|
|
22
|
+
if (groupUrls[name]) {
|
|
23
|
+
url = groupUrls[name];
|
|
24
|
+
} else {
|
|
25
|
+
const fn = await scope.get(name);
|
|
26
|
+
url = fn?.documentation;
|
|
27
|
+
}
|
|
28
|
+
if (!url) {
|
|
29
|
+
console.error(
|
|
30
|
+
`help: ${name} does not have a property called "documentation" linking to its documentation`
|
|
31
|
+
);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
url = "https://graphorigami.org/cli/";
|
|
36
|
+
}
|
|
37
|
+
const platform = process.platform;
|
|
38
|
+
const start =
|
|
39
|
+
platform === "darwin"
|
|
40
|
+
? "open"
|
|
41
|
+
: platform === "win32"
|
|
42
|
+
? "start"
|
|
43
|
+
: "xdg-open";
|
|
44
|
+
const command = `${start} ${url}`;
|
|
45
|
+
child_process.exec(command);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
help.usage = `@help/<name>\tOpens documentation for the named built-in command`;
|
|
49
|
+
help.documentation = "https://graphorigami.org/language/@help.html";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ops } from "@weborigami/language";
|
|
2
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Retrieve the indicated web resource via HTTP.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
+
*
|
|
9
|
+
* @this {AsyncTree|null}
|
|
10
|
+
* @param {string} host
|
|
11
|
+
* @param {...string} keys
|
|
12
|
+
*/
|
|
13
|
+
export default async function http(host, ...keys) {
|
|
14
|
+
assertScopeIsDefined(this);
|
|
15
|
+
return ops.http.call(this, host, ...keys);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
http.usage = `@http <host>, <...keys>\tA web resource via HTTP`;
|
|
19
|
+
http.documentation = "https://graphorigami.org/language/@http.html";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ops } from "@weborigami/language";
|
|
2
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Retrieve the indicated web resource via HTTPS.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
8
|
+
*
|
|
9
|
+
* @this {AsyncTree|null}
|
|
10
|
+
* @param {string} host
|
|
11
|
+
* @param {...string} keys
|
|
12
|
+
*/
|
|
13
|
+
export default async function https(host, ...keys) {
|
|
14
|
+
assertScopeIsDefined(this);
|
|
15
|
+
return ops.https.call(this, host, ...keys);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
https.usage = `@https <host>, <...keys>\tA web resource via HTTPS`;
|
|
19
|
+
https.documentation = "https://graphorigami.org/language/@https.html";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
|
+
import { Tree } from "@weborigami/async-tree";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @this {AsyncTree|null}
|
|
7
|
+
* @param {any} value
|
|
8
|
+
* @param {any} trueResult
|
|
9
|
+
* @param {any} [falseResult]
|
|
10
|
+
*/
|
|
11
|
+
export default async function ifCommand(value, trueResult, falseResult) {
|
|
12
|
+
assertScopeIsDefined(this);
|
|
13
|
+
let condition = await value;
|
|
14
|
+
if (Tree.isAsyncTree(condition)) {
|
|
15
|
+
const keys = Array.from(await condition.keys());
|
|
16
|
+
condition = keys.length > 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let result = condition ? trueResult : falseResult;
|
|
20
|
+
if (typeof result === "function") {
|
|
21
|
+
result = await result.call(this);
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
ifCommand.usage = `@if <value>, <true>, [<false>]\tThe true or false result based on the value`;
|
|
27
|
+
ifCommand.documentation = "https://graphorigami.org/language/@if.html";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Tree } from "@weborigami/async-tree";
|
|
2
|
+
import { keySymbol } from "../common/utilities.js";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Return a default index.html page for the current tree.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
10
|
+
* @this {AsyncTree|null}
|
|
11
|
+
* @param {Treelike} [treelike]
|
|
12
|
+
*/
|
|
13
|
+
export default async function index(treelike) {
|
|
14
|
+
assertScopeIsDefined(this);
|
|
15
|
+
treelike = treelike ?? (await this?.get("@current"));
|
|
16
|
+
if (treelike === undefined) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const tree = Tree.from(treelike);
|
|
20
|
+
const keys = Array.from(await tree.keys());
|
|
21
|
+
|
|
22
|
+
// Skip system-ish files that start with a period. Also skip `index.html`.
|
|
23
|
+
const filtered = keys.filter(
|
|
24
|
+
(key) => !(key.startsWith?.(".") || key === "index.html")
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const links = [];
|
|
28
|
+
for (const key of filtered) {
|
|
29
|
+
const keyText = String(key);
|
|
30
|
+
// Simple key.
|
|
31
|
+
const link = `<li><a href="${keyText}">${keyText}</a></li>`;
|
|
32
|
+
links.push(link);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const heading = tree[keySymbol] ?? "Index";
|
|
36
|
+
const list = `
|
|
37
|
+
<h1>${heading.trim()}</h1>
|
|
38
|
+
<ul>\n${links.join("\n").trim()}\n</ul>
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
const html = `
|
|
42
|
+
<!DOCTYPE html>
|
|
43
|
+
<html lang="en">
|
|
44
|
+
<head>
|
|
45
|
+
<meta charset="utf-8" />
|
|
46
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
47
|
+
<style>
|
|
48
|
+
li {
|
|
49
|
+
margin-bottom: 0.20em;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
a {
|
|
53
|
+
text-decoration: none;
|
|
54
|
+
}
|
|
55
|
+
a:hover {
|
|
56
|
+
text-decoration: revert;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
59
|
+
</head>
|
|
60
|
+
<body>
|
|
61
|
+
${list.trim()}
|
|
62
|
+
</body>
|
|
63
|
+
</html>`;
|
|
64
|
+
|
|
65
|
+
/** @type {any} */
|
|
66
|
+
const result = new String(html.trim());
|
|
67
|
+
result.unpack = () => tree;
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
index.usage = `@index\tReturn a default index.html page for the current tree`;
|
|
72
|
+
index.documentation = "https://graphorigami.org/language/@index.html";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
|
+
import { ops } from "@weborigami/language";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Return the inherited value (if any) for the indicated key.
|
|
7
|
+
*
|
|
8
|
+
* @param {any} key
|
|
9
|
+
* @this {AsyncTree|null}
|
|
10
|
+
*/
|
|
11
|
+
export default async function inherited(key) {
|
|
12
|
+
assertScopeIsDefined(this);
|
|
13
|
+
return ops.inherited.call(this, key);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
inherited.usage = `@inherited <key>\tThe value of the key in the tree's inherited scope`;
|
|
17
|
+
inherited.documentation = "https://graphorigami.org/language/@inherited.html";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
2
|
+
import unpackOrigamiTemplate from "./@loaders/orit.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Inline any Origami expressions found inside {{...}} placeholders in the input
|
|
6
|
+
* text.
|
|
7
|
+
*
|
|
8
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
9
|
+
* @typedef {import("@weborigami/async-tree").StringLike} StringLike
|
|
10
|
+
*
|
|
11
|
+
* @this {AsyncTree|null}
|
|
12
|
+
* @param {StringLike} input
|
|
13
|
+
*/
|
|
14
|
+
export default async function inline(input) {
|
|
15
|
+
assertScopeIsDefined(this);
|
|
16
|
+
if (/** @type {any} */ (input).unpack) {
|
|
17
|
+
input = await /** @type {any} */ (input).unpack();
|
|
18
|
+
}
|
|
19
|
+
const inputDocument = input["@text"] ? input : null;
|
|
20
|
+
const templateInput = inputDocument ?? input;
|
|
21
|
+
const templateFn = await unpackOrigamiTemplate(templateInput);
|
|
22
|
+
const text = await templateFn(inputDocument);
|
|
23
|
+
return inputDocument
|
|
24
|
+
? Object.assign({}, inputDocument, { "@text": String(text) })
|
|
25
|
+
: text;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
inline.usage = `@inline <text>\tInline Origami expressions found in the text`;
|
|
29
|
+
inline.documentation = "https://graphorigami.org/language/@inline.html";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import builtins from "./@builtins.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Invoke the given function.
|
|
5
|
+
*
|
|
6
|
+
* This built-in exists to facilitate executing an Origami file as a script via
|
|
7
|
+
* a [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) directive.
|
|
8
|
+
*
|
|
9
|
+
* You can execute a foo.ori file as a script by adding the following shebang
|
|
10
|
+
* directive to the top of the file:
|
|
11
|
+
*
|
|
12
|
+
* ```sh
|
|
13
|
+
* #!/usr/bin/env ori @invoke
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Then mark the file as executable:
|
|
17
|
+
*
|
|
18
|
+
* ```sh
|
|
19
|
+
* chmod +x foo.ori
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @this {import("@weborigami/types").AsyncTree|null}
|
|
23
|
+
*/
|
|
24
|
+
export default async function invoke(fn) {
|
|
25
|
+
if (typeof fn !== "function" && fn.unpack) {
|
|
26
|
+
fn = await fn.unpack();
|
|
27
|
+
}
|
|
28
|
+
const scope = (await this?.get("@current")) ?? builtins;
|
|
29
|
+
return typeof fn === "function" ? fn.call(scope) : fn;
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const js = {
|
|
2
|
+
Array,
|
|
3
|
+
Boolean,
|
|
4
|
+
Date,
|
|
5
|
+
Error,
|
|
6
|
+
Infinity,
|
|
7
|
+
Intl,
|
|
8
|
+
JSON,
|
|
9
|
+
Math,
|
|
10
|
+
NaN,
|
|
11
|
+
Number,
|
|
12
|
+
Object,
|
|
13
|
+
RegExp,
|
|
14
|
+
String,
|
|
15
|
+
Symbol,
|
|
16
|
+
decodeURI,
|
|
17
|
+
decodeURIComponent,
|
|
18
|
+
encodeURI,
|
|
19
|
+
encodeURIComponent,
|
|
20
|
+
false: false,
|
|
21
|
+
isFinite,
|
|
22
|
+
isNaN,
|
|
23
|
+
null: null,
|
|
24
|
+
parseFloat,
|
|
25
|
+
parseInt,
|
|
26
|
+
true: true,
|
|
27
|
+
undefined: undefined,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
js.usage = "@js\tAccess JavaScript classes and utility functions";
|
|
31
|
+
js.documentation = "https://graphorigami.org/language/@js.html";
|
|
32
|
+
|
|
33
|
+
export default js;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
|
|
2
|
+
import * as serialize from "../common/serialize.js";
|
|
3
|
+
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Render the given object in JSON format.
|
|
7
|
+
*
|
|
8
|
+
* @this {AsyncTree|null}
|
|
9
|
+
* @param {any} [obj]
|
|
10
|
+
*/
|
|
11
|
+
export default async function json(obj) {
|
|
12
|
+
assertScopeIsDefined(this);
|
|
13
|
+
obj = obj ?? (await this?.get("@current"));
|
|
14
|
+
if (obj === undefined) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const value = await serialize.toJsonValue(obj);
|
|
18
|
+
return JSON.stringify(value, null, 2);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
json.usage = "@json <obj>\tRender the object as text in JSON format";
|
|
22
|
+
json.documentation = "https://graphorigami.org/language/@json.html";
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Scope } from "@weborigami/language";
|
|
2
|
+
import * as compile from "../../../../language/src/compiler/compile.js";
|
|
3
|
+
import processUnpackedContent from "../../common/processUnpackedContent.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(input, options = {}) {
|
|
12
|
+
const parent = options.parent ?? null;
|
|
13
|
+
|
|
14
|
+
// Compile the body text as an Origami expression and evaluate it.
|
|
15
|
+
const text = String(input);
|
|
16
|
+
const fn = compile.expression(text);
|
|
17
|
+
const parentScope = parent ? Scope.getScope(parent) : builtins;
|
|
18
|
+
let content = await fn.call(parentScope);
|
|
19
|
+
|
|
20
|
+
return processUnpackedContent(content, parent);
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Scope } from "@weborigami/language";
|
|
2
|
+
import * as compile from "../../../../language/src/compiler/compile.js";
|
|
3
|
+
import processUnpackedContent from "../../common/processUnpackedContent.js";
|
|
4
|
+
import * as utilities from "../../common/utilities.js";
|
|
5
|
+
import builtins from "../@builtins.js";
|
|
6
|
+
import unpackText from "./txt.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Load and evaluate an Origami template from a file.
|
|
10
|
+
*
|
|
11
|
+
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
12
|
+
* @type {import("@weborigami/language").FileUnpackFunction}
|
|
13
|
+
*/
|
|
14
|
+
export default async function unpackOrigamiTemplate(input, options = {}) {
|
|
15
|
+
const parent =
|
|
16
|
+
options.parent ??
|
|
17
|
+
/** @type {any} */ (input).parent ??
|
|
18
|
+
/** @type {any} */ (input)[utilities.parentSymbol];
|
|
19
|
+
|
|
20
|
+
// Get the input text and any attached front matter.
|
|
21
|
+
let inputDocument;
|
|
22
|
+
if (input["@text"]) {
|
|
23
|
+
inputDocument = input;
|
|
24
|
+
} else {
|
|
25
|
+
// Unpack the input as a text document with possible front matter.
|
|
26
|
+
inputDocument = await unpackText(input, options);
|
|
27
|
+
}
|
|
28
|
+
const text = utilities.toString(inputDocument);
|
|
29
|
+
|
|
30
|
+
// Compile the body text as an Origami expression and evaluate it.
|
|
31
|
+
const expression = compile.templateDocument(text);
|
|
32
|
+
const parentScope = parent ? Scope.getScope(parent) : builtins;
|
|
33
|
+
const lambda = await expression.call(parentScope);
|
|
34
|
+
|
|
35
|
+
// Wrap the lambda with a function that will attach the input data to the
|
|
36
|
+
// result.
|
|
37
|
+
/** @this {AsyncTree|null} */
|
|
38
|
+
const fn = async function createTemplateResult(templateInput) {
|
|
39
|
+
const text = await lambda.call(this, templateInput);
|
|
40
|
+
/** @type {any} */
|
|
41
|
+
const result = new String(text);
|
|
42
|
+
result.unpack = () => templateInput;
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
fn.code = lambda.code;
|
|
46
|
+
|
|
47
|
+
return processUnpackedContent(fn, parent, inputDocument);
|
|
48
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import TextDocument from "../../common/TextDocument.js";
|
|
2
|
+
import { evaluateYaml } from "../../common/serialize.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Load a file as text document with possible front matter.
|
|
6
|
+
*
|
|
7
|
+
* This process will parse out any YAML or JSON front matter and attach it to
|
|
8
|
+
* the document as data. The first line of the text must be "---", followed by a
|
|
9
|
+
* block of JSON or YAML, followed by another line of "---". Any lines following
|
|
10
|
+
* will be treated as the document text.
|
|
11
|
+
*
|
|
12
|
+
* Any Origami expressions in the front matter will be evaluated and the results
|
|
13
|
+
* incorporated into the document data.
|
|
14
|
+
*
|
|
15
|
+
* @type {import("@weborigami/language").FileUnpackFunction}
|
|
16
|
+
*/
|
|
17
|
+
export default async function unpackText(input, options = {}) {
|
|
18
|
+
const parent = options.parent ?? null;
|
|
19
|
+
const text = String(input);
|
|
20
|
+
const regex =
|
|
21
|
+
/^(---\r?\n(?<frontText>[\s\S]*?\r?\n)---\r?\n)(?<body>[\s\S]*$)/;
|
|
22
|
+
const match = regex.exec(text);
|
|
23
|
+
|
|
24
|
+
const body = match?.groups?.body ?? text;
|
|
25
|
+
|
|
26
|
+
const frontData = match?.groups
|
|
27
|
+
? await evaluateYaml(match.groups.frontText, parent)
|
|
28
|
+
: null;
|
|
29
|
+
|
|
30
|
+
const object = Object.assign({}, frontData, { "@text": body });
|
|
31
|
+
|
|
32
|
+
return new TextDocument(object, options.parent);
|
|
33
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as YAMLModule from "yaml";
|
|
2
|
+
import processUnpackedContent from "../../common/processUnpackedContent.js";
|
|
3
|
+
import { evaluateYaml } from "../../common/serialize.js";
|
|
4
|
+
|
|
5
|
+
// See notes at serialize.js
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
const YAML = YAMLModule.default ?? YAMLModule.YAML;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Load a file as YAML.
|
|
11
|
+
*
|
|
12
|
+
* @type {import("@weborigami/language").FileUnpackFunction}
|
|
13
|
+
*/
|
|
14
|
+
export default async function unpackYaml(input, options = {}) {
|
|
15
|
+
const parent = options.parent ?? null;
|
|
16
|
+
const data = evaluateYaml(String(input), options.parent);
|
|
17
|
+
return processUnpackedContent(data, parent);
|
|
18
|
+
}
|