void 1.5.0 → 1.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.
- package/dist/{account-cmd-ChVKPZ-w.mjs → account-cmd-DRhmCWcm.mjs} +3 -3
- package/dist/{application-analysis-2vGZrKzg.mjs → application-analysis-HRFsZOv3.mjs} +3 -3
- package/dist/{application-routing-DnUQoOJD.mjs → application-routing-P4TggvWp.mjs} +1 -1
- package/dist/{auth-link-D4uMdOsw.mjs → auth-link-CVXP1G6G.mjs} +3 -3
- package/dist/{auth-router-62dna450.mjs → auth-router-D1pGdbvB.mjs} +2 -2
- package/dist/{better-auth-shared-CiclgPde.mjs → better-auth-shared-C958aM7W.mjs} +28 -3
- package/dist/{build-cmd-D93K_4Sa.mjs → build-cmd-DmjbuT6d.mjs} +1 -1
- package/dist/{cache-CiIzEED4.mjs → cache-2khBO1MR.mjs} +1 -1
- package/dist/{cancel-deploy-BNoGfn2e.mjs → cancel-deploy-_itbbvY3.mjs} +1 -1
- package/dist/cli/cli.mjs +27 -27
- package/dist/client-CEtr5UOR.mjs +1 -0
- package/dist/{client-Qayy9xEh.mjs → client-CoxPEhJq.mjs} +6 -2
- package/dist/{cloudflare-cmd-DiFGaLow.mjs → cloudflare-cmd-fZ6AMSWk.mjs} +1 -1
- package/dist/{cloudflare-config-Chet188_.mjs → cloudflare-config-eQunqX6A.mjs} +1 -1
- package/dist/{cloudflare-connect-BdgAQBc7.mjs → cloudflare-connect-9OZe4XVQ.mjs} +1 -1
- package/dist/{cloudflare-operations-CWA24vCh.mjs → cloudflare-operations-CrskD4_O.mjs} +4 -4
- package/dist/{cloudflare-operations-D8MoezuN.mjs → cloudflare-operations-oLvAd9Nd.mjs} +1 -1
- package/dist/{config-Bt4rw93x.mjs → config-BBlVXZCU.mjs} +1 -1
- package/dist/{config-DkA9jYF2.mjs → config-BITKQ3O6.mjs} +2 -1
- package/dist/{config-BszFVhpk.mjs → config-BgysUhnm.mjs} +1 -1
- package/dist/{config-CzsNzGVH.d.mts → config-CPxJmt4M.d.mts} +2 -0
- package/dist/config-entry.d.mts +1 -1
- package/dist/{connect-b9mJbb6X.mjs → connect-CKvmkl2R.mjs} +4 -4
- package/dist/{create-project-rnjum4_V.mjs → create-project-BiMmR5wA.mjs} +1 -1
- package/dist/{create-project-eomwm0wa.mjs → create-project-Bq0M8MtO.mjs} +1 -1
- package/dist/{db-UPWmiSk1.mjs → db-cq5RW4Vy.mjs} +17 -17
- package/dist/{delete-BeeYi1WO.mjs → delete-CY4L8fi2.mjs} +1 -1
- package/dist/deploy-B029oHlE.mjs +2 -0
- package/dist/{deploy-CwmCcTlq.mjs → deploy-D_gEojD2.mjs} +79 -42
- package/dist/{deploy-managed-static-gPDxyp3v.mjs → deploy-managed-static-BHVbB_-A.mjs} +11 -11
- package/dist/{deploy-transport-L6zzPE9T.mjs → deploy-transport-DEyOUfac.mjs} +2 -2
- package/dist/deploy.mjs +5 -4
- package/dist/{dev-inbox-CwH5VuZj.mjs → dev-inbox-CUUS6iUg.mjs} +1 -1
- package/dist/{dispatch-CiJ1Xrba.mjs → dispatch-BNLB5_Gm.mjs} +1 -1
- package/dist/{domain-3xdH9p2L.mjs → domain-BlH90Ods.mjs} +2 -2
- package/dist/{email-Du3YRnM5.mjs → email-Bkq8ZL1p.mjs} +6 -6
- package/dist/{email-cloudflare-CtD8qE13.mjs → email-cloudflare-MvJIxrwx.mjs} +5 -107
- package/dist/{env-Cnvp0pGy.mjs → env-AvuCSeCH.mjs} +2 -2
- package/dist/{gen-BvVmpZ5f.mjs → gen-BD-dfjxY.mjs} +3 -3
- package/dist/gen-CIHXh9I8.mjs +1 -0
- package/dist/{github-cmd-X2GKiLi-.mjs → github-cmd-CA-lBdkn.mjs} +1 -1
- package/dist/{handler-Drm_lyrV.d.mts → handler-BR6Tvjkp.d.mts} +8 -3
- package/dist/{handler-xmzz0U38.mjs → handler-CKeTtYID.mjs} +2 -12
- package/dist/headers-CuTEdP9C.mjs +445 -0
- package/dist/{help-EWDNxST-.mjs → help-1OCFDsRr.mjs} +9 -1
- package/dist/help-Ba8Dq5-r.mjs +1 -0
- package/dist/{inbound-DSKSHDUj.d.mts → inbound-BHt4dIlL.d.mts} +16 -5
- package/dist/{inbound-DQfekMtz.mjs → inbound-CdO-qY0w.mjs} +2 -76
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +65 -37
- package/dist/{info-jW8_d3VI.mjs → info-CJxua_db.mjs} +4 -4
- package/dist/{init-jDQ5G9QC.mjs → init-B-4CluYx.mjs} +12 -11
- package/dist/{isr-config-DhBkzCdY.mjs → isr-config-Czzb4mIq.mjs} +1 -47
- package/dist/{link-DOyxX5Xs.mjs → link-DAXOT-G_.mjs} +2 -2
- package/dist/{list-C9pTYDtl.mjs → list-BYSOo9fm.mjs} +2 -2
- package/dist/{live-CDBHyYiR.d.mts → live-0xrcVpyq.d.mts} +1 -1
- package/dist/{local-d1-CKfek6Z4.mjs → local-d1-BLgsNUj9.mjs} +1 -1
- package/dist/login-BpbYeu-n.mjs +1 -0
- package/dist/{login-koQbjzPd.mjs → login-CJopTWX4.mjs} +2 -2
- package/dist/{logs-cTU5TsRW.mjs → logs-DE0weBsR.mjs} +13 -11
- package/dist/{migrate-C62pGTfr.mjs → migrate-ChHHZBTi.mjs} +3 -3
- package/dist/migrate-HdA6Kh2p.mjs +1 -0
- package/dist/{mime-DKkO7ZtA.mjs → mime-CtP6-qAF.mjs} +143 -15
- package/dist/nitro.mjs +3 -3
- package/dist/{node-BfAt2rz8.mjs → node-CZ6lGNLn.mjs} +1 -1
- package/dist/{operator-cmd-CnAvSqJ5.mjs → operator-cmd-BUqsdk2K.mjs} +28 -10
- package/dist/operator-cmd-wBYyp8iQ.mjs +1 -0
- package/dist/pages/client.d.mts +143 -11
- package/dist/pages/client.mjs +173 -12
- package/dist/pages/index.d.mts +22 -3
- package/dist/pages/index.mjs +18 -4
- package/dist/pages/islands-plugin.d.mts +46 -2
- package/dist/pages/islands-plugin.mjs +91 -5
- package/dist/pages/prefetch.d.mts +2 -2
- package/dist/pages/prefetch.mjs +1 -1
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +2 -2
- package/dist/platform-args-C7XUw9mw.mjs +1 -0
- package/dist/{platform-args-Bv9hoLEL.mjs → platform-args-Cx1M-7bq.mjs} +18 -4
- package/dist/{platform-auth-config-CLj0EvnB.mjs → platform-auth-config-K4m_LE8b.mjs} +4 -4
- package/dist/{platform-auth-protection-DQDSxVhr.mjs → platform-auth-protection-KF5Vo-1I.mjs} +2 -2
- package/dist/{platform-auth-recovery-DD3oLerq.mjs → platform-auth-recovery-BOdFrl7R.mjs} +2 -2
- package/dist/{platform-cmd-WnOmdLzR.mjs → platform-cmd-DpCHawGF.mjs} +1 -1
- package/dist/{platform-cmd-PLNLg-2N.mjs → platform-cmd-Ds3EAV5t.mjs} +5 -4
- package/dist/{platform-domain-Bnq0vg0q.mjs → platform-domain-rWJshybd.mjs} +2 -2
- package/dist/{platform-lifecycle-BQiN9HN5.mjs → platform-lifecycle-BH34I0rh.mjs} +1 -1
- package/dist/{platform-lifecycle-BCsFg1Tl.mjs → platform-lifecycle-D9RdGub1.mjs} +66 -31
- package/dist/{platform-management-nzCDwtiN.mjs → platform-management-BRefdHGD.mjs} +21 -3
- package/dist/{platform-management-CMJR8Zi-.mjs → platform-management-BfLW0Zlo.mjs} +1 -1
- package/dist/{platform-recovery-DBNoME3I.mjs → platform-recovery-DZuZGJtt.mjs} +2 -2
- package/dist/platform-runtime-logs-CdJGnk3f.mjs +68 -0
- package/dist/{platform-setup-VEcHu0Vq.mjs → platform-setup-Vw1AaUN8.mjs} +15 -2
- package/dist/{plugin-inference-DmwjC3y2.mjs → plugin-inference-CdLbxZL_.mjs} +1 -1
- package/dist/{prefetch-L93_1Jk7.mjs → prefetch-Dx2jIbtg.mjs} +19 -1
- package/dist/{prefetch-CG0K6JPd.d.mts → prefetch-NdNeubbH.d.mts} +7 -1
- package/dist/{prepare-pfl2LIMy.mjs → prepare-BJW-f1f1.mjs} +4 -4
- package/dist/{prepare-BPsfLWaW.mjs → prepare-BMGeKL16.mjs} +1 -1
- package/dist/prepare-BdxJJCMv.mjs +1 -0
- package/dist/{project-cmd-5Izu4Pg3.mjs → project-cmd-B_bUyZ3J.mjs} +15 -15
- package/dist/{project-team-DSUyjZFh.mjs → project-team-MjT5K4rQ.mjs} +1 -1
- package/dist/{project-token-wj09YQSB.mjs → project-token-BKHGwY3k.mjs} +1 -1
- package/dist/{project-zero-trust-BMHf2YF0.mjs → project-zero-trust-Bzdd05-h.mjs} +1 -1
- package/dist/{protocol-0-lp9ZYx.mjs → protocol-COyySMki.mjs} +130 -107
- package/dist/{protocol-xdrl-In0.d.mts → protocol-CkwjASep.d.mts} +2 -2
- package/dist/{provision-CRiNnlfE.mjs → provision-BbCzpbXs.mjs} +1 -1
- package/dist/{provision-CxHIGBIZ.mjs → provision-DQF6Kw-6.mjs} +1 -1
- package/dist/{requests-DicgB5jU.mjs → requests-daJmVpjk.mjs} +1 -1
- package/dist/{rollback-DrDZOKNE.mjs → rollback-BgL0wY1J.mjs} +2 -2
- package/dist/{route-types-irZc1txT.mjs → route-types-CZc1YXjF.mjs} +40 -4
- package/dist/route-url-C_YIH_zO.d.mts +37 -0
- package/dist/routes-stub.d.mts +6 -2
- package/dist/runtime/better-auth-mysql.mjs +1 -1
- package/dist/runtime/better-auth-pg.mjs +1 -1
- package/dist/runtime/better-auth.mjs +1 -1
- package/dist/runtime/email/testing.d.mts +1 -1
- package/dist/runtime/email/testing.mjs +3 -3
- package/dist/runtime/email.d.mts +1 -1
- package/dist/runtime/email.mjs +3 -3
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/handler.mjs +2 -2
- package/dist/runtime/live-client.d.mts +1 -1
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/route-url.d.mts +2 -2
- package/dist/runtime/routing.d.mts +3 -3
- package/dist/runtime/routing.mjs +37 -16
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +1 -1
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/{scan-DSQtH3oS.mjs → scan-X2rDDRNa.mjs} +18 -10
- package/dist/{secret-C_QtTzJG.mjs → secret-CPq-B_vp.mjs} +2 -2
- package/dist/{static-asset-marker-NR1XS2z5.mjs → static-asset-marker-DsQKz6lt.mjs} +8 -1
- package/dist/validation-error-uAAjlsiW.mjs +82 -0
- package/dist/{version-metadata-Blf5H9BQ.mjs → version-metadata-C8hLzQkv.mjs} +1 -1
- package/dist/{wrangler-p-kLCJqF.mjs → wrangler-DESSbN8L.mjs} +2 -2
- package/dist/wrangler-DUB3MGHV.mjs +1 -0
- package/dist/{wrapper-iejSJDwL.mjs → wrapper-C9SUxoj7.mjs} +2 -2
- package/dist/{ws-DzBD-NUj.d.mts → ws-Dmjg5NH2.d.mts} +1 -1
- package/docs/guide/edge/headers.md +2 -0
- package/docs/guide/edge/rewrites.md +1 -1
- package/docs/guide/email/receiving.md +1 -1
- package/docs/guide/email/sending.md +42 -12
- package/docs/guide/pages-routing/actions-and-forms.md +21 -1
- package/docs/guide/pages-routing/islands.md +3 -3
- package/docs/guide/pages-routing/layouts.md +16 -2
- package/docs/guide/pages-routing/loaders.md +2 -2
- package/docs/guide/pages-routing/markdown.md +1 -1
- package/docs/guide/pages-routing/overview.md +103 -0
- package/docs/guide/platform/administration/connected-apps.md +4 -2
- package/docs/guide/platform/installation/credentials.md +6 -4
- package/docs/guide/platform/installation/maintenance.md +13 -0
- package/docs/guide/platform/installation/setup.md +22 -1
- package/docs/guide/ssg.md +3 -3
- package/docs/guide/type-safety.md +42 -1
- package/docs/integrations/frameworks/astro.md +17 -12
- package/docs/integrations/frameworks/overview.md +2 -2
- package/docs/reference/api/pages.md +101 -50
- package/docs/reference/api/rewrites.md +4 -1
- package/docs/reference/api/types.md +14 -10
- package/docs/reference/api.md +1 -1
- package/docs/reference/cli/platform-installation.md +4 -1
- package/docs/reference/cli/setup.md +1 -1
- package/docs/reference/config.md +10 -0
- package/package.json +8 -7
- package/schema.json +4 -0
- package/skills/void/SKILL.md +5 -0
- package/dist/client-DVtAKeUm.mjs +0 -1
- package/dist/deploy-CfU7CR-b.mjs +0 -2
- package/dist/gen-i61rdQgg.mjs +0 -1
- package/dist/headers-DEUBAM6W.mjs +0 -225
- package/dist/help-BcZDUcTw.mjs +0 -1
- package/dist/login-C0MiQrYs.mjs +0 -1
- package/dist/migrate-BG09-KOv.mjs +0 -1
- package/dist/operator-cmd-BhHXIL2G.mjs +0 -1
- package/dist/platform-args-C1kqYUen.mjs +0 -1
- package/dist/prepare-BJMmfq3W.mjs +0 -1
- package/dist/route-url-BGOiyKNz.d.mts +0 -24
- package/dist/validation-error-rDVbUJet.mjs +0 -47
- package/dist/wrangler-CPRX2d9A.mjs +0 -1
package/dist/pages/client.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as searchWithoutActionKey } from "../action-key-XtKKbbsi.mjs";
|
|
2
2
|
import { t as ISLAND_FRONTMATTER_ID } from "../serialize-DUuYuaY3.mjs";
|
|
3
3
|
import { r as toUrlString, t as interpolateRouteParams } from "../route-url-CRDF-I0I.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { r as parseCacheFor, t as PrefetchCache } from "../prefetch-Dx2jIbtg.mjs";
|
|
5
5
|
import { readUsageLimit } from "@void/edge";
|
|
6
6
|
// src/pages/action-result.ts
|
|
7
7
|
var VoidActionError = class extends Error {
|
|
@@ -10,9 +10,9 @@ var VoidActionError = class extends Error {
|
|
|
10
10
|
status;
|
|
11
11
|
statusText;
|
|
12
12
|
url;
|
|
13
|
-
constructor({ body, status, statusText, url }) {
|
|
13
|
+
constructor({ body, message, status, statusText, url }) {
|
|
14
14
|
const limit = status === 429 ? readUsageLimit(body) : null;
|
|
15
|
-
super(limit?.message ?? (statusText ? `Action failed with ${status} ${statusText}` : `Action failed with ${status}`));
|
|
15
|
+
super(message ?? limit?.message ?? (statusText ? `Action failed with ${status} ${statusText}` : `Action failed with ${status}`));
|
|
16
16
|
this.name = "VoidActionError";
|
|
17
17
|
this.body = body;
|
|
18
18
|
this.limit = limit;
|
|
@@ -52,9 +52,16 @@ async function readActionErrorBody(response) {
|
|
|
52
52
|
return null;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
+
function readActionErrorMessage(response, body) {
|
|
56
|
+
if (response.status < 400 || response.status >= 500) return;
|
|
57
|
+
if (!response.headers.get("content-type")?.includes("text/plain")) return;
|
|
58
|
+
return typeof body === "string" && body.trim() ? body : void 0;
|
|
59
|
+
}
|
|
55
60
|
async function createActionErrorFromResponse(response, url) {
|
|
61
|
+
const body = await readActionErrorBody(response);
|
|
56
62
|
return new VoidActionError({
|
|
57
|
-
body
|
|
63
|
+
body,
|
|
64
|
+
message: readActionErrorMessage(response, body),
|
|
58
65
|
status: response.status,
|
|
59
66
|
statusText: response.statusText,
|
|
60
67
|
url
|
|
@@ -362,7 +369,7 @@ async function fetchPageResponse(fetchUrl, init) {
|
|
|
362
369
|
}
|
|
363
370
|
}
|
|
364
371
|
async function createPageNavigationEngine(config) {
|
|
365
|
-
const { adapter, components, layoutTree, routeMeta, staticPageData: STATIC_PAGE_DATA_ENABLED = false, staticPageDataFastPath: STATIC_PAGE_DATA_FAST_PATH = STATIC_PAGE_DATA_ENABLED, prefetchHoverDelay: PREFETCH_HOVER_DELAY, prefetchDefaultCacheFor: PREFETCH_DEFAULT_CACHE_FOR, cacheVisitedPageData: CACHE_VISITED_PAGE_DATA = false } = config;
|
|
372
|
+
const { adapter, components, layoutTree, routeMeta, staticPageData: STATIC_PAGE_DATA_ENABLED = false, staticPageDataFastPath: STATIC_PAGE_DATA_FAST_PATH = STATIC_PAGE_DATA_ENABLED, prefetchHoverDelay: PREFETCH_HOVER_DELAY, prefetchDefaultCacheFor: PREFETCH_DEFAULT_CACHE_FOR, prefetchDefaultStrategy: PREFETCH_DEFAULT_STRATEGY = false, cacheVisitedPageData: CACHE_VISITED_PAGE_DATA = false } = config;
|
|
366
373
|
const matchRoute = (url) => config.matchRoute(decodePagePath(new URL(url, "http://x").pathname));
|
|
367
374
|
const _prefetchCache = new PrefetchCache();
|
|
368
375
|
let _nextNavigationId = 0;
|
|
@@ -659,6 +666,7 @@ async function createPageNavigationEngine(config) {
|
|
|
659
666
|
url = fetchUrl + redirectUrl.hash;
|
|
660
667
|
commitTarget.fetchUrl = fetchUrl;
|
|
661
668
|
commitTarget.hash = redirectUrl.hash;
|
|
669
|
+
commitTarget.method = method;
|
|
662
670
|
}
|
|
663
671
|
if (response && method !== "GET" && !response.ok) throw await createActionErrorFromResponse(response, fetchUrl);
|
|
664
672
|
if (response && !response.headers.get("X-VoidPages")) {
|
|
@@ -743,6 +751,7 @@ async function createPageNavigationEngine(config) {
|
|
|
743
751
|
const result = await shell;
|
|
744
752
|
if (!result) return false;
|
|
745
753
|
if (resourceId < _urlNavigationId) return false;
|
|
754
|
+
const preserveScroll = options.preserveScroll ?? (commitTarget.method !== "GET" && commitTarget.fetchUrl === window.location.pathname + window.location.search);
|
|
746
755
|
if (!options._popstate) {
|
|
747
756
|
const historyUrl = commitTarget.fetchUrl + commitTarget.hash;
|
|
748
757
|
const resource = getResource();
|
|
@@ -777,7 +786,7 @@ async function createPageNavigationEngine(config) {
|
|
|
777
786
|
_currentFetchUrl = commitTarget.fetchUrl;
|
|
778
787
|
scrollRestoration.commit();
|
|
779
788
|
requestAnimationFrame(() => {
|
|
780
|
-
if (!
|
|
789
|
+
if (!preserveScroll) restoreScroll(options._scrollPosition, commitTarget.hash);
|
|
781
790
|
});
|
|
782
791
|
return true;
|
|
783
792
|
};
|
|
@@ -791,6 +800,7 @@ async function createPageNavigationEngine(config) {
|
|
|
791
800
|
_htmlDeferredRegistry = initialDeferredRegistry;
|
|
792
801
|
return {
|
|
793
802
|
_hoverDelay: PREFETCH_HOVER_DELAY,
|
|
803
|
+
_prefetchDefaultStrategy: PREFETCH_DEFAULT_STRATEGY,
|
|
794
804
|
initialPageData,
|
|
795
805
|
initialComponent,
|
|
796
806
|
initialLayouts,
|
|
@@ -834,7 +844,8 @@ async function createPageNavigationEngine(config) {
|
|
|
834
844
|
const deferredRegistry = new DeferredRegistry();
|
|
835
845
|
const commitTarget = {
|
|
836
846
|
fetchUrl: effectiveFetchUrl,
|
|
837
|
-
hash
|
|
847
|
+
hash,
|
|
848
|
+
method
|
|
838
849
|
};
|
|
839
850
|
const shell = loadNavigationShell(id, url, effectiveFetchUrl, method, options, controller.signal, commitTarget, deferredRegistry);
|
|
840
851
|
let commitResource = async () => false;
|
|
@@ -971,6 +982,147 @@ function isModifiedEvent(e) {
|
|
|
971
982
|
const target = e.currentTarget.getAttribute("target");
|
|
972
983
|
return target !== null && target !== "_self" || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || e.button !== 0;
|
|
973
984
|
}
|
|
985
|
+
// src/pages/link.ts
|
|
986
|
+
/** Normalizes the method and destination, rejecting options that only GET links support. */
|
|
987
|
+
function resolveLink(props) {
|
|
988
|
+
const method = (props.method ?? "GET").toUpperCase();
|
|
989
|
+
const isGet = method === "GET";
|
|
990
|
+
if (props.prefetch !== void 0 && props.prefetch !== false && !isGet) throw new Error("Link: prefetch only supports GET links. Remove `prefetch` or use method=\"GET\".");
|
|
991
|
+
if (props.reloadDocument && !isGet) throw new Error("Link: reloadDocument only supports GET links.");
|
|
992
|
+
return {
|
|
993
|
+
method,
|
|
994
|
+
isGet,
|
|
995
|
+
href: isGet ? mergeDataIntoHref(props.href, props.data) : props.href
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* The events that prefetch a Link. A Link without a `prefetch` prop uses the app's
|
|
1000
|
+
* `defaultStrategy`, but only when it is a GET link, the only kind that can prefetch.
|
|
1001
|
+
*/
|
|
1002
|
+
function linkPrefetchStrategies(props, link, defaultStrategy = false) {
|
|
1003
|
+
if (props.reloadDocument) return [];
|
|
1004
|
+
const prefetch = props.prefetch ?? (link.isGet ? defaultStrategy : false);
|
|
1005
|
+
if (prefetch === false) return [];
|
|
1006
|
+
if (prefetch === true) return ["hover"];
|
|
1007
|
+
if (typeof prefetch === "string") return [prefetch];
|
|
1008
|
+
return prefetch;
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Marks a GET link to the current page. Pathnames compare the way the server
|
|
1012
|
+
* matches pages: case-sensitive, trailing slash significant, decoded like Hono's
|
|
1013
|
+
* getPath. The query and hash are ignored. `prefix` also matches nested pages by
|
|
1014
|
+
* whole segment, except for `/`, but only an exact match is `aria-current`.
|
|
1015
|
+
* Spread the result before the user's attributes so theirs win.
|
|
1016
|
+
*/
|
|
1017
|
+
function linkActiveAttributes(router, link, match = "exact") {
|
|
1018
|
+
if (!router || !link.isGet) return {};
|
|
1019
|
+
const current = router.url;
|
|
1020
|
+
const target = resolveSameOrigin(link.href, current);
|
|
1021
|
+
if (!target) return {};
|
|
1022
|
+
const currentPath = decodePagePath(current.pathname);
|
|
1023
|
+
const linkPath = decodePagePath(target.pathname);
|
|
1024
|
+
if (linkPath === currentPath) return {
|
|
1025
|
+
"aria-current": "page",
|
|
1026
|
+
"data-void-active": ""
|
|
1027
|
+
};
|
|
1028
|
+
if (match === "prefix" && linkPath !== "/") {
|
|
1029
|
+
const parent = linkPath.endsWith("/") ? linkPath : `${linkPath}/`;
|
|
1030
|
+
if (currentPath.startsWith(parent)) return { "data-void-active": "" };
|
|
1031
|
+
}
|
|
1032
|
+
return {};
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Marks a link while a visit to its destination is loading: the visit uses the link's
|
|
1036
|
+
* method and goes to its path, query and hash. Unlike active links, the query counts,
|
|
1037
|
+
* so `?page=2` isn't pending during a visit to `?page=3`. Every link to the destination
|
|
1038
|
+
* is marked, not only the one that was clicked.
|
|
1039
|
+
* Spread the result before the user's attributes so theirs win.
|
|
1040
|
+
*/
|
|
1041
|
+
function linkPendingAttributes(router, navigation, link) {
|
|
1042
|
+
if (!router || !navigation?.location || navigation.state === "idle" || navigation.method !== link.method) return {};
|
|
1043
|
+
const destination = navigation.location;
|
|
1044
|
+
const target = resolveSameOrigin(link.href, router.url);
|
|
1045
|
+
if (target && target.host === destination.host && target.protocol === destination.protocol && decodePagePath(target.pathname) === decodePagePath(destination.pathname) && target.search === destination.search && target.hash === destination.hash) return { "data-void-pending": "" };
|
|
1046
|
+
return {};
|
|
1047
|
+
}
|
|
1048
|
+
/** Resolves `href` against `base`, or returns `null` for a malformed or other-origin href. */
|
|
1049
|
+
function resolveSameOrigin(href, base) {
|
|
1050
|
+
let target;
|
|
1051
|
+
try {
|
|
1052
|
+
target = new URL(href, base);
|
|
1053
|
+
} catch {
|
|
1054
|
+
return null;
|
|
1055
|
+
}
|
|
1056
|
+
if (target.protocol !== base.protocol || target.host !== base.host) return null;
|
|
1057
|
+
return target;
|
|
1058
|
+
}
|
|
1059
|
+
/** Data saver is on, or the connection is 2G-class. Read per call: both change while the page is open. */
|
|
1060
|
+
function isConstrainedConnection() {
|
|
1061
|
+
const connection = navigator.connection;
|
|
1062
|
+
return connection?.saveData === true || connection?.effectiveType === "2g" || connection?.effectiveType === "slow-2g";
|
|
1063
|
+
}
|
|
1064
|
+
/** Link's automatic prefetch. `router.prefetch()` called directly is not limited by the connection. */
|
|
1065
|
+
function prefetchLink(router, href, cacheFor) {
|
|
1066
|
+
if (!router?.prefetch || isConstrainedConnection()) return;
|
|
1067
|
+
if (new URL(href, window.location.href).origin !== window.location.origin) return;
|
|
1068
|
+
if (href === window.location.pathname + window.location.search) return;
|
|
1069
|
+
const options = {};
|
|
1070
|
+
if (cacheFor !== void 0) options.cacheFor = cacheFor;
|
|
1071
|
+
router.prefetch(href, options);
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Runs a client-side visit for a plain same-origin click. Modified clicks, downloads,
|
|
1075
|
+
* cross-origin destinations and `reloadDocument` links are left to the browser.
|
|
1076
|
+
* Call it after the user's own click handler so its `preventDefault()` is respected.
|
|
1077
|
+
*/
|
|
1078
|
+
function handleLinkClick(event, router, link, props) {
|
|
1079
|
+
if (props.reloadDocument || !router || event.defaultPrevented || isModifiedEvent(event)) return;
|
|
1080
|
+
if (event.currentTarget.hasAttribute("download")) return;
|
|
1081
|
+
if (new URL(link.href, window.location.href).origin !== window.location.origin) return;
|
|
1082
|
+
let navigatePrevented = false;
|
|
1083
|
+
props.onNavigate?.({ preventDefault() {
|
|
1084
|
+
navigatePrevented = true;
|
|
1085
|
+
} });
|
|
1086
|
+
event.preventDefault();
|
|
1087
|
+
if (navigatePrevented) return;
|
|
1088
|
+
router.visit(link.href, {
|
|
1089
|
+
method: link.method,
|
|
1090
|
+
data: link.isGet ? void 0 : props.data,
|
|
1091
|
+
preserveScroll: props.preserveScroll,
|
|
1092
|
+
preserveState: props.preserveState,
|
|
1093
|
+
replace: props.replace,
|
|
1094
|
+
viewTransition: props.viewTransition
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Calls `onVisible` once, after `element` has stayed in the viewport for
|
|
1099
|
+
* `LINK_VISIBLE_PREFETCH_DELAY` ms. Leaving the viewport cancels the wait and entering
|
|
1100
|
+
* again restarts it. Returns a cleanup that also cancels a pending wait.
|
|
1101
|
+
*/
|
|
1102
|
+
function observeLinkVisible(element, onVisible) {
|
|
1103
|
+
let timer;
|
|
1104
|
+
let done = false;
|
|
1105
|
+
const stop = () => {
|
|
1106
|
+
done = true;
|
|
1107
|
+
clearTimeout(timer);
|
|
1108
|
+
timer = void 0;
|
|
1109
|
+
observer.disconnect();
|
|
1110
|
+
};
|
|
1111
|
+
const observer = new IntersectionObserver((entries) => {
|
|
1112
|
+
if (done) return;
|
|
1113
|
+
if (entries.some((entry) => !entry.isIntersecting)) {
|
|
1114
|
+
clearTimeout(timer);
|
|
1115
|
+
timer = void 0;
|
|
1116
|
+
}
|
|
1117
|
+
if (!entries.at(-1)?.isIntersecting) return;
|
|
1118
|
+
timer ??= setTimeout(() => {
|
|
1119
|
+
stop();
|
|
1120
|
+
onVisible();
|
|
1121
|
+
}, 300);
|
|
1122
|
+
}, { rootMargin: "0px" });
|
|
1123
|
+
observer.observe(element);
|
|
1124
|
+
return stop;
|
|
1125
|
+
}
|
|
974
1126
|
// src/pages/island-action.ts
|
|
975
1127
|
async function submitIslandAction(url, method, data) {
|
|
976
1128
|
const response = await fetch(url, {
|
|
@@ -1081,8 +1233,12 @@ function currentUrl() {
|
|
|
1081
1233
|
function getUrlOrigin() {
|
|
1082
1234
|
return typeof window === "undefined" ? "http://localhost" : window.location.origin;
|
|
1083
1235
|
}
|
|
1236
|
+
/** Relative URLs such as `?page=2` resolve against the current page, as in an anchor. */
|
|
1237
|
+
function getUrlBase() {
|
|
1238
|
+
return typeof window === "undefined" ? "http://localhost/" : getUrlOrigin() + currentUrl();
|
|
1239
|
+
}
|
|
1084
1240
|
function toUrl(value) {
|
|
1085
|
-
return value instanceof URL ? new URL(value.href) : new URL(value || "/",
|
|
1241
|
+
return value instanceof URL ? new URL(value.href) : new URL(value || "/", getUrlBase());
|
|
1086
1242
|
}
|
|
1087
1243
|
function normalizeUrl(value) {
|
|
1088
1244
|
const urlString = toUrlString(value);
|
|
@@ -1115,8 +1271,11 @@ function createRouterFacade(router, getCurrentUrl, getCurrentParams = () => rout
|
|
|
1115
1271
|
get _hoverDelay() {
|
|
1116
1272
|
return router._hoverDelay;
|
|
1117
1273
|
},
|
|
1274
|
+
get _prefetchDefaultStrategy() {
|
|
1275
|
+
return router._prefetchDefaultStrategy;
|
|
1276
|
+
},
|
|
1118
1277
|
get url() {
|
|
1119
|
-
return
|
|
1278
|
+
return new URL(getCurrentUrl() || "/", router.url);
|
|
1120
1279
|
},
|
|
1121
1280
|
get path() {
|
|
1122
1281
|
return this.url.pathname;
|
|
@@ -1144,11 +1303,11 @@ function createRouterFacade(router, getCurrentUrl, getCurrentParams = () => rout
|
|
|
1144
1303
|
}
|
|
1145
1304
|
};
|
|
1146
1305
|
}
|
|
1147
|
-
function createSsrRouter(url = "/", params = {}) {
|
|
1306
|
+
function createSsrRouter(url = "/", params = {}, requestUrl) {
|
|
1148
1307
|
return {
|
|
1149
1308
|
_hoverDelay: 75,
|
|
1150
1309
|
get url() {
|
|
1151
|
-
return
|
|
1310
|
+
return new URL(url || "/", requestUrl ?? getUrlBase());
|
|
1152
1311
|
},
|
|
1153
1312
|
get path() {
|
|
1154
1313
|
return this.url.pathname;
|
|
@@ -1229,6 +1388,7 @@ function createActionClient(defaults = {}) {
|
|
|
1229
1388
|
return submitAction(_router, resolvedUrl, {
|
|
1230
1389
|
method,
|
|
1231
1390
|
data,
|
|
1391
|
+
preserveScroll: options?.preserveScroll,
|
|
1232
1392
|
...defaults
|
|
1233
1393
|
});
|
|
1234
1394
|
}
|
|
@@ -1320,6 +1480,7 @@ async function createVoidRouter(config) {
|
|
|
1320
1480
|
}
|
|
1321
1481
|
const router = {
|
|
1322
1482
|
_hoverDelay: engine._hoverDelay,
|
|
1483
|
+
_prefetchDefaultStrategy: engine._prefetchDefaultStrategy,
|
|
1323
1484
|
get url() {
|
|
1324
1485
|
return toUrl(routeUrl);
|
|
1325
1486
|
},
|
|
@@ -1397,4 +1558,4 @@ function initIslands(islands, hydrateFn) {
|
|
|
1397
1558
|
if (loader) scheduleHydration(el, loader, props, strategy, hydrate);
|
|
1398
1559
|
});
|
|
1399
1560
|
}
|
|
1400
|
-
export { VoidActionError, categorizeActionError, cloneFormValue, createActionClient, createPageNavigationEngine, createRouterFacade, createSsrRouter, createVoidRouter, formErrorMessage, formRetryMessage, formSubmissionBlocked, getValidationErrors, hasFiles, idleNavigationState, initIslands, interpolateRouteParams, isAbortError, isCallSiteActionError, isEqualFormValue, isFile, isFormResetOptions, isModifiedEvent, mergeDataIntoHref, objectToFormData, parseFormResetArgs, refreshPage, scheduleFormRetry, scheduleHydration, ssrProxy, submitAction, submitIslandAction, toUrlString };
|
|
1561
|
+
export { VoidActionError, categorizeActionError, cloneFormValue, createActionClient, createPageNavigationEngine, createRouterFacade, createSsrRouter, createVoidRouter, formErrorMessage, formRetryMessage, formSubmissionBlocked, getValidationErrors, handleLinkClick, hasFiles, idleNavigationState, initIslands, interpolateRouteParams, isAbortError, isCallSiteActionError, isEqualFormValue, isFile, isFormResetOptions, isModifiedEvent, linkActiveAttributes, linkPendingAttributes, linkPrefetchStrategies, mergeDataIntoHref, objectToFormData, observeLinkVisible, parseFormResetArgs, prefetchLink, refreshPage, resolveLink, scheduleFormRetry, scheduleHydration, ssrProxy, submitAction, submitIslandAction, toUrlString };
|
package/dist/pages/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { a as renderHtmlAttrs, i as renderHeadToString, n as HeadDescriptor, o as resolveHead, r as renderBodyAttrs, t as HeadConfig } from "../head-MeF_5M_3.mjs";
|
|
2
|
-
import "../config-
|
|
2
|
+
import "../config-CPxJmt4M.mjs";
|
|
3
3
|
import { i as PageDefinition, n as LayoutDefinition, o as PageScanResult, r as NamedLayoutDefinition, s as RouteEnvironment } from "../types-agfx0alu.mjs";
|
|
4
|
+
import { a as LinkPrefetchValue, n as CacheForInput } from "../prefetch-NdNeubbH.mjs";
|
|
4
5
|
import { r as serializePageData } from "../serialize-I4EmS-Wf.mjs";
|
|
5
6
|
import { Plugin, UserConfig } from "vite";
|
|
6
7
|
type ProjectPaths = {
|
|
@@ -72,7 +73,25 @@ type PagesPluginContext = {
|
|
|
72
73
|
isDev: boolean;
|
|
73
74
|
scan: () => Promise<PageScanResult | null>;
|
|
74
75
|
};
|
|
76
|
+
/** The `prefetch` option of a framework adapter plugin. */
|
|
77
|
+
type PrefetchConfig = {
|
|
78
|
+
/** How a Link without its own `prefetch` prop prefetches. Accepts the same values. */
|
|
79
|
+
defaultStrategy?: LinkPrefetchValue;
|
|
80
|
+
hoverDelay?: number;
|
|
81
|
+
cacheFor?: CacheForInput;
|
|
82
|
+
};
|
|
83
|
+
/** Options of a framework adapter's pages plugin. */
|
|
75
84
|
type PagesPluginOptions = {
|
|
85
|
+
root?: string;
|
|
86
|
+
viewTransitions?: boolean;
|
|
87
|
+
prefetch?: PrefetchConfig;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* `prefetch` with its defaults: Links prefetch only when they ask to, with a 75 ms
|
|
91
|
+
* hover delay and a 30 second cache.
|
|
92
|
+
*/
|
|
93
|
+
export declare function resolvePrefetchConfig(prefetch: PrefetchConfig | undefined): Required<PrefetchConfig>;
|
|
94
|
+
type CreatePagesPluginOptions = {
|
|
76
95
|
name: string;
|
|
77
96
|
root?: string;
|
|
78
97
|
generateRenderer: (scan: PageScanResult, isDev: boolean) => string;
|
|
@@ -80,5 +99,5 @@ type PagesPluginOptions = {
|
|
|
80
99
|
config: (context: PagesPluginContext) => UserConfig | void | Promise<UserConfig | void>;
|
|
81
100
|
};
|
|
82
101
|
/** Shared Vite lifecycle; adapters own their generated code and environment configuration. */
|
|
83
|
-
export declare function createPagesPlugin(pagesDir: string, options:
|
|
84
|
-
export { type HeadConfig, type HeadDescriptor, type LayoutDefinition, type NamedLayoutDefinition, type PageDefinition, type PageScanResult, type StaticPageDataBuildOptions, renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveHead, serializePageData };
|
|
102
|
+
export declare function createPagesPlugin(pagesDir: string, options: CreatePagesPluginOptions): Plugin;
|
|
103
|
+
export { type HeadConfig, type HeadDescriptor, type LayoutDefinition, type NamedLayoutDefinition, type PageDefinition, type PageScanResult, type PagesPluginOptions, type PrefetchConfig, type StaticPageDataBuildOptions, renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveHead, serializePageData };
|
package/dist/pages/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { a as join, n as dirname } from "../dist-DMYe8CZJ.mjs";
|
|
2
2
|
import { r as resolvePagesDir } from "../project-paths-CdGv9Tmi.mjs";
|
|
3
|
-
import { p as readConfig } from "../config-
|
|
4
|
-
import { a as resolveLayoutChain, i as resolveEffectiveLayoutChain, n as scanPages, r as generateComponentManifest, s as resolveNamedLayout, t as pageFileEnvironment } from "../scan-
|
|
5
|
-
import { r as parseRedirectsFile } from "../headers-
|
|
3
|
+
import { p as readConfig } from "../config-BITKQ3O6.mjs";
|
|
4
|
+
import { a as resolveLayoutChain, i as resolveEffectiveLayoutChain, n as scanPages, r as generateComponentManifest, s as resolveNamedLayout, t as pageFileEnvironment } from "../scan-X2rDDRNa.mjs";
|
|
5
|
+
import { r as parseRedirectsFile } from "../headers-CuTEdP9C.mjs";
|
|
6
6
|
import { i as resolveHead, n as renderHeadToString, r as renderHtmlAttrs, t as renderBodyAttrs } from "../head-5XPcnG-j.mjs";
|
|
7
7
|
import { r as serializePageData } from "../serialize-DUuYuaY3.mjs";
|
|
8
|
+
import { n as assertLinkPrefetchValue } from "../prefetch-Dx2jIbtg.mjs";
|
|
8
9
|
import { existsSync } from "node:fs";
|
|
9
10
|
import { normalizePath } from "vite";
|
|
10
11
|
// src/pages/static-data.ts
|
|
@@ -27,6 +28,19 @@ function resolveStaticPageDataBuildOptions(root, options = {}) {
|
|
|
27
28
|
// src/pages/plugin.ts
|
|
28
29
|
const RENDERER_ID = "virtual:void-pages-renderer";
|
|
29
30
|
const CLIENT_ENTRY_ID = "virtual:void-pages-client";
|
|
31
|
+
/**
|
|
32
|
+
* `prefetch` with its defaults: Links prefetch only when they ask to, with a 75 ms
|
|
33
|
+
* hover delay and a 30 second cache.
|
|
34
|
+
*/
|
|
35
|
+
function resolvePrefetchConfig(prefetch) {
|
|
36
|
+
const defaultStrategy = prefetch?.defaultStrategy ?? false;
|
|
37
|
+
assertLinkPrefetchValue(defaultStrategy, "prefetch.defaultStrategy");
|
|
38
|
+
return {
|
|
39
|
+
defaultStrategy,
|
|
40
|
+
hoverDelay: prefetch?.hoverDelay ?? 75,
|
|
41
|
+
cacheFor: prefetch?.cacheFor ?? "30s"
|
|
42
|
+
};
|
|
43
|
+
}
|
|
30
44
|
/** Shared Vite lifecycle; adapters own their generated code and environment configuration. */
|
|
31
45
|
function createPagesPlugin(pagesDir, options) {
|
|
32
46
|
let pageScan = null;
|
|
@@ -112,4 +126,4 @@ function createPagesPlugin(pagesDir, options) {
|
|
|
112
126
|
}
|
|
113
127
|
};
|
|
114
128
|
}
|
|
115
|
-
export { createPagesPlugin, generateComponentManifest, pageFileEnvironment, renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveEffectiveLayoutChain, resolveHead, resolveLayoutChain, resolveNamedLayout, resolvePagesDir, resolveStaticPageDataBuildOptions, scanPages, serializePageData };
|
|
129
|
+
export { createPagesPlugin, generateComponentManifest, pageFileEnvironment, renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveEffectiveLayoutChain, resolveHead, resolveLayoutChain, resolveNamedLayout, resolvePagesDir, resolvePrefetchConfig, resolveStaticPageDataBuildOptions, scanPages, serializePageData };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as PageScanResult } from "../types-agfx0alu.mjs";
|
|
2
|
-
import { Plugin, ResolvedConfig, ViteDevServer } from "vite";
|
|
2
|
+
import { Plugin, ResolvedConfig, UserConfig, ViteDevServer } from "vite";
|
|
3
3
|
//#region src/SourceMap.d.ts
|
|
4
4
|
interface SourceMapOptions {
|
|
5
5
|
/**
|
|
@@ -306,14 +306,43 @@ export type IslandEntry = {
|
|
|
306
306
|
islandId: string;
|
|
307
307
|
hydrate: string;
|
|
308
308
|
};
|
|
309
|
+
/** The pages whose Markdown script `@void/md` serves to the browser. */
|
|
310
|
+
export declare function mdClientScriptIds(resolvedConfig: ResolvedConfig | null): Set<string>;
|
|
309
311
|
/** Resolve a relative import specifier to an absolute path by checking extensions. */
|
|
310
|
-
export declare function resolveSpecifier(specifier: string, importerDir: string, extensions:
|
|
312
|
+
export declare function resolveSpecifier(specifier: string, importerDir: string, extensions: ReadonlyArray<string>): string | null;
|
|
313
|
+
/** The islands that island pages and layouts import, for the islands client entry. */
|
|
314
|
+
export type IslandManifest = {
|
|
315
|
+
readonly entries: Map<string, IslandEntry>;
|
|
316
|
+
/**
|
|
317
|
+
* Resolve an island import and record it. An import that does not resolve
|
|
318
|
+
* keeps its specifier as its id and is not recorded.
|
|
319
|
+
*/
|
|
320
|
+
register(specifier: string, importerDir: string, hydrate: string): {
|
|
321
|
+
absPath: string | null;
|
|
322
|
+
islandId: string;
|
|
323
|
+
};
|
|
324
|
+
/**
|
|
325
|
+
* Record the island imports of every island page and layout. The client
|
|
326
|
+
* build may load the islands client entry before their transforms run.
|
|
327
|
+
*/
|
|
328
|
+
registerPages(pageScan: PageScanResult, pagesDir: string): void;
|
|
329
|
+
};
|
|
330
|
+
/** `extensions` are tried, in order, for an island import without one. */
|
|
331
|
+
export declare function createIslandManifest(root: string, extensions: ReadonlyArray<string>): IslandManifest;
|
|
332
|
+
/**
|
|
333
|
+
* The island pages that match `componentPattern` and the layouts of every
|
|
334
|
+
* island page. Without a server build, the islands client entry imports their
|
|
335
|
+
* own styles and stylesheet imports.
|
|
336
|
+
*/
|
|
337
|
+
export declare function islandCssFiles(pageScan: PageScanResult, pagesDir: string, componentPattern: RegExp): Set<string>;
|
|
311
338
|
/**
|
|
312
339
|
* Whether the app has island pages (`*.island.*` files or Markdown). Their
|
|
313
340
|
* layouts can reach a stylesheet through a component, which only the module
|
|
314
341
|
* graph shows, so the islands client entry is built for every such app.
|
|
315
342
|
*/
|
|
316
343
|
export declare function hasIslandPages(root: string, pagesDir: string): Promise<boolean>;
|
|
344
|
+
/** Build config that adds the islands client entry to the client build of an app with island pages. */
|
|
345
|
+
export declare function islandsBuildConfig(root: string, pagesDir: string): Promise<UserConfig | undefined>;
|
|
317
346
|
/**
|
|
318
347
|
* The layouts of every island page, outermost first, then the pages. All
|
|
319
348
|
* island pages share one production stylesheet, so layout styles come first.
|
|
@@ -357,6 +386,21 @@ export declare function islandStylesPlugin(pagesDir: string): Plugin;
|
|
|
357
386
|
* virtual module. Absolute and bare specifiers are kept as-is.
|
|
358
387
|
*/
|
|
359
388
|
export declare function rewriteCssImportForVirtualModule(matchedLine: string, specifier: string, sourceFilePath: string): string;
|
|
389
|
+
export type IslandClientEntryOptions = {
|
|
390
|
+
manifest: IslandManifest;
|
|
391
|
+
/** From `islandCssFiles`. */
|
|
392
|
+
cssFiles: ReadonlySet<string>;
|
|
393
|
+
/** From `recordedIslandStyles`. */
|
|
394
|
+
styles: ReadonlyArray<string> | null;
|
|
395
|
+
/** Whether a built page loads the entry for its islands. */
|
|
396
|
+
needsRuntime: boolean;
|
|
397
|
+
isDev: boolean;
|
|
398
|
+
/** Imports for the style blocks of a Vue or Svelte component. */
|
|
399
|
+
styleBlockImports?: (file: string, content: string) => Array<string>;
|
|
400
|
+
/** Source that defines `async function hydrateIsland(el, mod, props, frontmatter)`. */
|
|
401
|
+
hydrateIsland: string;
|
|
402
|
+
};
|
|
403
|
+
export declare function generateIslandClientEntry(options: IslandClientEntryOptions): string;
|
|
360
404
|
/** Extract CSS import statements from a file and return them as @import rules. */
|
|
361
405
|
export declare function extractCssImports(filePath: string): string;
|
|
362
406
|
/** Compute which island pages need client-side JavaScript. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as resolve, n as dirname } from "../dist-DMYe8CZJ.mjs";
|
|
2
|
-
import { c as editIslandSource, i as resolveEffectiveLayoutChain, l as findIslandImports, n as scanPages, u as findStaticCssImports } from "../scan-
|
|
1
|
+
import { c as resolve, n as dirname, s as relative } from "../dist-DMYe8CZJ.mjs";
|
|
2
|
+
import { c as editIslandSource, i as resolveEffectiveLayoutChain, l as findIslandImports, n as scanPages, u as findStaticCssImports } from "../scan-X2rDDRNa.mjs";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { isCSSRequest, normalizePath } from "vite";
|
|
5
5
|
// src/pages/islands-plugin.ts
|
|
@@ -8,6 +8,11 @@ const ISLANDS_CLIENT_ENTRY_ID = "virtual:void-islands-client";
|
|
|
8
8
|
function hasIslandImports(code, filename) {
|
|
9
9
|
return findIslandImports(code, filename).length > 0;
|
|
10
10
|
}
|
|
11
|
+
/** The pages whose Markdown script `@void/md` serves to the browser. */
|
|
12
|
+
function mdClientScriptIds(resolvedConfig) {
|
|
13
|
+
const mdPlugin = resolvedConfig?.plugins?.find((plugin) => plugin.name === "void-md");
|
|
14
|
+
return new Set(mdPlugin?.api?.getClientScripts?.()?.keys() ?? []);
|
|
15
|
+
}
|
|
11
16
|
/** Resolve a relative import specifier to an absolute path by checking extensions. */
|
|
12
17
|
function resolveSpecifier(specifier, importerDir, extensions) {
|
|
13
18
|
const base = normalizePath(resolve(importerDir, specifier));
|
|
@@ -15,6 +20,61 @@ function resolveSpecifier(specifier, importerDir, extensions) {
|
|
|
15
20
|
if (existsSync(base)) return base;
|
|
16
21
|
return null;
|
|
17
22
|
}
|
|
23
|
+
/** `extensions` are tried, in order, for an island import without one. */
|
|
24
|
+
function createIslandManifest(root, extensions) {
|
|
25
|
+
const entries = /* @__PURE__ */ new Map();
|
|
26
|
+
function register(specifier, importerDir, hydrate) {
|
|
27
|
+
const absPath = resolveSpecifier(specifier, importerDir, extensions);
|
|
28
|
+
if (!absPath) return {
|
|
29
|
+
absPath,
|
|
30
|
+
islandId: specifier
|
|
31
|
+
};
|
|
32
|
+
const islandId = normalizePath(relative(root, absPath)).replace(/\.[^.]+$/, "");
|
|
33
|
+
entries.set(islandId, {
|
|
34
|
+
componentPath: absPath,
|
|
35
|
+
islandId,
|
|
36
|
+
hydrate
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
absPath,
|
|
40
|
+
islandId
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
entries,
|
|
45
|
+
register,
|
|
46
|
+
registerPages(pageScan, pagesDir) {
|
|
47
|
+
const files = [
|
|
48
|
+
...pageScan.pages.map((page) => ({
|
|
49
|
+
filePath: page.componentPath,
|
|
50
|
+
island: page.island
|
|
51
|
+
})),
|
|
52
|
+
...pageScan.layouts,
|
|
53
|
+
...pageScan.namedLayouts
|
|
54
|
+
];
|
|
55
|
+
for (const entry of files) {
|
|
56
|
+
if (!entry.island) continue;
|
|
57
|
+
const filePath = resolve(pagesDir, entry.filePath);
|
|
58
|
+
const code = readFileSync(filePath, "utf-8");
|
|
59
|
+
for (const islandImport of findIslandImports(code, filePath)) register(islandImport.specifier, dirname(filePath), islandImport.hydrate);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The island pages that match `componentPattern` and the layouts of every
|
|
66
|
+
* island page. Without a server build, the islands client entry imports their
|
|
67
|
+
* own styles and stylesheet imports.
|
|
68
|
+
*/
|
|
69
|
+
function islandCssFiles(pageScan, pagesDir, componentPattern) {
|
|
70
|
+
const files = /* @__PURE__ */ new Set();
|
|
71
|
+
for (const page of pageScan.pages) {
|
|
72
|
+
if (!page.island) continue;
|
|
73
|
+
if (componentPattern.test(page.componentPath)) files.add(normalizePath(resolve(pagesDir, page.componentPath)));
|
|
74
|
+
for (const layout of resolveEffectiveLayoutChain(page, pageScan.layouts, pageScan.namedLayouts)) files.add(normalizePath(resolve(pagesDir, layout.filePath)));
|
|
75
|
+
}
|
|
76
|
+
return files;
|
|
77
|
+
}
|
|
18
78
|
/**
|
|
19
79
|
* Whether the app has island pages (`*.island.*` files or Markdown). Their
|
|
20
80
|
* layouts can reach a stylesheet through a component, which only the module
|
|
@@ -31,6 +91,14 @@ async function hasIslandPages(root, pagesDir) {
|
|
|
31
91
|
return false;
|
|
32
92
|
}
|
|
33
93
|
}
|
|
94
|
+
/** Build config that adds the islands client entry to the client build of an app with island pages. */
|
|
95
|
+
async function islandsBuildConfig(root, pagesDir) {
|
|
96
|
+
if (!await hasIslandPages(root, pagesDir)) return;
|
|
97
|
+
return { environments: { client: { build: {
|
|
98
|
+
manifest: true,
|
|
99
|
+
rollupOptions: { input: { "islands-client": ISLANDS_CLIENT_ENTRY_ID } }
|
|
100
|
+
} } } };
|
|
101
|
+
}
|
|
34
102
|
/**
|
|
35
103
|
* The layouts of every island page, outermost first, then the pages. All
|
|
36
104
|
* island pages share one production stylesheet, so layout styles come first.
|
|
@@ -131,6 +199,25 @@ function rewriteCssImportForVirtualModule(matchedLine, specifier, sourceFilePath
|
|
|
131
199
|
const statement = matchedLine.trim();
|
|
132
200
|
return statement.endsWith(";") ? statement : statement + ";";
|
|
133
201
|
}
|
|
202
|
+
function generateIslandClientEntry(options) {
|
|
203
|
+
const uniqueIslands = /* @__PURE__ */ new Map();
|
|
204
|
+
for (const entry of options.manifest.entries.values()) uniqueIslands.set(entry.islandId, entry.componentPath);
|
|
205
|
+
const lines = [];
|
|
206
|
+
if (!options.isDev && options.styles) for (const id of options.styles) lines.push(`import ${JSON.stringify(id)};`);
|
|
207
|
+
else if (!options.isDev) for (const file of options.cssFiles) {
|
|
208
|
+
const content = readFileSync(file, "utf-8");
|
|
209
|
+
lines.push(...options.styleBlockImports?.(file, content) ?? []);
|
|
210
|
+
for (const item of findStaticCssImports(content, file)) lines.push(rewriteCssImportForVirtualModule(item.statement, item.specifier, file));
|
|
211
|
+
}
|
|
212
|
+
if (!options.needsRuntime && !options.isDev) return lines.join("\n");
|
|
213
|
+
lines.push("import { initIslands } from \"void/pages-client\";");
|
|
214
|
+
lines.push("const islands = {");
|
|
215
|
+
for (const [id, path] of uniqueIslands) lines.push(` ${JSON.stringify(id)}: () => import(${JSON.stringify(path)}),`);
|
|
216
|
+
lines.push("};");
|
|
217
|
+
lines.push(options.hydrateIsland);
|
|
218
|
+
lines.push("initIslands(islands, hydrateIsland);");
|
|
219
|
+
return lines.join("\n");
|
|
220
|
+
}
|
|
134
221
|
/** Extract CSS import statements from a file and return them as @import rules. */
|
|
135
222
|
function extractCssImports(filePath) {
|
|
136
223
|
const code = readFileSync(filePath, "utf-8");
|
|
@@ -138,8 +225,7 @@ function extractCssImports(filePath) {
|
|
|
138
225
|
}
|
|
139
226
|
/** Compute which island pages need client-side JavaScript. */
|
|
140
227
|
function computePagesNeedingClientJS(pageScan, pagesDir, resolvedConfig) {
|
|
141
|
-
const
|
|
142
|
-
const mdScriptIds = new Set(mdPlugin?.api?.getClientScripts?.()?.keys() ?? []);
|
|
228
|
+
const mdScriptIds = mdClientScriptIds(resolvedConfig);
|
|
143
229
|
const layoutDirsWithIslands = /* @__PURE__ */ new Set();
|
|
144
230
|
for (const layout of pageScan.layouts) {
|
|
145
231
|
if (!layout.island) continue;
|
|
@@ -205,4 +291,4 @@ function watchPagesForRescan(server, pagesDir, root, onRescan) {
|
|
|
205
291
|
});
|
|
206
292
|
return { flush: () => pending ?? Promise.resolve() };
|
|
207
293
|
}
|
|
208
|
-
export { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, collectIslandStyles, computePagesNeedingClientJS, editIslandSource, extractCssImports, findIslandImports, findStaticCssImports, hasIslandPages, islandStyleRoots, islandStylesPlugin, recordIslandStyles, recordedIslandStyles, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan };
|
|
294
|
+
export { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, collectIslandStyles, computePagesNeedingClientJS, createIslandManifest, editIslandSource, extractCssImports, findIslandImports, findStaticCssImports, generateIslandClientEntry, hasIslandPages, islandCssFiles, islandStyleRoots, islandStylesPlugin, islandsBuildConfig, mdClientScriptIds, recordIslandStyles, recordedIslandStyles, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as parseCacheFor, i as
|
|
2
|
-
export { CacheEntry, CacheForInput, CacheForResult, PrefetchCache, parseCacheFor };
|
|
1
|
+
import { a as LinkPrefetchValue, c as parseCacheFor, i as LinkPrefetchStrategy, n as CacheForInput, o as PrefetchCache, r as CacheForResult, s as assertLinkPrefetchValue, t as CacheEntry } from "../prefetch-NdNeubbH.mjs";
|
|
2
|
+
export { CacheEntry, CacheForInput, CacheForResult, LinkPrefetchStrategy, LinkPrefetchValue, PrefetchCache, assertLinkPrefetchValue, parseCacheFor };
|
package/dist/pages/prefetch.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as PrefetchCache, n as parseCacheFor } from "../prefetch-
|
|
1
|
+
export { t as PrefetchCache, n as assertLinkPrefetchValue, r as parseCacheFor } from "../prefetch-Dx2jIbtg.mjs";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { w as ValidationError } from "../handler-
|
|
2
|
-
import { a as handlePageMutation, i as handlePageGet, n as PageRenderResult, o as safeJsonStringify, r as flattenValidationErrors, t as PageObject } from "../protocol-
|
|
1
|
+
import { w as ValidationError } from "../handler-BR6Tvjkp.mjs";
|
|
2
|
+
import { a as handlePageMutation, i as handlePageGet, n as PageRenderResult, o as safeJsonStringify, r as flattenValidationErrors, t as PageObject } from "../protocol-CkwjASep.mjs";
|
|
3
3
|
export { PageObject, PageRenderResult, ValidationError, flattenValidationErrors, handlePageGet, handlePageMutation, safeJsonStringify };
|
package/dist/pages/protocol.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as ValidationError } from "../validation-error-
|
|
2
|
-
import { i as safeJsonStringify, n as handlePageGet, r as handlePageMutation, t as flattenValidationErrors } from "../protocol-
|
|
1
|
+
import { t as ValidationError } from "../validation-error-uAAjlsiW.mjs";
|
|
2
|
+
import { i as safeJsonStringify, n as handlePageGet, r as handlePageMutation, t as flattenValidationErrors } from "../protocol-COyySMki.mjs";
|
|
3
3
|
export { ValidationError, flattenValidationErrors, handlePageGet, handlePageMutation, safeJsonStringify };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as parsePlatformArgs } from "./platform-args-Cx1M-7bq.mjs";
|