@nonphoto/sanity-image 1.0.1 → 2.0.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 +42 -15
- package/dist/index.js +88 -34
- package/package.json +5 -5
- package/src/index.ts +189 -67
package/dist/index.d.ts
CHANGED
|
@@ -1,31 +1,58 @@
|
|
|
1
|
-
import { SanityImageDimensions, SanityClientLike, SanityProjectDetails, SanityModernClientLike, SanityImageSource } from '@sanity/image-url/lib/types/types.js';
|
|
1
|
+
import { SanityImageObject, SanityImageDimensions, SanityImageCrop, SanityImageHotspot, SanityReference, SanityAsset, SanityClientLike, SanityProjectDetails, SanityModernClientLike, SanityImageSource } from '@sanity/image-url/lib/types/types.js';
|
|
2
2
|
|
|
3
|
-
interface
|
|
3
|
+
interface SanityImageObjectLike extends Pick<SanityImageObject, "asset"> {
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
}
|
|
6
|
+
interface SanityImageMetadata {
|
|
4
7
|
lqip?: string;
|
|
5
8
|
dimensions?: SanityImageDimensions;
|
|
9
|
+
[key: string]: any;
|
|
6
10
|
}
|
|
7
11
|
interface Size {
|
|
8
12
|
width: number;
|
|
9
13
|
height: number;
|
|
10
14
|
}
|
|
11
15
|
declare const defaultWidths: number[];
|
|
12
|
-
declare const
|
|
13
|
-
declare const defaultMetaImageWidth = 1200;
|
|
16
|
+
declare const defaultWidth = 1280;
|
|
14
17
|
declare const defaultQuality = 90;
|
|
15
|
-
|
|
18
|
+
declare const fitComparators: {
|
|
19
|
+
cover: (...values: number[]) => number;
|
|
20
|
+
contain: (...values: number[]) => number;
|
|
21
|
+
};
|
|
22
|
+
declare function fit(containee: Size, container: Size, mode: keyof typeof fitComparators): {
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
};
|
|
26
|
+
declare function isCrop(x: unknown): x is SanityImageCrop;
|
|
27
|
+
declare function isHotspot(x: unknown): x is SanityImageHotspot;
|
|
28
|
+
declare function isImageObjectLike(x: unknown): x is SanityImageObjectLike;
|
|
29
|
+
declare function isImageObject(x: unknown): x is SanityImageObject;
|
|
30
|
+
declare function isReference(x: unknown): x is SanityReference;
|
|
31
|
+
declare function isAsset(x: unknown): x is SanityAsset;
|
|
32
|
+
declare function isDimensions(x: unknown): x is SanityImageDimensions;
|
|
33
|
+
declare function isSize(x: unknown): x is Size;
|
|
34
|
+
declare function isMetadata(x: unknown): x is SanityImageMetadata;
|
|
35
|
+
interface ImageSrcOptions {
|
|
16
36
|
client: SanityClientLike | SanityProjectDetails | SanityModernClientLike;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
widths?: number[];
|
|
37
|
+
source: SanityImageSource;
|
|
38
|
+
width: number;
|
|
20
39
|
quality?: number;
|
|
21
40
|
aspectRatio?: number;
|
|
22
41
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
declare function imageSrc({ client, source, width, quality, aspectRatio, }: ImageSrcOptions): string;
|
|
43
|
+
interface ImageSrcsetOptions {
|
|
44
|
+
client: SanityClientLike | SanityProjectDetails | SanityModernClientLike;
|
|
45
|
+
source: SanityImageSource;
|
|
46
|
+
widths?: number[];
|
|
47
|
+
quality?: number;
|
|
48
|
+
aspectRatio?: number;
|
|
28
49
|
}
|
|
29
|
-
declare function
|
|
50
|
+
declare function imageSrcset({ client, source, widths, quality, aspectRatio, }: ImageSrcsetOptions): string;
|
|
51
|
+
declare function imageAlt(source: SanityImageSource): string | undefined;
|
|
52
|
+
declare function croppedSize(intrinsicSize: Size, crop: SanityImageCrop): Size;
|
|
53
|
+
declare function aspectRatio(size: Size): number;
|
|
54
|
+
declare function imageMetadata(source: SanityImageSource): SanityImageMetadata | undefined;
|
|
55
|
+
declare function imageCroppedSize(source: SanityImageSource): Size | undefined;
|
|
56
|
+
declare function imageAspectRatio(source: SanityImageSource): number | undefined;
|
|
30
57
|
|
|
31
|
-
export { type
|
|
58
|
+
export { type ImageSrcOptions, type ImageSrcsetOptions, type SanityImageMetadata, type SanityImageObjectLike, type Size, aspectRatio, croppedSize, defaultQuality, defaultWidth, defaultWidths, fit, fitComparators, imageAlt, imageAspectRatio, imageCroppedSize, imageMetadata, imageSrc, imageSrcset, isAsset, isCrop, isDimensions, isHotspot, isImageObject, isImageObjectLike, isMetadata, isReference, isSize };
|
package/dist/index.js
CHANGED
|
@@ -32,13 +32,11 @@ var defaultWidths = [
|
|
|
32
32
|
360,
|
|
33
33
|
240
|
|
34
34
|
];
|
|
35
|
-
var
|
|
36
|
-
var defaultMetaImageWidth = 1200;
|
|
35
|
+
var defaultWidth = 1280;
|
|
37
36
|
var defaultQuality = 90;
|
|
38
37
|
var fitComparators = {
|
|
39
38
|
cover: Math.max,
|
|
40
|
-
contain: Math.min
|
|
41
|
-
mean: (a, b) => (a + b) / 2
|
|
39
|
+
contain: Math.min
|
|
42
40
|
};
|
|
43
41
|
function fit(containee, container, mode) {
|
|
44
42
|
const sx = container.width / containee.width;
|
|
@@ -49,45 +47,101 @@ function fit(containee, container, mode) {
|
|
|
49
47
|
height: containee.height * s
|
|
50
48
|
};
|
|
51
49
|
}
|
|
52
|
-
function buildAspectRatio(builder, width, aspectRatio) {
|
|
53
|
-
if (aspectRatio) {
|
|
54
|
-
return builder.width(width).height(Math.round(width * aspectRatio));
|
|
55
|
-
} else {
|
|
56
|
-
return builder.width(width);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
50
|
function isCrop(x) {
|
|
60
|
-
return x && typeof x == "object" && "top" in x && typeof x.top === "number" && "right" in x && typeof x.right === "number" && "bottom" in x && typeof x.bottom === "number" && "left" in x && typeof x.left === "number";
|
|
51
|
+
return x != null && typeof x == "object" && "top" in x && typeof x.top === "number" && "right" in x && typeof x.right === "number" && "bottom" in x && typeof x.bottom === "number" && "left" in x && typeof x.left === "number" && ("_type" in x ? typeof x._type === "undefined" || typeof x._type === "string" : true);
|
|
52
|
+
}
|
|
53
|
+
function isHotspot(x) {
|
|
54
|
+
return x != null && typeof x == "object" && "width" in x && typeof x.width === "number" && "height" in x && typeof x.height === "number" && "x" in x && typeof x.x === "number" && "y" in x && typeof x.y === "number" && ("_type" in x ? typeof x._type === "undefined" || typeof x._type === "string" : true);
|
|
55
|
+
}
|
|
56
|
+
function isImageObjectLike(x) {
|
|
57
|
+
return x != null && typeof x === "object" && "asset" in x && (isAsset(x) || isReference(x));
|
|
58
|
+
}
|
|
59
|
+
function isImageObject(x) {
|
|
60
|
+
return isImageObjectLike(x) && ("crop" in x ? typeof x.crop === "undefined" || isCrop(x.crop) : true) && ("hotspot" in x ? typeof x.hotspot === "undefined" || isHotspot(x.hotspot) : true);
|
|
61
|
+
}
|
|
62
|
+
function isReference(x) {
|
|
63
|
+
return x != null && typeof x === "object" && "_ref" in x && typeof x._ref === "string";
|
|
61
64
|
}
|
|
62
|
-
function
|
|
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({
|
|
63
78
|
client,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
widths,
|
|
79
|
+
source,
|
|
80
|
+
width,
|
|
67
81
|
quality = defaultQuality,
|
|
68
|
-
aspectRatio
|
|
82
|
+
aspectRatio: aspectRatio2
|
|
69
83
|
}) {
|
|
70
|
-
const builder = imageUrlBuilder(client).image(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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();
|
|
97
|
+
return `${url} ${width}w`;
|
|
98
|
+
}).join(",");
|
|
99
|
+
}
|
|
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) {
|
|
78
104
|
return {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
(width) => `${buildAspectRatio(builder, width, aspectRatio).url()} ${width}w`
|
|
82
|
-
).join(",") : void 0,
|
|
83
|
-
naturalWidth: naturalSize?.width,
|
|
84
|
-
naturalHeight: naturalSize?.height
|
|
105
|
+
width: intrinsicSize.width - crop.left - crop.right,
|
|
106
|
+
height: intrinsicSize.height - crop.top - crop.bottom
|
|
85
107
|
};
|
|
86
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
|
+
}
|
|
87
124
|
export {
|
|
88
|
-
|
|
125
|
+
aspectRatio,
|
|
126
|
+
croppedSize,
|
|
89
127
|
defaultQuality,
|
|
128
|
+
defaultWidth,
|
|
90
129
|
defaultWidths,
|
|
91
|
-
|
|
92
|
-
|
|
130
|
+
fit,
|
|
131
|
+
fitComparators,
|
|
132
|
+
imageAlt,
|
|
133
|
+
imageAspectRatio,
|
|
134
|
+
imageCroppedSize,
|
|
135
|
+
imageMetadata,
|
|
136
|
+
imageSrc,
|
|
137
|
+
imageSrcset,
|
|
138
|
+
isAsset,
|
|
139
|
+
isCrop,
|
|
140
|
+
isDimensions,
|
|
141
|
+
isHotspot,
|
|
142
|
+
isImageObject,
|
|
143
|
+
isImageObjectLike,
|
|
144
|
+
isMetadata,
|
|
145
|
+
isReference,
|
|
146
|
+
isSize
|
|
93
147
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nonphoto/sanity-image",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
"author": "Jonas Luebbers <jonas@jonasluebbers.com> (https://www.jonasluebbers.com)",
|
|
35
35
|
"license": "MIT",
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"semantic-release": "24.2.
|
|
38
|
-
"tsup": "8.
|
|
39
|
-
"typescript": "5.
|
|
37
|
+
"semantic-release": "24.2.7",
|
|
38
|
+
"tsup": "8.5.0",
|
|
39
|
+
"typescript": "5.9.2"
|
|
40
40
|
},
|
|
41
41
|
"engines": {
|
|
42
42
|
"node": ">=20",
|
|
43
43
|
"pnpm": ">=9"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@sanity/image-url": "1.0
|
|
46
|
+
"@sanity/image-url": "^1.1.0"
|
|
47
47
|
}
|
|
48
48
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import imageUrlBuilder from "@sanity/image-url";
|
|
2
|
-
import { ImageUrlBuilder } from "@sanity/image-url/lib/types/builder";
|
|
3
2
|
import type {
|
|
3
|
+
SanityAsset,
|
|
4
4
|
SanityClientLike,
|
|
5
5
|
SanityImageCrop,
|
|
6
6
|
SanityImageDimensions,
|
|
7
|
+
SanityImageHotspot,
|
|
8
|
+
SanityImageObject,
|
|
7
9
|
SanityImageSource,
|
|
8
10
|
SanityModernClientLike,
|
|
9
11
|
SanityProjectDetails,
|
|
12
|
+
SanityReference,
|
|
10
13
|
} from "@sanity/image-url/lib/types/types.js";
|
|
11
14
|
|
|
12
|
-
export interface
|
|
15
|
+
export interface SanityImageObjectLike
|
|
16
|
+
extends Pick<SanityImageObject, "asset"> {
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SanityImageMetadata {
|
|
13
21
|
lqip?: string;
|
|
14
22
|
dimensions?: SanityImageDimensions;
|
|
23
|
+
[key: string]: any;
|
|
15
24
|
}
|
|
16
25
|
|
|
17
26
|
export interface Size {
|
|
@@ -39,19 +48,17 @@ export const defaultWidths = [
|
|
|
39
48
|
240,
|
|
40
49
|
];
|
|
41
50
|
|
|
42
|
-
export const
|
|
43
|
-
|
|
44
|
-
export const defaultMetaImageWidth = 1200;
|
|
51
|
+
export const defaultWidth = 1280;
|
|
45
52
|
|
|
46
53
|
export const defaultQuality = 90;
|
|
47
54
|
|
|
48
|
-
const fitComparators = {
|
|
55
|
+
export const fitComparators = {
|
|
49
56
|
cover: Math.max,
|
|
50
57
|
contain: Math.min,
|
|
51
|
-
mean: (a: number, b: number) => (a + b) / 2,
|
|
52
58
|
};
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
// TODO: impement comparators for every FitMode
|
|
61
|
+
export function fit(
|
|
55
62
|
containee: Size,
|
|
56
63
|
container: Size,
|
|
57
64
|
mode: keyof typeof fitComparators
|
|
@@ -65,21 +72,9 @@ function fit(
|
|
|
65
72
|
};
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
function
|
|
69
|
-
builder: ImageUrlBuilder,
|
|
70
|
-
width: number,
|
|
71
|
-
aspectRatio?: number
|
|
72
|
-
) {
|
|
73
|
-
if (aspectRatio) {
|
|
74
|
-
return builder.width(width).height(Math.round(width * aspectRatio));
|
|
75
|
-
} else {
|
|
76
|
-
return builder.width(width);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function isCrop(x: any): x is SanityImageCrop {
|
|
75
|
+
export function isCrop(x: unknown): x is SanityImageCrop {
|
|
81
76
|
return (
|
|
82
|
-
x &&
|
|
77
|
+
x != null &&
|
|
83
78
|
typeof x == "object" &&
|
|
84
79
|
"top" in x &&
|
|
85
80
|
typeof x.top === "number" &&
|
|
@@ -88,69 +83,196 @@ function isCrop(x: any): x is SanityImageCrop {
|
|
|
88
83
|
"bottom" in x &&
|
|
89
84
|
typeof x.bottom === "number" &&
|
|
90
85
|
"left" in x &&
|
|
91
|
-
typeof x.left === "number"
|
|
86
|
+
typeof x.left === "number" &&
|
|
87
|
+
("_type" in x
|
|
88
|
+
? typeof x._type === "undefined" || typeof x._type === "string"
|
|
89
|
+
: true)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function isHotspot(x: unknown): x is SanityImageHotspot {
|
|
94
|
+
return (
|
|
95
|
+
x != null &&
|
|
96
|
+
typeof x == "object" &&
|
|
97
|
+
"width" in x &&
|
|
98
|
+
typeof x.width === "number" &&
|
|
99
|
+
"height" in x &&
|
|
100
|
+
typeof x.height === "number" &&
|
|
101
|
+
"x" in x &&
|
|
102
|
+
typeof x.x === "number" &&
|
|
103
|
+
"y" in x &&
|
|
104
|
+
typeof x.y === "number" &&
|
|
105
|
+
("_type" in x
|
|
106
|
+
? typeof x._type === "undefined" || typeof x._type === "string"
|
|
107
|
+
: true)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function isImageObjectLike(x: unknown): x is SanityImageObjectLike {
|
|
112
|
+
return (
|
|
113
|
+
x != null &&
|
|
114
|
+
typeof x === "object" &&
|
|
115
|
+
"asset" in x &&
|
|
116
|
+
(isAsset(x) || isReference(x))
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function isImageObject(x: unknown): x is SanityImageObject {
|
|
121
|
+
return (
|
|
122
|
+
isImageObjectLike(x) &&
|
|
123
|
+
("crop" in x ? typeof x.crop === "undefined" || isCrop(x.crop) : true) &&
|
|
124
|
+
("hotspot" in x
|
|
125
|
+
? typeof x.hotspot === "undefined" || isHotspot(x.hotspot)
|
|
126
|
+
: true)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function isReference(x: unknown): x is SanityReference {
|
|
131
|
+
return (
|
|
132
|
+
x != null &&
|
|
133
|
+
typeof x === "object" &&
|
|
134
|
+
"_ref" in x &&
|
|
135
|
+
typeof x._ref === "string"
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function isAsset(x: unknown): x is SanityAsset {
|
|
140
|
+
return (
|
|
141
|
+
x != null &&
|
|
142
|
+
typeof x === "object" &&
|
|
143
|
+
"_type" in x &&
|
|
144
|
+
x._type === "sanity.asset"
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function isDimensions(x: unknown): x is SanityImageDimensions {
|
|
149
|
+
return (
|
|
150
|
+
x != null &&
|
|
151
|
+
typeof x === "object" &&
|
|
152
|
+
"aspectRatio" in x &&
|
|
153
|
+
typeof x.aspectRatio === "number" &&
|
|
154
|
+
"width" in x &&
|
|
155
|
+
typeof x.width === "number" &&
|
|
156
|
+
"height" in x &&
|
|
157
|
+
typeof x.height === "number"
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function isSize(x: unknown): x is Size {
|
|
162
|
+
return (
|
|
163
|
+
x != null &&
|
|
164
|
+
typeof x === "object" &&
|
|
165
|
+
"width" in x &&
|
|
166
|
+
typeof x.width === "number" &&
|
|
167
|
+
"height" in x &&
|
|
168
|
+
typeof x.height === "number"
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function isMetadata(x: unknown): x is SanityImageMetadata {
|
|
173
|
+
return (
|
|
174
|
+
x != null &&
|
|
175
|
+
typeof x === "object" &&
|
|
176
|
+
"lqip" in x &&
|
|
177
|
+
typeof x.lqip === "string" &&
|
|
178
|
+
"dimensions" in x &&
|
|
179
|
+
isDimensions(x.dimensions)
|
|
92
180
|
);
|
|
93
181
|
}
|
|
94
182
|
|
|
95
|
-
export interface
|
|
183
|
+
export interface ImageSrcOptions {
|
|
96
184
|
client: SanityClientLike | SanityProjectDetails | SanityModernClientLike;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
widths?: number[];
|
|
185
|
+
source: SanityImageSource;
|
|
186
|
+
width: number;
|
|
100
187
|
quality?: number;
|
|
101
188
|
aspectRatio?: number;
|
|
102
189
|
}
|
|
103
190
|
|
|
104
|
-
export
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
191
|
+
export function imageSrc({
|
|
192
|
+
client,
|
|
193
|
+
source,
|
|
194
|
+
width,
|
|
195
|
+
quality = defaultQuality,
|
|
196
|
+
aspectRatio,
|
|
197
|
+
}: ImageSrcOptions): string {
|
|
198
|
+
const builder = imageUrlBuilder(client)
|
|
199
|
+
.image(source)
|
|
200
|
+
.quality(quality)
|
|
201
|
+
.auto("format")
|
|
202
|
+
.width(width);
|
|
203
|
+
return (aspectRatio ? builder.height(width * aspectRatio) : builder).url();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export interface ImageSrcsetOptions {
|
|
207
|
+
client: SanityClientLike | SanityProjectDetails | SanityModernClientLike;
|
|
208
|
+
source: SanityImageSource;
|
|
209
|
+
widths?: number[];
|
|
210
|
+
quality?: number;
|
|
211
|
+
aspectRatio?: number;
|
|
109
212
|
}
|
|
110
213
|
|
|
111
|
-
export function
|
|
214
|
+
export function imageSrcset({
|
|
112
215
|
client,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
widths,
|
|
216
|
+
source,
|
|
217
|
+
widths = defaultWidths,
|
|
116
218
|
quality = defaultQuality,
|
|
117
219
|
aspectRatio,
|
|
118
|
-
}:
|
|
220
|
+
}: ImageSrcsetOptions): string {
|
|
119
221
|
const builder = imageUrlBuilder(client)
|
|
120
|
-
.image(
|
|
222
|
+
.image(source)
|
|
121
223
|
.quality(quality)
|
|
122
224
|
.auto("format");
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
: metadata.dimensions
|
|
134
|
-
: undefined;
|
|
225
|
+
return widths
|
|
226
|
+
.sort((a, b) => a - b)
|
|
227
|
+
.map((width) => {
|
|
228
|
+
const url = (aspectRatio ? builder.height(width * aspectRatio) : builder)
|
|
229
|
+
.width(width)
|
|
230
|
+
.url();
|
|
231
|
+
return `${url} ${width}w`;
|
|
232
|
+
})
|
|
233
|
+
.join(",");
|
|
234
|
+
}
|
|
135
235
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
236
|
+
export function imageAlt(source: SanityImageSource): string | undefined {
|
|
237
|
+
return isImageObjectLike(source) &&
|
|
238
|
+
"alt" in source &&
|
|
239
|
+
typeof source.alt === "string"
|
|
240
|
+
? source.alt
|
|
140
241
|
: undefined;
|
|
141
|
-
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function croppedSize(intrinsicSize: Size, crop: SanityImageCrop): Size {
|
|
142
245
|
return {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
? Array.from(widths)
|
|
146
|
-
.sort((a, b) => a - b)
|
|
147
|
-
.map(
|
|
148
|
-
(width) =>
|
|
149
|
-
`${buildAspectRatio(builder, width, aspectRatio).url()} ${width}w`
|
|
150
|
-
)
|
|
151
|
-
.join(",")
|
|
152
|
-
: undefined,
|
|
153
|
-
naturalWidth: naturalSize?.width,
|
|
154
|
-
naturalHeight: naturalSize?.height,
|
|
246
|
+
width: intrinsicSize.width - crop.left - crop.right,
|
|
247
|
+
height: intrinsicSize.height - crop.top - crop.bottom,
|
|
155
248
|
};
|
|
156
249
|
}
|
|
250
|
+
|
|
251
|
+
export function aspectRatio(size: Size): number {
|
|
252
|
+
return size.height / size.width;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export function imageMetadata(
|
|
256
|
+
source: SanityImageSource
|
|
257
|
+
): SanityImageMetadata | undefined {
|
|
258
|
+
const asset = isImageObjectLike(source) ? source.asset : source;
|
|
259
|
+
return isAsset(asset) && isMetadata(asset.metadata)
|
|
260
|
+
? asset.metadata
|
|
261
|
+
: undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function imageCroppedSize(source: SanityImageSource): Size | undefined {
|
|
265
|
+
const metadata = imageMetadata(source);
|
|
266
|
+
return metadata?.dimensions
|
|
267
|
+
? isImageObject(source) && source.crop != null
|
|
268
|
+
? croppedSize(metadata.dimensions, source.crop)
|
|
269
|
+
: metadata.dimensions
|
|
270
|
+
: undefined;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function imageAspectRatio(
|
|
274
|
+
source: SanityImageSource
|
|
275
|
+
): number | undefined {
|
|
276
|
+
const size = imageCroppedSize(source);
|
|
277
|
+
return size ? aspectRatio(size) : undefined;
|
|
278
|
+
}
|