@mdsnai/sdk 0.2.2 → 0.3.0

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.
Files changed (255) hide show
  1. package/README.md +39 -75
  2. package/dist/core/errors.d.ts +14 -0
  3. package/dist/core/errors.d.ts.map +1 -0
  4. package/dist/core/errors.js +13 -0
  5. package/dist/core/errors.js.map +1 -0
  6. package/dist/core/index.d.ts +16 -4
  7. package/dist/core/index.d.ts.map +1 -0
  8. package/dist/core/index.js +69 -13
  9. package/dist/core/index.js.map +1 -0
  10. package/dist/core/markdown-body.d.ts +3 -0
  11. package/dist/core/markdown-body.d.ts.map +1 -0
  12. package/dist/core/markdown-body.js +65 -0
  13. package/dist/core/markdown-body.js.map +1 -0
  14. package/dist/core/markdown-renderer.d.ts +5 -0
  15. package/dist/core/markdown-renderer.d.ts.map +1 -0
  16. package/dist/core/markdown-renderer.js +75 -0
  17. package/dist/core/markdown-renderer.js.map +1 -0
  18. package/dist/core/negotiate.d.ts +3 -0
  19. package/dist/core/negotiate.d.ts.map +1 -0
  20. package/dist/core/negotiate.js +63 -0
  21. package/dist/core/negotiate.js.map +1 -0
  22. package/dist/core/parse/anchors.d.ts +2 -0
  23. package/dist/core/parse/anchors.d.ts.map +1 -0
  24. package/dist/core/parse/anchors.js +26 -0
  25. package/dist/core/parse/anchors.js.map +1 -0
  26. package/dist/core/parse/block-parser.d.ts +3 -0
  27. package/dist/core/parse/block-parser.d.ts.map +1 -0
  28. package/dist/core/parse/block-parser.js +116 -0
  29. package/dist/core/parse/block-parser.js.map +1 -0
  30. package/dist/core/parse/executable-block.d.ts +6 -0
  31. package/dist/core/parse/executable-block.d.ts.map +1 -0
  32. package/dist/core/parse/executable-block.js +48 -0
  33. package/dist/core/parse/executable-block.js.map +1 -0
  34. package/dist/core/parse/frontmatter.d.ts +7 -0
  35. package/dist/core/parse/frontmatter.d.ts.map +1 -0
  36. package/dist/core/parse/frontmatter.js +45 -0
  37. package/dist/core/parse/frontmatter.js.map +1 -0
  38. package/dist/core/serialize.d.ts +4 -0
  39. package/dist/core/serialize.d.ts.map +1 -0
  40. package/dist/core/serialize.js +123 -0
  41. package/dist/core/serialize.js.map +1 -0
  42. package/dist/core/types.d.ts +66 -0
  43. package/dist/core/types.d.ts.map +1 -0
  44. package/dist/core/types.js +2 -0
  45. package/dist/core/types.js.map +1 -0
  46. package/dist/core/validate.d.ts +3 -0
  47. package/dist/core/validate.d.ts.map +1 -0
  48. package/dist/core/validate.js +91 -0
  49. package/dist/core/validate.js.map +1 -0
  50. package/dist/elements/components/mdsn-action.d.ts +6 -0
  51. package/dist/elements/components/mdsn-action.d.ts.map +1 -0
  52. package/dist/elements/components/mdsn-action.js +34 -0
  53. package/dist/elements/components/mdsn-action.js.map +1 -0
  54. package/dist/elements/components/mdsn-block.d.ts +9 -0
  55. package/dist/elements/components/mdsn-block.d.ts.map +1 -0
  56. package/dist/elements/components/mdsn-block.js +36 -0
  57. package/dist/elements/components/mdsn-block.js.map +1 -0
  58. package/dist/elements/components/mdsn-error.d.ts +9 -0
  59. package/dist/elements/components/mdsn-error.d.ts.map +1 -0
  60. package/dist/elements/components/mdsn-error.js +36 -0
  61. package/dist/elements/components/mdsn-error.js.map +1 -0
  62. package/dist/elements/components/mdsn-field.d.ts +6 -0
  63. package/dist/elements/components/mdsn-field.d.ts.map +1 -0
  64. package/dist/elements/components/mdsn-field.js +35 -0
  65. package/dist/elements/components/mdsn-field.js.map +1 -0
  66. package/dist/elements/components/mdsn-form.d.ts +6 -0
  67. package/dist/elements/components/mdsn-form.d.ts.map +1 -0
  68. package/dist/elements/components/mdsn-form.js +22 -0
  69. package/dist/elements/components/mdsn-form.js.map +1 -0
  70. package/dist/elements/components/mdsn-page.d.ts +9 -0
  71. package/dist/elements/components/mdsn-page.d.ts.map +1 -0
  72. package/dist/elements/components/mdsn-page.js +46 -0
  73. package/dist/elements/components/mdsn-page.js.map +1 -0
  74. package/dist/elements/index.d.ts +3 -0
  75. package/dist/elements/index.d.ts.map +1 -0
  76. package/dist/elements/index.js +3 -0
  77. package/dist/elements/index.js.map +1 -0
  78. package/dist/elements/mount.d.ts +11 -0
  79. package/dist/elements/mount.d.ts.map +1 -0
  80. package/dist/elements/mount.js +245 -0
  81. package/dist/elements/mount.js.map +1 -0
  82. package/dist/elements/register.d.ts +2 -0
  83. package/dist/elements/register.d.ts.map +1 -0
  84. package/dist/elements/register.js +27 -0
  85. package/dist/elements/register.js.map +1 -0
  86. package/dist/elements/theme.d.ts +2 -0
  87. package/dist/elements/theme.d.ts.map +1 -0
  88. package/dist/elements/theme.js +13 -0
  89. package/dist/elements/theme.js.map +1 -0
  90. package/dist/index.d.ts +4 -8
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +5 -35
  93. package/dist/index.js.map +1 -0
  94. package/dist/server/hosted-app.d.ts +35 -0
  95. package/dist/server/hosted-app.d.ts.map +1 -0
  96. package/dist/server/hosted-app.js +105 -0
  97. package/dist/server/hosted-app.js.map +1 -0
  98. package/dist/server/html-render.d.ts +13 -0
  99. package/dist/server/html-render.d.ts.map +1 -0
  100. package/dist/server/html-render.js +316 -0
  101. package/dist/server/html-render.js.map +1 -0
  102. package/dist/server/index.d.ts +8 -15
  103. package/dist/server/index.d.ts.map +1 -0
  104. package/dist/server/index.js +6 -32
  105. package/dist/server/index.js.map +1 -0
  106. package/dist/server/node.d.ts +23 -0
  107. package/dist/server/node.d.ts.map +1 -0
  108. package/dist/server/node.js +200 -0
  109. package/dist/server/node.js.map +1 -0
  110. package/dist/server/result.d.ts +15 -0
  111. package/dist/server/result.d.ts.map +1 -0
  112. package/dist/server/result.js +64 -0
  113. package/dist/server/result.js.map +1 -0
  114. package/dist/server/router.d.ts +12 -0
  115. package/dist/server/router.d.ts.map +1 -0
  116. package/dist/server/router.js +24 -0
  117. package/dist/server/router.js.map +1 -0
  118. package/dist/server/runtime.d.ts +15 -0
  119. package/dist/server/runtime.d.ts.map +1 -0
  120. package/dist/server/runtime.js +245 -0
  121. package/dist/server/runtime.js.map +1 -0
  122. package/dist/server/session.d.ts +5 -40
  123. package/dist/server/session.d.ts.map +1 -0
  124. package/dist/server/session.js +11 -213
  125. package/dist/server/session.js.map +1 -0
  126. package/dist/server/types.d.ts +62 -0
  127. package/dist/server/types.d.ts.map +1 -0
  128. package/dist/server/types.js +2 -0
  129. package/dist/server/types.js.map +1 -0
  130. package/dist/web/headless.d.ts +22 -92
  131. package/dist/web/headless.d.ts.map +1 -0
  132. package/dist/web/headless.js +311 -337
  133. package/dist/web/headless.js.map +1 -0
  134. package/dist/web/index.d.ts +2 -11
  135. package/dist/web/index.d.ts.map +1 -0
  136. package/dist/web/index.js +2 -23
  137. package/dist/web/index.js.map +1 -0
  138. package/package.json +19 -43
  139. package/LICENSE +0 -21
  140. package/dist/cli/args.d.ts +0 -8
  141. package/dist/cli/args.js +0 -63
  142. package/dist/cli/commands/build.d.ts +0 -5
  143. package/dist/cli/commands/build.js +0 -19
  144. package/dist/cli/commands/create.d.ts +0 -2
  145. package/dist/cli/commands/create.js +0 -39
  146. package/dist/cli/commands/dev.d.ts +0 -10
  147. package/dist/cli/commands/dev.js +0 -13
  148. package/dist/cli/commands/start.d.ts +0 -9
  149. package/dist/cli/commands/start.js +0 -13
  150. package/dist/cli/entry.d.ts +0 -2
  151. package/dist/cli/entry.js +0 -8
  152. package/dist/cli/index.d.ts +0 -9
  153. package/dist/cli/index.js +0 -58
  154. package/dist/core/document/frontmatter.d.ts +0 -5
  155. package/dist/core/document/frontmatter.js +0 -41
  156. package/dist/core/document/markdown.d.ts +0 -5
  157. package/dist/core/document/markdown.js +0 -81
  158. package/dist/core/document/page-definition.d.ts +0 -2
  159. package/dist/core/document/page-definition.js +0 -23
  160. package/dist/core/model/block.d.ts +0 -26
  161. package/dist/core/model/block.js +0 -8
  162. package/dist/core/model/document.d.ts +0 -11
  163. package/dist/core/model/document.js +0 -2
  164. package/dist/core/model/fragment.d.ts +0 -4
  165. package/dist/core/model/fragment.js +0 -2
  166. package/dist/core/model/index.d.ts +0 -4
  167. package/dist/core/model/index.js +0 -2
  168. package/dist/core/model/input.d.ts +0 -10
  169. package/dist/core/model/input.js +0 -2
  170. package/dist/core/protocol/mdsn.d.ts +0 -4
  171. package/dist/core/protocol/mdsn.js +0 -66
  172. package/dist/core/protocol/statements.d.ts +0 -7
  173. package/dist/core/protocol/statements.js +0 -115
  174. package/dist/core/protocol/validation.d.ts +0 -3
  175. package/dist/core/protocol/validation.js +0 -70
  176. package/dist/core/utils/html.d.ts +0 -6
  177. package/dist/core/utils/html.js +0 -28
  178. package/dist/core/utils/index.d.ts +0 -2
  179. package/dist/core/utils/index.js +0 -12
  180. package/dist/core/utils/logger.d.ts +0 -12
  181. package/dist/core/utils/logger.js +0 -45
  182. package/dist/framework/create-framework-app.d.ts +0 -13
  183. package/dist/framework/create-framework-app.js +0 -12
  184. package/dist/framework/hosted-app.d.ts +0 -34
  185. package/dist/framework/hosted-app.js +0 -223
  186. package/dist/framework/index.d.ts +0 -6
  187. package/dist/framework/index.js +0 -9
  188. package/dist/framework/site-app.d.ts +0 -13
  189. package/dist/framework/site-app.js +0 -147
  190. package/dist/server/action-context.d.ts +0 -11
  191. package/dist/server/action-context.js +0 -26
  192. package/dist/server/action-host.d.ts +0 -2
  193. package/dist/server/action-host.js +0 -10
  194. package/dist/server/action-inputs.d.ts +0 -3
  195. package/dist/server/action-inputs.js +0 -178
  196. package/dist/server/action-runtime.d.ts +0 -8
  197. package/dist/server/action-runtime.js +0 -62
  198. package/dist/server/action.d.ts +0 -33
  199. package/dist/server/action.js +0 -101
  200. package/dist/server/build.d.ts +0 -10
  201. package/dist/server/build.js +0 -170
  202. package/dist/server/config.d.ts +0 -56
  203. package/dist/server/config.js +0 -42
  204. package/dist/server/dev.d.ts +0 -48
  205. package/dist/server/dev.js +0 -90
  206. package/dist/server/error-fragments.d.ts +0 -46
  207. package/dist/server/error-fragments.js +0 -77
  208. package/dist/server/init.d.ts +0 -1
  209. package/dist/server/init.js +0 -176
  210. package/dist/server/layout.d.ts +0 -17
  211. package/dist/server/layout.js +0 -40
  212. package/dist/server/markdown.d.ts +0 -49
  213. package/dist/server/markdown.js +0 -77
  214. package/dist/server/module-loader.d.ts +0 -4
  215. package/dist/server/module-loader.js +0 -71
  216. package/dist/server/negotiate.d.ts +0 -3
  217. package/dist/server/negotiate.js +0 -61
  218. package/dist/server/page-host.d.ts +0 -21
  219. package/dist/server/page-host.js +0 -66
  220. package/dist/server/page-links.d.ts +0 -10
  221. package/dist/server/page-links.js +0 -80
  222. package/dist/server/route-matcher.d.ts +0 -6
  223. package/dist/server/route-matcher.js +0 -73
  224. package/dist/server/routes.d.ts +0 -6
  225. package/dist/server/routes.js +0 -73
  226. package/dist/server/server.d.ts +0 -28
  227. package/dist/server/server.js +0 -161
  228. package/dist/server/site.d.ts +0 -11
  229. package/dist/server/site.js +0 -59
  230. package/dist/server/targets.d.ts +0 -7
  231. package/dist/server/targets.js +0 -21
  232. package/dist/web/block-runtime.d.ts +0 -2
  233. package/dist/web/block-runtime.js +0 -25
  234. package/dist/web/fragment-render.d.ts +0 -8
  235. package/dist/web/fragment-render.js +0 -58
  236. package/dist/web/i18n.d.ts +0 -29
  237. package/dist/web/i18n.js +0 -65
  238. package/dist/web/navigation.d.ts +0 -3
  239. package/dist/web/navigation.js +0 -32
  240. package/dist/web/page-bootstrap.d.ts +0 -6
  241. package/dist/web/page-bootstrap.js +0 -28
  242. package/dist/web/page-client-runtime.d.ts +0 -4
  243. package/dist/web/page-client-runtime.js +0 -7
  244. package/dist/web/page-client-script.d.ts +0 -1
  245. package/dist/web/page-client-script.js +0 -579
  246. package/dist/web/page-html.d.ts +0 -8
  247. package/dist/web/page-html.js +0 -42
  248. package/dist/web/page-render.d.ts +0 -20
  249. package/dist/web/page-render.js +0 -84
  250. package/dist/web/public-client-runtime.d.ts +0 -1
  251. package/dist/web/public-client-runtime.js +0 -5
  252. package/dist/web/public-render.d.ts +0 -12
  253. package/dist/web/public-render.js +0 -18
  254. package/dist/web/target-path.d.ts +0 -1
  255. package/dist/web/target-path.js +0 -35
