-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontentful.ts
51 lines (44 loc) · 1.52 KB
/
contentful.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import type { GetSources, Source } from "$lib/components/Image";
import { defaultWidths, formats, quality } from "$lib/constants/images";
const getURL = (url: string, format?: string, size?: number) =>
`${url}?${Object.entries({
fm: format,
w: size,
q: quality,
})
.filter(([_, val]) => Boolean(val))
.map((x) => x.join("="))
.join("&")}`;
const maxAvifMegapixels = 9;
const maxAvifPixels = maxAvifMegapixels * 1000000;
export const getSources: GetSources = (
url,
{ widths, srcWidth, srcHeight } = { widths: [...defaultWidths] },
) => {
const heightProportion = srcWidth && (srcHeight ? srcHeight / srcWidth : 1);
return formats.map((format) => {
const shortFormat = format.slice("image/".length).replace(/^jpeg$/, "jpg");
const fallback = getURL(url, shortFormat);
const includeFallback =
shortFormat !== "avif" ||
!srcWidth ||
!heightProportion ||
srcWidth * (srcWidth * heightProportion) <= maxAvifPixels;
const filteredWidths =
shortFormat === "avif" && heightProportion
? widths.filter((width) => {
const height = width * heightProportion;
const pixels = width * height;
return pixels <= maxAvifPixels;
})
: widths;
const srcsetEntries = filteredWidths.map((width): [string, number] => [
getURL(url, shortFormat, width),
width,
]);
return {
type: format,
srcset: includeFallback ? [fallback, ...srcsetEntries] : srcsetEntries,
} satisfies Source;
});
};