@weborigami/origami 0.0.60 → 0.0.61

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,6 +1,5 @@
1
1
  // This file is generated by running buildExports.js -- do not edit by hand.
2
2
  export { default as addNextPrevious } from "../src/builtins/@addNextPrevious.js";
3
- export { default as arrowsMap } from "../src/builtins/@arrowsMap.js";
4
3
  export { default as basename } from "../src/builtins/@basename.js";
5
4
  export { default as breakpoint } from "../src/builtins/@breakpoint.js";
6
5
  export { default as builtins } from "../src/builtins/@builtins.js";
@@ -133,6 +132,7 @@ export * from "../src/common/utilities.js";
133
132
  export { default as assertTreeIsDefined } from "../src/misc/assertTreeIsDefined.js";
134
133
  export { default as getTreeArgument } from "../src/misc/getTreeArgument.js";
135
134
  export { default as OriCommandTransform } from "../src/misc/OriCommandTransform.js";
135
+ export { default as origamiHighlightDefinition } from "../src/misc/origamiHighlightDefinition.js";
136
136
  export { default as treeDot } from "../src/misc/treeDot.js";
137
137
  export { default as constructResponse } from "../src/server/constructResponse.js";
138
138
  export * from "../src/server/mediaTypes.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/origami",
3
- "version": "0.0.60",
3
+ "version": "0.0.61",
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.5.3"
18
18
  },
