|
1 | 1 | --- |
2 | 2 | import { stegaClean } from "@sanity/client/stega"; |
| 3 | +import type { SanityImageSource } from "@sanity/image-url"; |
3 | 4 | import type { Props as PtProps } from "astro-portabletext/types"; |
4 | 5 | import { youtubeId } from "@/lib/youtube"; |
5 | 6 |
|
6 | 7 | type YouTubeNode = { _type: "youtube"; youtube?: string }; |
7 | 8 |
|
8 | | -type Props = PtProps<YouTubeNode>; |
| 9 | +type Props = PtProps<YouTubeNode> & { |
| 10 | + coverImage?: (SanityImageSource & { alt?: string }) | null; |
| 11 | + priority?: boolean; |
| 12 | +}; |
9 | 13 |
|
10 | | -const { node } = Astro.props; |
| 14 | +const { node, coverImage, priority = false } = Astro.props; |
11 | 15 | const id = youtubeId(stegaClean(node.youtube)); |
| 16 | +
|
| 17 | +const builder = Astro.locals.sanity.urlForImage(coverImage ?? undefined); |
| 18 | +const sanitySrc = builder?.width(1920).height(1080).quality(82).url(); |
| 19 | +const sanitySrcset = builder |
| 20 | + ? [480, 640, 960, 1280, 1600, 1920] |
| 21 | + .map((w) => { |
| 22 | + const h = Math.round((w * 9) / 16); |
| 23 | + return `${builder.width(w).height(h).quality(82).url()} ${w}w`; |
| 24 | + }) |
| 25 | + .join(", ") |
| 26 | + : undefined; |
| 27 | +const rawAlt = stegaClean((coverImage as { alt?: string } | null)?.alt); |
| 28 | +const alt = rawAlt && rawAlt.trim().length > 0 ? rawAlt : ""; |
12 | 29 | --- |
13 | 30 |
|
14 | 31 | { |
15 | 32 | id && ( |
16 | 33 | <div class="not-prose my-6"> |
17 | 34 | <div class="yt-embed relative aspect-video isolate overflow-hidden rounded-md" data-yt={id}> |
18 | | - <picture> |
19 | | - <source |
20 | | - type="image/webp" |
21 | | - srcset={[ |
22 | | - `https://i.ytimg.com/vi_webp/${id}/mqdefault.webp 320w`, |
23 | | - `https://i.ytimg.com/vi_webp/${id}/hqdefault.webp 480w`, |
24 | | - `https://i.ytimg.com/vi_webp/${id}/sddefault.webp 640w`, |
25 | | - ].join(", ")} |
26 | | - /> |
| 35 | + {sanitySrc ? ( |
27 | 36 | <img |
28 | 37 | class="size-full object-cover" |
29 | | - src={`https://i.ytimg.com/vi/${id}/sddefault.jpg`} |
30 | | - alt="" |
31 | | - width={640} |
32 | | - height={480} |
33 | | - loading="lazy" |
34 | | - decoding="async" |
| 38 | + src={sanitySrc} |
| 39 | + srcset={sanitySrcset} |
| 40 | + sizes="(max-width: 1280px) 100vw, 1280px" |
| 41 | + alt={alt} |
| 42 | + width={1920} |
| 43 | + height={1080} |
| 44 | + loading={priority ? "eager" : "lazy"} |
| 45 | + fetchpriority={priority ? "high" : "auto"} |
| 46 | + decoding={priority ? "sync" : "async"} |
35 | 47 | /> |
36 | | - </picture> |
| 48 | + ) : ( |
| 49 | + <picture> |
| 50 | + <source |
| 51 | + type="image/webp" |
| 52 | + sizes="(max-width: 1280px) 100vw, 1280px" |
| 53 | + srcset={[ |
| 54 | + `https://i.ytimg.com/vi_webp/${id}/mqdefault.webp 320w`, |
| 55 | + `https://i.ytimg.com/vi_webp/${id}/hqdefault.webp 480w`, |
| 56 | + `https://i.ytimg.com/vi_webp/${id}/sddefault.webp 640w`, |
| 57 | + `https://i.ytimg.com/vi_webp/${id}/maxresdefault.webp 1280w`, |
| 58 | + ].join(", ")} |
| 59 | + /> |
| 60 | + <img |
| 61 | + class="size-full object-cover" |
| 62 | + src={`https://i.ytimg.com/vi/${id}/maxresdefault.jpg`} |
| 63 | + alt="" |
| 64 | + width={1280} |
| 65 | + height={720} |
| 66 | + loading={priority ? "eager" : "lazy"} |
| 67 | + fetchpriority={priority ? "high" : "auto"} |
| 68 | + decoding={priority ? "sync" : "async"} |
| 69 | + /> |
| 70 | + </picture> |
| 71 | + )} |
37 | 72 | <button |
38 | 73 | type="button" |
39 | 74 | class="absolute inset-0 grid size-full place-items-center border-0 bg-transparent" |
|
0 commit comments