@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.
- package/README.md +39 -75
- package/dist/core/errors.d.ts +14 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +13 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +16 -4
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +69 -13
- package/dist/core/index.js.map +1 -0
- package/dist/core/markdown-body.d.ts +3 -0
- package/dist/core/markdown-body.d.ts.map +1 -0
- package/dist/core/markdown-body.js +65 -0
- package/dist/core/markdown-body.js.map +1 -0
- package/dist/core/markdown-renderer.d.ts +5 -0
- package/dist/core/markdown-renderer.d.ts.map +1 -0
- package/dist/core/markdown-renderer.js +75 -0
- package/dist/core/markdown-renderer.js.map +1 -0
- package/dist/core/negotiate.d.ts +3 -0
- package/dist/core/negotiate.d.ts.map +1 -0
- package/dist/core/negotiate.js +63 -0
- package/dist/core/negotiate.js.map +1 -0
- package/dist/core/parse/anchors.d.ts +2 -0
- package/dist/core/parse/anchors.d.ts.map +1 -0
- package/dist/core/parse/anchors.js +26 -0
- package/dist/core/parse/anchors.js.map +1 -0
- package/dist/core/parse/block-parser.d.ts +3 -0
- package/dist/core/parse/block-parser.d.ts.map +1 -0
- package/dist/core/parse/block-parser.js +116 -0
- package/dist/core/parse/block-parser.js.map +1 -0
- package/dist/core/parse/executable-block.d.ts +6 -0
- package/dist/core/parse/executable-block.d.ts.map +1 -0
- package/dist/core/parse/executable-block.js +48 -0
- package/dist/core/parse/executable-block.js.map +1 -0
- package/dist/core/parse/frontmatter.d.ts +7 -0
- package/dist/core/parse/frontmatter.d.ts.map +1 -0
- package/dist/core/parse/frontmatter.js +45 -0
- package/dist/core/parse/frontmatter.js.map +1 -0
- package/dist/core/serialize.d.ts +4 -0
- package/dist/core/serialize.d.ts.map +1 -0
- package/dist/core/serialize.js +123 -0
- package/dist/core/serialize.js.map +1 -0
- package/dist/core/types.d.ts +66 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/validate.d.ts +3 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +91 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/elements/components/mdsn-action.d.ts +6 -0
- package/dist/elements/components/mdsn-action.d.ts.map +1 -0
- package/dist/elements/components/mdsn-action.js +34 -0
- package/dist/elements/components/mdsn-action.js.map +1 -0
- package/dist/elements/components/mdsn-block.d.ts +9 -0
- package/dist/elements/components/mdsn-block.d.ts.map +1 -0
- package/dist/elements/components/mdsn-block.js +36 -0
- package/dist/elements/components/mdsn-block.js.map +1 -0
- package/dist/elements/components/mdsn-error.d.ts +9 -0
- package/dist/elements/components/mdsn-error.d.ts.map +1 -0
- package/dist/elements/components/mdsn-error.js +36 -0
- package/dist/elements/components/mdsn-error.js.map +1 -0
- package/dist/elements/components/mdsn-field.d.ts +6 -0
- package/dist/elements/components/mdsn-field.d.ts.map +1 -0
- package/dist/elements/components/mdsn-field.js +35 -0
- package/dist/elements/components/mdsn-field.js.map +1 -0
- package/dist/elements/components/mdsn-form.d.ts +6 -0
- package/dist/elements/components/mdsn-form.d.ts.map +1 -0
- package/dist/elements/components/mdsn-form.js +22 -0
- package/dist/elements/components/mdsn-form.js.map +1 -0
- package/dist/elements/components/mdsn-page.d.ts +9 -0
- package/dist/elements/components/mdsn-page.d.ts.map +1 -0
- package/dist/elements/components/mdsn-page.js +46 -0
- package/dist/elements/components/mdsn-page.js.map +1 -0
- package/dist/elements/index.d.ts +3 -0
- package/dist/elements/index.d.ts.map +1 -0
- package/dist/elements/index.js +3 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/elements/mount.d.ts +11 -0
- package/dist/elements/mount.d.ts.map +1 -0
- package/dist/elements/mount.js +245 -0
- package/dist/elements/mount.js.map +1 -0
- package/dist/elements/register.d.ts +2 -0
- package/dist/elements/register.d.ts.map +1 -0
- package/dist/elements/register.js +27 -0
- package/dist/elements/register.js.map +1 -0
- package/dist/elements/theme.d.ts +2 -0
- package/dist/elements/theme.d.ts.map +1 -0
- package/dist/elements/theme.js +13 -0
- package/dist/elements/theme.js.map +1 -0
- package/dist/index.d.ts +4 -8
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -35
- package/dist/index.js.map +1 -0
- package/dist/server/hosted-app.d.ts +35 -0
- package/dist/server/hosted-app.d.ts.map +1 -0
- package/dist/server/hosted-app.js +105 -0
- package/dist/server/hosted-app.js.map +1 -0
- package/dist/server/html-render.d.ts +13 -0
- package/dist/server/html-render.d.ts.map +1 -0
- package/dist/server/html-render.js +316 -0
- package/dist/server/html-render.js.map +1 -0
- package/dist/server/index.d.ts +8 -15
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +6 -32
- package/dist/server/index.js.map +1 -0
- package/dist/server/node.d.ts +23 -0
- package/dist/server/node.d.ts.map +1 -0
- package/dist/server/node.js +200 -0
- package/dist/server/node.js.map +1 -0
- package/dist/server/result.d.ts +15 -0
- package/dist/server/result.d.ts.map +1 -0
- package/dist/server/result.js +64 -0
- package/dist/server/result.js.map +1 -0
- package/dist/server/router.d.ts +12 -0
- package/dist/server/router.d.ts.map +1 -0
- package/dist/server/router.js +24 -0
- package/dist/server/router.js.map +1 -0
- package/dist/server/runtime.d.ts +15 -0
- package/dist/server/runtime.d.ts.map +1 -0
- package/dist/server/runtime.js +245 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/session.d.ts +5 -40
- package/dist/server/session.d.ts.map +1 -0
- package/dist/server/session.js +11 -213
- package/dist/server/session.js.map +1 -0
- package/dist/server/types.d.ts +62 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/web/headless.d.ts +22 -92
- package/dist/web/headless.d.ts.map +1 -0
- package/dist/web/headless.js +311 -337
- package/dist/web/headless.js.map +1 -0
- package/dist/web/index.d.ts +2 -11
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +2 -23
- package/dist/web/index.js.map +1 -0
- package/package.json +19 -43
- package/LICENSE +0 -21
- package/dist/cli/args.d.ts +0 -8
- package/dist/cli/args.js +0 -63
- package/dist/cli/commands/build.d.ts +0 -5
- package/dist/cli/commands/build.js +0 -19
- package/dist/cli/commands/create.d.ts +0 -2
- package/dist/cli/commands/create.js +0 -39
- package/dist/cli/commands/dev.d.ts +0 -10
- package/dist/cli/commands/dev.js +0 -13
- package/dist/cli/commands/start.d.ts +0 -9
- package/dist/cli/commands/start.js +0 -13
- package/dist/cli/entry.d.ts +0 -2
- package/dist/cli/entry.js +0 -8
- package/dist/cli/index.d.ts +0 -9
- package/dist/cli/index.js +0 -58
- package/dist/core/document/frontmatter.d.ts +0 -5
- package/dist/core/document/frontmatter.js +0 -41
- package/dist/core/document/markdown.d.ts +0 -5
- package/dist/core/document/markdown.js +0 -81
- package/dist/core/document/page-definition.d.ts +0 -2
- package/dist/core/document/page-definition.js +0 -23
- package/dist/core/model/block.d.ts +0 -26
- package/dist/core/model/block.js +0 -8
- package/dist/core/model/document.d.ts +0 -11
- package/dist/core/model/document.js +0 -2
- package/dist/core/model/fragment.d.ts +0 -4
- package/dist/core/model/fragment.js +0 -2
- package/dist/core/model/index.d.ts +0 -4
- package/dist/core/model/index.js +0 -2
- package/dist/core/model/input.d.ts +0 -10
- package/dist/core/model/input.js +0 -2
- package/dist/core/protocol/mdsn.d.ts +0 -4
- package/dist/core/protocol/mdsn.js +0 -66
- package/dist/core/protocol/statements.d.ts +0 -7
- package/dist/core/protocol/statements.js +0 -115
- package/dist/core/protocol/validation.d.ts +0 -3
- package/dist/core/protocol/validation.js +0 -70
- package/dist/core/utils/html.d.ts +0 -6
- package/dist/core/utils/html.js +0 -28
- package/dist/core/utils/index.d.ts +0 -2
- package/dist/core/utils/index.js +0 -12
- package/dist/core/utils/logger.d.ts +0 -12
- package/dist/core/utils/logger.js +0 -45
- package/dist/framework/create-framework-app.d.ts +0 -13
- package/dist/framework/create-framework-app.js +0 -12
- package/dist/framework/hosted-app.d.ts +0 -34
- package/dist/framework/hosted-app.js +0 -223
- package/dist/framework/index.d.ts +0 -6
- package/dist/framework/index.js +0 -9
- package/dist/framework/site-app.d.ts +0 -13
- package/dist/framework/site-app.js +0 -147
- package/dist/server/action-context.d.ts +0 -11
- package/dist/server/action-context.js +0 -26
- package/dist/server/action-host.d.ts +0 -2
- package/dist/server/action-host.js +0 -10
- package/dist/server/action-inputs.d.ts +0 -3
- package/dist/server/action-inputs.js +0 -178
- package/dist/server/action-runtime.d.ts +0 -8
- package/dist/server/action-runtime.js +0 -62
- package/dist/server/action.d.ts +0 -33
- package/dist/server/action.js +0 -101
- package/dist/server/build.d.ts +0 -10
- package/dist/server/build.js +0 -170
- package/dist/server/config.d.ts +0 -56
- package/dist/server/config.js +0 -42
- package/dist/server/dev.d.ts +0 -48
- package/dist/server/dev.js +0 -90
- package/dist/server/error-fragments.d.ts +0 -46
- package/dist/server/error-fragments.js +0 -77
- package/dist/server/init.d.ts +0 -1
- package/dist/server/init.js +0 -176
- package/dist/server/layout.d.ts +0 -17
- package/dist/server/layout.js +0 -40
- package/dist/server/markdown.d.ts +0 -49
- package/dist/server/markdown.js +0 -77
- package/dist/server/module-loader.d.ts +0 -4
- package/dist/server/module-loader.js +0 -71
- package/dist/server/negotiate.d.ts +0 -3
- package/dist/server/negotiate.js +0 -61
- package/dist/server/page-host.d.ts +0 -21
- package/dist/server/page-host.js +0 -66
- package/dist/server/page-links.d.ts +0 -10
- package/dist/server/page-links.js +0 -80
- package/dist/server/route-matcher.d.ts +0 -6
- package/dist/server/route-matcher.js +0 -73
- package/dist/server/routes.d.ts +0 -6
- package/dist/server/routes.js +0 -73
- package/dist/server/server.d.ts +0 -28
- package/dist/server/server.js +0 -161
- package/dist/server/site.d.ts +0 -11
- package/dist/server/site.js +0 -59
- package/dist/server/targets.d.ts +0 -7
- package/dist/server/targets.js +0 -21
- package/dist/web/block-runtime.d.ts +0 -2
- package/dist/web/block-runtime.js +0 -25
- package/dist/web/fragment-render.d.ts +0 -8
- package/dist/web/fragment-render.js +0 -58
- package/dist/web/i18n.d.ts +0 -29
- package/dist/web/i18n.js +0 -65
- package/dist/web/navigation.d.ts +0 -3
- package/dist/web/navigation.js +0 -32
- package/dist/web/page-bootstrap.d.ts +0 -6
- package/dist/web/page-bootstrap.js +0 -28
- package/dist/web/page-client-runtime.d.ts +0 -4
- package/dist/web/page-client-runtime.js +0 -7
- package/dist/web/page-client-script.d.ts +0 -1
- package/dist/web/page-client-script.js +0 -579
- package/dist/web/page-html.d.ts +0 -8
- package/dist/web/page-html.js +0 -42
- package/dist/web/page-render.d.ts +0 -20
- package/dist/web/page-render.js +0 -84
- package/dist/web/public-client-runtime.d.ts +0 -1
- package/dist/web/public-client-runtime.js +0 -5
- package/dist/web/public-render.d.ts +0 -12
- package/dist/web/public-render.js +0 -18
- package/dist/web/target-path.d.ts +0 -1
- package/dist/web/target-path.js +0 -35
package/dist/web/headless.js
CHANGED
|
@@ -1,370 +1,344 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
18
|
+
return null;
|
|
88
19
|
}
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
108
|
+
replaced = true;
|
|
109
|
+
return nextBlock;
|
|
110
|
+
});
|
|
111
|
+
if (!replaced) {
|
|
112
|
+
next.push(nextBlock);
|
|
127
113
|
}
|
|
128
|
-
|
|
114
|
+
return next;
|
|
129
115
|
}
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
139
|
-
|
|
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
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
243
|
-
|
|
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
|
-
|
|
254
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
|
|
306
|
-
|
|
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
|
-
|
|
309
|
-
|
|
310
|
-
continue;
|
|
242
|
+
buffer += decoder.decode(value, { stream: true });
|
|
243
|
+
buffer = drainSseBuffer(buffer, applyMessage);
|
|
311
244
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
362
|
-
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|