]> git.otsuka.systems Git - cotsuka.github.io/commitdiff
add review star rating to rss feed and opengraph images
authorCameron Otsuka <cameron@otsuka.haus>
Sun, 30 Nov 2025 23:22:45 +0000 (15:22 -0800)
committerCameron Otsuka <cameron@otsuka.haus>
Wed, 3 Dec 2025 00:25:40 +0000 (16:25 -0800)
src/components/ui/rating.astro
src/pages/feed.xml.ts
src/pages/reviews/[type]/[id]/opengraph.png.ts
src/utils/generateOpenGraphImage.ts
src/utils/generateStarRating.ts [new file with mode: 0644]

index 07158b7f5fe51ae605a37ac42e484846eef42b8c..729c924806b8500e39ad4ccabf706bcba4badbd1 100644 (file)
@@ -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);
 ---
 <Fragment>
-    {filledStars}{unfilledStars}
+    {starRating}
 </Fragment>
\ No newline at end of file
index 6900d78a4d0998df84010a32465a438a81170e03..75b2378fd1a192ff21ef5c28d203a905e706df8f 100644 (file)
@@ -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
     })
index bb6b39028f1368d071622db4ff4d5c0d3dfe4a15..960be4627737e66fe6a8528f865d4af067882dd0 100644 (file)
@@ -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
index 5d1bc4f08872d7c4979ec9983a34d574fab46faa..8c89b3e5b193f8e2da56f860c816a1ab8784c67a 100644 (file)
@@ -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 (file)
index 0000000..0c3688b
--- /dev/null
@@ -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