void 0.1.6 → 0.7.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/AGENT_PROMPT.md +15 -0
- package/README.md +62 -123
- package/dist/auth-BdsJ0Aff.d.mts +43 -0
- package/dist/auth-cmd-Dx8oPKZC.mjs +43 -0
- package/dist/auth-migrations-BAtAck2g.mjs +117 -0
- package/dist/better-auth-shared-C9_GHSkR.d.mts +71 -0
- package/dist/better-auth-shared-CdYmQGry.mjs +163 -0
- package/dist/cache-W82I8ihI.mjs +47 -0
- package/dist/cancel-deploy-BOBTqqh0.mjs +59 -0
- package/dist/cf-access-Dee5cXxL.mjs +22 -0
- package/dist/chunk-DJd-R1mw.mjs +34 -0
- package/dist/cli/cli.d.mts +1 -0
- package/dist/cli/cli.mjs +1807 -0
- package/dist/client-snXOjrp1.mjs +565 -0
- package/dist/collect-CjeZgz5D.mjs +55 -0
- package/dist/config-BIa9HwVX.mjs +573 -0
- package/dist/config-BzM9Dy7T.mjs +37 -0
- package/dist/config-CvHtTM0q.mjs +30 -0
- package/dist/create-project-BIA15W7z.mjs +90 -0
- package/dist/db-DsRoMcfN.mjs +895 -0
- package/dist/defer-DcxEsVH1.mjs +49 -0
- package/dist/delete-DAP6yDc7.mjs +64 -0
- package/dist/deploy-BPKblFx6.mjs +2424 -0
- package/dist/discover-B7FkXBLB.mjs +40 -0
- package/dist/dist-DUyXJLkq.mjs +2667 -0
- package/dist/dist-Dayj3gCK.mjs +1287 -0
- package/dist/domain-BGofcQ6I.mjs +79 -0
- package/dist/dotenv-DwO4ti0Z.mjs +173 -0
- package/dist/drizzle-NnudE_UN.mjs +232 -0
- package/dist/env-CyG3tvU0.mjs +301 -0
- package/dist/env-helpers-Dr9Y7RnE.d.mts +52 -0
- package/dist/env-raw-BDL4TvdN.mjs +32 -0
- package/dist/env-types-DknSA4SO.mjs +64 -0
- package/dist/env-validation-DJKjR_8q.mjs +163 -0
- package/dist/fetch-error-BQ8sZ5Nd.mjs +266 -0
- package/dist/fetch-error-CVZ5CGA-.d.mts +20 -0
- package/dist/gen-U0Ktr4Zd.mjs +761 -0
- package/dist/handler-B0ds0OHJ.d.mts +269 -0
- package/dist/head-P-egrtFE.d.mts +45 -0
- package/dist/headers-DCXc7mDs.mjs +279 -0
- package/dist/index.d.mts +32 -0
- package/dist/index.mjs +4695 -0
- package/dist/init-C7wS5iGP.mjs +2625 -0
- package/dist/link-p2R6NbgN.mjs +49 -0
- package/dist/list-Bfel-QLc.mjs +113 -0
- package/dist/log-DXdqnmhF.mjs +26 -0
- package/dist/login-CkcXUiIu.mjs +72 -0
- package/dist/logs-DmkrRvx6.mjs +98 -0
- package/dist/magic-string.es-D6g9UnIy.mjs +1011 -0
- package/dist/mcp-CaQzfeUi.mjs +373 -0
- package/dist/node-DDfXj10V.mjs +54 -0
- package/dist/output-BwlcIYSR.mjs +139 -0
- package/dist/pages/client.d.mts +198 -0
- package/dist/pages/client.mjs +980 -0
- package/dist/pages/head-client.d.mts +15 -0
- package/dist/pages/head-client.mjs +90 -0
- package/dist/pages/head.d.mts +2 -0
- package/dist/pages/head.mjs +112 -0
- package/dist/pages/index.d.mts +38 -0
- package/dist/pages/index.mjs +76 -0
- package/dist/pages/islands-plugin.d.mts +50 -0
- package/dist/pages/islands-plugin.mjs +195 -0
- package/dist/pages/prefetch.d.mts +31 -0
- package/dist/pages/prefetch.mjs +90 -0
- package/dist/pages/protocol.d.mts +3 -0
- package/dist/pages/protocol.mjs +193 -0
- package/dist/pages/serialize.d.mts +10 -0
- package/dist/pages/serialize.mjs +14 -0
- package/dist/pathe.M-eThtNZ-D-kmWkCS.mjs +150 -0
- package/dist/plugin-inference-oZ6Ybu2_.mjs +2447 -0
- package/dist/prepare-BAtWufvm.mjs +99 -0
- package/dist/preset-D4I73kT4.mjs +221 -0
- package/dist/project-TqORyHn8.mjs +72 -0
- package/dist/project-cmd-B7lQp3F3.mjs +67 -0
- package/dist/project-slug-CKam8lF9.mjs +11 -0
- package/dist/project-tsconfig-DfkESbDL.mjs +63 -0
- package/dist/protocol-BWzXs2A2.d.mts +34 -0
- package/dist/providers-B3aMxWzP.mjs +67 -0
- package/dist/resolve-project-Br5BR03U.mjs +29 -0
- package/dist/rollback-gyC59l7U.mjs +92 -0
- package/dist/route-types-DReF1gUY.mjs +255 -0
- package/dist/routes-stub.d.mts +55 -0
- package/dist/routes-stub.mjs +1 -0
- package/dist/runner-6Ep3fNQu.mjs +123 -0
- package/dist/runner-pg-D0wWHYnr.mjs +57 -0
- package/dist/runtime/ai.d.mts +127 -0
- package/dist/runtime/ai.mjs +348 -0
- package/dist/runtime/auth-client-react.d.mts +8 -0
- package/dist/runtime/auth-client-react.mjs +6 -0
- package/dist/runtime/auth-client-solid.d.mts +8 -0
- package/dist/runtime/auth-client-solid.mjs +6 -0
- package/dist/runtime/auth-client-svelte.d.mts +8 -0
- package/dist/runtime/auth-client-svelte.mjs +6 -0
- package/dist/runtime/auth-client-vue.d.mts +8 -0
- package/dist/runtime/auth-client-vue.mjs +6 -0
- package/dist/runtime/auth-client.d.mts +8 -0
- package/dist/runtime/auth-client.mjs +6 -0
- package/dist/runtime/auth.d.mts +2 -0
- package/dist/runtime/auth.mjs +22 -0
- package/dist/runtime/better-auth-pg.d.mts +11 -0
- package/dist/runtime/better-auth-pg.mjs +51 -0
- package/dist/runtime/better-auth.d.mts +11 -0
- package/dist/runtime/better-auth.mjs +33 -0
- package/dist/runtime/client.d.mts +6 -0
- package/dist/runtime/client.mjs +5 -0
- package/dist/runtime/db-pg.d.mts +2 -0
- package/dist/runtime/db-pg.mjs +1 -0
- package/dist/runtime/db.d.mts +17 -0
- package/dist/runtime/db.mjs +30 -0
- package/dist/runtime/drizzle-arktype.d.mts +1 -0
- package/dist/runtime/drizzle-arktype.mjs +2 -0
- package/dist/runtime/drizzle-valibot.d.mts +1 -0
- package/dist/runtime/drizzle-valibot.mjs +2 -0
- package/dist/runtime/drizzle-zod.d.mts +1 -0
- package/dist/runtime/drizzle-zod.mjs +2 -0
- package/dist/runtime/env-helpers.d.mts +2 -0
- package/dist/runtime/env-helpers.mjs +173 -0
- package/dist/runtime/env-public-client.d.mts +22 -0
- package/dist/runtime/env-public-client.mjs +54 -0
- package/dist/runtime/env-public.d.mts +143 -0
- package/dist/runtime/env-public.mjs +366 -0
- package/dist/runtime/env.d.mts +13 -0
- package/dist/runtime/env.mjs +51 -0
- package/dist/runtime/fetch-stream.d.mts +51 -0
- package/dist/runtime/fetch-stream.mjs +81 -0
- package/dist/runtime/fetch.d.mts +59 -0
- package/dist/runtime/fetch.mjs +18 -0
- package/dist/runtime/handler.d.mts +3 -0
- package/dist/runtime/handler.mjs +85 -0
- package/dist/runtime/isr.d.mts +26 -0
- package/dist/runtime/isr.mjs +43 -0
- package/dist/runtime/kv.d.mts +48 -0
- package/dist/runtime/kv.mjs +106 -0
- package/dist/runtime/log.d.mts +24 -0
- package/dist/runtime/log.mjs +31 -0
- package/dist/runtime/migration-handler-pg.d.mts +6 -0
- package/dist/runtime/migration-handler-pg.mjs +85 -0
- package/dist/runtime/migration-handler.d.mts +19 -0
- package/dist/runtime/migration-handler.mjs +92 -0
- package/dist/runtime/queues.d.mts +7 -0
- package/dist/runtime/queues.mjs +8 -0
- package/dist/runtime/remote/binding-handler.d.mts +15 -0
- package/dist/runtime/remote/binding-handler.mjs +208 -0
- package/dist/runtime/remote/index.d.mts +8 -0
- package/dist/runtime/remote/index.mjs +461 -0
- package/dist/runtime/response.d.mts +14 -0
- package/dist/runtime/response.mjs +30 -0
- package/dist/runtime/sandbox.d.mts +17 -0
- package/dist/runtime/sandbox.mjs +19 -0
- package/dist/runtime/schema-d1.d.mts +1 -0
- package/dist/runtime/schema-d1.mjs +2 -0
- package/dist/runtime/schema-pg.d.mts +1 -0
- package/dist/runtime/schema-pg.mjs +2 -0
- package/dist/runtime/seed.d.mts +30 -0
- package/dist/runtime/seed.mjs +6 -0
- package/dist/runtime/storage.d.mts +7 -0
- package/dist/runtime/storage.mjs +14 -0
- package/dist/runtime/validator.d.mts +2 -0
- package/dist/runtime/validator.mjs +72 -0
- package/dist/runtime/ws-server.d.mts +26 -0
- package/dist/runtime/ws-server.mjs +296 -0
- package/dist/runtime/ws.d.mts +123 -0
- package/dist/runtime/ws.mjs +103 -0
- package/dist/scan-Ba4hFwlH.mjs +324 -0
- package/dist/scan-C6HMEIdW.mjs +318 -0
- package/dist/secret-CeRSukgM.mjs +109 -0
- package/dist/skills-ipldjlKE.mjs +62 -0
- package/dist/standard-schema-9CRjx-uR.d.mts +42 -0
- package/dist/subcommand-prompt-BKjuNAPb.mjs +349 -0
- package/dist/sveltekit.d.mts +20 -0
- package/dist/sveltekit.mjs +61 -0
- package/dist/types-mHOEwpW4.d.mts +57 -0
- package/dist/validate-CaMavMxu.mjs +146 -0
- package/dist/yarn-pnp-BFqMV_bl.mjs +196 -0
- package/getting-started-prompt.txt +26 -0
- package/package.json +322 -30
- package/schema.json +364 -0
- package/skills/migrate-vite-cloudflare-to-void/SKILL.md +175 -0
- package/skills/void/SKILL.md +75 -0
- package/skills/void/command/void.md +7 -0
- package/skills/void/docs/guide/ai.md +235 -0
- package/skills/void/docs/guide/app-types.md +103 -0
- package/skills/void/docs/guide/auth.md +257 -0
- package/skills/void/docs/guide/database/d1.md +106 -0
- package/skills/void/docs/guide/database/postgresql.md +106 -0
- package/skills/void/docs/guide/database.md +418 -0
- package/skills/void/docs/guide/deployment.md +98 -0
- package/skills/void/docs/guide/edge/headers.md +79 -0
- package/skills/void/docs/guide/edge/prerendering.md +83 -0
- package/skills/void/docs/guide/edge/redirects.md +116 -0
- package/skills/void/docs/guide/edge/revalidation.md +131 -0
- package/skills/void/docs/guide/edge/rewrites.md +354 -0
- package/skills/void/docs/guide/edge/static-assets.md +72 -0
- package/skills/void/docs/guide/env-vars.md +298 -0
- package/skills/void/docs/guide/index.md +80 -0
- package/skills/void/docs/guide/jobs.md +91 -0
- package/skills/void/docs/guide/kv.md +107 -0
- package/skills/void/docs/guide/pages-routing/actions-and-forms.md +419 -0
- package/skills/void/docs/guide/pages-routing/head.md +130 -0
- package/skills/void/docs/guide/pages-routing/islands.md +405 -0
- package/skills/void/docs/guide/pages-routing/layouts.md +362 -0
- package/skills/void/docs/guide/pages-routing/loaders.md +267 -0
- package/skills/void/docs/guide/pages-routing/markdown.md +625 -0
- package/skills/void/docs/guide/pages-routing/overview.md +236 -0
- package/skills/void/docs/guide/pages-routing/view-transitions.md +140 -0
- package/skills/void/docs/guide/queues.md +140 -0
- package/skills/void/docs/guide/quickstart.md +233 -0
- package/skills/void/docs/guide/remote-dev.md +67 -0
- package/skills/void/docs/guide/sandboxes.md +82 -0
- package/skills/void/docs/guide/server-routing.md +246 -0
- package/skills/void/docs/guide/ssg.md +74 -0
- package/skills/void/docs/guide/ssr.md +105 -0
- package/skills/void/docs/guide/storage.md +67 -0
- package/skills/void/docs/guide/type-safety.md +179 -0
- package/skills/void/docs/guide/typed-fetch.md +113 -0
- package/skills/void/docs/guide/websockets.md +190 -0
- package/skills/void/docs/index.md +48 -0
- package/skills/void/docs/integrations/agents.md +84 -0
- package/skills/void/docs/integrations/cloudflare.md +284 -0
- package/skills/void/docs/integrations/frameworks/analog.md +182 -0
- package/skills/void/docs/integrations/frameworks/astro.md +197 -0
- package/skills/void/docs/integrations/frameworks/nuxt.md +164 -0
- package/skills/void/docs/integrations/frameworks/overview.md +136 -0
- package/skills/void/docs/integrations/frameworks/react-router.md +137 -0
- package/skills/void/docs/integrations/frameworks/sveltekit.md +191 -0
- package/skills/void/docs/integrations/frameworks/tanstack-start.md +140 -0
- package/skills/void/docs/integrations/hono.md +97 -0
- package/skills/void/docs/integrations/nodejs-bun-deno.md +210 -0
- package/skills/void/docs/node_modules/@iconify/vue/README.md +408 -0
- package/skills/void/docs/node_modules/@iconify/vue/offline/readme.md +5 -0
- package/skills/void/docs/node_modules/@voidzero-dev/vitepress-theme/README.md +103 -0
- package/skills/void/docs/node_modules/oxc-minify/README.md +78 -0
- package/skills/void/docs/node_modules/reka-ui/README.md +80 -0
- package/skills/void/docs/node_modules/vitepress/README.md +28 -0
- package/skills/void/docs/node_modules/vitepress/template/api-examples.md +49 -0
- package/skills/void/docs/node_modules/vitepress/template/index.md +28 -0
- package/skills/void/docs/node_modules/vitepress/template/markdown-examples.md +85 -0
- package/skills/void/docs/node_modules/vitepress-plugin-group-icons/README.md +101 -0
- package/skills/void/docs/node_modules/void/AGENTS.md +204 -0
- package/skills/void/docs/node_modules/void/AGENT_PROMPT.md +15 -0
- package/skills/void/docs/node_modules/void/README.md +89 -0
- package/skills/void/docs/node_modules/void/node_modules/@clack/prompts/CHANGELOG.md +591 -0
- package/skills/void/docs/node_modules/void/node_modules/@clack/prompts/README.md +375 -0
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/sandbox/README.md +174 -0
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/vite-plugin/README.md +37 -0
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/workers-types/README.md +135 -0
- package/skills/void/docs/node_modules/void/node_modules/@electric-sql/pglite/README.md +189 -0
- package/skills/void/docs/node_modules/void/node_modules/@hono/oauth-providers/CHANGELOG.md +143 -0
- package/skills/void/docs/node_modules/void/node_modules/@hono/oauth-providers/README.md +1272 -0
- package/skills/void/docs/node_modules/void/node_modules/@napi-rs/keyring/README.md +19 -0
- package/skills/void/docs/node_modules/void/node_modules/@types/better-sqlite3/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@types/node/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@types/pg/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@typescript/native-preview/README.md +22 -0
- package/skills/void/docs/node_modules/void/node_modules/@typescript/native-preview/vendor/vscode-jsonrpc/README.md +69 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/README.md +152 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@shikijs/engine-javascript/README.md +9 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@shikijs/transformers/README.md +9 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@types/node/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/gray-matter/CHANGELOG.md +24 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/gray-matter/README.md +565 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-exit/README.md +124 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-anchor/README.md +600 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-attrs/README.md +386 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-container/README.md +95 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-emoji/README.md +101 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathe/README.md +73 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/shiki/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/tinyglobby/README.md +25 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/tsdown/README.md +55 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite/LICENSE.md +2230 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite/README.md +20 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vue/README.md +58 -0
- package/skills/void/docs/node_modules/void/node_modules/arktype/README.md +165 -0
- package/skills/void/docs/node_modules/void/node_modules/better-auth/LICENSE.md +20 -0
- package/skills/void/docs/node_modules/void/node_modules/better-auth/README.md +32 -0
- package/skills/void/docs/node_modules/void/node_modules/better-sqlite3/README.md +99 -0
- package/skills/void/docs/node_modules/void/node_modules/blake3-jit/README.md +108 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-arktype/README.md +51 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-kit/README.md +79 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-orm/README.md +44 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-valibot/README.md +51 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-zod/README.md +65 -0
- package/skills/void/docs/node_modules/void/node_modules/es-module-lexer/README.md +390 -0
- package/skills/void/docs/node_modules/void/node_modules/estree-walker/README.md +48 -0
- package/skills/void/docs/node_modules/void/node_modules/hono/README.md +85 -0
- package/skills/void/docs/node_modules/void/node_modules/ignore/README.md +452 -0
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/CHANGELOG.md +76 -0
- package/{LICENSE → skills/void/docs/node_modules/void/node_modules/jsonc-parser/LICENSE.md} +21 -21
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/README.md +364 -0
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/SECURITY.md +41 -0
- package/skills/void/docs/node_modules/void/node_modules/magic-string/README.md +325 -0
- package/skills/void/docs/node_modules/void/node_modules/ofetch/README.md +398 -0
- package/skills/void/docs/node_modules/void/node_modules/pathe/README.md +73 -0
- package/skills/void/docs/node_modules/void/node_modules/pg/README.md +95 -0
- package/skills/void/docs/node_modules/void/node_modules/pglite-server/LICENSE.md +21 -0
- package/skills/void/docs/node_modules/void/node_modules/pglite-server/README.md +135 -0
- package/skills/void/docs/node_modules/void/node_modules/picocolors/README.md +21 -0
- package/skills/void/docs/node_modules/void/node_modules/tinyglobby/README.md +25 -0
- package/skills/void/docs/node_modules/void/node_modules/tsdown/README.md +55 -0
- package/skills/void/docs/node_modules/void/node_modules/valibot/LICENSE.md +9 -0
- package/skills/void/docs/node_modules/void/node_modules/valibot/README.md +94 -0
- package/skills/void/docs/node_modules/void/node_modules/vite/LICENSE.md +2230 -0
- package/skills/void/docs/node_modules/void/node_modules/vite/README.md +20 -0
- package/skills/void/docs/node_modules/void/node_modules/wrangler/README.md +63 -0
- package/skills/void/docs/node_modules/void/node_modules/zod/README.md +191 -0
- package/skills/void/docs/node_modules/void/skills/migrate-vite-cloudflare-to-void/SKILL.md +175 -0
- package/skills/void/docs/node_modules/void/skills/void/SKILL.md +75 -0
- package/skills/void/docs/node_modules/void/skills/void/command/void.md +7 -0
- package/skills/void/docs/reference/api.md +917 -0
- package/skills/void/docs/reference/cli.md +561 -0
- package/skills/void/docs/reference/config.md +408 -0
- package/skills/void/docs/reference/resource-inference.md +149 -0
- package/skills/void/docs/reference/structure.md +176 -0
- package/.npmignore +0 -29
- package/.travis.yml +0 -9
- package/favicon.ico +0 -0
- package/index.js +0 -14
- package/lib/Job.js +0 -150
- package/lib/Void.js +0 -99
- package/lib/scan.js +0 -19
- package/test/credentials.js +0 -20
- package/test/job.js +0 -64
- package/test/static/dir1/test6.html +0 -0
- package/test/static/dir2/test7.html +0 -0
- package/test/static/dir2/test8.html +0 -0
- package/test/static/dir2/test9.html +0 -0
- package/test/static/test1.html +0 -0
- package/test/static/test2.html +0 -0
- package/test/static/test3.html +0 -0
- package/test/void.js +0 -31
- /package/{test/static/dir1/test4.html → skills/void/docs/integrations/auth-providers.md} +0 -0
- /package/{test/static/dir1/test5.html → skills/void/docs/integrations/payment-processors.md} +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { n as HeadDescriptor } from "../head-P-egrtFE.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/pages/head-client.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Mark SSR-rendered head tags so they are cleaned up on the first SPA navigation.
|
|
6
|
+
* Call once after hydration with the initial page's head descriptor.
|
|
7
|
+
*/
|
|
8
|
+
declare function initClientHead(head: HeadDescriptor | undefined): void;
|
|
9
|
+
/**
|
|
10
|
+
* Apply head changes on SPA navigation.
|
|
11
|
+
* Preserves existing managed tags when their final attributes are unchanged.
|
|
12
|
+
*/
|
|
13
|
+
declare function applyClientHead(head: HeadDescriptor | undefined): void;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { applyClientHead, initClientHead };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//#region src/pages/head-client.ts
|
|
2
|
+
const ATTR = "data-void-head";
|
|
3
|
+
function elementDescriptorSignature(descriptor) {
|
|
4
|
+
const attrs = Object.entries(descriptor.attrs).sort(([a], [b]) => a.localeCompare(b));
|
|
5
|
+
return `${encodeURIComponent(descriptor.tag)}:${attrs.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&")}`;
|
|
6
|
+
}
|
|
7
|
+
function elementSignature(el) {
|
|
8
|
+
const attrs = {};
|
|
9
|
+
for (const attr of Array.from(el.attributes)) if (attr.name !== ATTR) attrs[attr.name] = attr.value;
|
|
10
|
+
return elementDescriptorSignature({
|
|
11
|
+
tag: el.tagName.toLowerCase(),
|
|
12
|
+
attrs
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function createHeadElement(descriptor) {
|
|
16
|
+
const el = document.createElement(descriptor.tag);
|
|
17
|
+
for (const [key, value] of Object.entries(descriptor.attrs)) el.setAttribute(key, value);
|
|
18
|
+
el.setAttribute(ATTR, "");
|
|
19
|
+
return el;
|
|
20
|
+
}
|
|
21
|
+
function collectDesiredHeadElements(head) {
|
|
22
|
+
const desired = [];
|
|
23
|
+
if (head.meta) for (const entry of head.meta) {
|
|
24
|
+
const attrs = {};
|
|
25
|
+
if (entry.charset) attrs.charset = entry.charset;
|
|
26
|
+
if (entry.name) attrs.name = entry.name;
|
|
27
|
+
if (entry.property) attrs.property = entry.property;
|
|
28
|
+
if (entry.content !== void 0) attrs.content = entry.content;
|
|
29
|
+
desired.push({
|
|
30
|
+
tag: "meta",
|
|
31
|
+
attrs
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (head.link) for (const entry of head.link) {
|
|
35
|
+
const attrs = {};
|
|
36
|
+
for (const [key, value] of Object.entries(entry)) if (value != null) attrs[key] = value;
|
|
37
|
+
desired.push({
|
|
38
|
+
tag: "link",
|
|
39
|
+
attrs
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return desired;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Mark SSR-rendered head tags so they are cleaned up on the first SPA navigation.
|
|
46
|
+
* Call once after hydration with the initial page's head descriptor.
|
|
47
|
+
*/
|
|
48
|
+
function initClientHead(head) {
|
|
49
|
+
if (!head) return;
|
|
50
|
+
if (head.meta) for (const entry of head.meta) {
|
|
51
|
+
const selector = entry.charset ? "meta[charset]" : entry.property ? `meta[property="${entry.property}"]` : entry.name ? `meta[name="${entry.name}"]` : null;
|
|
52
|
+
if (!selector) continue;
|
|
53
|
+
const el = document.head.querySelector(selector);
|
|
54
|
+
if (el) el.setAttribute(ATTR, "");
|
|
55
|
+
}
|
|
56
|
+
if (head.link) for (const entry of head.link) {
|
|
57
|
+
const el = document.head.querySelector(`link[rel="${entry.rel}"][href="${entry.href}"]`);
|
|
58
|
+
if (el) el.setAttribute(ATTR, "");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Apply head changes on SPA navigation.
|
|
63
|
+
* Preserves existing managed tags when their final attributes are unchanged.
|
|
64
|
+
*/
|
|
65
|
+
function applyClientHead(head) {
|
|
66
|
+
const existing = /* @__PURE__ */ new Map();
|
|
67
|
+
for (const el of document.head.querySelectorAll(`[${ATTR}]`)) {
|
|
68
|
+
const signature = elementSignature(el);
|
|
69
|
+
const elements = existing.get(signature);
|
|
70
|
+
if (elements) elements.push(el);
|
|
71
|
+
else existing.set(signature, [el]);
|
|
72
|
+
}
|
|
73
|
+
const desiredElements = [];
|
|
74
|
+
for (const descriptor of head ? collectDesiredHeadElements(head) : []) {
|
|
75
|
+
const signature = elementDescriptorSignature(descriptor);
|
|
76
|
+
const elements = existing.get(signature);
|
|
77
|
+
const preserved = elements?.shift();
|
|
78
|
+
if (elements && elements.length === 0) existing.delete(signature);
|
|
79
|
+
desiredElements.push(preserved ?? createHeadElement(descriptor));
|
|
80
|
+
}
|
|
81
|
+
for (const elements of existing.values()) for (const el of elements) el.remove();
|
|
82
|
+
let cursor = document.head.querySelector(`[${ATTR}]`);
|
|
83
|
+
for (const el of desiredElements) {
|
|
84
|
+
if (el !== cursor) document.head.insertBefore(el, cursor);
|
|
85
|
+
cursor = el.nextSibling;
|
|
86
|
+
}
|
|
87
|
+
if (head?.title !== void 0) document.title = head.title;
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { applyClientHead, initClientHead };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//#region src/pages/head.ts
|
|
2
|
+
/**
|
|
3
|
+
* Merge head descriptors with precedence: page > middleware > config.
|
|
4
|
+
*
|
|
5
|
+
* - `title`: page wins; `titleTemplate` from config wraps it (`%s` replaced)
|
|
6
|
+
* - `meta`: page overrides entries with same `name`/`property`; others appended
|
|
7
|
+
* - `link`/`script`: concatenated (config first, then middleware, then page)
|
|
8
|
+
* - `htmlAttrs`/`bodyAttrs`: shallow merge, page wins conflicts
|
|
9
|
+
*/
|
|
10
|
+
function resolveHead(configHead, middlewareHead, pageHead) {
|
|
11
|
+
if (!configHead && !middlewareHead && !pageHead) return;
|
|
12
|
+
const result = {};
|
|
13
|
+
const title = pageHead?.title ?? middlewareHead?.title ?? configHead?.title;
|
|
14
|
+
if (title !== void 0) {
|
|
15
|
+
const template = configHead?.titleTemplate;
|
|
16
|
+
result.title = template ? template.replace("%s", title) : title;
|
|
17
|
+
}
|
|
18
|
+
const metaMap = /* @__PURE__ */ new Map();
|
|
19
|
+
const metaOrder = [];
|
|
20
|
+
for (const layer of [
|
|
21
|
+
configHead,
|
|
22
|
+
middlewareHead,
|
|
23
|
+
pageHead
|
|
24
|
+
]) {
|
|
25
|
+
if (!layer?.meta) continue;
|
|
26
|
+
for (const entry of layer.meta) {
|
|
27
|
+
const key = entry.charset ? "charset" : entry.property ? `property:${entry.property}` : `name:${entry.name ?? ""}`;
|
|
28
|
+
if (!metaMap.has(key)) metaOrder.push(key);
|
|
29
|
+
metaMap.set(key, entry);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (metaMap.size > 0) result.meta = metaOrder.map((key) => metaMap.get(key));
|
|
33
|
+
const links = [];
|
|
34
|
+
for (const layer of [
|
|
35
|
+
configHead,
|
|
36
|
+
middlewareHead,
|
|
37
|
+
pageHead
|
|
38
|
+
]) if (layer?.link) links.push(...layer.link);
|
|
39
|
+
if (links.length > 0) result.link = links;
|
|
40
|
+
const scripts = [];
|
|
41
|
+
for (const layer of [
|
|
42
|
+
configHead,
|
|
43
|
+
middlewareHead,
|
|
44
|
+
pageHead
|
|
45
|
+
]) if (layer?.script) scripts.push(...layer.script);
|
|
46
|
+
if (scripts.length > 0) result.script = scripts;
|
|
47
|
+
const htmlAttrs = {};
|
|
48
|
+
let hasHtmlAttrs = false;
|
|
49
|
+
for (const layer of [
|
|
50
|
+
configHead,
|
|
51
|
+
middlewareHead,
|
|
52
|
+
pageHead
|
|
53
|
+
]) if (layer?.htmlAttrs) {
|
|
54
|
+
Object.assign(htmlAttrs, layer.htmlAttrs);
|
|
55
|
+
hasHtmlAttrs = true;
|
|
56
|
+
}
|
|
57
|
+
if (hasHtmlAttrs) result.htmlAttrs = htmlAttrs;
|
|
58
|
+
const bodyAttrs = {};
|
|
59
|
+
let hasBodyAttrs = false;
|
|
60
|
+
for (const layer of [
|
|
61
|
+
configHead,
|
|
62
|
+
middlewareHead,
|
|
63
|
+
pageHead
|
|
64
|
+
]) if (layer?.bodyAttrs) {
|
|
65
|
+
Object.assign(bodyAttrs, layer.bodyAttrs);
|
|
66
|
+
hasBodyAttrs = true;
|
|
67
|
+
}
|
|
68
|
+
if (hasBodyAttrs) result.bodyAttrs = bodyAttrs;
|
|
69
|
+
if (result.title === void 0 && !result.meta && !result.link && !result.script && !result.htmlAttrs && !result.bodyAttrs) return;
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
function escapeHtml(s) {
|
|
73
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
74
|
+
}
|
|
75
|
+
/** Serialize a HeadDescriptor to HTML tags for injection into `<head>`. */
|
|
76
|
+
function renderHeadToString(head) {
|
|
77
|
+
const parts = [];
|
|
78
|
+
if (head.title !== void 0) parts.push(`<title>${escapeHtml(head.title)}</title>`);
|
|
79
|
+
if (head.meta) for (const entry of head.meta) {
|
|
80
|
+
const attrs = [];
|
|
81
|
+
if (entry.charset) attrs.push(`charset="${escapeHtml(entry.charset)}"`);
|
|
82
|
+
if (entry.name) attrs.push(`name="${escapeHtml(entry.name)}"`);
|
|
83
|
+
if (entry.property) attrs.push(`property="${escapeHtml(entry.property)}"`);
|
|
84
|
+
if (entry.content !== void 0) attrs.push(`content="${escapeHtml(entry.content)}"`);
|
|
85
|
+
parts.push(`<meta ${attrs.join(" ")}>`);
|
|
86
|
+
}
|
|
87
|
+
if (head.link) for (const entry of head.link) {
|
|
88
|
+
const attrs = Object.entries(entry).filter(([, v]) => v != null).map(([k, v]) => `${k}="${escapeHtml(v)}"`).join(" ");
|
|
89
|
+
parts.push(`<link ${attrs}>`);
|
|
90
|
+
}
|
|
91
|
+
if (head.script) for (const entry of head.script) {
|
|
92
|
+
const { innerHTML, ...rest } = entry;
|
|
93
|
+
const attrs = Object.entries(rest).filter(([, v]) => v != null).map(([k, v]) => `${k}="${escapeHtml(v)}"`).join(" ");
|
|
94
|
+
if (innerHTML) parts.push(`<script${attrs ? " " + attrs : ""}>${innerHTML}<\/script>`);
|
|
95
|
+
else if (attrs) parts.push(`<script ${attrs}><\/script>`);
|
|
96
|
+
}
|
|
97
|
+
return parts.join("\n");
|
|
98
|
+
}
|
|
99
|
+
/** Serialize htmlAttrs to an attribute string (includes leading space). */
|
|
100
|
+
function renderHtmlAttrs(head) {
|
|
101
|
+
if (!head.htmlAttrs) return "";
|
|
102
|
+
const attrs = Object.entries(head.htmlAttrs).map(([k, v]) => `${k}="${escapeHtml(v)}"`).join(" ");
|
|
103
|
+
return attrs ? " " + attrs : "";
|
|
104
|
+
}
|
|
105
|
+
/** Serialize bodyAttrs to an attribute string (includes leading space). */
|
|
106
|
+
function renderBodyAttrs(head) {
|
|
107
|
+
if (!head.bodyAttrs) return "";
|
|
108
|
+
const attrs = Object.entries(head.bodyAttrs).map(([k, v]) => `${k}="${escapeHtml(v)}"`).join(" ");
|
|
109
|
+
return attrs ? " " + attrs : "";
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveHead };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { a as renderHtmlAttrs, i as renderHeadToString, n as HeadDescriptor, o as resolveHead, r as renderBodyAttrs, t as HeadConfig } from "../head-P-egrtFE.mjs";
|
|
2
|
+
import { i as PageScanResult, n as NamedLayoutDefinition, r as PageDefinition, t as LayoutDefinition } from "../types-mHOEwpW4.mjs";
|
|
3
|
+
import { serializePageData } from "./serialize.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/pages/layout-resolution.d.ts
|
|
6
|
+
/** Resolve the layout chain for a component (innermost last) */
|
|
7
|
+
declare function resolveLayoutChain(componentId: string, layouts: Array<LayoutDefinition>): Array<LayoutDefinition>;
|
|
8
|
+
/** Walk up directory tree to find closest _layouts/<name> */
|
|
9
|
+
declare function resolveNamedLayout(name: string, componentId: string, namedLayouts: Array<NamedLayoutDefinition>): NamedLayoutDefinition | null;
|
|
10
|
+
/** Resolve effective layout chain accounting for named layout selection */
|
|
11
|
+
declare function resolveEffectiveLayoutChain(page: {
|
|
12
|
+
componentId: string;
|
|
13
|
+
layout?: string | false;
|
|
14
|
+
}, layouts: Array<LayoutDefinition>, namedLayouts: Array<NamedLayoutDefinition>): Array<LayoutDefinition | NamedLayoutDefinition>;
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/pages/scan.d.ts
|
|
17
|
+
declare function scanPages(root: string, options?: {
|
|
18
|
+
output?: "server" | "static";
|
|
19
|
+
}): Promise<PageScanResult>;
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/pages/manifest.d.ts
|
|
22
|
+
/**
|
|
23
|
+
* Generates the component import map and layout tree as code strings.
|
|
24
|
+
* Used by both SSR renderer and client entry virtual modules.
|
|
25
|
+
*/
|
|
26
|
+
declare function generateComponentManifest(scan: PageScanResult, pagesDir: string): string;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/pages/static-data.d.ts
|
|
29
|
+
interface StaticPageDataBuildOptions {
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
fastPath: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface ResolveStaticPageDataBuildOptionsInput {
|
|
34
|
+
publicDir?: string | false;
|
|
35
|
+
}
|
|
36
|
+
declare function resolveStaticPageDataBuildOptions(root: string, options?: ResolveStaticPageDataBuildOptionsInput): StaticPageDataBuildOptions;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { type HeadConfig, type HeadDescriptor, type LayoutDefinition, type NamedLayoutDefinition, type PageDefinition, type PageScanResult, type StaticPageDataBuildOptions, generateComponentManifest, renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveEffectiveLayoutChain, resolveHead, resolveLayoutChain, resolveNamedLayout, resolveStaticPageDataBuildOptions, scanPages, serializePageData };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { a as join } from "../pathe.M-eThtNZ-D-kmWkCS.mjs";
|
|
2
|
+
import { f as readConfig } from "../config-BIa9HwVX.mjs";
|
|
3
|
+
import { a as resolveNamedLayout, i as resolveLayoutIds, n as resolveEffectiveLayoutChain, r as resolveLayoutChain, t as scanPages } from "../scan-Ba4hFwlH.mjs";
|
|
4
|
+
import { i as parseRedirectsFile } from "../headers-DCXc7mDs.mjs";
|
|
5
|
+
import { renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveHead } from "./head.mjs";
|
|
6
|
+
import { serializePageData } from "./serialize.mjs";
|
|
7
|
+
//#region src/pages/manifest.ts
|
|
8
|
+
/**
|
|
9
|
+
* Generates the component import map and layout tree as code strings.
|
|
10
|
+
* Used by both SSR renderer and client entry virtual modules.
|
|
11
|
+
*/
|
|
12
|
+
function generateComponentManifest(scan, pagesDir) {
|
|
13
|
+
const lines = [];
|
|
14
|
+
lines.push("const components = {");
|
|
15
|
+
for (const page of scan.pages) {
|
|
16
|
+
const importPath = `${pagesDir}/${page.componentPath}`;
|
|
17
|
+
lines.push(` ${JSON.stringify(page.componentId)}: () => import(${JSON.stringify(importPath)}),`);
|
|
18
|
+
}
|
|
19
|
+
for (const layout of scan.layouts) {
|
|
20
|
+
const importPath = `${pagesDir}/${layout.filePath}`;
|
|
21
|
+
const layoutId = layout.directory ? `${layout.directory}/layout` : "layout";
|
|
22
|
+
lines.push(` ${JSON.stringify(layoutId)}: () => import(${JSON.stringify(importPath)}),`);
|
|
23
|
+
}
|
|
24
|
+
for (const nl of scan.namedLayouts) {
|
|
25
|
+
const importPath = `${pagesDir}/${nl.filePath}`;
|
|
26
|
+
const layoutId = nl.directory ? `${nl.directory}/_layouts/${nl.name}` : `_layouts/${nl.name}`;
|
|
27
|
+
lines.push(` ${JSON.stringify(layoutId)}: () => import(${JSON.stringify(importPath)}),`);
|
|
28
|
+
}
|
|
29
|
+
lines.push("};");
|
|
30
|
+
lines.push("const layoutTree = {");
|
|
31
|
+
for (const page of scan.pages) {
|
|
32
|
+
const chain = resolveLayoutIds(page, scan.layouts, scan.namedLayouts);
|
|
33
|
+
if (chain.length > 0) lines.push(` ${JSON.stringify(page.componentId)}: ${JSON.stringify(chain)},`);
|
|
34
|
+
}
|
|
35
|
+
lines.push("};");
|
|
36
|
+
lines.push("const routeMeta = {");
|
|
37
|
+
for (const page of scan.pages) if (page.island) lines.push(` ${JSON.stringify(page.componentId)}: { island: true },`);
|
|
38
|
+
lines.push("};");
|
|
39
|
+
lines.push("const routes = [");
|
|
40
|
+
for (const page of scan.pages) {
|
|
41
|
+
const regex = patternToRegex(page.pattern);
|
|
42
|
+
lines.push(` { pattern: ${regex}, id: ${JSON.stringify(page.componentId)} },`);
|
|
43
|
+
}
|
|
44
|
+
lines.push("];");
|
|
45
|
+
lines.push(`function matchRoute(url) {
|
|
46
|
+
const path = new URL(url, "http://x").pathname;
|
|
47
|
+
for (const r of routes) {
|
|
48
|
+
if (r.pattern.test(path)) return r.id;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}`);
|
|
52
|
+
return lines.join("\n");
|
|
53
|
+
}
|
|
54
|
+
function patternToRegex(pattern) {
|
|
55
|
+
return `/^${pattern.replace(/:[^/{}]+\{\.\+\}/g, "(.+)").replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/, "(.*)").replace(/:[^/]+/g, "([^/]+)").replace(/\//g, "\\/")}$/`;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/pages/static-data.ts
|
|
59
|
+
function resolveStaticPageDataBuildOptions(root, options = {}) {
|
|
60
|
+
const config = readConfig(root);
|
|
61
|
+
const enabled = config.output === "static";
|
|
62
|
+
const r = config.routing;
|
|
63
|
+
const hasConfigRouting = r?.redirects !== void 0 && Object.keys(r.redirects).length > 0 || r?.rewrites !== void 0 && Object.keys(r.rewrites).length > 0 || r?.fallbacks !== void 0 && Object.keys(r.fallbacks).length > 0;
|
|
64
|
+
const redirectDirs = [root];
|
|
65
|
+
if (options.publicDir !== false) redirectDirs.push(options.publicDir ?? join(root, "public"));
|
|
66
|
+
const hasRedirectsFile = redirectDirs.some((dir) => {
|
|
67
|
+
const parsed = parseRedirectsFile(dir);
|
|
68
|
+
return parsed != null && parsed.rules.length > 0;
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
enabled,
|
|
72
|
+
fastPath: enabled && !hasConfigRouting && !hasRedirectsFile
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { generateComponentManifest, renderBodyAttrs, renderHeadToString, renderHtmlAttrs, resolveEffectiveLayoutChain, resolveHead, resolveLayoutChain, resolveNamedLayout, resolveStaticPageDataBuildOptions, scanPages, serializePageData };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { i as PageScanResult } from "../types-mHOEwpW4.mjs";
|
|
2
|
+
import { ResolvedConfig, ViteDevServer } from "vite";
|
|
3
|
+
|
|
4
|
+
//#region src/pages/islands-plugin.d.ts
|
|
5
|
+
declare const ISLANDS_RENDERER_ID = "virtual:void-islands-renderer";
|
|
6
|
+
declare const ISLANDS_CLIENT_ENTRY_ID = "virtual:void-islands-client";
|
|
7
|
+
interface IslandEntry {
|
|
8
|
+
componentPath: string;
|
|
9
|
+
islandId: string;
|
|
10
|
+
hydrate: string;
|
|
11
|
+
}
|
|
12
|
+
/** Resolve a relative import specifier to an absolute path by checking extensions. */
|
|
13
|
+
declare function resolveSpecifier(specifier: string, importerDir: string, extensions: Array<string>): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Check whether the islands client bundle is needed by scanning file contents.
|
|
16
|
+
* Returns true if any island/layout file has island imports or CSS,
|
|
17
|
+
* or any .md file has a `<script>` block.
|
|
18
|
+
*/
|
|
19
|
+
declare function needsIslandClientBundle(dir: string, islandFilePattern: RegExp, checkStyleBlocks: boolean): boolean;
|
|
20
|
+
/** Check if a file has CSS import statements (JS-style imports). */
|
|
21
|
+
declare function fileHasCssImports(filePath: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Rewrite a matched CSS import line so relative specifiers resolve from the
|
|
24
|
+
* virtual module. Absolute and bare specifiers are kept as-is.
|
|
25
|
+
*/
|
|
26
|
+
declare function rewriteCssImportForVirtualModule(matchedLine: string, specifier: string, sourceFilePath: string): string;
|
|
27
|
+
/** Extract CSS import statements from a file and return them as @import rules. */
|
|
28
|
+
declare function extractCssImports(filePath: string): string;
|
|
29
|
+
/** Rebuild islandCssMap from current file contents. */
|
|
30
|
+
declare function rebuildIslandCssMap(pageScan: PageScanResult, pagesDir: string, islandCssMap: Map<string, Array<string>>, fileHasCssFn: (filePath: string) => boolean): void;
|
|
31
|
+
/** Compute which island pages need client-side JavaScript. */
|
|
32
|
+
declare function computePagesNeedingClientJS(pageScan: PageScanResult, pagesDir: string, resolvedConfig: ResolvedConfig | null): Set<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Configure the Vite dev server for island CSS serving.
|
|
35
|
+
* Sets up file watching and a middleware for serving virtual CSS modules.
|
|
36
|
+
*/
|
|
37
|
+
declare function configureIslandCssServer(server: ViteDevServer, islandCssFiles: Set<string>, viteRoot: string, rebuildCssMap: () => void): void;
|
|
38
|
+
/**
|
|
39
|
+
* Watch the pages directory for structural changes (add/remove) and .md content
|
|
40
|
+
* changes (frontmatter layout field) so that new layouts and named layouts are
|
|
41
|
+
* picked up without a dev server restart.
|
|
42
|
+
*
|
|
43
|
+
* Returns a `flush()` function that resolves when any pending rescan completes
|
|
44
|
+
* (useful for tests).
|
|
45
|
+
*/
|
|
46
|
+
declare function watchPagesForRescan(server: ViteDevServer, pagesDir: string, root: string, onRescan: (pageScan: PageScanResult) => void): {
|
|
47
|
+
flush: () => Promise<void>;
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, IslandEntry, computePagesNeedingClientJS, configureIslandCssServer, extractCssImports, fileHasCssImports, needsIslandClientBundle, rebuildIslandCssMap, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan };
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { n as dirname, s as resolve } from "../pathe.M-eThtNZ-D-kmWkCS.mjs";
|
|
2
|
+
import { n as resolveEffectiveLayoutChain, t as scanPages } from "../scan-Ba4hFwlH.mjs";
|
|
3
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
4
|
+
import { normalizePath } from "vite";
|
|
5
|
+
//#region src/pages/islands-plugin.ts
|
|
6
|
+
const ISLANDS_RENDERER_ID = "virtual:void-islands-renderer";
|
|
7
|
+
const ISLANDS_CLIENT_ENTRY_ID = "virtual:void-islands-client";
|
|
8
|
+
/** Resolve a relative import specifier to an absolute path by checking extensions. */
|
|
9
|
+
function resolveSpecifier(specifier, importerDir, extensions) {
|
|
10
|
+
const base = normalizePath(resolve(importerDir, specifier));
|
|
11
|
+
for (const ext of extensions) if (existsSync(base + ext)) return base + ext;
|
|
12
|
+
if (existsSync(base)) return base;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check whether the islands client bundle is needed by scanning file contents.
|
|
17
|
+
* Returns true if any island/layout file has island imports or CSS,
|
|
18
|
+
* or any .md file has a `<script>` block.
|
|
19
|
+
*/
|
|
20
|
+
function needsIslandClientBundle(dir, islandFilePattern, checkStyleBlocks) {
|
|
21
|
+
const importAttrRe = /import\s+\w+\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:/;
|
|
22
|
+
const cssImportRe = /import\b[^"']*["'][^"']+\.(?:css|scss|sass|less|styl|stylus|pcss|postcss)["']/;
|
|
23
|
+
const mdScriptRe = /^<script\b/m;
|
|
24
|
+
const styleRe = checkStyleBlocks ? /<style\b/ : null;
|
|
25
|
+
try {
|
|
26
|
+
for (const entry of readdirSync(dir, {
|
|
27
|
+
withFileTypes: true,
|
|
28
|
+
recursive: true
|
|
29
|
+
})) {
|
|
30
|
+
if (!entry.isFile()) continue;
|
|
31
|
+
const name = entry.name;
|
|
32
|
+
if (islandFilePattern.test(name) || name.startsWith("layout.") || name.startsWith("_")) {
|
|
33
|
+
const content = readFileSync(resolve(entry.parentPath, name), "utf-8");
|
|
34
|
+
if (importAttrRe.test(content)) return true;
|
|
35
|
+
if (styleRe && styleRe.test(content)) return true;
|
|
36
|
+
if (cssImportRe.test(content)) return true;
|
|
37
|
+
}
|
|
38
|
+
if (name.endsWith(".md")) {
|
|
39
|
+
const content = readFileSync(resolve(entry.parentPath, name), "utf-8");
|
|
40
|
+
if (mdScriptRe.test(content)) return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} catch {}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
/** Check if a file has CSS import statements (JS-style imports). */
|
|
47
|
+
function fileHasCssImports(filePath) {
|
|
48
|
+
try {
|
|
49
|
+
const code = readFileSync(filePath, "utf-8");
|
|
50
|
+
return /import\b[^"']*["'][^"']+\.(?:css|scss|sass|less|styl|stylus|pcss|postcss)["']/.test(code);
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Rewrite a matched CSS import line so relative specifiers resolve from the
|
|
57
|
+
* virtual module. Absolute and bare specifiers are kept as-is.
|
|
58
|
+
*/
|
|
59
|
+
function rewriteCssImportForVirtualModule(matchedLine, specifier, sourceFilePath) {
|
|
60
|
+
if (specifier.startsWith(".")) {
|
|
61
|
+
const absPath = normalizePath(resolve(dirname(sourceFilePath), specifier));
|
|
62
|
+
return `import ${JSON.stringify(absPath)};`;
|
|
63
|
+
}
|
|
64
|
+
return matchedLine.trim() + ";";
|
|
65
|
+
}
|
|
66
|
+
/** Extract CSS import statements from a file and return them as @import rules. */
|
|
67
|
+
function extractCssImports(filePath) {
|
|
68
|
+
const code = readFileSync(filePath, "utf-8");
|
|
69
|
+
const re = /^\s*import\b[^"']*["']([^"']+\.(?:css|scss|sass|less|styl|stylus|pcss|postcss))["']/gm;
|
|
70
|
+
const imports = [];
|
|
71
|
+
let match;
|
|
72
|
+
while ((match = re.exec(code)) !== null) imports.push(`@import ${JSON.stringify(match[1])};`);
|
|
73
|
+
return imports.join("\n");
|
|
74
|
+
}
|
|
75
|
+
/** Rebuild islandCssMap from current file contents. */
|
|
76
|
+
function rebuildIslandCssMap(pageScan, pagesDir, islandCssMap, fileHasCssFn) {
|
|
77
|
+
islandCssMap.clear();
|
|
78
|
+
for (const page of pageScan.pages) {
|
|
79
|
+
if (!page.island) continue;
|
|
80
|
+
const cssPaths = [];
|
|
81
|
+
const layoutChain = resolveEffectiveLayoutChain(page, pageScan.layouts, pageScan.namedLayouts);
|
|
82
|
+
for (const layout of layoutChain) {
|
|
83
|
+
const layoutPath = resolve(pagesDir, layout.filePath);
|
|
84
|
+
if (fileHasCssFn(layoutPath)) cssPaths.push(layoutPath);
|
|
85
|
+
}
|
|
86
|
+
const pagePath = resolve(pagesDir, page.componentPath);
|
|
87
|
+
if (fileHasCssFn(pagePath)) cssPaths.push(pagePath);
|
|
88
|
+
if (cssPaths.length > 0) islandCssMap.set(page.componentId, cssPaths);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Compute which island pages need client-side JavaScript. */
|
|
92
|
+
function computePagesNeedingClientJS(pageScan, pagesDir, resolvedConfig) {
|
|
93
|
+
const mdPlugin = resolvedConfig?.plugins?.find((plugin) => plugin.name === "void-md");
|
|
94
|
+
const mdScriptIds = new Set(mdPlugin?.api?.getClientScripts?.()?.keys() ?? []);
|
|
95
|
+
const importAttrRe = /import\s+\w+\s+from\s+("[^"]+"|'[^']+')\s+with\s*\{\s*island\s*:\s*("[^"]+"|'[^']+')\s*\}/g;
|
|
96
|
+
const layoutDirsWithIslands = /* @__PURE__ */ new Set();
|
|
97
|
+
for (const layout of pageScan.layouts) {
|
|
98
|
+
if (!layout.island) continue;
|
|
99
|
+
const code = readFileSync(resolve(pagesDir, layout.filePath), "utf-8");
|
|
100
|
+
importAttrRe.lastIndex = 0;
|
|
101
|
+
if (importAttrRe.test(code)) layoutDirsWithIslands.add(layout.directory);
|
|
102
|
+
}
|
|
103
|
+
const result = /* @__PURE__ */ new Set();
|
|
104
|
+
for (const page of pageScan.pages) {
|
|
105
|
+
if (!page.island) continue;
|
|
106
|
+
if (mdScriptIds.has(page.componentId)) {
|
|
107
|
+
result.add(page.componentId);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const code = readFileSync(resolve(pagesDir, page.componentPath), "utf-8");
|
|
111
|
+
importAttrRe.lastIndex = 0;
|
|
112
|
+
if (importAttrRe.test(code)) {
|
|
113
|
+
result.add(page.componentId);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const layoutChain = resolveEffectiveLayoutChain(page, pageScan.layouts, pageScan.namedLayouts);
|
|
117
|
+
for (const layout of layoutChain) if (layoutDirsWithIslands.has(layout.directory)) {
|
|
118
|
+
result.add(page.componentId);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Configure the Vite dev server for island CSS serving.
|
|
126
|
+
* Sets up file watching and a middleware for serving virtual CSS modules.
|
|
127
|
+
*/
|
|
128
|
+
function configureIslandCssServer(server, islandCssFiles, viteRoot, rebuildCssMap) {
|
|
129
|
+
server.watcher.on("change", (path) => {
|
|
130
|
+
const normalizedPath = normalizePath(path);
|
|
131
|
+
if (!islandCssFiles.has(normalizedPath)) return;
|
|
132
|
+
rebuildCssMap();
|
|
133
|
+
for (const env of Object.values(server.environments)) {
|
|
134
|
+
const mod = env.moduleGraph.getModuleById("\0" + ISLANDS_RENDERER_ID);
|
|
135
|
+
if (mod) env.moduleGraph.invalidateModule(mod);
|
|
136
|
+
}
|
|
137
|
+
const cssMod = server.environments.client?.moduleGraph.getModuleById(normalizedPath + ".css");
|
|
138
|
+
if (cssMod) server.environments.client.moduleGraph.invalidateModule(cssMod);
|
|
139
|
+
});
|
|
140
|
+
server.middlewares.use(async (req, res, next) => {
|
|
141
|
+
if (!req.url) return next();
|
|
142
|
+
const url = req.url.split("?")[0];
|
|
143
|
+
if (!url.endsWith(".css")) return next();
|
|
144
|
+
const srcPath = normalizePath(resolve(viteRoot, url.slice(1, -4)));
|
|
145
|
+
if (!islandCssFiles.has(srcPath)) return next();
|
|
146
|
+
try {
|
|
147
|
+
const result = await server.environments.client.transformRequest(url);
|
|
148
|
+
if (result) {
|
|
149
|
+
const m = result.code.match(/\b__vite__css\s*=\s*("(?:[^"\\]|\\.)*")/) || result.code.match(/export\s+default\s+("(?:[^"\\]|\\.)*")/);
|
|
150
|
+
if (m) {
|
|
151
|
+
res.setHeader("Content-Type", "text/css");
|
|
152
|
+
res.statusCode = 200;
|
|
153
|
+
res.end(JSON.parse(m[1]));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} catch {}
|
|
158
|
+
next();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Watch the pages directory for structural changes (add/remove) and .md content
|
|
163
|
+
* changes (frontmatter layout field) so that new layouts and named layouts are
|
|
164
|
+
* picked up without a dev server restart.
|
|
165
|
+
*
|
|
166
|
+
* Returns a `flush()` function that resolves when any pending rescan completes
|
|
167
|
+
* (useful for tests).
|
|
168
|
+
*/
|
|
169
|
+
function watchPagesForRescan(server, pagesDir, root, onRescan) {
|
|
170
|
+
let pending = null;
|
|
171
|
+
let debounceTimer = null;
|
|
172
|
+
const scheduleRescan = (path) => {
|
|
173
|
+
if (!path.startsWith(pagesDir)) return;
|
|
174
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
175
|
+
debounceTimer = setTimeout(() => {
|
|
176
|
+
debounceTimer = null;
|
|
177
|
+
pending = scanPages(root).then((pageScan) => {
|
|
178
|
+
onRescan(pageScan);
|
|
179
|
+
for (const env of Object.values(server.environments)) {
|
|
180
|
+
const mod = env.moduleGraph.getModuleById("\0" + ISLANDS_RENDERER_ID);
|
|
181
|
+
if (mod) env.moduleGraph.invalidateModule(mod);
|
|
182
|
+
}
|
|
183
|
+
pending = null;
|
|
184
|
+
});
|
|
185
|
+
}, 50);
|
|
186
|
+
};
|
|
187
|
+
server.watcher.on("add", scheduleRescan);
|
|
188
|
+
server.watcher.on("unlink", scheduleRescan);
|
|
189
|
+
server.watcher.on("change", (path) => {
|
|
190
|
+
if (path.endsWith(".md")) scheduleRescan(path);
|
|
191
|
+
});
|
|
192
|
+
return { flush: () => pending ?? Promise.resolve() };
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
195
|
+
export { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, computePagesNeedingClientJS, configureIslandCssServer, extractCssImports, fileHasCssImports, needsIslandClientBundle, rebuildIslandCssMap, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/pages/prefetch.d.ts
|
|
2
|
+
interface CacheForResult {
|
|
3
|
+
stale: number;
|
|
4
|
+
expires: number;
|
|
5
|
+
}
|
|
6
|
+
type CacheForInput = number | string | [string, string];
|
|
7
|
+
declare function parseCacheFor(value: CacheForInput): CacheForResult;
|
|
8
|
+
interface CacheEntry {
|
|
9
|
+
url: string;
|
|
10
|
+
method: string;
|
|
11
|
+
response: Promise<unknown>;
|
|
12
|
+
staleAt: number;
|
|
13
|
+
expiresAt: number;
|
|
14
|
+
singleUse: boolean;
|
|
15
|
+
timer: ReturnType<typeof setTimeout> | null;
|
|
16
|
+
}
|
|
17
|
+
declare class PrefetchCache {
|
|
18
|
+
private entries;
|
|
19
|
+
private key;
|
|
20
|
+
has(url: string, method?: string): boolean;
|
|
21
|
+
get(url: string, method?: string): CacheEntry | null;
|
|
22
|
+
isFresh(entry: CacheEntry): boolean;
|
|
23
|
+
isUsable(entry: CacheEntry): boolean;
|
|
24
|
+
set(url: string, method: string, response: Promise<unknown>, ttl: CacheForResult): void;
|
|
25
|
+
/** Mark entry as consumed — removes it if singleUse. */
|
|
26
|
+
consume(url: string, method?: string): void;
|
|
27
|
+
flush(url: string, method?: string): void;
|
|
28
|
+
flushAll(): void;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { CacheEntry, CacheForInput, CacheForResult, PrefetchCache, parseCacheFor };
|