@emkodev/emroute 1.8.2-beta.1 → 1.10.0-beta.1
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/widget.component.ts +1 -1
- package/core/pipeline/pipeline.ts +11 -1
- package/core/renderer/html.renderer.ts +16 -18
- package/core/renderer/md.renderer.ts +3 -5
- package/core/renderer/ssr.renderer.ts +21 -5
- package/core/server/emroute.server.ts +9 -62
- package/core/util/widget-resolve.util.ts +2 -2
- package/core/widget/widget.registry.ts +14 -28
- package/dist/core/component/widget.component.d.ts +1 -1
- package/dist/core/component/widget.component.js +1 -1
- package/dist/core/pipeline/pipeline.d.ts +1 -0
- package/dist/core/pipeline/pipeline.js +9 -1
- package/dist/core/pipeline/pipeline.js.map +1 -1
- package/dist/core/renderer/html.renderer.js +10 -12
- package/dist/core/renderer/html.renderer.js.map +1 -1
- package/dist/core/renderer/md.renderer.js +3 -5
- package/dist/core/renderer/md.renderer.js.map +1 -1
- package/dist/core/renderer/ssr.renderer.d.ts +6 -4
- package/dist/core/renderer/ssr.renderer.js +16 -3
- package/dist/core/renderer/ssr.renderer.js.map +1 -1
- package/dist/core/server/emroute.server.d.ts +2 -4
- package/dist/core/server/emroute.server.js +7 -52
- package/dist/core/server/emroute.server.js.map +1 -1
- package/dist/core/util/widget-resolve.util.d.ts +1 -3
- package/dist/core/util/widget-resolve.util.js +2 -2
- package/dist/core/util/widget-resolve.util.js.map +1 -1
- package/dist/core/widget/widget.registry.d.ts +5 -10
- package/dist/core/widget/widget.registry.js +15 -20
- package/dist/core/widget/widget.registry.js.map +1 -1
- package/dist/emroute.js +449 -95
- package/dist/emroute.js.map +17 -14
- package/dist/runtime/cache.runtime.d.ts +31 -0
- package/dist/runtime/cache.runtime.js +107 -0
- package/dist/runtime/cache.runtime.js.map +1 -0
- package/dist/runtime/idb.runtime.d.ts +31 -0
- package/dist/runtime/idb.runtime.js +178 -0
- package/dist/runtime/idb.runtime.js.map +1 -0
- package/dist/src/element/component.element.d.ts +4 -1
- package/dist/src/element/component.element.js +4 -1
- package/dist/src/element/component.element.js.map +1 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/renderer/spa/emroute.app.d.ts +3 -0
- package/dist/src/renderer/spa/emroute.app.js +6 -4
- package/dist/src/renderer/spa/emroute.app.js.map +1 -1
- package/dist/src/renderer/spa/mod.d.ts +4 -3
- package/dist/src/renderer/spa/mod.js +5 -3
- package/dist/src/renderer/spa/mod.js.map +1 -1
- package/dist/src/service-worker/emroute.sw.d.ts +54 -0
- package/dist/src/service-worker/emroute.sw.js +181 -0
- package/dist/src/service-worker/emroute.sw.js.map +1 -0
- package/dist/src/service-worker/mod.d.ts +8 -0
- package/dist/src/service-worker/mod.js +9 -0
- package/dist/src/service-worker/mod.js.map +1 -0
- package/package.json +16 -1
- package/runtime/cache.runtime.ts +127 -0
- package/runtime/idb.runtime.ts +203 -0
- package/src/element/component.element.ts +4 -1
- package/src/index.ts +0 -1
- package/src/renderer/spa/emroute.app.ts +11 -4
- package/src/renderer/spa/mod.ts +6 -4
- package/src/service-worker/emroute.sw.ts +264 -0
- package/src/service-worker/mod.ts +9 -0
package/README.md
CHANGED
|
@@ -114,7 +114,7 @@ export default new ProjectPage();
|
|
|
114
114
|
- **Configurable base paths** — `/html/` and `/md/` prefixes are configurable via `BasePath`
|
|
115
115
|
- **SPA modes** — `'root'` (default), `'leaf'`, `'none'`, or `'only'` to control how the server handles non-file requests and SSR endpoints
|
|
116
116
|
- **Sitemap generation** — opt-in `sitemap.xml` from the routes manifest with support for dynamic route enumerators
|
|
117
|
-
- **Dev server** — zero-config: auto-generates `main.ts
|
|
117
|
+
- **Dev server** — zero-config: auto-generates `main.ts` and route/widget manifests. File watcher with hot reload and bundle serving
|
|
118
118
|
|
|
119
119
|
## Runtimes
|
|
120
120
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Embeddable unit within page content. Everything reusable that is not
|
|
5
5
|
* a page is a Widget. Widgets render across all contexts (HTML, Markdown, SPA)
|
|
6
|
-
* and are resolved by name via
|
|
6
|
+
* and are resolved by name via the widgets manifest.
|
|
7
7
|
*
|
|
8
8
|
* Default rendering fallback chains (parallel to PageComponent):
|
|
9
9
|
* - renderHTML: html file → md file in <mark-down> → base Component default
|
|
@@ -22,7 +22,8 @@ import type { RouteNode } from '../type/route-tree.type.ts';
|
|
|
22
22
|
import type { RouteConfig, MatchedRoute, RouteInfo } from '../type/route.type.ts';
|
|
23
23
|
import type { ComponentContext, ContextProvider, FileContents } from '../type/component.type.ts';
|
|
24
24
|
import type { Runtime } from '../runtime/abstract.runtime.ts';
|
|
25
|
-
import { ROUTES_MANIFEST_PATH } from '../runtime/abstract.runtime.ts';
|
|
25
|
+
import { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH } from '../runtime/abstract.runtime.ts';
|
|
26
|
+
import type { WidgetManifestEntry } from '../type/widget.type.ts';
|
|
26
27
|
import { type Logger, defaultLogger } from '../type/logger.type.ts';
|
|
27
28
|
|
|
28
29
|
/** Default root route — renders a slot for child routes. */
|
|
@@ -128,6 +129,15 @@ export class Pipeline {
|
|
|
128
129
|
return hierarchy;
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
// ── Widget manifest lookup ─────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
async findWidgetModulePath(name: string): Promise<string | undefined> {
|
|
135
|
+
const response = await this.runtime.query(WIDGETS_MANIFEST_PATH);
|
|
136
|
+
if (response.status === 404) return undefined;
|
|
137
|
+
const entries: WidgetManifestEntry[] = await response.json();
|
|
138
|
+
return entries.find((e) => e.name === name)?.modulePath;
|
|
139
|
+
}
|
|
140
|
+
|
|
131
141
|
// ── Module loading ─────────────────────────────────────────────────
|
|
132
142
|
|
|
133
143
|
async loadModule<T>(modulePath: string): Promise<T> {
|
|
@@ -65,24 +65,22 @@ export class SsrHtmlRenderer extends SsrRenderer {
|
|
|
65
65
|
content = this.attributeSlots(content, route.pattern);
|
|
66
66
|
|
|
67
67
|
// Resolve <widget-*> tags
|
|
68
|
-
|
|
69
|
-
content
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
);
|
|
85
|
-
}
|
|
68
|
+
content = await resolveWidgetTags(
|
|
69
|
+
content,
|
|
70
|
+
(name) => this.resolveWidget(name),
|
|
71
|
+
routeInfo,
|
|
72
|
+
async (name) => {
|
|
73
|
+
const modulePath = await this.pipeline.findWidgetModulePath(name);
|
|
74
|
+
if (modulePath) {
|
|
75
|
+
const mod = await this.pipeline.loadModule(modulePath);
|
|
76
|
+
const inlined = this.pipeline.getModuleFiles(mod);
|
|
77
|
+
if (inlined) return inlined;
|
|
78
|
+
}
|
|
79
|
+
return {};
|
|
80
|
+
},
|
|
81
|
+
this.pipeline.contextProvider,
|
|
82
|
+
this.logger,
|
|
83
|
+
);
|
|
86
84
|
|
|
87
85
|
return { content, ...(title !== undefined ? { title } : {}) };
|
|
88
86
|
}
|
|
@@ -57,9 +57,7 @@ export class SsrMdRenderer extends SsrRenderer {
|
|
|
57
57
|
content = content.replaceAll(BARE_SLOT_BLOCK, routerSlotBlock(route.pattern));
|
|
58
58
|
|
|
59
59
|
// Resolve fenced widget blocks
|
|
60
|
-
|
|
61
|
-
content = await this.resolveWidgets(content, routeInfo);
|
|
62
|
-
}
|
|
60
|
+
content = await this.resolveWidgets(content, routeInfo);
|
|
63
61
|
|
|
64
62
|
return { content, ...(title !== undefined ? { title } : {}) };
|
|
65
63
|
}
|
|
@@ -95,14 +93,14 @@ export class SsrMdRenderer extends SsrRenderer {
|
|
|
95
93
|
return `> **Error** (\`${block.widgetName}\`): ${block.parseError}`;
|
|
96
94
|
}
|
|
97
95
|
|
|
98
|
-
const widget = this.
|
|
96
|
+
const widget = await this.resolveWidget(block.widgetName);
|
|
99
97
|
if (!widget) {
|
|
100
98
|
return `> **Error**: Unknown widget \`${block.widgetName}\``;
|
|
101
99
|
}
|
|
102
100
|
|
|
103
101
|
try {
|
|
104
102
|
let files: { html?: string; md?: string } | undefined;
|
|
105
|
-
const modulePath = this.
|
|
103
|
+
const modulePath = await this.pipeline.findWidgetModulePath(block.widgetName);
|
|
106
104
|
if (modulePath) {
|
|
107
105
|
const mod = await this.pipeline.loadModule(modulePath);
|
|
108
106
|
files = this.pipeline.getModuleFiles(mod);
|
|
@@ -15,11 +15,13 @@ import type { Logger } from '../type/logger.type.ts';
|
|
|
15
15
|
import defaultPageComponent, { type PageComponent } from '../component/page.component.ts';
|
|
16
16
|
import { DEFAULT_ROOT_ROUTE, type Pipeline } from '../pipeline/pipeline.ts';
|
|
17
17
|
import { assertSafeRedirect } from '../util/html.util.ts';
|
|
18
|
-
import
|
|
18
|
+
import { extractWidgetExport } from '../widget/widget.registry.ts';
|
|
19
|
+
import type { WidgetComponent } from '../component/widget.component.ts';
|
|
19
20
|
|
|
20
21
|
/** Options for SSR renderers. */
|
|
21
22
|
export interface SsrRendererOptions {
|
|
22
|
-
|
|
23
|
+
/** @deprecated Widgets are resolved from the manifest via Runtime. This option is ignored. */
|
|
24
|
+
widgets?: unknown;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
/**
|
|
@@ -27,15 +29,29 @@ export interface SsrRendererOptions {
|
|
|
27
29
|
*/
|
|
28
30
|
export abstract class SsrRenderer {
|
|
29
31
|
protected readonly pipeline: Pipeline;
|
|
30
|
-
protected widgets: WidgetRegistry | null;
|
|
31
32
|
protected abstract readonly label: string;
|
|
32
33
|
|
|
33
34
|
protected readonly logger: Logger;
|
|
34
35
|
|
|
35
|
-
constructor(pipeline: Pipeline,
|
|
36
|
+
constructor(pipeline: Pipeline, _options: SsrRendererOptions = {}) {
|
|
36
37
|
this.pipeline = pipeline;
|
|
37
38
|
this.logger = pipeline.logger;
|
|
38
|
-
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Resolve a widget by name — queries manifest from Runtime on demand. */
|
|
42
|
+
protected async resolveWidget(name: string): Promise<WidgetComponent | undefined> {
|
|
43
|
+
const path = await this.pipeline.findWidgetModulePath(name);
|
|
44
|
+
if (!path) return undefined;
|
|
45
|
+
try {
|
|
46
|
+
const mod = await this.pipeline.loadModule<Record<string, unknown>>(path);
|
|
47
|
+
return extractWidgetExport(mod) ?? undefined;
|
|
48
|
+
} catch (e) {
|
|
49
|
+
this.logger.error(
|
|
50
|
+
`[${this.label}] Failed to load widget "${name}"`,
|
|
51
|
+
e instanceof Error ? e : undefined,
|
|
52
|
+
);
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
39
55
|
}
|
|
40
56
|
|
|
41
57
|
/**
|
|
@@ -6,12 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { WidgetManifestEntry } from '../type/widget.type.ts';
|
|
9
|
-
import type { WidgetComponent } from '../component/widget.component.ts';
|
|
10
9
|
import type { Runtime } from '../runtime/abstract.runtime.ts';
|
|
11
10
|
import { Pipeline } from '../pipeline/pipeline.ts';
|
|
12
11
|
import { SsrHtmlRenderer } from '../renderer/html.renderer.ts';
|
|
13
12
|
import { SsrMdRenderer } from '../renderer/md.renderer.ts';
|
|
14
|
-
import { WidgetRegistry } from '../widget/widget.registry.ts';
|
|
15
13
|
import { escapeHtml } from '../util/html.util.ts';
|
|
16
14
|
import { rewriteMdLinks } from '../util/md.util.ts';
|
|
17
15
|
import type { RouteNode } from '../type/route-tree.type.ts';
|
|
@@ -49,7 +47,8 @@ export class Emroute {
|
|
|
49
47
|
static async create(
|
|
50
48
|
config: {
|
|
51
49
|
routeTree?: RouteNode;
|
|
52
|
-
|
|
50
|
+
/** @deprecated Widgets are resolved from the manifest via Runtime. This option is ignored. */
|
|
51
|
+
widgets?: unknown;
|
|
53
52
|
spa?: SpaMode;
|
|
54
53
|
basePath?: BasePath;
|
|
55
54
|
title?: string;
|
|
@@ -86,21 +85,6 @@ export class Emroute {
|
|
|
86
85
|
...(config.moduleLoaders ? { moduleLoaders: config.moduleLoaders } : {}),
|
|
87
86
|
});
|
|
88
87
|
|
|
89
|
-
// ── Widgets ───────────────────────────────────────────────────────
|
|
90
|
-
|
|
91
|
-
let widgets: WidgetRegistry | undefined;
|
|
92
|
-
|
|
93
|
-
const widgetsResponse = await runtime.query(WIDGETS_MANIFEST_PATH);
|
|
94
|
-
if (widgetsResponse.status !== 404) {
|
|
95
|
-
const entries: WidgetManifestEntry[] = await widgetsResponse.json();
|
|
96
|
-
widgets = await Emroute.importWidgets(entries, runtime);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (config.widgets) {
|
|
100
|
-
if (!widgets) widgets = new WidgetRegistry();
|
|
101
|
-
for (const w of config.widgets) widgets.add(w);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
88
|
// ── Renderers ─────────────────────────────────────────────────────
|
|
105
89
|
|
|
106
90
|
let ssrHtmlRenderer: SsrHtmlRenderer | null = null;
|
|
@@ -109,12 +93,9 @@ export class Emroute {
|
|
|
109
93
|
if (spa !== 'only') {
|
|
110
94
|
ssrHtmlRenderer = new SsrHtmlRenderer(pipeline, {
|
|
111
95
|
...(config.markdownRenderer ? { markdownRenderer: config.markdownRenderer } : {}),
|
|
112
|
-
...(widgets ? { widgets } : {}),
|
|
113
96
|
});
|
|
114
97
|
|
|
115
|
-
ssrMdRenderer = new SsrMdRenderer(pipeline
|
|
116
|
-
...(widgets ? { widgets } : {}),
|
|
117
|
-
});
|
|
98
|
+
ssrMdRenderer = new SsrMdRenderer(pipeline);
|
|
118
99
|
}
|
|
119
100
|
|
|
120
101
|
// ── HTML shell ────────────────────────────────────────────────────
|
|
@@ -240,45 +221,6 @@ export class Emroute {
|
|
|
240
221
|
|
|
241
222
|
// ── Private static helpers ────────────────────────────────────────
|
|
242
223
|
|
|
243
|
-
private static extractWidgetExport(
|
|
244
|
-
mod: Record<string, unknown>,
|
|
245
|
-
): WidgetComponent | null {
|
|
246
|
-
for (const value of Object.values(mod)) {
|
|
247
|
-
if (!value) continue;
|
|
248
|
-
if (typeof value === 'object' && 'getData' in value) {
|
|
249
|
-
return value as WidgetComponent;
|
|
250
|
-
}
|
|
251
|
-
if (typeof value === 'function' && value.prototype?.getData) {
|
|
252
|
-
return new (value as new () => WidgetComponent)();
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
private static async importWidgets(
|
|
259
|
-
entries: WidgetManifestEntry[],
|
|
260
|
-
runtime: Runtime,
|
|
261
|
-
): Promise<WidgetRegistry> {
|
|
262
|
-
const registry = new WidgetRegistry();
|
|
263
|
-
|
|
264
|
-
for (const entry of entries) {
|
|
265
|
-
try {
|
|
266
|
-
const runtimePath = entry.modulePath.startsWith('/')
|
|
267
|
-
? entry.modulePath
|
|
268
|
-
: `/${entry.modulePath}`;
|
|
269
|
-
|
|
270
|
-
const mod = await runtime.loadModule(runtimePath) as Record<string, unknown>;
|
|
271
|
-
const instance = Emroute.extractWidgetExport(mod);
|
|
272
|
-
if (!instance) continue;
|
|
273
|
-
registry.add(instance, runtimePath);
|
|
274
|
-
} catch (e) {
|
|
275
|
-
console.error(`[emroute] Failed to load widget ${entry.modulePath}:`, e);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return registry;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
224
|
private static async buildHtmlShell(
|
|
283
225
|
runtime: Runtime,
|
|
284
226
|
title: string,
|
|
@@ -287,6 +229,11 @@ export class Emroute {
|
|
|
287
229
|
): Promise<string> {
|
|
288
230
|
const baseTag = basePath ? `\n <base href="${escapeHtml(basePath)}/">` : '';
|
|
289
231
|
|
|
232
|
+
let manifestTag = '';
|
|
233
|
+
if ((await runtime.query('/manifest.json')).status !== 404) {
|
|
234
|
+
manifestTag = '\n <link rel="manifest" href="/manifest.json">';
|
|
235
|
+
}
|
|
236
|
+
|
|
290
237
|
let cssTag = '';
|
|
291
238
|
if ((await runtime.query('/main.css')).status !== 404) {
|
|
292
239
|
cssTag = '\n <link rel="stylesheet" href="/main.css">';
|
|
@@ -314,7 +261,7 @@ export class Emroute {
|
|
|
314
261
|
<meta charset="utf-8">
|
|
315
262
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
316
263
|
<title>${escapeHtml(title)}</title>
|
|
317
|
-
<style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>${cssTag}
|
|
264
|
+
<style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>${manifestTag}${cssTag}
|
|
318
265
|
</head>
|
|
319
266
|
<body>
|
|
320
267
|
<router-slot></router-slot>${importMapHtml}${scriptHtml}
|
|
@@ -53,7 +53,7 @@ export async function resolveRecursively<T>(
|
|
|
53
53
|
*/
|
|
54
54
|
export function resolveWidgetTags(
|
|
55
55
|
html: string,
|
|
56
|
-
|
|
56
|
+
getWidget: (name: string) => Promise<Component | undefined>,
|
|
57
57
|
routeInfo: RouteInfo,
|
|
58
58
|
loadFiles?: (
|
|
59
59
|
widgetName: string,
|
|
@@ -78,7 +78,7 @@ export function resolveWidgetTags(
|
|
|
78
78
|
const resolve = async (match: RegExpExecArray): Promise<string> => {
|
|
79
79
|
const widgetName = match.groups!.name!;
|
|
80
80
|
const attrsString = match.groups!.attrs?.trim() ?? '';
|
|
81
|
-
const widget =
|
|
81
|
+
const widget = await getWidget(widgetName);
|
|
82
82
|
|
|
83
83
|
if (!widget) return match[0];
|
|
84
84
|
|
|
@@ -1,36 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Widget Registry
|
|
2
|
+
* Widget Registry Utilities
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Helpers for extracting widget components from loaded modules.
|
|
5
|
+
* Widget resolution is handled by Pipeline → Runtime (widgets manifest).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { WidgetComponent } from '../component/widget.component.ts';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
})();
|
|
10
|
+
/** Extract a WidgetComponent from a loaded module's exports. */
|
|
11
|
+
export function extractWidgetExport(mod: Record<string, unknown>): WidgetComponent | null {
|
|
12
|
+
for (const value of Object.values(mod)) {
|
|
13
|
+
if (!value) continue;
|
|
14
|
+
if (typeof value === 'object' && 'getData' in value) {
|
|
15
|
+
return value as WidgetComponent;
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === 'function' && value.prototype?.getData) {
|
|
18
|
+
return new (value as new () => WidgetComponent)();
|
|
19
|
+
}
|
|
35
20
|
}
|
|
21
|
+
return null;
|
|
36
22
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Embeddable unit within page content. Everything reusable that is not
|
|
5
5
|
* a page is a Widget. Widgets render across all contexts (HTML, Markdown, SPA)
|
|
6
|
-
* and are resolved by name via
|
|
6
|
+
* and are resolved by name via the widgets manifest.
|
|
7
7
|
*
|
|
8
8
|
* Default rendering fallback chains (parallel to PageComponent):
|
|
9
9
|
* - renderHTML: html file → md file in <mark-down> → base Component default
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Embeddable unit within page content. Everything reusable that is not
|
|
5
5
|
* a page is a Widget. Widgets render across all contexts (HTML, Markdown, SPA)
|
|
6
|
-
* and are resolved by name via
|
|
6
|
+
* and are resolved by name via the widgets manifest.
|
|
7
7
|
*
|
|
8
8
|
* Default rendering fallback chains (parallel to PageComponent):
|
|
9
9
|
* - renderHTML: html file → md file in <mark-down> → base Component default
|
|
@@ -46,6 +46,7 @@ export declare class Pipeline {
|
|
|
46
46
|
getStatusPage(status: number): Promise<RouteConfig | undefined>;
|
|
47
47
|
getErrorHandler(): Promise<RouteConfig | undefined>;
|
|
48
48
|
buildRouteHierarchy(pattern: string): string[];
|
|
49
|
+
findWidgetModulePath(name: string): Promise<string | undefined>;
|
|
49
50
|
loadModule<T>(modulePath: string): Promise<T>;
|
|
50
51
|
/**
|
|
51
52
|
* Get inlined `__files` from a loaded module (merged module pattern).
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* - Navigation events (that's the browser adapter)
|
|
18
18
|
*/
|
|
19
19
|
import { RouteTrie } from "../router/route.trie.js";
|
|
20
|
-
import { ROUTES_MANIFEST_PATH } from "../runtime/abstract.runtime.js";
|
|
20
|
+
import { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH } from "../runtime/abstract.runtime.js";
|
|
21
21
|
import { defaultLogger } from "../type/logger.type.js";
|
|
22
22
|
/** Default root route — renders a slot for child routes. */
|
|
23
23
|
export const DEFAULT_ROOT_ROUTE = {
|
|
@@ -104,6 +104,14 @@ export class Pipeline {
|
|
|
104
104
|
}
|
|
105
105
|
return hierarchy;
|
|
106
106
|
}
|
|
107
|
+
// ── Widget manifest lookup ─────────────────────────────────────────
|
|
108
|
+
async findWidgetModulePath(name) {
|
|
109
|
+
const response = await this.runtime.query(WIDGETS_MANIFEST_PATH);
|
|
110
|
+
if (response.status === 404)
|
|
111
|
+
return undefined;
|
|
112
|
+
const entries = await response.json();
|
|
113
|
+
return entries.find((e) => e.name === name)?.modulePath;
|
|
114
|
+
}
|
|
107
115
|
// ── Module loading ─────────────────────────────────────────────────
|
|
108
116
|
async loadModule(modulePath) {
|
|
109
117
|
const loader = this.moduleLoaders[modulePath];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../core/pipeline/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAKpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../core/pipeline/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,18 +37,16 @@ export class SsrHtmlRenderer extends SsrRenderer {
|
|
|
37
37
|
// Attribute bare <router-slot> tags with this route's pattern
|
|
38
38
|
content = this.attributeSlots(content, route.pattern);
|
|
39
39
|
// Resolve <widget-*> tags
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}, this.pipeline.contextProvider, this.logger);
|
|
51
|
-
}
|
|
40
|
+
content = await resolveWidgetTags(content, (name) => this.resolveWidget(name), routeInfo, async (name) => {
|
|
41
|
+
const modulePath = await this.pipeline.findWidgetModulePath(name);
|
|
42
|
+
if (modulePath) {
|
|
43
|
+
const mod = await this.pipeline.loadModule(modulePath);
|
|
44
|
+
const inlined = this.pipeline.getModuleFiles(mod);
|
|
45
|
+
if (inlined)
|
|
46
|
+
return inlined;
|
|
47
|
+
}
|
|
48
|
+
return {};
|
|
49
|
+
}, this.pipeline.contextProvider, this.logger);
|
|
52
50
|
return { content, ...(title !== undefined ? { title } : {}) };
|
|
53
51
|
}
|
|
54
52
|
renderContent(component, args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.renderer.js","sourceRoot":"","sources":["../../../core/renderer/html.renderer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AAOzE,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAClB,KAAK,GAAG,UAAU,CAAC;IACvC,gBAAgB,CAA0B;IAC1C,aAAa,GAAyB,IAAI,CAAC;IAEnD,YAAY,QAAkB,EAAE,UAAkC,EAAE;QAClE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;QAEzD,IAAI,IAAI,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IAEkB,UAAU,CAAC,MAAc,EAAE,KAAa,EAAE,aAAqB;QAChF,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO,MAAM,CAAC,OAAO,CACnB,IAAI,MAAM,CAAC,mCAAmC,OAAO,uBAAuB,CAAC,EAC7E,KAAK,CACN,CAAC;IACJ,CAAC;IAEkB,UAAU,CAAC,MAAc;QAC1C,OAAO,MAAM,CAAC,OAAO,CAAC,oCAAoC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IAEkB,KAAK,CAAC,kBAAkB,CACzC,SAAoB,EACpB,KAAkB,EAClB,MAAgB,EAChB,MAAoB;QAEpB,IAAI,KAAK,CAAC,UAAU,KAAK,kBAAkB,CAAC,UAAU,EAAE,CAAC;YACvD,OAAO,EAAE,OAAO,EAAE,yBAAyB,KAAK,CAAC,OAAO,kBAAkB,EAAE,CAAC;QAC/E,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACrG,IAAI,OAAO,GAAG,UAAU,CAAC;QAEzB,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAE7C,8DAA8D;QAC9D,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAEtD,0BAA0B;QAC1B,
|
|
1
|
+
{"version":3,"file":"html.renderer.js","sourceRoot":"","sources":["../../../core/renderer/html.renderer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AAOzE,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAClB,KAAK,GAAG,UAAU,CAAC;IACvC,gBAAgB,CAA0B;IAC1C,aAAa,GAAyB,IAAI,CAAC;IAEnD,YAAY,QAAkB,EAAE,UAAkC,EAAE;QAClE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;QAEzD,IAAI,IAAI,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IAEkB,UAAU,CAAC,MAAc,EAAE,KAAa,EAAE,aAAqB;QAChF,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO,MAAM,CAAC,OAAO,CACnB,IAAI,MAAM,CAAC,mCAAmC,OAAO,uBAAuB,CAAC,EAC7E,KAAK,CACN,CAAC;IACJ,CAAC;IAEkB,UAAU,CAAC,MAAc;QAC1C,OAAO,MAAM,CAAC,OAAO,CAAC,oCAAoC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IAEkB,KAAK,CAAC,kBAAkB,CACzC,SAAoB,EACpB,KAAkB,EAClB,MAAgB,EAChB,MAAoB;QAEpB,IAAI,KAAK,CAAC,UAAU,KAAK,kBAAkB,CAAC,UAAU,EAAE,CAAC;YACvD,OAAO,EAAE,OAAO,EAAE,yBAAyB,KAAK,CAAC,OAAO,kBAAkB,EAAE,CAAC;QAC/E,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACrG,IAAI,OAAO,GAAG,UAAU,CAAC;QAEzB,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAE7C,8DAA8D;QAC9D,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAEtD,0BAA0B;QAC1B,OAAO,GAAG,MAAM,iBAAiB,CAC/B,OAAO,EACP,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAClC,SAAS,EACT,KAAK,EAAE,IAAI,EAAE,EAAE;YACb,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAClE,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;gBACvD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;gBAClD,IAAI,OAAO;oBAAE,OAAO,OAAO,CAAC;YAC9B,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,EACD,IAAI,CAAC,QAAQ,CAAC,eAAe,EAC7B,IAAI,CAAC,MAAM,CACZ,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAChE,CAAC;IAEkB,aAAa,CAC9B,SAAwB,EACxB,IAAiC;QAEjC,OAAO,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEkB,cAAc,CAAC,EAAU;QAC1C,OAAO,6CAA6C,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC;IACzE,CAAC;IAEkB,gBAAgB,CAAC,MAAc,EAAE,GAAQ;QAC1D,OAAO;YACC,eAAe,CAAC,MAAM,CAAC,IAAI,OAAO;iBAC7B,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;KACpC,CAAC;IACJ,CAAC;IAEkB,eAAe,CAAC,KAAc,EAAE,GAAQ;QACzD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO;;iBAEM,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;WAC9B,UAAU,CAAC,OAAO,CAAC;KACzB,CAAC;IACJ,CAAC;IAEO,cAAc,CAAC,OAAe,EAAE,YAAoB;QAC1D,OAAO,OAAO,CAAC,OAAO,CACpB,yDAAyD,EACzD,yBAAyB,YAAY,oBAAoB,CAC1D,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,OAAe;QAC1C,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO,OAAO,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;YAAE,OAAO,OAAO,CAAC;QAErD,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,aAAa,CAAC;QAC3B,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACvC,MAAM,OAAO,GAAG,qCAAqC,CAAC;QAEtD,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,OAAe,EAAE,EAAE;YAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACvC,OAAO,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -35,9 +35,7 @@ export class SsrMdRenderer extends SsrRenderer {
|
|
|
35
35
|
// Attribute bare router-slot blocks with this route's pattern
|
|
36
36
|
content = content.replaceAll(BARE_SLOT_BLOCK, routerSlotBlock(route.pattern));
|
|
37
37
|
// Resolve fenced widget blocks
|
|
38
|
-
|
|
39
|
-
content = await this.resolveWidgets(content, routeInfo);
|
|
40
|
-
}
|
|
38
|
+
content = await this.resolveWidgets(content, routeInfo);
|
|
41
39
|
return { content, ...(title !== undefined ? { title } : {}) };
|
|
42
40
|
}
|
|
43
41
|
renderContent(component, args) {
|
|
@@ -57,13 +55,13 @@ export class SsrMdRenderer extends SsrRenderer {
|
|
|
57
55
|
if (block.parseError || !block.params) {
|
|
58
56
|
return `> **Error** (\`${block.widgetName}\`): ${block.parseError}`;
|
|
59
57
|
}
|
|
60
|
-
const widget = this.
|
|
58
|
+
const widget = await this.resolveWidget(block.widgetName);
|
|
61
59
|
if (!widget) {
|
|
62
60
|
return `> **Error**: Unknown widget \`${block.widgetName}\``;
|
|
63
61
|
}
|
|
64
62
|
try {
|
|
65
63
|
let files;
|
|
66
|
-
const modulePath = this.
|
|
64
|
+
const modulePath = await this.pipeline.findWidgetModulePath(block.widgetName);
|
|
67
65
|
if (modulePath) {
|
|
68
66
|
const mod = await this.pipeline.loadModule(modulePath);
|
|
69
67
|
files = this.pipeline.getModuleFiles(mod);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md.renderer.js","sourceRoot":"","sources":["../../../core/renderer/md.renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AAEzE,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,kCAAkC,OAAO,YAAY,CAAC;AAC/D,CAAC;AAID,MAAM,OAAO,aAAc,SAAQ,WAAW;IAChB,KAAK,GAAG,QAAQ,CAAC;IAE7C,YAAY,QAAkB,EAAE,UAAgC,EAAE;QAChE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC;IAEkB,UAAU,CAAC,MAAc,EAAE,KAAa,EAAE,aAAqB;QAChF,OAAO,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/D,CAAC;IAEkB,UAAU,CAAC,MAAc;QAC1C,OAAO,MAAM;aACV,OAAO,CAAC,sCAAsC,EAAE,EAAE,CAAC;aACnD,IAAI,EAAE,CAAC;IACZ,CAAC;IAEkB,KAAK,CAAC,kBAAkB,CACzC,SAAoB,EACpB,KAAkB,EAClB,MAAgB,EAChB,MAAoB;QAEpB,IAAI,KAAK,CAAC,UAAU,KAAK,kBAAkB,CAAC,UAAU,EAAE,CAAC;YACvD,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACrG,IAAI,OAAO,GAAG,UAAU,CAAC;QAEzB,8DAA8D;QAC9D,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAE9E,+BAA+B;QAC/B,
|
|
1
|
+
{"version":3,"file":"md.renderer.js","sourceRoot":"","sources":["../../../core/renderer/md.renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,20 +9,22 @@ import type { ComponentContext } from '../type/component.type.ts';
|
|
|
9
9
|
import type { Logger } from '../type/logger.type.ts';
|
|
10
10
|
import { type PageComponent } from '../component/page.component.ts';
|
|
11
11
|
import { type Pipeline } from '../pipeline/pipeline.ts';
|
|
12
|
-
import type {
|
|
12
|
+
import type { WidgetComponent } from '../component/widget.component.ts';
|
|
13
13
|
/** Options for SSR renderers. */
|
|
14
14
|
export interface SsrRendererOptions {
|
|
15
|
-
|
|
15
|
+
/** @deprecated Widgets are resolved from the manifest via Runtime. This option is ignored. */
|
|
16
|
+
widgets?: unknown;
|
|
16
17
|
}
|
|
17
18
|
/**
|
|
18
19
|
* Abstract SSR renderer with shared routing pipeline.
|
|
19
20
|
*/
|
|
20
21
|
export declare abstract class SsrRenderer {
|
|
21
22
|
protected readonly pipeline: Pipeline;
|
|
22
|
-
protected widgets: WidgetRegistry | null;
|
|
23
23
|
protected abstract readonly label: string;
|
|
24
24
|
protected readonly logger: Logger;
|
|
25
|
-
constructor(pipeline: Pipeline,
|
|
25
|
+
constructor(pipeline: Pipeline, _options?: SsrRendererOptions);
|
|
26
|
+
/** Resolve a widget by name — queries manifest from Runtime on demand. */
|
|
27
|
+
protected resolveWidget(name: string): Promise<WidgetComponent | undefined>;
|
|
26
28
|
/**
|
|
27
29
|
* Render a URL to a content string.
|
|
28
30
|
*/
|
|
@@ -7,17 +7,30 @@
|
|
|
7
7
|
import defaultPageComponent from "../component/page.component.js";
|
|
8
8
|
import { DEFAULT_ROOT_ROUTE } from "../pipeline/pipeline.js";
|
|
9
9
|
import { assertSafeRedirect } from "../util/html.util.js";
|
|
10
|
+
import { extractWidgetExport } from "../widget/widget.registry.js";
|
|
10
11
|
/**
|
|
11
12
|
* Abstract SSR renderer with shared routing pipeline.
|
|
12
13
|
*/
|
|
13
14
|
export class SsrRenderer {
|
|
14
15
|
pipeline;
|
|
15
|
-
widgets;
|
|
16
16
|
logger;
|
|
17
|
-
constructor(pipeline,
|
|
17
|
+
constructor(pipeline, _options = {}) {
|
|
18
18
|
this.pipeline = pipeline;
|
|
19
19
|
this.logger = pipeline.logger;
|
|
20
|
-
|
|
20
|
+
}
|
|
21
|
+
/** Resolve a widget by name — queries manifest from Runtime on demand. */
|
|
22
|
+
async resolveWidget(name) {
|
|
23
|
+
const path = await this.pipeline.findWidgetModulePath(name);
|
|
24
|
+
if (!path)
|
|
25
|
+
return undefined;
|
|
26
|
+
try {
|
|
27
|
+
const mod = await this.pipeline.loadModule(path);
|
|
28
|
+
return extractWidgetExport(mod) ?? undefined;
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
this.logger.error(`[${this.label}] Failed to load widget "${name}"`, e instanceof Error ? e : undefined);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
21
34
|
}
|
|
22
35
|
/**
|
|
23
36
|
* Render a URL to a content string.
|