vinext 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -9
- package/dist/build/client-build-config.d.ts +64 -3
- package/dist/build/client-build-config.js +131 -4
- package/dist/build/client-reference-groups.d.ts +163 -0
- package/dist/build/client-reference-groups.js +534 -0
- package/dist/build/module-dependency-cache.d.ts +31 -0
- package/dist/build/module-dependency-cache.js +51 -1
- package/dist/build/next-client-runtime-manifests.d.ts +10 -1
- package/dist/build/next-client-runtime-manifests.js +19 -4
- package/dist/build/nitro-public-files.d.ts +24 -0
- package/dist/build/nitro-public-files.js +60 -0
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/prerender-paths.js +5 -2
- package/dist/build/server-actions-encryption-key.d.ts +23 -0
- package/dist/build/server-actions-encryption-key.js +101 -0
- package/dist/build/ssr-manifest.d.ts +3 -0
- package/dist/build/ssr-manifest.js +10 -1
- package/dist/client/client-rewrite-params.d.ts +9 -0
- package/dist/client/client-rewrite-params.js +20 -0
- package/dist/client/dev-error-overlay.js +2 -1
- package/dist/client/navigation-runtime.d.ts +25 -2
- package/dist/client/navigation-runtime.js +42 -11
- package/dist/client/vinext-next-data.d.ts +0 -1
- package/dist/config/config-matchers.d.ts +15 -40
- package/dist/config/config-matchers.js +183 -255
- package/dist/config/config-source.d.ts +34 -0
- package/dist/config/config-source.js +141 -0
- package/dist/config/header-params.d.ts +29 -0
- package/dist/config/header-params.js +106 -0
- package/dist/config/next-config.d.ts +7 -5
- package/dist/config/next-config.js +120 -7
- package/dist/entries/app-browser-entry.d.ts +14 -1
- package/dist/entries/app-browser-entry.js +26 -36
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +92 -57
- package/dist/entries/app-rsc-manifest.d.ts +10 -0
- package/dist/entries/app-rsc-manifest.js +20 -1
- package/dist/entries/app-ssr-entry.d.ts +4 -1
- package/dist/entries/app-ssr-entry.js +9 -2
- package/dist/entries/pages-client-entry.d.ts +1 -0
- package/dist/entries/pages-client-entry.js +6 -6
- package/dist/entries/pages-server-entry.js +17 -14
- package/dist/index.d.ts +11 -0
- package/dist/index.js +239 -83
- package/dist/init.js +17 -0
- package/dist/plugins/optimize-imports.d.ts +25 -2
- package/dist/plugins/optimize-imports.js +106 -20
- package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
- package/dist/plugins/rsc-client-reference-loaders.js +336 -18
- package/dist/plugins/use-cache-callable.d.ts +5 -0
- package/dist/plugins/use-cache-callable.js +30 -8
- package/dist/plugins/worker-image-imports.d.ts +1 -0
- package/dist/plugins/worker-image-imports.js +1 -1
- package/dist/routing/app-route-graph.d.ts +1 -1
- package/dist/routing/browser-route-manifest.d.ts +43 -0
- package/dist/routing/browser-route-manifest.js +195 -0
- package/dist/routing/hashed-route-patterns.d.ts +4 -0
- package/dist/routing/hashed-route-patterns.js +22 -0
- package/dist/routing/optimistic-route-trie.d.ts +27 -0
- package/dist/routing/optimistic-route-trie.js +102 -0
- package/dist/routing/route-validation.d.ts +6 -1
- package/dist/routing/route-validation.js +26 -10
- package/dist/server/app-action-forwarding.d.ts +8 -0
- package/dist/server/app-action-forwarding.js +15 -1
- package/dist/server/app-browser-entry.js +147 -60
- package/dist/server/app-browser-error.d.ts +3 -1
- package/dist/server/app-browser-error.js +7 -2
- package/dist/server/app-browser-interception-context.d.ts +2 -2
- package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
- package/dist/server/app-browser-mpa-navigation.js +6 -5
- package/dist/server/app-browser-navigation-controller.d.ts +17 -6
- package/dist/server/app-browser-navigation-controller.js +88 -26
- package/dist/server/app-browser-state.d.ts +2 -2
- package/dist/server/app-browser-visible-commit.d.ts +4 -4
- package/dist/server/app-client-reference-preloader.d.ts +23 -0
- package/dist/server/app-client-reference-preloader.js +30 -7
- package/dist/server/app-fallback-renderer.js +2 -1
- package/dist/server/app-middleware.d.ts +6 -0
- package/dist/server/app-middleware.js +8 -10
- package/dist/server/app-optimistic-routing.d.ts +8 -10
- package/dist/server/app-optimistic-routing.js +4 -95
- package/dist/server/app-page-boundary-render.js +8 -1
- package/dist/server/app-page-cache-render.js +1 -0
- package/dist/server/app-page-dispatch.js +2 -0
- package/dist/server/app-page-render.js +3 -1
- package/dist/server/app-page-rsc-render-status.d.ts +1 -0
- package/dist/server/app-page-rsc-render-status.js +1 -0
- package/dist/server/app-page-search-params-observation.d.ts +1 -4
- package/dist/server/app-page-search-params-observation.js +8 -10
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +1 -0
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +11 -7
- package/dist/server/app-prerender-static-params.js +3 -2
- package/dist/server/app-render-dependency.js +42 -2
- package/dist/server/app-request-stage-independent-entry.js +2 -2
- package/dist/server/app-response-stage-entry.js +3 -3
- package/dist/server/app-route-handler-dispatch.js +3 -1
- package/dist/server/app-route-handler-execution.d.ts +2 -0
- package/dist/server/app-route-handler-execution.js +9 -2
- package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
- package/dist/server/app-route-handler-middleware-context.js +3 -3
- package/dist/server/app-route-handler-response.d.ts +2 -1
- package/dist/server/app-route-handler-response.js +2 -2
- package/dist/server/app-route-handler-runtime.d.ts +2 -0
- package/dist/server/app-route-handler-runtime.js +20 -3
- package/dist/server/app-route-module-loader.js +7 -6
- package/dist/server/app-route-tree.d.ts +20 -0
- package/dist/server/app-route-tree.js +18 -0
- package/dist/server/app-router-entry.js +2 -2
- package/dist/server/app-rsc-combined-handler.js +8 -1
- package/dist/server/app-rsc-errors.d.ts +7 -0
- package/dist/server/app-rsc-errors.js +9 -2
- package/dist/server/app-rsc-handler.d.ts +4 -1
- package/dist/server/app-rsc-handler.js +146 -130
- package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.js +3 -1
- package/dist/server/app-rsc-route-matching.d.ts +1 -0
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +23 -6
- package/dist/server/app-server-action-execution.js +50 -56
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +16 -7
- package/dist/server/app-ssr-stream.d.ts +7 -0
- package/dist/server/app-ssr-stream.js +13 -1
- package/dist/server/config-headers.js +12 -3
- package/dist/server/isolate-shared-promise.d.ts +10 -0
- package/dist/server/isolate-shared-promise.js +33 -0
- package/dist/server/isr-cache.js +3 -2
- package/dist/server/middleware-matcher-pattern.d.ts +0 -1
- package/dist/server/middleware-matcher-pattern.js +11 -140
- package/dist/server/middleware-matcher.js +5 -6
- package/dist/server/middleware-response-headers.d.ts +31 -0
- package/dist/server/middleware-response-headers.js +57 -1
- package/dist/server/middleware-runtime.js +26 -13
- package/dist/server/navigation-planner.d.ts +2 -2
- package/dist/server/nitro-public-files-plugin.d.ts +38 -0
- package/dist/server/nitro-public-files-plugin.js +106 -0
- package/dist/server/nitro-public-files.d.ts +21 -0
- package/dist/server/nitro-public-files.js +39 -0
- package/dist/server/pages-asset-tags.d.ts +5 -0
- package/dist/server/pages-asset-tags.js +9 -2
- package/dist/server/pages-client-assets.d.ts +4 -1
- package/dist/server/pages-i18n.d.ts +18 -0
- package/dist/server/pages-i18n.js +18 -2
- package/dist/server/pages-node-compat.d.ts +5 -3
- package/dist/server/pages-node-compat.js +35 -16
- package/dist/server/pages-request-pipeline.d.ts +6 -1
- package/dist/server/pages-request-pipeline.js +31 -35
- package/dist/server/pages-request-stage-entry.js +16 -6
- package/dist/server/pages-response-stage-entry.js +1 -1
- package/dist/server/pages-revalidate.js +1 -0
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +71 -33
- package/dist/server/proxy-trust.d.ts +6 -0
- package/dist/server/proxy-trust.js +12 -6
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +12 -1
- package/dist/server/server-reference-loader.js +10 -1
- package/dist/server/static-file-cache.js +15 -3
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/cache-handler.js +3 -2
- package/dist/shims/cache-request-state.d.ts +40 -3
- package/dist/shims/cache-request-state.js +70 -5
- package/dist/shims/cache-runtime.js +47 -19
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +17 -8
- package/dist/shims/cdn-purge-routes.d.ts +24 -0
- package/dist/shims/cdn-purge-routes.js +77 -0
- package/dist/shims/dynamic.js +17 -4
- package/dist/shims/form.js +8 -3
- package/dist/shims/image-props.d.ts +93 -0
- package/dist/shims/image-props.js +323 -0
- package/dist/shims/image.d.ts +4 -18
- package/dist/shims/image.js +4 -319
- package/dist/shims/internal/headers-state.d.ts +7 -0
- package/dist/shims/internal/headers-state.js +14 -2
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +31 -14
- package/dist/shims/internal/hybrid-client-route-owner.js +8 -8
- package/dist/shims/link.js +5 -3
- package/dist/shims/navigation.d.ts +1 -1
- package/dist/shims/navigation.js +17 -5
- package/dist/shims/og.js +35 -10
- package/dist/shims/request-context.d.ts +13 -0
- package/dist/shims/router.js +19 -40
- package/dist/shims/server.d.ts +31 -4
- package/dist/shims/server.js +58 -10
- package/dist/shims/thenable-params.d.ts +6 -1
- package/dist/shims/thenable-params.js +11 -2
- package/dist/shims/unified-request-context.d.ts +5 -0
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/utils/asset-prefix.d.ts +7 -0
- package/dist/utils/asset-prefix.js +10 -1
- package/dist/utils/client-build-manifest.js +12 -5
- package/dist/utils/client-runtime-metadata.d.ts +1 -0
- package/dist/utils/client-runtime-metadata.js +15 -2
- package/dist/utils/lazy-chunks.d.ts +4 -0
- package/dist/utils/manifest-paths.d.ts +14 -0
- package/dist/utils/manifest-paths.js +22 -1
- package/dist/utils/path-to-regexp.d.ts +21 -0
- package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
- package/dist/utils/plugin-react-version.d.ts +15 -0
- package/dist/utils/plugin-react-version.js +64 -0
- package/dist/utils/public-routes.d.ts +2 -0
- package/dist/utils/public-routes.js +18 -7
- package/package.json +1 -1
- package/dist/server/middleware-path-to-regexp.d.ts +0 -13
- package/dist/utils/regex-safety.d.ts +0 -17
- package/dist/utils/regex-safety.js +0 -789
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { getDeploymentId } from "../utils/deployment-id.js";
|
|
2
|
+
import { hasRemoteMatch, isPrivateIp } from "./image-config.js";
|
|
3
|
+
//#region src/shims/image-props.ts
|
|
4
|
+
/**
|
|
5
|
+
* Image config injected at build time via Vite define.
|
|
6
|
+
* Serialized as JSON — parsed once at module level.
|
|
7
|
+
*/
|
|
8
|
+
const __imageRemotePatterns = (() => {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(process.env.__VINEXT_IMAGE_REMOTE_PATTERNS ?? "[]");
|
|
11
|
+
} catch {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
})();
|
|
15
|
+
const __imageDomains = (() => {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(process.env.__VINEXT_IMAGE_DOMAINS ?? "[]");
|
|
18
|
+
} catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
})();
|
|
22
|
+
const __hasImageConfig = __imageRemotePatterns.length > 0 || __imageDomains.length > 0;
|
|
23
|
+
const __isDev = process.env.NODE_ENV !== "production";
|
|
24
|
+
const __imageDeviceSizes = (() => {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(process.env.__VINEXT_IMAGE_DEVICE_SIZES ?? "[640,750,828,1080,1200,1920,2048,3840]");
|
|
27
|
+
} catch {
|
|
28
|
+
return [
|
|
29
|
+
640,
|
|
30
|
+
750,
|
|
31
|
+
828,
|
|
32
|
+
1080,
|
|
33
|
+
1200,
|
|
34
|
+
1920,
|
|
35
|
+
2048,
|
|
36
|
+
3840
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
})();
|
|
40
|
+
const __imageSizes = (() => {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(process.env.__VINEXT_IMAGE_SIZES ?? "[32,48,64,96,128,256,384]");
|
|
43
|
+
} catch {
|
|
44
|
+
return [
|
|
45
|
+
32,
|
|
46
|
+
48,
|
|
47
|
+
64,
|
|
48
|
+
96,
|
|
49
|
+
128,
|
|
50
|
+
256,
|
|
51
|
+
384
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
})();
|
|
55
|
+
/**
|
|
56
|
+
* Whether dangerouslyAllowSVG is enabled in next.config.js.
|
|
57
|
+
* When false (default), .svg sources auto-skip the optimization endpoint
|
|
58
|
+
* and are served directly, matching Next.js behavior.
|
|
59
|
+
* When true, .svg sources are routed through the optimizer (served as-is
|
|
60
|
+
* with security headers).
|
|
61
|
+
*/
|
|
62
|
+
const __dangerouslyAllowSVG = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_SVG === "true";
|
|
63
|
+
/**
|
|
64
|
+
* Whether dangerouslyAllowLocalIP is enabled in next.config.js.
|
|
65
|
+
* When false (default), remote image URLs with literal private-IP hostnames
|
|
66
|
+
* are blocked to mitigate SSRF risk.
|
|
67
|
+
*/
|
|
68
|
+
const __dangerouslyAllowLocalIP = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_LOCAL_IP === "true";
|
|
69
|
+
const __globallyUnoptimized = process.env.__VINEXT_IMAGE_UNOPTIMIZED === "true";
|
|
70
|
+
/**
|
|
71
|
+
* Validate that a remote URL is allowed by the configured remote patterns.
|
|
72
|
+
* Returns true if the URL is allowed, false otherwise.
|
|
73
|
+
*
|
|
74
|
+
* When no remotePatterns/domains are configured, all remote URLs are allowed
|
|
75
|
+
* (backwards-compatible — user hasn't opted into restriction).
|
|
76
|
+
*
|
|
77
|
+
* When patterns ARE configured, only matching URLs are allowed.
|
|
78
|
+
* In development, non-matching URLs produce a console warning.
|
|
79
|
+
* In production, non-matching URLs are blocked (src replaced with empty string).
|
|
80
|
+
*
|
|
81
|
+
* Private-IP hostnames are additionally rejected unless dangerouslyAllowLocalIP
|
|
82
|
+
* is set, mirroring Next.js's fetchExternalImage guard.
|
|
83
|
+
*/
|
|
84
|
+
function validateRemoteUrl(src) {
|
|
85
|
+
let url;
|
|
86
|
+
try {
|
|
87
|
+
url = new URL(src, "http://n");
|
|
88
|
+
} catch {
|
|
89
|
+
return {
|
|
90
|
+
allowed: false,
|
|
91
|
+
reason: `Invalid URL: ${src}`
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (!__dangerouslyAllowLocalIP && isPrivateIp(url.hostname)) return {
|
|
95
|
+
allowed: false,
|
|
96
|
+
reason: `Image URL "${src}" resolved to private IP. If this is expected and you understand SSRF risk, use images.dangerouslyAllowLocalIP = true to continue.`
|
|
97
|
+
};
|
|
98
|
+
if (!__hasImageConfig) return { allowed: true };
|
|
99
|
+
if (hasRemoteMatch(__imageDomains, __imageRemotePatterns, url)) return { allowed: true };
|
|
100
|
+
return {
|
|
101
|
+
allowed: false,
|
|
102
|
+
reason: `Image URL "${src}" is not configured in images.remotePatterns or images.domains in next.config.js. See: https://nextjs.org/docs/messages/next-image-unconfigured-host`
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Sanitize a blurDataURL to prevent CSS injection.
|
|
107
|
+
*
|
|
108
|
+
* A crafted data URL containing `)` can break out of the `url()` CSS function,
|
|
109
|
+
* allowing injection of arbitrary CSS properties or rules. Characters like `{`,
|
|
110
|
+
* `}`, and `\` can also assist in crafting injection payloads.
|
|
111
|
+
*
|
|
112
|
+
* This validates the URL starts with `data:image/` and rejects characters that
|
|
113
|
+
* could escape the `url()` context. Semicolons are allowed since they're part
|
|
114
|
+
* of valid data URLs (`data:image/png;base64,...`) and harmless inside `url()`.
|
|
115
|
+
*
|
|
116
|
+
* Returns undefined for invalid URLs, which causes the blur placeholder to be
|
|
117
|
+
* skipped gracefully.
|
|
118
|
+
*/
|
|
119
|
+
function sanitizeBlurDataURL(url) {
|
|
120
|
+
if (!url.startsWith("data:image/")) return void 0;
|
|
121
|
+
if (/[)(}{\\'"\n\r]/.test(url)) return void 0;
|
|
122
|
+
return url;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Determine if a src is a remote URL (CDN-optimizable) or local.
|
|
126
|
+
*/
|
|
127
|
+
function isRemoteUrl(src) {
|
|
128
|
+
return src.startsWith("http://") || src.startsWith("https://") || src.startsWith("//");
|
|
129
|
+
}
|
|
130
|
+
function isSvgUrl(src) {
|
|
131
|
+
try {
|
|
132
|
+
return new URL(src, "http://vinext.local").pathname.toLowerCase().endsWith(".svg");
|
|
133
|
+
} catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function getFillStyle(style, backgroundStyle) {
|
|
138
|
+
return {
|
|
139
|
+
position: "absolute",
|
|
140
|
+
inset: 0,
|
|
141
|
+
width: "100%",
|
|
142
|
+
height: "100%",
|
|
143
|
+
objectFit: "cover",
|
|
144
|
+
...backgroundStyle,
|
|
145
|
+
...style
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Resolve src, width, height, blurDataURL from Image props (string or StaticImageData).
|
|
150
|
+
* Shared by the Image component and getImageProps to keep behavior in sync.
|
|
151
|
+
*/
|
|
152
|
+
function resolveImageSource(v) {
|
|
153
|
+
const staticData = typeof v.src === "object" && "default" in v.src ? v.src.default : v.src;
|
|
154
|
+
const src = typeof staticData === "string" ? staticData : staticData.src;
|
|
155
|
+
const sourceWidth = v.width ?? (typeof staticData === "object" ? staticData.width : void 0);
|
|
156
|
+
const sourceHeight = v.height ?? (typeof staticData === "object" ? staticData.height : void 0);
|
|
157
|
+
return {
|
|
158
|
+
src,
|
|
159
|
+
width: typeof sourceWidth === "string" ? Number(sourceWidth) : sourceWidth,
|
|
160
|
+
height: typeof sourceHeight === "string" ? Number(sourceHeight) : sourceHeight,
|
|
161
|
+
blurDataURL: v.blurDataURL ?? (typeof staticData === "object" ? staticData.blurDataURL : void 0)
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Responsive image widths matching Next.js's device sizes config.
|
|
166
|
+
* These are the breakpoints used for srcSet generation.
|
|
167
|
+
* Configurable via `images.deviceSizes` in next.config.js.
|
|
168
|
+
*/
|
|
169
|
+
const RESPONSIVE_WIDTHS = [...__imageDeviceSizes].sort((left, right) => left - right);
|
|
170
|
+
const ALL_IMAGE_WIDTHS = [...RESPONSIVE_WIDTHS, ...__imageSizes].sort((left, right) => left - right);
|
|
171
|
+
function extractLocalDeploymentId(src) {
|
|
172
|
+
let deploymentId = getDeploymentId();
|
|
173
|
+
if (!src.startsWith("/") || src.startsWith("//")) return {
|
|
174
|
+
src,
|
|
175
|
+
deploymentId
|
|
176
|
+
};
|
|
177
|
+
const queryIndex = src.indexOf("?");
|
|
178
|
+
if (queryIndex === -1) return {
|
|
179
|
+
src,
|
|
180
|
+
deploymentId
|
|
181
|
+
};
|
|
182
|
+
const params = new URLSearchParams(src.slice(queryIndex + 1));
|
|
183
|
+
const sourceDeploymentId = params.get("dpl");
|
|
184
|
+
if (!sourceDeploymentId) return {
|
|
185
|
+
src,
|
|
186
|
+
deploymentId
|
|
187
|
+
};
|
|
188
|
+
deploymentId = sourceDeploymentId;
|
|
189
|
+
params.delete("dpl");
|
|
190
|
+
const remainingQuery = params.toString();
|
|
191
|
+
return {
|
|
192
|
+
src: src.slice(0, queryIndex) + (remainingQuery ? `?${remainingQuery}` : ""),
|
|
193
|
+
deploymentId
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const __imageEndpoint = `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/_next/image${process.env.__VINEXT_TRAILING_SLASH === "true" ? "/" : ""}`;
|
|
197
|
+
/**
|
|
198
|
+
* Build a `/_next/image` optimization URL.
|
|
199
|
+
*
|
|
200
|
+
* In production (Cloudflare Workers), the worker intercepts this path and uses
|
|
201
|
+
* the Images binding to resize/transcode on the fly. In dev, the Vite dev
|
|
202
|
+
* server handles it as a passthrough (serves the original file).
|
|
203
|
+
*/
|
|
204
|
+
function imageOptimizationUrl(src, width, quality = 75) {
|
|
205
|
+
const source = extractLocalDeploymentId(src);
|
|
206
|
+
const deploymentQuery = source.src.startsWith("/") && source.deploymentId ? `&dpl=${source.deploymentId}` : "";
|
|
207
|
+
return `${__imageEndpoint}?url=${encodeURIComponent(source.src)}&w=${width}&q=${quality}${deploymentQuery}`;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Generate a srcSet string for responsive images.
|
|
211
|
+
*
|
|
212
|
+
* Each width points to the `/_next/image` optimization endpoint so the
|
|
213
|
+
* server can resize and transcode the image.
|
|
214
|
+
*/
|
|
215
|
+
function getImageWidths(width) {
|
|
216
|
+
return [...new Set([width, width * 2].map((targetWidth) => ALL_IMAGE_WIDTHS.find((configuredWidth) => configuredWidth >= targetWidth) ?? ALL_IMAGE_WIDTHS[ALL_IMAGE_WIDTHS.length - 1]))];
|
|
217
|
+
}
|
|
218
|
+
function generateImageAttributes(src, width, quality = 75, sizes) {
|
|
219
|
+
if (sizes) {
|
|
220
|
+
const viewportPercentages = Array.from(sizes.matchAll(/(^|\s)(1?\d?\d)vw/g), (match) => Number.parseInt(match[2], 10));
|
|
221
|
+
const minimumWidth = viewportPercentages.length > 0 ? RESPONSIVE_WIDTHS[0] * (Math.min(...viewportPercentages) * .01) : 0;
|
|
222
|
+
const candidates = ALL_IMAGE_WIDTHS.filter((candidateWidth) => candidateWidth >= minimumWidth);
|
|
223
|
+
return {
|
|
224
|
+
src: imageOptimizationUrl(src, candidates[candidates.length - 1], quality),
|
|
225
|
+
srcSet: candidates.map((candidateWidth) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${candidateWidth}w`).join(", ")
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
const widths = getImageWidths(width);
|
|
229
|
+
return {
|
|
230
|
+
src: imageOptimizationUrl(src, widths[widths.length - 1], quality),
|
|
231
|
+
srcSet: widths.map((candidateWidth, index) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${index + 1}x`).join(", ")
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* getImageProps — for advanced use cases (picture elements, background images).
|
|
236
|
+
* Returns the props that would be passed to the underlying <img> element.
|
|
237
|
+
*/
|
|
238
|
+
function getImageProps(props) {
|
|
239
|
+
const { src: srcProp, alt, width, height, fill, preload: _preload, priority, quality: _quality, placeholder, blurDataURL: blurDataURLProp, loader, sizes, className, style, onLoad: _onLoad, onLoadingComplete: _onLoadingComplete, unoptimized: _unoptimized, overrideSrc, loading, ...rest } = props;
|
|
240
|
+
const { src, width: imgWidth, height: imgHeight, blurDataURL: imgBlurDataURL } = resolveImageSource({
|
|
241
|
+
src: srcProp,
|
|
242
|
+
width,
|
|
243
|
+
height,
|
|
244
|
+
blurDataURL: blurDataURLProp
|
|
245
|
+
});
|
|
246
|
+
const shouldPreload = _preload === true || priority === true;
|
|
247
|
+
if (_unoptimized === true || __globallyUnoptimized) {
|
|
248
|
+
const renderedSrc = overrideSrc || src;
|
|
249
|
+
const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
|
|
250
|
+
const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
|
|
251
|
+
backgroundImage: `url(${sanitizedBlurURL})`,
|
|
252
|
+
backgroundSize: "cover",
|
|
253
|
+
backgroundRepeat: "no-repeat",
|
|
254
|
+
backgroundPosition: "center"
|
|
255
|
+
} : void 0;
|
|
256
|
+
const imageProps = {
|
|
257
|
+
src: renderedSrc,
|
|
258
|
+
alt,
|
|
259
|
+
width: fill ? void 0 : imgWidth,
|
|
260
|
+
height: fill ? void 0 : imgHeight,
|
|
261
|
+
loading: priority ? "eager" : shouldPreload ? loading : loading ?? "lazy",
|
|
262
|
+
fetchPriority: priority ? "high" : void 0,
|
|
263
|
+
decoding: "async",
|
|
264
|
+
className,
|
|
265
|
+
style: fill ? getFillStyle(style, blurStyle) : {
|
|
266
|
+
...blurStyle,
|
|
267
|
+
...style
|
|
268
|
+
},
|
|
269
|
+
...rest,
|
|
270
|
+
sizes: sizes ?? (fill ? "100vw" : void 0),
|
|
271
|
+
srcSet: void 0
|
|
272
|
+
};
|
|
273
|
+
return { props: Object.assign(imageProps, { "data-nimg": fill ? "fill" : "1" }) };
|
|
274
|
+
}
|
|
275
|
+
let blockedInProd = false;
|
|
276
|
+
if (isRemoteUrl(src)) {
|
|
277
|
+
const validation = validateRemoteUrl(src);
|
|
278
|
+
if (!validation.allowed) {
|
|
279
|
+
if (__isDev) console.warn(`[next/image] ${validation.reason}`);
|
|
280
|
+
else {
|
|
281
|
+
console.error(`[next/image] ${validation.reason}`);
|
|
282
|
+
blockedInProd = true;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const imgQuality = typeof _quality === "string" ? Number(_quality) : _quality ?? 75;
|
|
287
|
+
const resolvedSrc = blockedInProd ? "" : loader ? loader({
|
|
288
|
+
src,
|
|
289
|
+
width: imgWidth ?? 0,
|
|
290
|
+
quality: imgQuality
|
|
291
|
+
}) : src;
|
|
292
|
+
const skipOpt = isSvgUrl(resolvedSrc) && !__dangerouslyAllowSVG || blockedInProd || !!loader || isRemoteUrl(resolvedSrc);
|
|
293
|
+
const optimizedAttributes = imgWidth && !fill && !skipOpt ? generateImageAttributes(resolvedSrc, imgWidth, imgQuality, sizes) : null;
|
|
294
|
+
const optimizedSrc = skipOpt ? resolvedSrc : optimizedAttributes ? optimizedAttributes.src : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);
|
|
295
|
+
const srcSet = optimizedAttributes?.srcSet;
|
|
296
|
+
const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
|
|
297
|
+
const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
|
|
298
|
+
backgroundImage: `url(${sanitizedBlurURL})`,
|
|
299
|
+
backgroundSize: "cover",
|
|
300
|
+
backgroundRepeat: "no-repeat",
|
|
301
|
+
backgroundPosition: "center"
|
|
302
|
+
} : void 0;
|
|
303
|
+
const imageProps = {
|
|
304
|
+
src: optimizedSrc,
|
|
305
|
+
alt,
|
|
306
|
+
width: fill ? void 0 : imgWidth,
|
|
307
|
+
height: fill ? void 0 : imgHeight,
|
|
308
|
+
loading: priority ? "eager" : shouldPreload ? loading : loading ?? "lazy",
|
|
309
|
+
fetchPriority: priority ? "high" : void 0,
|
|
310
|
+
decoding: "async",
|
|
311
|
+
srcSet,
|
|
312
|
+
sizes: sizes ?? (fill ? "100vw" : void 0),
|
|
313
|
+
className,
|
|
314
|
+
style: fill ? getFillStyle(style, blurStyle) : {
|
|
315
|
+
...blurStyle,
|
|
316
|
+
...style
|
|
317
|
+
},
|
|
318
|
+
...rest
|
|
319
|
+
};
|
|
320
|
+
return { props: Object.assign(imageProps, { "data-nimg": fill ? "fill" : "1" }) };
|
|
321
|
+
}
|
|
322
|
+
//#endregion
|
|
323
|
+
export { RESPONSIVE_WIDTHS, __dangerouslyAllowSVG, __globallyUnoptimized, __isDev, generateImageAttributes, getFillStyle, getImageProps, imageOptimizationUrl, isRemoteUrl, isSvgUrl, resolveImageSource, sanitizeBlurDataURL, validateRemoteUrl };
|
package/dist/shims/image.d.ts
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
|
+
import { getImageProps, imageOptimizationUrl } from "./image-props.js";
|
|
1
2
|
import React from "react";
|
|
2
|
-
import { ImageLoader, ImageProps as ImageProps$1,
|
|
3
|
+
import { ImageLoader, ImageProps as ImageProps$1, StaticImageData, StaticRequire } from "@vinext/types/next/upstream/dist/shared/lib/get-img-props";
|
|
3
4
|
//#region src/shims/image.d.ts
|
|
4
5
|
export type ImageLoaderProps = Parameters<ImageLoader>[0];
|
|
5
6
|
export type ImageProps = ImageProps$1;
|
|
6
|
-
/**
|
|
7
|
-
* Build a `/_next/image` optimization URL.
|
|
8
|
-
*
|
|
9
|
-
* In production (Cloudflare Workers), the worker intercepts this path and uses
|
|
10
|
-
* the Images binding to resize/transcode on the fly. In dev, the Vite dev
|
|
11
|
-
* server handles it as a passthrough (serves the original file).
|
|
12
|
-
*/
|
|
13
|
-
export declare function imageOptimizationUrl(src: string, width: number, quality?: number): string;
|
|
14
7
|
declare const Image: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "alt" | "height" | "loading" | "ref" | "src" | "srcSet" | "width"> & {
|
|
15
|
-
src: string | StaticImport;
|
|
8
|
+
src: string | import("@vinext/types/next/upstream/dist/shared/lib/get-img-props").StaticImport;
|
|
16
9
|
alt: string;
|
|
17
10
|
width?: number | `${number}`;
|
|
18
11
|
height?: number | `${number}`;
|
|
@@ -33,12 +26,5 @@ declare const Image: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProp
|
|
|
33
26
|
lazyBoundary?: string;
|
|
34
27
|
lazyRoot?: string;
|
|
35
28
|
} & React.RefAttributes<HTMLImageElement>>;
|
|
36
|
-
/**
|
|
37
|
-
* getImageProps — for advanced use cases (picture elements, background images).
|
|
38
|
-
* Returns the props that would be passed to the underlying <img> element.
|
|
39
|
-
*/
|
|
40
|
-
export declare function getImageProps(props: ImageProps): {
|
|
41
|
-
props: ImgProps;
|
|
42
|
-
};
|
|
43
29
|
//#endregion
|
|
44
|
-
export { type ImageLoader, type StaticImageData, type StaticRequire, Image as default };
|
|
30
|
+
export { type ImageLoader, type StaticImageData, type StaticRequire, Image as default, getImageProps, imageOptimizationUrl };
|