@weborigami/origami 0.5.1 → 0.5.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/origami",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Web Origami language, CLI, framework, and server",
5
5
  "type": "module",
6
6
  "repository": {
@@ -17,10 +17,10 @@
17
17
  "typescript": "5.9.2"
18
18
  },
19
19
  "dependencies": {
20
- "@weborigami/async-tree": "0.5.1",
20
+ "@weborigami/async-tree": "0.5.2",
21
21
  "@weborigami/json-feed-to-rss": "1.0.0",
22
- "@weborigami/language": "0.5.1",
23
- "@weborigami/types": "0.5.1",
22
+ "@weborigami/language": "0.5.2",
23
+ "@weborigami/types": "0.5.2",
24
24
  "css-tree": "3.1.0",
25
25
  "exif-parser": "0.1.12",
26
26
  "graphviz-wasm": "3.0.2",
package/src/dev/help.yaml CHANGED
@@ -88,6 +88,9 @@ Origami:
88
88
  mdHtml:
89
89
  args: (markdown)
90
90
  description: Render the markdown as HTML
91
+ mdOutline:
92
+ args: (markdown)
93
+ description: The outline structure of the markdown document
91
94
  naturalOrder:
92
95
  description: A comparison function for natural sort order
93
96
  once:
@@ -15,7 +15,7 @@ const exifDateTags = [
15
15
  export default {
16
16
  mediaType: "image/jpeg",
17
17
 
18
- /** @type {import("@weborigami/language").UnpackFunction} */
18
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
19
19
  async unpack(packed, options) {
20
20
  if (packed instanceof Uint8Array) {
21
21
  // Downgrade to old Node Buffer for exif-parser.
@@ -9,7 +9,7 @@ import processUnpackedContent from "./processUnpackedContent.js";
9
9
  export default {
10
10
  mediaType: "application/javascript",
11
11
 
12
- /** @type {import("@weborigami/language").UnpackFunction} */
12
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
13
13
  async unpack(packed, options = {}) {
14
14
  const { key, parent } = options;
15
15
  if (parent && "import" in parent) {
@@ -9,7 +9,7 @@ import * as utilities from "../common/utilities.js";
9
9
  export default {
10
10
  mediaType: "application/json",
11
11
 
12
- /** @type {import("@weborigami/language").UnpackFunction} */
12
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
13
13
  unpack(packed) {
14
14
  const json = utilities.toString(packed);
15
15
  if (!json) {
@@ -1,8 +1,8 @@
1
+ import { getParent } from "@weborigami/async-tree";
1
2
  import { compile } from "@weborigami/language";
2
3
  import builtinsProgram from "../builtinsProgram.js";
3
4
  import getConfig from "../cli/getConfig.js";
4
5
  import * as utilities from "../common/utilities.js";
5
- import getParent from "./getParent.js";
6
6
  import processUnpackedContent from "./processUnpackedContent.js";
7
7
 
8
8
  /**
@@ -13,7 +13,7 @@ import processUnpackedContent from "./processUnpackedContent.js";
13
13
  export default {
14
14
  mediaType: "text/plain",
15
15
 
16
- /** @type {import("@weborigami/language").UnpackFunction} */
16
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
17
17
  async unpack(packed, options = {}) {
18
18
  const parent = getParent(packed, options);
19
19
 
@@ -1,9 +1,8 @@
1
- import { extension, trailingSlash } from "@weborigami/async-tree";
1
+ import { extension, getParent, trailingSlash } from "@weborigami/async-tree";
2
2
  import { compile } from "@weborigami/language";
3
3
  import builtinsProgram from "../builtinsProgram.js";
4
4
  import getConfig from "../cli/getConfig.js";
5
5
  import { toString } from "../common/utilities.js";
6
- import getParent from "./getParent.js";
7
6
  import processUnpackedContent from "./processUnpackedContent.js";
8
7
 
9
8
  /**
@@ -13,7 +12,7 @@ import processUnpackedContent from "./processUnpackedContent.js";
13
12
  export default {
14
13
  mediaType: "text/plain",
15
14
 
16
- /** @type {import("@weborigami/language").UnpackFunction} */
15
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
17
16
  async unpack(packed, options = {}) {
18
17
  const parent = getParent(packed, options);
19
18
 
@@ -52,7 +52,7 @@ export default {
52
52
  }
53
53
  },
54
54
 
55
- /** @type {import("@weborigami/language").UnpackFunction} */
55
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
56
56
  async unpack(packed, options = {}) {
57
57
  const parent = options.parent ?? null;
58
58
  const text = toString(packed);
@@ -8,7 +8,7 @@ import processUnpackedContent from "./processUnpackedContent.js";
8
8
  export default {
9
9
  mediaType: "application/wasm",
10
10
 
11
- /** @type {import("@weborigami/language").UnpackFunction} */
11
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
12
12
  async unpack(packed, options = {}) {
13
13
  const wasmModule = await WebAssembly.instantiate(packed);
14
14
  // @ts-ignore TypeScript thinks wasmModule is already an Instance.
@@ -17,7 +17,7 @@ const YAML = YAMLModule.default ?? YAMLModule.YAML;
17
17
  export default {
18
18
  mediaType: "application/yaml",
19
19
 
20
- /** @type {import("@weborigami/language").UnpackFunction} */
20
+ /** @type {import("@weborigami/async-tree").UnpackFunction} */
21
21
  unpack(packed, options = {}) {
22
22
  const parent = options.parent ?? null;
23
23
  const yaml = utilities.toString(packed);
@@ -0,0 +1,80 @@
1
+ import { isUnpackable } from "@weborigami/async-tree";
2
+ import { Marked } from "marked";
3
+ import { toString } from "../common/utilities.js";
4
+
5
+ export default async function mdOutline(input) {
6
+ if (isUnpackable(input)) {
7
+ input = await input.unpack();
8
+ }
9
+ const markdown = toString(input);
10
+ if (markdown === null) {
11
+ throw new Error("mdHtml: The provided input couldn't be treated as text.");
12
+ }
13
+
14
+ // Call the marked lexer to parse the markdown into tokens
15
+ const marked = new Marked();
16
+ const lexer = new marked.Lexer();
17
+ const tokens = lexer.lex(markdown);
18
+
19
+ // Turn the linear list of tokens into a hierarchical outline
20
+ const outline = {};
21
+ const stack = [];
22
+ let sectionText = "";
23
+ /** @type {any} */
24
+ let current = outline;
25
+ for (const token of tokens) {
26
+ if (token.type === "heading") {
27
+ // Current section text gets added as content for the current node.
28
+ if (sectionText) {
29
+ current._text = sectionText.trim();
30
+ sectionText = "";
31
+ }
32
+
33
+ // Pop the stack to find the right level for this heading
34
+ const { depth, text: headingText } = token;
35
+ while (stack.length >= depth) {
36
+ current = stack.pop();
37
+ consolidateText(current);
38
+ }
39
+
40
+ // Start a new node for this heading
41
+ const newNode = {};
42
+ current[headingText] = newNode;
43
+ stack.push(current);
44
+ current = newNode;
45
+ } else {
46
+ // Body element, accumulate text
47
+ sectionText += token.raw;
48
+ }
49
+ }
50
+
51
+ // Any remaining section text gets added as content for the current node.
52
+ if (sectionText) {
53
+ current._text = sectionText.trim();
54
+ current = stack.pop();
55
+ if (current) {
56
+ consolidateText(current);
57
+ }
58
+ }
59
+
60
+ return outline;
61
+ }
62
+
63
+ function consolidateText(node) {
64
+ // If the node's last property value is an object with only a _text property,
65
+ // destructively edit the value to be just the text.
66
+ const keys = Object.keys(node);
67
+ if (keys.length === 0) {
68
+ return;
69
+ }
70
+ const lastKey = keys[keys.length - 1];
71
+ const lastValue = node[lastKey];
72
+ if (
73
+ typeof lastValue === "object" &&
74
+ lastValue !== null &&
75
+ Object.keys(lastValue).length === 1 &&
76
+ typeof lastValue._text === "string"
77
+ ) {
78
+ node[lastKey] = lastValue._text;
79
+ }
80
+ }
@@ -21,6 +21,7 @@ export * as image from "./image/image.js";
21
21
  export { default as resize } from "./image/resize.js";
22
22
  export { default as json } from "./json.js";
23
23
  export { default as jsonParse } from "./jsonParse.js";
24
+ export { default as mdOutline } from "./mdOutline.js";
24
25
  export { default as naturalOrder } from "./naturalOrder.js";
25
26
  export { default as once } from "./once.js";
26
27
  export { default as ori } from "./ori.js";
@@ -17,9 +17,9 @@ const templateText = `(urls) => \`<?xml version="1.0" encoding="UTF-8"?>
17
17
  * @typedef {import("@weborigami/async-tree").Treelike} Treelike
18
18
  * @this {AsyncTree|null}
19
19
  * @param {Treelike} treelike
20
- * @param {string} [baseHref ]
20
+ * @param {{ assumeSlashes?: boolean, base?: string }} options
21
21
  */
22
- export default async function sitemap(treelike, baseHref = "") {
22
+ export default async function sitemap(treelike, options = {}) {
23
23
  assertTreeIsDefined(this, "sitemap");
24
24
  const tree = await getTreeArgument(this, arguments, treelike, "sitemap");
25
25
 
@@ -38,7 +38,7 @@ export default async function sitemap(treelike, baseHref = "") {
38
38
  },
39
39
  };
40
40
 
41
- const treePaths = await Tree.paths(filterTree, baseHref);
41
+ const treePaths = await Tree.paths(filterTree, options);
42
42
 
43
43
  // For simplicity, we assume that HTML pages will end in .html.
44
44
  // If the page is named index.html, we remove index.html from
@@ -1,29 +0,0 @@
1
- import { symbols } from "@weborigami/async-tree";
2
-
3
- /**
4
- * Return a suitable parent for the packed file.
5
- *
6
- * @param {any} packed
7
- * @param {any} options
8
- * @returns {import("@weborigami/types").AsyncTree|null}
9
- */
10
- export default function getParent(packed, options) {
11
- // Prefer parent set on options
12
- if (options?.parent) {
13
- return options.parent;
14
- }
15
-
16
- // If the packed object has a `parent` property, use that. Exception: Node
17
- // Buffer objects have a `parent` property that we ignore.
18
- if (packed.parent && !(packed instanceof Buffer)) {
19
- return packed.parent;
20
- }
21
-
22
- // If the packed object has a parent symbol, use that.
23
- if (packed[symbols.parent]) {
24
- return packed[symbols.parent];
25
- }
26
-
27
- // Otherwise, return null.
28
- return null;
29
- }