From a4006b1f3e1d629fae90d7466f9d6cc11cd29cfa Mon Sep 17 00:00:00 2001 From: Cameron Otsuka Date: Sun, 30 Nov 2025 15:22:45 -0800 Subject: [PATCH] add review star rating to rss feed and opengraph images --- src/components/ui/rating.astro | 7 +++--- src/pages/feed.xml.ts | 18 ++++++++++--- .../reviews/[type]/[id]/opengraph.png.ts | 3 ++- src/utils/generateOpenGraphImage.ts | 25 ++++++++++++++++--- src/utils/generateStarRating.ts | 5 ++++ 5 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 src/utils/generateStarRating.ts diff --git a/src/components/ui/rating.astro b/src/components/ui/rating.astro index 07158b7..729c924 100644 --- a/src/components/ui/rating.astro +++ b/src/components/ui/rating.astro @@ -1,12 +1,13 @@ --- +import generateStarRating from '@utils/generateStarRating.ts'; + interface Props { rating: number } const { rating } = Astro.props; -const filledStars = '★'.repeat(rating); -const unfilledStars = '☆'.repeat(5 - rating); +const starRating = generateStarRating(rating); --- - {filledStars}{unfilledStars} + {starRating} \ No newline at end of file diff --git a/src/pages/feed.xml.ts b/src/pages/feed.xml.ts index 6900d78..75b2378 100644 --- a/src/pages/feed.xml.ts +++ b/src/pages/feed.xml.ts @@ -6,6 +6,7 @@ import { getCollection, render } from 'astro:content'; import { loadRenderers } from 'astro:container'; import { experimental_AstroContainer as AstroContainer } from 'astro/container'; import generateContentUrl from '@utils/generateContentUrl'; +import generateStarRating from '@utils/generateStarRating.ts'; export async function GET(context: APIContext) { const articles = await getCollection('articles'); @@ -23,17 +24,28 @@ export async function GET(context: APIContext) { const content = await container.renderToString(Content); const categories = (item.data.tags ?? []).concat(item.collection) if ('type' in item.data) { - categories.push(item.data.type) + categories.push(item.data.type); } if ('show' in item.data) { - categories.push(item.data.show) + categories.push(item.data.show); + } + + var description: string; + switch (item.collection) { + case 'reviews': + const starRating = generateStarRating(item.data.rating); + description = starRating + break; + default: + description = item.data.description; + break; } feedItems.push({ title: item.data.title, link: link, pubDate: item.data.date, - description: item.data.description, + description: description, content: content, categories: categories }) diff --git a/src/pages/reviews/[type]/[id]/opengraph.png.ts b/src/pages/reviews/[type]/[id]/opengraph.png.ts index bb6b390..960be46 100644 --- a/src/pages/reviews/[type]/[id]/opengraph.png.ts +++ b/src/pages/reviews/[type]/[id]/opengraph.png.ts @@ -1,6 +1,7 @@ import type { APIRoute } from 'astro'; import { getCollection } from 'astro:content'; import generateOpenGraphImage from '@utils/generateOpenGraphImage.ts'; +import generateStarRating from '@utils/generateStarRating.ts'; export async function getStaticPaths() { const reviews = await getCollection('reviews'); @@ -13,6 +14,6 @@ export async function getStaticPaths() { export const GET: APIRoute = async ({ props }) => { return generateOpenGraphImage( props.review.data.title, - props.review.data.description ?? "" + generateStarRating(props.review.data.rating) ?? "" ) }; \ No newline at end of file diff --git a/src/utils/generateOpenGraphImage.ts b/src/utils/generateOpenGraphImage.ts index 5d1bc4f..8c89b3e 100644 --- a/src/utils/generateOpenGraphImage.ts +++ b/src/utils/generateOpenGraphImage.ts @@ -1,8 +1,19 @@ import { ImageResponse } from '@vercel/og'; import { siteAuthor } from '@utils/globals.ts'; -async function loadFont() { - const url = `https://cdn.jsdelivr.net/fontsource/fonts/public-sans@latest/latin-400-normal.ttf` +async function loadFont(fontName: string) { + var url: string + switch (fontName) { + case 'Public Sans Variable': + url = `https://cdn.jsdelivr.net/fontsource/fonts/public-sans@latest/latin-400-normal.ttf`; + break; + case 'DejaVu Mono': + url = `https://cdn.jsdelivr.net/fontsource/fonts/dejavu-mono@latest/latin-400-normal.ttf`; + break; + default: + throw new Error('font url not defined'); + } + const font = await fetch(url); if (font) { return await font.arrayBuffer(); @@ -24,7 +35,7 @@ export default async function (title: string, description: string) { width: '100%', height: '100%', padding: 80, - fontFamily: 'Public Sans Variable', + fontFamily: 'Public Sans Variable' }, children: [ { @@ -44,6 +55,7 @@ export default async function (title: string, description: string) { style: { fontSize: 32, marginBottom: 40, + fontFamily: 'DejaVu Mono' }, children: description, }, @@ -90,7 +102,12 @@ export default async function (title: string, description: string) { fonts: [ { name: 'Public Sans Variable', - data: await loadFont(), + data: await loadFont('Public Sans Variable'), + style: 'normal' + }, + { + name: 'DejaVu Mono', + data: await loadFont('DejaVu Mono'), style: 'normal' } ] diff --git a/src/utils/generateStarRating.ts b/src/utils/generateStarRating.ts new file mode 100644 index 0000000..0c3688b --- /dev/null +++ b/src/utils/generateStarRating.ts @@ -0,0 +1,5 @@ +export default function (rating: number): string { + const filledStars = '★'.repeat(rating); + const unfilledStars = '☆'.repeat(5 - rating); + return filledStars + unfilledStars; +} \ No newline at end of file -- 2.52.0