diff --git a/src/components/ContentFigure.astro b/src/components/ContentFigure.astro index 2da2562..b6ace2f 100644 --- a/src/components/ContentFigure.astro +++ b/src/components/ContentFigure.astro @@ -4,20 +4,23 @@ * * Usage in MDX: * - * Images: - * - * Optional **markdown** caption here - * + * Images (with glob import - recommended for unique filenames): + * export const images = import.meta.glob('./img/*.webp', { eager: true, import: 'default' }); + * + * + * Images (string path - uses loose matching): + * * - * + * With options: + * * Caption with *italic* and [links](url) * * - * + * * Custom border style * * - * + * * Left-aligned image * * @@ -31,7 +34,7 @@ * * * Props: - * - src: Image path (relative or absolute) OR YouTube URL + * - src: ImageMetadata (from glob import), image path string, or YouTube URL * - alt: Alt text for accessibility (images only) * - width: Width of the figure (e.g., "60%", "400px") - defaults to 100% * - border: Add a border (boolean for default style, or string for custom CSS border) @@ -47,7 +50,7 @@ const assetImages = import.meta.glob<{ default: ImageMetadata }>('/src/assets/co const allImages = { ...contentImages, ...assetImages }; interface Props { - src: string; + src: string | ImageMetadata; alt?: string; width?: string; border?: boolean | string; @@ -57,6 +60,9 @@ interface Props { const { src, alt = '', width = '100%', border = false, align = 'center', class: className } = Astro.props; +// Check if src is already an ImageMetadata object (from glob import) +const isImageMetadata = typeof src === 'object' && src !== null && 'src' in src; + // Determine border style const hasBorder = Boolean(border); const borderStyle = typeof border === 'string' ? border : '5px solid var(--sl-color-gray-5)'; @@ -66,9 +72,10 @@ const marginLeft = align === 'right' ? 'auto' : '0'; const marginRight = align === 'left' ? 'auto' : '0'; const marginStyle = align === 'center' ? '0 auto' : `0 ${marginRight} 0 ${marginLeft}`; -// Check if src is a YouTube URL -function isYouTubeUrl(url: string): boolean { - return url.includes('youtube.com') || url.includes('youtu.be'); +// Check if src is a YouTube URL (only for string sources) +function isYouTubeUrl(source: string | ImageMetadata): boolean { + if (typeof source !== 'string') return false; + return source.includes('youtube.com') || source.includes('youtu.be'); } // Extract video ID from YouTube URL @@ -114,9 +121,21 @@ function getOptimizedImage(srcPath: string): ImageMetadata | null { } const isVideo = isYouTubeUrl(src); -const videoId = isVideo ? extractVideoId(src) : ''; +const videoId = isVideo && typeof src === 'string' ? extractVideoId(src) : ''; const embedUrl = isVideo ? `https://www.youtube.com/embed/${videoId}?rel=0&controls=1&showinfo=0&vq=hd1080` : ''; -const optimizedImage = !isVideo ? getOptimizedImage(src) : null; + +// Determine the image source - either already ImageMetadata, or resolve from string path +let optimizedImage: ImageMetadata | null = null; +if (!isVideo) { + if (isImageMetadata) { + // Already an ImageMetadata object from glob import + optimizedImage = src as ImageMetadata; + } else if (typeof src === 'string') { + // Try to resolve string path + optimizedImage = getOptimizedImage(src); + } +} + const hasCaption = Astro.slots.has('default'); --- @@ -142,7 +161,7 @@ const hasCaption = Astro.slots.has('default'); /> ) : (