diff --git a/src/pages/post/[...slug].astro b/src/pages/post/[...slug].astro index 740eba7..25990b4 100644 --- a/src/pages/post/[...slug].astro +++ b/src/pages/post/[...slug].astro @@ -3,6 +3,10 @@ import Layout from '../../layouts/Layout.astro'; import { getCollection } from 'astro:content'; import Comments from "../../components/Comments.astro"; import {getImage} from "astro:assets"; +import { unified } from "unified"; +import { select } from "unist-util-select"; +import remarkMdx from "remark-mdx"; +import remarkParse from "remark-parse"; export async function getStaticPaths() { const blogEntries = await getCollection('posts'); @@ -14,16 +18,19 @@ export async function getStaticPaths() { const { entry } = Astro.props; const { Content } = await entry.render(); - const slug = Astro.params.slug; + +// get featured image and use it as og:image +// use the custom cover image if it exists, otherwise use the featured image file in the same directory const featuredImages = import.meta.glob(`/src/content/posts/*/featured.*`,{import:'default',eager:true}); +const customFeaturedImage = entry.data.cover?.src const matchedImage = Object.keys(featuredImages).find(path => path.includes(slug)); let matchedImage_src; -if (matchedImage) { +if (matchedImage && !customFeaturedImage) { matchedImage_src = await getImage({src: featuredImages[matchedImage], format: 'webp'}) || null; } -const cover = entry.data.cover || matchedImage_src?.src || `/post/${slug}/og.webp`; -//|| `/posts/${slug}/featured.webp` || `/posts/${slug}/featured.png` || `/posts/${slug}/featured.jpg` + +const cover = customFeaturedImage || matchedImage_src?.src || `/post/${slug}/featured.png` || ''; --- ({ + params: { slug: post.slug }, props: { post }, + })); +} + +// get the post has a external featured.* image files +async function getExternalImage(post) { + const featuredImages = import.meta.glob(`/src/content/posts/*/featured.*`, {import: 'default', eager: true}); + const matchedImage = Object.keys(featuredImages).find(path => path.includes(post.slug)); + let matchedImage_src; + if (matchedImage) { + matchedImage_src = await getImage({src: featuredImages[matchedImage], format: 'webp'}) || null; + } + return matchedImage_src; +} + +// This function dynamically generates og:images for posts that don't have a featured image +export async function GET({ props }) { + const {post} = props; + try { + // Check if a custom cover image already exists + if (post.data.cover && await getExternalImage(post)) { + // Redirect to the existing image + return new Response(null); + } + + // Generate an image with post title and description + const width = 1280; + const height = 720; + + // Create a simple image with text + const svg = ` + + + ${post.data.title} + ${post.data.description} + + `; + + // Convert SVG to WebP + const buffer = await sharp(Buffer.from(svg)) + .toFormat('webp') + .toBuffer(); + + // Return the image + return new Response(buffer, { + headers: { + 'Content-Type': 'image/png', + 'Cache-Control': 'public, max-age=31536000' + } + }); + } catch (error) { + console.error('Error generating image:', error); + return new Response('Error generating image', { status: 500 }); + } +} \ No newline at end of file