@nonphoto/sanity-image 2.1.0 → 3.1.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/index.d.ts +92 -188
- package/dist/index.js +133 -111
- package/package.json +1 -4
- package/src/asset.ts +12 -0
- package/src/imageObject.ts +15 -0
- package/src/index.ts +7 -267
- package/src/metadata.ts +35 -0
- package/src/params.ts +118 -0
- package/src/reference.ts +12 -0
- package/src/stub.ts +44 -0
- package/src/url.ts +76 -0
- package/src/types.ts +0 -208
package/dist/index.d.ts
CHANGED
|
@@ -1,208 +1,112 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
interface SanityImageAssetLike {
|
|
2
|
+
_id: string;
|
|
3
|
+
}
|
|
4
|
+
declare function isSanityImageAssetLike(x: any): x is SanityImageAssetLike;
|
|
5
|
+
|
|
6
|
+
interface SanityReference {
|
|
7
|
+
_ref: string;
|
|
8
|
+
}
|
|
9
|
+
declare function isSanityReference(x: any): x is SanityReference;
|
|
10
|
+
|
|
11
|
+
interface SanityImageObject {
|
|
12
|
+
asset: SanityImageAssetLike | SanityReference;
|
|
13
|
+
}
|
|
14
|
+
declare function isSanityImageObject(x: any): x is SanityImageObject;
|
|
15
|
+
|
|
16
|
+
interface SanityImagePaletteSwatch {
|
|
17
|
+
_type?: "sanity.imagePaletteSwatch" | null;
|
|
18
|
+
background?: string | null;
|
|
19
|
+
foreground?: string | null;
|
|
20
|
+
population?: number | null;
|
|
21
|
+
title?: string | null;
|
|
22
|
+
}
|
|
23
|
+
interface SanityImagePalette {
|
|
24
|
+
_type?: "sanity.imagePalette" | null;
|
|
25
|
+
darkMuted?: SanityImagePaletteSwatch | null;
|
|
26
|
+
darkVibrant?: SanityImagePaletteSwatch | null;
|
|
27
|
+
dominant?: SanityImagePaletteSwatch | null;
|
|
28
|
+
lightMuted?: SanityImagePaletteSwatch | null;
|
|
29
|
+
lightVibrant?: SanityImagePaletteSwatch | null;
|
|
30
|
+
muted?: SanityImagePaletteSwatch | null;
|
|
31
|
+
vibrant?: SanityImagePaletteSwatch | null;
|
|
32
|
+
}
|
|
33
|
+
interface SanityImageDimensions {
|
|
34
|
+
_type?: "sanity.imageDimensions" | null;
|
|
35
|
+
aspectRatio?: number | null;
|
|
36
|
+
width?: number | null;
|
|
37
|
+
height?: number | null;
|
|
38
|
+
}
|
|
39
|
+
interface SanityImageMetadata {
|
|
40
|
+
_type: "sanity.imageMetadata";
|
|
41
|
+
blurHash?: string | null;
|
|
42
|
+
dimensions?: SanityImageDimensions | null;
|
|
43
|
+
hasAlpha?: boolean | null;
|
|
44
|
+
isOpaque?: boolean | null;
|
|
45
|
+
lqip?: string | null;
|
|
46
|
+
palette?: SanityImagePalette | null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type ImageFormat = "jpg" | "pjpg" | "png" | "webp";
|
|
50
|
+
type FitMode = "clip" | "crop" | "fill" | "fillmax" | "max" | "scale" | "min";
|
|
51
|
+
type CropMode = "top" | "bottom" | "left" | "right" | "center" | "focalpoint" | "entropy";
|
|
52
|
+
type AutoMode = "format";
|
|
53
|
+
type Orientation = 0 | 90 | 180 | 270;
|
|
54
|
+
type Dpr = 1 | 2 | 3;
|
|
55
|
+
type SanityImageParams = {
|
|
56
|
+
auto?: AutoMode;
|
|
57
|
+
background?: string;
|
|
58
|
+
blur?: number;
|
|
59
|
+
crop?: CropMode;
|
|
60
|
+
download?: boolean | string;
|
|
61
|
+
dpr?: Dpr;
|
|
62
|
+
fit?: FitMode;
|
|
63
|
+
flipHorizontal?: boolean;
|
|
64
|
+
flipVertical?: boolean;
|
|
8
65
|
focalPoint?: {
|
|
9
66
|
x: number;
|
|
10
67
|
y: number;
|
|
11
68
|
};
|
|
12
|
-
|
|
69
|
+
format?: ImageFormat;
|
|
70
|
+
frame?: number;
|
|
71
|
+
height?: number;
|
|
72
|
+
invert?: boolean;
|
|
13
73
|
maxHeight?: number;
|
|
14
|
-
|
|
74
|
+
maxWidth?: number;
|
|
15
75
|
minHeight?: number;
|
|
16
|
-
|
|
17
|
-
|
|
76
|
+
minWidth?: number;
|
|
77
|
+
orientation?: Orientation;
|
|
78
|
+
pad?: number;
|
|
79
|
+
quality?: number;
|
|
18
80
|
rect?: {
|
|
19
81
|
left: number;
|
|
20
82
|
top: number;
|
|
21
83
|
width: number;
|
|
22
84
|
height: number;
|
|
23
85
|
};
|
|
24
|
-
format?: ImageFormat;
|
|
25
|
-
invert?: boolean;
|
|
26
|
-
orientation?: Orientation;
|
|
27
|
-
quality?: number;
|
|
28
|
-
download?: boolean | string;
|
|
29
|
-
flipHorizontal?: boolean;
|
|
30
|
-
flipVertical?: boolean;
|
|
31
|
-
ignoreImageParams?: boolean;
|
|
32
|
-
fit?: FitMode;
|
|
33
|
-
crop?: CropMode;
|
|
34
86
|
saturation?: number;
|
|
35
|
-
|
|
36
|
-
pad?: number;
|
|
37
|
-
vanityName?: string;
|
|
38
|
-
frame?: number;
|
|
39
|
-
};
|
|
40
|
-
type ImageUrlBuilderOptionsWithAliases = ImageUrlBuilderOptions & {
|
|
41
|
-
w?: number;
|
|
42
|
-
h?: number;
|
|
43
|
-
q?: number;
|
|
44
|
-
fm?: number;
|
|
45
|
-
dl?: boolean | string;
|
|
46
|
-
or?: Orientation;
|
|
47
|
-
sharp?: number;
|
|
48
|
-
"min-h"?: number;
|
|
49
|
-
"max-h"?: number;
|
|
50
|
-
"min-w"?: number;
|
|
51
|
-
"max-w"?: number;
|
|
52
|
-
sat?: number;
|
|
53
|
-
[key: string]: any;
|
|
54
|
-
};
|
|
55
|
-
type ImageUrlBuilderOptionsWithAsset = ImageUrlBuilderOptions & {
|
|
56
|
-
asset: {
|
|
57
|
-
id: string;
|
|
58
|
-
width: number;
|
|
59
|
-
height: number;
|
|
60
|
-
format: string;
|
|
61
|
-
};
|
|
62
|
-
[key: string]: any;
|
|
63
|
-
};
|
|
64
|
-
type ImageFormat = "jpg" | "pjpg" | "png" | "webp";
|
|
65
|
-
type FitMode = "clip" | "crop" | "fill" | "fillmax" | "max" | "scale" | "min";
|
|
66
|
-
type CropMode = "top" | "bottom" | "left" | "right" | "center" | "focalpoint" | "entropy";
|
|
67
|
-
type AutoMode = "format";
|
|
68
|
-
type Orientation = 0 | 90 | 180 | 270;
|
|
69
|
-
interface SanityClientLike {
|
|
70
|
-
clientConfig: {
|
|
71
|
-
dataset?: string;
|
|
72
|
-
projectId?: string;
|
|
73
|
-
apiHost?: string;
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
type SanityModernClientLike = {
|
|
77
|
-
config(): {
|
|
78
|
-
dataset?: string;
|
|
79
|
-
projectId?: string;
|
|
80
|
-
apiHost?: string;
|
|
81
|
-
};
|
|
82
|
-
};
|
|
83
|
-
declare type SanityImageSource = string | SanityReference | SanityAsset | SanityImageObject | SanityImageWithAssetStub;
|
|
84
|
-
interface SanityProjectDetails {
|
|
85
|
-
baseUrl?: string;
|
|
86
|
-
projectId: string;
|
|
87
|
-
dataset: string;
|
|
88
|
-
}
|
|
89
|
-
interface SanityReference {
|
|
90
|
-
_ref: string;
|
|
91
|
-
}
|
|
92
|
-
interface SanityImageWithAssetStub {
|
|
93
|
-
asset: {
|
|
94
|
-
url: string;
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
interface SanityAsset {
|
|
98
|
-
_id?: string;
|
|
99
|
-
url?: string;
|
|
100
|
-
path?: string;
|
|
101
|
-
assetId?: string;
|
|
102
|
-
extension?: string;
|
|
103
|
-
[key: string]: any;
|
|
104
|
-
}
|
|
105
|
-
interface SanityImageDimensions {
|
|
106
|
-
aspectRatio: number;
|
|
107
|
-
height: number;
|
|
108
|
-
width: number;
|
|
109
|
-
}
|
|
110
|
-
interface SanityImageFitResult {
|
|
87
|
+
sharpen?: number;
|
|
111
88
|
width?: number;
|
|
112
|
-
height?: number;
|
|
113
|
-
rect: SanityImageRect;
|
|
114
|
-
}
|
|
115
|
-
interface SanityImageRect {
|
|
116
|
-
left: number;
|
|
117
|
-
top: number;
|
|
118
|
-
width: number;
|
|
119
|
-
height: number;
|
|
120
|
-
}
|
|
121
|
-
interface SanityImageCrop {
|
|
122
|
-
_type?: string;
|
|
123
|
-
left: number;
|
|
124
|
-
bottom: number;
|
|
125
|
-
right: number;
|
|
126
|
-
top: number;
|
|
127
|
-
}
|
|
128
|
-
interface SanityImageHotspot {
|
|
129
|
-
_type?: string;
|
|
130
|
-
width: number;
|
|
131
|
-
height: number;
|
|
132
|
-
x: number;
|
|
133
|
-
y: number;
|
|
134
|
-
}
|
|
135
|
-
interface SanityImageObject {
|
|
136
|
-
asset: SanityReference | SanityAsset;
|
|
137
|
-
crop?: SanityImageCrop;
|
|
138
|
-
hotspot?: SanityImageHotspot;
|
|
139
|
-
}
|
|
140
|
-
interface CropSpec {
|
|
141
|
-
left: number;
|
|
142
|
-
top: number;
|
|
143
|
-
width: number;
|
|
144
|
-
height: number;
|
|
145
|
-
}
|
|
146
|
-
interface HotspotSpec {
|
|
147
|
-
left: number;
|
|
148
|
-
top: number;
|
|
149
|
-
right: number;
|
|
150
|
-
bottom: number;
|
|
151
|
-
}
|
|
152
|
-
interface SanityImageObjectLike extends Pick<SanityImageObject, "asset"> {
|
|
153
|
-
[key: string]: any;
|
|
154
|
-
}
|
|
155
|
-
interface SanityImageMetadata {
|
|
156
|
-
lqip?: string;
|
|
157
|
-
dimensions?: SanityImageDimensions;
|
|
158
|
-
[key: string]: any;
|
|
159
|
-
}
|
|
160
|
-
interface Size {
|
|
161
|
-
width: number;
|
|
162
|
-
height: number;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
declare const defaultWidths: number[];
|
|
166
|
-
declare const defaultWidth = 1280;
|
|
167
|
-
declare const defaultQuality = 90;
|
|
168
|
-
declare const fitComparators: {
|
|
169
|
-
cover: (...values: number[]) => number;
|
|
170
|
-
contain: (...values: number[]) => number;
|
|
171
89
|
};
|
|
172
|
-
declare function
|
|
90
|
+
declare function sanityImageParamsToSearchParamEntries({ auto, background, blur, crop, download, dpr, fit, flipHorizontal, flipVertical, focalPoint, format, frame, height, invert, maxHeight, maxWidth, minHeight, minWidth, orientation, pad, quality, rect, saturation, sharpen, width, }: SanityImageParams): string[][];
|
|
91
|
+
|
|
92
|
+
type SanityImageSource = SanityImageObject | SanityReference | SanityImageAssetLike | string;
|
|
93
|
+
interface SanityImageAssetStub {
|
|
94
|
+
id: string;
|
|
173
95
|
width: number;
|
|
174
96
|
height: number;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
declare function isHotspot(x: unknown): x is SanityImageHotspot;
|
|
178
|
-
declare function isImageObjectLike(x: unknown): x is SanityImageObjectLike;
|
|
179
|
-
declare function isImageObject(x: unknown): x is SanityImageObject;
|
|
180
|
-
declare function isReference(x: unknown): x is SanityReference;
|
|
181
|
-
declare function isAsset(x: unknown): x is SanityAsset;
|
|
182
|
-
declare function isDimensions(x: unknown): x is SanityImageDimensions;
|
|
183
|
-
declare function isSize(x: unknown): x is Size;
|
|
184
|
-
declare function isMetadata(x: unknown): x is SanityImageMetadata;
|
|
185
|
-
interface ImageSrcOptions {
|
|
186
|
-
client: SanityClientLike | SanityProjectDetails | SanityModernClientLike;
|
|
187
|
-
source: SanityImageSource;
|
|
188
|
-
width: number;
|
|
189
|
-
quality?: number;
|
|
190
|
-
aspectRatio?: number;
|
|
97
|
+
format: string;
|
|
98
|
+
vanityName?: string;
|
|
191
99
|
}
|
|
192
|
-
declare function
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
100
|
+
declare function parseSanityImageAssetId(assetId: string): SanityImageAssetStub | undefined;
|
|
101
|
+
declare function sanityImageAssetId(source: SanityImageSource): string;
|
|
102
|
+
declare function sanityImageAssetStub(source: SanityImageSource): SanityImageAssetStub | undefined;
|
|
103
|
+
|
|
104
|
+
declare const defaultSrcsetWidths: number[];
|
|
105
|
+
interface SanityClientLike {
|
|
106
|
+
projectId: string;
|
|
107
|
+
dataset: string;
|
|
199
108
|
}
|
|
200
|
-
declare function
|
|
201
|
-
declare function
|
|
202
|
-
declare function croppedSize(intrinsicSize: Size, crop: SanityImageCrop): Size;
|
|
203
|
-
declare function aspectRatio(size: Size): number;
|
|
204
|
-
declare function imageMetadata(source: SanityImageSource): SanityImageMetadata | undefined;
|
|
205
|
-
declare function imageCroppedSize(source: SanityImageSource): Size | undefined;
|
|
206
|
-
declare function imageAspectRatio(source: SanityImageSource): number | undefined;
|
|
109
|
+
declare function sanityImageUrl(client: SanityClientLike, image: SanityImageAssetStub, params?: SanityImageParams): string;
|
|
110
|
+
declare function sanityImageSrcset(client: SanityClientLike, image: SanityImageAssetStub, params?: Omit<SanityImageParams, "width">, widths?: number[]): string;
|
|
207
111
|
|
|
208
|
-
export { type AutoMode, type CropMode, type
|
|
112
|
+
export { type AutoMode, type CropMode, type Dpr, type FitMode, type ImageFormat, type Orientation, type SanityClientLike, type SanityImageAssetLike, type SanityImageAssetStub, type SanityImageDimensions, type SanityImageMetadata, type SanityImageObject, type SanityImagePalette, type SanityImagePaletteSwatch, type SanityImageParams, type SanityImageSource, type SanityReference, defaultSrcsetWidths, isSanityImageAssetLike, isSanityImageObject, isSanityReference, parseSanityImageAssetId, sanityImageAssetId, sanityImageAssetStub, sanityImageParamsToSearchParamEntries, sanityImageSrcset, sanityImageUrl };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,98 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// src/asset.ts
|
|
2
|
+
function isSanityImageAssetLike(x) {
|
|
3
|
+
return x != null && typeof x === "object" && "_id" in x && typeof x._id === "string";
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// src/reference.ts
|
|
7
|
+
function isSanityReference(x) {
|
|
8
|
+
return x != null && typeof x === "object" && "_ref" in x && typeof x._ref === "string";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/imageObject.ts
|
|
12
|
+
function isSanityImageObject(x) {
|
|
13
|
+
return x != null && typeof x === "object" && "asset" in x && (isSanityImageAssetLike(x.asset) || isSanityReference(x.asset));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/params.ts
|
|
17
|
+
function sanityImageParamsToSearchParamEntries({
|
|
18
|
+
auto,
|
|
19
|
+
background,
|
|
20
|
+
blur,
|
|
21
|
+
crop,
|
|
22
|
+
download,
|
|
23
|
+
dpr,
|
|
24
|
+
fit,
|
|
25
|
+
flipHorizontal,
|
|
26
|
+
flipVertical,
|
|
27
|
+
focalPoint,
|
|
28
|
+
format,
|
|
29
|
+
frame,
|
|
30
|
+
height,
|
|
31
|
+
invert,
|
|
32
|
+
maxHeight,
|
|
33
|
+
maxWidth,
|
|
34
|
+
minHeight,
|
|
35
|
+
minWidth,
|
|
36
|
+
orientation,
|
|
37
|
+
pad,
|
|
38
|
+
quality,
|
|
39
|
+
rect,
|
|
40
|
+
saturation,
|
|
41
|
+
sharpen,
|
|
42
|
+
width
|
|
43
|
+
}) {
|
|
44
|
+
return Object.entries({
|
|
45
|
+
auto,
|
|
46
|
+
bg: background,
|
|
47
|
+
blur,
|
|
48
|
+
crop,
|
|
49
|
+
dl: download,
|
|
50
|
+
dpr,
|
|
51
|
+
fit,
|
|
52
|
+
flip: [flipHorizontal && "h", flipVertical && "v"].filter(Boolean).join(""),
|
|
53
|
+
fm: format,
|
|
54
|
+
"fp-x": focalPoint?.x,
|
|
55
|
+
"fp-y": focalPoint?.y,
|
|
56
|
+
frame,
|
|
57
|
+
h: height,
|
|
58
|
+
invert,
|
|
59
|
+
"max-h": maxHeight,
|
|
60
|
+
"max-w": maxWidth,
|
|
61
|
+
"min-h": minHeight,
|
|
62
|
+
"min-w": minWidth,
|
|
63
|
+
or: orientation,
|
|
64
|
+
pad,
|
|
65
|
+
q: quality,
|
|
66
|
+
rect: rect ? [rect.left, rect.top, rect.width, rect.height].map(Math.round).join(",") : void 0,
|
|
67
|
+
sat: saturation,
|
|
68
|
+
sharp: sharpen,
|
|
69
|
+
w: width
|
|
70
|
+
}).filter(([, value]) => typeof value === "number" || Boolean(value)).map(([key, value]) => [
|
|
71
|
+
key,
|
|
72
|
+
encodeURIComponent(
|
|
73
|
+
typeof value === "number" ? Math.round(value) : value
|
|
74
|
+
)
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/stub.ts
|
|
79
|
+
function parseSanityImageAssetId(assetId) {
|
|
80
|
+
const matches = assetId.match(/^image-(\w+)-(\d+)x(\d+)-(\w+)$/);
|
|
81
|
+
if (matches) {
|
|
82
|
+
const [, id, width, height, format] = matches;
|
|
83
|
+
return { id, width: Number(width), height: Number(height), format };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function sanityImageAssetId(source) {
|
|
87
|
+
return typeof source === "string" ? source : isSanityReference(source) ? source._ref : isSanityImageAssetLike(source) ? source._id : sanityImageAssetId(source.asset);
|
|
88
|
+
}
|
|
89
|
+
function sanityImageAssetStub(source) {
|
|
90
|
+
const id = sanityImageAssetId(source);
|
|
91
|
+
return id ? parseSanityImageAssetId(id) : void 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/url.ts
|
|
95
|
+
var defaultSrcsetWidths = [
|
|
4
96
|
6016,
|
|
5
97
|
// 6K
|
|
6
98
|
5120,
|
|
@@ -32,116 +124,46 @@ var defaultWidths = [
|
|
|
32
124
|
360,
|
|
33
125
|
240
|
|
34
126
|
];
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return x != null && typeof x === "object" && "_ref" in x && typeof x._ref === "string";
|
|
64
|
-
}
|
|
65
|
-
function isAsset(x) {
|
|
66
|
-
return x != null && typeof x === "object" && "_type" in x && x._type === "sanity.asset";
|
|
67
|
-
}
|
|
68
|
-
function isDimensions(x) {
|
|
69
|
-
return x != null && typeof x === "object" && "aspectRatio" in x && typeof x.aspectRatio === "number" && "width" in x && typeof x.width === "number" && "height" in x && typeof x.height === "number";
|
|
70
|
-
}
|
|
71
|
-
function isSize(x) {
|
|
72
|
-
return x != null && typeof x === "object" && "width" in x && typeof x.width === "number" && "height" in x && typeof x.height === "number";
|
|
73
|
-
}
|
|
74
|
-
function isMetadata(x) {
|
|
75
|
-
return x != null && typeof x === "object" && "lqip" in x && typeof x.lqip === "string" && "dimensions" in x && isDimensions(x.dimensions);
|
|
76
|
-
}
|
|
77
|
-
function imageSrc({
|
|
78
|
-
client,
|
|
79
|
-
source,
|
|
80
|
-
width,
|
|
81
|
-
quality = defaultQuality,
|
|
82
|
-
aspectRatio: aspectRatio2
|
|
83
|
-
}) {
|
|
84
|
-
const builder = imageUrlBuilder(client).image(source).quality(quality).auto("format").width(width);
|
|
85
|
-
return (aspectRatio2 ? builder.height(width * aspectRatio2) : builder).url();
|
|
86
|
-
}
|
|
87
|
-
function imageSrcset({
|
|
88
|
-
client,
|
|
89
|
-
source,
|
|
90
|
-
widths = defaultWidths,
|
|
91
|
-
quality = defaultQuality,
|
|
92
|
-
aspectRatio: aspectRatio2
|
|
93
|
-
}) {
|
|
94
|
-
const builder = imageUrlBuilder(client).image(source).quality(quality).auto("format");
|
|
95
|
-
return widths.sort((a, b) => a - b).map((width) => {
|
|
96
|
-
const url = (aspectRatio2 ? builder.height(width * aspectRatio2) : builder).width(width).url();
|
|
127
|
+
function sanityImageUrl(client, image, params) {
|
|
128
|
+
const url = new URL(
|
|
129
|
+
[
|
|
130
|
+
`https://cdn.sanity.io/images`,
|
|
131
|
+
client.projectId,
|
|
132
|
+
client.dataset,
|
|
133
|
+
`${image.id}-${image.width}x${image.height}.${image.format}`,
|
|
134
|
+
image.vanityName
|
|
135
|
+
].filter(Boolean).join("/")
|
|
136
|
+
);
|
|
137
|
+
if (params) {
|
|
138
|
+
url.search = new URLSearchParams(
|
|
139
|
+
sanityImageParamsToSearchParamEntries(params)
|
|
140
|
+
).toString();
|
|
141
|
+
}
|
|
142
|
+
return url.href;
|
|
143
|
+
}
|
|
144
|
+
function sanityImageSrcset(client, image, params, widths = defaultSrcsetWidths) {
|
|
145
|
+
const aspectRatio = image.height / image.width;
|
|
146
|
+
return [
|
|
147
|
+
...widths.sort((a, b) => a - b).filter((width) => width < image.width),
|
|
148
|
+
image.width
|
|
149
|
+
].map((width) => {
|
|
150
|
+
const url = sanityImageUrl(client, image, {
|
|
151
|
+
...params,
|
|
152
|
+
width,
|
|
153
|
+
height: width * aspectRatio
|
|
154
|
+
});
|
|
97
155
|
return `${url} ${width}w`;
|
|
98
156
|
}).join(",");
|
|
99
157
|
}
|
|
100
|
-
function imageAlt(source) {
|
|
101
|
-
return isImageObjectLike(source) && "alt" in source && typeof source.alt === "string" ? source.alt : void 0;
|
|
102
|
-
}
|
|
103
|
-
function croppedSize(intrinsicSize, crop) {
|
|
104
|
-
return {
|
|
105
|
-
width: intrinsicSize.width - crop.left - crop.right,
|
|
106
|
-
height: intrinsicSize.height - crop.top - crop.bottom
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
function aspectRatio(size) {
|
|
110
|
-
return size.height / size.width;
|
|
111
|
-
}
|
|
112
|
-
function imageMetadata(source) {
|
|
113
|
-
const asset = isImageObjectLike(source) ? source.asset : source;
|
|
114
|
-
return isAsset(asset) && isMetadata(asset.metadata) ? asset.metadata : void 0;
|
|
115
|
-
}
|
|
116
|
-
function imageCroppedSize(source) {
|
|
117
|
-
const metadata = imageMetadata(source);
|
|
118
|
-
return metadata?.dimensions ? isImageObject(source) && source.crop != null ? croppedSize(metadata.dimensions, source.crop) : metadata.dimensions : void 0;
|
|
119
|
-
}
|
|
120
|
-
function imageAspectRatio(source) {
|
|
121
|
-
const size = imageCroppedSize(source);
|
|
122
|
-
return size ? aspectRatio(size) : void 0;
|
|
123
|
-
}
|
|
124
158
|
export {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
imageMetadata,
|
|
136
|
-
imageSrc,
|
|
137
|
-
imageSrcset,
|
|
138
|
-
isAsset,
|
|
139
|
-
isCrop,
|
|
140
|
-
isDimensions,
|
|
141
|
-
isHotspot,
|
|
142
|
-
isImageObject,
|
|
143
|
-
isImageObjectLike,
|
|
144
|
-
isMetadata,
|
|
145
|
-
isReference,
|
|
146
|
-
isSize
|
|
159
|
+
defaultSrcsetWidths,
|
|
160
|
+
isSanityImageAssetLike,
|
|
161
|
+
isSanityImageObject,
|
|
162
|
+
isSanityReference,
|
|
163
|
+
parseSanityImageAssetId,
|
|
164
|
+
sanityImageAssetId,
|
|
165
|
+
sanityImageAssetStub,
|
|
166
|
+
sanityImageParamsToSearchParamEntries,
|
|
167
|
+
sanityImageSrcset,
|
|
168
|
+
sanityImageUrl
|
|
147
169
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nonphoto/sanity-image",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"author": "Jonas Luebbers <jonas@jonasluebbers.com> (https://www.jonasluebbers.com)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,9 +28,6 @@
|
|
|
28
28
|
"build": "tsup ./src/index.ts --dts --format esm --clean",
|
|
29
29
|
"release": "semantic-release"
|
|
30
30
|
},
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"@sanity/image-url": "^1.1.0"
|
|
33
|
-
},
|
|
34
31
|
"devDependencies": {
|
|
35
32
|
"semantic-release": "24.2.7",
|
|
36
33
|
"tsup": "8.5.0",
|
package/src/asset.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isSanityImageAssetLike, SanityImageAssetLike } from "./asset";
|
|
2
|
+
import { isSanityReference, SanityReference } from "./reference";
|
|
3
|
+
|
|
4
|
+
export interface SanityImageObject {
|
|
5
|
+
asset: SanityImageAssetLike | SanityReference;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isSanityImageObject(x: any): x is SanityImageObject {
|
|
9
|
+
return (
|
|
10
|
+
x != null &&
|
|
11
|
+
typeof x === "object" &&
|
|
12
|
+
"asset" in x &&
|
|
13
|
+
(isSanityImageAssetLike(x.asset) || isSanityReference(x.asset))
|
|
14
|
+
);
|
|
15
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,267 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
SanityImageMetadata,
|
|
9
|
-
SanityImageObject,
|
|
10
|
-
SanityImageObjectLike,
|
|
11
|
-
SanityImageSource,
|
|
12
|
-
SanityModernClientLike,
|
|
13
|
-
SanityProjectDetails,
|
|
14
|
-
SanityReference,
|
|
15
|
-
Size,
|
|
16
|
-
} from "./types";
|
|
17
|
-
|
|
18
|
-
export * from "./types";
|
|
19
|
-
|
|
20
|
-
export const defaultWidths = [
|
|
21
|
-
6016, // 6K
|
|
22
|
-
5120, // 5K
|
|
23
|
-
4480, // 4.5K
|
|
24
|
-
3840, // 4K
|
|
25
|
-
3200, // QHD+
|
|
26
|
-
2560, // WQXGA
|
|
27
|
-
2048, // QXGA
|
|
28
|
-
1920, // 1080p
|
|
29
|
-
1668, // iPad
|
|
30
|
-
1280, // 720p
|
|
31
|
-
1080, // iPhone 6-8 Plus
|
|
32
|
-
960,
|
|
33
|
-
720, // iPhone 6-8
|
|
34
|
-
640, // 480p
|
|
35
|
-
480,
|
|
36
|
-
360,
|
|
37
|
-
240,
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
export const defaultWidth = 1280;
|
|
41
|
-
|
|
42
|
-
export const defaultQuality = 90;
|
|
43
|
-
|
|
44
|
-
export const fitComparators = {
|
|
45
|
-
cover: Math.max,
|
|
46
|
-
contain: Math.min,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// TODO: impement comparators for every FitMode
|
|
50
|
-
export function fit(
|
|
51
|
-
containee: Size,
|
|
52
|
-
container: Size,
|
|
53
|
-
mode: keyof typeof fitComparators
|
|
54
|
-
) {
|
|
55
|
-
const sx = container.width / containee.width;
|
|
56
|
-
const sy = container.height / containee.height;
|
|
57
|
-
const s = fitComparators[mode](sx, sy);
|
|
58
|
-
return {
|
|
59
|
-
width: containee.width * s,
|
|
60
|
-
height: containee.height * s,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function isCrop(x: unknown): x is SanityImageCrop {
|
|
65
|
-
return (
|
|
66
|
-
x != null &&
|
|
67
|
-
typeof x == "object" &&
|
|
68
|
-
"top" in x &&
|
|
69
|
-
typeof x.top === "number" &&
|
|
70
|
-
"right" in x &&
|
|
71
|
-
typeof x.right === "number" &&
|
|
72
|
-
"bottom" in x &&
|
|
73
|
-
typeof x.bottom === "number" &&
|
|
74
|
-
"left" in x &&
|
|
75
|
-
typeof x.left === "number" &&
|
|
76
|
-
("_type" in x
|
|
77
|
-
? typeof x._type === "undefined" || typeof x._type === "string"
|
|
78
|
-
: true)
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function isHotspot(x: unknown): x is SanityImageHotspot {
|
|
83
|
-
return (
|
|
84
|
-
x != null &&
|
|
85
|
-
typeof x == "object" &&
|
|
86
|
-
"width" in x &&
|
|
87
|
-
typeof x.width === "number" &&
|
|
88
|
-
"height" in x &&
|
|
89
|
-
typeof x.height === "number" &&
|
|
90
|
-
"x" in x &&
|
|
91
|
-
typeof x.x === "number" &&
|
|
92
|
-
"y" in x &&
|
|
93
|
-
typeof x.y === "number" &&
|
|
94
|
-
("_type" in x
|
|
95
|
-
? typeof x._type === "undefined" || typeof x._type === "string"
|
|
96
|
-
: true)
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function isImageObjectLike(x: unknown): x is SanityImageObjectLike {
|
|
101
|
-
return (
|
|
102
|
-
x != null &&
|
|
103
|
-
typeof x === "object" &&
|
|
104
|
-
"asset" in x &&
|
|
105
|
-
(isAsset(x.asset) || isReference(x.asset))
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function isImageObject(x: unknown): x is SanityImageObject {
|
|
110
|
-
return (
|
|
111
|
-
isImageObjectLike(x) &&
|
|
112
|
-
("crop" in x ? typeof x.crop === "undefined" || isCrop(x.crop) : true) &&
|
|
113
|
-
("hotspot" in x
|
|
114
|
-
? typeof x.hotspot === "undefined" || isHotspot(x.hotspot)
|
|
115
|
-
: true)
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function isReference(x: unknown): x is SanityReference {
|
|
120
|
-
return (
|
|
121
|
-
x != null &&
|
|
122
|
-
typeof x === "object" &&
|
|
123
|
-
"_ref" in x &&
|
|
124
|
-
typeof x._ref === "string"
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function isAsset(x: unknown): x is SanityAsset {
|
|
129
|
-
return (
|
|
130
|
-
x != null &&
|
|
131
|
-
typeof x === "object" &&
|
|
132
|
-
"_type" in x &&
|
|
133
|
-
x._type === "sanity.asset"
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function isDimensions(x: unknown): x is SanityImageDimensions {
|
|
138
|
-
return (
|
|
139
|
-
x != null &&
|
|
140
|
-
typeof x === "object" &&
|
|
141
|
-
"aspectRatio" in x &&
|
|
142
|
-
typeof x.aspectRatio === "number" &&
|
|
143
|
-
"width" in x &&
|
|
144
|
-
typeof x.width === "number" &&
|
|
145
|
-
"height" in x &&
|
|
146
|
-
typeof x.height === "number"
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function isSize(x: unknown): x is Size {
|
|
151
|
-
return (
|
|
152
|
-
x != null &&
|
|
153
|
-
typeof x === "object" &&
|
|
154
|
-
"width" in x &&
|
|
155
|
-
typeof x.width === "number" &&
|
|
156
|
-
"height" in x &&
|
|
157
|
-
typeof x.height === "number"
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function isMetadata(x: unknown): x is SanityImageMetadata {
|
|
162
|
-
return (
|
|
163
|
-
x != null &&
|
|
164
|
-
typeof x === "object" &&
|
|
165
|
-
"lqip" in x &&
|
|
166
|
-
typeof x.lqip === "string" &&
|
|
167
|
-
"dimensions" in x &&
|
|
168
|
-
isDimensions(x.dimensions)
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export interface ImageSrcOptions {
|
|
173
|
-
client: SanityClientLike | SanityProjectDetails | SanityModernClientLike;
|
|
174
|
-
source: SanityImageSource;
|
|
175
|
-
width: number;
|
|
176
|
-
quality?: number;
|
|
177
|
-
aspectRatio?: number;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export function imageSrc({
|
|
181
|
-
client,
|
|
182
|
-
source,
|
|
183
|
-
width,
|
|
184
|
-
quality = defaultQuality,
|
|
185
|
-
aspectRatio,
|
|
186
|
-
}: ImageSrcOptions): string {
|
|
187
|
-
const builder = imageUrlBuilder(client)
|
|
188
|
-
.image(source)
|
|
189
|
-
.quality(quality)
|
|
190
|
-
.auto("format")
|
|
191
|
-
.width(width);
|
|
192
|
-
return (aspectRatio ? builder.height(width * aspectRatio) : builder).url();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export interface ImageSrcsetOptions {
|
|
196
|
-
client: SanityClientLike | SanityProjectDetails | SanityModernClientLike;
|
|
197
|
-
source: SanityImageSource;
|
|
198
|
-
widths?: number[];
|
|
199
|
-
quality?: number;
|
|
200
|
-
aspectRatio?: number;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export function imageSrcset({
|
|
204
|
-
client,
|
|
205
|
-
source,
|
|
206
|
-
widths = defaultWidths,
|
|
207
|
-
quality = defaultQuality,
|
|
208
|
-
aspectRatio,
|
|
209
|
-
}: ImageSrcsetOptions): string {
|
|
210
|
-
const builder = imageUrlBuilder(client)
|
|
211
|
-
.image(source)
|
|
212
|
-
.quality(quality)
|
|
213
|
-
.auto("format");
|
|
214
|
-
return widths
|
|
215
|
-
.sort((a, b) => a - b)
|
|
216
|
-
.map((width) => {
|
|
217
|
-
const url = (aspectRatio ? builder.height(width * aspectRatio) : builder)
|
|
218
|
-
.width(width)
|
|
219
|
-
.url();
|
|
220
|
-
return `${url} ${width}w`;
|
|
221
|
-
})
|
|
222
|
-
.join(",");
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export function imageAlt(source: SanityImageSource): string | undefined {
|
|
226
|
-
return isImageObjectLike(source) &&
|
|
227
|
-
"alt" in source &&
|
|
228
|
-
typeof source.alt === "string"
|
|
229
|
-
? source.alt
|
|
230
|
-
: undefined;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export function croppedSize(intrinsicSize: Size, crop: SanityImageCrop): Size {
|
|
234
|
-
return {
|
|
235
|
-
width: intrinsicSize.width - crop.left - crop.right,
|
|
236
|
-
height: intrinsicSize.height - crop.top - crop.bottom,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export function aspectRatio(size: Size): number {
|
|
241
|
-
return size.height / size.width;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export function imageMetadata(
|
|
245
|
-
source: SanityImageSource
|
|
246
|
-
): SanityImageMetadata | undefined {
|
|
247
|
-
const asset = isImageObjectLike(source) ? source.asset : source;
|
|
248
|
-
return isAsset(asset) && isMetadata(asset.metadata)
|
|
249
|
-
? asset.metadata
|
|
250
|
-
: undefined;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export function imageCroppedSize(source: SanityImageSource): Size | undefined {
|
|
254
|
-
const metadata = imageMetadata(source);
|
|
255
|
-
return metadata?.dimensions
|
|
256
|
-
? isImageObject(source) && source.crop != null
|
|
257
|
-
? croppedSize(metadata.dimensions, source.crop)
|
|
258
|
-
: metadata.dimensions
|
|
259
|
-
: undefined;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export function imageAspectRatio(
|
|
263
|
-
source: SanityImageSource
|
|
264
|
-
): number | undefined {
|
|
265
|
-
const size = imageCroppedSize(source);
|
|
266
|
-
return size ? aspectRatio(size) : undefined;
|
|
267
|
-
}
|
|
1
|
+
export * from "./asset";
|
|
2
|
+
export * from "./imageObject";
|
|
3
|
+
export * from "./metadata";
|
|
4
|
+
export * from "./params";
|
|
5
|
+
export * from "./reference";
|
|
6
|
+
export * from "./stub";
|
|
7
|
+
export * from "./url";
|
package/src/metadata.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface SanityImagePaletteSwatch {
|
|
2
|
+
_type?: "sanity.imagePaletteSwatch" | null;
|
|
3
|
+
background?: string | null;
|
|
4
|
+
foreground?: string | null;
|
|
5
|
+
population?: number | null;
|
|
6
|
+
title?: string | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface SanityImagePalette {
|
|
10
|
+
_type?: "sanity.imagePalette" | null;
|
|
11
|
+
darkMuted?: SanityImagePaletteSwatch | null;
|
|
12
|
+
darkVibrant?: SanityImagePaletteSwatch | null;
|
|
13
|
+
dominant?: SanityImagePaletteSwatch | null;
|
|
14
|
+
lightMuted?: SanityImagePaletteSwatch | null;
|
|
15
|
+
lightVibrant?: SanityImagePaletteSwatch | null;
|
|
16
|
+
muted?: SanityImagePaletteSwatch | null;
|
|
17
|
+
vibrant?: SanityImagePaletteSwatch | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SanityImageDimensions {
|
|
21
|
+
_type?: "sanity.imageDimensions" | null;
|
|
22
|
+
aspectRatio?: number | null;
|
|
23
|
+
width?: number | null;
|
|
24
|
+
height?: number | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface SanityImageMetadata {
|
|
28
|
+
_type: "sanity.imageMetadata";
|
|
29
|
+
blurHash?: string | null;
|
|
30
|
+
dimensions?: SanityImageDimensions | null;
|
|
31
|
+
hasAlpha?: boolean | null;
|
|
32
|
+
isOpaque?: boolean | null;
|
|
33
|
+
lqip?: string | null;
|
|
34
|
+
palette?: SanityImagePalette | null;
|
|
35
|
+
}
|
package/src/params.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export type ImageFormat = "jpg" | "pjpg" | "png" | "webp";
|
|
2
|
+
|
|
3
|
+
export type FitMode =
|
|
4
|
+
| "clip"
|
|
5
|
+
| "crop"
|
|
6
|
+
| "fill"
|
|
7
|
+
| "fillmax"
|
|
8
|
+
| "max"
|
|
9
|
+
| "scale"
|
|
10
|
+
| "min";
|
|
11
|
+
|
|
12
|
+
export type CropMode =
|
|
13
|
+
| "top"
|
|
14
|
+
| "bottom"
|
|
15
|
+
| "left"
|
|
16
|
+
| "right"
|
|
17
|
+
| "center"
|
|
18
|
+
| "focalpoint"
|
|
19
|
+
| "entropy";
|
|
20
|
+
|
|
21
|
+
export type AutoMode = "format";
|
|
22
|
+
|
|
23
|
+
export type Orientation = 0 | 90 | 180 | 270;
|
|
24
|
+
|
|
25
|
+
export type Dpr = 1 | 2 | 3;
|
|
26
|
+
|
|
27
|
+
export type SanityImageParams = {
|
|
28
|
+
auto?: AutoMode;
|
|
29
|
+
background?: string;
|
|
30
|
+
blur?: number;
|
|
31
|
+
crop?: CropMode;
|
|
32
|
+
download?: boolean | string;
|
|
33
|
+
dpr?: Dpr;
|
|
34
|
+
fit?: FitMode;
|
|
35
|
+
flipHorizontal?: boolean;
|
|
36
|
+
flipVertical?: boolean;
|
|
37
|
+
focalPoint?: { x: number; y: number };
|
|
38
|
+
format?: ImageFormat;
|
|
39
|
+
frame?: number;
|
|
40
|
+
height?: number;
|
|
41
|
+
invert?: boolean;
|
|
42
|
+
maxHeight?: number;
|
|
43
|
+
maxWidth?: number;
|
|
44
|
+
minHeight?: number;
|
|
45
|
+
minWidth?: number;
|
|
46
|
+
orientation?: Orientation;
|
|
47
|
+
pad?: number;
|
|
48
|
+
quality?: number;
|
|
49
|
+
rect?: { left: number; top: number; width: number; height: number };
|
|
50
|
+
saturation?: number;
|
|
51
|
+
sharpen?: number;
|
|
52
|
+
width?: number;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function sanityImageParamsToSearchParamEntries({
|
|
56
|
+
auto,
|
|
57
|
+
background,
|
|
58
|
+
blur,
|
|
59
|
+
crop,
|
|
60
|
+
download,
|
|
61
|
+
dpr,
|
|
62
|
+
fit,
|
|
63
|
+
flipHorizontal,
|
|
64
|
+
flipVertical,
|
|
65
|
+
focalPoint,
|
|
66
|
+
format,
|
|
67
|
+
frame,
|
|
68
|
+
height,
|
|
69
|
+
invert,
|
|
70
|
+
maxHeight,
|
|
71
|
+
maxWidth,
|
|
72
|
+
minHeight,
|
|
73
|
+
minWidth,
|
|
74
|
+
orientation,
|
|
75
|
+
pad,
|
|
76
|
+
quality,
|
|
77
|
+
rect,
|
|
78
|
+
saturation,
|
|
79
|
+
sharpen,
|
|
80
|
+
width,
|
|
81
|
+
}: SanityImageParams): string[][] {
|
|
82
|
+
return Object.entries({
|
|
83
|
+
auto,
|
|
84
|
+
bg: background,
|
|
85
|
+
blur,
|
|
86
|
+
crop,
|
|
87
|
+
dl: download,
|
|
88
|
+
dpr,
|
|
89
|
+
fit,
|
|
90
|
+
flip: [flipHorizontal && "h", flipVertical && "v"].filter(Boolean).join(""),
|
|
91
|
+
fm: format,
|
|
92
|
+
"fp-x": focalPoint?.x,
|
|
93
|
+
"fp-y": focalPoint?.y,
|
|
94
|
+
frame,
|
|
95
|
+
h: height,
|
|
96
|
+
invert,
|
|
97
|
+
"max-h": maxHeight,
|
|
98
|
+
"max-w": maxWidth,
|
|
99
|
+
"min-h": minHeight,
|
|
100
|
+
"min-w": minWidth,
|
|
101
|
+
or: orientation,
|
|
102
|
+
pad,
|
|
103
|
+
q: quality,
|
|
104
|
+
rect: rect
|
|
105
|
+
? [rect.left, rect.top, rect.width, rect.height].map(Math.round).join(",")
|
|
106
|
+
: undefined,
|
|
107
|
+
sat: saturation,
|
|
108
|
+
sharp: sharpen,
|
|
109
|
+
w: width,
|
|
110
|
+
})
|
|
111
|
+
.filter(([, value]) => typeof value === "number" || Boolean(value))
|
|
112
|
+
.map(([key, value]) => [
|
|
113
|
+
key,
|
|
114
|
+
encodeURIComponent(
|
|
115
|
+
typeof value === "number" ? Math.round(value) : (value as string)
|
|
116
|
+
),
|
|
117
|
+
]);
|
|
118
|
+
}
|
package/src/reference.ts
ADDED
package/src/stub.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { isSanityImageAssetLike, SanityImageAssetLike } from "./asset";
|
|
2
|
+
import { SanityImageObject } from "./imageObject";
|
|
3
|
+
import { isSanityReference, SanityReference } from "./reference";
|
|
4
|
+
|
|
5
|
+
export type SanityImageSource =
|
|
6
|
+
| SanityImageObject
|
|
7
|
+
| SanityReference
|
|
8
|
+
| SanityImageAssetLike
|
|
9
|
+
| string;
|
|
10
|
+
|
|
11
|
+
export interface SanityImageAssetStub {
|
|
12
|
+
id: string;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
format: string;
|
|
16
|
+
vanityName?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function parseSanityImageAssetId(
|
|
20
|
+
assetId: string
|
|
21
|
+
): SanityImageAssetStub | undefined {
|
|
22
|
+
const matches = assetId.match(/^image-(\w+)-(\d+)x(\d+)-(\w+)$/);
|
|
23
|
+
if (matches) {
|
|
24
|
+
const [, id, width, height, format] = matches;
|
|
25
|
+
return { id, width: Number(width), height: Number(height), format };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function sanityImageAssetId(source: SanityImageSource): string {
|
|
30
|
+
return typeof source === "string"
|
|
31
|
+
? source
|
|
32
|
+
: isSanityReference(source)
|
|
33
|
+
? source._ref
|
|
34
|
+
: isSanityImageAssetLike(source)
|
|
35
|
+
? source._id
|
|
36
|
+
: sanityImageAssetId(source.asset);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function sanityImageAssetStub(
|
|
40
|
+
source: SanityImageSource
|
|
41
|
+
): SanityImageAssetStub | undefined {
|
|
42
|
+
const id = sanityImageAssetId(source);
|
|
43
|
+
return id ? parseSanityImageAssetId(id) : undefined;
|
|
44
|
+
}
|
package/src/url.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SanityImageParams,
|
|
3
|
+
sanityImageParamsToSearchParamEntries,
|
|
4
|
+
} from "./params";
|
|
5
|
+
import { SanityImageAssetStub } from "./stub";
|
|
6
|
+
|
|
7
|
+
export const defaultSrcsetWidths = [
|
|
8
|
+
6016, // 6K
|
|
9
|
+
5120, // 5K
|
|
10
|
+
4480, // 4.5K
|
|
11
|
+
3840, // 4K
|
|
12
|
+
3200, // QHD+
|
|
13
|
+
2560, // WQXGA
|
|
14
|
+
2048, // QXGA
|
|
15
|
+
1920, // 1080p
|
|
16
|
+
1668, // iPad
|
|
17
|
+
1280, // 720p
|
|
18
|
+
1080, // iPhone 6-8 Plus
|
|
19
|
+
960,
|
|
20
|
+
720, // iPhone 6-8
|
|
21
|
+
640, // 480p
|
|
22
|
+
480,
|
|
23
|
+
360,
|
|
24
|
+
240,
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export interface SanityClientLike {
|
|
28
|
+
projectId: string;
|
|
29
|
+
dataset: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function sanityImageUrl(
|
|
33
|
+
client: SanityClientLike,
|
|
34
|
+
image: SanityImageAssetStub,
|
|
35
|
+
params?: SanityImageParams
|
|
36
|
+
): string {
|
|
37
|
+
const url = new URL(
|
|
38
|
+
[
|
|
39
|
+
`https://cdn.sanity.io/images`,
|
|
40
|
+
client.projectId,
|
|
41
|
+
client.dataset,
|
|
42
|
+
`${image.id}-${image.width}x${image.height}.${image.format}`,
|
|
43
|
+
image.vanityName,
|
|
44
|
+
]
|
|
45
|
+
.filter(Boolean)
|
|
46
|
+
.join("/")
|
|
47
|
+
);
|
|
48
|
+
if (params) {
|
|
49
|
+
url.search = new URLSearchParams(
|
|
50
|
+
sanityImageParamsToSearchParamEntries(params)
|
|
51
|
+
).toString();
|
|
52
|
+
}
|
|
53
|
+
return url.href;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function sanityImageSrcset(
|
|
57
|
+
client: SanityClientLike,
|
|
58
|
+
image: SanityImageAssetStub,
|
|
59
|
+
params?: Omit<SanityImageParams, "width">,
|
|
60
|
+
widths: number[] = defaultSrcsetWidths
|
|
61
|
+
): string {
|
|
62
|
+
const aspectRatio = image.height / image.width;
|
|
63
|
+
return [
|
|
64
|
+
...widths.sort((a, b) => a - b).filter((width) => width < image.width),
|
|
65
|
+
image.width,
|
|
66
|
+
]
|
|
67
|
+
.map((width) => {
|
|
68
|
+
const url = sanityImageUrl(client, image, {
|
|
69
|
+
...params,
|
|
70
|
+
width,
|
|
71
|
+
height: width * aspectRatio,
|
|
72
|
+
});
|
|
73
|
+
return `${url} ${width}w`;
|
|
74
|
+
})
|
|
75
|
+
.join(",");
|
|
76
|
+
}
|
package/src/types.ts
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
export type ImageUrlBuilderOptions = Partial<SanityProjectDetails> & {
|
|
2
|
-
baseUrl?: string;
|
|
3
|
-
source?: SanityImageSource;
|
|
4
|
-
bg?: string;
|
|
5
|
-
dpr?: number;
|
|
6
|
-
width?: number;
|
|
7
|
-
height?: number;
|
|
8
|
-
focalPoint?: {
|
|
9
|
-
x: number;
|
|
10
|
-
y: number;
|
|
11
|
-
};
|
|
12
|
-
maxWidth?: number;
|
|
13
|
-
maxHeight?: number;
|
|
14
|
-
minWidth?: number;
|
|
15
|
-
minHeight?: number;
|
|
16
|
-
blur?: number;
|
|
17
|
-
sharpen?: number;
|
|
18
|
-
rect?: {
|
|
19
|
-
left: number;
|
|
20
|
-
top: number;
|
|
21
|
-
width: number;
|
|
22
|
-
height: number;
|
|
23
|
-
};
|
|
24
|
-
format?: ImageFormat;
|
|
25
|
-
invert?: boolean;
|
|
26
|
-
orientation?: Orientation;
|
|
27
|
-
quality?: number;
|
|
28
|
-
download?: boolean | string;
|
|
29
|
-
flipHorizontal?: boolean;
|
|
30
|
-
flipVertical?: boolean;
|
|
31
|
-
ignoreImageParams?: boolean;
|
|
32
|
-
fit?: FitMode;
|
|
33
|
-
crop?: CropMode;
|
|
34
|
-
saturation?: number;
|
|
35
|
-
auto?: AutoMode;
|
|
36
|
-
pad?: number;
|
|
37
|
-
vanityName?: string;
|
|
38
|
-
frame?: number;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type ImageUrlBuilderOptionsWithAliases = ImageUrlBuilderOptions & {
|
|
42
|
-
w?: number;
|
|
43
|
-
h?: number;
|
|
44
|
-
q?: number;
|
|
45
|
-
fm?: number;
|
|
46
|
-
dl?: boolean | string;
|
|
47
|
-
or?: Orientation;
|
|
48
|
-
sharp?: number;
|
|
49
|
-
"min-h"?: number;
|
|
50
|
-
"max-h"?: number;
|
|
51
|
-
"min-w"?: number;
|
|
52
|
-
"max-w"?: number;
|
|
53
|
-
sat?: number;
|
|
54
|
-
[key: string]: any;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export type ImageUrlBuilderOptionsWithAsset = ImageUrlBuilderOptions & {
|
|
58
|
-
asset: {
|
|
59
|
-
id: string;
|
|
60
|
-
width: number;
|
|
61
|
-
height: number;
|
|
62
|
-
format: string;
|
|
63
|
-
};
|
|
64
|
-
[key: string]: any;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export type ImageFormat = "jpg" | "pjpg" | "png" | "webp";
|
|
68
|
-
|
|
69
|
-
export type FitMode =
|
|
70
|
-
| "clip"
|
|
71
|
-
| "crop"
|
|
72
|
-
| "fill"
|
|
73
|
-
| "fillmax"
|
|
74
|
-
| "max"
|
|
75
|
-
| "scale"
|
|
76
|
-
| "min";
|
|
77
|
-
|
|
78
|
-
export type CropMode =
|
|
79
|
-
| "top"
|
|
80
|
-
| "bottom"
|
|
81
|
-
| "left"
|
|
82
|
-
| "right"
|
|
83
|
-
| "center"
|
|
84
|
-
| "focalpoint"
|
|
85
|
-
| "entropy";
|
|
86
|
-
|
|
87
|
-
export type AutoMode = "format";
|
|
88
|
-
|
|
89
|
-
export type Orientation = 0 | 90 | 180 | 270;
|
|
90
|
-
|
|
91
|
-
export interface SanityClientLike {
|
|
92
|
-
clientConfig: {
|
|
93
|
-
dataset?: string;
|
|
94
|
-
projectId?: string;
|
|
95
|
-
apiHost?: string;
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export type SanityModernClientLike = {
|
|
100
|
-
config(): {
|
|
101
|
-
dataset?: string;
|
|
102
|
-
projectId?: string;
|
|
103
|
-
apiHost?: string;
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
export declare type SanityImageSource =
|
|
108
|
-
| string
|
|
109
|
-
| SanityReference
|
|
110
|
-
| SanityAsset
|
|
111
|
-
| SanityImageObject
|
|
112
|
-
| SanityImageWithAssetStub;
|
|
113
|
-
|
|
114
|
-
export interface SanityProjectDetails {
|
|
115
|
-
baseUrl?: string;
|
|
116
|
-
projectId: string;
|
|
117
|
-
dataset: string;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface SanityReference {
|
|
121
|
-
_ref: string;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export interface SanityImageWithAssetStub {
|
|
125
|
-
asset: {
|
|
126
|
-
url: string;
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface SanityAsset {
|
|
131
|
-
_id?: string;
|
|
132
|
-
url?: string;
|
|
133
|
-
path?: string;
|
|
134
|
-
assetId?: string;
|
|
135
|
-
extension?: string;
|
|
136
|
-
[key: string]: any;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export interface SanityImageDimensions {
|
|
140
|
-
aspectRatio: number;
|
|
141
|
-
height: number;
|
|
142
|
-
width: number;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export interface SanityImageFitResult {
|
|
146
|
-
width?: number;
|
|
147
|
-
height?: number;
|
|
148
|
-
rect: SanityImageRect;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export interface SanityImageRect {
|
|
152
|
-
left: number;
|
|
153
|
-
top: number;
|
|
154
|
-
width: number;
|
|
155
|
-
height: number;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export interface SanityImageCrop {
|
|
159
|
-
_type?: string;
|
|
160
|
-
left: number;
|
|
161
|
-
bottom: number;
|
|
162
|
-
right: number;
|
|
163
|
-
top: number;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export interface SanityImageHotspot {
|
|
167
|
-
_type?: string;
|
|
168
|
-
width: number;
|
|
169
|
-
height: number;
|
|
170
|
-
x: number;
|
|
171
|
-
y: number;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export interface SanityImageObject {
|
|
175
|
-
asset: SanityReference | SanityAsset;
|
|
176
|
-
crop?: SanityImageCrop;
|
|
177
|
-
hotspot?: SanityImageHotspot;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export interface CropSpec {
|
|
181
|
-
left: number;
|
|
182
|
-
top: number;
|
|
183
|
-
width: number;
|
|
184
|
-
height: number;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export interface HotspotSpec {
|
|
188
|
-
left: number;
|
|
189
|
-
top: number;
|
|
190
|
-
right: number;
|
|
191
|
-
bottom: number;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export interface SanityImageObjectLike
|
|
195
|
-
extends Pick<SanityImageObject, "asset"> {
|
|
196
|
-
[key: string]: any;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export interface SanityImageMetadata {
|
|
200
|
-
lqip?: string;
|
|
201
|
-
dimensions?: SanityImageDimensions;
|
|
202
|
-
[key: string]: any;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export interface Size {
|
|
206
|
-
width: number;
|
|
207
|
-
height: number;
|
|
208
|
-
}
|