@@ -1,370 +1,344 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.parseMarkdown = parseMarkdown;
7
- exports.parsePage = parsePage;
8
- exports.createParsedPage = createParsedPage;
9
- exports.parseFragment = parseFragment;
10
- const markdown_it_1 = __importDefault(require("markdown-it"));
11
- const core_1 = require("../core");
12
- const frontmatter_1 = require("../core/document/frontmatter");
13
- const mdsn_1 = require("../core/protocol/mdsn");
14
- function createMarkdownParser() {
15
- return new markdown_it_1.default({
16
- html: true,
17
- linkify: true,
18
- typographer: false,
19
- });
20
- }
21
- function parseInlineNodes(tokens, startIndex = 0, stopType) {
22
- const nodes = [];
23
- let index = startIndex;
24
- while (index < tokens.length) {
25
- const token = tokens[index];
26
- if (stopType && token.type === stopType) {
27
- return [nodes, index];
1
+ import { parsePage, serializeMarkdownBody } from "../core/index.js";
2
+ function findBootstrapScript(root) {
3
+ if (root instanceof Document) {
4
+ const element = root.getElementById("mdsn-bootstrap");
5
+ return element instanceof HTMLScriptElement ? element : null;
6
+ }
7
+ for (const child of Array.from(root.childNodes)) {
8
+ if (child instanceof HTMLScriptElement && child.id === "mdsn-bootstrap") {
9
+ return child;
28
10
  }
29
- switch (token.type) {
30
- case "text":
31
- nodes.push({ type: "text", value: token.content });
32
- index += 1;
33
- continue;
34
- case "strong_open": {
35
- const [children, nextIndex] = parseInlineNodes(tokens, index + 1, "strong_close");
36
- nodes.push({ type: "strong", children });
37
- index = nextIndex + 1;
38
- continue;
39
- }
40
- case "em_open": {
41
- const [children, nextIndex] = parseInlineNodes(tokens, index + 1, "em_close");
42
- nodes.push({ type: "em", children });
43
- index = nextIndex + 1;
44
- continue;
45
- }
46
- case "code_inline":
47
- nodes.push({ type: "inline_code", value: token.content });
48
- index += 1;
49
- continue;
50
- case "link_open": {
51
- const [children, nextIndex] = parseInlineNodes(tokens, index + 1, "link_close");
52
- nodes.push({
53
- type: "link",
54
- href: token.attrGet("href") ?? "",
55
- title: token.attrGet("title") ?? undefined,
56
- children,
57
- });
58
- index = nextIndex + 1;
59
- continue;
11
+ if (child instanceof Element) {
12
+ const nested = findBootstrapScript(child);
13
+ if (nested) {
14
+ return nested;
60
15
  }
61
- case "image":
62
- nodes.push({
63
- type: "image",
64
- src: token.attrGet("src") ?? "",
65
- alt: token.content,
66
- title: token.attrGet("title") ?? undefined,
67
- });
68
- index += 1;
69
- continue;
70
- case "softbreak":
71
- nodes.push({ type: "softbreak" });
72
- index += 1;
73
- continue;
74
- case "hardbreak":
75
- nodes.push({ type: "hardbreak" });
76
- index += 1;
77
- continue;
78
- case "html_inline":
79
- nodes.push({ type: "html_inline", value: token.content });
80
- index += 1;
81
- continue;
82
- default:
83
- index += 1;
84
- continue;
85
16
  }
86
17
  }
87
- return [nodes, index];
18
+ return null;
88
19
  }
89
- function parseTable(tokens, startIndex) {
90
- const header = [];
91
- const rows = [];
92
- let index = startIndex + 1;
93
- let currentRow = null;
94
- while (index < tokens.length) {
95
- const token = tokens[index];
96
- if (token.type === "table_close") {
97
- return [{ type: "table", header, rows }, index + 1];
98
- }
99
- if (token.type === "tr_open") {
100
- currentRow = [];
101
- index += 1;
102
- continue;
20
+ function getDocument(root) {
21
+ if (root instanceof Document) {
22
+ return root;
23
+ }
24
+ return root.ownerDocument ?? document;
25
+ }
26
+ function parseBootstrap(root) {
27
+ const element = findBootstrapScript(root);
28
+ if (!(element instanceof HTMLScriptElement) || !element.textContent?.trim()) {
29
+ throw new Error("Missing mdsn bootstrap data.");
30
+ }
31
+ return JSON.parse(element.textContent);
32
+ }
33
+ function parseBootstrapFromHtml(content) {
34
+ const document = new DOMParser().parseFromString(content, "text/html");
35
+ return parseBootstrap(document);
36
+ }
37
+ function toHeadlessBlock(block, markdown) {
38
+ return {
39
+ name: block.name,
40
+ markdown,
41
+ inputs: block.inputs,
42
+ operations: block.operations
43
+ };
44
+ }
45
+ function findOperationBlock(blocks, operation) {
46
+ return (blocks.find((block) => block.operations.some((candidate) => candidate.method === operation.method &&
47
+ candidate.target === operation.target &&
48
+ candidate.name === operation.name)) ?? null);
49
+ }
50
+ function fragmentBlockFromMarkdown(markdown, fallbackBlock) {
51
+ const page = parsePage(markdown);
52
+ const trimmedMarkdown = page.markdown.trim();
53
+ const block = page.blocks[0];
54
+ if (block) {
55
+ return toHeadlessBlock(block, trimmedMarkdown);
56
+ }
57
+ if (!fallbackBlock) {
58
+ return null;
59
+ }
60
+ return {
61
+ ...fallbackBlock,
62
+ markdown: trimmedMarkdown
63
+ };
64
+ }
65
+ function parseSseMessages(content) {
66
+ return content
67
+ .split(/\n\n+/)
68
+ .map((chunk) => chunk
69
+ .split("\n")
70
+ .map((line) => line.trim())
71
+ .filter((line) => line.startsWith("data:"))
72
+ .map((line) => line.slice(5).trimStart())
73
+ .join("\n"))
74
+ .filter(Boolean);
75
+ }
76
+ function parseSseEvent(rawEvent) {
77
+ const message = rawEvent
78
+ .split("\n")
79
+ .map((line) => line.trim())
80
+ .filter((line) => line.startsWith("data:"))
81
+ .map((line) => line.slice(5).trimStart())
82
+ .join("\n");
83
+ return message || null;
84
+ }
85
+ function drainSseBuffer(buffer, onMessage) {
86
+ const normalized = buffer.replaceAll("\r\n", "\n");
87
+ let cursor = normalized;
88
+ while (true) {
89
+ const separatorIndex = cursor.indexOf("\n\n");
90
+ if (separatorIndex === -1) {
91
+ break;
103
92
  }
104
- if (token.type === "tr_close") {
105
- if (currentRow) {
106
- if (header.length === 0) {
107
- header.push(...currentRow);
108
- }
109
- else {
110
- rows.push(currentRow);
111
- }
112
- }
113
- currentRow = null;
114
- index += 1;
115
- continue;
93
+ const rawEvent = cursor.slice(0, separatorIndex);
94
+ cursor = cursor.slice(separatorIndex + 2);
95
+ const message = parseSseEvent(rawEvent);
96
+ if (message) {
97
+ onMessage(message);
116
98
  }
117
- if (token.type === "th_open" || token.type === "td_open") {
118
- const inlineToken = tokens[index + 1];
119
- const children = inlineToken?.type === "inline"
120
- ? parseInlineNodes(inlineToken.children ?? [])[0]
121
- : [];
122
- currentRow?.push(children);
123
- index += 3;
124
- continue;
99
+ }
100
+ return cursor;
101
+ }
102
+ function replaceBlock(blocks, nextBlock) {
103
+ let replaced = false;
104
+ const next = blocks.map((block) => {
105
+ if (block.name !== nextBlock.name) {
106
+ return block;
125
107
  }
126
- index += 1;
108
+ replaced = true;
109
+ return nextBlock;
110
+ });
111
+ if (!replaced) {
112
+ next.push(nextBlock);
127
113
  }
128
- throw new Error("Unterminated markdown table");
114
+ return next;
129
115
  }
130
- function parseBlockNodes(tokens, startIndex = 0, stopType) {
131
- const nodes = [];
132
- let index = startIndex;
133
- while (index < tokens.length) {
134
- const token = tokens[index];
135
- if (stopType && token.type === stopType) {
136
- return [nodes, index];
116
+ function toSnapshot(bootstrap, current) {
117
+ if (bootstrap.kind === "page") {
118
+ const next = {
119
+ status: current?.status ?? "idle",
120
+ markdown: bootstrap.markdown,
121
+ blocks: [...bootstrap.blocks]
122
+ };
123
+ const route = bootstrap.route ?? current?.route;
124
+ if (route) {
125
+ next.route = route;
137
126
  }
138
- switch (token.type) {
139
- case "heading_open": {
140
- const inlineToken = tokens[index + 1];
141
- const children = inlineToken?.type === "inline"
142
- ? parseInlineNodes(inlineToken.children ?? [])[0]
143
- : [];
144
- nodes.push({
145
- type: "heading",
146
- depth: Number(token.tag.slice(1)),
147
- children,
148
- });
149
- index += 3;
150
- continue;
151
- }
152
- case "paragraph_open": {
153
- const inlineToken = tokens[index + 1];
154
- const children = inlineToken?.type === "inline"
155
- ? parseInlineNodes(inlineToken.children ?? [])[0]
156
- : [];
157
- nodes.push({ type: "paragraph", children });
158
- index += 3;
159
- continue;
160
- }
161
- case "bullet_list_open":
162
- case "ordered_list_open": {
163
- const ordered = token.type === "ordered_list_open";
164
- const closeType = ordered ? "ordered_list_close" : "bullet_list_close";
165
- const items = [];
166
- const startValue = token.attrGet("start");
167
- index += 1;
168
- while (index < tokens.length && tokens[index]?.type !== closeType) {
169
- if (tokens[index]?.type !== "list_item_open") {
170
- index += 1;
171
- continue;
172
- }
173
- const [itemNodes, nextIndex] = parseBlockNodes(tokens, index + 1, "list_item_close");
174
- items.push(itemNodes);
175
- index = nextIndex + 1;
176
- }
177
- nodes.push({
178
- type: "list",
179
- ordered,
180
- start: ordered && startValue ? Number(startValue) : undefined,
181
- items,
182
- });
183
- index += 1;
184
- continue;
185
- }
186
- case "blockquote_open": {
187
- const [children, nextIndex] = parseBlockNodes(tokens, index + 1, "blockquote_close");
188
- nodes.push({ type: "blockquote", children });
189
- index = nextIndex + 1;
190
- continue;
191
- }
192
- case "fence":
193
- case "code_block":
194
- nodes.push({
195
- type: "code",
196
- language: token.info?.trim() || undefined,
197
- value: token.content,
198
- });
199
- index += 1;
200
- continue;
201
- case "html_block":
202
- nodes.push({ type: "html", value: token.content });
203
- index += 1;
204
- continue;
205
- case "hr":
206
- nodes.push({ type: "thematic_break" });
207
- index += 1;
208
- continue;
209
- case "table_open": {
210
- const [tableNode, nextIndex] = parseTable(tokens, index);
211
- nodes.push(tableNode);
212
- index = nextIndex;
213
- continue;
214
- }
215
- default:
216
- index += 1;
217
- continue;
127
+ if (current?.error) {
128
+ next.error = current.error;
218
129
  }
130
+ return next;
219
131
  }
220
- return [nodes, index];
221
- }
222
- function parseMarkdownContainer(markdown, id) {
223
- return {
224
- id,
225
- markdown,
226
- nodes: parseMarkdown(markdown),
132
+ const next = {
133
+ status: current?.status ?? "idle",
134
+ markdown: current?.markdown ?? "",
135
+ blocks: replaceBlock(current?.blocks ?? [], bootstrap.block)
227
136
  };
137
+ if (current?.route) {
138
+ next.route = current.route;
139
+ }
140
+ if (current?.error) {
141
+ next.error = current.error;
142
+ }
143
+ return next;
228
144
  }
229
- function splitMarkdownByAnchors(markdown) {
230
- const containers = [];
231
- const anchors = [];
232
- const segments = [];
233
- const lines = markdown.split(/\r?\n/);
234
- let activeFence = false;
235
- let currentLines = [];
236
- const pushContainer = () => {
237
- const containerMarkdown = currentLines.join("\n").trim();
238
- currentLines = [];
239
- if (!containerMarkdown) {
240
- return;
145
+ function toQueryString(values) {
146
+ const params = new URLSearchParams();
147
+ for (const [key, value] of Object.entries(values)) {
148
+ params.set(key, value);
149
+ }
150
+ const query = params.toString();
151
+ return query ? `?${query}` : "";
152
+ }
153
+ function pushHistory(target) {
154
+ if (typeof window === "undefined") {
155
+ return;
156
+ }
157
+ window.history.pushState({}, "", target);
158
+ }
159
+ export function createHeadlessHost(options) {
160
+ const fetchImpl = options.fetchImpl ?? fetch;
161
+ let mounted = false;
162
+ let snapshot = toSnapshot(parseBootstrap(options.root), null);
163
+ let status = { status: "idle" };
164
+ const listeners = new Set();
165
+ function publish() {
166
+ const next = {
167
+ status: status.status,
168
+ markdown: snapshot.markdown,
169
+ blocks: [...snapshot.blocks]
170
+ };
171
+ if (status.error) {
172
+ next.error = status.error;
241
173
  }
242
- const container = parseMarkdownContainer(containerMarkdown, `container-${containers.length}`);
243
- containers.push(container);
244
- segments.push({ type: "container", container });
245
- };
246
- for (const line of lines) {
247
- const trimmed = line.trim();
248
- if (trimmed.startsWith("```") || trimmed.startsWith("~~~")) {
249
- activeFence = !activeFence;
250
- currentLines.push(line);
251
- continue;
174
+ if (snapshot.route) {
175
+ next.route = snapshot.route;
252
176
  }
253
- if (!activeFence) {
254
- const anchorMatch = trimmed.match(/^<!--\s*mdsn:block\s+([a-zA-Z_][\w-]*)\s*-->$/);
255
- if (anchorMatch) {
256
- pushContainer();
257
- const anchor = { name: anchorMatch[1] };
258
- anchors.push(anchor);
259
- segments.push({ type: "anchor", anchor });
260
- continue;
261
- }
177
+ for (const listener of listeners) {
178
+ listener(next);
262
179
  }
263
- currentLines.push(line);
264
180
  }
265
- pushContainer();
266
- return { containers, anchors, segments };
267
- }
268
- function splitFragmentSource(markdown) {
269
- const segments = [];
270
- const lines = markdown.split(/\r?\n/);
271
- let activeFence = null;
272
- let currentMarkdownLines = [];
273
- let index = 0;
274
- const pushMarkdownSegment = () => {
275
- const segmentMarkdown = currentMarkdownLines.join("\n").trim();
276
- currentMarkdownLines = [];
277
- if (!segmentMarkdown) {
181
+ function setStatus(next) {
182
+ status = next;
183
+ publish();
184
+ }
185
+ async function applyResponse(content) {
186
+ const bootstrap = parseBootstrapFromHtml(content);
187
+ if (bootstrap.kind === "fragment" && bootstrap.continueTarget) {
188
+ await visit(bootstrap.continueTarget, true);
278
189
  return;
279
190
  }
280
- segments.push({ type: "markdown", markdown: segmentMarkdown });
281
- };
282
- while (index < lines.length) {
283
- const line = lines[index] ?? "";
284
- const trimmed = line.trim();
285
- const fenceMatch = trimmed.match(/^(`{3,}|~{3,})(.*)$/);
286
- if (fenceMatch) {
287
- const marker = fenceMatch[1];
288
- const info = fenceMatch[2].trim();
289
- if (activeFence) {
290
- if (trimmed === activeFence) {
291
- activeFence = null;
191
+ snapshot = toSnapshot(bootstrap, snapshot);
192
+ setStatus({ status: "idle" });
193
+ }
194
+ async function request(target, init) {
195
+ setStatus({ status: "loading" });
196
+ try {
197
+ const response = await fetchImpl(target, init);
198
+ const content = await response.text();
199
+ await applyResponse(content);
200
+ }
201
+ catch (error) {
202
+ setStatus({ status: "error", error: error instanceof Error ? error.message : String(error) });
203
+ }
204
+ }
205
+ async function requestStream(target, operation) {
206
+ const fallbackBlock = findOperationBlock(snapshot.blocks, operation);
207
+ setStatus({ status: "loading" });
208
+ try {
209
+ const response = await fetchImpl(target, {
210
+ method: "GET",
211
+ headers: {
212
+ accept: "text/event-stream"
292
213
  }
293
- currentMarkdownLines.push(line);
294
- index += 1;
295
- continue;
296
- }
297
- if (marker === "```" && info === "mdsn") {
298
- pushMarkdownSegment();
299
- index += 1;
300
- const blockLines = [];
301
- while (index < lines.length && lines[index]?.trim() !== "```") {
302
- blockLines.push(lines[index] ?? "");
303
- index += 1;
214
+ });
215
+ const applyMessage = (message) => {
216
+ const nextBlock = fragmentBlockFromMarkdown(message, fallbackBlock);
217
+ if (!nextBlock) {
218
+ return;
304
219
  }
305
- if (index >= lines.length) {
306
- throw new Error("Unterminated mdsn code block");
220
+ snapshot = {
221
+ ...snapshot,
222
+ blocks: replaceBlock(snapshot.blocks, nextBlock)
223
+ };
224
+ publish();
225
+ };
226
+ if (!response.body) {
227
+ const content = await response.text();
228
+ for (const message of parseSseMessages(content)) {
229
+ applyMessage(message);
230
+ }
231
+ setStatus({ status: "idle" });
232
+ return;
233
+ }
234
+ const reader = response.body.getReader();
235
+ const decoder = new TextDecoder();
236
+ let buffer = "";
237
+ while (true) {
238
+ const { value, done } = await reader.read();
239
+ if (done) {
240
+ break;
307
241
  }
308
- segments.push({ type: "mdsn", source: blockLines.join("\n") });
309
- index += 1;
310
- continue;
242
+ buffer += decoder.decode(value, { stream: true });
243
+ buffer = drainSseBuffer(buffer, applyMessage);
311
244
  }
312
- activeFence = marker;
313
- currentMarkdownLines.push(line);
314
- index += 1;
315
- continue;
245
+ buffer += decoder.decode();
246
+ drainSseBuffer(buffer, applyMessage);
247
+ setStatus({ status: "idle" });
248
+ }
249
+ catch (error) {
250
+ setStatus({ status: "error", error: error instanceof Error ? error.message : String(error) });
316
251
  }
317
- currentMarkdownLines.push(line);
318
- index += 1;
319
- }
320
- pushMarkdownSegment();
321
- return segments;
322
- }
323
- function parseMarkdown(source) {
324
- const parser = createMarkdownParser();
325
- const tokens = parser.parse(source, {});
326
- return parseBlockNodes(tokens)[0];
327
- }
328
- function parsePage(source) {
329
- const document = (0, core_1.parsePageDefinition)(source);
330
- return createParsedPage(document);
331
- }
332
- function createParsedPage(document) {
333
- const structure = splitMarkdownByAnchors(document.markdown);
334
- return {
335
- frontmatter: document.frontmatter,
336
- containers: structure.containers,
337
- anchors: structure.anchors,
338
- blocks: document.blocks,
339
- segments: structure.segments,
340
- };
341
- }
342
- function parseFragment(source) {
343
- const { body } = (0, frontmatter_1.parseFrontmatter)(source);
344
- const sourceSegments = splitFragmentSource(body);
345
- const mdsnSegments = sourceSegments.filter((segment) => segment.type === "mdsn");
346
- if (mdsnSegments.length > 1) {
347
- throw new Error("A block fragment may contain at most one mdsn code block");
348
252
  }
349
- const parsedBlock = mdsnSegments.length > 0
350
- ? (0, mdsn_1.parseMdsnBlocks)([mdsnSegments[0].source]).blocks[0]
351
- : undefined;
352
- const containers = [];
353
- const segments = [];
354
- for (const segment of sourceSegments) {
355
- if (segment.type === "markdown") {
356
- const container = parseMarkdownContainer(segment.markdown, `container-${containers.length}`);
357
- containers.push(container);
358
- segments.push({ type: "container", container });
359
- continue;
253
+ async function visit(target, updateHistory = false) {
254
+ setStatus({ status: "loading" });
255
+ try {
256
+ const response = await fetchImpl(target, {
257
+ method: "GET",
258
+ headers: {
259
+ accept: "text/html"
260
+ }
261
+ });
262
+ const content = await response.text();
263
+ snapshot = toSnapshot(parseBootstrapFromHtml(content), snapshot);
264
+ if (updateHistory) {
265
+ pushHistory(target);
266
+ }
267
+ setStatus({ status: "idle" });
360
268
  }
361
- if (parsedBlock) {
362
- segments.push({ type: "block", block: parsedBlock });
269
+ catch (error) {
270
+ setStatus({ status: "error", error: error instanceof Error ? error.message : String(error) });
363
271
  }
364
272
  }
273
+ function onPopState() {
274
+ const target = `${window.location.pathname}${window.location.search}`;
275
+ void visit(target, false);
276
+ }
365
277
  return {
366
- containers,
367
- block: parsedBlock,
368
- segments,
278
+ mount() {
279
+ if (mounted || typeof window === "undefined") {
280
+ mounted = true;
281
+ return;
282
+ }
283
+ window.addEventListener("popstate", onPopState);
284
+ mounted = true;
285
+ },
286
+ unmount() {
287
+ if (!mounted || typeof window === "undefined") {
288
+ mounted = false;
289
+ return;
290
+ }
291
+ window.removeEventListener("popstate", onPopState);
292
+ mounted = false;
293
+ },
294
+ subscribe(listener) {
295
+ listeners.add(listener);
296
+ listener(this.getSnapshot());
297
+ return () => {
298
+ listeners.delete(listener);
299
+ };
300
+ },
301
+ getSnapshot() {
302
+ const next = {
303
+ status: status.status,
304
+ markdown: snapshot.markdown,
305
+ blocks: [...snapshot.blocks]
306
+ };
307
+ if (status.error) {
308
+ next.error = status.error;
309
+ }
310
+ if (snapshot.route) {
311
+ next.route = snapshot.route;
312
+ }
313
+ return next;
314
+ },
315
+ async submit(operation, values = {}) {
316
+ if (operation.method === "GET") {
317
+ const target = `${operation.target}${toQueryString(values)}`;
318
+ if (operation.accept === "text/event-stream") {
319
+ void requestStream(target, operation);
320
+ return;
321
+ }
322
+ await request(target, {
323
+ method: "GET",
324
+ headers: {
325
+ accept: "text/html"
326
+ }
327
+ });
328
+ return;
329
+ }
330
+ await request(operation.target, {
331
+ method: "POST",
332
+ headers: {
333
+ accept: "text/html",
334
+ "content-type": "text/markdown"
335
+ },
336
+ body: serializeMarkdownBody(values)
337
+ });
338
+ },
339
+ visit(target) {
340
+ return visit(target, true);
341
+ }
369
342
  };
370
343
  }
344
+ //# sourceMappingURL=headless.js.map