Commit 620282e

HPCesia <me@hpcesia.com>
2025-03-18 12:51:57
fix: ImageMetadata as `src` param in ImageWrapper
1 parent 5e341cd
Changed files (4)
src/components/utils/ImageWrapper.astro
@@ -4,7 +4,7 @@ import { Image } from 'astro:assets';
 import path from 'path';
 interface Props {
   id?: string;
-  src: string;
+  src: ImageMetadata | string;
   class?: string;
   alt?: string;
   position?: string;
@@ -14,30 +14,36 @@ interface Props {
 const { id, src, alt, position = 'center', basePath = '/' } = Astro.props;
 const className = Astro.props.class;
 
-const isLocal = !(
-  src.startsWith('/') ||
-  src.startsWith('http') ||
-  src.startsWith('https') ||
-  src.startsWith('data:')
-);
-const isPublic = src.startsWith('/');
+const isLocal =
+  typeof src !== 'string' ||
+  !(
+    src.startsWith('/') ||
+    src.startsWith('http') ||
+    src.startsWith('https') ||
+    src.startsWith('data:')
+  );
+const isPublic = typeof src === 'string' && src.startsWith('/');
 
-let img;
+let img: ImageMetadata | undefined;
 if (isLocal) {
-  const files = import.meta.glob<ImageMetadata>(
-    '../../**/*.{png,jpg,jpeg,tiff,webp,gif,svg,avif,jfif,pjpeg,pjp,ico}',
-    {
-      import: 'default',
-    }
-  );
-  let normalizedPath = path.normalize(path.join('../../', basePath, src)).replace(/\\/g, '/');
-  const file = files[normalizedPath];
-  if (!file) {
-    console.error(
-      `\n[ERROR] Image file not found: ${normalizedPath.replace('../../', 'src/')}`
+  if (typeof src === 'string') {
+    const files = import.meta.glob<ImageMetadata>(
+      '../../**/*.{png,jpg,jpeg,tiff,webp,gif,svg,avif,jfif,pjpeg,pjp,ico}',
+      {
+        import: 'default',
+      }
     );
+    let normalizedPath = path.normalize(path.join('../../', basePath, src)).replace(/\\/g, '/');
+    const file = files[normalizedPath];
+    if (!file) {
+      console.error(
+        `\n[ERROR] Image file not found: ${normalizedPath.replace('../../', 'src/')}`
+      );
+    }
+    img = await file();
+  } else {
+    img = src;
   }
-  img = await file();
 }
 
 const imageClass = 'w-full h-full object-cover';
@@ -47,9 +53,20 @@ const imageStyle = `object-position: ${position}`;
 <div id={id} class:list={[className, 'relative overflow-hidden']}>
   {isLocal && img && <Image src={img} alt={alt || ''} class={imageClass} style={imageStyle} />}
   {
-    !isLocal && (
+    !isLocal && !isPublic && (
+      <Image
+        src={src as string}
+        alt={alt || ''}
+        class={imageClass}
+        style={imageStyle}
+        inferSize
+      />
+    )
+  }
+  {
+    !isLocal && isPublic && (
       <img
-        src={isPublic ? (new URL(src, Astro.site) as unknown as string) : src}
+        src={new URL(src, Astro.site) as unknown as string}
         alt={alt || ''}
         class={imageClass}
         style={imageStyle}
src/pages/posts/[article].astro
@@ -13,7 +13,6 @@ import { getPosts } from '@utils/content-utils';
 import { Icon } from 'astro-icon/components';
 import { render, type CollectionEntry } from 'astro:content';
 import MarkdownIt from 'markdown-it';
-import path from 'path';
 
 export async function getStaticPaths() {
   const posts = await getPosts();
@@ -25,13 +24,7 @@ export async function getStaticPaths() {
 
 const { article } = Astro.props;
 const { Content, headings, remarkPluginFrontmatter } = await render(article);
-const hasCover =
-  article.data.cover !== '' && article.data.cover !== undefined && article.data.cover !== null;
-const coverSrc = hasCover
-  ? article.data.cover.startsWith('.')
-    ? path.join('content/posts', article.id, article.data.cover)
-    : article.data.cover
-  : undefined;
+const coverSrc = article.data.cover?.src;
 const description = article.data.description || remarkPluginFrontmatter.excerpt;
 const isDraft = article.data.draft === true;
 
@@ -131,7 +124,7 @@ const backLinks: {
     />
   </Fragment>
   {
-    siteConfig.banner === false && hasCover && (
+    siteConfig.banner === false && coverSrc && (
       <ImageWrapper src={coverSrc!} class="mb-6 rounded-xl shadow" alt={article.data.title} />
     )
   }
src/types/data.ts
@@ -1,3 +1,4 @@
+import type { ImageMetadata } from 'astro';
 import type { RenderedContent } from 'astro:content';
 
 export type BlogPostData = {
@@ -8,7 +9,7 @@ export type BlogPostData = {
   description: string;
   tags: string[];
   draft?: boolean;
-  cover?: string;
+  cover?: ImageMetadata;
   category?: string;
   comment?: boolean;
 };
src/utils/content-utils.ts
@@ -5,7 +5,6 @@ import I18nKey from '@i18n/I18nKey';
 import { i18n } from '@i18n/translation';
 import { type CollectionEntry, getCollection, render } from 'astro:content';
 import dayjs from 'dayjs';
-import path from 'path';
 
 export async function getPosts() {
   const posts = await getCollection('posts');
@@ -33,12 +32,6 @@ export async function getSortedPosts(): Promise<BlogPost[]> {
       return dateA > dateB ? -1 : 1;
     }
   );
-  sortedBlogPosts.forEach((post) => {
-    const coverPath = post.data.cover;
-    if (coverPath?.startsWith('.')) {
-      post.data.cover = path.join('content/posts', post.id, coverPath);
-    }
-  });
   return sortedBlogPosts;
 }