@emkodev/emroute 1.6.2 → 1.6.4
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 +6 -6
- package/dist/runtime/abstract.runtime.d.ts +94 -0
- package/dist/runtime/abstract.runtime.js +339 -0
- package/dist/runtime/abstract.runtime.js.map +1 -0
- package/dist/runtime/bun/esbuild-runtime-loader.plugin.d.ts +25 -0
- package/dist/runtime/bun/esbuild-runtime-loader.plugin.js +72 -0
- package/dist/runtime/bun/esbuild-runtime-loader.plugin.js.map +1 -0
- package/dist/runtime/bun/fs/bun-fs.runtime.d.ts +21 -0
- package/dist/runtime/bun/fs/bun-fs.runtime.js +205 -0
- package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -0
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.d.ts +27 -0
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +234 -0
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -0
- package/dist/runtime/sitemap.generator.d.ts +58 -0
- package/dist/runtime/sitemap.generator.js +107 -0
- package/dist/runtime/sitemap.generator.js.map +1 -0
- package/dist/runtime/universal/fs/universal-fs.runtime.d.ts +29 -0
- package/dist/runtime/universal/fs/universal-fs.runtime.js +213 -0
- package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -0
- package/dist/server/codegen.util.d.ts +16 -0
- package/dist/server/codegen.util.js +46 -0
- package/dist/server/codegen.util.js.map +1 -0
- package/dist/server/emroute.server.d.ts +37 -0
- package/dist/server/emroute.server.js +314 -0
- package/dist/server/emroute.server.js.map +1 -0
- package/dist/server/esbuild-manifest.plugin.d.ts +26 -0
- package/dist/server/esbuild-manifest.plugin.js +187 -0
- package/dist/server/esbuild-manifest.plugin.js.map +1 -0
- package/dist/server/scanner.util.d.ts +22 -0
- package/dist/server/scanner.util.js +194 -0
- package/dist/server/scanner.util.js.map +1 -0
- package/dist/server/server-api.type.d.ts +71 -0
- package/dist/server/server-api.type.js +9 -0
- package/dist/server/server-api.type.js.map +1 -0
- package/dist/src/component/abstract.component.d.ts +197 -0
- package/dist/src/component/abstract.component.js +84 -0
- package/dist/src/component/abstract.component.js.map +1 -0
- package/dist/src/component/page.component.d.ts +74 -0
- package/dist/src/component/page.component.js +107 -0
- package/dist/src/component/page.component.js.map +1 -0
- package/dist/src/component/widget.component.d.ts +47 -0
- package/dist/src/component/widget.component.js +69 -0
- package/dist/src/component/widget.component.js.map +1 -0
- package/dist/src/element/component.element.d.ts +79 -0
- package/dist/src/element/component.element.js +293 -0
- package/dist/src/element/component.element.js.map +1 -0
- package/dist/src/element/markdown.element.d.ts +36 -0
- package/dist/src/element/markdown.element.js +93 -0
- package/dist/src/element/markdown.element.js.map +1 -0
- package/dist/src/element/slot.element.d.ts +30 -0
- package/dist/src/element/slot.element.js +31 -0
- package/dist/src/element/slot.element.js.map +1 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.js +24 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/overlay/mod.d.ts +9 -0
- package/dist/src/overlay/mod.js +9 -0
- package/dist/src/overlay/mod.js.map +1 -0
- package/dist/src/overlay/overlay.css.d.ts +8 -0
- package/dist/src/overlay/overlay.css.js +170 -0
- package/dist/src/overlay/overlay.css.js.map +1 -0
- package/dist/src/overlay/overlay.service.d.ts +14 -0
- package/dist/src/overlay/overlay.service.js +307 -0
- package/dist/src/overlay/overlay.service.js.map +1 -0
- package/dist/src/overlay/overlay.type.d.ts +33 -0
- package/dist/src/overlay/overlay.type.js +11 -0
- package/dist/src/overlay/overlay.type.js.map +1 -0
- package/dist/src/renderer/spa/base.renderer.d.ts +39 -0
- package/dist/src/renderer/spa/base.renderer.js +149 -0
- package/dist/src/renderer/spa/base.renderer.js.map +1 -0
- package/dist/src/renderer/spa/hash.renderer.d.ts +78 -0
- package/dist/src/renderer/spa/hash.renderer.js +162 -0
- package/dist/src/renderer/spa/hash.renderer.js.map +1 -0
- package/dist/src/renderer/spa/html.renderer.d.ts +81 -0
- package/dist/src/renderer/spa/html.renderer.js +304 -0
- package/dist/src/renderer/spa/html.renderer.js.map +1 -0
- package/dist/src/renderer/spa/mod.d.ts +30 -0
- package/dist/src/renderer/spa/mod.js +35 -0
- package/dist/src/renderer/spa/mod.js.map +1 -0
- package/dist/src/renderer/ssr/html.renderer.d.ts +49 -0
- package/dist/src/renderer/ssr/html.renderer.js +108 -0
- package/dist/src/renderer/ssr/html.renderer.js.map +1 -0
- package/dist/src/renderer/ssr/md.renderer.d.ts +40 -0
- package/dist/src/renderer/ssr/md.renderer.js +100 -0
- package/dist/src/renderer/ssr/md.renderer.js.map +1 -0
- package/dist/src/renderer/ssr/ssr.renderer.d.ts +74 -0
- package/dist/src/renderer/ssr/ssr.renderer.js +185 -0
- package/dist/src/renderer/ssr/ssr.renderer.js.map +1 -0
- package/dist/src/route/route.core.d.ts +129 -0
- package/dist/src/route/route.core.js +255 -0
- package/dist/src/route/route.core.js.map +1 -0
- package/dist/src/route/route.matcher.d.ts +86 -0
- package/dist/src/route/route.matcher.js +214 -0
- package/dist/src/route/route.matcher.js.map +1 -0
- package/dist/src/type/logger.type.d.ts +17 -0
- package/dist/src/type/logger.type.js +9 -0
- package/dist/src/type/logger.type.js.map +1 -0
- package/dist/src/type/markdown.type.d.ts +20 -0
- package/dist/src/type/markdown.type.js +2 -0
- package/dist/src/type/markdown.type.js.map +1 -0
- package/dist/src/type/route.type.d.ts +112 -0
- package/dist/src/type/route.type.js +8 -0
- package/dist/src/type/route.type.js.map +1 -0
- package/dist/src/type/widget.type.d.ts +55 -0
- package/dist/src/type/widget.type.js +10 -0
- package/dist/src/type/widget.type.js.map +1 -0
- package/dist/src/util/html.util.d.ts +29 -0
- package/dist/src/util/html.util.js +158 -0
- package/dist/src/util/html.util.js.map +1 -0
- package/dist/src/util/logger.util.d.ts +26 -0
- package/dist/src/util/logger.util.js +80 -0
- package/dist/src/util/logger.util.js.map +1 -0
- package/dist/src/util/widget-resolve.util.d.ts +52 -0
- package/dist/src/util/widget-resolve.util.js +149 -0
- package/dist/src/util/widget-resolve.util.js.map +1 -0
- package/dist/src/widget/breadcrumb.widget.d.ts +48 -0
- package/dist/src/widget/breadcrumb.widget.js +72 -0
- package/dist/src/widget/breadcrumb.widget.js.map +1 -0
- package/dist/src/widget/page-title.widget.d.ts +33 -0
- package/dist/src/widget/page-title.widget.js +33 -0
- package/dist/src/widget/page-title.widget.js.map +1 -0
- package/dist/src/widget/widget.parser.d.ts +26 -0
- package/dist/src/widget/widget.parser.js +76 -0
- package/dist/src/widget/widget.parser.js.map +1 -0
- package/dist/src/widget/widget.registry.d.ts +23 -0
- package/dist/src/widget/widget.registry.js +42 -0
- package/dist/src/widget/widget.registry.js.map +1 -0
- package/package.json +63 -13
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route Matcher
|
|
3
|
+
*
|
|
4
|
+
* URLPattern-based route matching with support for:
|
|
5
|
+
* - Static routes (/about)
|
|
6
|
+
* - Dynamic segments (/projects/:id)
|
|
7
|
+
* - Wildcard/catch-all (future)
|
|
8
|
+
*
|
|
9
|
+
* Uses native URLPattern API (supported in all major browsers).
|
|
10
|
+
*/
|
|
11
|
+
/** Parse a URL path string into a URL object. Passes through URL objects unchanged. */
|
|
12
|
+
export function toUrl(url) {
|
|
13
|
+
return typeof url === 'string' ? new URL(url, 'http://url-parse') : url;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Route matcher using native URLPattern API.
|
|
17
|
+
*
|
|
18
|
+
* Routes are matched in order of specificity:
|
|
19
|
+
* 1. Exact static matches first
|
|
20
|
+
* 2. Dynamic segment matches
|
|
21
|
+
* 3. More specific patterns before less specific
|
|
22
|
+
*/
|
|
23
|
+
export class RouteMatcher {
|
|
24
|
+
compiledRoutes = [];
|
|
25
|
+
errorBoundaries = [];
|
|
26
|
+
statusPages = new Map();
|
|
27
|
+
errorHandler;
|
|
28
|
+
/**
|
|
29
|
+
* Initialize matcher with routes manifest.
|
|
30
|
+
* Routes should be pre-sorted by specificity in the manifest.
|
|
31
|
+
*/
|
|
32
|
+
constructor(manifest) {
|
|
33
|
+
this.errorBoundaries = manifest.errorBoundaries.toSorted((a, b) => b.pattern.length - a.pattern.length);
|
|
34
|
+
this.statusPages = manifest.statusPages;
|
|
35
|
+
this.errorHandler = manifest.errorHandler;
|
|
36
|
+
// Compile URLPatterns for all routes
|
|
37
|
+
for (const route of manifest.routes) {
|
|
38
|
+
try {
|
|
39
|
+
const pattern = new URLPattern({ pathname: route.pattern });
|
|
40
|
+
this.compiledRoutes.push({ route, pattern });
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
console.error(`[Router] Invalid pattern: ${route.pattern}`, e);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Match a URL against registered routes.
|
|
49
|
+
* Returns the first matching route or undefined.
|
|
50
|
+
*/
|
|
51
|
+
match(url) {
|
|
52
|
+
const urlObj = toUrl(url);
|
|
53
|
+
const searchParams = urlObj.searchParams;
|
|
54
|
+
for (const { route, pattern } of this.compiledRoutes) {
|
|
55
|
+
const result = pattern.exec(urlObj);
|
|
56
|
+
if (result) {
|
|
57
|
+
return {
|
|
58
|
+
route,
|
|
59
|
+
params: this.extractParams(result),
|
|
60
|
+
searchParams,
|
|
61
|
+
patternResult: result,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Find error boundary for a given pathname.
|
|
69
|
+
* Searches from most specific to least specific.
|
|
70
|
+
*/
|
|
71
|
+
findErrorBoundary(pathname) {
|
|
72
|
+
for (const boundary of this.errorBoundaries) {
|
|
73
|
+
const prefix = boundary.pattern.endsWith('/') ? boundary.pattern : boundary.pattern + '/';
|
|
74
|
+
if (pathname === boundary.pattern || pathname.startsWith(prefix)) {
|
|
75
|
+
return boundary;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get status-specific page (404, 401, 403).
|
|
82
|
+
*/
|
|
83
|
+
getStatusPage(status) {
|
|
84
|
+
return this.statusPages.get(status);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get generic error handler.
|
|
88
|
+
*/
|
|
89
|
+
getErrorHandler() {
|
|
90
|
+
return this.errorHandler;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Find a route by its exact pattern or by matching a pathname.
|
|
94
|
+
* Used for building route hierarchy.
|
|
95
|
+
*/
|
|
96
|
+
findRoute(patternOrPath) {
|
|
97
|
+
// First try exact pattern match
|
|
98
|
+
for (const { route } of this.compiledRoutes) {
|
|
99
|
+
if (route.pattern === patternOrPath) {
|
|
100
|
+
return route;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Then try to match as a URL path
|
|
104
|
+
const matched = this.match(toUrl(patternOrPath));
|
|
105
|
+
return matched?.route;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Extract params from URLPatternResult.
|
|
109
|
+
*/
|
|
110
|
+
extractParams(result) {
|
|
111
|
+
const groups = result.pathname.groups;
|
|
112
|
+
const params = {};
|
|
113
|
+
for (const [key, value] of Object.entries(groups)) {
|
|
114
|
+
if (value !== undefined) {
|
|
115
|
+
params[key] = value;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return params;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Convert file-based route path to URLPattern.
|
|
123
|
+
*
|
|
124
|
+
* Examples:
|
|
125
|
+
* - index.page.ts → /
|
|
126
|
+
* - about.page.ts → /about
|
|
127
|
+
* - projects/index.page.ts → /projects/:rest*
|
|
128
|
+
* - projects/[id].page.ts → /projects/:id
|
|
129
|
+
* - projects/[id]/tasks.page.ts → /projects/:id/tasks
|
|
130
|
+
*
|
|
131
|
+
* Directory index files (non-root) become wildcard catch-all routes.
|
|
132
|
+
* See ADR-0002: Wildcard Routes via Directory Index Convention.
|
|
133
|
+
*/
|
|
134
|
+
export function filePathToPattern(filePath) {
|
|
135
|
+
// Remove routes/ prefix and file extension
|
|
136
|
+
let pattern = filePath
|
|
137
|
+
.replace(/^routes\//, '')
|
|
138
|
+
.replace(/\.(page|error|redirect)\.(ts|html|md|css)$/, '');
|
|
139
|
+
// Detect non-root directory index before stripping
|
|
140
|
+
const isDirectoryIndex = pattern.endsWith('/index') && pattern !== 'index';
|
|
141
|
+
// Handle index files
|
|
142
|
+
pattern = pattern.replace(/\/index$/, '').replace(/^index$/, '');
|
|
143
|
+
// Convert [param] to :param
|
|
144
|
+
pattern = pattern.replace(/\[(?<param>[^\]]+)\]/g, ':$<param>');
|
|
145
|
+
// Ensure leading slash
|
|
146
|
+
pattern = '/' + pattern;
|
|
147
|
+
// Non-root directory index becomes wildcard catch-all
|
|
148
|
+
if (isDirectoryIndex) {
|
|
149
|
+
pattern += '/:rest*';
|
|
150
|
+
}
|
|
151
|
+
return pattern;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Determine route type from filename.
|
|
155
|
+
*/
|
|
156
|
+
export function getRouteType(filename) {
|
|
157
|
+
if (filename.endsWith('.page.ts') ||
|
|
158
|
+
filename.endsWith('.page.html') ||
|
|
159
|
+
filename.endsWith('.page.md')) {
|
|
160
|
+
return 'page';
|
|
161
|
+
}
|
|
162
|
+
if (filename.endsWith('.error.ts')) {
|
|
163
|
+
return 'error';
|
|
164
|
+
}
|
|
165
|
+
if (filename.endsWith('.redirect.ts')) {
|
|
166
|
+
return 'redirect';
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get the file extension type from a page filename.
|
|
172
|
+
*/
|
|
173
|
+
export function getPageFileType(filename) {
|
|
174
|
+
if (filename.endsWith('.page.ts'))
|
|
175
|
+
return 'ts';
|
|
176
|
+
if (filename.endsWith('.page.html'))
|
|
177
|
+
return 'html';
|
|
178
|
+
if (filename.endsWith('.page.md'))
|
|
179
|
+
return 'md';
|
|
180
|
+
if (filename.endsWith('.page.css'))
|
|
181
|
+
return 'css';
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Sort routes by specificity.
|
|
186
|
+
* Non-wildcards before wildcards, static before dynamic, longer paths first.
|
|
187
|
+
*/
|
|
188
|
+
export function sortRoutesBySpecificity(routes) {
|
|
189
|
+
return routes.toSorted((a, b) => {
|
|
190
|
+
const aSegments = a.pattern.split('/').filter(Boolean);
|
|
191
|
+
const bSegments = b.pattern.split('/').filter(Boolean);
|
|
192
|
+
// Wildcards always sort last
|
|
193
|
+
const aIsWildcard = aSegments.some((s) => s.endsWith('*') || s.endsWith('+'));
|
|
194
|
+
const bIsWildcard = bSegments.some((s) => s.endsWith('*') || s.endsWith('+'));
|
|
195
|
+
if (aIsWildcard !== bIsWildcard) {
|
|
196
|
+
return aIsWildcard ? 1 : -1;
|
|
197
|
+
}
|
|
198
|
+
// More segments = more specific
|
|
199
|
+
if (aSegments.length !== bSegments.length) {
|
|
200
|
+
return bSegments.length - aSegments.length;
|
|
201
|
+
}
|
|
202
|
+
// Compare segment by segment
|
|
203
|
+
for (let i = 0; i < aSegments.length; i++) {
|
|
204
|
+
const aIsDynamic = aSegments[i].startsWith(':');
|
|
205
|
+
const bIsDynamic = bSegments[i].startsWith(':');
|
|
206
|
+
// Static segments are more specific than dynamic
|
|
207
|
+
if (aIsDynamic !== bIsDynamic) {
|
|
208
|
+
return aIsDynamic ? 1 : -1;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return 0;
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=route.matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.matcher.js","sourceRoot":"","sources":["../../../src/route/route.matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Interface
|
|
3
|
+
*
|
|
4
|
+
* Minimal pluggable logger for surfacing errors from silent catch blocks.
|
|
5
|
+
* Structurally compatible with hardkore's StructuredLogger — any instance
|
|
6
|
+
* of that class satisfies this interface without an explicit dependency.
|
|
7
|
+
*
|
|
8
|
+
* Default: no-op (silent degradation). Call setLogger() at startup to wire in.
|
|
9
|
+
*/
|
|
10
|
+
export interface Logger {
|
|
11
|
+
error(msg: string, error?: Error): void;
|
|
12
|
+
warn(msg: string): void;
|
|
13
|
+
}
|
|
14
|
+
/** Module-level logger. Always callable — defaults to no-op. */
|
|
15
|
+
export declare const logger: Logger;
|
|
16
|
+
/** Replace the logger implementation. Call once at startup. */
|
|
17
|
+
export declare function setLogger(impl: Logger): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const noop = () => { };
|
|
2
|
+
/** Module-level logger. Always callable — defaults to no-op. */
|
|
3
|
+
export const logger = { error: noop, warn: noop };
|
|
4
|
+
/** Replace the logger implementation. Call once at startup. */
|
|
5
|
+
export function setLogger(impl) {
|
|
6
|
+
logger.error = impl.error.bind(impl);
|
|
7
|
+
logger.warn = impl.warn.bind(impl);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=logger.type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.type.js","sourceRoot":"","sources":["../../../src/type/logger.type.ts"],"names":[],"mappings":"AAcA,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;AAEtB,gEAAgE;AAChE,MAAM,CAAC,MAAM,MAAM,GAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAE1D,+DAA+D;AAC/D,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown Renderer Interface
|
|
3
|
+
*
|
|
4
|
+
* Implement this to provide custom markdown rendering.
|
|
5
|
+
* Used by MarkdownElement (browser) and SsrHtmlRouter (server).
|
|
6
|
+
*/
|
|
7
|
+
export interface MarkdownRenderer {
|
|
8
|
+
/**
|
|
9
|
+
* Initialize the renderer (e.g., load WASM).
|
|
10
|
+
* Called once before first render.
|
|
11
|
+
*/
|
|
12
|
+
init?(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Render markdown to HTML.
|
|
15
|
+
*
|
|
16
|
+
* **Security:** Output is assigned to `innerHTML` — the renderer must
|
|
17
|
+
* sanitize dangerous markup. See `doc/08-markdown-renderer.md`.
|
|
18
|
+
*/
|
|
19
|
+
render(markdown: string): string;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.type.js","sourceRoot":"","sources":["../../../src/type/markdown.type.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Types
|
|
3
|
+
*
|
|
4
|
+
* Native browser APIs only - no external dependencies.
|
|
5
|
+
* Follows islands architecture: pages = HTML, widgets = web components.
|
|
6
|
+
*/
|
|
7
|
+
/** Parameters extracted from URL patterns */
|
|
8
|
+
export type RouteParams = Readonly<Record<string, string>>;
|
|
9
|
+
/** Immutable route context built once per navigation, shared across the render pipeline. */
|
|
10
|
+
export interface RouteInfo {
|
|
11
|
+
/** Actual URL path (e.g., '/projects/123') */
|
|
12
|
+
readonly pathname: string;
|
|
13
|
+
/** Matched route pattern (e.g., '/projects/:id') */
|
|
14
|
+
readonly pattern: string;
|
|
15
|
+
/** URL parameters extracted by the router */
|
|
16
|
+
readonly params: RouteParams;
|
|
17
|
+
/** Query string parameters */
|
|
18
|
+
readonly searchParams: URLSearchParams;
|
|
19
|
+
}
|
|
20
|
+
/** Supported file patterns in file-based routing */
|
|
21
|
+
export type RouteFileType = 'page' | 'error' | 'redirect';
|
|
22
|
+
/** Redirect configuration */
|
|
23
|
+
export interface RedirectConfig {
|
|
24
|
+
to: string;
|
|
25
|
+
status: 301 | 302;
|
|
26
|
+
}
|
|
27
|
+
/** Available files for a route */
|
|
28
|
+
export interface RouteFiles {
|
|
29
|
+
/** TypeScript module path (.page.ts) */
|
|
30
|
+
ts?: string;
|
|
31
|
+
/** HTML template path (.page.html) */
|
|
32
|
+
html?: string;
|
|
33
|
+
/** Markdown content path (.page.md) */
|
|
34
|
+
md?: string;
|
|
35
|
+
/** CSS stylesheet path (.page.css) */
|
|
36
|
+
css?: string;
|
|
37
|
+
}
|
|
38
|
+
/** Route configuration for a single route */
|
|
39
|
+
export interface RouteConfig {
|
|
40
|
+
/** URLPattern pathname pattern (e.g., '/projects/:id') */
|
|
41
|
+
pattern: string;
|
|
42
|
+
/** Type of route file */
|
|
43
|
+
type: RouteFileType;
|
|
44
|
+
/** Module path for dynamic import (primary file based on precedence) */
|
|
45
|
+
modulePath: string;
|
|
46
|
+
/** Available files for this route */
|
|
47
|
+
files?: RouteFiles;
|
|
48
|
+
/** Parent route pattern for nested routes */
|
|
49
|
+
parent?: string;
|
|
50
|
+
/** HTTP status code (for status-specific pages like 404, 401, 403) */
|
|
51
|
+
statusCode?: number;
|
|
52
|
+
}
|
|
53
|
+
/** Result of matching a URL against routes */
|
|
54
|
+
export interface MatchedRoute {
|
|
55
|
+
/** The matched route configuration */
|
|
56
|
+
readonly route: RouteConfig;
|
|
57
|
+
/** Extracted URL parameters */
|
|
58
|
+
readonly params: RouteParams;
|
|
59
|
+
/** Query string parameters from the matched URL */
|
|
60
|
+
readonly searchParams?: URLSearchParams;
|
|
61
|
+
/** The URLPatternResult from matching */
|
|
62
|
+
readonly patternResult?: URLPatternResult;
|
|
63
|
+
}
|
|
64
|
+
/** Error boundary configuration */
|
|
65
|
+
export interface ErrorBoundary {
|
|
66
|
+
/** Pattern prefix this error boundary handles */
|
|
67
|
+
pattern: string;
|
|
68
|
+
/** Module path for the error handler */
|
|
69
|
+
modulePath: string;
|
|
70
|
+
}
|
|
71
|
+
/** Generated routes manifest from build tool */
|
|
72
|
+
export interface RoutesManifest {
|
|
73
|
+
/** All page routes */
|
|
74
|
+
routes: RouteConfig[];
|
|
75
|
+
/** Error boundaries by pattern prefix */
|
|
76
|
+
errorBoundaries: ErrorBoundary[];
|
|
77
|
+
/** Status-specific pages (404, 401, 403) */
|
|
78
|
+
statusPages: Map<number, RouteConfig>;
|
|
79
|
+
/** Generic error handler */
|
|
80
|
+
errorHandler?: RouteConfig;
|
|
81
|
+
/** Pre-bundled module loaders keyed by module path (for SPA bundles) */
|
|
82
|
+
moduleLoaders?: Record<string, () => Promise<unknown>>;
|
|
83
|
+
}
|
|
84
|
+
/** Router state for history management */
|
|
85
|
+
export interface RouterState {
|
|
86
|
+
/** Current URL pathname */
|
|
87
|
+
pathname: string;
|
|
88
|
+
/** Extracted route parameters */
|
|
89
|
+
params: RouteParams;
|
|
90
|
+
/** Scroll position to restore */
|
|
91
|
+
scrollY?: number;
|
|
92
|
+
}
|
|
93
|
+
/** Navigation options */
|
|
94
|
+
export interface NavigateOptions {
|
|
95
|
+
/** Replace current history entry instead of pushing */
|
|
96
|
+
replace?: boolean;
|
|
97
|
+
/** State to store in history */
|
|
98
|
+
state?: RouterState;
|
|
99
|
+
/** Hash to scroll to after navigation */
|
|
100
|
+
hash?: string;
|
|
101
|
+
}
|
|
102
|
+
/** Router event types */
|
|
103
|
+
export type RouterEventType = 'navigate' | 'error' | 'load';
|
|
104
|
+
/** Router event payload */
|
|
105
|
+
export interface RouterEvent {
|
|
106
|
+
type: RouterEventType;
|
|
107
|
+
pathname: string;
|
|
108
|
+
params: RouteParams;
|
|
109
|
+
error?: Error;
|
|
110
|
+
}
|
|
111
|
+
/** Router event listener */
|
|
112
|
+
export type RouterEventListener = (event: RouterEvent) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.type.js","sourceRoot":"","sources":["../../../src/type/route.type.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget System - Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Widgets are data-fetching components that work across three contexts:
|
|
5
|
+
* 1. /md/ (LLMs) - Returns markdown with JSON data
|
|
6
|
+
* 2. SSR/HTML - Pre-fetched data embedded in custom element
|
|
7
|
+
* 3. SPA/Browser - Custom element fetches and hydrates
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Parsed widget block from markdown.
|
|
11
|
+
* Represents a fenced code block with widget syntax.
|
|
12
|
+
*/
|
|
13
|
+
export interface ParsedWidgetBlock {
|
|
14
|
+
/** Full matched string including fences */
|
|
15
|
+
fullMatch: string;
|
|
16
|
+
/** Widget name extracted from widget:{name} */
|
|
17
|
+
widgetName: string;
|
|
18
|
+
/** Parsed JSON params, or null if empty/invalid */
|
|
19
|
+
params: Record<string, unknown> | null;
|
|
20
|
+
/** Parse error message if params JSON was invalid */
|
|
21
|
+
parseError?: string;
|
|
22
|
+
/** Start index in original markdown */
|
|
23
|
+
startIndex: number;
|
|
24
|
+
/** End index in original markdown */
|
|
25
|
+
endIndex: number;
|
|
26
|
+
}
|
|
27
|
+
/** Custom element tag name for widgets: `widget-{name}` */
|
|
28
|
+
export type WidgetTagName = `widget-${string}`;
|
|
29
|
+
/** SPA rendering mode. */
|
|
30
|
+
export type SpaMode = 'none' | 'leaf' | 'root' | 'only';
|
|
31
|
+
/**
|
|
32
|
+
* Widget manifest entry for code generation.
|
|
33
|
+
*/
|
|
34
|
+
export interface WidgetManifestEntry {
|
|
35
|
+
/** Widget name in kebab-case */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Path to widget module file */
|
|
38
|
+
modulePath: string;
|
|
39
|
+
/** Custom element tag name (widget-{name}) */
|
|
40
|
+
tagName: WidgetTagName;
|
|
41
|
+
/** Discovered/declared companion file paths (html, md, css) */
|
|
42
|
+
files?: {
|
|
43
|
+
html?: string;
|
|
44
|
+
md?: string;
|
|
45
|
+
css?: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generated widgets manifest structure.
|
|
50
|
+
*/
|
|
51
|
+
export interface WidgetsManifest {
|
|
52
|
+
widgets: WidgetManifestEntry[];
|
|
53
|
+
/** Pre-bundled module loaders keyed by module path (for SPA bundles) */
|
|
54
|
+
moduleLoaders?: Record<string, () => Promise<unknown>>;
|
|
55
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget System - Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Widgets are data-fetching components that work across three contexts:
|
|
5
|
+
* 1. /md/ (LLMs) - Returns markdown with JSON data
|
|
6
|
+
* 2. SSR/HTML - Pre-fetched data embedded in custom element
|
|
7
|
+
* 3. SPA/Browser - Custom element fetches and hydrates
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=widget.type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.type.js","sourceRoot":"","sources":["../../../src/type/widget.type.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core HTML utilities for emroute
|
|
3
|
+
*/
|
|
4
|
+
/** HTML attribute name marking a widget as server-rendered (skip client getData + render). */
|
|
5
|
+
export declare const SSR_ATTR = "ssr";
|
|
6
|
+
/** HTML attribute name for lazy-loading widgets via IntersectionObserver. */
|
|
7
|
+
export declare const LAZY_ATTR = "lazy";
|
|
8
|
+
/** Server-safe base class: HTMLElement in browser, SSR mock on server. */
|
|
9
|
+
export declare const HTMLElementBase: {
|
|
10
|
+
new (): HTMLElement;
|
|
11
|
+
prototype: HTMLElement;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Escape HTML entities for safe display.
|
|
15
|
+
*/
|
|
16
|
+
export declare function escapeHtml(text: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Unescape HTML entities back to plain text (server-side, no DOM).
|
|
19
|
+
*/
|
|
20
|
+
export declare function unescapeHtml(text: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Wrap CSS in a `@scope` rule scoped to the widget's custom element tag.
|
|
23
|
+
* Used by `WidgetComponent.renderHTML()` for companion CSS files.
|
|
24
|
+
*/
|
|
25
|
+
export declare function scopeWidgetCss(css: string, widgetName: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Status code to message mapping.
|
|
28
|
+
*/
|
|
29
|
+
export declare const STATUS_MESSAGES: Record<number, string>;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core HTML utilities for emroute
|
|
3
|
+
*/
|
|
4
|
+
/** HTML attribute name marking a widget as server-rendered (skip client getData + render). */
|
|
5
|
+
export const SSR_ATTR = 'ssr';
|
|
6
|
+
/** HTML attribute name for lazy-loading widgets via IntersectionObserver. */
|
|
7
|
+
export const LAZY_ATTR = 'lazy';
|
|
8
|
+
/**
|
|
9
|
+
* SSR-compatible ShadowRoot mock.
|
|
10
|
+
* Provides a 1-to-1 subset of the browser ShadowRoot API for server-side rendering.
|
|
11
|
+
*/
|
|
12
|
+
class SsrShadowRoot {
|
|
13
|
+
host;
|
|
14
|
+
_innerHTML = '';
|
|
15
|
+
constructor(host) {
|
|
16
|
+
this.host = host;
|
|
17
|
+
}
|
|
18
|
+
get innerHTML() {
|
|
19
|
+
return this._innerHTML;
|
|
20
|
+
}
|
|
21
|
+
set innerHTML(value) {
|
|
22
|
+
this._innerHTML = value;
|
|
23
|
+
}
|
|
24
|
+
setHTMLUnsafe(html, _options) {
|
|
25
|
+
this._innerHTML = html;
|
|
26
|
+
}
|
|
27
|
+
append(..._nodes) {
|
|
28
|
+
// On the server, append is a no-op — SSR content is already serialized via innerHTML.
|
|
29
|
+
}
|
|
30
|
+
querySelector(_selector) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
querySelectorAll(_selector) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
get childNodes() {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
get firstChild() {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* SSR-compatible HTMLElement mock.
|
|
45
|
+
* Provides a 1-to-1 subset of the browser HTMLElement API for server-side rendering.
|
|
46
|
+
* Methods that require DOM parsing (querySelector, childNodes) return empty results —
|
|
47
|
+
* SSR code should use innerHTML for content, not DOM traversal.
|
|
48
|
+
*/
|
|
49
|
+
class SsrHTMLElement {
|
|
50
|
+
_innerHTML = '';
|
|
51
|
+
_shadowRoot = null;
|
|
52
|
+
_attributes = new Map();
|
|
53
|
+
// Accept any CSS property assignment without error
|
|
54
|
+
style = new Proxy({}, {
|
|
55
|
+
set(_target, _prop, _value) {
|
|
56
|
+
return true;
|
|
57
|
+
},
|
|
58
|
+
get(_target, prop) {
|
|
59
|
+
if (typeof prop === 'string')
|
|
60
|
+
return '';
|
|
61
|
+
return undefined;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
get innerHTML() {
|
|
65
|
+
return this._innerHTML;
|
|
66
|
+
}
|
|
67
|
+
set innerHTML(value) {
|
|
68
|
+
this._innerHTML = value;
|
|
69
|
+
}
|
|
70
|
+
get shadowRoot() {
|
|
71
|
+
return this._shadowRoot;
|
|
72
|
+
}
|
|
73
|
+
get childNodes() {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
get firstChild() {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
get attributes() {
|
|
80
|
+
const attrs = [];
|
|
81
|
+
for (const [name, value] of this._attributes) {
|
|
82
|
+
attrs.push({ name, value });
|
|
83
|
+
}
|
|
84
|
+
return attrs;
|
|
85
|
+
}
|
|
86
|
+
attachShadow(_init) {
|
|
87
|
+
this._shadowRoot = new SsrShadowRoot(this);
|
|
88
|
+
return this._shadowRoot;
|
|
89
|
+
}
|
|
90
|
+
getAttribute(name) {
|
|
91
|
+
return this._attributes.get(name) ?? null;
|
|
92
|
+
}
|
|
93
|
+
setAttribute(name, value) {
|
|
94
|
+
this._attributes.set(name, value);
|
|
95
|
+
}
|
|
96
|
+
removeAttribute(name) {
|
|
97
|
+
this._attributes.delete(name);
|
|
98
|
+
}
|
|
99
|
+
hasAttribute(name) {
|
|
100
|
+
return this._attributes.has(name);
|
|
101
|
+
}
|
|
102
|
+
querySelector(_selector) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
querySelectorAll(_selector) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
append(..._nodes) {
|
|
109
|
+
// No-op on server — use innerHTML for content
|
|
110
|
+
}
|
|
111
|
+
appendChild(node) {
|
|
112
|
+
return node;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Server-safe base class: HTMLElement in browser, SSR mock on server. */
|
|
116
|
+
export const HTMLElementBase = globalThis.HTMLElement ??
|
|
117
|
+
SsrHTMLElement;
|
|
118
|
+
/**
|
|
119
|
+
* Escape HTML entities for safe display.
|
|
120
|
+
*/
|
|
121
|
+
export function escapeHtml(text) {
|
|
122
|
+
return text
|
|
123
|
+
.replaceAll('&', '&')
|
|
124
|
+
.replaceAll('<', '<')
|
|
125
|
+
.replaceAll('>', '>')
|
|
126
|
+
.replaceAll('"', '"')
|
|
127
|
+
.replaceAll("'", ''')
|
|
128
|
+
.replaceAll('`', '`');
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Unescape HTML entities back to plain text (server-side, no DOM).
|
|
132
|
+
*/
|
|
133
|
+
export function unescapeHtml(text) {
|
|
134
|
+
return text
|
|
135
|
+
.replaceAll('`', '`')
|
|
136
|
+
.replaceAll(''', "'")
|
|
137
|
+
.replaceAll('"', '"')
|
|
138
|
+
.replaceAll('>', '>')
|
|
139
|
+
.replaceAll('<', '<')
|
|
140
|
+
.replaceAll('&', '&');
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Wrap CSS in a `@scope` rule scoped to the widget's custom element tag.
|
|
144
|
+
* Used by `WidgetComponent.renderHTML()` for companion CSS files.
|
|
145
|
+
*/
|
|
146
|
+
export function scopeWidgetCss(css, widgetName) {
|
|
147
|
+
return `@scope (widget-${widgetName}) {\n${css}\n}`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Status code to message mapping.
|
|
151
|
+
*/
|
|
152
|
+
export const STATUS_MESSAGES = {
|
|
153
|
+
401: 'Unauthorized',
|
|
154
|
+
403: 'Forbidden',
|
|
155
|
+
404: 'Not Found',
|
|
156
|
+
500: 'Internal Server Error',
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=html.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.util.js","sourceRoot":"","sources":["../../../src/util/html.util.ts"],"names":[],"mappings":"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"}
|