97 lines
2.1 KiB
Plaintext
97 lines
2.1 KiB
Plaintext
---
|
|
import type { ImageMetadata } from "astro";
|
|
import { Picture as AstroImage } from "astro:assets";
|
|
import { inferRemoteSize } from "astro/assets/utils";
|
|
import { getProcessedImage } from "@helpers/image";
|
|
interface Props {
|
|
src: ImageMetadata & { fsPath?: string; src?: string };
|
|
alt: string;
|
|
pictureClass?: string;
|
|
class?: string;
|
|
caption?: string;
|
|
hash?: boolean;
|
|
loader?: boolean;
|
|
maxWidth?: number;
|
|
thumbnail?: boolean;
|
|
}
|
|
|
|
async function checkImage(image: ImageMetadata) {
|
|
const src = typeof image === "string" ? image : image.src;
|
|
if (!src) return false;
|
|
try {
|
|
if (src.startsWith("/@fs") || src.startsWith("/_astro")) return true;
|
|
const res = await inferRemoteSize(src);
|
|
if (res.format) {
|
|
image.format = res.format;
|
|
return true;
|
|
} else {
|
|
console.log("Failed to load: ", src);
|
|
}
|
|
return false;
|
|
} catch (err) {
|
|
console.log("\n");
|
|
console.log("Failed to fetch: ", src);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const {
|
|
src: image,
|
|
loader = true,
|
|
pictureClass = "",
|
|
hash = true,
|
|
alt,
|
|
maxWidth,
|
|
thumbnail = false,
|
|
} = Astro.props;
|
|
|
|
const imageOk = await checkImage(image);
|
|
|
|
const { thumbhash, exif } = imageOk
|
|
? await getProcessedImage(image)
|
|
: { thumbhash: undefined, exif: undefined };
|
|
|
|
const definedSizes = [
|
|
{
|
|
width: 240,
|
|
media: "(max-width: 360px)",
|
|
},
|
|
{
|
|
width: 540,
|
|
media: "(max-width: 720px)",
|
|
},
|
|
{
|
|
width: 720,
|
|
media: "(max-width: 1600px)",
|
|
},
|
|
{
|
|
width: image.width,
|
|
},
|
|
];
|
|
|
|
const sizes = thumbnail
|
|
? [definedSizes[0]]
|
|
: definedSizes.filter((size) => !maxWidth || size.width <= maxWidth);
|
|
---
|
|
|
|
{
|
|
imageOk ? (
|
|
<AstroImage
|
|
src={image}
|
|
alt={alt}
|
|
data-thumbhash={thumbhash}
|
|
data-exif={JSON.stringify(exif)}
|
|
inferSize={true}
|
|
pictureAttributes={{
|
|
class: `${hash ? "block h-full relative" : ""} ${loader ? "thumb" : ""} ${pictureClass}`,
|
|
}}
|
|
class={`${Astro.props.class} h-full w-full`}
|
|
widths={sizes.map((size) => size.width)}
|
|
sizes={sizes
|
|
.map((size) => `${size.media || "100vw"} ${size.width}px`)
|
|
.join(", ")}>
|
|
<slot />
|
|
</AstroImage>
|
|
) : undefined
|
|
}
|