@weborigami/origami 0.1.0 → 0.2.1
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/package.json +4 -4
- package/src/calc/calc.js +20 -0
- package/src/common/utilities.d.ts +1 -1
- package/src/common/utilities.js +22 -2
- package/src/dev/explore.js +2 -2
- package/src/dev/explore.ori +1 -1
- package/src/dev/treeDot.js +2 -2
- package/src/help/help.yaml +5 -31
- package/src/js.js +1 -0
- package/src/protocols/package.js +30 -8
- package/src/protocols/scope.js +11 -1
- package/src/server/constructResponse.js +3 -0
- package/src/server/server.js +13 -11
- package/src/site/index.js +2 -2
- package/src/text/origamiHighlightDefinition.js +7 -2
- package/src/tree/tree.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/origami",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Web Origami language, CLI, framework, and server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"typescript": "5.6.2"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@weborigami/async-tree": "0.1
|
|
21
|
-
"@weborigami/language": "0.1
|
|
22
|
-
"@weborigami/types": "0.1
|
|
20
|
+
"@weborigami/async-tree": "0.2.1",
|
|
21
|
+
"@weborigami/language": "0.2.1",
|
|
22
|
+
"@weborigami/types": "0.2.1",
|
|
23
23
|
"exif-parser": "0.1.12",
|
|
24
24
|
"graphviz-wasm": "3.0.2",
|
|
25
25
|
"highlight.js": "11.10.0",
|
package/src/calc/calc.js
CHANGED
|
@@ -2,19 +2,27 @@ import { Tree } from "@weborigami/async-tree";
|
|
|
2
2
|
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
3
3
|
|
|
4
4
|
export function add(...args) {
|
|
5
|
+
console.warn(`Warning: "add" is deprecated. Use the "+" operator instead.`);
|
|
5
6
|
const numbers = args.map((arg) => Number(arg));
|
|
6
7
|
return numbers.reduce((acc, val) => acc + val, 0);
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export function and(...args) {
|
|
11
|
+
console.warn(`Warning: "and" is deprecated. Use the "&&" operator instead.`);
|
|
10
12
|
return args.every((arg) => arg);
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export function divide(a, b) {
|
|
16
|
+
console.warn(
|
|
17
|
+
`Warning: "divide" is deprecated. Use the "/" operator instead.`
|
|
18
|
+
);
|
|
14
19
|
return Number(a) / Number(b);
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
export function equals(a, b) {
|
|
23
|
+
console.warn(
|
|
24
|
+
`Warning: "equals" is deprecated. Use the "===" operator instead.`
|
|
25
|
+
);
|
|
18
26
|
return a === b;
|
|
19
27
|
}
|
|
20
28
|
|
|
@@ -27,6 +35,10 @@ export function equals(a, b) {
|
|
|
27
35
|
* @param {any} [falseResult]
|
|
28
36
|
*/
|
|
29
37
|
export async function ifBuiltin(value, trueResult, falseResult) {
|
|
38
|
+
console.warn(
|
|
39
|
+
`Warning: "if" is deprecated. Use the conditional "a ? b : c" operator instead.`
|
|
40
|
+
);
|
|
41
|
+
|
|
30
42
|
assertTreeIsDefined(this, "calc:if");
|
|
31
43
|
let condition = await value;
|
|
32
44
|
if (Tree.isAsyncTree(condition)) {
|
|
@@ -44,18 +56,26 @@ export async function ifBuiltin(value, trueResult, falseResult) {
|
|
|
44
56
|
ifBuiltin.key = "if";
|
|
45
57
|
|
|
46
58
|
export function multiply(...args) {
|
|
59
|
+
console.warn(
|
|
60
|
+
`Warning: "multiply" is deprecated. Use the "*" operator instead.`
|
|
61
|
+
);
|
|
47
62
|
const numbers = args.map((arg) => Number(arg));
|
|
48
63
|
return numbers.reduce((acc, val) => acc * val, 1);
|
|
49
64
|
}
|
|
50
65
|
|
|
51
66
|
export function not(value) {
|
|
67
|
+
console.warn(`Warning: "not" is deprecated. Use the "!" operator instead.`);
|
|
52
68
|
return !value;
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
export function or(...args) {
|
|
72
|
+
console.warn(`Warning: "or" is deprecated. Use the "||" operator instead.`);
|
|
56
73
|
return args.find((arg) => arg);
|
|
57
74
|
}
|
|
58
75
|
|
|
59
76
|
export function subtract(a, b) {
|
|
77
|
+
console.warn(
|
|
78
|
+
`Warning: "subtract" is deprecated. Use the "-" operator instead.`
|
|
79
|
+
);
|
|
60
80
|
return Number(a) - Number(b);
|
|
61
81
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
export
|
|
2
|
+
export function getDescriptor(object: any): string;
|
|
3
3
|
export function hasNonPrintableCharacters(text: string): boolean;
|
|
4
4
|
export function isTransformApplied(Transform: Function, object: any): boolean;
|
|
5
5
|
export function toFunction(object: any): Function;
|
package/src/common/utilities.js
CHANGED
|
@@ -3,7 +3,29 @@ import {
|
|
|
3
3
|
toString as asyncTreeToString,
|
|
4
4
|
isPlainObject,
|
|
5
5
|
isUnpackable,
|
|
6
|
+
trailingSlash,
|
|
6
7
|
} from "@weborigami/async-tree";
|
|
8
|
+
import { symbols } from "@weborigami/language";
|
|
9
|
+
import { basename } from "node:path";
|
|
10
|
+
|
|
11
|
+
// For a given tree, return some user-friendly descriptor
|
|
12
|
+
export function getDescriptor(tree) {
|
|
13
|
+
if ("path" in tree) {
|
|
14
|
+
return trailingSlash.add(basename(tree.path));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const source = tree[symbols.sourceSymbol];
|
|
18
|
+
if (source) {
|
|
19
|
+
// If the source looks like an identifier, use that.
|
|
20
|
+
// TODO: Use real identifier parsing.
|
|
21
|
+
const identifierRegex = /^[A-Za-z0-9_\-\.]+\/?$/;
|
|
22
|
+
if (identifierRegex.test(source)) {
|
|
23
|
+
return trailingSlash.add(source);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
7
29
|
|
|
8
30
|
// Return true if the text appears to contain non-printable binary characters;
|
|
9
31
|
// used to infer whether a file is binary or text.
|
|
@@ -30,8 +52,6 @@ export function isTransformApplied(Transform, obj) {
|
|
|
30
52
|
return false;
|
|
31
53
|
}
|
|
32
54
|
|
|
33
|
-
export const keySymbol = Symbol("key");
|
|
34
|
-
|
|
35
55
|
/**
|
|
36
56
|
* Convert the given object to a function.
|
|
37
57
|
*
|
package/src/dev/explore.js
CHANGED
|
@@ -4,7 +4,7 @@ import { OrigamiFiles } from "@weborigami/language";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
|
|
7
|
-
import {
|
|
7
|
+
import { getDescriptor } from "../common/utilities.js";
|
|
8
8
|
import { builtinsTree } from "../internal.js";
|
|
9
9
|
import debug from "./debug.js";
|
|
10
10
|
|
|
@@ -61,7 +61,7 @@ async function getScopeData(scope) {
|
|
|
61
61
|
// Skip builtins.
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
|
-
const name = tree
|
|
64
|
+
const name = getDescriptor(tree);
|
|
65
65
|
const treeKeys = Array.from(await tree.keys());
|
|
66
66
|
// Skip system-ish files that start with a period.
|
|
67
67
|
const keys = treeKeys.filter((key) => !key.startsWith?.("."));
|
package/src/dev/explore.ori
CHANGED
package/src/dev/treeDot.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
trailingSlash,
|
|
7
7
|
} from "@weborigami/async-tree";
|
|
8
8
|
import * as serialize from "../common/serialize.js";
|
|
9
|
-
import {
|
|
9
|
+
import { getDescriptor } from "../common/utilities.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Render a tree in DOT format.
|
|
@@ -21,7 +21,7 @@ import { keySymbol } from "../common/utilities.js";
|
|
|
21
21
|
*/
|
|
22
22
|
export default async function dot(treelike, options = {}) {
|
|
23
23
|
const tree = Tree.from(treelike, { deep: true });
|
|
24
|
-
const rootLabel = tree
|
|
24
|
+
const rootLabel = getDescriptor(tree) ?? "";
|
|
25
25
|
const treeArcs = await statements(tree, "", rootLabel, options);
|
|
26
26
|
return `digraph g {
|
|
27
27
|
bgcolor="transparent";
|
package/src/help/help.yaml
CHANGED
|
@@ -1,34 +1,3 @@
|
|
|
1
|
-
calc:
|
|
2
|
-
description: Perform math and logical operations
|
|
3
|
-
commands:
|
|
4
|
-
add:
|
|
5
|
-
args: (a, b, ...)
|
|
6
|
-
description: Add the numbers
|
|
7
|
-
and:
|
|
8
|
-
args: (a, b, ...)
|
|
9
|
-
description: Return true if all the arguments are true
|
|
10
|
-
divide:
|
|
11
|
-
args: (a, b)
|
|
12
|
-
description: Divide a by b
|
|
13
|
-
equals:
|
|
14
|
-
args: (a, b)
|
|
15
|
-
description: Return true if a equals b
|
|
16
|
-
if:
|
|
17
|
-
args: (a, b, c)
|
|
18
|
-
description: If a is true return b, otherwise c
|
|
19
|
-
multiply:
|
|
20
|
-
args: (a, b, ...)
|
|
21
|
-
description: Multiply the numbers
|
|
22
|
-
not:
|
|
23
|
-
args: (value)
|
|
24
|
-
description: Return true if a is false and vice versa
|
|
25
|
-
or:
|
|
26
|
-
args: (a, b, ...)
|
|
27
|
-
description: Return true if any of the arguments are true
|
|
28
|
-
subtract:
|
|
29
|
-
args: (a, b)
|
|
30
|
-
description: Subtract b from a
|
|
31
|
-
|
|
32
1
|
dev:
|
|
33
2
|
description: Develop and debug Origami projects
|
|
34
3
|
commands:
|
|
@@ -97,6 +66,8 @@ js:
|
|
|
97
66
|
commands:
|
|
98
67
|
Array:
|
|
99
68
|
description: JavaScript Array class
|
|
69
|
+
BigInt:
|
|
70
|
+
description: JavaScript BigInt class
|
|
100
71
|
Boolean:
|
|
101
72
|
description: JavaScript Boolean class
|
|
102
73
|
Date:
|
|
@@ -399,6 +370,9 @@ tree:
|
|
|
399
370
|
reverse:
|
|
400
371
|
args: (tree)
|
|
401
372
|
description: Reverse the order of the tree's keys
|
|
373
|
+
root:
|
|
374
|
+
args: (tree)
|
|
375
|
+
description: The root node of the given tree
|
|
402
376
|
setDeep:
|
|
403
377
|
args: (target, source)
|
|
404
378
|
description: Applies the source tree to the target
|
package/src/js.js
CHANGED
package/src/protocols/package.js
CHANGED
|
@@ -7,22 +7,39 @@ import project from "../origami/project.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export default async function packageNamespace(...keys) {
|
|
9
9
|
const parent = this ?? (await project.call(null));
|
|
10
|
-
const parentScope = scope(parent);
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
let name = keys.shift();
|
|
12
|
+
let organization;
|
|
13
|
+
if (name?.startsWith("@")) {
|
|
14
|
+
// First key is an npm organization
|
|
15
|
+
organization = name;
|
|
16
|
+
if (keys.length === 0) {
|
|
17
|
+
// Return a function that will process the next key
|
|
18
|
+
return async (name, ...keys) =>
|
|
19
|
+
getPackage(parent, organization, name, keys);
|
|
20
|
+
}
|
|
21
|
+
name = keys.shift();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return getPackage(parent, organization, name, keys);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function getPackage(parent, organization, name, keys) {
|
|
28
|
+
const packagePath = ["node_modules"];
|
|
29
|
+
if (organization) {
|
|
30
|
+
packagePath.push(organization);
|
|
16
31
|
}
|
|
32
|
+
packagePath.push(name);
|
|
17
33
|
|
|
34
|
+
const parentScope = scope(parent);
|
|
18
35
|
const packageRoot = await Tree.traverse(
|
|
19
36
|
// @ts-ignore
|
|
20
37
|
parentScope,
|
|
21
|
-
|
|
22
|
-
...packageKeys
|
|
38
|
+
...packagePath
|
|
23
39
|
);
|
|
40
|
+
|
|
24
41
|
if (!packageRoot) {
|
|
25
|
-
throw new Error(`Can't find
|
|
42
|
+
throw new Error(`Can't find ${packagePath.join("/")}`);
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
const mainPath = await Tree.traverse(packageRoot, "package.json", "main");
|
|
@@ -44,5 +61,10 @@ export default async function packageNamespace(...keys) {
|
|
|
44
61
|
keys.length > 0
|
|
45
62
|
? await Tree.traverse(packageExports, ...keys)
|
|
46
63
|
: packageExports;
|
|
64
|
+
|
|
65
|
+
if (Tree.isAsyncTree(result)) {
|
|
66
|
+
result.parent = parent;
|
|
67
|
+
}
|
|
68
|
+
|
|
47
69
|
return result;
|
|
48
70
|
}
|
package/src/protocols/scope.js
CHANGED
|
@@ -9,6 +9,16 @@ import { ops } from "@weborigami/language";
|
|
|
9
9
|
*/
|
|
10
10
|
export default async function scope(...keys) {
|
|
11
11
|
const key = keys.shift();
|
|
12
|
-
|
|
12
|
+
let value;
|
|
13
|
+
try {
|
|
14
|
+
// Look up key in scope but don't throw if it's undefined
|
|
15
|
+
value = await ops.scope.call(this, key);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (error instanceof ReferenceError) {
|
|
18
|
+
value = undefined;
|
|
19
|
+
} else {
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
13
23
|
return keys.length > 0 ? await Tree.traverse(value, ...keys) : value;
|
|
14
24
|
}
|
|
@@ -43,6 +43,9 @@ export default async function constructResponse(request, resource) {
|
|
|
43
43
|
|
|
44
44
|
if (!isPacked(resource) && typeof resource.pack === "function") {
|
|
45
45
|
resource = await resource.pack();
|
|
46
|
+
if (typeof resource === "function") {
|
|
47
|
+
resource = await resource();
|
|
48
|
+
}
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
let mediaType;
|
package/src/server/server.js
CHANGED
|
@@ -87,26 +87,28 @@ export async function handleRequest(request, response, tree) {
|
|
|
87
87
|
// Ask the tree for the resource with those keys.
|
|
88
88
|
let resource;
|
|
89
89
|
try {
|
|
90
|
-
resource = await Tree.
|
|
90
|
+
resource = await Tree.traverseOrThrow(extendedTree, ...keys);
|
|
91
|
+
|
|
91
92
|
// If resource is a function, invoke to get the object we want to return.
|
|
92
93
|
// For a POST request, pass the data to the function.
|
|
93
94
|
if (typeof resource === "function") {
|
|
94
95
|
resource = data ? await resource(data) : await resource();
|
|
95
96
|
}
|
|
97
|
+
|
|
98
|
+
// Construct the response.
|
|
99
|
+
const constructed = await constructResponse(request, resource);
|
|
100
|
+
if (!constructed) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Copy the construct response to the ServerResponse and return true if
|
|
105
|
+
// the response was valid.
|
|
106
|
+
return copyResponse(constructed, response);
|
|
96
107
|
} catch (/** @type {any} */ error) {
|
|
108
|
+
// Display an error
|
|
97
109
|
respondWithError(response, error);
|
|
98
110
|
return true;
|
|
99
111
|
}
|
|
100
|
-
|
|
101
|
-
// Construct the response.
|
|
102
|
-
const constructed = await constructResponse(request, resource);
|
|
103
|
-
if (!constructed) {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Copy the construct response to the ServerResponse and return true if
|
|
108
|
-
// the response was valid.
|
|
109
|
-
return copyResponse(constructed, response);
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
function keysFromUrl(url) {
|
package/src/site/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import getTreeArgument from "../common/getTreeArgument.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getDescriptor } from "../common/utilities.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Return a default index.html page for the current tree.
|
|
@@ -26,7 +26,7 @@ export default async function index(treelike) {
|
|
|
26
26
|
links.push(link);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const heading = tree
|
|
29
|
+
const heading = getDescriptor(tree) ?? "Index";
|
|
30
30
|
const list = ` <ul>\n${links.join("\n")}\n </ul>`;
|
|
31
31
|
|
|
32
32
|
const html = `<!DOCTYPE html>
|
|
@@ -36,17 +36,22 @@ export default function origamiHighlightDefinition(hljs) {
|
|
|
36
36
|
// Treat identifier containing a period before an open paren or backtick as a variable
|
|
37
37
|
className: "variable",
|
|
38
38
|
begin:
|
|
39
|
-
/\b[^(){}\[\]
|
|
39
|
+
/\b[^(){}\[\]<>\?!\|=,/:\`"'«»\\→⇒… \t\n\r]+\.[^(){}\[\]<>\?!\|=,/:\`"'«»\\→⇒… \t\n\r]+(?=(\(|\`))\b/,
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
className: "built_in",
|
|
43
43
|
// Treat shorthands before open paren or backtick as a builtin
|
|
44
44
|
begin: /\b[A-Za-z][A-Za-z0-9]*(?=(\(|\`))\b/,
|
|
45
45
|
},
|
|
46
|
+
{
|
|
47
|
+
className: "operator",
|
|
48
|
+
begin:
|
|
49
|
+
/===|!==|==|!=|<=|<|>=|>|\*|\*\*|\/|%|\+|-|=>|⇒|->|→|=|:|\.\.\.|…|&&|&|\|\||\||!|\^|~|\?\?|\?|#!/,
|
|
50
|
+
},
|
|
46
51
|
{
|
|
47
52
|
// Treat remaining identifiers as variables
|
|
48
53
|
className: "variable",
|
|
49
|
-
begin: /\b[^(){}\[\]
|
|
54
|
+
begin: /\b[^(){}\[\]<>\?!\|=,/:\`"'«»\\→⇒… \t\n\r]+\b/,
|
|
50
55
|
},
|
|
51
56
|
],
|
|
52
57
|
};
|
package/src/tree/tree.js
CHANGED
|
@@ -44,6 +44,7 @@ export const isTreelike = Tree.isTreelike;
|
|
|
44
44
|
export const mapReduce = Tree.mapReduce;
|
|
45
45
|
export const paths = Tree.paths;
|
|
46
46
|
export const remove = Tree.remove;
|
|
47
|
+
export const root = Tree.root;
|
|
47
48
|
export const traverse = Tree.traverse;
|
|
48
49
|
export const traverseOrThrow = Tree.traverseOrThrow;
|
|
49
50
|
export const traversePath = Tree.traversePath;
|