vinext 0.0.49 → 0.0.51
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/build/client-build-config.js.map +1 -1
- package/dist/build/google-fonts/build-url.js.map +1 -1
- package/dist/build/google-fonts/fallback-metrics-data.js +14031 -0
- package/dist/build/google-fonts/fallback-metrics-data.js.map +1 -0
- package/dist/build/google-fonts/fallback-metrics.d.ts +13 -0
- package/dist/build/google-fonts/fallback-metrics.js +46 -0
- package/dist/build/google-fonts/fallback-metrics.js.map +1 -0
- package/dist/build/google-fonts/get-axes.js.map +1 -1
- package/dist/build/google-fonts/sort-variants.js.map +1 -1
- package/dist/build/google-fonts/validate.js.map +1 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/nitro-route-rules.js.map +1 -1
- package/dist/build/precompress.d.ts +13 -2
- package/dist/build/precompress.js +12 -3
- package/dist/build/precompress.js.map +1 -1
- package/dist/build/prerender.d.ts +17 -1
- package/dist/build/prerender.js +114 -23
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +5 -4
- package/dist/build/report.js +196 -348
- package/dist/build/report.js.map +1 -1
- package/dist/build/route-classification-injector.js.map +1 -1
- package/dist/build/route-classification-manifest.js.map +1 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/ssr-manifest.js.map +1 -1
- package/dist/build/standalone.js.map +1 -1
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.js +2 -1
- package/dist/check.js.map +1 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +68 -7
- package/dist/cli.js.map +1 -1
- package/dist/client/instrumentation-client-state.js.map +1 -1
- package/dist/client/validate-module-path.js.map +1 -1
- package/dist/client/vinext-next-data.d.ts +5 -1
- package/dist/client/window-next.d.ts +151 -0
- package/dist/client/window-next.js +48 -0
- package/dist/client/window-next.js.map +1 -0
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/cloudflare/tpr.js +2 -1
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.d.ts +3 -1
- package/dist/config/config-matchers.js +5 -4
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/dotenv.d.ts +11 -1
- package/dist/config/dotenv.js.map +1 -1
- package/dist/config/next-config.d.ts +93 -6
- package/dist/config/next-config.js +233 -6
- package/dist/config/next-config.js.map +1 -1
- package/dist/config/tsconfig-paths.d.ts +13 -0
- package/dist/config/tsconfig-paths.js +117 -0
- package/dist/config/tsconfig-paths.js.map +1 -0
- package/dist/deploy.js +16 -7
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.d.ts +3 -1
- package/dist/entries/app-browser-entry.js +36 -2
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +19 -1
- package/dist/entries/app-rsc-entry.js +49 -12
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +9 -0
- package/dist/entries/app-rsc-manifest.js +8 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -5
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-entry-helpers.js.map +1 -1
- package/dist/entries/pages-server-entry.js +34 -1
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +204 -53
- package/dist/index.js.map +1 -1
- package/dist/init.js.map +1 -1
- package/dist/plugins/async-hooks-stub.js.map +1 -1
- package/dist/plugins/client-reference-dedup.d.ts +15 -2
- package/dist/plugins/client-reference-dedup.js +138 -16
- package/dist/plugins/client-reference-dedup.js.map +1 -1
- package/dist/plugins/fonts.d.ts +2 -2
- package/dist/plugins/fonts.js +15 -6
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/instrumentation-client.js.map +1 -1
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/optimize-imports.js.map +1 -1
- package/dist/plugins/postcss.js.map +1 -1
- package/dist/plugins/rsc-client-reference-loaders.d.ts +7 -0
- package/dist/plugins/rsc-client-reference-loaders.js +48 -0
- package/dist/plugins/rsc-client-reference-loaders.js.map +1 -0
- package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
- package/dist/plugins/sass.d.ts +34 -0
- package/dist/plugins/sass.js +22 -0
- package/dist/plugins/sass.js.map +1 -0
- package/dist/plugins/server-externals-manifest.js.map +1 -1
- package/dist/plugins/strip-server-exports.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +78 -6
- package/dist/routing/app-route-graph.js +241 -25
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.js.map +1 -1
- package/dist/routing/route-pattern.d.ts +56 -1
- package/dist/routing/route-pattern.js +60 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-action-result.d.ts +44 -0
- package/dist/server/app-browser-action-result.js +79 -0
- package/dist/server/app-browser-action-result.js.map +1 -0
- package/dist/server/app-browser-entry.js +330 -133
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-error.js.map +1 -1
- package/dist/server/app-browser-hydration.d.ts +31 -0
- package/dist/server/app-browser-hydration.js +30 -0
- package/dist/server/app-browser-hydration.js.map +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +20 -4
- package/dist/server/app-browser-navigation-controller.js +90 -23
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-popstate.d.ts +16 -0
- package/dist/server/app-browser-popstate.js +17 -0
- package/dist/server/app-browser-popstate.js.map +1 -0
- package/dist/server/app-browser-rsc-redirect.d.ts +28 -0
- package/dist/server/app-browser-rsc-redirect.js +37 -0
- package/dist/server/app-browser-rsc-redirect.js.map +1 -0
- package/dist/server/app-browser-state.d.ts +27 -23
- package/dist/server/app-browser-state.js +158 -54
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-stream.d.ts +9 -4
- package/dist/server/app-browser-stream.js +29 -8
- package/dist/server/app-browser-stream.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +11 -1
- package/dist/server/app-browser-visible-commit.js +69 -21
- package/dist/server/app-browser-visible-commit.js.map +1 -1
- package/dist/server/app-client-reference-preloader.js.map +1 -1
- package/dist/server/app-elements-wire.d.ts +43 -6
- package/dist/server/app-elements-wire.js +121 -5
- package/dist/server/app-elements-wire.js.map +1 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +10 -1
- package/dist/server/app-fallback-renderer.js +37 -1
- package/dist/server/app-fallback-renderer.js.map +1 -1
- package/dist/server/app-history-state.d.ts +26 -0
- package/dist/server/app-history-state.js +53 -0
- package/dist/server/app-history-state.js.map +1 -0
- package/dist/server/app-hook-warning-suppression.js.map +1 -1
- package/dist/server/app-middleware.d.ts +1 -1
- package/dist/server/app-middleware.js +4 -9
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-mounted-slots-header.js.map +1 -1
- package/dist/server/app-page-boundary-render.d.ts +11 -1
- package/dist/server/app-page-boundary-render.js +27 -19
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.d.ts +1 -0
- package/dist/server/app-page-boundary.js +10 -7
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +23 -3
- package/dist/server/app-page-cache.js +63 -27
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +11 -1
- package/dist/server/app-page-dispatch.js +85 -14
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +10 -1
- package/dist/server/app-page-element-builder.js +38 -6
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.js +2 -3
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.d.ts +7 -0
- package/dist/server/app-page-head.js +6 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-params.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +23 -1
- package/dist/server/app-page-probe.js +29 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render-observation.d.ts +35 -0
- package/dist/server/app-page-render-observation.js +68 -0
- package/dist/server/app-page-render-observation.js.map +1 -0
- package/dist/server/app-page-render.d.ts +12 -2
- package/dist/server/app-page-render.js +90 -7
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +1 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +2 -0
- package/dist/server/app-page-response.js +18 -7
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +9 -3
- package/dist/server/app-page-route-wiring.js +91 -62
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-segment-state.d.ts +10 -0
- package/dist/server/app-page-segment-state.js +87 -0
- package/dist/server/app-page-segment-state.js.map +1 -0
- package/dist/server/app-page-stream.d.ts +9 -2
- package/dist/server/app-page-stream.js +4 -1
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-post-middleware-context.js.map +1 -1
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-prerender-static-params.js.map +1 -1
- package/dist/server/app-render-dependency.js.map +1 -1
- package/dist/server/app-request-context.js.map +1 -1
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.js +3 -1
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +1 -0
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.js +4 -3
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-router-entry.js +7 -15
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +23 -2
- package/dist/server/app-rsc-cache-busting.js +75 -19
- package/dist/server/app-rsc-cache-busting.js.map +1 -1
- package/dist/server/app-rsc-embedded-chunks.d.ts +9 -0
- package/dist/server/app-rsc-embedded-chunks.js +34 -0
- package/dist/server/app-rsc-embedded-chunks.js.map +1 -0
- package/dist/server/app-rsc-error-handler.js.map +1 -1
- package/dist/server/app-rsc-errors.d.ts +4 -1
- package/dist/server/app-rsc-errors.js +1 -1
- package/dist/server/app-rsc-errors.js.map +1 -1
- package/dist/server/app-rsc-handler.d.ts +18 -1
- package/dist/server/app-rsc-handler.js +55 -16
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-render-mode.d.ts +11 -0
- package/dist/server/app-rsc-render-mode.js +21 -0
- package/dist/server/app-rsc-render-mode.js.map +1 -0
- package/dist/server/app-rsc-request-normalization.d.ts +4 -1
- package/dist/server/app-rsc-request-normalization.js +7 -2
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -1
- package/dist/server/app-rsc-response-finalizer.js +6 -1
- package/dist/server/app-rsc-response-finalizer.js.map +1 -1
- package/dist/server/app-rsc-route-matching.d.ts +23 -0
- package/dist/server/app-rsc-route-matching.js +45 -23
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +51 -5
- package/dist/server/app-server-action-execution.js +161 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +7 -0
- package/dist/server/app-ssr-entry.js +44 -14
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/app-ssr-error-meta.d.ts +14 -0
- package/dist/server/app-ssr-error-meta.js +50 -0
- package/dist/server/app-ssr-error-meta.js.map +1 -0
- package/dist/server/app-ssr-stream.d.ts +1 -1
- package/dist/server/app-ssr-stream.js +9 -12
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/app-static-generation.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +12 -2
- package/dist/server/artifact-compatibility.js +12 -8
- package/dist/server/artifact-compatibility.js.map +1 -1
- package/dist/server/cache-control.js +1 -0
- package/dist/server/cache-control.js.map +1 -1
- package/dist/server/cache-proof.d.ts +124 -5
- package/dist/server/cache-proof.js +416 -18
- package/dist/server/cache-proof.js.map +1 -1
- package/dist/server/csp.js.map +1 -1
- package/dist/server/dev-error-overlay-store.js.map +1 -1
- package/dist/server/dev-error-overlay.js +5 -0
- package/dist/server/dev-error-overlay.js.map +1 -1
- package/dist/server/dev-lockfile.d.ts +110 -0
- package/dist/server/dev-lockfile.js +180 -0
- package/dist/server/dev-lockfile.js.map +1 -0
- package/dist/server/dev-module-runner.js.map +1 -1
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-route-files.js.map +1 -1
- package/dist/server/dev-server.js +23 -10
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/file-based-metadata.d.ts +13 -0
- package/dist/server/file-based-metadata.js +49 -2
- package/dist/server/file-based-metadata.js.map +1 -1
- package/dist/server/headers.d.ts +81 -0
- package/dist/server/headers.js +104 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/html.js +1 -1
- package/dist/server/html.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +10 -0
- package/dist/server/http-error-responses.js +11 -1
- package/dist/server/http-error-responses.js.map +1 -1
- package/dist/server/image-optimization.d.ts +11 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/implicit-tags.js +2 -1
- package/dist/server/implicit-tags.js.map +1 -1
- package/dist/server/instrumentation-runtime.js.map +1 -1
- package/dist/server/instrumentation.js.map +1 -1
- package/dist/server/isr-cache.d.ts +12 -2
- package/dist/server/isr-cache.js +16 -5
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-route-build-data.js.map +1 -1
- package/dist/server/metadata-route-response.js +22 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.js +27 -8
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-matcher.js.map +1 -1
- package/dist/server/middleware-request-headers.d.ts +4 -1
- package/dist/server/middleware-request-headers.js +15 -8
- package/dist/server/middleware-request-headers.js.map +1 -1
- package/dist/server/middleware-response-headers.d.ts +2 -1
- package/dist/server/middleware-response-headers.js +1 -1
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.d.ts +1 -0
- package/dist/server/middleware-runtime.js +7 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.d.ts +12 -0
- package/dist/server/middleware.js +12 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/navigation-planner.d.ts +133 -0
- package/dist/server/navigation-planner.js +432 -0
- package/dist/server/navigation-planner.js.map +1 -0
- package/dist/server/navigation-trace.d.ts +19 -2
- package/dist/server/navigation-trace.js +20 -1
- package/dist/server/navigation-trace.js.map +1 -1
- package/dist/server/next-error-digest.d.ts +3 -2
- package/dist/server/next-error-digest.js +4 -2
- package/dist/server/next-error-digest.js.map +1 -1
- package/dist/server/normalize-path.d.ts +2 -1
- package/dist/server/normalize-path.js +4 -1
- package/dist/server/normalize-path.js.map +1 -1
- package/dist/server/pages-api-route.js +1 -0
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-i18n.js.map +1 -1
- package/dist/server/pages-media-type.js.map +1 -1
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +3 -2
- package/dist/server/pages-page-data.js +27 -5
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.js +2 -1
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prerender-work-unit-setup.js +1 -1
- package/dist/server/prerender-work-unit-setup.js.map +1 -1
- package/dist/server/prod-server.d.ts +28 -1
- package/dist/server/prod-server.js +97 -22
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-log.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +1 -13
- package/dist/server/request-pipeline.js +3 -25
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/rsc-stream-hints.js.map +1 -1
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/server/server-action-not-found.d.ts +16 -3
- package/dist/server/server-action-not-found.js +22 -4
- package/dist/server/server-action-not-found.js.map +1 -1
- package/dist/server/server-globals.d.ts +5 -0
- package/dist/server/server-globals.js +37 -0
- package/dist/server/server-globals.js.map +1 -0
- package/dist/server/socket-error-backstop.js.map +1 -1
- package/dist/server/static-file-cache.js +1 -1
- package/dist/server/static-file-cache.js.map +1 -1
- package/dist/server/worker-utils.d.ts +0 -7
- package/dist/server/worker-utils.js +3 -2
- package/dist/server/worker-utils.js.map +1 -1
- package/dist/shims/amp.js.map +1 -1
- package/dist/shims/app.d.ts +37 -4
- package/dist/shims/app.js +50 -1
- package/dist/shims/app.js.map +1 -0
- package/dist/shims/cache-for-request.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +19 -2
- package/dist/shims/cache-runtime.js +87 -19
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +20 -21
- package/dist/shims/cache.js +101 -15
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/client-hook-error.js.map +1 -1
- package/dist/shims/compat-router.js.map +1 -1
- package/dist/shims/config.js.map +1 -1
- package/dist/shims/constants.js.map +1 -1
- package/dist/shims/document.js.map +1 -1
- package/dist/shims/dynamic.d.ts +18 -10
- package/dist/shims/dynamic.js +107 -51
- package/dist/shims/dynamic.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +35 -6
- package/dist/shims/error-boundary.js +116 -33
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/error.d.ts +18 -1
- package/dist/shims/error.js +56 -1
- package/dist/shims/error.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +25 -1
- package/dist/shims/fetch-cache.js +159 -13
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/font-google-base.d.ts +22 -8
- package/dist/shims/font-google-base.js +41 -71
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-local.d.ts +3 -20
- package/dist/shims/font-local.js +23 -75
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/font-utils.d.ts +51 -0
- package/dist/shims/font-utils.js +97 -0
- package/dist/shims/font-utils.js.map +1 -0
- package/dist/shims/form.js +3 -1
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/hash-scroll.d.ts +7 -0
- package/dist/shims/hash-scroll.js +30 -0
- package/dist/shims/hash-scroll.js.map +1 -0
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/head.d.ts +3 -1
- package/dist/shims/head.js +28 -16
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +11 -12
- package/dist/shims/headers.js +45 -8
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-context.js.map +1 -1
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/image-config.d.ts +14 -1
- package/dist/shims/image-config.js +24 -1
- package/dist/shims/image-config.js.map +1 -1
- package/dist/shims/image.d.ts +1 -0
- package/dist/shims/image.js +159 -80
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/als-registry.js.map +1 -1
- package/dist/shims/internal/app-router-context.d.ts +7 -6
- package/dist/shims/internal/app-router-context.js +17 -6
- package/dist/shims/internal/app-router-context.js.map +1 -1
- package/dist/shims/internal/cookie-serialize.js.map +1 -1
- package/dist/shims/internal/make-hanging-promise.d.ts +1 -1
- package/dist/shims/internal/make-hanging-promise.js +1 -1
- package/dist/shims/internal/make-hanging-promise.js.map +1 -1
- package/dist/shims/internal/parse-cookie-header.js.map +1 -1
- package/dist/shims/internal/utils.js.map +1 -1
- package/dist/shims/internal/work-unit-async-storage.js +2 -2
- package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
- package/dist/shims/layout-segment-context.js.map +1 -1
- package/dist/shims/legacy-image.js.map +1 -1
- package/dist/shims/link-prefetch.d.ts +42 -0
- package/dist/shims/link-prefetch.js +45 -0
- package/dist/shims/link-prefetch.js.map +1 -0
- package/dist/shims/link.d.ts +37 -4
- package/dist/shims/link.js +156 -46
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +16 -30
- package/dist/shims/metadata.js +87 -28
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +172 -10
- package/dist/shims/navigation.js +335 -70
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/navigation.react-server.d.ts +3 -2
- package/dist/shims/navigation.react-server.js +5 -2
- package/dist/shims/navigation.react-server.js.map +1 -1
- package/dist/shims/offline.js.map +1 -1
- package/dist/shims/pages-router-runtime.d.ts +7 -0
- package/dist/shims/pages-router-runtime.js +16 -0
- package/dist/shims/pages-router-runtime.js.map +1 -0
- package/dist/shims/readonly-url-search-params.js.map +1 -1
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/root-params.js.map +1 -1
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.d.ts +69 -7
- package/dist/shims/router.js +232 -249
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script-nonce-context.js.map +1 -1
- package/dist/shims/script.js +110 -32
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.js +12 -15
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +7 -1
- package/dist/shims/slot.js +60 -7
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.js +5 -0
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/unrecognized-action-error.d.ts +35 -0
- package/dist/shims/unrecognized-action-error.js +41 -0
- package/dist/shims/unrecognized-action-error.js.map +1 -0
- package/dist/shims/url-safety.js.map +1 -1
- package/dist/shims/url-utils.d.ts +22 -1
- package/dist/shims/url-utils.js +76 -3
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/shims/use-merged-ref.js.map +1 -1
- package/dist/shims/web-vitals.d.ts +4 -21
- package/dist/shims/web-vitals.js +19 -6
- package/dist/shims/web-vitals.js.map +1 -1
- package/dist/utils/asset-prefix.d.ts +69 -0
- package/dist/utils/asset-prefix.js +91 -0
- package/dist/utils/asset-prefix.js.map +1 -0
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +10 -1
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/cache-control-metadata.js.map +1 -1
- package/dist/utils/domain-locale.js.map +1 -1
- package/dist/utils/encode-cache-tag.d.ts +31 -0
- package/dist/utils/encode-cache-tag.js +38 -0
- package/dist/utils/encode-cache-tag.js.map +1 -0
- package/dist/utils/error-cause.js.map +1 -1
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/lazy-chunks.js.map +1 -1
- package/dist/utils/manifest-paths.js.map +1 -1
- package/dist/utils/mdx-scan.js.map +1 -1
- package/dist/utils/navigation-signal.d.ts +5 -0
- package/dist/utils/navigation-signal.js +14 -0
- package/dist/utils/navigation-signal.js.map +1 -0
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/public-routes.js.map +1 -1
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/safe-json-file.js.map +1 -1
- package/dist/utils/sorted-array.d.ts +9 -0
- package/dist/utils/sorted-array.js +22 -0
- package/dist/utils/sorted-array.js.map +1 -0
- package/dist/utils/text-stream.js.map +1 -1
- package/dist/utils/vinext-root.js.map +1 -1
- package/package.json +8 -6
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { escapeCSSString, formatFontClassRule, resolveSingleFaceStyle, sanitizeCSSVarName, sanitizeFallback } from "./font-utils.js";
|
|
1
2
|
import { buildGoogleFontsUrl as buildGoogleFontsUrl$1 } from "../build/google-fonts/build-url.js";
|
|
2
3
|
//#region src/shims/font-google-base.ts
|
|
3
4
|
/**
|
|
@@ -15,57 +16,9 @@ import { buildGoogleFontsUrl as buildGoogleFontsUrl$1 } from "../build/google-fo
|
|
|
15
16
|
* import { Inter } from 'next/font/google';
|
|
16
17
|
* const inter = Inter({ subsets: ['latin'], weight: ['400', '700'] });
|
|
17
18
|
* // inter.className -> stable CSS class for this font/options pair
|
|
18
|
-
* // inter.style -> { fontFamily: "'Inter',
|
|
19
|
-
* // inter.variable -> CSS class that sets the font CSS variable
|
|
19
|
+
* // inter.style -> { fontFamily: "'Inter', 'Inter Fallback'", fontStyle: "normal" }
|
|
20
|
+
* // inter.variable -> CSS class that sets the font CSS variable when requested
|
|
20
21
|
*/
|
|
21
|
-
/**
|
|
22
|
-
* Escape a string for safe interpolation inside a CSS single-quoted string.
|
|
23
|
-
*
|
|
24
|
-
* Prevents CSS injection by escaping characters that could break out of
|
|
25
|
-
* a `'...'` CSS string context: backslashes, single quotes, and newlines.
|
|
26
|
-
*/
|
|
27
|
-
function escapeCSSString(value) {
|
|
28
|
-
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\a ").replace(/\r/g, "\\d ");
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Validate a CSS custom property name (e.g. `--font-inter`).
|
|
32
|
-
*
|
|
33
|
-
* Custom properties must start with `--` and only contain alphanumeric
|
|
34
|
-
* characters, hyphens, and underscores. Anything else could be used to
|
|
35
|
-
* break out of the CSS declaration and inject arbitrary rules.
|
|
36
|
-
*
|
|
37
|
-
* Returns the name if valid, undefined otherwise.
|
|
38
|
-
*/
|
|
39
|
-
function sanitizeCSSVarName(name) {
|
|
40
|
-
if (/^--[a-zA-Z0-9_-]+$/.test(name)) return name;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Sanitize a CSS font-family fallback name.
|
|
44
|
-
*
|
|
45
|
-
* Generic family names (sans-serif, serif, monospace, etc.) are used as-is.
|
|
46
|
-
* Named families are wrapped in escaped quotes. This prevents injection via
|
|
47
|
-
* crafted fallback values like `); } body { color: red; } .x {`.
|
|
48
|
-
*/
|
|
49
|
-
function sanitizeFallback(name) {
|
|
50
|
-
const generics = new Set([
|
|
51
|
-
"serif",
|
|
52
|
-
"sans-serif",
|
|
53
|
-
"monospace",
|
|
54
|
-
"cursive",
|
|
55
|
-
"fantasy",
|
|
56
|
-
"system-ui",
|
|
57
|
-
"ui-serif",
|
|
58
|
-
"ui-sans-serif",
|
|
59
|
-
"ui-monospace",
|
|
60
|
-
"ui-rounded",
|
|
61
|
-
"emoji",
|
|
62
|
-
"math",
|
|
63
|
-
"fangsong"
|
|
64
|
-
]);
|
|
65
|
-
const trimmed = name.trim();
|
|
66
|
-
if (generics.has(trimmed)) return trimmed;
|
|
67
|
-
return `'${escapeCSSString(trimmed)}'`;
|
|
68
|
-
}
|
|
69
22
|
const injectedFonts = /* @__PURE__ */ new Set();
|
|
70
23
|
/**
|
|
71
24
|
* Convert a font family name to a CSS variable name.
|
|
@@ -124,7 +77,9 @@ function createFontIdentity(family, options, cssVarName, fallback) {
|
|
|
124
77
|
normalizeFallbackOption(fallback),
|
|
125
78
|
normalizeStringOrBooleanOption(options.adjustFontFallback),
|
|
126
79
|
normalizeStringSetOption(options.axes),
|
|
127
|
-
options.
|
|
80
|
+
options._vinext?.font?.selfHostedCSS ?? "",
|
|
81
|
+
options._vinext?.font?.fontWeight?.toString() ?? "",
|
|
82
|
+
options._vinext?.font?.fontStyle ?? ""
|
|
128
83
|
].join("\0"));
|
|
129
84
|
}
|
|
130
85
|
/**
|
|
@@ -133,10 +88,10 @@ function createFontIdentity(family, options, cssVarName, fallback) {
|
|
|
133
88
|
* In production this code path is dead. The build plugin
|
|
134
89
|
* (`vinext:google-fonts` in `src/plugins/fonts.ts`) statically resolves
|
|
135
90
|
* each font call's axis values against the bundled metadata, fetches the
|
|
136
|
-
* Google Fonts CSS, and injects the resulting CSS as
|
|
137
|
-
* the runtime never queries Google. The shim
|
|
138
|
-
* when the plugin's static parser bails (dynamic
|
|
139
|
-
* shapes), which is dev-only.
|
|
91
|
+
* Google Fonts CSS, and injects the resulting CSS as
|
|
92
|
+
* `_vinext.font.selfHostedCSS` so the runtime never queries Google. The shim
|
|
93
|
+
* only reaches this builder when the plugin's static parser bails (dynamic
|
|
94
|
+
* options, eval-only shapes), which is dev-only.
|
|
140
95
|
*
|
|
141
96
|
* The dev fallback intentionally has no metadata: shipping the 388 KB
|
|
142
97
|
* `font-data.json` to the Worker bundle would dwarf the rest of the shim,
|
|
@@ -175,26 +130,26 @@ function injectFontStylesheet(url) {
|
|
|
175
130
|
/** Track which className CSS rules have been injected. */
|
|
176
131
|
const injectedClassRules = /* @__PURE__ */ new Set();
|
|
177
132
|
/**
|
|
178
|
-
* Inject a CSS rule that maps a className to
|
|
133
|
+
* Inject a CSS rule that maps a className to the exported font style.
|
|
179
134
|
*
|
|
180
135
|
* This is what makes `<div className={inter.className}>` apply the font.
|
|
181
136
|
* Next.js generates equivalent rules at build time.
|
|
182
137
|
*
|
|
183
|
-
* In Next.js, the .className class
|
|
184
|
-
*
|
|
138
|
+
* In Next.js, the .className class sets font-family and any single
|
|
139
|
+
* font-weight/font-style. CSS variables are handled separately by .variable.
|
|
185
140
|
*/
|
|
186
|
-
function injectClassNameRule(className,
|
|
141
|
+
function injectClassNameRule(className, fontStyle) {
|
|
187
142
|
if (injectedClassRules.has(className)) return;
|
|
188
143
|
injectedClassRules.add(className);
|
|
189
|
-
const css =
|
|
144
|
+
const css = formatFontClassRule(className, fontStyle);
|
|
190
145
|
if (typeof document === "undefined") {
|
|
191
146
|
ssrFontStyles.push(css);
|
|
192
147
|
return;
|
|
193
148
|
}
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
document.head.appendChild(
|
|
149
|
+
const styleElement = document.createElement("style");
|
|
150
|
+
styleElement.textContent = css;
|
|
151
|
+
styleElement.setAttribute("data-vinext-font-class", className);
|
|
152
|
+
document.head.appendChild(styleElement);
|
|
198
153
|
}
|
|
199
154
|
/** Track which variable class CSS rules have been injected. */
|
|
200
155
|
const injectedVariableRules = /* @__PURE__ */ new Set();
|
|
@@ -310,15 +265,29 @@ function injectSelfHostedCSS(css) {
|
|
|
310
265
|
}
|
|
311
266
|
function createFontLoader(family) {
|
|
312
267
|
return function fontLoader(options = {}) {
|
|
313
|
-
const
|
|
314
|
-
const
|
|
268
|
+
const internal = options._vinext?.font;
|
|
269
|
+
const fallback = options.fallback ?? [];
|
|
270
|
+
const adjustedFallback = options.adjustFontFallback === false || !internal?.adjustedFallbackCSS ? [] : [`'${escapeCSSString(family)} Fallback'`];
|
|
271
|
+
const fontFamily = [
|
|
272
|
+
`'${escapeCSSString(family)}'`,
|
|
273
|
+
...adjustedFallback,
|
|
274
|
+
...fallback.map(sanitizeFallback)
|
|
275
|
+
].join(", ");
|
|
315
276
|
const defaultVarName = toVarName(family);
|
|
316
277
|
const cssVarName = options.variable ? sanitizeCSSVarName(options.variable) ?? defaultVarName : defaultVarName;
|
|
317
278
|
const id = createFontIdentity(family, options, cssVarName, fallback);
|
|
318
279
|
const classSegment = fontClassSegment(family);
|
|
319
280
|
const className = `__font_${classSegment}_${id}`;
|
|
320
281
|
const variableClassName = `__variable_${classSegment}_${id}`;
|
|
321
|
-
|
|
282
|
+
const style = resolveSingleFaceStyle({
|
|
283
|
+
fontFamily,
|
|
284
|
+
weight: options.weight,
|
|
285
|
+
style: options.style,
|
|
286
|
+
internalWeight: internal?.fontWeight,
|
|
287
|
+
internalStyle: internal?.fontStyle,
|
|
288
|
+
google: true
|
|
289
|
+
});
|
|
290
|
+
if (internal?.selfHostedCSS) injectSelfHostedCSS(internal.selfHostedCSS);
|
|
322
291
|
else {
|
|
323
292
|
const url = buildGoogleFontsUrl(family, options);
|
|
324
293
|
injectFontStylesheet(url);
|
|
@@ -326,12 +295,13 @@ function createFontLoader(family) {
|
|
|
326
295
|
if (!ssrFontUrls.includes(url)) ssrFontUrls.push(url);
|
|
327
296
|
}
|
|
328
297
|
}
|
|
329
|
-
|
|
330
|
-
|
|
298
|
+
if (options.adjustFontFallback !== false && internal?.adjustedFallbackCSS) injectSelfHostedCSS(internal.adjustedFallbackCSS);
|
|
299
|
+
injectClassNameRule(className, style);
|
|
300
|
+
if (options.variable) injectVariableClassRule(variableClassName, cssVarName, fontFamily);
|
|
331
301
|
return {
|
|
332
302
|
className,
|
|
333
|
-
style
|
|
334
|
-
variable: variableClassName
|
|
303
|
+
style,
|
|
304
|
+
...options.variable ? { variable: variableClassName } : {}
|
|
335
305
|
};
|
|
336
306
|
};
|
|
337
307
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"font-google-base.js","names":["buildUrlFromAxes"],"sources":["../../src/shims/font-google-base.ts"],"sourcesContent":["import { buildGoogleFontsUrl as buildUrlFromAxes } from \"../build/google-fonts/build-url.js\";\n\n/**\n * next/font/google shim\n *\n * Provides a compatible shim for Next.js Google Fonts.\n *\n * Two modes:\n * 1. **Dev / CDN mode** (default): Loads fonts from Google Fonts CDN via <link> tags.\n * 2. **Self-hosted mode** (production build): The vinext:google-fonts Vite plugin\n * fetches font CSS + .woff2 files at build time, caches them locally, and injects\n * @font-face CSS pointing at local assets. No requests to Google at runtime.\n *\n * Usage:\n * import { Inter } from 'next/font/google';\n * const inter = Inter({ subsets: ['latin'], weight: ['400', '700'] });\n * // inter.className -> stable CSS class for this font/options pair\n * // inter.style -> { fontFamily: \"'Inter', sans-serif\" }\n * // inter.variable -> CSS class that sets the font CSS variable\n */\n\n/**\n * Escape a string for safe interpolation inside a CSS single-quoted string.\n *\n * Prevents CSS injection by escaping characters that could break out of\n * a `'...'` CSS string context: backslashes, single quotes, and newlines.\n */\nfunction escapeCSSString(value: string): string {\n return value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, \"\\\\a \")\n .replace(/\\r/g, \"\\\\d \");\n}\n\n/**\n * Validate a CSS custom property name (e.g. `--font-inter`).\n *\n * Custom properties must start with `--` and only contain alphanumeric\n * characters, hyphens, and underscores. Anything else could be used to\n * break out of the CSS declaration and inject arbitrary rules.\n *\n * Returns the name if valid, undefined otherwise.\n */\nfunction sanitizeCSSVarName(name: string): string | undefined {\n if (/^--[a-zA-Z0-9_-]+$/.test(name)) return name;\n return undefined;\n}\n\n/**\n * Sanitize a CSS font-family fallback name.\n *\n * Generic family names (sans-serif, serif, monospace, etc.) are used as-is.\n * Named families are wrapped in escaped quotes. This prevents injection via\n * crafted fallback values like `); } body { color: red; } .x {`.\n */\nfunction sanitizeFallback(name: string): string {\n // CSS generic font families — safe to use unquoted\n const generics = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"emoji\",\n \"math\",\n \"fangsong\",\n ]);\n const trimmed = name.trim();\n if (generics.has(trimmed)) return trimmed;\n // Wrap in single quotes with escaping to prevent CSS injection\n return `'${escapeCSSString(trimmed)}'`;\n}\n\n// Track which font stylesheets have been injected (SSR + client)\nconst injectedFonts = new Set<string>();\n\nexport type FontOptions = {\n weight?: string | string[];\n style?: string | string[];\n subsets?: string[];\n display?: string;\n preload?: boolean;\n fallback?: string[];\n adjustFontFallback?: boolean | string;\n variable?: string;\n axes?: string[];\n};\n\nexport type FontResult = {\n className: string;\n style: { fontFamily: string };\n variable?: string;\n};\n\ntype FontLoaderOptions = FontOptions & { _selfHostedCSS?: string };\n\n/**\n * Convert a font family name to a CSS variable name.\n * e.g., \"Inter\" -> \"--font-inter\", \"Roboto Mono\" -> \"--font-roboto-mono\"\n */\nfunction toVarName(family: string): string {\n return \"--font-\" + family.toLowerCase().replace(/\\s+/g, \"-\");\n}\n\nfunction fontClassSegment(family: string): string {\n const segment = family\n .toLowerCase()\n .replace(/[^a-z0-9_-]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n return segment || \"font\";\n}\n\nfunction normalizeStringSetOption(value: string | string[] | undefined): string {\n if (!value) return \"\";\n const values = Array.isArray(value) ? value : [value];\n return [...new Set(values.map((item) => item.trim()).filter(Boolean))].sort().join(\",\");\n}\n\nfunction normalizeWeightOption(value: string | string[] | undefined): string {\n const normalized = normalizeStringSetOption(value);\n return normalized === \"variable\" ? \"\" : normalized;\n}\n\nfunction normalizeStyleOption(value: string | string[] | undefined): string {\n const values = new Set(\n (Array.isArray(value) ? value : value ? [value] : [])\n .map((item) => item.trim())\n .filter(Boolean),\n );\n const hasItalic = values.has(\"italic\");\n const hasNormal = values.has(\"normal\");\n if (!hasItalic) return \"\";\n return hasNormal ? \"italic,normal\" : \"italic\";\n}\n\nfunction normalizeFallbackOption(value: string[] | undefined): string {\n if (!value) return \"\";\n return value.map((item) => item.trim()).join(\",\");\n}\n\nfunction normalizeBooleanOption(value: boolean | undefined): string {\n if (value === undefined) return \"\";\n return value ? \"1\" : \"0\";\n}\n\nfunction normalizeStringOrBooleanOption(value: boolean | string | undefined): string {\n if (value === undefined) return \"\";\n return typeof value === \"boolean\" ? normalizeBooleanOption(value) : value;\n}\n\nfunction hashString(value: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < value.length; i++) {\n hash ^= value.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n return hash.toString(36).padStart(7, \"0\");\n}\n\nfunction createFontIdentity(\n family: string,\n options: FontLoaderOptions,\n cssVarName: string,\n fallback: string[],\n): string {\n return hashString(\n [\n family,\n cssVarName,\n normalizeWeightOption(options.weight),\n normalizeStyleOption(options.style),\n normalizeStringSetOption(options.subsets),\n options.display ?? \"swap\",\n normalizeBooleanOption(options.preload),\n normalizeFallbackOption(fallback),\n normalizeStringOrBooleanOption(options.adjustFontFallback),\n normalizeStringSetOption(options.axes),\n options._selfHostedCSS ?? \"\",\n ].join(\"\\0\"),\n );\n}\n\n/**\n * Build a Google Fonts CSS URL.\n *\n * In production this code path is dead. The build plugin\n * (`vinext:google-fonts` in `src/plugins/fonts.ts`) statically resolves\n * each font call's axis values against the bundled metadata, fetches the\n * Google Fonts CSS, and injects the resulting CSS as `_selfHostedCSS` so\n * the runtime never queries Google. The shim only reaches this builder\n * when the plugin's static parser bails (dynamic options, eval-only\n * shapes), which is dev-only.\n *\n * The dev fallback intentionally has no metadata: shipping the 388 KB\n * `font-data.json` to the Worker bundle would dwarf the rest of the shim,\n * and the production path already has the metadata-aware variant. The\n * tradeoff is that the dev fallback cannot resolve a variable font's\n * actual `wght` axis range. It emits no axis segment when no `weight` is\n * given, which makes Google return the default static face (200) instead\n * of the broken `:wght@100..900` URL that issue #885 reports.\n */\nexport function buildGoogleFontsUrl(family: string, options: FontOptions): string {\n const weights = options.weight\n ? Array.isArray(options.weight)\n ? options.weight\n : [options.weight]\n : [];\n const styles = options.style\n ? Array.isArray(options.style)\n ? options.style\n : [options.style]\n : [];\n\n const hasItalic = styles.includes(\"italic\");\n const hasNormal = styles.includes(\"normal\");\n // Google treats omitted ital as ital=0, so italic-only requests emit\n // ['1']; mixed requests emit ['0','1']; normal-only stays undefined so\n // the URL has no ital axis at all.\n const ital = hasItalic ? [...(hasNormal ? [\"0\"] : []), \"1\"] : undefined;\n\n // The dev fallback has no metadata, so the variable sentinel cannot be\n // resolved to the font's real axis range here. Drop it like empty options\n // instead of emitting the invalid Google Fonts URL `:wght@variable`.\n const normalizedWeights = weights.length === 1 && weights[0] === \"variable\" ? [] : weights;\n\n // Italic-only with no explicit weight still needs a wght value or the\n // ital axis has nowhere to attach in Google's URL grammar. Fall back to\n // '400' because every Google Font has it and it is the visible default.\n // The plugin's metadata-aware path covers the variable-font case in\n // production.\n const wght = normalizedWeights.length > 0 ? normalizedWeights : ital ? [\"400\"] : undefined;\n\n return buildUrlFromAxes(family, { wght, ital }, options.display ?? \"swap\");\n}\n\n/**\n * Inject a <link> tag for the font (client-side only).\n * On the server, we track font URLs for SSR head injection.\n */\nfunction injectFontStylesheet(url: string): void {\n if (injectedFonts.has(url)) return;\n injectedFonts.add(url);\n\n if (typeof document !== \"undefined\") {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = url;\n document.head.appendChild(link);\n }\n}\n\n/** Track which className CSS rules have been injected. */\nconst injectedClassRules = new Set<string>();\n\n/**\n * Inject a CSS rule that maps a className to a font-family.\n *\n * This is what makes `<div className={inter.className}>` apply the font.\n * Next.js generates equivalent rules at build time.\n *\n * In Next.js, the .className class ONLY sets font-family — it does NOT\n * set CSS variables. CSS variables are handled separately by the .variable class.\n */\nfunction injectClassNameRule(className: string, fontFamily: string): void {\n if (injectedClassRules.has(className)) return;\n injectedClassRules.add(className);\n\n const css = `.${className} { font-family: ${fontFamily}; }\\n`;\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-class\", className);\n document.head.appendChild(style);\n}\n\n/** Track which variable class CSS rules have been injected. */\nconst injectedVariableRules = new Set<string>();\n\n/**\n * Inject a CSS rule that sets a CSS variable on an element.\n * This is what makes `<html className={inter.variable}>` set the CSS variable\n * that can be referenced by other styles (e.g., Tailwind's font-sans).\n *\n * In Next.js, the .variable class ONLY sets the CSS variable — it does NOT\n * set font-family. This is critical because apps commonly apply multiple\n * .variable classes to <body> (e.g., geistSans.variable + geistMono.variable).\n * If we also set font-family here, the last class wins due to CSS cascade,\n * causing all text to use that font (e.g., everything becomes monospace).\n */\nfunction injectVariableClassRule(\n variableClassName: string,\n cssVarName: string,\n fontFamily: string,\n): void {\n if (injectedVariableRules.has(variableClassName)) return;\n injectedVariableRules.add(variableClassName);\n\n // Only set the CSS variable — do NOT set font-family.\n // This matches Next.js behavior where .variable classes only define CSS variables.\n const css = `.${variableClassName} { ${cssVarName}: ${fontFamily}; }\\n`;\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-variable\", variableClassName);\n document.head.appendChild(style);\n}\n\n// SSR: collect font class CSS for injection in <head>\nconst ssrFontStyles: string[] = [];\n\n/**\n * Get collected SSR font class styles (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontStyles(): string[] {\n return [...ssrFontStyles];\n}\n\n// SSR: collect font URLs to inject in <head>\nconst ssrFontUrls: string[] = [];\n\n/**\n * Get collected SSR font URLs (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontLinks(): string[] {\n return [...ssrFontUrls];\n}\n\n// SSR: collect font file URLs for <link rel=\"preload\"> injection (self-hosted Google fonts)\nconst ssrFontPreloads: Array<{ href: string; type: string }> = [];\nconst ssrFontPreloadHrefs = new Set<string>();\n\n/**\n * Get collected SSR font preload data (used by the renderer).\n * Returns an array of { href, type } objects for emitting\n * <link rel=\"preload\" as=\"font\" ...> tags.\n */\nexport function getSSRFontPreloads(): Array<{ href: string; type: string }> {\n return [...ssrFontPreloads];\n}\n\n/**\n * Determine the MIME type for a font file based on its extension.\n */\nfunction getFontMimeType(pathOrUrl: string): string {\n if (pathOrUrl.endsWith(\".woff2\")) return \"font/woff2\";\n if (pathOrUrl.endsWith(\".woff\")) return \"font/woff\";\n if (pathOrUrl.endsWith(\".ttf\")) return \"font/ttf\";\n if (pathOrUrl.endsWith(\".otf\")) return \"font/opentype\";\n return \"font/woff2\";\n}\n\n/**\n * Extract font file URLs from @font-face CSS rules.\n * Parses url('...') references from the CSS text.\n */\nfunction extractFontUrlsFromCSS(css: string): string[] {\n const urls: string[] = [];\n const urlRegex = /url\\(['\"]?([^'\")]+)['\"]?\\)/g;\n let match: RegExpExecArray | null;\n while ((match = urlRegex.exec(css)) !== null) {\n const url = match[1];\n // Only collect absolute paths (starting with /) — these are self-hosted font files\n if (url && url.startsWith(\"/\")) {\n urls.push(url);\n }\n }\n return urls;\n}\n\n/**\n * Collect font file URLs from self-hosted CSS for preload link generation.\n * Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.\n */\nfunction collectFontPreloadsFromCSS(css: string): void {\n if (typeof document !== \"undefined\") return; // client-side, skip\n\n const urls = extractFontUrlsFromCSS(css);\n for (const href of urls) {\n if (!ssrFontPreloadHrefs.has(href)) {\n ssrFontPreloadHrefs.add(href);\n ssrFontPreloads.push({ href, type: getFontMimeType(href) });\n }\n }\n}\n\n/** Track injected self-hosted @font-face blocks (deduplicate) */\nconst injectedSelfHosted = new Set<string>();\n\n/**\n * Inject self-hosted @font-face CSS (from the build plugin).\n * This replaces the CDN <link> tag with inline CSS.\n */\nfunction injectSelfHostedCSS(css: string): void {\n if (injectedSelfHosted.has(css)) return;\n injectedSelfHosted.add(css);\n\n // Extract font file URLs for preload hints (SSR only)\n collectFontPreloadsFromCSS(css);\n\n if (typeof document === \"undefined\") {\n // SSR: add to collected styles\n ssrFontStyles.push(css);\n return;\n }\n\n // Client: inject <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-selfhosted\", \"true\");\n document.head.appendChild(style);\n}\n\nexport type FontLoader = (options?: FontLoaderOptions) => FontResult;\n\nexport function createFontLoader(family: string): FontLoader {\n return function fontLoader(options: FontLoaderOptions = {}): FontResult {\n const fallback = options.fallback ?? [\"sans-serif\"];\n // Sanitize each fallback name to prevent CSS injection via crafted values\n const fontFamily = `'${escapeCSSString(family)}', ${fallback.map(sanitizeFallback).join(\", \")}`;\n // Validate CSS variable name — reject anything that could inject CSS.\n // Fall back to auto-generated name if invalid.\n const defaultVarName = toVarName(family);\n const cssVarName = options.variable\n ? (sanitizeCSSVarName(options.variable) ?? defaultVarName)\n : defaultVarName;\n const id = createFontIdentity(family, options, cssVarName, fallback);\n const classSegment = fontClassSegment(family);\n const className = `__font_${classSegment}_${id}`;\n // In Next.js, `variable` returns a CLASS NAME that sets the CSS variable.\n // Users apply this class to set the CSS variable on that element.\n const variableClassName = `__variable_${classSegment}_${id}`;\n\n if (options._selfHostedCSS) {\n // Self-hosted mode: inject local @font-face CSS instead of CDN link\n injectSelfHostedCSS(options._selfHostedCSS);\n } else {\n // CDN mode: inject <link> to Google Fonts\n const url = buildGoogleFontsUrl(family, options);\n injectFontStylesheet(url);\n\n // On SSR, collect the URL for head injection\n if (typeof document === \"undefined\") {\n if (!ssrFontUrls.includes(url)) {\n ssrFontUrls.push(url);\n }\n }\n }\n\n // Inject a CSS rule that maps className to font-family.\n // This is what makes `<div className={inter.className}>` work.\n injectClassNameRule(className, fontFamily);\n\n // Inject a CSS rule for the variable class name.\n // This is what makes `<html className={inter.variable}>` set the CSS variable.\n injectVariableClassRule(variableClassName, cssVarName, fontFamily);\n\n return {\n className,\n style: { fontFamily },\n variable: variableClassName,\n };\n };\n}\n\n// Export a Proxy that creates font loaders for any Google Font family.\n// Usage: import { Inter } from 'next/font/google'\n// The proxy intercepts property access and returns a loader for that font.\nconst googleFontLoaders: Record<string, FontLoader> = {};\n\nconst googleFonts = new Proxy(googleFontLoaders, {\n get(_target, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n if (prop === \"__esModule\") return true;\n if (prop === \"default\") return googleFonts;\n // Convert export-style names to proper font family names:\n // - Underscores to spaces: \"Roboto_Mono\" -> \"Roboto Mono\"\n // - PascalCase to spaces: \"RobotoMono\" -> \"Roboto Mono\"\n const family = prop.replace(/_/g, \" \").replace(/([a-z])([A-Z])/g, \"$1 $2\");\n return createFontLoader(family);\n },\n});\n\nexport default googleFonts;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"font-google-base.js","names":["buildUrlFromAxes"],"sources":["../../src/shims/font-google-base.ts"],"sourcesContent":["import { buildGoogleFontsUrl as buildUrlFromAxes } from \"../build/google-fonts/build-url.js\";\nimport {\n escapeCSSString,\n formatFontClassRule,\n resolveSingleFaceStyle,\n sanitizeCSSVarName,\n sanitizeFallback,\n type FontStyle,\n} from \"./font-utils.js\";\n\n/**\n * next/font/google shim\n *\n * Provides a compatible shim for Next.js Google Fonts.\n *\n * Two modes:\n * 1. **Dev / CDN mode** (default): Loads fonts from Google Fonts CDN via <link> tags.\n * 2. **Self-hosted mode** (production build): The vinext:google-fonts Vite plugin\n * fetches font CSS + .woff2 files at build time, caches them locally, and injects\n * @font-face CSS pointing at local assets. No requests to Google at runtime.\n *\n * Usage:\n * import { Inter } from 'next/font/google';\n * const inter = Inter({ subsets: ['latin'], weight: ['400', '700'] });\n * // inter.className -> stable CSS class for this font/options pair\n * // inter.style -> { fontFamily: \"'Inter', 'Inter Fallback'\", fontStyle: \"normal\" }\n * // inter.variable -> CSS class that sets the font CSS variable when requested\n */\n\n// Track which font stylesheets have been injected (SSR + client)\nconst injectedFonts = new Set<string>();\n\nexport type FontOptions = {\n weight?: string | string[];\n style?: string | string[];\n subsets?: string[];\n display?: string;\n preload?: boolean;\n fallback?: string[];\n adjustFontFallback?: boolean | string;\n variable?: string;\n axes?: string[];\n};\n\nexport type FontResult = {\n className: string;\n style: FontStyle;\n variable?: string;\n};\n\ntype InternalGoogleFontRuntimeOptions = {\n selfHostedCSS?: string;\n adjustedFallbackCSS?: string;\n fontWeight?: number;\n fontStyle?: \"normal\" | \"italic\";\n};\n\ntype FontLoaderOptions = FontOptions & {\n /**\n * Internal payload injected by the vinext:google-fonts transform after\n * metadata validation. Runtime must prefer these values over user options\n * because they represent the resolved Next-compatible face, including\n * metadata defaults such as italic-only families.\n */\n _vinext?: {\n font?: InternalGoogleFontRuntimeOptions;\n };\n};\n\n/**\n * Convert a font family name to a CSS variable name.\n * e.g., \"Inter\" -> \"--font-inter\", \"Roboto Mono\" -> \"--font-roboto-mono\"\n */\nfunction toVarName(family: string): string {\n return \"--font-\" + family.toLowerCase().replace(/\\s+/g, \"-\");\n}\n\nfunction fontClassSegment(family: string): string {\n const segment = family\n .toLowerCase()\n .replace(/[^a-z0-9_-]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n return segment || \"font\";\n}\n\nfunction normalizeStringSetOption(value: string | string[] | undefined): string {\n if (!value) return \"\";\n const values = Array.isArray(value) ? value : [value];\n return [...new Set(values.map((item) => item.trim()).filter(Boolean))].sort().join(\",\");\n}\n\nfunction normalizeWeightOption(value: string | string[] | undefined): string {\n const normalized = normalizeStringSetOption(value);\n return normalized === \"variable\" ? \"\" : normalized;\n}\n\nfunction normalizeStyleOption(value: string | string[] | undefined): string {\n const values = new Set(\n (Array.isArray(value) ? value : value ? [value] : [])\n .map((item) => item.trim())\n .filter(Boolean),\n );\n const hasItalic = values.has(\"italic\");\n const hasNormal = values.has(\"normal\");\n if (!hasItalic) return \"\";\n return hasNormal ? \"italic,normal\" : \"italic\";\n}\n\nfunction normalizeFallbackOption(value: string[] | undefined): string {\n if (!value) return \"\";\n return value.map((item) => item.trim()).join(\",\");\n}\n\nfunction normalizeBooleanOption(value: boolean | undefined): string {\n if (value === undefined) return \"\";\n return value ? \"1\" : \"0\";\n}\n\nfunction normalizeStringOrBooleanOption(value: boolean | string | undefined): string {\n if (value === undefined) return \"\";\n return typeof value === \"boolean\" ? normalizeBooleanOption(value) : value;\n}\n\nfunction hashString(value: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < value.length; i++) {\n hash ^= value.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n return hash.toString(36).padStart(7, \"0\");\n}\n\nfunction createFontIdentity(\n family: string,\n options: FontLoaderOptions,\n cssVarName: string,\n fallback: string[],\n): string {\n return hashString(\n [\n family,\n cssVarName,\n normalizeWeightOption(options.weight),\n normalizeStyleOption(options.style),\n normalizeStringSetOption(options.subsets),\n options.display ?? \"swap\",\n normalizeBooleanOption(options.preload),\n normalizeFallbackOption(fallback),\n normalizeStringOrBooleanOption(options.adjustFontFallback),\n normalizeStringSetOption(options.axes),\n options._vinext?.font?.selfHostedCSS ?? \"\",\n options._vinext?.font?.fontWeight?.toString() ?? \"\",\n options._vinext?.font?.fontStyle ?? \"\",\n ].join(\"\\0\"),\n );\n}\n\n/**\n * Build a Google Fonts CSS URL.\n *\n * In production this code path is dead. The build plugin\n * (`vinext:google-fonts` in `src/plugins/fonts.ts`) statically resolves\n * each font call's axis values against the bundled metadata, fetches the\n * Google Fonts CSS, and injects the resulting CSS as\n * `_vinext.font.selfHostedCSS` so the runtime never queries Google. The shim\n * only reaches this builder when the plugin's static parser bails (dynamic\n * options, eval-only shapes), which is dev-only.\n *\n * The dev fallback intentionally has no metadata: shipping the 388 KB\n * `font-data.json` to the Worker bundle would dwarf the rest of the shim,\n * and the production path already has the metadata-aware variant. The\n * tradeoff is that the dev fallback cannot resolve a variable font's\n * actual `wght` axis range. It emits no axis segment when no `weight` is\n * given, which makes Google return the default static face (200) instead\n * of the broken `:wght@100..900` URL that issue #885 reports.\n */\nexport function buildGoogleFontsUrl(family: string, options: FontOptions): string {\n const weights = options.weight\n ? Array.isArray(options.weight)\n ? options.weight\n : [options.weight]\n : [];\n const styles = options.style\n ? Array.isArray(options.style)\n ? options.style\n : [options.style]\n : [];\n\n const hasItalic = styles.includes(\"italic\");\n const hasNormal = styles.includes(\"normal\");\n // Google treats omitted ital as ital=0, so italic-only requests emit\n // ['1']; mixed requests emit ['0','1']; normal-only stays undefined so\n // the URL has no ital axis at all.\n const ital = hasItalic ? [...(hasNormal ? [\"0\"] : []), \"1\"] : undefined;\n\n // The dev fallback has no metadata, so the variable sentinel cannot be\n // resolved to the font's real axis range here. Drop it like empty options\n // instead of emitting the invalid Google Fonts URL `:wght@variable`.\n const normalizedWeights = weights.length === 1 && weights[0] === \"variable\" ? [] : weights;\n\n // Italic-only with no explicit weight still needs a wght value or the\n // ital axis has nowhere to attach in Google's URL grammar. Fall back to\n // '400' because every Google Font has it and it is the visible default.\n // The plugin's metadata-aware path covers the variable-font case in\n // production.\n const wght = normalizedWeights.length > 0 ? normalizedWeights : ital ? [\"400\"] : undefined;\n\n return buildUrlFromAxes(family, { wght, ital }, options.display ?? \"swap\");\n}\n\n/**\n * Inject a <link> tag for the font (client-side only).\n * On the server, we track font URLs for SSR head injection.\n */\nfunction injectFontStylesheet(url: string): void {\n if (injectedFonts.has(url)) return;\n injectedFonts.add(url);\n\n if (typeof document !== \"undefined\") {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = url;\n document.head.appendChild(link);\n }\n}\n\n/** Track which className CSS rules have been injected. */\nconst injectedClassRules = new Set<string>();\n\n/**\n * Inject a CSS rule that maps a className to the exported font style.\n *\n * This is what makes `<div className={inter.className}>` apply the font.\n * Next.js generates equivalent rules at build time.\n *\n * In Next.js, the .className class sets font-family and any single\n * font-weight/font-style. CSS variables are handled separately by .variable.\n */\nfunction injectClassNameRule(className: string, fontStyle: FontStyle): void {\n if (injectedClassRules.has(className)) return;\n injectedClassRules.add(className);\n\n const css = formatFontClassRule(className, fontStyle);\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const styleElement = document.createElement(\"style\");\n styleElement.textContent = css;\n styleElement.setAttribute(\"data-vinext-font-class\", className);\n document.head.appendChild(styleElement);\n}\n\n/** Track which variable class CSS rules have been injected. */\nconst injectedVariableRules = new Set<string>();\n\n/**\n * Inject a CSS rule that sets a CSS variable on an element.\n * This is what makes `<html className={inter.variable}>` set the CSS variable\n * that can be referenced by other styles (e.g., Tailwind's font-sans).\n *\n * In Next.js, the .variable class ONLY sets the CSS variable — it does NOT\n * set font-family. This is critical because apps commonly apply multiple\n * .variable classes to <body> (e.g., geistSans.variable + geistMono.variable).\n * If we also set font-family here, the last class wins due to CSS cascade,\n * causing all text to use that font (e.g., everything becomes monospace).\n */\nfunction injectVariableClassRule(\n variableClassName: string,\n cssVarName: string,\n fontFamily: string,\n): void {\n if (injectedVariableRules.has(variableClassName)) return;\n injectedVariableRules.add(variableClassName);\n\n // Only set the CSS variable — do NOT set font-family.\n // This matches Next.js behavior where .variable classes only define CSS variables.\n const css = `.${variableClassName} { ${cssVarName}: ${fontFamily}; }\\n`;\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-variable\", variableClassName);\n document.head.appendChild(style);\n}\n\n// SSR: collect font class CSS for injection in <head>\nconst ssrFontStyles: string[] = [];\n\n/**\n * Get collected SSR font class styles (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontStyles(): string[] {\n return [...ssrFontStyles];\n}\n\n// SSR: collect font URLs to inject in <head>\nconst ssrFontUrls: string[] = [];\n\n/**\n * Get collected SSR font URLs (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontLinks(): string[] {\n return [...ssrFontUrls];\n}\n\n// SSR: collect font file URLs for <link rel=\"preload\"> injection (self-hosted Google fonts)\nconst ssrFontPreloads: Array<{ href: string; type: string }> = [];\nconst ssrFontPreloadHrefs = new Set<string>();\n\n/**\n * Get collected SSR font preload data (used by the renderer).\n * Returns an array of { href, type } objects for emitting\n * <link rel=\"preload\" as=\"font\" ...> tags.\n */\nexport function getSSRFontPreloads(): Array<{ href: string; type: string }> {\n return [...ssrFontPreloads];\n}\n\n/**\n * Determine the MIME type for a font file based on its extension.\n */\nfunction getFontMimeType(pathOrUrl: string): string {\n if (pathOrUrl.endsWith(\".woff2\")) return \"font/woff2\";\n if (pathOrUrl.endsWith(\".woff\")) return \"font/woff\";\n if (pathOrUrl.endsWith(\".ttf\")) return \"font/ttf\";\n if (pathOrUrl.endsWith(\".otf\")) return \"font/opentype\";\n return \"font/woff2\";\n}\n\n/**\n * Extract font file URLs from @font-face CSS rules.\n * Parses url('...') references from the CSS text.\n */\nfunction extractFontUrlsFromCSS(css: string): string[] {\n const urls: string[] = [];\n const urlRegex = /url\\(['\"]?([^'\")]+)['\"]?\\)/g;\n let match: RegExpExecArray | null;\n while ((match = urlRegex.exec(css)) !== null) {\n const url = match[1];\n // Only collect absolute paths (starting with /) — these are self-hosted font files\n if (url && url.startsWith(\"/\")) {\n urls.push(url);\n }\n }\n return urls;\n}\n\n/**\n * Collect font file URLs from self-hosted CSS for preload link generation.\n * Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.\n */\nfunction collectFontPreloadsFromCSS(css: string): void {\n if (typeof document !== \"undefined\") return; // client-side, skip\n\n const urls = extractFontUrlsFromCSS(css);\n for (const href of urls) {\n if (!ssrFontPreloadHrefs.has(href)) {\n ssrFontPreloadHrefs.add(href);\n ssrFontPreloads.push({ href, type: getFontMimeType(href) });\n }\n }\n}\n\n/** Track injected self-hosted @font-face blocks (deduplicate) */\nconst injectedSelfHosted = new Set<string>();\n\n/**\n * Inject self-hosted @font-face CSS (from the build plugin).\n * This replaces the CDN <link> tag with inline CSS.\n */\nfunction injectSelfHostedCSS(css: string): void {\n if (injectedSelfHosted.has(css)) return;\n injectedSelfHosted.add(css);\n\n // Extract font file URLs for preload hints (SSR only)\n collectFontPreloadsFromCSS(css);\n\n if (typeof document === \"undefined\") {\n // SSR: add to collected styles\n ssrFontStyles.push(css);\n return;\n }\n\n // Client: inject <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-selfhosted\", \"true\");\n document.head.appendChild(style);\n}\n\nexport type FontLoader = (options?: FontLoaderOptions) => FontResult;\n\nexport function createFontLoader(family: string): FontLoader {\n return function fontLoader(options: FontLoaderOptions = {}): FontResult {\n const internal = options._vinext?.font;\n const fallback = options.fallback ?? [];\n // The adjusted fallback family name must match the font-family emitted by\n // buildFallbackFontFace() in build/google-fonts/fallback-metrics.ts ('{family} Fallback').\n // Keep these two sites in sync to prevent silent fallback mismatches.\n const adjustedFallback =\n options.adjustFontFallback === false || !internal?.adjustedFallbackCSS\n ? []\n : [`'${escapeCSSString(family)} Fallback'`];\n // Sanitize each fallback name to prevent CSS injection via crafted values\n const fontFamily = [\n `'${escapeCSSString(family)}'`,\n ...adjustedFallback,\n ...fallback.map(sanitizeFallback),\n ].join(\", \");\n // Validate CSS variable name — reject anything that could inject CSS.\n // Fall back to auto-generated name if invalid.\n const defaultVarName = toVarName(family);\n const cssVarName = options.variable\n ? (sanitizeCSSVarName(options.variable) ?? defaultVarName)\n : defaultVarName;\n const id = createFontIdentity(family, options, cssVarName, fallback);\n const classSegment = fontClassSegment(family);\n const className = `__font_${classSegment}_${id}`;\n // In Next.js, `variable` returns a CLASS NAME that sets the CSS variable.\n // Users apply this class to set the CSS variable on that element.\n const variableClassName = `__variable_${classSegment}_${id}`;\n const style = resolveSingleFaceStyle({\n fontFamily,\n weight: options.weight,\n style: options.style,\n internalWeight: internal?.fontWeight,\n internalStyle: internal?.fontStyle,\n google: true,\n });\n\n if (internal?.selfHostedCSS) {\n // Self-hosted mode: inject local @font-face CSS instead of CDN link\n injectSelfHostedCSS(internal.selfHostedCSS);\n } else {\n // CDN mode: inject <link> to Google Fonts\n const url = buildGoogleFontsUrl(family, options);\n injectFontStylesheet(url);\n\n // On SSR, collect the URL for head injection\n if (typeof document === \"undefined\") {\n if (!ssrFontUrls.includes(url)) {\n ssrFontUrls.push(url);\n }\n }\n }\n\n if (options.adjustFontFallback !== false && internal?.adjustedFallbackCSS) {\n injectSelfHostedCSS(internal.adjustedFallbackCSS);\n }\n\n // Inject a CSS rule that maps className to font-family.\n // This is what makes `<div className={inter.className}>` work.\n injectClassNameRule(className, style);\n\n if (options.variable) {\n // Inject a CSS rule for the variable class name.\n // This is what makes `<html className={inter.variable}>` set the CSS variable.\n injectVariableClassRule(variableClassName, cssVarName, fontFamily);\n }\n\n return {\n className,\n style,\n ...(options.variable ? { variable: variableClassName } : {}),\n };\n };\n}\n\n// Export a Proxy that creates font loaders for any Google Font family.\n// Usage: import { Inter } from 'next/font/google'\n// The proxy intercepts property access and returns a loader for that font.\nconst googleFontLoaders: Record<string, FontLoader> = {};\n\nconst googleFonts = new Proxy(googleFontLoaders, {\n get(_target, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n if (prop === \"__esModule\") return true;\n if (prop === \"default\") return googleFonts;\n // Convert export-style names to proper font family names:\n // - Underscores to spaces: \"Roboto_Mono\" -> \"Roboto Mono\"\n // - PascalCase to spaces: \"RobotoMono\" -> \"Roboto Mono\"\n const family = prop.replace(/_/g, \" \").replace(/([a-z])([A-Z])/g, \"$1 $2\");\n return createFontLoader(family);\n },\n});\n\nexport default googleFonts;\n"],"mappings":"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"}
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
+
import { FontStyle } from "./font-utils.js";
|
|
2
|
+
|
|
1
3
|
//#region src/shims/font-local.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* next/font/local shim
|
|
4
|
-
*
|
|
5
|
-
* Provides a runtime-compatible shim for Next.js local fonts.
|
|
6
|
-
* Generates @font-face CSS declarations and returns an object
|
|
7
|
-
* with className, style, and variable properties.
|
|
8
|
-
*
|
|
9
|
-
* Supports both client-side injection and SSR collection,
|
|
10
|
-
* matching the patterns used by the Google font shim.
|
|
11
|
-
*
|
|
12
|
-
* Usage:
|
|
13
|
-
* import localFont from 'next/font/local';
|
|
14
|
-
* const myFont = localFont({ src: './my-font.woff2' });
|
|
15
|
-
* // myFont.className -> unique CSS class
|
|
16
|
-
* // myFont.style -> { fontFamily: "'__local_font_0', sans-serif" }
|
|
17
|
-
* // myFont.variable -> generated class name (e.g. "__variable_local_0")
|
|
18
|
-
*/
|
|
19
4
|
type LocalFontSrc = {
|
|
20
5
|
path: string;
|
|
21
6
|
weight?: string;
|
|
@@ -37,9 +22,7 @@ type LocalFontOptions = {
|
|
|
37
22
|
};
|
|
38
23
|
type FontResult = {
|
|
39
24
|
className: string;
|
|
40
|
-
style:
|
|
41
|
-
fontFamily: string;
|
|
42
|
-
};
|
|
25
|
+
style: FontStyle;
|
|
43
26
|
variable?: string;
|
|
44
27
|
};
|
|
45
28
|
/**
|
package/dist/shims/font-local.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { escapeCSSString, formatFontClassRule, resolveSingleFaceStyle, sanitizeCSSVarName, sanitizeFallback, sanitizeFontDescriptorValue } from "./font-utils.js";
|
|
1
2
|
//#region src/shims/font-local.ts
|
|
2
3
|
/**
|
|
3
4
|
* next/font/local shim
|
|
@@ -14,57 +15,9 @@
|
|
|
14
15
|
* const myFont = localFont({ src: './my-font.woff2' });
|
|
15
16
|
* // myFont.className -> unique CSS class
|
|
16
17
|
* // myFont.style -> { fontFamily: "'__local_font_0', sans-serif" }
|
|
17
|
-
* // myFont.variable -> generated class name
|
|
18
|
+
* // myFont.variable -> generated class name when requested
|
|
18
19
|
*/
|
|
19
20
|
/**
|
|
20
|
-
* Escape a string for safe interpolation inside a CSS single-quoted string.
|
|
21
|
-
*
|
|
22
|
-
* Prevents CSS injection by escaping characters that could break out of
|
|
23
|
-
* a `'...'` CSS string context: backslashes, single quotes, and newlines.
|
|
24
|
-
*/
|
|
25
|
-
function escapeCSSString(value) {
|
|
26
|
-
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\a ").replace(/\r/g, "\\d ");
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Validate a CSS custom property name (e.g. `--font-inter`).
|
|
30
|
-
*
|
|
31
|
-
* Custom properties must start with `--` and only contain alphanumeric
|
|
32
|
-
* characters, hyphens, and underscores. Anything else could be used to
|
|
33
|
-
* break out of the CSS declaration and inject arbitrary rules.
|
|
34
|
-
*
|
|
35
|
-
* Returns the name if valid, undefined otherwise.
|
|
36
|
-
*/
|
|
37
|
-
function sanitizeCSSVarName(name) {
|
|
38
|
-
if (/^--[a-zA-Z0-9_-]+$/.test(name)) return name;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Sanitize a CSS font-family fallback name.
|
|
42
|
-
*
|
|
43
|
-
* Generic family names (sans-serif, serif, monospace, etc.) are used as-is.
|
|
44
|
-
* Named families are wrapped in escaped quotes. This prevents injection via
|
|
45
|
-
* crafted fallback values like `); } body { color: red; } .x {`.
|
|
46
|
-
*/
|
|
47
|
-
function sanitizeFallback(name) {
|
|
48
|
-
const generics = new Set([
|
|
49
|
-
"serif",
|
|
50
|
-
"sans-serif",
|
|
51
|
-
"monospace",
|
|
52
|
-
"cursive",
|
|
53
|
-
"fantasy",
|
|
54
|
-
"system-ui",
|
|
55
|
-
"ui-serif",
|
|
56
|
-
"ui-sans-serif",
|
|
57
|
-
"ui-monospace",
|
|
58
|
-
"ui-rounded",
|
|
59
|
-
"emoji",
|
|
60
|
-
"math",
|
|
61
|
-
"fangsong"
|
|
62
|
-
]);
|
|
63
|
-
const trimmed = name.trim();
|
|
64
|
-
if (generics.has(trimmed)) return trimmed;
|
|
65
|
-
return `'${escapeCSSString(trimmed)}'`;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
21
|
* Validate a CSS property name for use in declarations.
|
|
69
22
|
*
|
|
70
23
|
* Only allows standard CSS property names (lowercase letters and hyphens)
|
|
@@ -74,25 +27,14 @@ function sanitizeFallback(name) {
|
|
|
74
27
|
function sanitizeCSSProperty(prop) {
|
|
75
28
|
if (/^(--)?[a-zA-Z][a-zA-Z0-9-]*$/.test(prop)) return prop;
|
|
76
29
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Sanitize a CSS property value for use in declarations.
|
|
79
|
-
*
|
|
80
|
-
* Rejects values containing characters that could break out of a CSS
|
|
81
|
-
* declaration: `{`, `}`, `;`, and `</` (to prevent closing style tags).
|
|
82
|
-
*/
|
|
83
|
-
function sanitizeCSSValue(value) {
|
|
84
|
-
if (/[{}]|<\//.test(value)) return void 0;
|
|
85
|
-
return value;
|
|
86
|
-
}
|
|
87
30
|
let classCounter = 0;
|
|
88
31
|
const injectedFonts = /* @__PURE__ */ new Set();
|
|
89
|
-
function generateFontFaceCSS(family, options) {
|
|
90
|
-
const sources = normalizeSources(options);
|
|
32
|
+
function generateFontFaceCSS(family, options, sources) {
|
|
91
33
|
const display = options.display ?? "swap";
|
|
92
34
|
const rules = [];
|
|
93
35
|
for (const src of sources) {
|
|
94
|
-
const weight = src.weight ?? options.weight ?? "400";
|
|
95
|
-
const style = src.style ?? options.style ?? "normal";
|
|
36
|
+
const weight = sanitizeFontDescriptorValue(src.weight ?? options.weight ?? "400") ?? "400";
|
|
37
|
+
const style = sanitizeFontDescriptorValue(src.style ?? options.style ?? "normal") ?? "normal";
|
|
96
38
|
const format = src.path.endsWith(".woff2") ? "woff2" : src.path.endsWith(".woff") ? "woff" : src.path.endsWith(".ttf") ? "truetype" : src.path.endsWith(".otf") ? "opentype" : "woff2";
|
|
97
39
|
rules.push(`@font-face {
|
|
98
40
|
font-family: '${escapeCSSString(family)}';
|
|
@@ -104,7 +46,7 @@ function generateFontFaceCSS(family, options) {
|
|
|
104
46
|
}
|
|
105
47
|
if (options.declarations) for (const decl of options.declarations) {
|
|
106
48
|
const safeProp = sanitizeCSSProperty(decl.prop);
|
|
107
|
-
const safeValue =
|
|
49
|
+
const safeValue = sanitizeFontDescriptorValue(decl.value);
|
|
108
50
|
if (safeProp && safeValue) rules.push(`@font-face { font-family: '${escapeCSSString(family)}'; ${safeProp}: ${safeValue}; }`);
|
|
109
51
|
}
|
|
110
52
|
return rules.join("\n");
|
|
@@ -143,17 +85,17 @@ function injectFontFaceCSS(css, id) {
|
|
|
143
85
|
/** Track which className CSS rules have been injected. */
|
|
144
86
|
const injectedClassRules = /* @__PURE__ */ new Set();
|
|
145
87
|
/**
|
|
146
|
-
* Inject a CSS rule that maps a className to
|
|
88
|
+
* Inject a CSS rule that maps a className to the exported font style.
|
|
147
89
|
*
|
|
148
90
|
* This is what makes `<div className={font.className}>` apply the font.
|
|
149
91
|
*
|
|
150
|
-
* In Next.js, the .className class
|
|
151
|
-
*
|
|
92
|
+
* In Next.js, the .className class sets font-family and any single
|
|
93
|
+
* font-weight/font-style. CSS variables are handled separately by .variable.
|
|
152
94
|
*/
|
|
153
|
-
function injectClassNameRule(className,
|
|
95
|
+
function injectClassNameRule(className, fontStyle) {
|
|
154
96
|
if (injectedClassRules.has(className)) return;
|
|
155
97
|
injectedClassRules.add(className);
|
|
156
|
-
const css =
|
|
98
|
+
const css = formatFontClassRule(className, fontStyle);
|
|
157
99
|
if (typeof document === "undefined") {
|
|
158
100
|
ssrFontStyles.push(css);
|
|
159
101
|
return;
|
|
@@ -220,9 +162,8 @@ function getFontMimeType(pathOrUrl) {
|
|
|
220
162
|
* Collect font source URLs for preload link generation.
|
|
221
163
|
* Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.
|
|
222
164
|
*/
|
|
223
|
-
function collectFontPreloads(
|
|
165
|
+
function collectFontPreloads(sources) {
|
|
224
166
|
if (typeof document !== "undefined") return;
|
|
225
|
-
const sources = normalizeSources(options);
|
|
226
167
|
for (const src of sources) {
|
|
227
168
|
const href = src.path;
|
|
228
169
|
if (href && href.startsWith("/") && !ssrFontPreloadHrefs.has(href)) {
|
|
@@ -236,18 +177,25 @@ function collectFontPreloads(options) {
|
|
|
236
177
|
}
|
|
237
178
|
function localFont(options) {
|
|
238
179
|
const id = classCounter++;
|
|
180
|
+
const sources = normalizeSources(options);
|
|
181
|
+
const singleSource = sources.length === 1 ? sources[0] : void 0;
|
|
239
182
|
const family = `__local_font_${id}`;
|
|
240
183
|
const className = `__font_local_${id}`;
|
|
241
184
|
const fontFamily = `'${family}', ${(options.fallback ?? ["sans-serif"]).map(sanitizeFallback).join(", ")}`;
|
|
242
185
|
const cssVarName = options.variable ? sanitizeCSSVarName(options.variable) : void 0;
|
|
243
186
|
const variableClassName = `__variable_local_${id}`;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
187
|
+
const style = singleSource ? resolveSingleFaceStyle({
|
|
188
|
+
fontFamily,
|
|
189
|
+
weight: singleSource.weight ?? options.weight,
|
|
190
|
+
style: singleSource.style ?? options.style
|
|
191
|
+
}) : { fontFamily };
|
|
192
|
+
collectFontPreloads(sources);
|
|
193
|
+
injectFontFaceCSS(generateFontFaceCSS(family, options, sources), family);
|
|
194
|
+
injectClassNameRule(className, style);
|
|
247
195
|
if (cssVarName) injectVariableClassRule(variableClassName, cssVarName, fontFamily);
|
|
248
196
|
return {
|
|
249
197
|
className,
|
|
250
|
-
style
|
|
198
|
+
style,
|
|
251
199
|
...cssVarName ? { variable: variableClassName } : {}
|
|
252
200
|
};
|
|
253
201
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"font-local.js","names":[],"sources":["../../src/shims/font-local.ts"],"sourcesContent":["/**\n * next/font/local shim\n *\n * Provides a runtime-compatible shim for Next.js local fonts.\n * Generates @font-face CSS declarations and returns an object\n * with className, style, and variable properties.\n *\n * Supports both client-side injection and SSR collection,\n * matching the patterns used by the Google font shim.\n *\n * Usage:\n * import localFont from 'next/font/local';\n * const myFont = localFont({ src: './my-font.woff2' });\n * // myFont.className -> unique CSS class\n * // myFont.style -> { fontFamily: \"'__local_font_0', sans-serif\" }\n * // myFont.variable -> generated class name (e.g. \"__variable_local_0\")\n */\n\n/**\n * Escape a string for safe interpolation inside a CSS single-quoted string.\n *\n * Prevents CSS injection by escaping characters that could break out of\n * a `'...'` CSS string context: backslashes, single quotes, and newlines.\n */\nfunction escapeCSSString(value: string): string {\n return value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, \"\\\\a \")\n .replace(/\\r/g, \"\\\\d \");\n}\n\n/**\n * Validate a CSS custom property name (e.g. `--font-inter`).\n *\n * Custom properties must start with `--` and only contain alphanumeric\n * characters, hyphens, and underscores. Anything else could be used to\n * break out of the CSS declaration and inject arbitrary rules.\n *\n * Returns the name if valid, undefined otherwise.\n */\nfunction sanitizeCSSVarName(name: string): string | undefined {\n if (/^--[a-zA-Z0-9_-]+$/.test(name)) return name;\n return undefined;\n}\n\n/**\n * Sanitize a CSS font-family fallback name.\n *\n * Generic family names (sans-serif, serif, monospace, etc.) are used as-is.\n * Named families are wrapped in escaped quotes. This prevents injection via\n * crafted fallback values like `); } body { color: red; } .x {`.\n */\nfunction sanitizeFallback(name: string): string {\n // CSS generic font families — safe to use unquoted\n const generics = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"emoji\",\n \"math\",\n \"fangsong\",\n ]);\n const trimmed = name.trim();\n if (generics.has(trimmed)) return trimmed;\n // Wrap in single quotes with escaping to prevent CSS injection\n return `'${escapeCSSString(trimmed)}'`;\n}\n\n/**\n * Validate a CSS property name for use in declarations.\n *\n * Only allows standard CSS property names (lowercase letters and hyphens)\n * and custom properties (--prefixed). Rejects anything that could inject\n * CSS rules via crafted property names.\n */\nfunction sanitizeCSSProperty(prop: string): string | undefined {\n if (/^(--)?[a-zA-Z][a-zA-Z0-9-]*$/.test(prop)) return prop;\n return undefined;\n}\n\n/**\n * Sanitize a CSS property value for use in declarations.\n *\n * Rejects values containing characters that could break out of a CSS\n * declaration: `{`, `}`, `;`, and `</` (to prevent closing style tags).\n */\nfunction sanitizeCSSValue(value: string): string | undefined {\n if (/[{}]|<\\//.test(value)) return undefined;\n return value;\n}\n\nlet classCounter = 0;\nconst injectedFonts = new Set<string>();\n\ntype LocalFontSrc = {\n path: string;\n weight?: string;\n style?: string;\n};\n\ntype LocalFontOptions = {\n src: string | LocalFontSrc | LocalFontSrc[];\n display?: string;\n weight?: string;\n style?: string;\n fallback?: string[];\n preload?: boolean;\n variable?: string;\n adjustFontFallback?: boolean | string;\n declarations?: Array<{ prop: string; value: string }>;\n};\n\ntype FontResult = {\n className: string;\n style: { fontFamily: string };\n variable?: string;\n};\n\nfunction generateFontFaceCSS(family: string, options: LocalFontOptions): string {\n const sources = normalizeSources(options);\n\n const display = options.display ?? \"swap\";\n const rules: string[] = [];\n\n for (const src of sources) {\n const weight = src.weight ?? options.weight ?? \"400\";\n const style = src.style ?? options.style ?? \"normal\";\n const format = src.path.endsWith(\".woff2\")\n ? \"woff2\"\n : src.path.endsWith(\".woff\")\n ? \"woff\"\n : src.path.endsWith(\".ttf\")\n ? \"truetype\"\n : src.path.endsWith(\".otf\")\n ? \"opentype\"\n : \"woff2\";\n\n rules.push(`@font-face {\n font-family: '${escapeCSSString(family)}';\n src: url('${escapeCSSString(src.path)}') format('${format}');\n font-weight: ${weight};\n font-style: ${style};\n font-display: ${display};\n}`);\n }\n\n // Add extra declarations if provided — sanitize prop/value to prevent injection\n if (options.declarations) {\n for (const decl of options.declarations) {\n const safeProp = sanitizeCSSProperty(decl.prop);\n const safeValue = sanitizeCSSValue(decl.value);\n if (safeProp && safeValue) {\n rules.push(\n `@font-face { font-family: '${escapeCSSString(family)}'; ${safeProp}: ${safeValue}; }`,\n );\n }\n }\n }\n\n return rules.join(\"\\n\");\n}\n\n// SSR: collect font styles for injection in <head>\nconst ssrFontStyles: string[] = [];\n\n// SSR: collect font file URLs for <link rel=\"preload\"> injection\nconst ssrFontPreloads: Array<{ href: string; type: string }> = [];\nconst ssrFontPreloadHrefs = new Set<string>();\n\n/**\n * Get collected SSR font styles (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontStyles(): string[] {\n return [...ssrFontStyles];\n}\n\n/**\n * Get collected SSR font preload data (used by the renderer).\n * Returns an array of { href, type } objects for emitting\n * <link rel=\"preload\" as=\"font\" ...> tags.\n */\nexport function getSSRFontPreloads(): Array<{ href: string; type: string }> {\n return [...ssrFontPreloads];\n}\n\nfunction injectFontFaceCSS(css: string, id: string): void {\n if (injectedFonts.has(id)) return;\n injectedFonts.add(id);\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font\", id);\n document.head.appendChild(style);\n}\n\n/** Track which className CSS rules have been injected. */\nconst injectedClassRules = new Set<string>();\n\n/**\n * Inject a CSS rule that maps a className to a font-family.\n *\n * This is what makes `<div className={font.className}>` apply the font.\n *\n * In Next.js, the .className class ONLY sets font-family — it does NOT\n * set CSS variables. CSS variables are handled separately by the .variable class.\n */\nfunction injectClassNameRule(className: string, fontFamily: string): void {\n if (injectedClassRules.has(className)) return;\n injectedClassRules.add(className);\n\n const css = `.${className} { font-family: ${fontFamily}; }\\n`;\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-class\", className);\n document.head.appendChild(style);\n}\n\n/** Track which variable class CSS rules have been injected. */\nconst injectedVariableRules = new Set<string>();\n\n/** Track which :root CSS variable rules have been injected. */\nconst injectedRootVariables = new Set<string>();\n\n/**\n * Inject a CSS rule that sets a CSS variable on an element.\n * This is what makes `<html className={font.variable}>` set the CSS variable\n * that can be referenced by other styles (e.g., Tailwind's font-sans).\n *\n * In Next.js, the .variable class ONLY sets the CSS variable — it does NOT\n * set font-family. This is critical because apps commonly apply multiple\n * .variable classes to <body> (e.g., geistSans.variable + geistMono.variable).\n * If we also set font-family here, the last class wins due to CSS cascade,\n * causing all text to use that font (e.g., everything becomes monospace).\n */\nfunction injectVariableClassRule(\n variableClassName: string,\n cssVarName: string,\n fontFamily: string,\n): void {\n if (injectedVariableRules.has(variableClassName)) return;\n injectedVariableRules.add(variableClassName);\n\n // Only set the CSS variable — do NOT set font-family.\n // This matches Next.js behavior where .variable classes only define CSS variables.\n let css = `.${variableClassName} { ${cssVarName}: ${fontFamily}; }\\n`;\n\n // Also inject at :root so CSS variable inheritance works throughout the page.\n // This ensures Tailwind utilities like `font-sans` that reference these\n // variables via var(--font-geist-sans) work correctly.\n if (!injectedRootVariables.has(cssVarName)) {\n injectedRootVariables.add(cssVarName);\n css += `:root { ${cssVarName}: ${fontFamily}; }\\n`;\n }\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-variable\", variableClassName);\n document.head.appendChild(style);\n}\n\n/**\n * Normalize the `src` option into a flat array of `{ path, weight?, style? }`.\n * Handles string, single object, and array forms.\n */\nfunction normalizeSources(options: LocalFontOptions): LocalFontSrc[] {\n if (Array.isArray(options.src)) return options.src;\n if (typeof options.src === \"string\") return [{ path: options.src }];\n return [options.src];\n}\n\n/**\n * Determine the MIME type for a font file based on its extension.\n * Uses endsWith() only — matching the approach in generateFontFaceCSS —\n * to avoid false positives from substring matches (e.g. \".woff\" matching \".woff2\").\n */\nfunction getFontMimeType(pathOrUrl: string): string {\n if (pathOrUrl.endsWith(\".woff2\")) return \"font/woff2\";\n if (pathOrUrl.endsWith(\".woff\")) return \"font/woff\";\n if (pathOrUrl.endsWith(\".ttf\")) return \"font/ttf\";\n if (pathOrUrl.endsWith(\".otf\")) return \"font/opentype\";\n return \"font/woff2\";\n}\n\n/**\n * Collect font source URLs for preload link generation.\n * Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.\n */\nfunction collectFontPreloads(options: LocalFontOptions): void {\n if (typeof document !== \"undefined\") return; // client-side, skip\n\n const sources = normalizeSources(options);\n\n for (const src of sources) {\n const href = src.path;\n // Only collect URLs that are absolute (start with /) — relative paths\n // would resolve incorrectly from different page URLs. The vinext:local-fonts\n // Vite transform should have already resolved them to absolute URLs.\n if (href && href.startsWith(\"/\") && !ssrFontPreloadHrefs.has(href)) {\n ssrFontPreloadHrefs.add(href);\n ssrFontPreloads.push({ href, type: getFontMimeType(href) });\n }\n }\n}\n\nexport default function localFont(options: LocalFontOptions): FontResult {\n const id = classCounter++;\n const family = `__local_font_${id}`;\n const className = `__font_local_${id}`;\n const fallback = options.fallback ?? [\"sans-serif\"];\n // Sanitize each fallback name to prevent CSS injection via crafted values\n const fontFamily = `'${family}', ${fallback.map(sanitizeFallback).join(\", \")}`;\n // Validate CSS variable name — reject anything that could inject CSS\n const cssVarName = options.variable ? sanitizeCSSVarName(options.variable) : undefined;\n // In Next.js, `variable` returns a CLASS NAME that sets the CSS variable.\n // Users apply this class to set the CSS variable on that element.\n const variableClassName = `__variable_local_${id}`;\n\n // Collect font URLs for preload <link> tags (SSR only)\n collectFontPreloads(options);\n\n // Inject @font-face declarations\n const css = generateFontFaceCSS(family, options);\n injectFontFaceCSS(css, family);\n\n // Inject the className -> font-family CSS rule\n injectClassNameRule(className, fontFamily);\n\n // Inject a CSS rule for the variable class name if variable is specified.\n // This is what makes `<html className={font.variable}>` set the CSS variable.\n if (cssVarName) {\n injectVariableClassRule(variableClassName, cssVarName, fontFamily);\n }\n\n return {\n className,\n style: { fontFamily },\n ...(cssVarName ? { variable: variableClassName } : {}),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"font-local.js","names":[],"sources":["../../src/shims/font-local.ts"],"sourcesContent":["/**\n * next/font/local shim\n *\n * Provides a runtime-compatible shim for Next.js local fonts.\n * Generates @font-face CSS declarations and returns an object\n * with className, style, and variable properties.\n *\n * Supports both client-side injection and SSR collection,\n * matching the patterns used by the Google font shim.\n *\n * Usage:\n * import localFont from 'next/font/local';\n * const myFont = localFont({ src: './my-font.woff2' });\n * // myFont.className -> unique CSS class\n * // myFont.style -> { fontFamily: \"'__local_font_0', sans-serif\" }\n * // myFont.variable -> generated class name when requested\n */\nimport {\n escapeCSSString,\n formatFontClassRule,\n resolveSingleFaceStyle,\n sanitizeCSSVarName,\n sanitizeFallback,\n sanitizeFontDescriptorValue,\n type FontStyle,\n} from \"./font-utils.js\";\n\n/**\n * Validate a CSS property name for use in declarations.\n *\n * Only allows standard CSS property names (lowercase letters and hyphens)\n * and custom properties (--prefixed). Rejects anything that could inject\n * CSS rules via crafted property names.\n */\nfunction sanitizeCSSProperty(prop: string): string | undefined {\n if (/^(--)?[a-zA-Z][a-zA-Z0-9-]*$/.test(prop)) return prop;\n return undefined;\n}\n\nlet classCounter = 0;\nconst injectedFonts = new Set<string>();\n\ntype LocalFontSrc = {\n path: string;\n weight?: string;\n style?: string;\n};\n\ntype LocalFontOptions = {\n src: string | LocalFontSrc | LocalFontSrc[];\n display?: string;\n weight?: string;\n style?: string;\n fallback?: string[];\n preload?: boolean;\n variable?: string;\n adjustFontFallback?: boolean | string;\n declarations?: Array<{ prop: string; value: string }>;\n};\n\ntype FontResult = {\n className: string;\n style: FontStyle;\n variable?: string;\n};\n\nfunction generateFontFaceCSS(\n family: string,\n options: LocalFontOptions,\n sources: LocalFontSrc[],\n): string {\n const display = options.display ?? \"swap\";\n const rules: string[] = [];\n\n for (const src of sources) {\n const weight = sanitizeFontDescriptorValue(src.weight ?? options.weight ?? \"400\") ?? \"400\";\n const style = sanitizeFontDescriptorValue(src.style ?? options.style ?? \"normal\") ?? \"normal\";\n const format = src.path.endsWith(\".woff2\")\n ? \"woff2\"\n : src.path.endsWith(\".woff\")\n ? \"woff\"\n : src.path.endsWith(\".ttf\")\n ? \"truetype\"\n : src.path.endsWith(\".otf\")\n ? \"opentype\"\n : \"woff2\";\n\n rules.push(`@font-face {\n font-family: '${escapeCSSString(family)}';\n src: url('${escapeCSSString(src.path)}') format('${format}');\n font-weight: ${weight};\n font-style: ${style};\n font-display: ${display};\n}`);\n }\n\n // Add extra declarations if provided — sanitize prop/value to prevent injection\n if (options.declarations) {\n for (const decl of options.declarations) {\n const safeProp = sanitizeCSSProperty(decl.prop);\n const safeValue = sanitizeFontDescriptorValue(decl.value);\n if (safeProp && safeValue) {\n rules.push(\n `@font-face { font-family: '${escapeCSSString(family)}'; ${safeProp}: ${safeValue}; }`,\n );\n }\n }\n }\n\n return rules.join(\"\\n\");\n}\n\n// SSR: collect font styles for injection in <head>\nconst ssrFontStyles: string[] = [];\n\n// SSR: collect font file URLs for <link rel=\"preload\"> injection\nconst ssrFontPreloads: Array<{ href: string; type: string }> = [];\nconst ssrFontPreloadHrefs = new Set<string>();\n\n/**\n * Get collected SSR font styles (used by the renderer).\n * Note: We don't clear the arrays because fonts are loaded at module import\n * time and need to persist across all requests in the Workers environment.\n */\nexport function getSSRFontStyles(): string[] {\n return [...ssrFontStyles];\n}\n\n/**\n * Get collected SSR font preload data (used by the renderer).\n * Returns an array of { href, type } objects for emitting\n * <link rel=\"preload\" as=\"font\" ...> tags.\n */\nexport function getSSRFontPreloads(): Array<{ href: string; type: string }> {\n return [...ssrFontPreloads];\n}\n\nfunction injectFontFaceCSS(css: string, id: string): void {\n if (injectedFonts.has(id)) return;\n injectedFonts.add(id);\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font\", id);\n document.head.appendChild(style);\n}\n\n/** Track which className CSS rules have been injected. */\nconst injectedClassRules = new Set<string>();\n\n/**\n * Inject a CSS rule that maps a className to the exported font style.\n *\n * This is what makes `<div className={font.className}>` apply the font.\n *\n * In Next.js, the .className class sets font-family and any single\n * font-weight/font-style. CSS variables are handled separately by .variable.\n */\nfunction injectClassNameRule(className: string, fontStyle: FontStyle): void {\n if (injectedClassRules.has(className)) return;\n injectedClassRules.add(className);\n\n const css = formatFontClassRule(className, fontStyle);\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-class\", className);\n document.head.appendChild(style);\n}\n\n/** Track which variable class CSS rules have been injected. */\nconst injectedVariableRules = new Set<string>();\n\n/** Track which :root CSS variable rules have been injected. */\nconst injectedRootVariables = new Set<string>();\n\n/**\n * Inject a CSS rule that sets a CSS variable on an element.\n * This is what makes `<html className={font.variable}>` set the CSS variable\n * that can be referenced by other styles (e.g., Tailwind's font-sans).\n *\n * In Next.js, the .variable class ONLY sets the CSS variable — it does NOT\n * set font-family. This is critical because apps commonly apply multiple\n * .variable classes to <body> (e.g., geistSans.variable + geistMono.variable).\n * If we also set font-family here, the last class wins due to CSS cascade,\n * causing all text to use that font (e.g., everything becomes monospace).\n */\nfunction injectVariableClassRule(\n variableClassName: string,\n cssVarName: string,\n fontFamily: string,\n): void {\n if (injectedVariableRules.has(variableClassName)) return;\n injectedVariableRules.add(variableClassName);\n\n // Only set the CSS variable — do NOT set font-family.\n // This matches Next.js behavior where .variable classes only define CSS variables.\n let css = `.${variableClassName} { ${cssVarName}: ${fontFamily}; }\\n`;\n\n // Also inject at :root so CSS variable inheritance works throughout the page.\n // This ensures Tailwind utilities like `font-sans` that reference these\n // variables via var(--font-geist-sans) work correctly.\n if (!injectedRootVariables.has(cssVarName)) {\n injectedRootVariables.add(cssVarName);\n css += `:root { ${cssVarName}: ${fontFamily}; }\\n`;\n }\n\n // On server, store the CSS for SSR injection\n if (typeof document === \"undefined\") {\n ssrFontStyles.push(css);\n return;\n }\n\n // On client, inject a <style> tag\n const style = document.createElement(\"style\");\n style.textContent = css;\n style.setAttribute(\"data-vinext-font-variable\", variableClassName);\n document.head.appendChild(style);\n}\n\n/**\n * Normalize the `src` option into a flat array of `{ path, weight?, style? }`.\n * Handles string, single object, and array forms.\n */\nfunction normalizeSources(options: LocalFontOptions): LocalFontSrc[] {\n if (Array.isArray(options.src)) return options.src;\n if (typeof options.src === \"string\") return [{ path: options.src }];\n return [options.src];\n}\n\n/**\n * Determine the MIME type for a font file based on its extension.\n * Uses endsWith() only — matching the approach in generateFontFaceCSS —\n * to avoid false positives from substring matches (e.g. \".woff\" matching \".woff2\").\n */\nfunction getFontMimeType(pathOrUrl: string): string {\n if (pathOrUrl.endsWith(\".woff2\")) return \"font/woff2\";\n if (pathOrUrl.endsWith(\".woff\")) return \"font/woff\";\n if (pathOrUrl.endsWith(\".ttf\")) return \"font/ttf\";\n if (pathOrUrl.endsWith(\".otf\")) return \"font/opentype\";\n return \"font/woff2\";\n}\n\n/**\n * Collect font source URLs for preload link generation.\n * Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.\n */\nfunction collectFontPreloads(sources: LocalFontSrc[]): void {\n if (typeof document !== \"undefined\") return; // client-side, skip\n\n for (const src of sources) {\n const href = src.path;\n // Only collect URLs that are absolute (start with /) — relative paths\n // would resolve incorrectly from different page URLs. The vinext:local-fonts\n // Vite transform should have already resolved them to absolute URLs.\n if (href && href.startsWith(\"/\") && !ssrFontPreloadHrefs.has(href)) {\n ssrFontPreloadHrefs.add(href);\n ssrFontPreloads.push({ href, type: getFontMimeType(href) });\n }\n }\n}\n\nexport default function localFont(options: LocalFontOptions): FontResult {\n const id = classCounter++;\n const sources = normalizeSources(options);\n const singleSource = sources.length === 1 ? sources[0] : undefined;\n const family = `__local_font_${id}`;\n const className = `__font_local_${id}`;\n const fallback = options.fallback ?? [\"sans-serif\"];\n // Sanitize each fallback name to prevent CSS injection via crafted values\n const fontFamily = `'${family}', ${fallback.map(sanitizeFallback).join(\", \")}`;\n // Validate CSS variable name — reject anything that could inject CSS\n const cssVarName = options.variable ? sanitizeCSSVarName(options.variable) : undefined;\n // In Next.js, `variable` returns a CLASS NAME that sets the CSS variable.\n // Users apply this class to set the CSS variable on that element.\n const variableClassName = `__variable_local_${id}`;\n const style = singleSource\n ? resolveSingleFaceStyle({\n fontFamily,\n weight: singleSource.weight ?? options.weight,\n style: singleSource.style ?? options.style,\n })\n : { fontFamily };\n\n // Collect font URLs for preload <link> tags (SSR only)\n collectFontPreloads(sources);\n\n // Inject @font-face declarations\n const css = generateFontFaceCSS(family, options, sources);\n injectFontFaceCSS(css, family);\n\n // Inject the className -> font-family CSS rule\n injectClassNameRule(className, style);\n\n // Inject a CSS rule for the variable class name if variable is specified.\n // This is what makes `<html className={font.variable}>` set the CSS variable.\n if (cssVarName) {\n injectVariableClassRule(variableClassName, cssVarName, fontFamily);\n }\n\n return {\n className,\n style,\n ...(cssVarName ? { variable: variableClassName } : {}),\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/shims/font-utils.d.ts
|
|
2
|
+
type FontStyle = {
|
|
3
|
+
fontFamily: string;
|
|
4
|
+
fontWeight?: number;
|
|
5
|
+
fontStyle?: string;
|
|
6
|
+
};
|
|
7
|
+
type FontFaceStyleInput = {
|
|
8
|
+
fontFamily: string;
|
|
9
|
+
weight?: string | string[];
|
|
10
|
+
style?: string | string[];
|
|
11
|
+
internalWeight?: number;
|
|
12
|
+
internalStyle?: string;
|
|
13
|
+
google?: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Escape a string for safe interpolation inside a CSS single-quoted string.
|
|
17
|
+
*
|
|
18
|
+
* Prevents CSS injection by escaping characters that could break out of
|
|
19
|
+
* a `'...'` CSS string context: backslashes, single quotes, and newlines.
|
|
20
|
+
*
|
|
21
|
+
* Used by font-google-base.ts, font-local.ts, and fallback-metrics.ts.
|
|
22
|
+
*/
|
|
23
|
+
declare function escapeCSSString(value: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Validate a CSS custom property name (e.g. `--font-inter`).
|
|
26
|
+
*
|
|
27
|
+
* Custom properties must start with `--` and only contain alphanumeric
|
|
28
|
+
* characters, hyphens, and underscores. Anything else could be used to
|
|
29
|
+
* break out of the CSS declaration and inject arbitrary rules.
|
|
30
|
+
*
|
|
31
|
+
* Returns the name if valid, undefined otherwise.
|
|
32
|
+
*/
|
|
33
|
+
declare function sanitizeCSSVarName(name: string): string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Sanitize a CSS font-family fallback name.
|
|
36
|
+
*
|
|
37
|
+
* Generic family names (sans-serif, serif, monospace, etc.) are used as-is.
|
|
38
|
+
* Named families are wrapped in escaped quotes. This prevents injection via
|
|
39
|
+
* crafted fallback values like `); } body { color: red; } .x {`.
|
|
40
|
+
*/
|
|
41
|
+
declare function sanitizeFallback(name: string): string;
|
|
42
|
+
declare function singleFontOptionValue(value: string | string[] | undefined): string | undefined;
|
|
43
|
+
declare function sanitizeFontDescriptorValue(value: string): string | undefined;
|
|
44
|
+
declare function resolveFontWeight(weight: string | string[] | undefined): number | undefined;
|
|
45
|
+
declare function resolveFontStyle(style: string | string[] | undefined): string | undefined;
|
|
46
|
+
declare function resolveGoogleFontStyle(style: string | string[] | undefined): string | undefined;
|
|
47
|
+
declare function resolveSingleFaceStyle(input: FontFaceStyleInput): FontStyle;
|
|
48
|
+
declare function formatFontClassRule(className: string, style: FontStyle): string;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { FontFaceStyleInput, FontStyle, escapeCSSString, formatFontClassRule, resolveFontStyle, resolveFontWeight, resolveGoogleFontStyle, resolveSingleFaceStyle, sanitizeCSSVarName, sanitizeFallback, sanitizeFontDescriptorValue, singleFontOptionValue };
|
|
51
|
+
//# sourceMappingURL=font-utils.d.ts.map
|