Repository navigation
feat: add cover image display for article detail and list pages - #28
Conversation
- Display ogImage on article detail page above title with hover effects - Add thumbnail in article list cards (responsive layout) - Support cover image in RSS feed via enclosure tag - Auto-detect MIME type for RSS enclosure Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds visual cover image display functionality to article pages, leveraging the existing ogImage frontmatter field. Previously, ogImage was only used for Open Graph metadata; now it's also displayed on the article detail page (above the title) and as thumbnails in article list cards.
Changes:
- Added cover image display in article detail pages with hover effects and responsive sizing
- Implemented thumbnail images in article list cards with responsive layout (mobile: stacked, desktop: left-side)
- Extended RSS feed to include cover images via enclosure tags with automatic MIME type detection
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
src/pages/rss.xml.ts |
Added helper functions for ogImage URL parsing and MIME type detection, integrated cover images into RSS feed enclosures |
src/layouts/PostDetails.astro |
Added conditional cover image display above article content with hover effects and responsive max-height constraints |
src/components/Card.astro |
Implemented thumbnail display in list cards with responsive flex layout and hover scale effects |
src/data/blog/2026-01-17.extend-claude-code-with-slash-command.md |
Added example ogImage field demonstrating feature usage |
openspec/changes/archive/2026-01-19-add-cover-image-display/* |
Comprehensive documentation including proposal, design decisions, specs, and task breakdown |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }; | ||
| return mimeTypes[ext || ""] || "image/jpeg"; |
There was a problem hiding this comment.
The MIME type detection logic is limited and may not accurately handle all image formats. Consider adding support for additional formats like 'avif', 'bmp', and 'ico'. Also, the fallback to 'image/jpeg' may be incorrect for other file types. Consider defaulting to 'application/octet-stream' for unknown types or adding a warning.
| }; | |
| return mimeTypes[ext || ""] || "image/jpeg"; | |
| avif: "image/avif", | |
| bmp: "image/bmp", | |
| ico: "image/x-icon", | |
| }; | |
| return mimeTypes[ext || ""] || "application/octet-stream"; |
| ...(ogImageUrl && { | ||
| enclosure: { | ||
| url: ogImageUrl, | ||
| type: getImageMimeType(ogImageUrl), |
There was a problem hiding this comment.
The length property is hardcoded to 0, which is technically valid for RSS but not ideal. RSS enclosures should include the file size in bytes when possible. Consider either fetching the actual file size or documenting why this is set to 0 (e.g., "length set to 0 as file size is not known at build time").
| type: getImageMimeType(ogImageUrl), | |
| type: getImageMimeType(ogImageUrl), | |
| // length set to 0 as file size is not known at build time |
| if (ogImage.src) { | ||
| // 本地 asset | ||
| return new URL(ogImage.src, site).href; |
There was a problem hiding this comment.
The getOgImageUrl function doesn't handle the case where ogImage is a local asset but lacks a .src property. While this might be unlikely, adding explicit validation or type checking would make the code more robust. Consider adding a check to ensure the object has the expected structure before accessing .src.
| if (ogImage.src) { | |
| // 本地 asset | |
| return new URL(ogImage.src, site).href; | |
| if ( | |
| typeof ogImage === "object" && | |
| ogImage !== null && | |
| "src" in ogImage && | |
| typeof (ogImage as { src: unknown }).src === "string" | |
| ) { | |
| // 本地 asset | |
| return new URL((ogImage as { src: string }).src, site).href; |
| alt={title} | ||
| class="h-24 w-full object-cover transition-transform duration-300 group-hover/thumb:scale-105 sm:h-24 sm:w-40" | ||
| loading="lazy" | ||
| decoding="async" |
There was a problem hiding this comment.
Consider adding width and height attributes to the img tag to prevent layout shift during image loading. This helps with Cumulative Layout Shift (CLS) metrics and improves user experience. For the thumbnail, you could use width="160" height="96" to match the aspect ratio of the sm:w-40 sm:h-24 classes.
| decoding="async" | |
| decoding="async" | |
| width="160" | |
| height="96" |
| // 解析 ogImage URL | ||
| function getOgImageUrl( | ||
| ogImage: CollectionEntry<"blog">["data"]["ogImage"], | ||
| site: string | ||
| ): string | undefined { | ||
| if (!ogImage) return undefined; | ||
| if (typeof ogImage === "string") { | ||
| // 远程 URL 直接返回,相对路径拼接 site | ||
| return ogImage.startsWith("http") ? ogImage : new URL(ogImage, site).href; | ||
| } | ||
| if (ogImage.src) { | ||
| // 本地 asset | ||
| return new URL(ogImage.src, site).href; | ||
| } | ||
| return undefined; | ||
| } |
There was a problem hiding this comment.
The ogImage URL parsing logic here duplicates similar logic in PostDetails.astro (lines 51-55) and Card.astro (lines 31-35). Consider extracting this into a shared utility function in a file like @/utils/getOgImageUrl.ts to maintain consistency and reduce code duplication.
| <div class="group/cover mb-6 overflow-hidden rounded-xl border border-foreground/10 shadow-lg shadow-foreground/5 transition-shadow duration-300 hover:shadow-xl hover:shadow-foreground/10"> | ||
| <img | ||
| src={ogImageUrl} | ||
| alt={title} |
There was a problem hiding this comment.
While the alt attribute is set to the article title, this may not be the most descriptive alternative text for screen readers. Consider using a more descriptive alt text that describes what the cover image actually depicts, or use an empty alt (alt="") if the image is purely decorative and doesn't add meaningful content beyond what the title already conveys.
| alt={title} | |
| alt="" |
| <div class="group/thumb shrink-0 overflow-hidden rounded-md border border-foreground/10 shadow-sm"> | ||
| <img | ||
| src={ogImageUrl} | ||
| alt={title} |
There was a problem hiding this comment.
While the alt attribute is set to the article title, this may not be the most descriptive alternative text for screen readers. Consider using a more descriptive alt text that describes what the thumbnail image actually depicts, or use an empty alt (alt="") if the image is purely decorative and doesn't add meaningful content beyond what the title already conveys.
| alt={title} | |
| alt="" |
| <img | ||
| src={ogImageUrl} | ||
| alt={title} | ||
| class="h-auto max-h-[250px] w-full object-cover transition-transform duration-300 group-hover/cover:scale-[1.02] sm:max-h-[400px]" | ||
| loading="lazy" | ||
| decoding="async" | ||
| /> |
There was a problem hiding this comment.
Consider adding width and height attributes to the img tag to prevent layout shift during image loading. This helps with Cumulative Layout Shift (CLS) metrics and improves user experience. Since the image uses object-cover, you can set explicit dimensions that match the container's aspect ratio.
- Add avif MIME type support in RSS feed - Add comment explaining enclosure length: 0 rationale - Add width/height attributes to Card thumbnail to prevent CLS Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: address Copilot review suggestions for PR #28 - Add avif MIME type support in RSS feed - Add comment explaining enclosure length: 0 rationale - Add width/height attributes to Card thumbnail to prevent CLS Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add view source link and CC license declaration - Add viewSource config for raw markdown link (GitHub raw URL) - Add license config for CC BY-NC-SA 4.0 declaration - Create ViewSource.astro component with GitHub icon - Create License.astro component with official CC badge and post URL - Integrate components into PostDetails layout - Simplify BackToTopButton and move to TOC sidebar - Add tech stack info to Footer (Astro & AstroPaper) - Remove ShareLinks from post details - Update TableOfContents to support slot for BackToTopButton Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: 修复无头图文章错误显示动态 OG 图片的问题 - 分离 coverImageUrl(页面显示)和 ogImageUrl(meta 标签) - 页面封面图只在用户明确设置 ogImage 时才显示 - 动态 OG 图片仅用于 meta 标签,不影响页面显示 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: 更新项目文档并归档 OpenSpec proposal - 更新 README.md,添加特性列表和配置说明 - 完善 openspec/project.md 项目上下文 - 归档 add-source-link-and-license proposal - 创建 post-details spec Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: 添加小红书文案生成命令和忽略配置 - 新增 .claude/commands/xhs-copy.md 小红书文案生成命令 - .gitignore 添加 xhs-images/ 目录 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: 为 CC 协议徽章添加 width/height 属性 避免页面加载时的布局偏移 (CLS) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Summary
Test plan
🤖 Generated with Claude Code