@emkodev/emroute 1.7.3 → 1.8.0-beta.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/README.md +1 -1
- package/core/component/abstract.component.ts +74 -0
- package/{src → core}/component/page.component.ts +3 -61
- package/core/component/widget.component.ts +54 -0
- package/core/pipeline/pipeline.ts +224 -0
- package/{src/renderer/ssr → core/renderer}/html.renderer.ts +26 -47
- package/{src/renderer/ssr → core/renderer}/md.renderer.ts +22 -41
- package/{src/renderer/ssr → core/renderer}/ssr.renderer.ts +44 -58
- package/{src/route → core/router}/route.resolver.ts +1 -10
- package/core/router/route.trie.ts +175 -0
- package/core/runtime/abstract.runtime.ts +47 -0
- package/core/server/emroute.server.ts +324 -0
- package/core/type/component.type.ts +39 -0
- package/core/type/element.type.ts +10 -0
- package/core/type/logger.type.ts +20 -0
- package/core/type/markdown.type.ts +8 -0
- package/core/type/route-tree.type.ts +28 -0
- package/core/type/route.type.ts +75 -0
- package/core/type/widget.type.ts +27 -0
- package/core/util/html.util.ts +50 -0
- package/{src → core}/util/md.util.ts +3 -5
- package/{src/route → core/util}/route-tree.util.ts +0 -2
- package/{src → core}/util/widget-resolve.util.ts +15 -46
- package/{src → core}/widget/widget.parser.ts +2 -23
- package/core/widget/widget.registry.ts +36 -0
- package/dist/core/component/abstract.component.d.ts +48 -0
- package/dist/core/component/abstract.component.js +42 -0
- package/dist/core/component/abstract.component.js.map +1 -0
- package/dist/core/component/page.component.d.ts +23 -0
- package/dist/core/component/page.component.js +49 -0
- package/dist/core/component/page.component.js.map +1 -0
- package/dist/core/component/widget.component.d.ts +17 -0
- package/dist/core/component/widget.component.js +37 -0
- package/dist/core/component/widget.component.js.map +1 -0
- package/dist/core/pipeline/pipeline.d.ts +61 -0
- package/dist/core/pipeline/pipeline.js +189 -0
- package/dist/core/pipeline/pipeline.js.map +1 -0
- package/dist/{src/renderer/ssr → core/renderer}/html.renderer.d.ts +8 -24
- package/dist/{src/renderer/ssr → core/renderer}/html.renderer.js +20 -35
- package/dist/core/renderer/html.renderer.js.map +1 -0
- package/dist/{src/renderer/ssr → core/renderer}/md.renderer.d.ts +6 -21
- package/dist/{src/renderer/ssr → core/renderer}/md.renderer.js +16 -32
- package/dist/core/renderer/md.renderer.js.map +1 -0
- package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.d.ts +11 -27
- package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.js +33 -37
- package/dist/core/renderer/ssr.renderer.js.map +1 -0
- package/dist/{src/route → core/router}/route.resolver.d.ts +1 -8
- package/dist/{src/route → core/router}/route.resolver.js +0 -1
- package/dist/core/router/route.resolver.js.map +1 -0
- package/dist/core/router/route.trie.d.ts +32 -0
- package/dist/core/router/route.trie.js +152 -0
- package/dist/core/router/route.trie.js.map +1 -0
- package/dist/core/runtime/abstract.runtime.d.ts +32 -0
- package/dist/core/runtime/abstract.runtime.js +26 -0
- package/dist/core/runtime/abstract.runtime.js.map +1 -0
- package/dist/core/server/emroute.server.d.ts +48 -0
- package/dist/core/server/emroute.server.js +239 -0
- package/dist/core/server/emroute.server.js.map +1 -0
- package/dist/core/server/server.type.d.ts +45 -0
- package/dist/core/server/server.type.js +11 -0
- package/dist/core/server/server.type.js.map +1 -0
- package/dist/core/type/component.type.d.ts +37 -0
- package/dist/core/type/component.type.js +7 -0
- package/dist/core/type/component.type.js.map +1 -0
- package/dist/core/type/element.type.d.ts +9 -0
- package/dist/core/type/element.type.js +5 -0
- package/dist/core/type/element.type.js.map +1 -0
- package/dist/core/type/logger.type.d.ts +14 -0
- package/dist/core/type/logger.type.js +8 -0
- package/dist/core/type/logger.type.js.map +1 -0
- package/dist/core/type/markdown.type.d.ts +7 -0
- package/dist/core/type/markdown.type.js +5 -0
- package/dist/core/type/markdown.type.js.map +1 -0
- package/dist/{src → core}/type/route-tree.type.d.ts +0 -12
- package/dist/{src → core}/type/route-tree.type.js +0 -1
- package/dist/core/type/route-tree.type.js.map +1 -0
- package/dist/core/type/route.type.d.ts +62 -0
- package/dist/core/type/route.type.js +7 -0
- package/dist/core/type/route.type.js.map +1 -0
- package/dist/core/type/widget.type.d.ts +27 -0
- package/dist/core/type/widget.type.js +5 -0
- package/dist/core/type/widget.type.js.map +1 -0
- package/dist/core/util/html.util.d.ts +14 -0
- package/dist/core/util/html.util.js +43 -0
- package/dist/core/util/html.util.js.map +1 -0
- package/dist/{src → core}/util/md.util.d.ts +0 -1
- package/dist/{src → core}/util/md.util.js +0 -2
- package/dist/core/util/md.util.js.map +1 -0
- package/dist/{src/route → core/util}/route-tree.util.js +0 -2
- package/dist/core/util/route-tree.util.js.map +1 -0
- package/dist/core/util/widget-resolve.util.d.ts +28 -0
- package/dist/{src → core}/util/widget-resolve.util.js +12 -42
- package/dist/core/util/widget-resolve.util.js.map +1 -0
- package/dist/{src → core}/widget/widget.parser.d.ts +0 -13
- package/dist/{src → core}/widget/widget.parser.js +1 -22
- package/dist/core/widget/widget.parser.js.map +1 -0
- package/dist/core/widget/widget.registry.d.ts +14 -0
- package/dist/core/widget/widget.registry.js +26 -0
- package/dist/core/widget/widget.registry.js.map +1 -0
- package/dist/emroute.js +1092 -1220
- package/dist/emroute.js.map +36 -5
- package/dist/runtime/abstract.runtime.d.ts +41 -7
- package/dist/runtime/abstract.runtime.js +404 -9
- package/dist/runtime/abstract.runtime.js.map +1 -1
- package/dist/runtime/bun/fs/bun-fs.runtime.d.ts +1 -0
- package/dist/runtime/bun/fs/bun-fs.runtime.js +15 -1
- package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -1
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.d.ts +2 -0
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +8 -0
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -1
- package/dist/runtime/fetch.runtime.d.ts +3 -3
- package/dist/runtime/fetch.runtime.js +3 -3
- package/dist/runtime/sitemap.generator.d.ts +1 -1
- package/dist/runtime/sitemap.generator.js +1 -1
- package/dist/runtime/sitemap.generator.js.map +1 -1
- package/dist/runtime/universal/fs/universal-fs.runtime.d.ts +1 -0
- package/dist/runtime/universal/fs/universal-fs.runtime.js +15 -1
- package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -1
- package/dist/server/build.util.d.ts +9 -10
- package/dist/server/build.util.js +11 -31
- package/dist/server/build.util.js.map +1 -1
- package/dist/server/codegen.util.d.ts +1 -1
- package/dist/server/emroute.server.d.ts +8 -35
- package/dist/server/emroute.server.js +7 -351
- package/dist/server/emroute.server.js.map +1 -1
- package/dist/server/esbuild-manifest.plugin.js +1 -1
- package/dist/server/esbuild-manifest.plugin.js.map +1 -1
- package/dist/server/server-api.type.d.ts +3 -71
- package/dist/server/server-api.type.js +1 -8
- package/dist/server/server-api.type.js.map +1 -1
- package/dist/src/element/component.element.d.ts +6 -14
- package/dist/src/element/component.element.js +13 -40
- package/dist/src/element/component.element.js.map +1 -1
- package/dist/src/element/markdown.element.d.ts +2 -2
- package/dist/src/element/markdown.element.js +3 -2
- package/dist/src/element/markdown.element.js.map +1 -1
- package/dist/src/index.d.ts +15 -14
- package/dist/src/index.js +8 -8
- package/dist/src/index.js.map +1 -1
- package/dist/src/renderer/spa/emroute.app.d.ts +50 -0
- package/dist/src/renderer/spa/emroute.app.js +246 -0
- package/dist/src/renderer/spa/emroute.app.js.map +1 -0
- package/dist/src/renderer/spa/mod.d.ts +17 -16
- package/dist/src/renderer/spa/mod.js +9 -9
- package/dist/src/renderer/spa/mod.js.map +1 -1
- package/dist/src/renderer/spa/thin-client.d.ts +3 -3
- package/dist/src/renderer/spa/thin-client.js +7 -7
- package/dist/src/renderer/spa/thin-client.js.map +1 -1
- package/dist/src/route/route.core.d.ts +3 -3
- package/dist/src/util/html.util.d.ts +5 -22
- package/dist/src/util/html.util.js +8 -56
- package/dist/src/util/html.util.js.map +1 -1
- package/dist/src/widget/breadcrumb.widget.d.ts +2 -2
- package/dist/src/widget/breadcrumb.widget.js +2 -2
- package/dist/src/widget/breadcrumb.widget.js.map +1 -1
- package/dist/src/widget/page-title.widget.d.ts +1 -1
- package/dist/src/widget/page-title.widget.js +1 -1
- package/dist/src/widget/page-title.widget.js.map +1 -1
- package/package.json +8 -8
- package/runtime/abstract.runtime.ts +433 -17
- package/runtime/bun/fs/bun-fs.runtime.ts +15 -1
- package/runtime/bun/sqlite/bun-sqlite.runtime.ts +9 -0
- package/runtime/fetch.runtime.ts +3 -3
- package/runtime/sitemap.generator.ts +2 -2
- package/runtime/universal/fs/universal-fs.runtime.ts +15 -1
- package/server/build.util.ts +17 -43
- package/server/codegen.util.ts +1 -1
- package/server/emroute.server.ts +12 -426
- package/src/element/component.element.ts +14 -54
- package/src/element/markdown.element.ts +4 -3
- package/src/index.ts +22 -19
- package/src/renderer/spa/{thin-client.ts → emroute.app.ts} +19 -20
- package/src/renderer/spa/mod.ts +22 -22
- package/src/util/html.util.ts +16 -61
- package/src/widget/breadcrumb.widget.ts +3 -3
- package/src/widget/page-title.widget.ts +1 -1
- package/dist/src/component/abstract.component.d.ts +0 -199
- package/dist/src/component/abstract.component.js +0 -84
- package/dist/src/component/abstract.component.js.map +0 -1
- package/dist/src/component/page.component.d.ts +0 -74
- package/dist/src/component/page.component.js +0 -107
- package/dist/src/component/page.component.js.map +0 -1
- package/dist/src/component/widget.component.d.ts +0 -47
- package/dist/src/component/widget.component.js +0 -69
- package/dist/src/component/widget.component.js.map +0 -1
- package/dist/src/renderer/ssr/html.renderer.js.map +0 -1
- package/dist/src/renderer/ssr/md.renderer.js.map +0 -1
- package/dist/src/renderer/ssr/ssr.renderer.js.map +0 -1
- package/dist/src/route/route-tree.util.js.map +0 -1
- package/dist/src/route/route.matcher.d.ts +0 -86
- package/dist/src/route/route.matcher.js +0 -214
- package/dist/src/route/route.matcher.js.map +0 -1
- package/dist/src/route/route.resolver.js.map +0 -1
- package/dist/src/route/route.trie.d.ts +0 -38
- package/dist/src/route/route.trie.js +0 -206
- package/dist/src/route/route.trie.js.map +0 -1
- package/dist/src/type/element.type.d.ts +0 -19
- package/dist/src/type/element.type.js +0 -9
- package/dist/src/type/element.type.js.map +0 -1
- package/dist/src/type/logger.type.d.ts +0 -17
- package/dist/src/type/logger.type.js +0 -9
- package/dist/src/type/logger.type.js.map +0 -1
- package/dist/src/type/markdown.type.d.ts +0 -20
- package/dist/src/type/markdown.type.js +0 -2
- package/dist/src/type/markdown.type.js.map +0 -1
- package/dist/src/type/route-tree.type.js.map +0 -1
- package/dist/src/type/route.type.d.ts +0 -94
- package/dist/src/type/route.type.js +0 -8
- package/dist/src/type/route.type.js.map +0 -1
- package/dist/src/type/widget.type.d.ts +0 -55
- package/dist/src/type/widget.type.js +0 -10
- package/dist/src/type/widget.type.js.map +0 -1
- package/dist/src/util/logger.util.d.ts +0 -26
- package/dist/src/util/logger.util.js +0 -80
- package/dist/src/util/logger.util.js.map +0 -1
- package/dist/src/util/md.util.js.map +0 -1
- package/dist/src/util/widget-resolve.util.d.ts +0 -52
- package/dist/src/util/widget-resolve.util.js.map +0 -1
- package/dist/src/widget/widget.parser.js.map +0 -1
- package/dist/src/widget/widget.registry.d.ts +0 -23
- package/dist/src/widget/widget.registry.js +0 -42
- package/dist/src/widget/widget.registry.js.map +0 -1
- package/runtime/bun/esbuild-runtime-loader.plugin.ts +0 -112
- package/server/esbuild-manifest.plugin.ts +0 -209
- package/server/server-api.type.ts +0 -101
- package/src/component/abstract.component.ts +0 -231
- package/src/component/widget.component.ts +0 -85
- package/src/route/route.core.ts +0 -371
- package/src/route/route.trie.ts +0 -265
- package/src/type/element.type.ts +0 -22
- package/src/type/logger.type.ts +0 -24
- package/src/type/markdown.type.ts +0 -21
- package/src/type/route-tree.type.ts +0 -51
- package/src/type/route.type.ts +0 -124
- package/src/type/widget.type.ts +0 -65
- package/src/util/logger.util.ts +0 -83
- package/src/widget/widget.registry.ts +0 -51
- /package/dist/{src/route → core/util}/route-tree.util.d.ts +0 -0
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* Calls getData() + renderHTML() on widgets and injects SSR hydration data.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { Component
|
|
9
|
-
import {
|
|
8
|
+
import type { Component } from '../component/abstract.component.ts';
|
|
9
|
+
import type { ComponentContext, ContextProvider } from '../type/component.type.ts';
|
|
10
|
+
import { type Logger, defaultLogger } from '../type/logger.type.ts';
|
|
10
11
|
import type { RouteInfo } from '../type/route.type.ts';
|
|
11
12
|
import { LAZY_ATTR, SSR_ATTR } from './html.util.ts';
|
|
12
13
|
|
|
@@ -15,17 +16,6 @@ export const MAX_WIDGET_DEPTH = 10;
|
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Recursively resolve widgets in content with depth limit.
|
|
18
|
-
*
|
|
19
|
-
* Generic utility used by both HTML and Markdown widget resolution.
|
|
20
|
-
* Each depth level processes all widgets concurrently, then recurses
|
|
21
|
-
* into each rendered result to resolve nested widgets.
|
|
22
|
-
*
|
|
23
|
-
* @param content - Content containing widgets
|
|
24
|
-
* @param parse - Find widgets in content
|
|
25
|
-
* @param resolve - Resolve a single widget to rendered output
|
|
26
|
-
* @param replace - Replace widgets with resolved content
|
|
27
|
-
* @param depth - Current recursion depth (internal)
|
|
28
|
-
* @returns Content with all widgets recursively resolved
|
|
29
19
|
*/
|
|
30
20
|
export async function resolveRecursively<T>(
|
|
31
21
|
content: string,
|
|
@@ -33,6 +23,7 @@ export async function resolveRecursively<T>(
|
|
|
33
23
|
resolve: (widget: T) => Promise<string>,
|
|
34
24
|
replace: (content: string, replacements: Map<T, string>) => string,
|
|
35
25
|
depth = 0,
|
|
26
|
+
logger: Logger = defaultLogger,
|
|
36
27
|
): Promise<string> {
|
|
37
28
|
if (depth >= MAX_WIDGET_DEPTH) {
|
|
38
29
|
logger.warn(
|
|
@@ -49,10 +40,7 @@ export async function resolveRecursively<T>(
|
|
|
49
40
|
await Promise.all(
|
|
50
41
|
widgets.map(async (widget) => {
|
|
51
42
|
let rendered = await resolve(widget);
|
|
52
|
-
|
|
53
|
-
// Recursively resolve any nested widgets in the rendered output
|
|
54
|
-
rendered = await resolveRecursively(rendered, parse, resolve, replace, depth + 1);
|
|
55
|
-
|
|
43
|
+
rendered = await resolveRecursively(rendered, parse, resolve, replace, depth + 1, logger);
|
|
56
44
|
replacements.set(widget, rendered);
|
|
57
45
|
}),
|
|
58
46
|
);
|
|
@@ -61,18 +49,7 @@ export async function resolveRecursively<T>(
|
|
|
61
49
|
}
|
|
62
50
|
|
|
63
51
|
/**
|
|
64
|
-
* Resolve <widget-*> tags in HTML by calling getData() + renderHTML()
|
|
65
|
-
* via the widget registry. Injects rendered content and boolean ssr attribute.
|
|
66
|
-
*
|
|
67
|
-
* Supports nested widgets: if a widget's renderHTML() returns HTML containing
|
|
68
|
-
* other <widget-*> tags, those will be resolved recursively up to MAX_WIDGET_DEPTH.
|
|
69
|
-
*
|
|
70
|
-
* Before: <widget-crypto-price coin="bitcoin"></widget-crypto-price>
|
|
71
|
-
* After: <widget-crypto-price coin="bitcoin" ssr><template shadowrootmode="open"><span>$42,000</span></template></widget-crypto-price>
|
|
72
|
-
*
|
|
73
|
-
* When a widget has `exposeSsrData = true`, the getData() result is serialized
|
|
74
|
-
* as JSON text in the light DOM (alongside the shadow root template):
|
|
75
|
-
* After: <widget-crypto-price coin="bitcoin" ssr><template shadowrootmode="open"><span>$42,000</span></template>{"price":42000}</widget-crypto-price>
|
|
52
|
+
* Resolve <widget-*> tags in HTML by calling getData() + renderHTML().
|
|
76
53
|
*/
|
|
77
54
|
export function resolveWidgetTags(
|
|
78
55
|
html: string,
|
|
@@ -80,20 +57,16 @@ export function resolveWidgetTags(
|
|
|
80
57
|
routeInfo: RouteInfo,
|
|
81
58
|
loadFiles?: (
|
|
82
59
|
widgetName: string,
|
|
83
|
-
declaredFiles?: { html?: string; md?: string; css?: string },
|
|
84
60
|
) => Promise<{ html?: string; md?: string; css?: string }>,
|
|
85
61
|
contextProvider?: ContextProvider,
|
|
62
|
+
logger: Logger = defaultLogger,
|
|
86
63
|
): Promise<string> {
|
|
87
64
|
const tagPattern =
|
|
88
65
|
/<widget-(?<name>[a-z][a-z0-9-]*)(?<attrs>\s[^>]*)?>(?<content>.*?)<\/widget-\k<name>>/gis;
|
|
89
66
|
|
|
90
|
-
// Wrapping info stored per-match so replace() can apply it after recursion
|
|
91
67
|
const wrappers = new Map<RegExpExecArray, { tagName: string; attrs: string; ssrData: string }>();
|
|
92
|
-
|
|
93
|
-
// Matches standalone ssr attribute (boolean or with value), not as substring of another value
|
|
94
68
|
const ssrAttrPattern = new RegExp(`\\s${SSR_ATTR}(?:\\s|=|$)`);
|
|
95
69
|
|
|
96
|
-
// Parse: find unprocessed widget tags
|
|
97
70
|
const parse = (content: string) => {
|
|
98
71
|
const matches = content.matchAll(tagPattern).toArray();
|
|
99
72
|
return matches.filter((match) => {
|
|
@@ -102,20 +75,19 @@ export function resolveWidgetTags(
|
|
|
102
75
|
});
|
|
103
76
|
};
|
|
104
77
|
|
|
105
|
-
// Resolve: render a single widget's inner content (no outer tag wrapping — that's in replace)
|
|
106
78
|
const resolve = async (match: RegExpExecArray): Promise<string> => {
|
|
107
|
-
const widgetName = match.groups!.name
|
|
79
|
+
const widgetName = match.groups!.name!;
|
|
108
80
|
const attrsString = match.groups!.attrs?.trim() ?? '';
|
|
109
81
|
const widget = registry.get(widgetName);
|
|
110
82
|
|
|
111
|
-
if (!widget) return match[0];
|
|
83
|
+
if (!widget) return match[0];
|
|
112
84
|
|
|
113
85
|
const params = parseAttrsToParams(attrsString);
|
|
114
86
|
|
|
115
87
|
try {
|
|
116
88
|
let files: { html?: string; md?: string; css?: string } | undefined;
|
|
117
89
|
if (loadFiles) {
|
|
118
|
-
files = await loadFiles(widgetName
|
|
90
|
+
files = await loadFiles(widgetName);
|
|
119
91
|
}
|
|
120
92
|
|
|
121
93
|
const baseContext: ComponentContext = {
|
|
@@ -129,7 +101,6 @@ export function resolveWidgetTags(
|
|
|
129
101
|
const data = await widget.getData({ params, context });
|
|
130
102
|
const rendered = widget.renderHTML({ data, params, context });
|
|
131
103
|
|
|
132
|
-
// Store wrapping info — applied in replace() after recursion resolves nested widgets
|
|
133
104
|
wrappers.set(match, {
|
|
134
105
|
tagName: `widget-${widgetName}`,
|
|
135
106
|
attrs: attrsString ? ` ${attrsString}` : '',
|
|
@@ -142,11 +113,10 @@ export function resolveWidgetTags(
|
|
|
142
113
|
`[SSR HTML] Widget "${widgetName}" render failed`,
|
|
143
114
|
e instanceof Error ? e : undefined,
|
|
144
115
|
);
|
|
145
|
-
return match[0];
|
|
116
|
+
return match[0];
|
|
146
117
|
}
|
|
147
118
|
};
|
|
148
119
|
|
|
149
|
-
// Replace: wrap resolved content in outer tag + DSD template, then substitute by index
|
|
150
120
|
const replace = (content: string, replacements: Map<RegExpExecArray, string>) => {
|
|
151
121
|
let result = content;
|
|
152
122
|
const entries = [...replacements.entries()].sort((a, b) => b[0].index! - a[0].index!);
|
|
@@ -157,16 +127,16 @@ export function resolveWidgetTags(
|
|
|
157
127
|
const lightDomData = wrap?.ssrData ? wrap.ssrData : '';
|
|
158
128
|
const replacement = wrap
|
|
159
129
|
? `<${wrap.tagName}${wrap.attrs} ${SSR_ATTR}><template shadowrootmode="open">${innerHtml}</template>${lightDomData}</${wrap.tagName}>`
|
|
160
|
-
: innerHtml;
|
|
130
|
+
: innerHtml;
|
|
161
131
|
result = result.slice(0, start) + replacement + result.slice(end);
|
|
162
132
|
}
|
|
163
133
|
return result;
|
|
164
134
|
};
|
|
165
135
|
|
|
166
|
-
return resolveRecursively(html, parse, resolve, replace);
|
|
136
|
+
return resolveRecursively(html, parse, resolve, replace, 0, logger);
|
|
167
137
|
}
|
|
168
138
|
|
|
169
|
-
/** Parse HTML attribute string into params object
|
|
139
|
+
/** Parse HTML attribute string into params object. */
|
|
170
140
|
export function parseAttrsToParams(attrsString: string): Record<string, unknown> {
|
|
171
141
|
const params: Record<string, unknown> = {};
|
|
172
142
|
if (!attrsString) return params;
|
|
@@ -175,7 +145,7 @@ export function parseAttrsToParams(attrsString: string): Record<string, unknown>
|
|
|
175
145
|
/(?<attr>[a-z][a-z0-9-]*)(?:="(?<dq>[^"]*)"|='(?<sq>[^']*)'|=(?<uq>[^\s>]+))?/gi;
|
|
176
146
|
for (const match of attrsString.matchAll(attrPattern)) {
|
|
177
147
|
const { attr: attrName, dq, sq, uq } = match.groups!;
|
|
178
|
-
if (attrName === SSR_ATTR || attrName === LAZY_ATTR) continue;
|
|
148
|
+
if (!attrName || attrName === SSR_ATTR || attrName === LAZY_ATTR) continue;
|
|
179
149
|
const key = attrName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
180
150
|
const rawValue = dq ?? sq ?? uq;
|
|
181
151
|
if (rawValue === undefined) {
|
|
@@ -196,7 +166,6 @@ export function parseAttrsToParams(attrsString: string): Record<string, unknown>
|
|
|
196
166
|
return params;
|
|
197
167
|
}
|
|
198
168
|
|
|
199
|
-
/** Escape a value for use in a single-quoted HTML attribute. */
|
|
200
169
|
function escapeAttr(value: string): string {
|
|
201
170
|
return value.replaceAll('&', '&').replaceAll("'", ''');
|
|
202
171
|
}
|
|
@@ -11,36 +11,25 @@
|
|
|
11
11
|
|
|
12
12
|
import type { ParsedWidgetBlock } from '../type/widget.type.ts';
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* Pattern to match widget fenced code blocks.
|
|
16
|
-
* Captures: widget name, params content
|
|
17
|
-
*/
|
|
18
14
|
const WIDGET_PATTERN = /```widget:(?<name>[a-z][a-z0-9-]*)\n(?<params>.*?)```/gs;
|
|
19
15
|
|
|
20
|
-
/**
|
|
21
|
-
* Parse all widget blocks from markdown content.
|
|
22
|
-
*
|
|
23
|
-
* @param markdown - Markdown content to parse
|
|
24
|
-
* @returns Array of parsed widget blocks with positions
|
|
25
|
-
*/
|
|
26
16
|
export function parseWidgetBlocks(markdown: string): ParsedWidgetBlock[] {
|
|
27
17
|
const blocks: ParsedWidgetBlock[] = [];
|
|
28
18
|
|
|
29
19
|
for (const match of markdown.matchAll(WIDGET_PATTERN)) {
|
|
30
20
|
const fullMatch = match[0];
|
|
31
21
|
const { name: widgetName, params: paramsRaw } = match.groups!;
|
|
32
|
-
const paramsJson = paramsRaw
|
|
22
|
+
const paramsJson = paramsRaw!.trim();
|
|
33
23
|
const startIndex = match.index;
|
|
34
24
|
|
|
35
25
|
const block: ParsedWidgetBlock = {
|
|
36
26
|
fullMatch,
|
|
37
|
-
widgetName
|
|
27
|
+
widgetName: widgetName!,
|
|
38
28
|
params: null,
|
|
39
29
|
startIndex,
|
|
40
30
|
endIndex: startIndex + fullMatch.length,
|
|
41
31
|
};
|
|
42
32
|
|
|
43
|
-
// Parse JSON params if present
|
|
44
33
|
if (paramsJson) {
|
|
45
34
|
try {
|
|
46
35
|
const parsed = JSON.parse(paramsJson);
|
|
@@ -53,7 +42,6 @@ export function parseWidgetBlocks(markdown: string): ParsedWidgetBlock[] {
|
|
|
53
42
|
block.parseError = `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`;
|
|
54
43
|
}
|
|
55
44
|
} else {
|
|
56
|
-
// Empty params is valid - use empty object
|
|
57
45
|
block.params = {};
|
|
58
46
|
}
|
|
59
47
|
|
|
@@ -63,19 +51,10 @@ export function parseWidgetBlocks(markdown: string): ParsedWidgetBlock[] {
|
|
|
63
51
|
return blocks;
|
|
64
52
|
}
|
|
65
53
|
|
|
66
|
-
/**
|
|
67
|
-
* Replace widget blocks in markdown with rendered content.
|
|
68
|
-
*
|
|
69
|
-
* @param markdown - Original markdown content
|
|
70
|
-
* @param replacements - Map of parsed blocks to replacement strings
|
|
71
|
-
* @returns Markdown with widget blocks replaced
|
|
72
|
-
*/
|
|
73
54
|
export function replaceWidgetBlocks(
|
|
74
55
|
markdown: string,
|
|
75
56
|
replacements: Map<ParsedWidgetBlock, string>,
|
|
76
57
|
): string {
|
|
77
|
-
// Sort blocks by position descending to replace from end first
|
|
78
|
-
// This preserves indices during replacement
|
|
79
58
|
const sortedBlocks = [...replacements.entries()].sort(
|
|
80
59
|
([a], [b]) => b.startIndex - a.startIndex,
|
|
81
60
|
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget Registry
|
|
3
|
+
*
|
|
4
|
+
* Name → Component lookup. Used by all renderers.
|
|
5
|
+
* Pages are NOT in this registry — they live in the routes manifest.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { WidgetComponent } from '../component/widget.component.ts';
|
|
9
|
+
|
|
10
|
+
interface RegistryEntry {
|
|
11
|
+
widget: WidgetComponent;
|
|
12
|
+
modulePath?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class WidgetRegistry {
|
|
16
|
+
private entries = new Map<string, RegistryEntry>();
|
|
17
|
+
|
|
18
|
+
add(widget: WidgetComponent, modulePath?: string): void {
|
|
19
|
+
this.entries.set(widget.name, { widget, modulePath });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get(name: string): WidgetComponent | undefined {
|
|
23
|
+
return this.entries.get(name)?.widget;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getModulePath(name: string): string | undefined {
|
|
27
|
+
return this.entries.get(name)?.modulePath;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
[Symbol.iterator](): IterableIterator<WidgetComponent> {
|
|
31
|
+
const entries = this.entries.values();
|
|
32
|
+
return (function* () {
|
|
33
|
+
for (const entry of entries) yield entry.widget;
|
|
34
|
+
})();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Base Class
|
|
3
|
+
*
|
|
4
|
+
* Everything is a Component: pages and widgets.
|
|
5
|
+
* Components render differently based on context:
|
|
6
|
+
* - /md/* → Markdown (LLMs, text clients)
|
|
7
|
+
* - /html/* → Pre-rendered HTML (SSR)
|
|
8
|
+
* - SPA → Hydrated custom elements
|
|
9
|
+
*/
|
|
10
|
+
import type { ComponentContext } from '../type/component.type.ts';
|
|
11
|
+
export declare abstract class Component<TParams = unknown, TData = unknown, TContext extends ComponentContext = ComponentContext> {
|
|
12
|
+
readonly DataArgs: {
|
|
13
|
+
params: TParams;
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
context: TContext;
|
|
16
|
+
};
|
|
17
|
+
readonly RenderArgs: {
|
|
18
|
+
data: TData | null;
|
|
19
|
+
params: TParams;
|
|
20
|
+
context: TContext;
|
|
21
|
+
};
|
|
22
|
+
abstract readonly name: string;
|
|
23
|
+
/** Host element reference, set by ComponentElement in the browser. */
|
|
24
|
+
element?: HTMLElement | undefined;
|
|
25
|
+
/** Associated file paths for pre-loaded content (html, md, css). */
|
|
26
|
+
readonly files?: {
|
|
27
|
+
html?: string;
|
|
28
|
+
md?: string;
|
|
29
|
+
css?: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* When true, SSR serializes the getData() result into the element's
|
|
33
|
+
* light DOM so the client can access it immediately in hydrate()
|
|
34
|
+
* without re-fetching.
|
|
35
|
+
*/
|
|
36
|
+
readonly exposeSsrData?: boolean;
|
|
37
|
+
abstract getData(args: this['DataArgs']): Promise<TData | null>;
|
|
38
|
+
abstract renderMarkdown(args: this['RenderArgs']): string;
|
|
39
|
+
renderHTML(args: this['RenderArgs']): string;
|
|
40
|
+
hydrate?(args: this['RenderArgs']): void;
|
|
41
|
+
destroy?(): void;
|
|
42
|
+
validateParams?(params: TParams): string | undefined;
|
|
43
|
+
renderError(args: {
|
|
44
|
+
error: unknown;
|
|
45
|
+
params: TParams;
|
|
46
|
+
}): string;
|
|
47
|
+
renderMarkdownError(error: unknown): string;
|
|
48
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Base Class
|
|
3
|
+
*
|
|
4
|
+
* Everything is a Component: pages and widgets.
|
|
5
|
+
* Components render differently based on context:
|
|
6
|
+
* - /md/* → Markdown (LLMs, text clients)
|
|
7
|
+
* - /html/* → Pre-rendered HTML (SSR)
|
|
8
|
+
* - SPA → Hydrated custom elements
|
|
9
|
+
*/
|
|
10
|
+
import { escapeHtml } from "../util/html.util.js";
|
|
11
|
+
export class Component {
|
|
12
|
+
/** Host element reference, set by ComponentElement in the browser. */
|
|
13
|
+
element;
|
|
14
|
+
/** Associated file paths for pre-loaded content (html, md, css). */
|
|
15
|
+
files;
|
|
16
|
+
/**
|
|
17
|
+
* When true, SSR serializes the getData() result into the element's
|
|
18
|
+
* light DOM so the client can access it immediately in hydrate()
|
|
19
|
+
* without re-fetching.
|
|
20
|
+
*/
|
|
21
|
+
exposeSsrData;
|
|
22
|
+
renderHTML(args) {
|
|
23
|
+
if (args.data === null) {
|
|
24
|
+
return `<div data-component="${this.name}">Loading...</div>`;
|
|
25
|
+
}
|
|
26
|
+
const markdown = this.renderMarkdown({
|
|
27
|
+
data: args.data,
|
|
28
|
+
params: args.params,
|
|
29
|
+
context: args.context,
|
|
30
|
+
});
|
|
31
|
+
return `<div data-component="${this.name}" data-markdown>${escapeHtml(markdown)}</div>`;
|
|
32
|
+
}
|
|
33
|
+
renderError(args) {
|
|
34
|
+
const msg = args.error instanceof Error ? args.error.message : String(args.error);
|
|
35
|
+
return `<div data-component="${this.name}">Error: ${escapeHtml(msg)}</div>`;
|
|
36
|
+
}
|
|
37
|
+
renderMarkdownError(error) {
|
|
38
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
39
|
+
return `> **Error** (\`${this.name}\`): ${msg}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=abstract.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abstract.component.js","sourceRoot":"","sources":["../../../core/component/abstract.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,OAAgB,SAAS;IAmB7B,sEAAsE;IACtE,OAAO,CAA2B;IAElC,oEAAoE;IAC3D,KAAK,CAAgD;IAE9D;;;;OAIG;IACM,aAAa,CAAW;IAKjC,UAAU,CAAC,IAAwB;QACjC,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,wBAAwB,IAAI,CAAC,IAAI,oBAAoB,CAAC;QAC/D,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC;YACnC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,OAAO,wBAAwB,IAAI,CAAC,IAAI,mBAAmB,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC1F,CAAC;IAMD,WAAW,CAAC,IAAyC;QACnD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClF,OAAO,wBAAwB,IAAI,CAAC,IAAI,YAAY,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC9E,CAAC;IAED,mBAAmB,CAAC,KAAc;QAChC,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,OAAO,kBAAkB,IAAI,CAAC,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Component
|
|
3
|
+
*
|
|
4
|
+
* Params come from URL, context carries file content.
|
|
5
|
+
*
|
|
6
|
+
* Default implementations follow the fallback table:
|
|
7
|
+
* - renderHTML: html file → md via <mark-down> → <router-slot /> (non-leaf only)
|
|
8
|
+
* - renderMarkdown: md file → ```router-slot\n``` (non-leaf only)
|
|
9
|
+
* - getData: no-op (returns null)
|
|
10
|
+
*/
|
|
11
|
+
import { Component } from './abstract.component.ts';
|
|
12
|
+
import type { ComponentContext } from '../type/component.type.ts';
|
|
13
|
+
export declare class PageComponent<TParams extends Record<string, string> = Record<string, string>, TData = unknown, TContext extends ComponentContext = ComponentContext> extends Component<TParams, TData, TContext> {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly pattern?: string;
|
|
16
|
+
getData(_args: this['DataArgs']): Promise<TData | null>;
|
|
17
|
+
renderHTML(args: this['RenderArgs']): string;
|
|
18
|
+
renderMarkdown(args: this['RenderArgs']): string;
|
|
19
|
+
getTitle(_args: this['RenderArgs']): string | undefined;
|
|
20
|
+
}
|
|
21
|
+
/** Shared default instance used by renderers when no custom .page.ts exists. */
|
|
22
|
+
declare const _default: PageComponent<Record<string, string>, unknown, ComponentContext>;
|
|
23
|
+
export default _default;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Component
|
|
3
|
+
*
|
|
4
|
+
* Params come from URL, context carries file content.
|
|
5
|
+
*
|
|
6
|
+
* Default implementations follow the fallback table:
|
|
7
|
+
* - renderHTML: html file → md via <mark-down> → <router-slot /> (non-leaf only)
|
|
8
|
+
* - renderMarkdown: md file → ```router-slot\n``` (non-leaf only)
|
|
9
|
+
* - getData: no-op (returns null)
|
|
10
|
+
*/
|
|
11
|
+
import { Component } from "./abstract.component.js";
|
|
12
|
+
import { escapeHtml } from "../util/html.util.js";
|
|
13
|
+
export class PageComponent extends Component {
|
|
14
|
+
name = 'page';
|
|
15
|
+
pattern;
|
|
16
|
+
getData(_args) {
|
|
17
|
+
return Promise.resolve(null);
|
|
18
|
+
}
|
|
19
|
+
renderHTML(args) {
|
|
20
|
+
const files = args.context.files;
|
|
21
|
+
const style = files?.css ? `<style>${files.css}</style>\n` : '';
|
|
22
|
+
if (files?.html) {
|
|
23
|
+
let html = style + files.html;
|
|
24
|
+
if (files.md && html.includes('<mark-down></mark-down>')) {
|
|
25
|
+
html = html.replace('<mark-down></mark-down>', `<mark-down>${escapeHtml(files.md)}</mark-down>`);
|
|
26
|
+
}
|
|
27
|
+
return html;
|
|
28
|
+
}
|
|
29
|
+
if (files?.md) {
|
|
30
|
+
const hasSlot = files.md.includes('```router-slot');
|
|
31
|
+
const slot = args.context.isLeaf || hasSlot ? '' : '\n<router-slot></router-slot>';
|
|
32
|
+
return `${style}<mark-down>${escapeHtml(files.md)}</mark-down>${slot}`;
|
|
33
|
+
}
|
|
34
|
+
return args.context.isLeaf ? '' : '<router-slot></router-slot>';
|
|
35
|
+
}
|
|
36
|
+
renderMarkdown(args) {
|
|
37
|
+
const files = args.context.files;
|
|
38
|
+
if (files?.md) {
|
|
39
|
+
return files.md;
|
|
40
|
+
}
|
|
41
|
+
return args.context.isLeaf ? '' : '```router-slot\n```';
|
|
42
|
+
}
|
|
43
|
+
getTitle(_args) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Shared default instance used by renderers when no custom .page.ts exists. */
|
|
48
|
+
export default new PageComponent();
|
|
49
|
+
//# sourceMappingURL=page.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.component.js","sourceRoot":"","sources":["../../../core/component/page.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,OAAO,aAIX,SAAQ,SAAmC;IACzB,IAAI,GAAW,MAAM,CAAC;IAC/B,OAAO,CAAU;IAEjB,OAAO,CACd,KAAuB;QAEvB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAEQ,UAAU,CACjB,IAAwB;QAExB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QACjC,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAEhE,IAAI,KAAK,EAAE,IAAI,EAAE,CAAC;YAChB,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;YAC9B,IAAI,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC;gBACzD,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,yBAAyB,EACzB,cAAc,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,cAAc,CACjD,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,KAAK,EAAE,EAAE,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,+BAA+B,CAAC;YACnF,OAAO,GAAG,KAAK,cAAc,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,eAAe,IAAI,EAAE,CAAC;QACzE,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,6BAA6B,CAAC;IAClE,CAAC;IAEQ,cAAc,CACrB,IAAwB;QAExB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QAEjC,IAAI,KAAK,EAAE,EAAE,EAAE,CAAC;YACd,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAC1D,CAAC;IAED,QAAQ,CACN,KAAyB;QAEzB,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAED,gFAAgF;AAChF,eAAe,IAAI,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget Component
|
|
3
|
+
*
|
|
4
|
+
* Embeddable unit within page content. Everything reusable that is not
|
|
5
|
+
* a page is a Widget. Widgets render across all contexts (HTML, Markdown, SPA)
|
|
6
|
+
* and are resolved by name via WidgetRegistry.
|
|
7
|
+
*
|
|
8
|
+
* Default rendering fallback chains (parallel to PageComponent):
|
|
9
|
+
* - renderHTML: html file → md file in <mark-down> → base Component default
|
|
10
|
+
* - renderMarkdown: md file → ''
|
|
11
|
+
*/
|
|
12
|
+
import { Component } from './abstract.component.ts';
|
|
13
|
+
import type { ComponentContext } from '../type/component.type.ts';
|
|
14
|
+
export declare abstract class WidgetComponent<TParams = unknown, TData = unknown, TContext extends ComponentContext = ComponentContext> extends Component<TParams, TData, TContext> {
|
|
15
|
+
renderHTML(args: this['RenderArgs']): string;
|
|
16
|
+
renderMarkdown(args: this['RenderArgs']): string;
|
|
17
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget Component
|
|
3
|
+
*
|
|
4
|
+
* Embeddable unit within page content. Everything reusable that is not
|
|
5
|
+
* a page is a Widget. Widgets render across all contexts (HTML, Markdown, SPA)
|
|
6
|
+
* and are resolved by name via WidgetRegistry.
|
|
7
|
+
*
|
|
8
|
+
* Default rendering fallback chains (parallel to PageComponent):
|
|
9
|
+
* - renderHTML: html file → md file in <mark-down> → base Component default
|
|
10
|
+
* - renderMarkdown: md file → ''
|
|
11
|
+
*/
|
|
12
|
+
import { Component } from "./abstract.component.js";
|
|
13
|
+
import { escapeHtml, scopeWidgetCss } from "../util/html.util.js";
|
|
14
|
+
export class WidgetComponent extends Component {
|
|
15
|
+
renderHTML(args) {
|
|
16
|
+
const files = args.context.files;
|
|
17
|
+
const style = files?.css ? `<style>${scopeWidgetCss(files.css, this.name)}</style>\n` : '';
|
|
18
|
+
if (files?.html) {
|
|
19
|
+
return style + files.html;
|
|
20
|
+
}
|
|
21
|
+
if (files?.md) {
|
|
22
|
+
return `${style}<mark-down>${escapeHtml(files.md)}</mark-down>`;
|
|
23
|
+
}
|
|
24
|
+
if (style) {
|
|
25
|
+
return style + super.renderHTML(args);
|
|
26
|
+
}
|
|
27
|
+
return super.renderHTML(args);
|
|
28
|
+
}
|
|
29
|
+
renderMarkdown(args) {
|
|
30
|
+
const files = args.context.files;
|
|
31
|
+
if (files?.md) {
|
|
32
|
+
return files.md;
|
|
33
|
+
}
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=widget.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.component.js","sourceRoot":"","sources":["../../../core/component/widget.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAElE,MAAM,OAAgB,eAIpB,SAAQ,SAAmC;IAClC,UAAU,CACjB,IAAwB;QAExB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QACjC,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3F,IAAI,KAAK,EAAE,IAAI,EAAE,CAAC;YAChB,OAAO,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;QAC5B,CAAC;QAED,IAAI,KAAK,EAAE,EAAE,EAAE,CAAC;YACd,OAAO,GAAG,KAAK,cAAc,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,cAAc,CAAC;QAClE,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAEQ,cAAc,CACrB,IAAwB;QAExB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QAEjC,IAAI,KAAK,EAAE,EAAE,EAAE,CAAC;YACd,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;CACF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline
|
|
3
|
+
*
|
|
4
|
+
* Orchestration layer between Router, Runtime, and Component.
|
|
5
|
+
*
|
|
6
|
+
* Owns:
|
|
7
|
+
* - Route matching (reads manifest from Runtime, walks RouteNode tree)
|
|
8
|
+
* - Module loading (delegates to Runtime)
|
|
9
|
+
* - Companion file reading (delegates to Runtime)
|
|
10
|
+
* - ComponentContext building
|
|
11
|
+
* - Route hierarchy construction
|
|
12
|
+
*
|
|
13
|
+
* Does NOT own:
|
|
14
|
+
* - Rendering (that's Renderer)
|
|
15
|
+
* - HTTP routing / base paths (that's Server)
|
|
16
|
+
* - Storage I/O (that's Runtime)
|
|
17
|
+
* - Navigation events (that's the browser adapter)
|
|
18
|
+
*/
|
|
19
|
+
import type { RouteConfig, MatchedRoute, RouteInfo } from '../type/route.type.ts';
|
|
20
|
+
import type { ComponentContext, ContextProvider, FileContents } from '../type/component.type.ts';
|
|
21
|
+
import type { Runtime } from '../runtime/abstract.runtime.ts';
|
|
22
|
+
import { type Logger } from '../type/logger.type.ts';
|
|
23
|
+
/** Default root route — renders a slot for child routes. */
|
|
24
|
+
export declare const DEFAULT_ROOT_ROUTE: RouteConfig;
|
|
25
|
+
/** Pipeline configuration. */
|
|
26
|
+
export interface PipelineOptions {
|
|
27
|
+
runtime: Runtime;
|
|
28
|
+
contextProvider?: ContextProvider;
|
|
29
|
+
/** Pre-bundled module loaders (browser boot passes these). */
|
|
30
|
+
moduleLoaders?: Record<string, () => Promise<unknown>>;
|
|
31
|
+
logger?: Logger;
|
|
32
|
+
}
|
|
33
|
+
export declare class Pipeline {
|
|
34
|
+
private readonly runtime;
|
|
35
|
+
readonly contextProvider: ContextProvider | undefined;
|
|
36
|
+
readonly logger: Logger;
|
|
37
|
+
private readonly moduleLoaders;
|
|
38
|
+
constructor(options: PipelineOptions);
|
|
39
|
+
private getResolver;
|
|
40
|
+
match(url: URL): Promise<MatchedRoute | undefined>;
|
|
41
|
+
findRoute(pattern: string): Promise<RouteConfig | undefined>;
|
|
42
|
+
findErrorBoundary(pathname: string): Promise<{
|
|
43
|
+
pattern: string;
|
|
44
|
+
modulePath: string;
|
|
45
|
+
} | undefined>;
|
|
46
|
+
getStatusPage(status: number): Promise<RouteConfig | undefined>;
|
|
47
|
+
getErrorHandler(): Promise<RouteConfig | undefined>;
|
|
48
|
+
buildRouteHierarchy(pattern: string): string[];
|
|
49
|
+
loadModule<T>(modulePath: string): Promise<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Get inlined `__files` from a loaded module (merged module pattern).
|
|
52
|
+
*/
|
|
53
|
+
getModuleFiles(mod: unknown): FileContents | undefined;
|
|
54
|
+
loadFiles(files: {
|
|
55
|
+
html?: string;
|
|
56
|
+
md?: string;
|
|
57
|
+
css?: string;
|
|
58
|
+
}): Promise<FileContents>;
|
|
59
|
+
toRouteInfo(matched: MatchedRoute, url: URL): RouteInfo;
|
|
60
|
+
buildContext(routeInfo: RouteInfo, route: RouteConfig, signal?: AbortSignal, isLeaf?: boolean, loadedModule?: unknown): Promise<ComponentContext>;
|
|
61
|
+
}
|