From 7ab3f4e6fa4ebde9e1e7fe81d3a84b0d48732ab3 Mon Sep 17 00:00:00 2001 From: Daniel Masterson Date: Sun, 25 Aug 2024 19:59:19 +0100 Subject: [PATCH] feat: Limit RSS Feed to return a maximum of 20 items --- src/app/feed.xml/route.ts | 57 +++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/src/app/feed.xml/route.ts b/src/app/feed.xml/route.ts index c1fe957..4d761f1 100644 --- a/src/app/feed.xml/route.ts +++ b/src/app/feed.xml/route.ts @@ -1,9 +1,23 @@ import { Feed } from "feed"; -import { releaseNoteIsAlpha, releaseNotes } from "@/lib/release-notes"; +import { releaseNotes } from "@/lib/release-notes"; import type { ReleaseNote } from "@/lib/release-notes"; +// Force feed.xml to be cached as static and remain constant for the lifetime of the current site build. +// The supplied releaseNotes array is constant per build, so this will always be the latest release notes. +export const dynamic = "force-static"; + +/** The default number of entries to include in the RSS feed. */ +const RSS_ENTRY_LIMIT = 20; + +/** + * Handles the GET request for the `feed.xml` endpoint. + * @returns The RSS feed for the Zen Browser release notes. + */ export async function GET() { - releaseNotes[0].date + // Just in case the release notes array is empty for whatever reason. + const latestDate = releaseNotes.length > 0 + ? formatRssDate(releaseNotes[0].date) + : new Date(); const feed = new Feed({ id: "https://www.zen-browser.app/release-notes", @@ -13,10 +27,10 @@ export async function GET() { language: "en", favicon: "https://www.zen-browser.app/favicon.ico", copyright: `Zen Browser © ${new Date().getFullYear()} - Made with ❤️ by the Zen team.`, - updated: formatRssDate(releaseNotes[0].date), + updated: latestDate, }); - for (const releaseNote of releaseNotes) { + for (const releaseNote of releaseNotes.slice(0, RSS_ENTRY_LIMIT)) { feed.addItem({ title: `Release notes for version ${releaseNote.version}`, id: `https://www.zen-browser.app/release-notes/${releaseNote.version}`, @@ -34,23 +48,38 @@ export async function GET() { }); } -function formatRssDate(date: string) { - // NOTE: This is assuming the format day/month/year. If release notes change to ISO format, this will need to be updated. - const splitDate = date.split("/"); - const year = Number(splitDate[2]); - const month = Number(splitDate[1]) - 1; +/** + * Formats a date string in the format day/month/year. + * + * Note: If release notes change to ISO format, this will need to be updated. + * @param dateStr The date string to format. + * @returns The passed in date string as a Date object. + */ +function formatRssDate(dateStr: string) { + const splitDate = dateStr.split("/"); + if (splitDate.length !== 3) { + throw new Error("Invalid date format"); + } + const day = Number(splitDate[0]); + const month = Number(splitDate[1]) - 1; + const year = Number(splitDate[2]); return new Date(year, month, day); } +/** + * Formats the release note entry for use as the content of the RSS feed. + * @param releaseNote The release note to format. + * @returns The formatted release note as a HTML string. + */ function formatReleaseNote(releaseNote: ReleaseNote) { let content = "

If you encounter any issues, please report them on the issues page. Thanks everyone for your feedback! ❤️

"; - if(releaseNote.extra) { + if (releaseNote.extra) { content += `

${releaseNote.extra.replace(/(\n)/g, "
")}

` } - if(releaseNote.breakingChanges) { + if (releaseNote.breakingChanges) { content += `

⚠️ Breaking changes

` content += `` } - if(releaseNote.features) { + if (releaseNote.features) { content += `

⭐ Features

` content += `` } - if(releaseNote.fixes) { + if (releaseNote.fixes) { content += `

✓ Fixes

` content += `