@markless/router 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{create-server-entry-CVhSjR45.js → create-server-entry-BnaEfDHl.js} +288 -68
- package/dist/index.js +2 -2
- package/dist/{request-locals-BPfJaoM_.js → navigation-timing-CzH6VaBR.js} +2 -1
- package/dist/vite/runtime/create-server-entry.d.ts +1 -0
- package/dist/vite/runtime/create-server-entry.js +1 -1
- package/dist/vite/runtime/mdx-route.d.ts +188 -6
- package/dist/vite/runtime/mdx-route.js +124 -12
- package/dist/vite.js +384 -62
- package/package.json +5 -5
- package/src/vite/entries/fragment-entry.ts +433 -254
- package/src/vite/entries/prerender-wake-entry.ts +3 -1
- package/src/vite/entries/resume-entry.ts +36 -23
- package/src/vite/entries/resume-modules.ts +7 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as takeMiddlewareHeaders, c as SERVED_BODY_ATTRIBUTES_PROPERTY, d as servedHtmlAttributesScript, f as LINK_ATTRIBUTE, h as SCROLL_ATTRIBUTE, i as requestLocals, l as SERVED_HTML_ATTRIBUTES_PROPERTY, m as REPLACE_ATTRIBUTE, n as MARKLESS_NAV_SETTLE_DEADLINE_MS, o as HTML_ATTRIBUTES_SLOT, p as PREFETCH_ATTRIBUTE, s as ROUTE_SCRIPT_TYPE } from "./navigation-timing-CzH6VaBR.js";
|
|
2
2
|
import { i as matchRouteManifest, n as buildRouteManifestFromFileIds, o as normalizeRouteFileId } from "./route-manifest-DmoxXanW.js";
|
|
3
3
|
import { n as __marklessDebugBootstrapSource } from "./debug-channel-Di6SppZv.js";
|
|
4
|
-
import { CONTAINER_ATTRIBUTE, PROTOCOL_CONTAINER_END_COMMENT, PROTOCOL_CONTAINER_START_COMMENT, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE } from "@markless/web/fns/container-region";
|
|
4
|
+
import { CONTAINER_ATTRIBUTE, PROTOCOL_CONTAINER_END_COMMENT, PROTOCOL_CONTAINER_START_COMMENT, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE, PROTOCOL_STREAM_OPEN_PROPERTY } from "@markless/web/fns/container-region";
|
|
5
5
|
import { CONTAINER_RETIRE_PROPERTY, renderToString, splitSsrContainer } from "@markless/web/render-to-string";
|
|
6
6
|
import { STREAMED_ARM_SELECTOR, STREAM_ARM_EXECUTOR_GLOBAL, renderToStream } from "@markless/web/render-to-stream";
|
|
7
|
+
import { PROTOCOL_KEEP_ATTRIBUTE, PROTOCOL_OWN_ATTRIBUTE, installKeepParts } from "@markless/web/fns/keep-parts";
|
|
7
8
|
import { normalizeMarklessDevError, renderMarklessDevErrorDocument } from "@markless/bundler/dev-error";
|
|
8
9
|
//#region src/vite/link-intent.ts
|
|
9
10
|
function listenForLinkIntent(root, linkAttribute, preload, prefetchAttribute) {
|
|
@@ -55,13 +56,67 @@ function documentHandlersMessage(what) {
|
|
|
55
56
|
}
|
|
56
57
|
//#endregion
|
|
57
58
|
//#region src/vite/fragment-navigation.ts
|
|
58
|
-
function startFragmentNavigation(d, linkAttributeOf,
|
|
59
|
+
function startFragmentNavigation(d, linkAttributeOf, tableAttribute, importModule, loadRun, intentOf) {
|
|
59
60
|
const w = d.defaultView;
|
|
60
61
|
if (!w) return;
|
|
61
62
|
const host = d;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
if (host.__marklessFragmentTables) return host.__marklessFragmentTables();
|
|
64
|
+
const read = /* @__PURE__ */ new WeakSet();
|
|
65
|
+
const table = {};
|
|
66
|
+
let unread = true;
|
|
67
|
+
host.__marklessFragmentTables = () => void (unread = true);
|
|
68
|
+
const fill = () => {
|
|
69
|
+
if (!unread) return table;
|
|
70
|
+
unread = false;
|
|
71
|
+
for (const script of d.querySelectorAll(`script[${tableAttribute}]`)) {
|
|
72
|
+
if (read.has(script)) continue;
|
|
73
|
+
read.add(script);
|
|
74
|
+
const [preloads, destinations] = JSON.parse(script.textContent);
|
|
75
|
+
for (const path in destinations) table[path] = destinations[path].map((at) => preloads[at]);
|
|
76
|
+
}
|
|
77
|
+
return table;
|
|
78
|
+
};
|
|
79
|
+
const routes = new Proxy(table, {
|
|
80
|
+
get: (_, key) => fill()[key],
|
|
81
|
+
has: (_, key) => key in fill(),
|
|
82
|
+
ownKeys: () => Reflect.ownKeys(fill()),
|
|
83
|
+
getOwnPropertyDescriptor: (_, key) => Reflect.getOwnPropertyDescriptor(fill(), key)
|
|
84
|
+
});
|
|
85
|
+
const landed = new Promise((done) => {
|
|
86
|
+
const start = () => {
|
|
87
|
+
const pending = [...d.head.querySelectorAll("link[rel=\"modulepreload\"]")].filter((link) => !w.performance.getEntriesByName(link.href, "resource").length);
|
|
88
|
+
let left = pending.length;
|
|
89
|
+
if (!left) return done();
|
|
90
|
+
const arrived = () => void (--left || done());
|
|
91
|
+
for (const link of pending) {
|
|
92
|
+
link.addEventListener("load", arrived, { once: true });
|
|
93
|
+
link.addEventListener("error", arrived, { once: true });
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
if (d.readyState === "complete") start();
|
|
97
|
+
else w.addEventListener("load", start, { once: true });
|
|
98
|
+
});
|
|
99
|
+
host.__marklessFragmentIdle = landed.then(() => {
|
|
100
|
+
const intent = intentOf();
|
|
101
|
+
if (!intent) return false;
|
|
102
|
+
const connection = w.navigator.connection;
|
|
103
|
+
let bytes = 0;
|
|
104
|
+
const spans = [];
|
|
105
|
+
for (const entry of [...w.performance.getEntriesByType("navigation"), ...w.performance.getEntriesByType("resource")]) {
|
|
106
|
+
if (!(entry.transferSize > 0)) continue;
|
|
107
|
+
bytes += entry.transferSize;
|
|
108
|
+
spans.push([entry.responseStart, entry.responseEnd]);
|
|
109
|
+
}
|
|
110
|
+
let busy = 0;
|
|
111
|
+
let reach = -Infinity;
|
|
112
|
+
for (const [from, to] of spans.sort((a, b) => a[0] - b[0])) {
|
|
113
|
+
busy += Math.max(0, to - Math.max(from, reach));
|
|
114
|
+
reach = Math.max(reach, to);
|
|
115
|
+
}
|
|
116
|
+
if (bytes && (busy === 0 || bytes / busy * 1e3 >= intent.idleBytesPerSecond)) return true;
|
|
117
|
+
if (bytes >= intent.idleMeasuredBytes) return false;
|
|
118
|
+
return connection?.effectiveType === "4g" && connection.saveData !== true;
|
|
119
|
+
});
|
|
65
120
|
const scrolled = /* @__PURE__ */ new Set();
|
|
66
121
|
const arriving = /* @__PURE__ */ new Map();
|
|
67
122
|
let running;
|
|
@@ -71,9 +126,14 @@ function startFragmentNavigation(d, linkAttributeOf, routes, importModule, loadR
|
|
|
71
126
|
const href = new URL(typeof item === "string" ? item : item.href, d.baseURI).href;
|
|
72
127
|
if (arriving.has(href)) return;
|
|
73
128
|
const link = d.createElement("link");
|
|
74
|
-
|
|
129
|
+
if (typeof item !== "string" && "as" in item) {
|
|
130
|
+
link.rel = "preload";
|
|
131
|
+
link.as = item.as;
|
|
132
|
+
} else {
|
|
133
|
+
link.rel = "modulepreload";
|
|
134
|
+
link.crossOrigin = "anonymous";
|
|
135
|
+
}
|
|
75
136
|
link.href = href;
|
|
76
|
-
link.crossOrigin = "anonymous";
|
|
77
137
|
arriving.set(href, new Promise((done) => link.onload = link.onerror = done));
|
|
78
138
|
d.head.appendChild(link);
|
|
79
139
|
};
|
|
@@ -114,7 +174,6 @@ function startFragmentNavigation(d, linkAttributeOf, routes, importModule, loadR
|
|
|
114
174
|
};
|
|
115
175
|
const wake = (event) => {
|
|
116
176
|
starting ??= loadRun().then((run) => {
|
|
117
|
-
delete host.__marklessFragmentWake;
|
|
118
177
|
return running = run(d, routes, importModule, scrolled, arriving, pressed);
|
|
119
178
|
});
|
|
120
179
|
starting.then((api) => api.replay(event), () => starting = void 0);
|
|
@@ -167,11 +226,7 @@ function startFragmentNavigation(d, linkAttributeOf, routes, importModule, loadR
|
|
|
167
226
|
event.preventDefault();
|
|
168
227
|
wake().then((api) => api.go(anchor) || w.location.assign(url.href), () => w.location.assign(url.href));
|
|
169
228
|
};
|
|
170
|
-
if (
|
|
171
|
-
const idle = () => w.requestIdleCallback ? w.requestIdleCallback(() => wake(), { timeout: 3e3 }) : w.setTimeout(() => wake(), 500);
|
|
172
|
-
if (d.readyState === "complete") idle();
|
|
173
|
-
else w.addEventListener("load", idle, { once: true });
|
|
174
|
-
}
|
|
229
|
+
if (d.querySelector(`script[${tableAttribute}]`)) landed.then(() => w.requestIdleCallback ? w.requestIdleCallback(() => wake(), { timeout: 3e3 }) : w.setTimeout(() => wake(), 500));
|
|
175
230
|
}
|
|
176
231
|
function runFragmentNavigation(d, config, routes, importModule, scrolled, arriving, early) {
|
|
177
232
|
const w = d.defaultView;
|
|
@@ -179,6 +234,7 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
179
234
|
const location = w.location;
|
|
180
235
|
const connection = w.navigator.connection;
|
|
181
236
|
const pageKey = (url) => url.pathname + url.search;
|
|
237
|
+
const fetched = /* @__PURE__ */ new Set();
|
|
182
238
|
let module;
|
|
183
239
|
let loaded;
|
|
184
240
|
const load = () => {
|
|
@@ -189,23 +245,38 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
189
245
|
return module;
|
|
190
246
|
};
|
|
191
247
|
const underEndpoints = (pathname) => config.endpointPrefixes.some((prefix) => (pathname + "/").startsWith(prefix + "/"));
|
|
192
|
-
const
|
|
248
|
+
const decoded = (part) => {
|
|
249
|
+
try {
|
|
250
|
+
return decodeURIComponent(part);
|
|
251
|
+
} catch {
|
|
252
|
+
return part;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const staticPages = /* @__PURE__ */ new Map();
|
|
256
|
+
const patterns = [];
|
|
257
|
+
for (const page of config.pages) {
|
|
258
|
+
const segments = page.split("/").filter(Boolean);
|
|
259
|
+
const under = underEndpoints(page);
|
|
260
|
+
if (segments.some((segment) => segment === "**" || segment === ":")) patterns.push([under, segments]);
|
|
261
|
+
else {
|
|
262
|
+
const key = JSON.stringify(segments);
|
|
263
|
+
staticPages.set(key, [...staticPages.get(key) ?? [], under]);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const known = /* @__PURE__ */ new Map();
|
|
193
267
|
const isPage = (pathname) => {
|
|
268
|
+
const cached = known.get(pathname);
|
|
269
|
+
if (cached !== void 0) return cached;
|
|
194
270
|
const endpoint = underEndpoints(pathname);
|
|
195
|
-
const parts = pathname.split("/").filter(Boolean);
|
|
196
|
-
|
|
271
|
+
const parts = pathname.split("/").filter(Boolean).map(decoded);
|
|
272
|
+
const answer = !!staticPages.get(JSON.stringify(parts))?.some((under) => !endpoint || under) || patterns.some(([under, page]) => {
|
|
197
273
|
if (endpoint && !under) return false;
|
|
198
274
|
const rest = page.indexOf("**");
|
|
199
275
|
if (rest === -1 ? page.length !== parts.length : parts.length <= rest) return false;
|
|
200
|
-
return page.every((segment, index) =>
|
|
201
|
-
if (segment === "**" || segment === ":") return true;
|
|
202
|
-
try {
|
|
203
|
-
return segment === decodeURIComponent(parts[index]);
|
|
204
|
-
} catch {
|
|
205
|
-
return segment === parts[index];
|
|
206
|
-
}
|
|
207
|
-
});
|
|
276
|
+
return page.every((segment, index) => segment === "**" || segment === ":" || segment === parts[index]);
|
|
208
277
|
});
|
|
278
|
+
known.set(pathname, answer);
|
|
279
|
+
return answer;
|
|
209
280
|
};
|
|
210
281
|
const eligible = (anchor, forClick = false) => {
|
|
211
282
|
if (!anchor || anchor.localName !== "a") return;
|
|
@@ -241,9 +312,14 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
241
312
|
if (present.has(href) || arriving.has(href)) continue;
|
|
242
313
|
present.add(href);
|
|
243
314
|
const link = d.createElement("link");
|
|
244
|
-
|
|
315
|
+
if ("as" in entry) {
|
|
316
|
+
link.rel = "preload";
|
|
317
|
+
link.as = entry.as;
|
|
318
|
+
} else {
|
|
319
|
+
link.rel = "modulepreload";
|
|
320
|
+
link.crossOrigin = entry.crossOrigin ?? "anonymous";
|
|
321
|
+
}
|
|
245
322
|
link.href = href;
|
|
246
|
-
link.crossOrigin = entry.crossOrigin ?? "anonymous";
|
|
247
323
|
if (low) link.fetchPriority = "low";
|
|
248
324
|
arriving.set(href, new Promise((done) => {
|
|
249
325
|
link.addEventListener("load", done, { once: true });
|
|
@@ -266,13 +342,31 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
266
342
|
for (let index = 0; index < tags.length; index++) tags[index].textContent = raw[index];
|
|
267
343
|
return doc;
|
|
268
344
|
};
|
|
345
|
+
const preloadStyles = (doc) => {
|
|
346
|
+
for (const link of doc.head.querySelectorAll("link[rel=\"stylesheet\"][href]")) {
|
|
347
|
+
const href = new URL(link.getAttribute("href"), d.baseURI).href;
|
|
348
|
+
if ([...d.querySelectorAll("link[href]")].some((own) => own.href === href)) continue;
|
|
349
|
+
const preload = d.createElement("link");
|
|
350
|
+
preload.rel = "preload";
|
|
351
|
+
preload.as = "style";
|
|
352
|
+
preload.href = href;
|
|
353
|
+
for (const name of [
|
|
354
|
+
"media",
|
|
355
|
+
"crossorigin",
|
|
356
|
+
"integrity"
|
|
357
|
+
]) if (link.hasAttribute(name)) preload.setAttribute(name, link.getAttribute(name));
|
|
358
|
+
d.head.append(preload);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
269
361
|
const parse = (url, text) => {
|
|
270
362
|
const at = text.indexOf(config.regionEndMarker);
|
|
271
363
|
const prefix = at === -1 ? text : text.slice(0, at);
|
|
364
|
+
const doc = parseAsLoaded(prefix);
|
|
365
|
+
preloadStyles(doc);
|
|
272
366
|
return {
|
|
273
367
|
url,
|
|
274
368
|
prefix,
|
|
275
|
-
doc
|
|
369
|
+
doc,
|
|
276
370
|
tail: at === -1 ? "" : text.slice(at + config.regionEndMarker.length)
|
|
277
371
|
};
|
|
278
372
|
};
|
|
@@ -305,7 +399,8 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
305
399
|
cancel: () => reader.cancel()
|
|
306
400
|
};
|
|
307
401
|
};
|
|
308
|
-
const request = (url, speculative, started) => {
|
|
402
|
+
const request = (url, speculative, started, budget = Infinity) => {
|
|
403
|
+
fetched.add(pageKey(url));
|
|
309
404
|
const controller = started?.controller ?? new AbortController();
|
|
310
405
|
const read = async () => {
|
|
311
406
|
const prefix = config.requestPrefix;
|
|
@@ -315,9 +410,13 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
315
410
|
const response = await (started?.response ?? w.fetch(target.href, {
|
|
316
411
|
credentials: "same-origin",
|
|
317
412
|
headers: speculative ? { purpose: "prefetch" } : {},
|
|
318
|
-
priority: speculative ? "auto" : "high",
|
|
413
|
+
priority: speculative === "idle" ? "low" : speculative ? "auto" : "high",
|
|
319
414
|
signal: controller.signal
|
|
320
415
|
}));
|
|
416
|
+
const cacheControl = response.headers.get("cache-control") ?? "";
|
|
417
|
+
const maxAge = Number(/(?:^|,)\s*max-age\s*=\s*"?(\d+)/i.exec(cacheControl)?.[1]);
|
|
418
|
+
if (/(?:^|,)\s*no-store\b/i.test(cacheControl)) entry.expires = w.performance.now();
|
|
419
|
+
else if (maxAge > 0) entry.expires = entry.at + maxAge * 1e3;
|
|
321
420
|
const type = response.headers.get("content-type") ?? "";
|
|
322
421
|
if (!response.ok || !type.includes("text/html") || !response.body) throw new Error(`MARKLESS_ROUTER_FRAGMENT_UNAVAILABLE: ${response.status}`);
|
|
323
422
|
const finalUrl = new URL(response.url || target.href);
|
|
@@ -325,9 +424,11 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
325
424
|
if (!finalUrl.pathname.startsWith(`${prefix}/`)) throw new Error("MARKLESS_ROUTER_FRAGMENT_UNAVAILABLE: redirected");
|
|
326
425
|
finalUrl.pathname = finalUrl.pathname.slice(prefix.length);
|
|
327
426
|
finalUrl.hash = url.hash;
|
|
427
|
+
if (Number(response.headers.get("content-length") ?? 0) > budget) throw new Error("MARKLESS_ROUTER_FRAGMENT_OVER_IDLE_BUDGET");
|
|
328
428
|
const reader = response.body.getReader();
|
|
329
429
|
const decoder = new TextDecoder();
|
|
330
430
|
let text = "";
|
|
431
|
+
let bytes = 0;
|
|
331
432
|
for (;;) {
|
|
332
433
|
if (text.includes(config.regionEndMarker)) return {
|
|
333
434
|
...parse(finalUrl.href, text),
|
|
@@ -338,6 +439,11 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
338
439
|
closed();
|
|
339
440
|
return parse(finalUrl.href, text + decoder.decode());
|
|
340
441
|
}
|
|
442
|
+
bytes += chunk.value.byteLength;
|
|
443
|
+
if (bytes > budget) {
|
|
444
|
+
reader.cancel();
|
|
445
|
+
throw new Error("MARKLESS_ROUTER_FRAGMENT_OVER_IDLE_BUDGET");
|
|
446
|
+
}
|
|
341
447
|
text += decoder.decode(chunk.value, { stream: true });
|
|
342
448
|
}
|
|
343
449
|
};
|
|
@@ -347,6 +453,7 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
347
453
|
};
|
|
348
454
|
const entry = {
|
|
349
455
|
at: started?.at ?? w.performance.now(),
|
|
456
|
+
writes: state.writes,
|
|
350
457
|
result: read(),
|
|
351
458
|
open: true,
|
|
352
459
|
abort: () => {
|
|
@@ -357,25 +464,36 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
357
464
|
entry.result.catch(closed);
|
|
358
465
|
return entry;
|
|
359
466
|
};
|
|
360
|
-
const prefetch = (url, code = true, started) => {
|
|
467
|
+
const prefetch = (url, code = true, started, budget = Infinity, idle = false) => {
|
|
361
468
|
const key = pageKey(url);
|
|
362
469
|
if (!config.prefetch || key === state.shown) return;
|
|
363
470
|
const existing = state.prefetches.get(key);
|
|
364
|
-
if (existing && w.performance.now()
|
|
471
|
+
if (existing && fresh(existing, w.performance.now())) return void (code && preloadCode(url, false));
|
|
365
472
|
existing?.abort();
|
|
366
473
|
const open = [...state.prefetches].filter(([, entry]) => entry.open);
|
|
367
474
|
for (const [stale, entry] of open.slice(0, Math.max(0, open.length + 1 - config.prefetchConnections))) {
|
|
368
475
|
state.prefetches.delete(stale);
|
|
369
476
|
entry.abort();
|
|
370
477
|
}
|
|
371
|
-
const entry = request(url, true, started);
|
|
478
|
+
const entry = request(url, idle ? "idle" : true, started, budget);
|
|
479
|
+
entry.result.catch(() => {
|
|
480
|
+
if (state.prefetches.get(key) === entry) state.prefetches.delete(key);
|
|
481
|
+
});
|
|
372
482
|
state.prefetches.set(key, entry);
|
|
483
|
+
expire(key, entry);
|
|
484
|
+
if (code) preloadCode(url, false);
|
|
485
|
+
};
|
|
486
|
+
const stamps = /* @__PURE__ */ new WeakMap();
|
|
487
|
+
let stamped = 0;
|
|
488
|
+
const expire = (key, entry) => {
|
|
489
|
+
const stamp = ++stamped;
|
|
490
|
+
stamps.set(entry, stamp);
|
|
373
491
|
w.setTimeout(() => {
|
|
374
|
-
|
|
492
|
+
const current = state.prefetches.get(key);
|
|
493
|
+
if (!current || stamps.get(current) !== stamp) return;
|
|
375
494
|
state.prefetches.delete(key);
|
|
376
|
-
|
|
495
|
+
current.abort();
|
|
377
496
|
}, config.prefetchTtlMs);
|
|
378
|
-
if (code) preloadCode(url, false);
|
|
379
497
|
};
|
|
380
498
|
let scanning = false;
|
|
381
499
|
let idleQueue = [];
|
|
@@ -385,8 +503,8 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
385
503
|
for (const entry of state.prefetches.values()) if (entry.open) open += 1;
|
|
386
504
|
if (open >= config.prefetchConnections) return;
|
|
387
505
|
const url = idleQueue.shift();
|
|
388
|
-
if (state.prefetches.has(pageKey(url))) continue;
|
|
389
|
-
prefetch(url, false);
|
|
506
|
+
if (state.prefetches.has(pageKey(url)) || fetched.has(pageKey(url))) continue;
|
|
507
|
+
prefetch(url, false, void 0, config.idleFragmentBytes, true);
|
|
390
508
|
preloadCode(url, true);
|
|
391
509
|
}
|
|
392
510
|
};
|
|
@@ -407,18 +525,23 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
407
525
|
visible.set(pageKey(url), url);
|
|
408
526
|
}
|
|
409
527
|
idleQueue = [];
|
|
410
|
-
for (const [key, url] of visible) if (idleQueue.length < config.idleFragments && !state.prefetches.has(key)) idleQueue.push(url);
|
|
528
|
+
for (const [key, url] of visible) if (idleQueue.length < config.idleFragments && !state.prefetches.has(key) && !fetched.has(key)) idleQueue.push(url);
|
|
411
529
|
pumpIdle();
|
|
412
530
|
};
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
531
|
+
(host.__marklessFragmentIdle ?? Promise.resolve(false)).then((fast) => {
|
|
532
|
+
if (!fast) return void (scanning = false);
|
|
533
|
+
if (w.requestIdleCallback) w.requestIdleCallback(run, { timeout: 3e3 });
|
|
534
|
+
else w.setTimeout(run, 500);
|
|
535
|
+
});
|
|
416
536
|
};
|
|
537
|
+
const fresh = (entry, now) => entry.writes === state.writes && now - entry.at < config.prefetchTtlMs && (entry.expires === void 0 || now < entry.expires);
|
|
417
538
|
const state = {
|
|
418
539
|
config,
|
|
419
540
|
routes,
|
|
420
541
|
prefetches: /* @__PURE__ */ new Map(),
|
|
421
542
|
visited: /* @__PURE__ */ new Map(),
|
|
543
|
+
writes: 0,
|
|
544
|
+
fresh,
|
|
422
545
|
shown: pageKey(new URL(location.href)),
|
|
423
546
|
eligible,
|
|
424
547
|
preloadCode,
|
|
@@ -432,8 +555,42 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
432
555
|
};
|
|
433
556
|
host.__marklessFragmentNav = state;
|
|
434
557
|
if (early) prefetch(new URL(early.url), true, early);
|
|
558
|
+
const wrote = () => {
|
|
559
|
+
state.writes++;
|
|
560
|
+
for (const entry of state.prefetches.values()) entry.abort();
|
|
561
|
+
state.prefetches.clear();
|
|
562
|
+
state.visited.clear();
|
|
563
|
+
};
|
|
564
|
+
d.addEventListener("submit", wrote, true);
|
|
565
|
+
const read = /* @__PURE__ */ new Set([
|
|
566
|
+
"GET",
|
|
567
|
+
"HEAD",
|
|
568
|
+
"OPTIONS"
|
|
569
|
+
]);
|
|
570
|
+
const send = w.fetch;
|
|
571
|
+
w.fetch = function fetch(input, init) {
|
|
572
|
+
const response = send.call(w, input, init);
|
|
573
|
+
const request = input instanceof Request ? input : void 0;
|
|
574
|
+
const method = (init?.method ?? request?.method ?? "GET").toUpperCase();
|
|
575
|
+
if (!read.has(method)) {
|
|
576
|
+
let same = false;
|
|
577
|
+
try {
|
|
578
|
+
same = new URL(request?.url ?? String(input), location.href).origin === location.origin;
|
|
579
|
+
} catch {}
|
|
580
|
+
if (same) {
|
|
581
|
+
wrote();
|
|
582
|
+
response.then(wrote, wrote);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return response;
|
|
586
|
+
};
|
|
435
587
|
let restTimer = 0;
|
|
588
|
+
let resting = "";
|
|
436
589
|
let previous;
|
|
590
|
+
const stopRest = () => {
|
|
591
|
+
w.clearTimeout(restTimer);
|
|
592
|
+
resting = "";
|
|
593
|
+
};
|
|
437
594
|
const hover = (event) => {
|
|
438
595
|
const pointer = event;
|
|
439
596
|
if (pointer.pointerType !== "mouse") return;
|
|
@@ -442,20 +599,27 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
442
599
|
y: pointer.clientY,
|
|
443
600
|
t: pointer.timeStamp
|
|
444
601
|
};
|
|
445
|
-
if (previous && point.x === previous.x && point.y === previous.y)
|
|
602
|
+
if (previous && point.x === previous.x && point.y === previous.y) {
|
|
603
|
+
if (eligible(anchorOf(event))?.href !== resting) stopRest();
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
446
606
|
const gap = previous ? point.t - previous.t : 0;
|
|
447
607
|
const creeping = !!previous && gap > 0 && Math.hypot(point.x - previous.x, point.y - previous.y) / gap < .1;
|
|
448
608
|
previous = point;
|
|
449
|
-
|
|
609
|
+
stopRest();
|
|
450
610
|
const url = eligible(anchorOf(event));
|
|
451
611
|
if (!url) return;
|
|
452
|
-
if (creeping) prefetch(url);
|
|
453
|
-
|
|
612
|
+
if (creeping) return prefetch(url);
|
|
613
|
+
resting = url.href;
|
|
614
|
+
restTimer = w.setTimeout(() => {
|
|
615
|
+
resting = "";
|
|
616
|
+
prefetch(url);
|
|
617
|
+
}, Math.max(config.hoverDwellMs, gap * 1.5));
|
|
454
618
|
};
|
|
455
619
|
d.addEventListener("pointermove", hover, { passive: true });
|
|
456
|
-
d.addEventListener("pointerout",
|
|
620
|
+
d.addEventListener("pointerout", stopRest, { passive: true });
|
|
457
621
|
const press = (event) => {
|
|
458
|
-
|
|
622
|
+
stopRest();
|
|
459
623
|
const anchor = anchorOf(event);
|
|
460
624
|
const url = eligible(anchor);
|
|
461
625
|
if (url) prefetch(url);
|
|
@@ -470,7 +634,7 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
470
634
|
const url = eligible(anchor, true);
|
|
471
635
|
if (!url) return false;
|
|
472
636
|
const current = new URL(location.href);
|
|
473
|
-
|
|
637
|
+
stopRest();
|
|
474
638
|
const replace = anchor.hasAttribute(config.replaceAttribute) || url.href === current.href;
|
|
475
639
|
const manual = anchor.getAttribute(config.scrollAttribute) === "manual";
|
|
476
640
|
const swap = (entry) => entry.navigate(d, url, replace ? "replace" : "push", manual ? "manual" : "reset");
|
|
@@ -509,6 +673,8 @@ function runFragmentNavigation(d, config, routes, importModule, scrolled, arrivi
|
|
|
509
673
|
};
|
|
510
674
|
}
|
|
511
675
|
const FRAGMENT_PATH_PREFIX = "/_markless/fragment";
|
|
676
|
+
/** Set on every fragment response, so a redirect it answers can be pointed back at a fragment. */
|
|
677
|
+
const FRAGMENT_RESPONSE_HEADER = "x-markless-fragment";
|
|
512
678
|
function fragmentPageUrl(url) {
|
|
513
679
|
if (!url.pathname.startsWith(`/_markless/fragment/`)) return void 0;
|
|
514
680
|
const page = new URL(url);
|
|
@@ -518,10 +684,15 @@ function fragmentPageUrl(url) {
|
|
|
518
684
|
const FRAGMENT_REGION_END = "<!--markless:region-end-->";
|
|
519
685
|
const FRAGMENT_APPEND_END = "<!--markless:append-end-->";
|
|
520
686
|
const FRAGMENT_PREFETCH_TTL_MS = 3e4;
|
|
687
|
+
const FRAGMENT_IDLE_FRAGMENT_BYTES = 262144;
|
|
688
|
+
const FRAGMENT_IDLE_BYTES_PER_SECOND = 25e4;
|
|
689
|
+
const FRAGMENT_IDLE_MEASURED_BYTES = 65536;
|
|
521
690
|
//#endregion
|
|
522
691
|
//#region src/vite/runtime/link-bridge-module.ts
|
|
523
692
|
/** Marks the page's link bridge script: inline in dev, a module stub importing the shared bridge in a build. */
|
|
524
693
|
const LINK_BRIDGE_SCRIPT_ATTRIBUTE = "data-markless-router-link-resumer";
|
|
694
|
+
/** Marks the page's route table: inert JSON `[preloads, destinations]`, each destination a list of indexes into preloads. */
|
|
695
|
+
const LINK_TABLE_SCRIPT_ATTRIBUTE = "data-markless-router-links";
|
|
525
696
|
/** The client output folder a build writes its link bridge files into, served as immutable static assets. */
|
|
526
697
|
const LINK_BRIDGE_DIR = "_markless/links";
|
|
527
698
|
function linkBridgeModulePath(base, hash) {
|
|
@@ -785,12 +956,35 @@ function routerLinkBridgeModules(options, manifest = buildRouteManifestFromFileI
|
|
|
785
956
|
return linkBridgeModules(options.base ?? "/", options.navigationEntryPath, fragmentBridge !== void 0 || options.prefetch !== false, options.documentNavigation === "document", fragmentBridge, options.debug);
|
|
786
957
|
}
|
|
787
958
|
function createServerEntry(options) {
|
|
959
|
+
installKeepParts();
|
|
788
960
|
const manifest = buildRouteManifestFromFileIds(options.routeFileIds);
|
|
789
961
|
assertCurrentRouteAssets(options);
|
|
790
962
|
const fragmentBridge = fragmentBridgeFor(options, manifest);
|
|
791
963
|
const fragmentNavigation = fragmentBridge !== void 0;
|
|
792
964
|
const linkBridgeModules = options.dev || options.linkBridgePaths ? void 0 : routerLinkBridgeModules(options, manifest);
|
|
793
965
|
const linkBridges = options.dev ? void 0 : options.linkBridgePaths ?? (linkBridgeModules && [linkBridgeModules[0].path, linkBridgeModules[1].path]);
|
|
966
|
+
const documentHeads = /* @__PURE__ */ new Map();
|
|
967
|
+
function pageStylesheetsAt(url, match, documentModule, request) {
|
|
968
|
+
const own = pageStylesheets(options, match.route.file) ?? [];
|
|
969
|
+
if (options.documentNavigation !== "document" || !documentModule) return Promise.resolve(own);
|
|
970
|
+
const key = url.pathname + url.search;
|
|
971
|
+
let head = documentHeads.get(key);
|
|
972
|
+
if (!head) {
|
|
973
|
+
if (documentHeads.size >= 1e3) documentHeads.delete(documentHeads.keys().next().value);
|
|
974
|
+
head = renderDocumentShell(documentModule, {
|
|
975
|
+
http: createPageHttp(request, url).context,
|
|
976
|
+
params: match.params,
|
|
977
|
+
url: {
|
|
978
|
+
href: url.href,
|
|
979
|
+
pathname: url.pathname,
|
|
980
|
+
search: url.search
|
|
981
|
+
},
|
|
982
|
+
status: 200
|
|
983
|
+
}, "").then(stylesheetHrefs, () => []);
|
|
984
|
+
documentHeads.set(key, head);
|
|
985
|
+
}
|
|
986
|
+
return head.then((hrefs) => [.../* @__PURE__ */ new Set([...own, ...hrefs])]);
|
|
987
|
+
}
|
|
794
988
|
async function fetch(request) {
|
|
795
989
|
const requestUrl = new URL(request.url);
|
|
796
990
|
const fragmentUrl = fragmentNavigation ? fragmentPageUrl(requestUrl) : void 0;
|
|
@@ -868,7 +1062,10 @@ function createServerEntry(options) {
|
|
|
868
1062
|
const documentLoads = options.documentNavigation === "document";
|
|
869
1063
|
const linkIntent = fragmentNavigation || options.prefetch !== false;
|
|
870
1064
|
const destinationPreloads = documentLoads || fragmentNavigation ? options.routeSsrModulePreloads : options.routeModulePreloads;
|
|
871
|
-
const pageArtifact = routedPageArtifact(renderSsr, baseArtifact, pageProps,
|
|
1065
|
+
const pageArtifact = routedPageArtifact(renderSsr, baseArtifact, pageProps, {
|
|
1066
|
+
file,
|
|
1067
|
+
...options.routeResumeModules?.[file] ? { resume: options.routeResumeModules[file] } : {}
|
|
1068
|
+
}, options.navigationEntryPath, pageStylesheets(options, file), documentModule?.default?.headInjections ?? [], linkIntent ? (html) => linkIntentPreloads(html, pageProps.url.href, manifest, destinationPreloads, fragmentNavigation, fragmentNavigation ? (destination, match) => pageStylesheetsAt(destination, match, documentModule, request) : void 0) : void 0, documentLoads, fragmentBridge, linkBridges);
|
|
872
1069
|
let rendersStorage = false;
|
|
873
1070
|
const routedArtifact = {
|
|
874
1071
|
...pageArtifact,
|
|
@@ -977,7 +1174,7 @@ function pageStylesheets(options, file) {
|
|
|
977
1174
|
if (documentHrefs.length === 0) return routeHrefs;
|
|
978
1175
|
return [.../* @__PURE__ */ new Set([...documentHrefs, ...routeHrefs ?? []])];
|
|
979
1176
|
}
|
|
980
|
-
function routedPageArtifact(renderSsr, baseArtifact, pageProps,
|
|
1177
|
+
function routedPageArtifact(renderSsr, baseArtifact, pageProps, route, navigationEntryPath, stylesheetHrefs, documentHeadInjections = [], intentPreloads, documentLoads = false, fragment, linkBridgePaths) {
|
|
981
1178
|
const headInjections = dedupeHeadLinks([
|
|
982
1179
|
...documentHeadInjections,
|
|
983
1180
|
...baseArtifact?.headInjections ?? [],
|
|
@@ -998,8 +1195,8 @@ function routedPageArtifact(renderSsr, baseArtifact, pageProps, file, navigation
|
|
|
998
1195
|
async renderSsr(renderProps, renderContext) {
|
|
999
1196
|
const output = await renderSsr(renderProps ?? pageProps, renderContext);
|
|
1000
1197
|
if (!output) return { html: "" };
|
|
1001
|
-
const routeScript = output.state || output.view ? renderRouteScript(
|
|
1002
|
-
const linkBridge = navigationEntryPath ? renderLinkBridgeScript(navigationEntryPath, intentPreloads?.(output.html), documentLoads, fragment, output.html.includes("href=\"#/"), linkBridgePaths) : "";
|
|
1198
|
+
const routeScript = output.state || output.view ? renderRouteScript(route) : "";
|
|
1199
|
+
const linkBridge = navigationEntryPath ? renderLinkBridgeScript(navigationEntryPath, await intentPreloads?.(output.html), documentLoads, fragment, output.html.includes("href=\"#/"), linkBridgePaths) : "";
|
|
1003
1200
|
const stateWithProps = withPagePropsCell(output.state, pageProps);
|
|
1004
1201
|
return routeScript || linkBridge || stateWithProps !== output.state ? {
|
|
1005
1202
|
...output,
|
|
@@ -1027,17 +1224,21 @@ function withPagePropsCell(state, props) {
|
|
|
1027
1224
|
function landingModulePreloads(routePreloads, linkBridgePath) {
|
|
1028
1225
|
const preloads = [];
|
|
1029
1226
|
addModulePreloads(preloads, /* @__PURE__ */ new Set(), routePreloads);
|
|
1030
|
-
|
|
1031
|
-
|
|
1227
|
+
const landing = preloads.map(highFetchPriority);
|
|
1228
|
+
if (linkBridgePath) landing.push({
|
|
1229
|
+
href: linkBridgePath,
|
|
1230
|
+
fetchPriority: "low"
|
|
1231
|
+
});
|
|
1232
|
+
return landing.length > 0 ? landing : void 0;
|
|
1032
1233
|
}
|
|
1033
|
-
function
|
|
1234
|
+
function highFetchPriority(preload) {
|
|
1034
1235
|
if (typeof preload === "string") return {
|
|
1035
1236
|
href: preload,
|
|
1036
|
-
fetchPriority: "
|
|
1237
|
+
fetchPriority: "high"
|
|
1037
1238
|
};
|
|
1038
1239
|
return preload.fetchPriority ? preload : {
|
|
1039
1240
|
...preload,
|
|
1040
|
-
fetchPriority: "
|
|
1241
|
+
fetchPriority: "high"
|
|
1041
1242
|
};
|
|
1042
1243
|
}
|
|
1043
1244
|
function routerLinkHrefs(html) {
|
|
@@ -1046,16 +1247,28 @@ function routerLinkHrefs(html) {
|
|
|
1046
1247
|
function anchorHrefs(html) {
|
|
1047
1248
|
return [...html.matchAll(/<a\b(?=[^>]*\bhref="([^"]*)")[^>]*>/g)].map((match) => unescapeHtmlAttribute(match[1] ?? ""));
|
|
1048
1249
|
}
|
|
1049
|
-
function linkIntentPreloads(html, baseHref, manifest, routes, plainAnchors = false) {
|
|
1250
|
+
async function linkIntentPreloads(html, baseHref, manifest, routes, plainAnchors = false, stylesheetsOf) {
|
|
1050
1251
|
const destinations = Object.create(null);
|
|
1252
|
+
const here = new URL(baseHref);
|
|
1253
|
+
const herePage = stylesheetsOf && matchRouteManifest(here.pathname, manifest);
|
|
1254
|
+
const have = new Set(herePage ? await stylesheetsOf(here, herePage) : []);
|
|
1051
1255
|
for (const href of plainAnchors ? anchorHrefs(html) : routerLinkHrefs(html)) {
|
|
1052
1256
|
const url = parseSameOriginUrl(href, baseHref);
|
|
1053
1257
|
const match = url && matchRouteManifest(url.pathname, manifest);
|
|
1054
1258
|
const preloads = match && routes?.[match.route.file];
|
|
1055
|
-
if (url
|
|
1259
|
+
if (!url || !preloads || preloads.length === 0 && !plainAnchors || url.pathname in destinations) continue;
|
|
1260
|
+
const styles = stylesheetsOf ? (await stylesheetsOf(url, match)).filter((href) => !have.has(href)) : [];
|
|
1261
|
+
destinations[url.pathname] = styles.length ? [...preloads, ...styles.map((href) => ({
|
|
1262
|
+
href,
|
|
1263
|
+
as: "style"
|
|
1264
|
+
}))] : preloads;
|
|
1056
1265
|
}
|
|
1057
1266
|
return destinations;
|
|
1058
1267
|
}
|
|
1268
|
+
const STYLESHEET_LINK = /<link\b(?=[^>]*\brel="(?:[^"]*\s)?stylesheet(?:\s[^"]*)?")(?=[^>]*\bhref="([^"]*)")[^>]*>/g;
|
|
1269
|
+
function stylesheetHrefs(html) {
|
|
1270
|
+
return [...html.matchAll(STYLESHEET_LINK)].map((match) => unescapeHtmlAttribute(match[1]));
|
|
1271
|
+
}
|
|
1059
1272
|
function indexedPreloads(intentPreloads) {
|
|
1060
1273
|
const preloads = [];
|
|
1061
1274
|
const indexes = /* @__PURE__ */ new Map();
|
|
@@ -1166,18 +1379,20 @@ function insertHeadHtml(documentHtml, headHtml) {
|
|
|
1166
1379
|
if (headEnd === -1) return `${headHtml}${documentHtml}`;
|
|
1167
1380
|
return `${documentHtml.slice(0, headEnd)}${headHtml}${documentHtml.slice(headEnd)}`;
|
|
1168
1381
|
}
|
|
1169
|
-
function renderRouteScript(
|
|
1170
|
-
return `<script type="${ROUTE_SCRIPT_TYPE}">${escapeScriptJson(
|
|
1382
|
+
function renderRouteScript(route) {
|
|
1383
|
+
return `<script type="${ROUTE_SCRIPT_TYPE}">${escapeScriptJson(route)}<\/script>`;
|
|
1171
1384
|
}
|
|
1172
1385
|
function linkBridgeBody(resumeEntryPath, linkIntent, documentLoads, fragment, page, debug = debugDefined()) {
|
|
1173
1386
|
const inline = !("module" in page);
|
|
1174
1387
|
const fragmentNavigation = fragment !== void 0;
|
|
1175
1388
|
const fragmentSource = fragment ? `
|
|
1176
|
-
(${fragment.source})(d,()=>${JSON.stringify(LINK_ATTRIBUTE)},${
|
|
1389
|
+
(${fragment.source})(d,()=>${JSON.stringify(LINK_ATTRIBUTE)},${JSON.stringify(LINK_TABLE_SCRIPT_ATTRIBUTE)},(href)=>import(href),${"runPath" in page && page.runPath ? `()=>import(${JSON.stringify(page.runPath)}).then((m)=>m.default)` : `()=>Promise.resolve(${boundFragmentRun(fragment, documentLoads)})`},()=>(${fragment.prefetch ? escapeScriptJson({
|
|
1177
1390
|
code: [fragment.entry, ...fragment.entryImports],
|
|
1178
1391
|
hoverDwellMs: 20,
|
|
1179
1392
|
requestPrefix: FRAGMENT_PATH_PREFIX,
|
|
1180
|
-
prefetchAttribute: PREFETCH_ATTRIBUTE
|
|
1393
|
+
prefetchAttribute: PREFETCH_ATTRIBUTE,
|
|
1394
|
+
idleBytesPerSecond: FRAGMENT_IDLE_BYTES_PER_SECOND,
|
|
1395
|
+
idleMeasuredBytes: FRAGMENT_IDLE_MEASURED_BYTES
|
|
1181
1396
|
}) : "null"}));` : "";
|
|
1182
1397
|
const indexed = !fragmentNavigation && linkIntent ? inline ? page.intentPreloads && indexedPreloads(page.intentPreloads) : {
|
|
1183
1398
|
preloads: "preloads",
|
|
@@ -1284,21 +1499,22 @@ function renderLinkBridgeScript(resumeEntryPath, intentPreloads, documentLoads =
|
|
|
1284
1499
|
if (!r) return;
|
|
1285
1500
|
try { globalThis[Symbol.for('markless.debug.channel.v1.bootstrap')] = ${__marklessDebugBootstrapSource()}(r, 'ssr-inline', false); } catch {}
|
|
1286
1501
|
})();`)}<\/script>` : "";
|
|
1502
|
+
const table = fragment && intentPreloads && Object.keys(intentPreloads).length ? (({ preloads, destinations }) => `<script type="application/json" ${LINK_TABLE_SCRIPT_ATTRIBUTE}>${escapeScriptJson([preloads, destinations])}<\/script>`)(indexedPreloads(intentPreloads)) : "";
|
|
1287
1503
|
const modulePath = modulePaths?.[hashLinks ? 1 : 0];
|
|
1288
1504
|
if (modulePath) {
|
|
1289
1505
|
const indexed = !fragment && intentPreloads ? indexedPreloads(intentPreloads) : void 0;
|
|
1290
|
-
const args =
|
|
1506
|
+
const args = indexed ? [
|
|
1291
1507
|
"0",
|
|
1292
1508
|
escapeScriptJson(indexed.preloads),
|
|
1293
1509
|
escapeScriptJson(indexed.destinations)
|
|
1294
1510
|
] : [];
|
|
1295
|
-
return `${debugBootstrap}<script type="module" ${LINK_BRIDGE_SCRIPT_ATTRIBUTE}>${escapeInlineScript(`import b from${JSON.stringify(modulePath)};b(${args.join(",")})`)}<\/script>`;
|
|
1511
|
+
return `${debugBootstrap}${table}<script type="module" ${LINK_BRIDGE_SCRIPT_ATTRIBUTE}>${escapeInlineScript(`import b from${JSON.stringify(modulePath)};b(${args.join(",")})`)}<\/script>`;
|
|
1296
1512
|
}
|
|
1297
1513
|
const body = linkBridgeBody(resumeEntryPath, intentPreloads !== void 0, documentLoads, fragment, {
|
|
1298
1514
|
intentPreloads,
|
|
1299
1515
|
hashLinks
|
|
1300
1516
|
});
|
|
1301
|
-
return `${debugBootstrap}<script ${LINK_BRIDGE_SCRIPT_ATTRIBUTE}>${escapeInlineScript(`(()=>{const d=document,s=d.currentScript,r=s&&s.closest('[data-async-container]');if(!r)return;${body}
|
|
1517
|
+
return `${debugBootstrap}${table}<script ${LINK_BRIDGE_SCRIPT_ATTRIBUTE}>${escapeInlineScript(`(()=>{const d=document,s=d.currentScript,r=s&&s.closest('[data-async-container]');if(!r)return;${body}
|
|
1302
1518
|
})();`)}<\/script>`;
|
|
1303
1519
|
}
|
|
1304
1520
|
function boundFragmentRun(fragment, documentLoads) {
|
|
@@ -1318,18 +1534,22 @@ function fragmentConfig(fragment, documentLoads) {
|
|
|
1318
1534
|
retireProperty: CONTAINER_RETIRE_PROPERTY,
|
|
1319
1535
|
streamExecutorGlobal: STREAM_ARM_EXECUTOR_GLOBAL,
|
|
1320
1536
|
streamedArmSelector: STREAMED_ARM_SELECTOR,
|
|
1537
|
+
streamOpenProperty: PROTOCOL_STREAM_OPEN_PROPERTY,
|
|
1538
|
+
pendingDeadlineMs: MARKLESS_NAV_SETTLE_DEADLINE_MS,
|
|
1321
1539
|
requestPrefix: FRAGMENT_PATH_PREFIX,
|
|
1322
1540
|
regionEndMarker: FRAGMENT_REGION_END,
|
|
1323
1541
|
appendMarker: FRAGMENT_APPEND_END,
|
|
1324
1542
|
pageEndComment: PROTOCOL_CONTAINER_END_COMMENT,
|
|
1325
1543
|
pageStartComment: PROTOCOL_CONTAINER_START_COMMENT,
|
|
1326
1544
|
containerAttributes: [CONTAINER_ATTRIBUTE, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE],
|
|
1545
|
+
keepAttributes: [PROTOCOL_KEEP_ATTRIBUTE, PROTOCOL_OWN_ATTRIBUTE],
|
|
1327
1546
|
documentLoads,
|
|
1328
1547
|
hoverDwellMs: 20,
|
|
1329
1548
|
prefetchTtlMs: FRAGMENT_PREFETCH_TTL_MS,
|
|
1330
1549
|
prefetchConnections: 2,
|
|
1331
1550
|
endpointPrefixes: [API_PATHNAME_PREFIX],
|
|
1332
1551
|
idleFragments: 6,
|
|
1552
|
+
idleFragmentBytes: FRAGMENT_IDLE_FRAGMENT_BYTES,
|
|
1333
1553
|
idleWithoutConnectionInfo: true,
|
|
1334
1554
|
prefetch: fragment.prefetch,
|
|
1335
1555
|
pages: fragment.pages
|
|
@@ -1374,4 +1594,4 @@ function insertImportMap(html, importMap) {
|
|
|
1374
1594
|
return `${html.slice(0, at)}${importMap}${html.slice(at)}`;
|
|
1375
1595
|
}
|
|
1376
1596
|
//#endregion
|
|
1377
|
-
export {
|
|
1597
|
+
export { FRAGMENT_RESPONSE_HEADER as a, documentHandlersMessage as c, FRAGMENT_PATH_PREFIX as i, listenForLinkIntent as l, routerLinkBridgeModules as n, runFragmentNavigation as o, LINK_BRIDGE_DIR as r, startFragmentNavigation as s, createServerEntry as t };
|