@reckona/mreact-router 0.0.4 → 0.0.6
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 +57 -1
- package/dist/adapters/aws-lambda.d.ts +2 -0
- package/dist/adapters/aws-lambda.d.ts.map +1 -1
- package/dist/adapters/aws-lambda.js +2 -0
- package/dist/adapters/aws-lambda.js.map +1 -1
- package/dist/adapters/node.d.ts +2 -0
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +1 -0
- package/dist/adapters/node.js.map +1 -1
- package/dist/app-router-globals.d.ts +10 -0
- package/dist/app-router-globals.d.ts.map +1 -0
- package/dist/app-router-globals.js +2 -0
- package/dist/app-router-globals.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +525 -45
- package/dist/client.js.map +1 -1
- package/dist/dev-server.d.ts +1 -1
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +44 -16
- package/dist/dev-server.js.map +1 -1
- package/dist/import-policy.d.ts.map +1 -1
- package/dist/import-policy.js +43 -11
- package/dist/import-policy.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/link.d.ts +18 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +24 -0
- package/dist/link.js.map +1 -0
- package/dist/module-runner.d.ts.map +1 -1
- package/dist/module-runner.js +77 -15
- package/dist/module-runner.js.map +1 -1
- package/dist/navigation-state.d.ts +11 -0
- package/dist/navigation-state.d.ts.map +1 -0
- package/dist/navigation-state.js +65 -0
- package/dist/navigation-state.js.map +1 -0
- package/dist/render.d.ts +5 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +79 -9
- package/dist/render.js.map +1 -1
- package/dist/route-source.d.ts.map +1 -1
- package/dist/route-source.js +16 -5
- package/dist/route-source.js.map +1 -1
- package/dist/serve.d.ts +4 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +11 -3
- package/dist/serve.js.map +1 -1
- package/dist/vite-config.d.ts +9 -0
- package/dist/vite-config.d.ts.map +1 -1
- package/dist/vite-config.js +8 -1
- package/dist/vite-config.js.map +1 -1
- package/dist/workspace-packages.d.ts +14 -0
- package/dist/workspace-packages.d.ts.map +1 -0
- package/dist/workspace-packages.js +41 -0
- package/dist/workspace-packages.js.map +1 -0
- package/package.json +20 -7
package/dist/client.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import { dirname, extname, join } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
4
|
import { collectIdentifierReferenceNames, collectJsxComponentRootNames, collectStaticExportReferences, collectStaticImportReferences, formatDiagnostic, hasClientRuntimeSyntax, transform, } from "@reckona/mreact-compiler";
|
|
6
5
|
import { build } from "esbuild";
|
|
7
6
|
import { assetPath } from "./assets.js";
|
|
8
7
|
import { stripRouteClientOnlyExports } from "./route-source.js";
|
|
9
8
|
import { escapeHtmlQuotedAttribute as escapeHtmlAttribute } from "@reckona/mreact-shared/html-escape";
|
|
9
|
+
import { workspacePackageFile } from "./workspace-packages.js";
|
|
10
10
|
export async function routeToClientManifestEntry(route) {
|
|
11
11
|
if (route.kind === "server") {
|
|
12
12
|
return { path: route.path, kind: route.kind, client: false };
|
|
@@ -77,6 +77,11 @@ async function inferClientRouteModuleSource(options) {
|
|
|
77
77
|
filename: options.filename,
|
|
78
78
|
}));
|
|
79
79
|
for (const reference of await staticImportReferencesForSource(options)) {
|
|
80
|
+
const rendered = isRenderedImportReference(reference, jsxComponentRoots);
|
|
81
|
+
const referenced = isReferencedImportReference(reference, identifierReferences);
|
|
82
|
+
if (!rendered && !referenced) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
80
85
|
const resolved = await resolveAppLocalModule({
|
|
81
86
|
cache: options.cache,
|
|
82
87
|
importer: options.filename,
|
|
@@ -97,7 +102,7 @@ async function inferClientRouteModuleSource(options) {
|
|
|
97
102
|
if (!imported.client) {
|
|
98
103
|
continue;
|
|
99
104
|
}
|
|
100
|
-
if (
|
|
105
|
+
if (rendered) {
|
|
101
106
|
clientBoundaryImports.push(reference.source);
|
|
102
107
|
continue;
|
|
103
108
|
}
|
|
@@ -172,6 +177,10 @@ function isRenderedImportReference(reference, jsxComponentRoots) {
|
|
|
172
177
|
return (reference.sideEffect ||
|
|
173
178
|
reference.localNames.some((localName) => jsxComponentRoots.has(localName)));
|
|
174
179
|
}
|
|
180
|
+
function isReferencedImportReference(reference, identifierReferences) {
|
|
181
|
+
return (reference.sideEffect ||
|
|
182
|
+
reference.localNames.some((localName) => identifierReferences.has(localName)));
|
|
183
|
+
}
|
|
175
184
|
function unsupportedClientImportReferenceDiagnostic(options) {
|
|
176
185
|
if (options.reference.sideEffect) {
|
|
177
186
|
return undefined;
|
|
@@ -353,13 +362,25 @@ export async function buildClientRouteOutput(options) {
|
|
|
353
362
|
const clientNavigation = options.clientNavigation ?? detectClientNavigationHint(options.code);
|
|
354
363
|
const clientReferenceManifest = options.clientReferenceManifest ?? await inferClientReferenceManifestForBundle(options);
|
|
355
364
|
const clientReferenceRegistry = emitClientReferenceRegistry(clientReferenceManifest);
|
|
365
|
+
const routeComponentExpression = routeComponentExpressionForComponents(compiled.metadata.components);
|
|
356
366
|
const routeId = routeIdForPath(options.routePath);
|
|
357
367
|
const routeUsesCells = detectRouteCellStateHint(compiled.code);
|
|
358
368
|
const routeStateSignature = routeUsesCells ? routeStateSignatureForSource(compiled.code) : "";
|
|
359
369
|
const navigationStateDeclaration = clientNavigation
|
|
360
370
|
? `const __mreactNavigationState = __mreactGlobal.__mreactNavigationState ??= {
|
|
361
371
|
cache: new Map(),
|
|
372
|
+
current: {
|
|
373
|
+
from: null,
|
|
374
|
+
pending: false,
|
|
375
|
+
to: null,
|
|
376
|
+
type: null,
|
|
377
|
+
},
|
|
362
378
|
installed: false,
|
|
379
|
+
prefetchedScripts: new Set(),
|
|
380
|
+
routePrefetchManifest: undefined,
|
|
381
|
+
routePrefetchManifestText: undefined,
|
|
382
|
+
viewportAnchors: new WeakSet(),
|
|
383
|
+
viewportObserver: undefined,
|
|
363
384
|
};`
|
|
364
385
|
: "";
|
|
365
386
|
const routeCellStateDeclaration = routeUsesCells
|
|
@@ -455,11 +476,7 @@ export function __mreactHydrateRoute() {
|
|
|
455
476
|
: JSON.parse(__mreactClientReferencesElement.textContent);
|
|
456
477
|
const __mreactClientReferenceManifests = __mreactGlobal.__mreactClientReferenceManifests ??= new Map();
|
|
457
478
|
__mreactClientReferenceManifests.set(__mreactRouteId, __mreactClientReferences);
|
|
458
|
-
const __mreactComponent =
|
|
459
|
-
? Page
|
|
460
|
-
: typeof DefaultExport === "function"
|
|
461
|
-
? DefaultExport
|
|
462
|
-
: undefined;
|
|
479
|
+
const __mreactComponent = ${routeComponentExpression};
|
|
463
480
|
|
|
464
481
|
if (__mreactMarker === null || __mreactComponent === undefined) {
|
|
465
482
|
return;
|
|
@@ -478,7 +495,7 @@ __mreactHydrateRoute();
|
|
|
478
495
|
${clientNavigation ? "__mreactInstallNavigation();" : ""}
|
|
479
496
|
|
|
480
497
|
${clientNavigation
|
|
481
|
-
? `export function __mreactNavigateToHtml(html, url) {
|
|
498
|
+
? `export function __mreactNavigateToHtml(html, url, options = {}) {
|
|
482
499
|
__mreactSaveCurrentHistoryState();
|
|
483
500
|
const applied = __mreactApplyNavigationHtml(html, url);
|
|
484
501
|
|
|
@@ -487,50 +504,189 @@ ${clientNavigation
|
|
|
487
504
|
}
|
|
488
505
|
|
|
489
506
|
__mreactPushHistoryState(url);
|
|
490
|
-
|
|
507
|
+
if (options.scroll !== "preserve") {
|
|
508
|
+
__mreactScrollTo(0, 0);
|
|
509
|
+
}
|
|
491
510
|
return true;
|
|
492
511
|
}
|
|
493
512
|
|
|
494
513
|
export async function __mreactPrefetch(url) {
|
|
495
|
-
|
|
514
|
+
if (!__mreactCanPrefetch()) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const script = __mreactRouteScriptForNavigationUrl(url);
|
|
519
|
+
|
|
520
|
+
if (script === undefined) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return __mreactPrefetchRouteScript(script);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function __mreactPrefetchRouteScript(script) {
|
|
528
|
+
if (typeof document === "undefined") {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const href = __mreactNormalizeAssetUrl(script);
|
|
496
533
|
|
|
497
534
|
if (href === undefined) {
|
|
498
535
|
return false;
|
|
499
536
|
}
|
|
500
537
|
|
|
501
|
-
if (__mreactNavigationState.
|
|
538
|
+
if (__mreactNavigationState.prefetchedScripts.has(href)) {
|
|
502
539
|
return true;
|
|
503
540
|
}
|
|
504
541
|
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
542
|
+
for (const link of Array.from(document.querySelectorAll('link[rel="modulepreload"][href]'))) {
|
|
543
|
+
if (link.href === href) {
|
|
544
|
+
__mreactNavigationState.prefetchedScripts.add(href);
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
const link = document.createElement("link");
|
|
550
|
+
link.rel = "modulepreload";
|
|
551
|
+
link.href = href;
|
|
552
|
+
document.head.appendChild(link);
|
|
553
|
+
__mreactNavigationState.prefetchedScripts.add(href);
|
|
511
554
|
return true;
|
|
512
555
|
}
|
|
513
556
|
|
|
514
|
-
export async function __mreactNavigate(url) {
|
|
557
|
+
export async function __mreactNavigate(url, options = {}) {
|
|
515
558
|
const href = __mreactNormalizeNavigationUrl(url);
|
|
516
559
|
|
|
517
560
|
if (href === undefined) {
|
|
518
561
|
return false;
|
|
519
562
|
}
|
|
520
563
|
|
|
521
|
-
|
|
564
|
+
__mreactSetNavigationState(__mreactPendingNavigationState(href, options.type ?? "push"));
|
|
522
565
|
|
|
523
566
|
try {
|
|
524
567
|
const cachedHtml = __mreactNavigationState.cache.get(href);
|
|
525
568
|
const html = cachedHtml ?? await __mreactFetchNavigationHtml(href);
|
|
526
569
|
|
|
527
570
|
__mreactNavigationState.cache.set(href, html);
|
|
528
|
-
return
|
|
571
|
+
return await __mreactApplyNavigationHtmlWithOptionalTransition(html, href, options);
|
|
529
572
|
} finally {
|
|
530
|
-
|
|
573
|
+
__mreactSetNavigationState(__mreactIdleNavigationState());
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
export function __mreactGetNavigationState() {
|
|
578
|
+
return __mreactNavigationStateSnapshot(__mreactNavigationState.current);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function __mreactPendingNavigationState(to, type) {
|
|
582
|
+
return {
|
|
583
|
+
from: typeof location === "undefined" ? null : location.href,
|
|
584
|
+
pending: true,
|
|
585
|
+
to,
|
|
586
|
+
type: __mreactNavigationType(type),
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function __mreactIdleNavigationState() {
|
|
591
|
+
return {
|
|
592
|
+
from: null,
|
|
593
|
+
pending: false,
|
|
594
|
+
to: null,
|
|
595
|
+
type: null,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function __mreactSetNavigationState(state) {
|
|
600
|
+
const snapshot = __mreactNavigationStateSnapshot(state);
|
|
601
|
+
__mreactNavigationState.current = snapshot;
|
|
602
|
+
__mreactApplyNavigationStateAttributes(snapshot);
|
|
603
|
+
__mreactDispatchNavigationStateChange(snapshot);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
function __mreactNavigationStateSnapshot(state) {
|
|
607
|
+
return {
|
|
608
|
+
from: typeof state?.from === "string" ? state.from : null,
|
|
609
|
+
pending: state?.pending === true,
|
|
610
|
+
to: typeof state?.to === "string" ? state.to : null,
|
|
611
|
+
type: __mreactNavigationType(state?.type),
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function __mreactNavigationType(type) {
|
|
616
|
+
return type === "push" || type === "replace" || type === "pop" || type === "refresh"
|
|
617
|
+
? type
|
|
618
|
+
: null;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function __mreactApplyNavigationStateAttributes(state) {
|
|
622
|
+
if (typeof document === "undefined") {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const root = document.documentElement;
|
|
627
|
+
|
|
628
|
+
if (state.pending !== true) {
|
|
629
|
+
root.removeAttribute("data-mreact-navigation-pending");
|
|
630
|
+
root.removeAttribute("data-mreact-navigation-from");
|
|
631
|
+
root.removeAttribute("data-mreact-navigation-to");
|
|
632
|
+
root.removeAttribute("data-mreact-navigation-type");
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
root.setAttribute("data-mreact-navigation-pending", "true");
|
|
637
|
+
|
|
638
|
+
if (state.from === null) {
|
|
639
|
+
root.removeAttribute("data-mreact-navigation-from");
|
|
640
|
+
} else {
|
|
641
|
+
root.setAttribute("data-mreact-navigation-from", state.from);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (state.to === null) {
|
|
645
|
+
root.removeAttribute("data-mreact-navigation-to");
|
|
646
|
+
} else {
|
|
647
|
+
root.setAttribute("data-mreact-navigation-to", state.to);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if (state.type === null) {
|
|
651
|
+
root.removeAttribute("data-mreact-navigation-type");
|
|
652
|
+
} else {
|
|
653
|
+
root.setAttribute("data-mreact-navigation-type", state.type);
|
|
531
654
|
}
|
|
532
655
|
}
|
|
533
656
|
|
|
657
|
+
function __mreactDispatchNavigationStateChange(state) {
|
|
658
|
+
if (typeof window === "undefined" || typeof CustomEvent !== "function") {
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
window.dispatchEvent(new CustomEvent("mreact:navigation-state-change", {
|
|
663
|
+
detail: state,
|
|
664
|
+
}));
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
async function __mreactApplyNavigationHtmlWithOptionalTransition(html, href, options) {
|
|
668
|
+
if (
|
|
669
|
+
options.transition !== "auto" ||
|
|
670
|
+
typeof document === "undefined" ||
|
|
671
|
+
typeof document.startViewTransition !== "function"
|
|
672
|
+
) {
|
|
673
|
+
return __mreactNavigateToHtml(html, href, options);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
let navigated = false;
|
|
677
|
+
const transition = document.startViewTransition(() => {
|
|
678
|
+
navigated = __mreactNavigateToHtml(html, href, options);
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
try {
|
|
682
|
+
await transition.updateCallbackDone;
|
|
683
|
+
} catch {
|
|
684
|
+
return navigated;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return navigated;
|
|
688
|
+
}
|
|
689
|
+
|
|
534
690
|
export function __mreactInvalidateNavigationCache(path) {
|
|
535
691
|
const normalizedPath = __mreactNormalizeNavigationPath(path);
|
|
536
692
|
|
|
@@ -607,15 +763,12 @@ function __mreactApplyNavigationHtml(html, url) {
|
|
|
607
763
|
return false;
|
|
608
764
|
}
|
|
609
765
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
for (const propsElement of Array.from(document.querySelectorAll('script[type="application/json"][id^="mreact-props-"], script[type="application/json"][id^="mreact-client-references-"]'))) {
|
|
613
|
-
propsElement.remove();
|
|
614
|
-
}
|
|
766
|
+
const currentRouteId = currentMarker.getAttribute("data-mreact-route-id");
|
|
767
|
+
const nextRouteId = nextMarker.getAttribute("data-mreact-route-id");
|
|
615
768
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
769
|
+
__mreactSyncHeadMetadata(template.content, html);
|
|
770
|
+
__mreactResumeNode(currentMarker, nextMarker);
|
|
771
|
+
__mreactSyncRouteDataScripts(template.content, currentRouteId, nextRouteId);
|
|
619
772
|
|
|
620
773
|
const script = template.content.querySelector('script[type="module"][src]')?.getAttribute("src");
|
|
621
774
|
if (script !== null && script !== undefined) {
|
|
@@ -623,10 +776,85 @@ function __mreactApplyNavigationHtml(html, url) {
|
|
|
623
776
|
}
|
|
624
777
|
|
|
625
778
|
__mreactApplyOutOfOrderFragments(document);
|
|
779
|
+
__mreactObserveViewportPrefetchAnchors(document);
|
|
626
780
|
|
|
627
781
|
return true;
|
|
628
782
|
}
|
|
629
783
|
|
|
784
|
+
function __mreactSyncHeadMetadata(root, html) {
|
|
785
|
+
const nextHead = root.querySelector("head");
|
|
786
|
+
|
|
787
|
+
if ((nextHead === null && !/<head(?:\\s[^>]*)?>/i.test(html)) || document.head === null) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const metadataRoot = nextHead ?? root;
|
|
792
|
+
const selector = __mreactManagedHeadMetadataSelector();
|
|
793
|
+
|
|
794
|
+
for (const element of Array.from(document.head.querySelectorAll(selector))) {
|
|
795
|
+
element.remove();
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
for (const element of Array.from(metadataRoot.querySelectorAll(selector))) {
|
|
799
|
+
document.head.appendChild(element);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function __mreactManagedHeadMetadataSelector() {
|
|
804
|
+
return [
|
|
805
|
+
"title",
|
|
806
|
+
'meta[name="description"]',
|
|
807
|
+
'link[rel="canonical"]',
|
|
808
|
+
'meta[property="og:title"]',
|
|
809
|
+
'meta[property="og:description"]',
|
|
810
|
+
'meta[property="og:image"]',
|
|
811
|
+
'link[rel="icon"]',
|
|
812
|
+
'link[rel="apple-touch-icon"]',
|
|
813
|
+
'meta[name="robots"]',
|
|
814
|
+
'meta[name="theme-color"]',
|
|
815
|
+
'meta[name="viewport"]',
|
|
816
|
+
].join(",");
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function __mreactSyncRouteDataScripts(root, currentRouteId, nextRouteId) {
|
|
820
|
+
const managedIds = __mreactRouteDataScriptIds(currentRouteId, nextRouteId);
|
|
821
|
+
|
|
822
|
+
if (managedIds.size === 0) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
for (const element of Array.from(document.querySelectorAll(__mreactRouteDataScriptSelector()))) {
|
|
827
|
+
if (managedIds.has(element.id)) {
|
|
828
|
+
element.remove();
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
for (const element of Array.from(root.querySelectorAll(__mreactRouteDataScriptSelector()))) {
|
|
833
|
+
if (managedIds.has(element.id)) {
|
|
834
|
+
document.body.appendChild(element);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function __mreactRouteDataScriptIds(...routeIds) {
|
|
840
|
+
const ids = new Set();
|
|
841
|
+
|
|
842
|
+
for (const routeId of routeIds) {
|
|
843
|
+
if (typeof routeId !== "string" || routeId === "") {
|
|
844
|
+
continue;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
ids.add(\`mreact-props-\${routeId}\`);
|
|
848
|
+
ids.add(\`mreact-client-references-\${routeId}\`);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
return ids;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
function __mreactRouteDataScriptSelector() {
|
|
855
|
+
return 'script[type="application/json"][id^="mreact-props-"], script[type="application/json"][id^="mreact-client-references-"]';
|
|
856
|
+
}
|
|
857
|
+
|
|
630
858
|
function __mreactCurrentHistoryState(url) {
|
|
631
859
|
return {
|
|
632
860
|
__mreact: true,
|
|
@@ -661,6 +889,18 @@ function __mreactSaveCurrentHistoryState() {
|
|
|
661
889
|
}
|
|
662
890
|
}
|
|
663
891
|
|
|
892
|
+
function __mreactEnableManualScrollRestoration() {
|
|
893
|
+
if (typeof history === "undefined" || !("scrollRestoration" in history)) {
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
try {
|
|
898
|
+
history.scrollRestoration = "manual";
|
|
899
|
+
} catch {
|
|
900
|
+
// Ignore read-only history implementations in non-browser runtimes.
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
664
904
|
function __mreactNormalizeNavigationUrl(url) {
|
|
665
905
|
if (typeof location === "undefined") {
|
|
666
906
|
return typeof url === "string" ? url : undefined;
|
|
@@ -673,20 +913,156 @@ function __mreactNormalizeNavigationUrl(url) {
|
|
|
673
913
|
}
|
|
674
914
|
}
|
|
675
915
|
|
|
916
|
+
function __mreactNormalizeAssetUrl(url) {
|
|
917
|
+
if (typeof location === "undefined") {
|
|
918
|
+
return typeof url === "string" ? url : undefined;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
try {
|
|
922
|
+
return new URL(url, location.href).href;
|
|
923
|
+
} catch {
|
|
924
|
+
return undefined;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
function __mreactRouteScriptForNavigationUrl(url) {
|
|
929
|
+
const href = __mreactNormalizeNavigationUrl(url);
|
|
930
|
+
|
|
931
|
+
if (href === undefined || typeof location === "undefined") {
|
|
932
|
+
return undefined;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
let nextUrl;
|
|
936
|
+
|
|
937
|
+
try {
|
|
938
|
+
nextUrl = new URL(href, location.href);
|
|
939
|
+
} catch {
|
|
940
|
+
return undefined;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
if (nextUrl.origin !== location.origin) {
|
|
944
|
+
return undefined;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
for (const route of __mreactClientRoutePrefetchManifest()) {
|
|
948
|
+
if (__mreactRoutePathMatches(route.path, nextUrl.pathname)) {
|
|
949
|
+
return route.script;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
return undefined;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function __mreactClientRoutePrefetchManifest() {
|
|
957
|
+
const element = typeof document === "undefined"
|
|
958
|
+
? null
|
|
959
|
+
: document.getElementById("mreact-route-prefetch-manifest");
|
|
960
|
+
const text = element?.textContent ?? "";
|
|
961
|
+
|
|
962
|
+
if (
|
|
963
|
+
__mreactNavigationState.routePrefetchManifest !== undefined &&
|
|
964
|
+
__mreactNavigationState.routePrefetchManifestText === text
|
|
965
|
+
) {
|
|
966
|
+
return __mreactNavigationState.routePrefetchManifest;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
__mreactNavigationState.routePrefetchManifestText = text;
|
|
970
|
+
|
|
971
|
+
if (element === null) {
|
|
972
|
+
__mreactNavigationState.routePrefetchManifest = [];
|
|
973
|
+
return __mreactNavigationState.routePrefetchManifest;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
try {
|
|
977
|
+
const parsed = JSON.parse(text);
|
|
978
|
+
__mreactNavigationState.routePrefetchManifest = Array.isArray(parsed)
|
|
979
|
+
? parsed.filter((route) =>
|
|
980
|
+
route !== null &&
|
|
981
|
+
typeof route === "object" &&
|
|
982
|
+
typeof route.path === "string" &&
|
|
983
|
+
typeof route.script === "string"
|
|
984
|
+
)
|
|
985
|
+
: [];
|
|
986
|
+
} catch {
|
|
987
|
+
__mreactNavigationState.routePrefetchManifest = [];
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
return __mreactNavigationState.routePrefetchManifest;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
function __mreactRoutePathMatches(routePath, pathname) {
|
|
994
|
+
const routeSegments = __mreactNormalizeRoutePath(routePath);
|
|
995
|
+
const pathSegments = __mreactNormalizeRoutePath(pathname);
|
|
996
|
+
|
|
997
|
+
if (routeSegments.length === 0) {
|
|
998
|
+
return pathSegments.length === 0;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
for (const [index, segment] of routeSegments.entries()) {
|
|
1002
|
+
const value = pathSegments[index];
|
|
1003
|
+
|
|
1004
|
+
if (segment.startsWith(":...")) {
|
|
1005
|
+
return pathSegments.length >= index + 1;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
if (value === undefined) {
|
|
1009
|
+
return false;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
if (!segment.startsWith(":") && segment !== value) {
|
|
1013
|
+
return false;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
return routeSegments.length === pathSegments.length;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
function __mreactNormalizeRoutePath(path) {
|
|
1021
|
+
const normalized = path.length > 1 ? path.replace(/\\/+$/, "") : path;
|
|
1022
|
+
return normalized === "/" || normalized === "" ? [] : normalized.replace(/^\\/+/, "").split("/");
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function __mreactCanPrefetch() {
|
|
1026
|
+
if (typeof navigator === "undefined") {
|
|
1027
|
+
return true;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
const connection = navigator.connection ?? navigator.mozConnection ?? navigator.webkitConnection;
|
|
1031
|
+
const effectiveType = typeof connection?.effectiveType === "string"
|
|
1032
|
+
? connection.effectiveType.toLowerCase()
|
|
1033
|
+
: "";
|
|
1034
|
+
|
|
1035
|
+
return connection?.saveData !== true && effectiveType !== "slow-2g" && effectiveType !== "2g";
|
|
1036
|
+
}
|
|
1037
|
+
|
|
676
1038
|
function __mreactScrollTo(x, y) {
|
|
677
1039
|
if (typeof scrollTo === "function") {
|
|
678
1040
|
scrollTo(x, y);
|
|
679
1041
|
}
|
|
680
1042
|
}
|
|
681
1043
|
|
|
1044
|
+
function __mreactIsHashOnlyNavigation(nextUrl) {
|
|
1045
|
+
if (typeof location === "undefined") {
|
|
1046
|
+
return false;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
return nextUrl.origin === location.origin &&
|
|
1050
|
+
nextUrl.pathname === location.pathname &&
|
|
1051
|
+
nextUrl.search === location.search &&
|
|
1052
|
+
nextUrl.hash !== "" &&
|
|
1053
|
+
nextUrl.hash !== location.hash;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
682
1056
|
function __mreactInstallNavigation() {
|
|
683
1057
|
if (__mreactNavigationState.installed || typeof document === "undefined") {
|
|
684
1058
|
return;
|
|
685
1059
|
}
|
|
686
1060
|
|
|
687
1061
|
__mreactNavigationState.installed = true;
|
|
1062
|
+
__mreactEnableManualScrollRestoration();
|
|
688
1063
|
__mreactSaveCurrentHistoryState();
|
|
689
1064
|
addEventListener("popstate", (event) => {
|
|
1065
|
+
__mreactSaveCurrentHistoryState();
|
|
690
1066
|
if (!__mreactRestoreHistoryState(event.state)) {
|
|
691
1067
|
location.reload();
|
|
692
1068
|
}
|
|
@@ -694,17 +1070,25 @@ function __mreactInstallNavigation() {
|
|
|
694
1070
|
document.addEventListener("pointerenter", (event) => {
|
|
695
1071
|
const anchor = __mreactAnchorFromEvent(event);
|
|
696
1072
|
|
|
697
|
-
if (anchor !== null && anchor
|
|
1073
|
+
if (anchor !== null && __mreactAnchorPrefetchMode(anchor) === "intent") {
|
|
1074
|
+
void __mreactPrefetch(anchor.href);
|
|
1075
|
+
}
|
|
1076
|
+
}, true);
|
|
1077
|
+
document.addEventListener("pointerdown", (event) => {
|
|
1078
|
+
const anchor = __mreactAnchorFromEvent(event);
|
|
1079
|
+
|
|
1080
|
+
if (anchor !== null && __mreactAnchorPrefetchMode(anchor) === "intent") {
|
|
698
1081
|
void __mreactPrefetch(anchor.href);
|
|
699
1082
|
}
|
|
700
1083
|
}, true);
|
|
701
1084
|
document.addEventListener("focusin", (event) => {
|
|
702
1085
|
const anchor = __mreactAnchorFromEvent(event);
|
|
703
1086
|
|
|
704
|
-
if (anchor !== null && anchor
|
|
1087
|
+
if (anchor !== null && __mreactAnchorPrefetchMode(anchor) === "intent") {
|
|
705
1088
|
void __mreactPrefetch(anchor.href);
|
|
706
1089
|
}
|
|
707
1090
|
});
|
|
1091
|
+
__mreactObserveViewportPrefetchAnchors(document);
|
|
708
1092
|
document.addEventListener("click", (event) => {
|
|
709
1093
|
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
710
1094
|
return;
|
|
@@ -716,14 +1100,25 @@ function __mreactInstallNavigation() {
|
|
|
716
1100
|
return;
|
|
717
1101
|
}
|
|
718
1102
|
|
|
1103
|
+
if (anchor.dataset.mreactReload === "true") {
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
719
1107
|
const nextUrl = new URL(anchor.href, location.href);
|
|
720
1108
|
|
|
721
1109
|
if (nextUrl.origin !== location.origin) {
|
|
722
1110
|
return;
|
|
723
1111
|
}
|
|
724
1112
|
|
|
1113
|
+
if (__mreactIsHashOnlyNavigation(nextUrl)) {
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
725
1117
|
event.preventDefault();
|
|
726
|
-
void __mreactNavigate(nextUrl.href
|
|
1118
|
+
void __mreactNavigate(nextUrl.href, {
|
|
1119
|
+
scroll: __mreactAnchorScrollMode(anchor),
|
|
1120
|
+
transition: __mreactAnchorTransitionMode(anchor),
|
|
1121
|
+
})
|
|
727
1122
|
.then((navigated) => {
|
|
728
1123
|
if (!navigated) {
|
|
729
1124
|
location.href = nextUrl.href;
|
|
@@ -744,6 +1139,52 @@ function __mreactAnchorFromEvent(event) {
|
|
|
744
1139
|
|
|
745
1140
|
return anchor;
|
|
746
1141
|
}
|
|
1142
|
+
|
|
1143
|
+
function __mreactAnchorPrefetchMode(anchor) {
|
|
1144
|
+
const value = anchor.dataset.mreactPrefetch;
|
|
1145
|
+
|
|
1146
|
+
if (value === "false" || value === "none") {
|
|
1147
|
+
return "none";
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
return value === "viewport" ? "viewport" : "intent";
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
function __mreactAnchorScrollMode(anchor) {
|
|
1154
|
+
return anchor.dataset.mreactScroll === "preserve" ? "preserve" : "top";
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
function __mreactAnchorTransitionMode(anchor) {
|
|
1158
|
+
return anchor.dataset.mreactTransition === "auto" ? "auto" : "none";
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function __mreactObserveViewportPrefetchAnchors(root) {
|
|
1162
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
if (__mreactNavigationState.viewportObserver === undefined) {
|
|
1167
|
+
__mreactNavigationState.viewportObserver = new IntersectionObserver((entries) => {
|
|
1168
|
+
for (const entry of entries) {
|
|
1169
|
+
if (!entry.isIntersecting || !(entry.target instanceof HTMLAnchorElement)) {
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
__mreactNavigationState.viewportObserver?.unobserve(entry.target);
|
|
1174
|
+
void __mreactPrefetch(entry.target.href);
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
for (const anchor of Array.from(root.querySelectorAll('a[href][data-mreact-prefetch="viewport"]'))) {
|
|
1180
|
+
if (!(anchor instanceof HTMLAnchorElement) || __mreactNavigationState.viewportAnchors.has(anchor)) {
|
|
1181
|
+
continue;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
__mreactNavigationState.viewportAnchors.add(anchor);
|
|
1185
|
+
__mreactNavigationState.viewportObserver.observe(anchor);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
747
1188
|
`
|
|
748
1189
|
: ""}
|
|
749
1190
|
|
|
@@ -1051,24 +1492,47 @@ function __mreactResumeChildren(current, next) {
|
|
|
1051
1492
|
};
|
|
1052
1493
|
}
|
|
1053
1494
|
function workspaceRuntimePlugin(options) {
|
|
1054
|
-
const rootDir = join(dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
1055
1495
|
const routeDir = dirname(options.routeFile);
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1496
|
+
const packageFile = (monorepoDir, packageName, entry) => workspacePackageFile({
|
|
1497
|
+
currentFileUrl: import.meta.url,
|
|
1498
|
+
entry,
|
|
1499
|
+
monorepoDir,
|
|
1500
|
+
packageName,
|
|
1501
|
+
});
|
|
1502
|
+
const reactiveCorePath = packageFile("reactive-core", "@reckona/mreact-reactive-core", "index");
|
|
1503
|
+
const reactiveCoreDir = dirname(reactiveCorePath);
|
|
1058
1504
|
const runtimePaths = new Map([
|
|
1059
|
-
["@reckona/mreact-compat", packageFile("react-compat", "index")],
|
|
1060
|
-
[
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
["@reckona/mreact-compat/
|
|
1065
|
-
[
|
|
1066
|
-
|
|
1505
|
+
["@reckona/mreact-compat", packageFile("react-compat", "@reckona/mreact-compat", "index")],
|
|
1506
|
+
[
|
|
1507
|
+
"@reckona/mreact-compat/event-priority",
|
|
1508
|
+
packageFile("react-compat", "@reckona/mreact-compat", "event-priority"),
|
|
1509
|
+
],
|
|
1510
|
+
["@reckona/mreact-compat/flight", packageFile("react-compat", "@reckona/mreact-compat", "flight")],
|
|
1511
|
+
[
|
|
1512
|
+
"@reckona/mreact-compat/internal",
|
|
1513
|
+
packageFile("react-compat", "@reckona/mreact-compat", "internal"),
|
|
1514
|
+
],
|
|
1515
|
+
[
|
|
1516
|
+
"@reckona/mreact-compat/jsx-dev-runtime",
|
|
1517
|
+
packageFile("react-compat", "@reckona/mreact-compat", "jsx-dev-runtime"),
|
|
1518
|
+
],
|
|
1519
|
+
[
|
|
1520
|
+
"@reckona/mreact-compat/jsx-runtime",
|
|
1521
|
+
packageFile("react-compat", "@reckona/mreact-compat", "jsx-runtime"),
|
|
1522
|
+
],
|
|
1523
|
+
[
|
|
1524
|
+
"@reckona/mreact-compat/scheduler",
|
|
1525
|
+
packageFile("react-compat", "@reckona/mreact-compat", "scheduler"),
|
|
1526
|
+
],
|
|
1527
|
+
[
|
|
1528
|
+
"@reckona/mreact-reactive-dom",
|
|
1529
|
+
packageFile("reactive-dom", "@reckona/mreact-reactive-dom", "index"),
|
|
1530
|
+
],
|
|
1067
1531
|
]);
|
|
1068
1532
|
return {
|
|
1069
1533
|
name: "mreact-workspace-runtime",
|
|
1070
1534
|
setup(buildApi) {
|
|
1071
|
-
buildApi.onResolve({ filter: /^\.\/devtools\.js$/ }, (args) => args.importer?.startsWith(
|
|
1535
|
+
buildApi.onResolve({ filter: /^\.\/devtools\.js$/ }, (args) => args.importer?.startsWith(reactiveCoreDir) === true
|
|
1072
1536
|
? { namespace: "mreact-devtools-stub", path: "devtools" }
|
|
1073
1537
|
: undefined);
|
|
1074
1538
|
buildApi.onResolve({ filter: /^@reckona\/mreact-reactive-core$/ }, () => ({
|
|
@@ -1089,7 +1553,7 @@ export function cell(initial) {
|
|
|
1089
1553
|
return typeof routeCell === "function" ? routeCell(nativeCell, initial) : nativeCell(initial);
|
|
1090
1554
|
}`,
|
|
1091
1555
|
loader: "ts",
|
|
1092
|
-
resolveDir:
|
|
1556
|
+
resolveDir: reactiveCoreDir,
|
|
1093
1557
|
}));
|
|
1094
1558
|
buildApi.onLoad({ filter: /^devtools$/, namespace: "mreact-devtools-stub" }, () => ({
|
|
1095
1559
|
contents: `export function emitReactiveDevtoolsEvent() {}
|
|
@@ -1180,6 +1644,22 @@ function emitClientReferenceRegistry(manifest) {
|
|
|
1180
1644
|
function clientReferenceExpression(name) {
|
|
1181
1645
|
return /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(name) ? name : undefined;
|
|
1182
1646
|
}
|
|
1647
|
+
function routeComponentExpressionForComponents(components) {
|
|
1648
|
+
const candidates = uniqueStrings([
|
|
1649
|
+
...components
|
|
1650
|
+
.filter((component) => component.exportName === "default")
|
|
1651
|
+
.map((component) => component.name),
|
|
1652
|
+
"Page",
|
|
1653
|
+
"DefaultExport",
|
|
1654
|
+
]).filter(isIdentifierName);
|
|
1655
|
+
return candidates.reduceRight((next, name) => `typeof ${name} === "function" ? ${name} : ${next}`, "undefined");
|
|
1656
|
+
}
|
|
1657
|
+
function uniqueStrings(values) {
|
|
1658
|
+
return Array.from(new Set(values));
|
|
1659
|
+
}
|
|
1660
|
+
function isIdentifierName(value) {
|
|
1661
|
+
return /^[A-Za-z_$][\w$]*$/.test(value);
|
|
1662
|
+
}
|
|
1183
1663
|
function routeStateSignatureForSource(code) {
|
|
1184
1664
|
const callExpression = routeCellCallExpressionSource(code);
|
|
1185
1665
|
const callsitePattern = callExpression === undefined
|