@rebask/core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/image.d.ts +16 -3
- package/dist/components/image.d.ts.map +1 -1
- package/dist/components/image.js +50 -68
- package/dist/components/link.d.ts.map +1 -1
- package/dist/components/link.js +6 -2
- package/dist/lib/image-optimization/fetch-remote-image.d.ts +17 -0
- package/dist/lib/image-optimization/fetch-remote-image.d.ts.map +1 -0
- package/dist/lib/image-optimization/fetch-remote-image.js +157 -0
- package/dist/lib/image-optimization/get-img-props.d.ts +3 -5
- package/dist/lib/image-optimization/get-img-props.d.ts.map +1 -1
- package/dist/lib/image-optimization/get-img-props.js +66 -40
- package/dist/lib/image-optimization/handler.d.ts +0 -3
- package/dist/lib/image-optimization/handler.d.ts.map +1 -1
- package/dist/lib/image-optimization/handler.js +339 -124
- package/dist/lib/image-optimization/image-config.d.ts +31 -4
- package/dist/lib/image-optimization/image-config.d.ts.map +1 -1
- package/dist/lib/image-optimization/image-config.js +6 -0
- package/dist/lib/image-optimization/image-error.d.ts +8 -0
- package/dist/lib/image-optimization/image-error.d.ts.map +1 -0
- package/dist/lib/image-optimization/image-error.js +10 -0
- package/dist/lib/image-optimization/image-plugin.d.ts.map +1 -1
- package/dist/lib/image-optimization/image-plugin.js +27 -14
- package/dist/lib/image-optimization/is-private-ip.d.ts +2 -0
- package/dist/lib/image-optimization/is-private-ip.d.ts.map +1 -0
- package/dist/lib/image-optimization/is-private-ip.js +43 -0
- package/dist/lib/image-optimization/match-patterns.d.ts +4 -0
- package/dist/lib/image-optimization/match-patterns.d.ts.map +1 -0
- package/dist/lib/image-optimization/match-patterns.js +39 -0
- package/dist/lib/image-optimization/read-body.d.ts +2 -0
- package/dist/lib/image-optimization/read-body.d.ts.map +1 -0
- package/dist/lib/image-optimization/read-body.js +27 -0
- package/dist/lib/image-optimization/static-image-loader.d.ts +2 -0
- package/dist/lib/image-optimization/static-image-loader.d.ts.map +1 -0
- package/dist/lib/image-optimization/static-image-loader.js +60 -0
- package/dist/lib/server-router/build-entries.d.ts.map +1 -1
- package/dist/lib/server-router/route-entries.js +1 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +12 -4
- package/package.json +2 -1
- package/dist/__type_probe__.d.ts +0 -2
- package/dist/__type_probe__.d.ts.map +0 -1
- package/dist/__type_probe__.js +0 -4
- package/dist/components/error-boundary-client.d.ts +0 -49
- package/dist/components/error-boundary-client.d.ts.map +0 -1
- package/dist/components/error-boundary-client.js +0 -71
- package/dist/components/error-boundary.browser.d.ts +0 -8
- package/dist/components/error-boundary.browser.d.ts.map +0 -1
- package/dist/components/error-boundary.browser.js +0 -6
- package/dist/components/error.d.ts +0 -2
- package/dist/components/error.d.ts.map +0 -1
- package/dist/components/error.js +0 -5
- package/dist/components/not-found-activator.d.ts +0 -11
- package/dist/components/not-found-activator.d.ts.map +0 -1
- package/dist/components/not-found-activator.js +0 -26
- package/dist/components/not-found-boundary-client.d.ts +0 -3
- package/dist/components/not-found-boundary-client.d.ts.map +0 -1
- package/dist/components/not-found-boundary-client.js +0 -20
- package/dist/components/not-found-boundary.browser.d.ts +0 -8
- package/dist/components/not-found-boundary.browser.d.ts.map +0 -1
- package/dist/components/not-found-boundary.browser.js +0 -4
- package/dist/components/not-found-boundary.d.ts +0 -8
- package/dist/components/not-found-boundary.d.ts.map +0 -1
- package/dist/components/not-found-boundary.js +0 -9
- package/dist/components/not-found-thrower.d.ts +0 -2
- package/dist/components/not-found-thrower.d.ts.map +0 -1
- package/dist/components/not-found-thrower.js +0 -7
- package/dist/components/not-found.d.ts +0 -2
- package/dist/components/not-found.d.ts.map +0 -1
- package/dist/components/not-found.js +0 -5
- package/dist/components/status-page.d.ts +0 -6
- package/dist/components/status-page.d.ts.map +0 -1
- package/dist/components/status-page.js +0 -61
- package/dist/handler.d.ts +0 -12
- package/dist/handler.d.ts.map +0 -1
- package/dist/handler.js +0 -21
- package/dist/handlers/rsc/constants.d.ts +0 -3
- package/dist/handlers/rsc/constants.d.ts.map +0 -1
- package/dist/handlers/rsc/constants.js +0 -2
- package/dist/handlers/rsc/create-response.d.ts +0 -3
- package/dist/handlers/rsc/create-response.d.ts.map +0 -1
- package/dist/handlers/rsc/create-response.js +0 -378
- package/dist/handlers/rsc/render-with-retries.d.ts +0 -4
- package/dist/handlers/rsc/render-with-retries.d.ts.map +0 -1
- package/dist/handlers/rsc/render-with-retries.js +0 -154
- package/dist/handlers/rsc/retry-loop.d.ts +0 -3
- package/dist/handlers/rsc/retry-loop.d.ts.map +0 -1
- package/dist/handlers/rsc/retry-loop.js +0 -145
- package/dist/handlers/rsc/stream-rsc-payload.d.ts +0 -9
- package/dist/handlers/rsc/stream-rsc-payload.d.ts.map +0 -1
- package/dist/handlers/rsc/stream-rsc-payload.js +0 -20
- package/dist/handlers/rsc/types.d.ts +0 -26
- package/dist/handlers/rsc/types.d.ts.map +0 -1
- package/dist/handlers/rsc/types.js +0 -7
- package/dist/handlers/rsc.d.ts +0 -20
- package/dist/handlers/rsc.d.ts.map +0 -1
- package/dist/handlers/rsc.js +0 -872
- package/dist/integration.d.ts +0 -14
- package/dist/integration.d.ts.map +0 -1
- package/dist/integration.js +0 -9
- package/dist/lib/dev-module-load-race.d.ts +0 -8
- package/dist/lib/dev-module-load-race.d.ts.map +0 -1
- package/dist/lib/dev-module-load-race.js +0 -31
- package/dist/lib/dev-page-exports.d.ts +0 -5
- package/dist/lib/dev-page-exports.d.ts.map +0 -1
- package/dist/lib/dev-page-exports.js +0 -14
- package/dist/lib/environment-names.d.ts +0 -11
- package/dist/lib/environment-names.d.ts.map +0 -1
- package/dist/lib/environment-names.js +0 -10
- package/dist/lib/initial-hash-scroll.d.ts.map +0 -1
- package/dist/lib/not-found.d.ts +0 -5
- package/dist/lib/not-found.d.ts.map +0 -1
- package/dist/lib/not-found.js +0 -7
- package/dist/lib/page-exports.d.ts +0 -9
- package/dist/lib/page-exports.d.ts.map +0 -1
- package/dist/lib/page-exports.js +0 -47
- package/dist/lib/pattern-segments.d.ts +0 -8
- package/dist/lib/pattern-segments.d.ts.map +0 -1
- package/dist/lib/pattern-segments.js +0 -22
- package/dist/lib/ppr/cache-status.d.ts +0 -3
- package/dist/lib/ppr/cache-status.d.ts.map +0 -1
- package/dist/lib/ppr/cache-status.js +0 -5
- package/dist/lib/server-router-contract.d.ts +0 -42
- package/dist/lib/server-router-contract.d.ts.map +0 -1
- package/dist/lib/server-router-contract.js +0 -6
- package/dist/lib/server-router-loader.d.ts +0 -10
- package/dist/lib/server-router-loader.d.ts.map +0 -1
- package/dist/lib/server-router-loader.js +0 -180
- package/dist/lib/server-router.d.ts +0 -8
- package/dist/lib/server-router.d.ts.map +0 -1
- package/dist/lib/server-router.js +0 -173
- package/dist/plugins/ppr-upgrade.d.ts +0 -36
- package/dist/plugins/ppr-upgrade.d.ts.map +0 -1
- package/dist/plugins/ppr-upgrade.js +0 -32
- package/dist/plugins/server-router-fallback.d.ts +0 -15
- package/dist/plugins/server-router-fallback.d.ts.map +0 -1
- package/dist/plugins/server-router-fallback.js +0 -30
- package/dist/server.d.ts +0 -10
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -57
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import type { ImageProps } from "../lib/image-optimization/get-img-props.js";
|
|
2
|
-
export type { ImageProps }
|
|
1
|
+
import type { ImageProps, PlaceholderValue } from "../lib/image-optimization/get-img-props.js";
|
|
2
|
+
export type { ImageProps };
|
|
3
3
|
/**
|
|
4
4
|
* The `Image` component is used to optimize images.
|
|
5
5
|
*/
|
|
6
|
-
export declare
|
|
6
|
+
export declare const Image: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "alt" | "height" | "loading" | "ref" | "src" | "srcSet" | "width"> & {
|
|
7
|
+
src: string | import("../lib/image-optimization/get-img-props.js").StaticImport;
|
|
8
|
+
alt: string;
|
|
9
|
+
width?: number | `${number}`;
|
|
10
|
+
height?: number | `${number}`;
|
|
11
|
+
fill?: boolean;
|
|
12
|
+
loader?: import("../lib/image-optimization/get-img-props.js").ImageLoader;
|
|
13
|
+
quality?: number | `${number}`;
|
|
14
|
+
preload?: boolean;
|
|
15
|
+
loading?: "eager" | "lazy" | undefined;
|
|
16
|
+
placeholder?: PlaceholderValue;
|
|
17
|
+
blurDataURL?: string;
|
|
18
|
+
unoptimized?: boolean;
|
|
19
|
+
} & import("react").RefAttributes<HTMLImageElement>>;
|
|
7
20
|
//# sourceMappingURL=image.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/components/image.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,UAAU,
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/components/image.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,UAAU,EAGV,gBAAgB,EAChB,MAAM,4CAA4C,CAAA;AAMnD,YAAY,EAAE,UAAU,EAAE,CAAA;AA2O1B;;GAEG;AACH,eAAO,MAAM,KAAK;;;;;;;;;;;;;oDA0ChB,CAAA"}
|
package/dist/components/image.js
CHANGED
|
@@ -1,36 +1,34 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect,
|
|
3
|
+
import { forwardRef, useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import ReactDOM from "react-dom";
|
|
5
5
|
import { getImgProps } from "../lib/image-optimization/get-img-props.js";
|
|
6
6
|
import { imageConfigDefault } from "../lib/image-optimization/image-config.js";
|
|
7
7
|
import { warnOnce } from "../lib/image-optimization/warn-once.js";
|
|
8
|
-
// Get image config from injected global (via Vite define) or default.
|
|
9
8
|
// Vite replaces __REBASK_IMAGE_OPTS at build time.
|
|
10
9
|
function getImageConfig() {
|
|
11
10
|
try {
|
|
12
|
-
// @ts-expect-error -
|
|
13
|
-
|
|
14
|
-
if (configEnv && typeof configEnv === "string") {
|
|
15
|
-
return JSON.parse(configEnv);
|
|
16
|
-
}
|
|
11
|
+
// @ts-expect-error - injected at build time by Vite
|
|
12
|
+
return JSON.parse(__REBASK_IMAGE_OPTS);
|
|
17
13
|
}
|
|
18
14
|
catch {
|
|
19
|
-
|
|
15
|
+
return imageConfigDefault;
|
|
20
16
|
}
|
|
21
|
-
return imageConfigDefault;
|
|
22
17
|
}
|
|
18
|
+
const config = getImageConfig();
|
|
19
|
+
const VALID_POSITIONS = ["absolute", "fixed", "relative"];
|
|
23
20
|
// See https://stackoverflow.com/q/39777833/266535 for why we use this ref
|
|
24
21
|
// handler instead of the img's onLoad attribute.
|
|
25
|
-
function handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized, sizesInput) {
|
|
26
|
-
const src = img
|
|
27
|
-
if (
|
|
22
|
+
function handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized, sizesInput, fill) {
|
|
23
|
+
const src = img.src;
|
|
24
|
+
if (img["data-loaded-src"] === src)
|
|
28
25
|
return;
|
|
29
|
-
}
|
|
30
26
|
img["data-loaded-src"] = src;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
img
|
|
28
|
+
.decode()
|
|
29
|
+
.catch(() => { })
|
|
30
|
+
.then(() => {
|
|
31
|
+
if (!img.isConnected) {
|
|
34
32
|
// Exit early in case of race condition:
|
|
35
33
|
// - onload() is called
|
|
36
34
|
// - decode() is called but incomplete
|
|
@@ -41,26 +39,21 @@ function handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized
|
|
|
41
39
|
if (placeholder !== "empty") {
|
|
42
40
|
setBlurComplete(true);
|
|
43
41
|
}
|
|
44
|
-
if (onLoadRef
|
|
42
|
+
if (onLoadRef.current) {
|
|
45
43
|
// Since we don't have the SyntheticEvent here,
|
|
46
44
|
// we must create one with the same shape.
|
|
47
45
|
// See https://reactjs.org/docs/events.html
|
|
48
46
|
const event = new Event("load");
|
|
49
47
|
Object.defineProperty(event, "target", { writable: false, value: img });
|
|
50
|
-
let prevented = false;
|
|
51
48
|
let stopped = false;
|
|
52
49
|
onLoadRef.current({
|
|
53
|
-
...event,
|
|
54
50
|
nativeEvent: event,
|
|
55
51
|
currentTarget: img,
|
|
56
52
|
target: img,
|
|
57
|
-
isDefaultPrevented: () =>
|
|
53
|
+
isDefaultPrevented: () => event.defaultPrevented,
|
|
58
54
|
isPropagationStopped: () => stopped,
|
|
59
55
|
persist: () => { },
|
|
60
|
-
preventDefault: () =>
|
|
61
|
-
prevented = true;
|
|
62
|
-
event.preventDefault();
|
|
63
|
-
},
|
|
56
|
+
preventDefault: () => event.preventDefault(),
|
|
64
57
|
stopPropagation: () => {
|
|
65
58
|
stopped = true;
|
|
66
59
|
event.stopPropagation();
|
|
@@ -69,7 +62,7 @@ function handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized
|
|
|
69
62
|
}
|
|
70
63
|
if (import.meta.env.DEV) {
|
|
71
64
|
const origSrc = new URL(src, "http://n").searchParams.get("url") || src;
|
|
72
|
-
if (
|
|
65
|
+
if (fill) {
|
|
73
66
|
if (!unoptimized && (!sizesInput || sizesInput === "100vw")) {
|
|
74
67
|
const widthViewportRatio = img.getBoundingClientRect().width / window.innerWidth;
|
|
75
68
|
if (widthViewportRatio < 0.6) {
|
|
@@ -83,9 +76,8 @@ function handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized
|
|
|
83
76
|
}
|
|
84
77
|
if (img.parentElement) {
|
|
85
78
|
const { position } = window.getComputedStyle(img.parentElement);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
warnOnce(`Image with src "${origSrc}" has "fill" and parent element with invalid "position". Provided "${position}" should be one of ${valid.map(String).join(",")}.`);
|
|
79
|
+
if (!VALID_POSITIONS.includes(position)) {
|
|
80
|
+
warnOnce(`Image with src "${origSrc}" has "fill" and parent element with invalid "position". Provided "${position}" should be one of ${VALID_POSITIONS.join(",")}.`);
|
|
89
81
|
}
|
|
90
82
|
}
|
|
91
83
|
if (img.height === 0) {
|
|
@@ -94,21 +86,27 @@ function handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized
|
|
|
94
86
|
}
|
|
95
87
|
const heightModified = img.height.toString() !== img.getAttribute("height");
|
|
96
88
|
const widthModified = img.width.toString() !== img.getAttribute("width");
|
|
97
|
-
if (
|
|
89
|
+
if (heightModified !== widthModified) {
|
|
98
90
|
warnOnce(`Image with src "${origSrc}" has either width or height modified, but not the other. If you use CSS to change the size of your image, also include the styles 'width: "auto"' or 'height: "auto"' to maintain the aspect ratio.`);
|
|
99
91
|
}
|
|
100
92
|
}
|
|
101
93
|
});
|
|
102
94
|
}
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
function ImageElement({ src, srcSet, sizes, height, width, decoding, className, style, fetchPriority, placeholder, loading, unoptimized, fill, onLoadRef, setBlurComplete, setShowAltText, sizesInput, forwardedRef, onError, ...rest }) {
|
|
96
|
+
const imgRef = useRef(null);
|
|
97
|
+
const setRef = useCallback((img) => {
|
|
98
|
+
imgRef.current = img;
|
|
99
|
+
if (typeof forwardedRef === "function") {
|
|
100
|
+
forwardedRef(img);
|
|
101
|
+
}
|
|
102
|
+
else if (forwardedRef) {
|
|
103
|
+
forwardedRef.current = img;
|
|
111
104
|
}
|
|
105
|
+
}, [forwardedRef]);
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const img = imgRef.current;
|
|
108
|
+
if (!img)
|
|
109
|
+
return;
|
|
112
110
|
if (onError) {
|
|
113
111
|
// If the image has an error before react hydrates, then the error is lost.
|
|
114
112
|
// The workaround is to wait until the image is mounted which is after hydration,
|
|
@@ -121,15 +119,15 @@ function ImageElement({ src, srcSet, sizes, height, width, decoding, className,
|
|
|
121
119
|
if (!src) {
|
|
122
120
|
console.error(`Image is missing required "src" property:`, img);
|
|
123
121
|
}
|
|
124
|
-
if (img.
|
|
122
|
+
if (!img.hasAttribute("alt")) {
|
|
125
123
|
console.error(`Image is missing required "alt" property. Please add Alternative Text to describe the image for screen readers and search engines.`);
|
|
126
124
|
}
|
|
127
125
|
}
|
|
128
126
|
if (img.complete) {
|
|
129
|
-
handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized, sizesInput);
|
|
127
|
+
handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized, sizesInput, fill);
|
|
130
128
|
}
|
|
131
|
-
}, [
|
|
132
|
-
return (_jsx("img", { ...rest,
|
|
129
|
+
}, []);
|
|
130
|
+
return (_jsx("img", { ...rest, fetchPriority: fetchPriority,
|
|
133
131
|
// It's intended to keep `loading` before `src` because React updates
|
|
134
132
|
// props in order which causes Safari/Firefox to not lazy load properly.
|
|
135
133
|
// See https://github.com/facebook/react/issues/25883
|
|
@@ -140,9 +138,9 @@ function ImageElement({ src, srcSet, sizes, height, width, decoding, className,
|
|
|
140
138
|
// updated by React. That causes multiple unnecessary requests if `srcSet`
|
|
141
139
|
// and `sizes` are defined.
|
|
142
140
|
// This bug cannot be reproduced in Chrome or Firefox.
|
|
143
|
-
sizes: sizes, srcSet: srcSet, src: src, ref:
|
|
141
|
+
sizes: sizes, srcSet: srcSet, src: src, ref: setRef, onLoad: (event) => {
|
|
144
142
|
const img = event.currentTarget;
|
|
145
|
-
handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized, sizesInput);
|
|
143
|
+
handleLoading(img, placeholder, onLoadRef, setBlurComplete, unoptimized, sizesInput, fill);
|
|
146
144
|
}, onError: (event) => {
|
|
147
145
|
// if the real image fails to load, this will ensure "alt" is visible
|
|
148
146
|
setShowAltText(true);
|
|
@@ -158,7 +156,7 @@ function ImageElement({ src, srcSet, sizes, height, width, decoding, className,
|
|
|
158
156
|
/**
|
|
159
157
|
* The `Image` component is used to optimize images.
|
|
160
158
|
*/
|
|
161
|
-
export function Image(props) {
|
|
159
|
+
export const Image = forwardRef(function Image(props, forwardedRef) {
|
|
162
160
|
const { onLoad } = props;
|
|
163
161
|
const onLoadRef = useRef(onLoad);
|
|
164
162
|
useEffect(() => {
|
|
@@ -166,37 +164,21 @@ export function Image(props) {
|
|
|
166
164
|
}, [onLoad]);
|
|
167
165
|
const [blurComplete, setBlurComplete] = useState(false);
|
|
168
166
|
const [showAltText, setShowAltText] = useState(false);
|
|
169
|
-
const config = useMemo(() => getImageConfig(), []);
|
|
170
167
|
const { props: imgAttributes, meta: imgMeta } = getImgProps(props, {
|
|
171
168
|
imgConf: config,
|
|
172
169
|
blurComplete,
|
|
173
170
|
showAltText,
|
|
174
171
|
});
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
if (!imgMeta.preload)
|
|
179
|
-
return;
|
|
172
|
+
if (imgMeta.preload) {
|
|
173
|
+
const { sizes, crossOrigin, referrerPolicy, fetchPriority } = imgAttributes;
|
|
180
174
|
ReactDOM.preload(imgAttributes.src, {
|
|
181
175
|
as: "image",
|
|
182
176
|
imageSrcSet: imgAttributes.srcSet,
|
|
183
177
|
imageSizes: sizes,
|
|
184
|
-
crossOrigin
|
|
185
|
-
referrerPolicy
|
|
186
|
-
|
|
187
|
-
? {
|
|
188
|
-
fetchPriority: fetchPriority,
|
|
189
|
-
}
|
|
190
|
-
: {}),
|
|
178
|
+
crossOrigin,
|
|
179
|
+
referrerPolicy,
|
|
180
|
+
fetchPriority,
|
|
191
181
|
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
imgAttributes.srcSet,
|
|
196
|
-
sizes,
|
|
197
|
-
crossOrigin,
|
|
198
|
-
referrerPolicy,
|
|
199
|
-
fetchPriority,
|
|
200
|
-
]);
|
|
201
|
-
return (_jsx(ImageElement, { ...imgAttributes, unoptimized: imgMeta.unoptimized, placeholder: imgMeta.placeholder, fill: imgMeta.fill, onLoadRef: onLoadRef, setBlurComplete: setBlurComplete, setShowAltText: setShowAltText, sizesInput: props.sizes }));
|
|
202
|
-
}
|
|
182
|
+
}
|
|
183
|
+
return (_jsx(ImageElement, { ...imgAttributes, unoptimized: imgMeta.unoptimized, placeholder: imgMeta.placeholder, fill: imgMeta.fill, onLoadRef: onLoadRef, setBlurComplete: setBlurComplete, setShowAltText: setShowAltText, sizesInput: props.sizes, forwardedRef: forwardedRef }));
|
|
184
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/components/link.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAO,MAAM,OAAO,CAAA;AAEvD,OAAO,EAKN,KAAK,aAAa,EAClB,MAAM,0BAA0B,CAAA;AAIjC,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,EAAE,aAAa;IACzF,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,+
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/components/link.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAO,MAAM,OAAO,CAAA;AAEvD,OAAO,EAKN,KAAK,aAAa,EAClB,MAAM,0BAA0B,CAAA;AAIjC,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,EAAE,aAAa;IACzF,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,+BA6GjF"}
|
package/dist/components/link.js
CHANGED
|
@@ -56,8 +56,12 @@ export function Link({ href, prefetch, scroll, onClick, ref, ...props }) {
|
|
|
56
56
|
}
|
|
57
57
|
return listenLinkViewport(link, onPrefetchStatic);
|
|
58
58
|
}, [router, prefetch]);
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
useOnCacheInvalidation((invalidation) => {
|
|
60
|
+
// Path invalidations already refresh active segments and links re-check on intent. Tags can
|
|
61
|
+
// affect any link's data, so only tags need this eager pass.
|
|
62
|
+
if (invalidation.tags.length > 0)
|
|
63
|
+
prefetchLink();
|
|
64
|
+
});
|
|
61
65
|
// The persistent observer only fires on intersection changes, so a link that stays in view across
|
|
62
66
|
// a navigation keeps a dropped shell otherwise.
|
|
63
67
|
useEffect(prefetchLink, [router, prefetch, pathname]);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ImageConfigComplete } from "./image-config.js";
|
|
2
|
+
type RemoteImageConfig = Pick<ImageConfigComplete, "remotePatterns" | "dangerouslyAllowLocalIP" | "maximumRedirects" | "maximumResponseBody">;
|
|
3
|
+
export type RemoteImageCacheControl = {
|
|
4
|
+
maxAge: number | undefined;
|
|
5
|
+
browserMaxAge: number | undefined;
|
|
6
|
+
sharedMaxAge: number | undefined;
|
|
7
|
+
noStore: boolean;
|
|
8
|
+
private: boolean;
|
|
9
|
+
noCache: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare const PUBLIC_IMAGE_CACHE_CONTROL: RemoteImageCacheControl;
|
|
12
|
+
export declare function fetchRemoteImage(href: string, config: RemoteImageConfig): Promise<{
|
|
13
|
+
buffer: Buffer;
|
|
14
|
+
cacheControl: RemoteImageCacheControl;
|
|
15
|
+
}>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=fetch-remote-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-remote-image.d.ts","sourceRoot":"","sources":["../../../src/lib/image-optimization/fetch-remote-image.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAS5D,KAAK,iBAAiB,GAAG,IAAI,CAC5B,mBAAmB,EACnB,gBAAgB,GAAG,yBAAyB,GAAG,kBAAkB,GAAG,qBAAqB,CACzF,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAE,uBAOxC,CAAA;AAwGD,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,GACvB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,uBAAuB,CAAA;CAAE,CAAC,CAiEpE"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { lookup } from "node:dns/promises";
|
|
2
|
+
import { request as httpRequest } from "node:http";
|
|
3
|
+
import { request as httpsRequest } from "node:https";
|
|
4
|
+
import { isIP } from "node:net";
|
|
5
|
+
import { ImageError, INVALID_UPSTREAM, NOT_ALLOWED, TIMED_OUT } from "./image-error.js";
|
|
6
|
+
import { isPrivateIp } from "./is-private-ip.js";
|
|
7
|
+
import { hasRemoteMatch } from "./match-patterns.js";
|
|
8
|
+
import { readBody } from "./read-body.js";
|
|
9
|
+
const TIMEOUT_MS = 7000;
|
|
10
|
+
const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
|
|
11
|
+
export const PUBLIC_IMAGE_CACHE_CONTROL = {
|
|
12
|
+
maxAge: undefined,
|
|
13
|
+
browserMaxAge: undefined,
|
|
14
|
+
sharedMaxAge: undefined,
|
|
15
|
+
noStore: false,
|
|
16
|
+
private: false,
|
|
17
|
+
noCache: false,
|
|
18
|
+
};
|
|
19
|
+
function parseCacheControl(cacheControl) {
|
|
20
|
+
let maxAge;
|
|
21
|
+
let sMaxAge;
|
|
22
|
+
let noStore = false;
|
|
23
|
+
let privateCache = false;
|
|
24
|
+
let noCache = false;
|
|
25
|
+
for (const directive of cacheControl?.split(",") ?? []) {
|
|
26
|
+
const [rawKey, rawValue] = directive.trim().split("=", 2);
|
|
27
|
+
if (!rawKey)
|
|
28
|
+
continue;
|
|
29
|
+
const key = rawKey.trim().toLowerCase();
|
|
30
|
+
const parsed = rawValue ? parseInt(rawValue.replace(/"/g, "").trim(), 10) : Number.NaN;
|
|
31
|
+
const validAge = !Number.isNaN(parsed);
|
|
32
|
+
if (key === "max-age" && validAge) {
|
|
33
|
+
maxAge = parsed;
|
|
34
|
+
}
|
|
35
|
+
else if (key === "s-maxage" && validAge) {
|
|
36
|
+
sMaxAge = parsed;
|
|
37
|
+
}
|
|
38
|
+
else if (key === "no-store") {
|
|
39
|
+
noStore = true;
|
|
40
|
+
}
|
|
41
|
+
else if (key === "private") {
|
|
42
|
+
privateCache = true;
|
|
43
|
+
}
|
|
44
|
+
else if (key === "no-cache") {
|
|
45
|
+
noCache = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
maxAge: sMaxAge ?? maxAge,
|
|
50
|
+
browserMaxAge: maxAge,
|
|
51
|
+
sharedMaxAge: sMaxAge,
|
|
52
|
+
noStore,
|
|
53
|
+
private: privateCache,
|
|
54
|
+
noCache,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function resolveAddresses(hostname) {
|
|
58
|
+
const literalFamily = isIP(hostname);
|
|
59
|
+
if (literalFamily) {
|
|
60
|
+
return [{ address: hostname, family: literalFamily }];
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return await lookup(hostname, { all: true });
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
throw new ImageError(400, INVALID_UPSTREAM);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Pin the connection to the addresses checked above so a second DNS lookup cannot rebind.
|
|
70
|
+
function createPinnedLookup(hostname, addresses) {
|
|
71
|
+
return (name, options, callback) => {
|
|
72
|
+
if (name !== hostname) {
|
|
73
|
+
const error = new Error(`Unexpected lookup for ${name}`);
|
|
74
|
+
error.code = "ENOTFOUND";
|
|
75
|
+
callback(error, [], 0);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const family = typeof options.family === "number" ? options.family : 0;
|
|
79
|
+
const matched = family ? addresses.filter((address) => address.family === family) : addresses;
|
|
80
|
+
if (matched.length === 0) {
|
|
81
|
+
const error = new Error(`No address available for ${hostname}`);
|
|
82
|
+
error.code = "ENOTFOUND";
|
|
83
|
+
callback(error, [], 0);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (options.all) {
|
|
87
|
+
callback(null, matched);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
callback(null, matched[0].address, matched[0].family);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function requestImage(url, hostname, addresses, signal) {
|
|
95
|
+
return new Promise((resolve, reject) => {
|
|
96
|
+
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
97
|
+
const req = request(url, {
|
|
98
|
+
lookup: isIP(hostname) ? undefined : createPinnedLookup(hostname, addresses),
|
|
99
|
+
signal,
|
|
100
|
+
headers: { accept: "*/*", "accept-encoding": "identity", "user-agent": "rebask" },
|
|
101
|
+
}, resolve);
|
|
102
|
+
req.on("error", reject);
|
|
103
|
+
req.end();
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
export async function fetchRemoteImage(href, config) {
|
|
107
|
+
let current = new URL(href);
|
|
108
|
+
for (let redirects = 0; redirects <= config.maximumRedirects; redirects++) {
|
|
109
|
+
if (!hasRemoteMatch(config.remotePatterns, current)) {
|
|
110
|
+
throw new ImageError(400, NOT_ALLOWED);
|
|
111
|
+
}
|
|
112
|
+
const hostname = current.hostname.replace(/^\[|\]$/g, "");
|
|
113
|
+
const addresses = await resolveAddresses(hostname);
|
|
114
|
+
if (!config.dangerouslyAllowLocalIP &&
|
|
115
|
+
addresses.some((address) => isPrivateIp(address.address))) {
|
|
116
|
+
throw new ImageError(400, NOT_ALLOWED);
|
|
117
|
+
}
|
|
118
|
+
const signal = AbortSignal.timeout(TIMEOUT_MS);
|
|
119
|
+
let response;
|
|
120
|
+
try {
|
|
121
|
+
response = await requestImage(current, hostname, addresses, signal);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
if (signal.aborted) {
|
|
125
|
+
throw new ImageError(504, TIMED_OUT);
|
|
126
|
+
}
|
|
127
|
+
throw new ImageError(400, INVALID_UPSTREAM);
|
|
128
|
+
}
|
|
129
|
+
const statusCode = response.statusCode ?? 0;
|
|
130
|
+
const location = response.headers.location;
|
|
131
|
+
if (REDIRECT_STATUSES.has(statusCode) && location) {
|
|
132
|
+
response.destroy();
|
|
133
|
+
if (redirects === config.maximumRedirects) {
|
|
134
|
+
throw new ImageError(508, INVALID_UPSTREAM);
|
|
135
|
+
}
|
|
136
|
+
let next;
|
|
137
|
+
try {
|
|
138
|
+
next = new URL(location, current);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
throw new ImageError(400, INVALID_UPSTREAM);
|
|
142
|
+
}
|
|
143
|
+
if (next.protocol !== "http:" && next.protocol !== "https:") {
|
|
144
|
+
throw new ImageError(400, NOT_ALLOWED);
|
|
145
|
+
}
|
|
146
|
+
current = next;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (statusCode < 200 || statusCode >= 300) {
|
|
150
|
+
response.destroy();
|
|
151
|
+
throw new ImageError(400, INVALID_UPSTREAM);
|
|
152
|
+
}
|
|
153
|
+
const buffer = await readBody(response, config.maximumResponseBody, signal);
|
|
154
|
+
return { buffer, cacheControl: parseCacheControl(response.headers["cache-control"]) };
|
|
155
|
+
}
|
|
156
|
+
throw new ImageError(508, INVALID_UPSTREAM);
|
|
157
|
+
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import type { CSSProperties, JSX } from "react";
|
|
2
|
-
import type { ImageConfigComplete, ImageLoaderProps } from "./image-config.js";
|
|
2
|
+
import type { ImageBlur, ImageConfigComplete, ImageLoaderProps } from "./image-config.js";
|
|
3
3
|
export interface StaticImageData {
|
|
4
4
|
src: string;
|
|
5
5
|
height: number;
|
|
6
6
|
width: number;
|
|
7
|
-
|
|
8
|
-
blurWidth?: number;
|
|
9
|
-
blurHeight?: number;
|
|
7
|
+
blur?: ImageBlur;
|
|
10
8
|
}
|
|
11
9
|
export interface StaticRequire {
|
|
12
10
|
default: StaticImageData;
|
|
@@ -44,7 +42,7 @@ export type PlaceholderStyle = Partial<Pick<CSSProperties, "backgroundSize" | "b
|
|
|
44
42
|
/**
|
|
45
43
|
* A shared function, used on both client and server, to generate the props for <img>.
|
|
46
44
|
*/
|
|
47
|
-
export declare function getImgProps({ src, sizes, unoptimized, preload, loading, className, quality, width, height, fill, style,
|
|
45
|
+
export declare function getImgProps({ src, sizes, unoptimized, preload, loading, className, quality, width, height, fill, style, loader: loaderProp, placeholder, blurDataURL, fetchPriority, decoding, ...rest }: ImageProps, _state: {
|
|
48
46
|
imgConf: ImageConfigComplete;
|
|
49
47
|
showAltText?: boolean;
|
|
50
48
|
blurComplete?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-img-props.d.ts","sourceRoot":"","sources":["../../../src/lib/image-optimization/get-img-props.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAE/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"get-img-props.d.ts","sourceRoot":"","sources":["../../../src/lib/image-optimization/get-img-props.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAE/C,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAKzF,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,eAAe,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG,IAAI,CAC5B,GAAG,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAC5B,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CACjE,GAAG;IACH,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,WAAW,CAAC,EAAE,gBAAgB,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,QAAQ,CAAC,GAAG;IAC3D,OAAO,EAAE,YAAY,CAAA;IACrB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IACzD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,GAAG,EAAE,MAAM,CAAA;CACX,CAAA;AAED,QAAA,MAAM,oBAAoB,YAAI,MAAM,EAAE,OAAO,YAAqB,CAAA;AAKlE,KAAK,YAAY,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAKzD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,gBAAgB,KAAK,MAAM,CAAA;AAEzD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,cAAc,MAAM,EAAE,CAAA;AACxE,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAA;AAS1E,MAAM,MAAM,gBAAgB,GAAG,OAAO,CACrC,IAAI,CACH,aAAa,EACb,gBAAgB,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,iBAAiB,CAChF,CACD,CAAA;AA2ED;;GAEG;AACH,wBAAgB,WAAW,CAC1B,EACC,GAAG,EACH,KAAK,EACL,WAAmB,EACnB,OAAe,EACf,OAAO,EACP,SAAS,EACT,OAAO,EACP,KAAK,EACL,MAAM,EACN,IAAY,EACZ,KAAK,EACL,MAAM,EAAE,UAAU,EAClB,WAAqB,EACrB,WAAW,EACX,aAAa,EACb,QAAkB,EAClB,GAAG,IAAI,EACP,EAAE,UAAU,EACb,MAAM,EAAE;IACP,OAAO,EAAE,mBAAmB,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,OAAO,CAAA;CACtB,GACC;IACF,KAAK,EAAE,QAAQ,CAAA;IACf,IAAI,EAAE;QACL,WAAW,EAAE,OAAO,CAAA;QACpB,OAAO,EAAE,OAAO,CAAA;QAChB,WAAW,EAAE,WAAW,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAA;QACnD,IAAI,EAAE,OAAO,CAAA;KACb,CAAA;CACD,CA+TA"}
|