19
19
  "dependencies": {
20
- "@weborigami/async-tree": "0.0.60",
21
- "@weborigami/language": "0.0.60",
22
- "@weborigami/types": "0.0.60",
20
+ "@weborigami/async-tree": "0.0.61",
21
+ "@weborigami/language": "0.0.61",
22
+ "@weborigami/types": "0.0.61",
23
23
  "exif-parser": "0.1.12",
24
24
  "graphviz-wasm": "3.0.2",
25
25
  "highlight.js": "11.9.0",
@@ -6,6 +6,9 @@ import { markedHighlight } from "marked-highlight";
6
6
  import { markedSmartypants } from "marked-smartypants";
7
7
  import documentObject from "../common/documentObject.js";
8
8
  import { replaceExtension, toString } from "../common/utilities.js";
9
+ import origamiHighlightDefinition from "../misc/origamiHighlightDefinition.js";
10
+
11
+ highlight.registerLanguage("ori", origamiHighlightDefinition);
9
12
 
10
13
  marked.use(
11
14
  markedGfmHeadingId(),
@@ -1,4 +1,8 @@
1
- import { Tree, getRealmObjectPrototype } from "@weborigami/async-tree";
1
+ import {
2
+ Tree,
3
+ getRealmObjectPrototype,
4
+ toString,
5
+ } from "@weborigami/async-tree";
2
6
  import { compile } from "@weborigami/language";
3
7
  import builtins from "../builtins/@builtins.js";
4
8
  import { toYaml } from "../common/serialize.js";
@@ -22,7 +26,7 @@ export default async function ori(
22
26
  assertTreeIsDefined(this, "ori");
23
27
 
24
28
  // In case expression has come from a file, cast it to a string.
25
- expression = String(expression);
29
+ expression = toString(expression);
26
30
 
27
31
  // Run in the context of `this` if defined, otherwise use the builtins.
28
32
  const tree = this ?? builtins;
@@ -1,55 +1,109 @@
1
1
  import { Tree } from "@weborigami/async-tree";
2
2
  import assertTreeIsDefined from "../misc/assertTreeIsDefined.js";
3
3
 
4
+ const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
5
+ const months = [
6
+ "Jan",
7
+ "Feb",
8
+ "Mar",
9
+ "Apr",
10
+ "May",
11
+ "Jun",
12
+ "Jul",
13
+ "Aug",
14
+ "Sep",
15
+ "Oct",
16
+ "Nov",
17
+ "Dec",
18
+ ];
19
+
4
20
  /**
5
21
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
6
22
  * @typedef {import("@weborigami/async-tree").Treelike} Treelike
7
23
  * @this {AsyncTree|null}
8
24
  * @param {Treelike} jsonFeedTree
25
+ * @param {any} options
9
26
  */
10
- export default async function rss(jsonFeedTree) {
27
+ export default async function rss(jsonFeedTree, options = {}) {
11
28
  assertTreeIsDefined(this, "rss");
12
29
  const jsonFeed = await Tree.plain(jsonFeedTree);
13
- const { description, home_page_url, items, feed_url, title } = jsonFeed;
30
+ const { description, home_page_url, items, title } = jsonFeed;
14
31
 
15
- // Presume that the RSS feed lives in same location as feed_url.
16
- const parts = feed_url.split("/");
17
- parts.pop();
18
- parts.push("rss.xml");
19
- const rssUrl = parts.join("/");
32
+ let { feed_url, language } = options;
33
+ if (!feed_url && jsonFeed.feed_url) {
34
+ // Presume that the RSS feed lives in same location as feed_url
35
+ // but with a .xml extension.
36
+ feed_url = jsonFeed.feed_url;
37
+ if (feed_url.endsWith(".json")) {
38
+ feed_url = feed_url.replace(".json", ".xml");
39
+ }
40
+ }
20
41
 
21
42
  const itemsRss = items?.map((story) => itemRss(story)).join("") ?? [];
22
43
 
44
+ const titleElement = title ? ` <title>![CDATA[${title}]]</title>\n` : "";
45
+ const descriptionElement = description
46
+ ? ` <description>${description}</description>\n`
47
+ : "";
48
+ const linkElement = home_page_url
49
+ ? ` <link>${home_page_url}</link>\n`
50
+ : "";
51
+ const languageElement = language
52
+ ? ` <language>${language}</language>\n`
53
+ : "";
54
+ const feedLinkElement = ` <atom:link href="${feed_url}" rel="self" type="application/rss+xml"/>\n`;
55
+ // const feedLinkElement = ` <link rel="self" type="application/atom+xml" href="${feed_url}"/>\n`;
56
+
23
57
  return `<?xml version="1.0" ?>
24
- <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
58
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
25
59
  <channel>
26
- <atom:link href="${rssUrl}" rel="self" type="application/rss+xml"/>
27
- <title><![CDATA[${title}]]></title>
28
- <link>${home_page_url}</link>
29
- <description>${description}</description>
30
- ${itemsRss}</channel>
60
+ ${titleElement}${descriptionElement}${linkElement}${languageElement}${feedLinkElement}${itemsRss} </channel>
31
61
  </rss>`;
32
62
  }
33
63
 
34
64
  function itemRss(jsonFeedItem) {
35
- const { content_html, date_published, id, title, url } = jsonFeedItem;
36
- // RSS wants dates in RFC-822, essentially the same as ISO 8601.
65
+ const { content_html, id, summary, title, url } = jsonFeedItem;
66
+ let { date_published } = jsonFeedItem;
67
+ if (typeof date_published === "string") {
68
+ // Parse as ISO 8601 date.
69
+ date_published = new Date(date_published);
70
+ }
37
71
  const date =
38
72
  date_published instanceof Date
39
- ? date_published.toUTCString()
73
+ ? toRFC822Date(date_published)
40
74
  : date_published;
75
+
41
76
  const dateElement = date ? ` <pubDate>${date}</pubDate>\n` : "";
42
- const guidElement = id ? ` <guid>${id}</guid>\n` : "";
77
+ const isPermaLink =
78
+ id !== undefined && !URL.canParse(id) ? ` isPermaLink="false"` : "";
79
+ const guidElement = id ? ` <guid${isPermaLink}>${id}</guid>\n` : "";
80
+ const descriptionElement = summary
81
+ ? ` <description><![CDATA[${summary}]]></description>\n`
82
+ : "";
43
83
  const contentElement = content_html
44
- ? ` <description><![CDATA[${content_html}]]></description>\n`
84
+ ? ` <content:encoded><![CDATA[${content_html}]]></content:encoded>\n`
85
+ : "";
86
+ const titleElement = title
87
+ ? ` <title><![CDATA[${title}]]></title>\n`
45
88
  : "";
46
- const titleElement = `<![CDATA[${title}]]>`;
89
+ const linkElement = url ? ` <link>${url}</link>\n` : "";
90
+
47
91
  return ` <item>
48
- ${dateElement} <title>${titleElement}</title>
49
- <link>${url}</link>
50
- ${guidElement}${contentElement} </item>
92
+ ${dateElement}${titleElement}${linkElement}${guidElement}${descriptionElement}${contentElement} </item>
51
93
  `;
52
94
  }
53
95
 
96
+ // RSS wants dates in RFC-822.
97
+ function toRFC822Date(date) {
98
+ const day = days[date.getUTCDay()];
99
+ const dayOfMonth = date.getUTCDate().toString().padStart(2, "0");
100
+ const month = months[date.getUTCMonth()];
101
+ const year = date.getUTCFullYear();
102
+ const hours = date.getUTCHours().toString().padStart(2, "0");
103
+ const minutes = date.getUTCMinutes().toString().padStart(2, "0");
104
+ const seconds = date.getUTCSeconds().toString().padStart(2, "0");
105
+ return `${day}, ${dayOfMonth} ${month} ${year} ${hours}:${minutes}:${seconds} GMT`;
106
+ }
107
+
54
108
  rss.usage = `@rss <feed>\tTransforms a JSON Feed tree to RSS XML`;
55
109
  rss.documentation = "https://weborigami.org/language/@rss.html";
@@ -91,10 +91,9 @@ export function toFunction(obj) {
91
91
  */
92
92
  export function toString(object) {
93
93
  if (isPlainObject(object) && "@text" in object) {
94
- return object["@text"];
95
- } else {
96
- return asyncTreeToString(object);
94
+ object = object["@text"];
97
95
  }
96
+ return asyncTreeToString(object);
98
97
  }
99
98
 
100
99
  /**
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Origami language definition for highlight.js
3
+ */
4
+ export default function origamiHighlightDefinition(hljs) {
5
+ return {
6
+ name: "Origami",
7
+ contains: [
8
+ hljs.C_LINE_COMMENT_MODE,
9
+ hljs.C_BLOCK_COMMENT_MODE,
10
+ hljs.C_NUMBER_MODE,
11
+ hljs.APOS_STRING_MODE,
12
+ hljs.QUOTE_STRING_MODE,
13
+ hljs.BACKSLASH_ESCAPE,
14
+ {
15
+ // Backtick template strings
16
+ className: "string",
17
+ begin: "`",
18
+ end: "`",
19
+ contains: [
20
+ hljs.BACKSLASH_ESCAPE,
21
+ {
22
+ className: "subst",
23
+ begin: "\\$\\{",
24
+ end: "\\}",
25
+ contains: [hljs.C_NUMBER_MODE, hljs.QUOTE_STRING_MODE],
26
+ },
27
+ ],
28
+ },
29
+ {
30
+ // Treat all `@` builtins as keywords.
31
+ className: "keyword",
32
+ begin: /@\w+\b/,
33
+ },
34
+ ],
35
+ };
36
+ }
@@ -1,24 +0,0 @@
1
- import { functionResultsMap } from "@weborigami/language";
2
- import arrowsMapFn from "../common/arrowsMapFn.js";
3
- import { keySymbol } from "../common/utilities.js";
4
- import getTreeArgument from "../misc/getTreeArgument.js";
5
- import builtins from "./@builtins.js";
6
-
7
- /**
8
- * Interpret arrow keys in the tree as function calls.
9
- *
10
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
11
- * @typedef {import("@weborigami/async-tree").Treelike} Treelike
12
- * @this {AsyncTree|null}
13
- * @param {Treelike} [treelike]
14
- */
15
- export default async function arrowsMap(treelike) {
16
- const tree = await getTreeArgument(this, arguments, treelike, "arrowsMap");
17
- const mapped = functionResultsMap(arrowsMapFn()(tree));
18
- mapped.parent = this ?? builtins;
19
- mapped[keySymbol] = "@arrowsMap";
20
- return mapped;
21
- }
22
-
23
- arrowsMap.usage = `@arrowsMap <obj>\tInterpret arrow keys in the tree as function calls`;
24
- arrowsMap.documentation = "https://weborigami.org/language/@arrowsMap.html";