@markless/router 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { extname, isAbsolute, normalize, relative, resolve } from "pathe";
2
2
  //#region src/typescript-plugin/index.ts
3
- const PAGE_EXTENSIONS = new Set([".tsrx", ".mdx"]);
3
+ const PAGE_EXTENSIONS = /* @__PURE__ */ new Set([".tsrx", ".mdx"]);
4
4
  function init(modules) {
5
5
  const typeScript = modules.typescript;
6
6
  return { create(info) {
@@ -15,7 +15,8 @@ function init(modules) {
15
15
  const projectRoot = getProjectRoot(typeScript, info);
16
16
  const pagesDir = resolvePagesDir(getConfiguredProjectRoot(info) ?? projectRoot, pluginConfig);
17
17
  proxy.getCompletionsAtPosition = (fileName, position, options, formattingSettings) => {
18
- return withRouteHrefCompletions(typeScript, info, pagesDir, fileName, position, languageService.getCompletionsAtPosition(fileName, position, options, formattingSettings));
18
+ const completions = languageService.getCompletionsAtPosition(fileName, position, options, formattingSettings);
19
+ return withRouteHrefCompletions(typeScript, info, pagesDir, fileName, position, completions);
19
20
  };
20
21
  return proxy;
21
22
  } };
@@ -57,7 +58,7 @@ function isRouteHrefCompletionContext(typeScript, info, fileName, position) {
57
58
  }
58
59
  function isInsideStringLikeToken(typeScript, source, position) {
59
60
  const scanner = typeScript.createScanner(typeScript.ScriptTarget.Latest, false, typeScript.LanguageVariant.JSX, source);
60
- const stringLikeTokens = new Set([
61
+ const stringLikeTokens = /* @__PURE__ */ new Set([
61
62
  typeScript.SyntaxKind.StringLiteral,
62
63
  typeScript.SyntaxKind.NoSubstitutionTemplateLiteral,
63
64
  typeScript.SyntaxKind.TemplateHead,
@@ -164,13 +165,15 @@ function routeHrefCompletion(fileId) {
164
165
  }
165
166
  function isReservedOrUnsupportedPage(fileId) {
166
167
  const extension = extname(fileId);
167
- const routeFile = normalize(fileId.slice(0, -extension.length));
168
+ const withoutExtension = fileId.slice(0, -extension.length);
169
+ const routeFile = normalize(withoutExtension);
168
170
  const segments = routeFile === "." ? [] : routeFile.split("/").filter(Boolean);
169
- return segments[0] === "api" || segments.length === 1 && (segments[0] === "404" || segments[0] === "500");
171
+ return segments.length === 1 && (segments[0] === "404" || segments[0] === "500");
170
172
  }
171
173
  function routeFromFileId(fileId) {
172
174
  const extension = extname(fileId);
173
- const routeFile = normalize(fileId.slice(0, -extension.length));
175
+ const withoutExtension = fileId.slice(0, -extension.length);
176
+ const routeFile = normalize(withoutExtension);
174
177
  const segments = routeFile === "." ? [] : routeFile.split("/").filter(Boolean);
175
178
  if (segments.at(-1) === "index") segments.pop();
176
179
  const params = [];
@@ -1,4 +1,3 @@
1
1
  //#region src/vite/entries/route-href.d.ts
2
- declare function __marklessRouteHref(pattern: string, params: Readonly<Record<string, unknown>>): string;
3
- //#endregion
4
- export { __marklessRouteHref };
2
+ export declare function __marklessRouteHref(pattern: string, params: Readonly<Record<string, unknown>>): string;
3
+ //#endregion
@@ -1,18 +1,2 @@
1
- //#region src/vite/entries/route-href.ts
2
- const routeParamPattern = /\[\.\.\.([A-Za-z_$][\w$]*)\]|\[([A-Za-z_$][\w$]*)\]/g;
3
- function __marklessRouteHref(pattern, params) {
4
- return pattern.replace(routeParamPattern, (_match, catchAll, dynamic) => {
5
- const name = catchAll || dynamic;
6
- const value = params?.[name];
7
- if (catchAll) return encodeCatchAllParam(pattern, value);
8
- if (value === null || value === void 0) throw new Error(`Typed route error: ${pattern} requires params:\n- ${name}`);
9
- return encodeURIComponent(String(value));
10
- });
11
- }
12
- function encodeCatchAllParam(pattern, value) {
13
- const segments = Array.isArray(value) ? value : value === null || value === void 0 ? [] : String(value).split("/");
14
- if (segments.length === 0 || segments.some((segment) => String(segment) === "")) throw new Error(`Typed route error: ${pattern} requires a non-empty catch-all param.`);
15
- return segments.map((segment) => encodeURIComponent(String(segment))).join("/");
16
- }
17
- //#endregion
1
+ import { t as __marklessRouteHref } from "../route-href-CGooO_g6.js";
18
2
  export { __marklessRouteHref };
@@ -1,8 +1,7 @@
1
1
  //#region src/vite/runtime/create-route-discovery.d.ts
2
- interface RouteDiscovery {
2
+ export interface RouteDiscovery {
3
3
  readonly pageModuleLoaders: Record<string, () => Promise<unknown>>;
4
4
  readonly routeFileIds: readonly string[];
5
5
  }
6
- declare function createRouteDiscovery(discoveredPageModuleLoaders: Record<string, () => Promise<unknown>>): RouteDiscovery;
7
- //#endregion
8
- export { RouteDiscovery, createRouteDiscovery };
6
+ export declare function createRouteDiscovery(discoveredPageModuleLoaders: Record<string, () => Promise<unknown>>): RouteDiscovery;
7
+ //#endregion
@@ -1,4 +1,4 @@
1
- import { i as normalizeRouteFileId } from "../../route-manifest-DPgGIyrS.js";
1
+ import { o as normalizeRouteFileId } from "../../route-manifest-DMizh42B.js";
2
2
  //#region src/vite/runtime/create-route-discovery.ts
3
3
  function createRouteDiscovery(discoveredPageModuleLoaders) {
4
4
  const pageModuleLoaders = Object.fromEntries(Object.entries(discoveredPageModuleLoaders).map(([file, loader]) => [normalizeRouteFileId(file), loader]));
@@ -1,21 +1,43 @@
1
+ import { z as RouteManifest } from "../../index-BjxpxRL7.js";
1
2
  import { ModulePreloadInput } from "@markless/web/render-to-string";
2
-
3
3
  //#region src/vite/runtime/create-server-entry.d.ts
4
- interface ServerEntryOptions {
4
+ export interface ServerEntryOptions {
5
5
  readonly dev?: boolean;
6
+ readonly base?: string;
6
7
  readonly navigationEntryPath?: string;
8
+ readonly prefetch?: boolean;
7
9
  readonly resumeEntryPath?: string;
8
10
  readonly prerenderWakeEntryPath?: string;
9
11
  readonly routeModulePreloads?: Record<string, readonly ModulePreloadInput[]>;
10
12
  readonly routeSsrModulePreloads?: Record<string, readonly ModulePreloadInput[]>;
11
13
  readonly routeStylesheets?: Record<string, readonly string[]>;
14
+ readonly documentStylesheets?: readonly string[];
15
+ readonly importMap?: string;
12
16
  readonly documentModuleLoader: (() => Promise<unknown>) | undefined;
17
+ readonly documentNavigation?: 'client' | 'document';
13
18
  readonly pageModuleLoaders: Record<string, () => Promise<unknown>>;
14
19
  readonly routeFileIds: readonly string[];
15
20
  readonly render?: 'streaming' | 'blocking';
21
+ readonly navigation?: 'fragment' | 'render';
22
+ readonly fragmentEntryPath?: string;
23
+ readonly fragmentEntryImports?: readonly string[];
24
+ readonly fragmentNavigationSource?: string;
25
+ readonly fragmentNavigationRunSource?: string;
26
+ readonly linkBridgePaths?: readonly [withoutHashLinks: string, withHashLinks: string];
16
27
  }
17
- declare function createServerEntry(options: ServerEntryOptions): {
28
+ export type LinkBridgeOptions = Pick<ServerEntryOptions, 'base' | 'navigationEntryPath' | 'prefetch' | 'documentNavigation' | 'navigation' | 'fragmentEntryPath' | 'fragmentEntryImports' | 'fragmentNavigationSource' | 'fragmentNavigationRunSource' | 'routeFileIds'> & {
29
+ readonly debug?: boolean;
30
+ };
31
+ /** The link bridge modules a built app's pages import; the build writes them as static client files. */
32
+ export declare function routerLinkBridgeModules(options: LinkBridgeOptions, manifest?: RouteManifest): LinkBridgeFiles | undefined;
33
+ export declare function createServerEntry(options: ServerEntryOptions): {
18
34
  fetch: (request: Request) => Promise<Response>;
35
+ linkBridgeModules: LinkBridgeFiles | undefined;
19
36
  };
20
- //#endregion
21
- export { ServerEntryOptions, createServerEntry };
37
+ export interface LinkBridgeModule {
38
+ readonly path: string;
39
+ readonly source: string;
40
+ }
41
+ /** The two page-imported bridges (without and with '#/' links), then any file they load later. */
42
+ export type LinkBridgeFiles = readonly [withoutHashLinks: LinkBridgeModule, withHashLinks: LinkBridgeModule, ...later: LinkBridgeModule[]];
43
+ //#endregion
@@ -1,400 +1,2 @@
1
- import { t as __marklessDebugBootstrapSource } from "../../debug-channel-CSzo-Zj8.js";
2
- import { i as normalizeRouteFileId, n as matchRouteManifest, t as buildRouteManifestFromFileIds } from "../../route-manifest-DPgGIyrS.js";
3
- import { renderToString } from "@markless/web/render-to-string";
4
- import { renderToStream } from "@markless/web/render-to-stream";
5
- import { normalizeMarklessDevError, renderMarklessDevErrorDocument } from "@markless/bundler/dev-error";
6
- //#region src/vite/runtime/create-server-entry.ts
7
- const DOCUMENT_CHILDREN_PLACEHOLDER = "__markless_router_document_children__";
8
- function createServerEntry(options) {
9
- const manifest = buildRouteManifestFromFileIds(options.routeFileIds);
10
- assertCurrentRouteAssets(options);
11
- async function fetch(request) {
12
- const url = new URL(request.url);
13
- if (isNitroApiPathname(url.pathname)) return new Response("Not found", { status: 404 });
14
- const match = matchRouteManifest(url.pathname, manifest);
15
- if (!match) return renderStatusPage(url, manifest.statusPages.notFound, 404, "Not found");
16
- try {
17
- return await renderPage(url, match.route.file, match.params, 200);
18
- } catch (error) {
19
- console.error("[markless-router] page render failed:", error);
20
- if (options.dev) return renderDevelopmentError(url, error);
21
- try {
22
- return await renderStatusPage(url, manifest.statusPages.error, 500, "Internal Server Error");
23
- } catch (errorPageError) {
24
- console.error("[markless-router] error page render failed:", errorPageError);
25
- return new Response("Internal Server Error", {
26
- status: 500,
27
- headers: { "content-type": "text/plain;charset=utf-8" }
28
- });
29
- }
30
- }
31
- }
32
- function renderDevelopmentError(url, error) {
33
- const headers = {
34
- "cache-control": "no-store",
35
- "content-type": "text/html;charset=utf-8"
36
- };
37
- try {
38
- const payload = normalizeMarklessDevError(error, { id: `navigation:${url.pathname}` });
39
- return new Response(renderMarklessDevErrorDocument(payload), {
40
- status: 500,
41
- headers
42
- });
43
- } catch {
44
- return new Response(escapeHtml(flattenError(error)), {
45
- status: 500,
46
- headers: {
47
- ...headers,
48
- "content-type": "text/plain;charset=utf-8"
49
- }
50
- });
51
- }
52
- }
53
- async function renderStatusPage(url, file, status, fallbackText) {
54
- if (!file) return new Response(fallbackText, { status });
55
- return renderPage(url, file, {}, status);
56
- }
57
- async function renderPage(url, file, params, status) {
58
- const loadPageModule = options.pageModuleLoaders[file];
59
- if (!loadPageModule) return new Response(`Page module not found: ${file}`, { status: 500 });
60
- const pageModule = await loadPageModule();
61
- const pageProps = {
62
- params,
63
- url: {
64
- href: url.href,
65
- pathname: url.pathname,
66
- search: url.search
67
- },
68
- status
69
- };
70
- const documentModule = options.documentModuleLoader ? await options.documentModuleLoader() : void 0;
71
- const headers = { "content-type": "text/html;charset=utf-8" };
72
- const baseArtifact = pageModule.default;
73
- const renderSsr = baseArtifact?.renderSsr ?? pageModule.marklessRenderSsr;
74
- if (!renderSsr) {
75
- const shell = await renderDocumentShell(documentModule, pageProps, "");
76
- const message = `Page module must export an Markless compiled artifact: ${escapeHtml(file)}`;
77
- return new Response(fillDocumentChildren(shell, message), {
78
- status,
79
- headers
80
- });
81
- }
82
- const pageArtifact = routedPageArtifact(renderSsr, baseArtifact, pageProps, file, options.navigationEntryPath, options.routeStylesheets?.[file]);
83
- const routedArtifact = options.prerenderWakeEntryPath ? {
84
- ...pageArtifact,
85
- prerenderWakeModuleUrl: options.prerenderWakeEntryPath
86
- } : pageArtifact;
87
- const renderOptions = {
88
- props: pageProps,
89
- resumeModuleUrl: options.resumeEntryPath ?? baseArtifact?.resumeModuleUrl,
90
- modulePreloads: (html) => modulePreloadsForPage(file, html, pageProps.url.href, manifest, options.routeModulePreloads, options.routeSsrModulePreloads)
91
- };
92
- if (options.render === "blocking") {
93
- const pageHtml = splitLeadingHeadHtml(await renderToString(routedArtifact, renderOptions));
94
- const shell = await renderDocumentShell(documentModule, pageProps, pageHtml.headHtml);
95
- return new Response(fillDocumentChildren(shell, pageHtml.bodyHtml), {
96
- status,
97
- headers
98
- });
99
- }
100
- const stream = await renderToStream(routedArtifact, renderOptions);
101
- const pageHtml = splitLeadingHeadHtml(stream.shell);
102
- const shell = await renderDocumentShell(documentModule, pageProps, pageHtml.headHtml);
103
- if (stream.pendingArmCount === 0) return new Response(fillDocumentChildren(shell, pageHtml.bodyHtml), {
104
- status,
105
- headers
106
- });
107
- const placeholderAt = shell.indexOf(DOCUMENT_CHILDREN_PLACEHOLDER);
108
- const prefix = placeholderAt === -1 ? shell : shell.slice(0, placeholderAt) + pageHtml.bodyHtml;
109
- const suffix = placeholderAt === -1 ? "" : shell.slice(placeholderAt + 37);
110
- const encoder = new TextEncoder();
111
- let cancelled = false;
112
- let completed = false;
113
- const body = new ReadableStream({
114
- async start(controller) {
115
- controller.enqueue(encoder.encode(prefix));
116
- try {
117
- for await (const chunk of stream.appends()) {
118
- if (cancelled) return;
119
- controller.enqueue(encoder.encode(chunk));
120
- }
121
- } catch (error) {
122
- if (cancelled) return;
123
- console.error("[markless-router] streaming settle failed:", error);
124
- controller.error(error);
125
- completed = true;
126
- return;
127
- }
128
- if (cancelled) return;
129
- controller.enqueue(encoder.encode(suffix));
130
- controller.close();
131
- completed = true;
132
- },
133
- cancel(reason) {
134
- if (completed) return;
135
- cancelled = true;
136
- stream.cancel(reason);
137
- }
138
- });
139
- return new Response(body, {
140
- status,
141
- headers
142
- });
143
- }
144
- return { fetch };
145
- }
146
- function flattenError(error) {
147
- if (error instanceof Error) return error.message;
148
- if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") return error.message;
149
- return String(error);
150
- }
151
- function assertCurrentRouteAssets(options) {
152
- if (options.routeStylesheets === void 0) return;
153
- const routeMaps = [
154
- ["navigation", options.routeModulePreloads ?? {}],
155
- ["SSR", options.routeSsrModulePreloads ?? {}],
156
- ["style", options.routeStylesheets]
157
- ];
158
- const expected = [...new Set(options.routeFileIds.map(normalizeRouteFileId))].filter((file) => /^pages\/.+\.(?:tsrx|mdx)$/.test(file)).toSorted();
159
- for (const [label, routes] of routeMaps) {
160
- const actual = Object.keys(routes).toSorted();
161
- if (JSON.stringify(actual) !== JSON.stringify(expected)) throw new Error(`Markless Router ${label} client-asset routes are stale; expected ${JSON.stringify(expected)}, received ${JSON.stringify(actual)}. Rebuild the client environment before the server environment.`);
162
- }
163
- }
164
- function routedPageArtifact(renderSsr, baseArtifact, pageProps, file, navigationEntryPath, stylesheetHrefs) {
165
- const headInjections = [...baseArtifact?.headInjections ?? [], ...(stylesheetHrefs ?? []).map((href) => ({
166
- tag: "link",
167
- location: "head",
168
- attributes: {
169
- rel: "stylesheet",
170
- href
171
- }
172
- }))];
173
- return {
174
- resumeModuleUrl: baseArtifact?.resumeModuleUrl,
175
- inlineResumerSources: baseArtifact?.inlineResumerSources,
176
- storageSeeds: baseArtifact?.storageSeeds,
177
- ...headInjections.length > 0 ? { headInjections } : {},
178
- async renderSsr(renderProps, renderContext) {
179
- const output = await renderSsr(renderProps ?? pageProps, renderContext);
180
- if (!output) return { html: "" };
181
- const routeScript = output.state || output.view ? renderRouteScript(file) : "";
182
- const linkBridge = navigationEntryPath ? renderLinkBridgeScript(navigationEntryPath) : "";
183
- const stateWithProps = withPagePropsCell(output.state, pageProps);
184
- return routeScript || linkBridge || stateWithProps !== output.state ? {
185
- ...output,
186
- state: stateWithProps,
187
- html: `${output.html}${routeScript}${linkBridge}`
188
- } : output;
189
- }
190
- };
191
- }
192
- function withPagePropsCell(state, props) {
193
- if (!state || typeof state !== "object") return state;
194
- const cells = state.cells;
195
- if (!Array.isArray(cells) || cells.some((cell) => cell?.graphNodeId === "prop:props")) return state;
196
- return {
197
- ...state,
198
- cells: [...cells, {
199
- graphNodeId: "prop:props",
200
- name: "props",
201
- valueKind: "object",
202
- directValue: props
203
- }]
204
- };
205
- }
206
- function modulePreloadsForPage(file, html, baseHref, manifest, routeModulePreloads, routeSsrModulePreloads) {
207
- const preloads = [];
208
- const seen = /* @__PURE__ */ new Set();
209
- addModulePreloads(preloads, seen, routeSsrModulePreloads?.[file]);
210
- if (!routeModulePreloads || !html.includes("data-markless-router-link")) return preloads.length > 0 ? preloads : void 0;
211
- for (const href of routerLinkHrefs(html)) {
212
- const url = parseSameOriginUrl(href, baseHref);
213
- const match = url && matchRouteManifest(url.pathname, manifest);
214
- addModulePreloads(preloads, seen, match && routeModulePreloads[match.route.file]);
215
- }
216
- return preloads.length > 0 ? preloads : void 0;
217
- }
218
- function routerLinkHrefs(html) {
219
- return [...html.matchAll(/<a\b(?=[^>]*\bdata-markless-router-link(?:[\s=>]|$))(?=[^>]*\bhref="([^"]*)")[^>]*>/g)].map((match) => unescapeHtmlAttribute(match[1] ?? ""));
220
- }
221
- function parseSameOriginUrl(href, base) {
222
- try {
223
- const current = new URL(base);
224
- const url = new URL(href, current);
225
- return url.origin === current.origin ? url : void 0;
226
- } catch {
227
- return;
228
- }
229
- }
230
- function unescapeHtmlAttribute(value) {
231
- return value.replaceAll("&quot;", "\"").replaceAll("&gt;", ">").replaceAll("&lt;", "<").replaceAll("&amp;", "&");
232
- }
233
- function addModulePreloads(preloads, seen, items) {
234
- for (const preload of items ?? []) {
235
- const preloadHref = typeof preload === "string" ? preload : preload.href;
236
- if (!preloadHref || seen.has(preloadHref)) continue;
237
- seen.add(preloadHref);
238
- preloads.push(preload);
239
- }
240
- }
241
- function splitLeadingHeadHtml(html) {
242
- const containerStart = html.indexOf("<div data-async-container");
243
- if (containerStart <= 0) return {
244
- bodyHtml: html,
245
- headHtml: ""
246
- };
247
- return {
248
- bodyHtml: html.slice(containerStart),
249
- headHtml: html.slice(0, containerStart)
250
- };
251
- }
252
- async function renderDocumentShell(documentModule, pageProps, headHtml) {
253
- const attributes = htmlAttributes(documentModule, pageProps);
254
- const documentHtml = await renderDocumentModule(documentModule, {
255
- ...pageProps,
256
- children: DOCUMENT_CHILDREN_PLACEHOLDER
257
- });
258
- if (documentHtml !== void 0) return [
259
- "<!doctype html>",
260
- `<html${renderAttributes(attributes)}>`,
261
- insertHeadHtml(documentHtml, headHtml),
262
- "</html>"
263
- ].join("");
264
- return [
265
- "<!doctype html>",
266
- `<html${renderAttributes(attributes)}>`,
267
- "<head>",
268
- "<meta charset=\"utf-8\">",
269
- "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
270
- headHtml,
271
- "</head>",
272
- "<body>",
273
- DOCUMENT_CHILDREN_PLACEHOLDER,
274
- "</body>",
275
- "</html>"
276
- ].join("");
277
- }
278
- function fillDocumentChildren(documentShell, children) {
279
- const at = documentShell.indexOf(DOCUMENT_CHILDREN_PLACEHOLDER);
280
- if (at === -1) return documentShell;
281
- return documentShell.slice(0, at) + children + documentShell.slice(at + 37);
282
- }
283
- async function renderDocumentModule(documentModule, props) {
284
- const output = await documentModule?.default?.renderSsr?.(props);
285
- assertDocumentStorageFree(output);
286
- return output?.html;
287
- }
288
- function assertDocumentStorageFree(output) {
289
- const storage = documentStorageRecords(output?.state);
290
- if (storage.length === 0) return;
291
- const keys = storage.map((record) => record.key).join(", ");
292
- throw new Error(`MARKLESS_ROUTER_DOCUMENT_STORAGE_UNSUPPORTED: the document declares storage cells (${keys}), but the router serves only the document's HTML, so their state payload never reaches the browser and they can never resume. Declare storage() at module scope in a component the page renders instead.`);
293
- }
294
- function documentStorageRecords(state) {
295
- if (!state || typeof state !== "object") return [];
296
- const storage = state.storage;
297
- return Array.isArray(storage) ? storage : [];
298
- }
299
- function insertHeadHtml(documentHtml, headHtml) {
300
- if (!headHtml) return documentHtml;
301
- const headEnd = documentHtml.indexOf("</head>");
302
- if (headEnd === -1) return `${headHtml}${documentHtml}`;
303
- return `${documentHtml.slice(0, headEnd)}${headHtml}${documentHtml.slice(headEnd)}`;
304
- }
305
- function renderRouteScript(file) {
306
- return `<script type="@markless/core/route">${escapeScriptJson({ file })}<\/script>`;
307
- }
308
- function renderLinkBridgeScript(resumeEntryPath) {
309
- const debugBootstrap = typeof __MARKLESS_DEBUG_ENABLED__ !== "undefined" && __MARKLESS_DEBUG_ENABLED__ ? `<script data-markless-router-debug-bootstrap>${escapeInlineScript(`(() => {
310
- const d = document;
311
- const s = d.currentScript;
312
- const r = s && s.closest('[data-async-container]');
313
- if (!r) return;
314
- try { globalThis[Symbol.for('markless.debug.channel.v1.bootstrap')] = ${__marklessDebugBootstrapSource()}(r, 'ssr-inline', false); } catch {}
315
- })();`)}<\/script>` : "";
316
- const debugRegistration = typeof __MARKLESS_DEBUG_ENABLED__ !== "undefined" && __MARKLESS_DEBUG_ENABLED__ ? `
317
- try {
318
- const key = Symbol.for('markless.debug.channel.v1.bootstrap');
319
- const md = globalThis[key];
320
- if (md) { md.router('ssr-link-bridge'); md.activate(); }
321
- } catch {}` : "";
322
- return `${debugBootstrap}<script data-markless-router-link-resumer>${escapeInlineScript(`(() => {
323
- const d = document;
324
- const s = d.currentScript;
325
- const r = s && s.closest('[data-async-container]');
326
- if (!r || r.__marklessRouterLinkResumerStarted) return;
327
- r.__marklessRouterLinkResumerStarted = true;
328
- const linkAttr = 'data-markless-router-link';
329
- const replaceAttr = 'data-markless-router-replace';
330
- const scrollAttr = 'data-markless-router-scroll';
331
- const anchorFrom = (event) => {
332
- const target = event.composedPath && event.composedPath()[0] || event.target;
333
- return target && target.closest ? target.closest('a[href]') : target && target.parentElement && target.parentElement.closest ? target.parentElement.closest('a[href]') : null;
334
- };
335
- const sameOrigin = (href) => {
336
- try {
337
- const url = new URL(href, location.href);
338
- return url.origin === location.origin ? url : null;
339
- } catch {
340
- return null;
341
- }
342
- };
343
- if (location.hash && location.hash.startsWith('#/')) {
344
- import(${JSON.stringify(resumeEntryPath)}).catch(() => {});
345
- }
346
- r.addEventListener('click', async (event) => {
347
- if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) return;
348
- const anchor = anchorFrom(event);
349
- if (!anchor || !anchor.hasAttribute(linkAttr) || anchor.hasAttribute('download')) return;
350
- const target = anchor.getAttribute('target');
351
- if (target && target !== '_self') return;
352
- if (anchor.relList && anchor.relList.contains('external')) return;
353
- const url = sameOrigin(anchor.href);
354
- if (!url) return;
355
- event.preventDefault();
356
- try {
357
- const mod = await import(${JSON.stringify(resumeEntryPath)});
358
- const navigate = mod.navigateMarklessRouterLink;
359
- if (typeof navigate === 'function') {
360
- await navigate({
361
- href: url.href,
362
- replace: anchor.hasAttribute(replaceAttr),
363
- scroll: anchor.getAttribute(scrollAttr) === 'manual' ? 'manual' : undefined,
364
- });
365
- } else {
366
- location.assign(url.href);
367
- }
368
- } catch (error) {
369
- setTimeout(() => { throw error; });
370
- location.assign(url.href);
371
- }
372
- }, true);${debugRegistration}
373
- })();`)}<\/script>`;
374
- }
375
- function htmlAttributes(documentModule, pageProps) {
376
- const attributes = documentModule?.__marklessRouterHtmlAttributes?.(pageProps) ?? { lang: "en" };
377
- const normalized = {};
378
- for (const [name, value] of Object.entries(attributes)) {
379
- if (value === false || value === null || value === void 0) continue;
380
- normalized[name] = String(value);
381
- }
382
- return normalized;
383
- }
384
- function renderAttributes(attributes) {
385
- return Object.entries(attributes).map(([name, value]) => ` ${name}="${escapeHtml(value)}"`).join("");
386
- }
387
- function escapeHtml(value) {
388
- return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;");
389
- }
390
- function escapeScriptJson(value) {
391
- return JSON.stringify(value).replaceAll("<", "\\u003c");
392
- }
393
- function escapeInlineScript(value) {
394
- return value.replace(/<\/script/gi, "<\\/script");
395
- }
396
- function isNitroApiPathname(pathname) {
397
- return pathname === "/api" || pathname.startsWith("/api/");
398
- }
399
- //#endregion
400
- export { createServerEntry };
1
+ import { n as routerLinkBridgeModules, t as createServerEntry } from "../../create-server-entry-DaYssO9x.js";
2
+ export { createServerEntry, routerLinkBridgeModules };