@weborigami/origami 0.0.42 → 0.0.44
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/exports/buildExports.js +1 -1
- package/exports/exports.js +9 -7
- package/package.json +5 -4
- package/src/builtins/@arrows.js +1 -1
- package/src/builtins/@count.js +1 -1
- package/src/builtins/@image/resize.js +3 -1
- package/src/builtins/@inline.js +12 -1
- package/src/builtins/@loaders/css.js +2 -4
- package/src/builtins/@loaders/htm.js +2 -4
- package/src/builtins/@loaders/html.js +2 -4
- package/src/builtins/@loaders/jpeg.js +55 -0
- package/src/builtins/@loaders/jpg.js +2 -0
- package/src/builtins/@loaders/md.js +2 -4
- package/src/builtins/@loaders/mjs.js +2 -4
- package/src/builtins/@loaders/ori.js +4 -4
- package/src/builtins/@loaders/xhtml.js +2 -4
- package/src/builtins/@loaders/yaml.js +1 -1
- package/src/builtins/@loaders/yml.js +2 -4
- package/src/builtins/@node.js +12 -1
- package/src/builtins/@ori.js +1 -1
- package/src/builtins/@rss.js +8 -6
- package/src/builtins/@sitemap.js +3 -3
- package/src/common/CommandModulesTransform.js +1 -1
- package/src/common/TextDocument.js +2 -1
- package/src/common/processUnpackedContent.js +6 -4
- package/src/common/utilities.d.ts +0 -1
- package/src/common/utilities.js +0 -2
- package/src/misc/explore.ori +4 -4
- package/src/misc/treeDot.js +5 -1
- package/src/misc/yamlOrigamiTag.js +2 -2
package/exports/buildExports.js
CHANGED
|
@@ -15,7 +15,7 @@ const specialBuiltinNames = {
|
|
|
15
15
|
|
|
16
16
|
// Top-level template for the export file
|
|
17
17
|
const templateText = `=\`// This file is generated by running buildExports.js -- do not edit by hand.
|
|
18
|
-
{
|
|
18
|
+
\${ _ }\``;
|
|
19
19
|
|
|
20
20
|
// Generate a top-level export file for the entire project. For each .js file in
|
|
21
21
|
// the given source tree, generate an appropriate statement that includes that
|
package/exports/exports.js
CHANGED
|
@@ -38,18 +38,20 @@ export { default as js } from "../src/builtins/@js.js";
|
|
|
38
38
|
export { default as json } from "../src/builtins/@json.js";
|
|
39
39
|
export { default as keys } from "../src/builtins/@keys.js";
|
|
40
40
|
export { default as keysJson } from "../src/builtins/@keysJson.js";
|
|
41
|
-
export
|
|
42
|
-
export
|
|
43
|
-
export
|
|
41
|
+
export * from "../src/builtins/@loaders/css.js";
|
|
42
|
+
export * from "../src/builtins/@loaders/htm.js";
|
|
43
|
+
export * from "../src/builtins/@loaders/html.js";
|
|
44
|
+
export { default as loadersJpeg } from "../src/builtins/@loaders/jpeg.js";
|
|
45
|
+
export * from "../src/builtins/@loaders/jpg.js";
|
|
44
46
|
export { default as loadersJs } from "../src/builtins/@loaders/js.js";
|
|
45
47
|
export { default as loadersJson } from "../src/builtins/@loaders/json.js";
|
|
46
|
-
export
|
|
47
|
-
export
|
|
48
|
+
export * from "../src/builtins/@loaders/md.js";
|
|
49
|
+
export * from "../src/builtins/@loaders/mjs.js";
|
|
48
50
|
export { default as loadersOri } from "../src/builtins/@loaders/ori.js";
|
|
49
51
|
export { default as loadersTxt } from "../src/builtins/@loaders/txt.js";
|
|
50
|
-
export
|
|
52
|
+
export * from "../src/builtins/@loaders/xhtml.js";
|
|
51
53
|
export { default as loadersYaml } from "../src/builtins/@loaders/yaml.js";
|
|
52
|
-
export
|
|
54
|
+
export * from "../src/builtins/@loaders/yml.js";
|
|
53
55
|
export { default as map } from "../src/builtins/@map.js";
|
|
54
56
|
export { default as mapDeep } from "../src/builtins/@mapDeep.js";
|
|
55
57
|
export { default as match } from "../src/builtins/@match.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/origami",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.44",
|
|
4
4
|
"description": "Web Origami language, CLI, framework, and server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -19,9 +19,10 @@
|
|
|
19
19
|
"typescript": "5.3.3"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@weborigami/async-tree": "
|
|
23
|
-
"@weborigami/language": "
|
|
24
|
-
"@weborigami/types": "0.0.
|
|
22
|
+
"@weborigami/async-tree": "0.0.44",
|
|
23
|
+
"@weborigami/language": "0.0.44",
|
|
24
|
+
"@weborigami/types": "0.0.44",
|
|
25
|
+
"exif-parser": "0.1.12",
|
|
25
26
|
"graphviz-wasm": "3.0.1",
|
|
26
27
|
"highlight.js": "11.9.0",
|
|
27
28
|
"marked": "11.1.1",
|
package/src/builtins/@arrows.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Scope, functionResultsMap } from "@weborigami/language";
|
|
2
|
-
import builtins from "../../src/builtins/@builtins.js";
|
|
3
2
|
import arrowFunctionsMap from "../common/arrowFunctionsMap.js";
|
|
4
3
|
import { keySymbol } from "../common/utilities.js";
|
|
5
4
|
import getTreeArgument from "../misc/getTreeArgument.js";
|
|
5
|
+
import builtins from "./@builtins.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Interpret arrow keys in the tree as function calls.
|
package/src/builtins/@count.js
CHANGED
|
@@ -10,7 +10,7 @@ import getTreeArgument from "../misc/getTreeArgument.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export default async function count(treelike) {
|
|
12
12
|
const tree = await getTreeArgument(this, arguments, treelike, "@count");
|
|
13
|
-
const keys =
|
|
13
|
+
const keys = Array.from(await tree.keys());
|
|
14
14
|
return keys.length;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -27,7 +27,9 @@ export default function resize(param1, param2) {
|
|
|
27
27
|
options = param2;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
// Include `rotate()` to auto-rotate according to EXIF data.
|
|
31
|
+
const transform = (buffer) =>
|
|
32
|
+
sharp(buffer).rotate().resize(options).toBuffer();
|
|
31
33
|
|
|
32
34
|
return buffer ? transform(buffer) : transform;
|
|
33
35
|
}
|
package/src/builtins/@inline.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { Tree, isPlainObject } from "@weborigami/async-tree";
|
|
1
2
|
import { compile } from "@weborigami/language";
|
|
2
3
|
import unpackText from "../builtins/@loaders/txt.js";
|
|
3
4
|
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
|
4
5
|
import unpackOrigamiExpression from "./@loaders/ori.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* Inline any Origami expressions found inside {
|
|
8
|
+
* Inline any Origami expressions found inside ${...} placeholders in the input
|
|
8
9
|
* text.
|
|
9
10
|
*
|
|
10
11
|
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
|
@@ -28,7 +29,17 @@ export default async function inline(input) {
|
|
|
28
29
|
inputDocument = await unpackText(input);
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
// If the input document is a plain object or AsyncTree, we'll have it
|
|
33
|
+
// included in scope for the evaluated expression. We ignore other kinds of
|
|
34
|
+
// treelike inputs for this test: in particular, a Buffer will be interpreted
|
|
35
|
+
// as a tree, but we don't want to put a Buffer in scope.
|
|
36
|
+
const attachedData =
|
|
37
|
+
isPlainObject(inputDocument) || Tree.isAsyncTree(inputDocument)
|
|
38
|
+
? inputDocument
|
|
39
|
+
: null;
|
|
40
|
+
|
|
31
41
|
const templateFn = await unpackOrigamiExpression(inputDocument, {
|
|
42
|
+
attachedData,
|
|
32
43
|
compiler: compile.templateDocument,
|
|
33
44
|
});
|
|
34
45
|
const templateResult = await templateFn(inputDocument);
|
|
@@ -0,0 +1,55 @@
|
|
|
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,5 +1,4 @@
|
|
|
1
|
-
import { Scope } from "@weborigami/language";
|
|
2
|
-
import * as compile from "../../../../language/src/compiler/compile.js";
|
|
1
|
+
import { Scope, compile, symbols } from "@weborigami/language";
|
|
3
2
|
import processUnpackedContent from "../../common/processUnpackedContent.js";
|
|
4
3
|
import * as utilities from "../../common/utilities.js";
|
|
5
4
|
import builtins from "../@builtins.js";
|
|
@@ -13,10 +12,11 @@ export default async function unpackOrigamiExpression(
|
|
|
13
12
|
inputDocument,
|
|
14
13
|
options = {}
|
|
15
14
|
) {
|
|
15
|
+
const attachedData = options.attachedData;
|
|
16
16
|
const parent =
|
|
17
17
|
options.parent ??
|
|
18
18
|
/** @type {any} */ (inputDocument).parent ??
|
|
19
|
-
/** @type {any} */ (inputDocument)[
|
|
19
|
+
/** @type {any} */ (inputDocument)[symbols.parent];
|
|
20
20
|
|
|
21
21
|
// Construct an object to represent the source code.
|
|
22
22
|
const sourceName = options.key;
|
|
@@ -41,5 +41,5 @@ export default async function unpackOrigamiExpression(
|
|
|
41
41
|
const parentScope = parent ? Scope.getScope(parent) : builtins;
|
|
42
42
|
let content = await fn.call(parentScope);
|
|
43
43
|
|
|
44
|
-
return processUnpackedContent(content, parent,
|
|
44
|
+
return processUnpackedContent(content, parent, attachedData);
|
|
45
45
|
}
|
|
@@ -13,6 +13,6 @@ const YAML = YAMLModule.default ?? YAMLModule.YAML;
|
|
|
13
13
|
*/
|
|
14
14
|
export default async function unpackYaml(input, options = {}) {
|
|
15
15
|
const parent = options.parent ?? null;
|
|
16
|
-
const data = evaluateYaml(String(input), options.parent);
|
|
16
|
+
const data = await evaluateYaml(String(input), options.parent);
|
|
17
17
|
return processUnpackedContent(data, parent);
|
|
18
18
|
}
|
package/src/builtins/@node.js
CHANGED
|
@@ -2,10 +2,21 @@ import path from "node:path";
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import url from "node:url";
|
|
4
4
|
|
|
5
|
+
// Patch process.env to be a plain object. Among other things, this lets us dump
|
|
6
|
+
// the complete environment to the terminal with `ori @node/process/env`.
|
|
7
|
+
const patchedProcess = Object.create(null, {
|
|
8
|
+
...Object.getOwnPropertyDescriptors(process),
|
|
9
|
+
env: {
|
|
10
|
+
value: function () {
|
|
11
|
+
return Object.assign({}, process.env);
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
5
16
|
const node = {
|
|
6
17
|
Buffer,
|
|
7
18
|
path,
|
|
8
|
-
process,
|
|
19
|
+
process: patchedProcess,
|
|
9
20
|
url,
|
|
10
21
|
};
|
|
11
22
|
|
package/src/builtins/@ori.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tree, getRealmObjectPrototype } from "@weborigami/async-tree";
|
|
2
|
-
import
|
|
2
|
+
import { compile } from "@weborigami/language";
|
|
3
3
|
import builtins from "../builtins/@builtins.js";
|
|
4
4
|
import { toYaml } from "../common/serialize.js";
|
|
5
5
|
import assertScopeIsDefined from "../misc/assertScopeIsDefined.js";
|
package/src/builtins/@rss.js
CHANGED
|
@@ -18,7 +18,7 @@ export default async function rss(jsonFeedTree) {
|
|
|
18
18
|
parts.push("rss.xml");
|
|
19
19
|
const rssUrl = parts.join("/");
|
|
20
20
|
|
|
21
|
-
const itemsRss = items?.map((story) => itemRss(story)).join("
|
|
21
|
+
const itemsRss = items?.map((story) => itemRss(story)).join("") ?? [];
|
|
22
22
|
|
|
23
23
|
return `<?xml version="1.0" ?>
|
|
24
24
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
@@ -27,7 +27,7 @@ export default async function rss(jsonFeedTree) {
|
|
|
27
27
|
<title>${title}</title>
|
|
28
28
|
<link>${home_page_url}</link>
|
|
29
29
|
<description>${description}</description>
|
|
30
|
-
|
|
30
|
+
${itemsRss}</channel>
|
|
31
31
|
</rss>`;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -36,12 +36,14 @@ function itemRss(jsonFeedItem) {
|
|
|
36
36
|
// RSS wants dates in RFC-822.
|
|
37
37
|
const date = date_published?.toUTCString() ?? null;
|
|
38
38
|
const dateElement = date ? ` <pubDate>${date}</pubDate>\n` : "";
|
|
39
|
+
const guidElement = id ? ` <guid>${id}</guid>\n` : "";
|
|
40
|
+
const contentElement = content_html
|
|
41
|
+
? ` <description><![CDATA[${content_html}]]></description>\n`
|
|
42
|
+
: "";
|
|
39
43
|
return ` <item>
|
|
40
|
-
|
|
44
|
+
${dateElement} <title>${title}</title>
|
|
41
45
|
<link>${url}</link>
|
|
42
|
-
|
|
43
|
-
<description><![CDATA[${content_html}]]></description>
|
|
44
|
-
</item>
|
|
46
|
+
${guidElement}${contentElement} </item>
|
|
45
47
|
`;
|
|
46
48
|
}
|
|
47
49
|
|
package/src/builtins/@sitemap.js
CHANGED
|
@@ -5,11 +5,11 @@ import paths from "./@paths.js";
|
|
|
5
5
|
|
|
6
6
|
const templateText = `=\`<?xml version="1.0" encoding="UTF-8"?>
|
|
7
7
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
8
|
-
{
|
|
8
|
+
\${ @map(=\`
|
|
9
9
|
<url>
|
|
10
|
-
<loc
|
|
10
|
+
<loc>\${ _ }</loc>
|
|
11
11
|
</url>
|
|
12
|
-
\`)(_) }
|
|
12
|
+
\`)(_) }
|
|
13
13
|
</urlset>
|
|
14
14
|
\`
|
|
15
15
|
`;
|
|
@@ -27,7 +27,7 @@ export default function CommandsModulesTransform(Base) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async keys() {
|
|
30
|
-
const keys =
|
|
30
|
+
const keys = Array.from(await super.keys());
|
|
31
31
|
// If we find a key like "foo.js", then return "foo" as the key.
|
|
32
32
|
return keys.map((key) =>
|
|
33
33
|
key.endsWith(".js") ? path.basename(key, ".js") : key
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isStringLike } from "@weborigami/async-tree";
|
|
2
|
+
import { symbols } from "@weborigami/language";
|
|
2
3
|
import { toYaml } from "./serialize.js";
|
|
3
4
|
import * as utilities from "./utilities.js";
|
|
4
5
|
|
|
@@ -22,7 +23,7 @@ export default class TextDocument {
|
|
|
22
23
|
constructor(data, parent) {
|
|
23
24
|
Object.assign(this, data);
|
|
24
25
|
if (parent) {
|
|
25
|
-
this[
|
|
26
|
+
this[symbols.parent] = parent;
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -10,18 +10,20 @@ import builtins from "../builtins/@builtins.js";
|
|
|
10
10
|
*
|
|
11
11
|
* @param {any} content
|
|
12
12
|
* @param {AsyncTree|null} parent
|
|
13
|
-
* @param {any} [
|
|
13
|
+
* @param {any} [attachedData]
|
|
14
14
|
* @returns
|
|
15
15
|
*/
|
|
16
|
-
export default function processUnpackedContent(content, parent,
|
|
16
|
+
export default function processUnpackedContent(content, parent, attachedData) {
|
|
17
17
|
if (typeof content === "function") {
|
|
18
18
|
// Wrap the function such to add ambients to the scope.
|
|
19
19
|
const fn = content;
|
|
20
20
|
|
|
21
21
|
// Use the parent's scope, adding any attached data.
|
|
22
22
|
const parentScope = parent ? Scope.getScope(parent) : builtins;
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
// If there's attached data, include it in the scope.
|
|
25
|
+
const extendedScope = attachedData
|
|
26
|
+
? new Scope(attachedData, parentScope)
|
|
25
27
|
: parentScope;
|
|
26
28
|
|
|
27
29
|
const boundFn = fn.bind(extendedScope);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
export const keySymbol: unique symbol;
|
|
3
|
-
export const parentSymbol: unique symbol;
|
|
4
3
|
export function hasNonPrintableCharacters(text: string): boolean;
|
|
5
4
|
export function isTransformApplied(Transform: Function, object: any): boolean;
|
|
6
5
|
export function replaceExtension(key: string, sourceExtension: string, resultExtension: string): string;
|
package/src/common/utilities.js
CHANGED
|
@@ -30,8 +30,6 @@ export function isTransformApplied(Transform, obj) {
|
|
|
30
30
|
|
|
31
31
|
export const keySymbol = Symbol("key");
|
|
32
32
|
|
|
33
|
-
export const parentSymbol = Symbol("parent");
|
|
34
|
-
|
|
35
33
|
/**
|
|
36
34
|
* If the given key ends in the source extension (which will generally include a
|
|
37
35
|
* period), replace that extension with the result extension (which again should
|
package/src/misc/explore.ori
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
6
6
|
<title>Web Origami Explorer</title>
|
|
7
|
-
<style
|
|
8
|
-
<script
|
|
7
|
+
<style>${ explore.css }</style>
|
|
8
|
+
<script>${ explore.js.inline }</script>
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<nav>
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
{{ @map(=`
|
|
20
20
|
<ul>
|
|
21
|
-
<h2
|
|
21
|
+
<h2>${ _/name }</h2>
|
|
22
22
|
{{ @map(=`
|
|
23
23
|
<li>
|
|
24
|
-
<a href="./!@explore
|
|
24
|
+
<a href="./!@explore/${ _ }" target="frame">${ _ }</a>
|
|
25
25
|
</li>
|
|
26
26
|
`)(_/keys) }}
|
|
27
27
|
</ul>
|
package/src/misc/treeDot.js
CHANGED
|
@@ -154,7 +154,11 @@ async function statements(tree, nodePath, nodeLabel, options) {
|
|
|
154
154
|
for (const key in nodes) {
|
|
155
155
|
const node = nodes[key];
|
|
156
156
|
const icon = node.isError ? "⚠️ " : "";
|
|
157
|
-
|
|
157
|
+
// GraphViz has trouble rendering DOT nodes whose labels contain ellipsis
|
|
158
|
+
// characters, so we map those to three periods. GraphViz appears to turn
|
|
159
|
+
// those back into ellipsis characters when rendering the graph.
|
|
160
|
+
const text = node.label.replace(/…/g, "...");
|
|
161
|
+
const label = `label="${icon}${text}"`;
|
|
158
162
|
const color = node.isError ? `; color="red"` : "";
|
|
159
163
|
const fill = node.isError ? `; fillcolor="#FFF4F4"` : "";
|
|
160
164
|
const destPath = nodePath ? `${nodePath}/${key}` : key;
|