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');
/>
) : (
