From f8572d0b47194ece750d04917a5127baec0d9ed2 Mon Sep 17 00:00:00 2001 From: taskylizard <75871323+taskylizard@users.noreply.github.com> Date: Sun, 31 Dec 2023 11:15:48 +0000 Subject: [PATCH] rss feed --- .vitepress/config.mts | 7 ++++-- .vitepress/constants.ts | 2 +- .vitepress/hooks/index.ts | 2 ++ .vitepress/hooks/opengraph.ts | 4 +++- .vitepress/hooks/rss.ts | 42 ++++++++++++++++++++++++++++++++++ .vitepress/rss.ts | 39 ------------------------------- .vitepress/theme/Posts.vue | 27 ++++++++++++++++++++++ package.json | 3 ++- pnpm-lock.yaml | 43 +++++++++++++++++------------------ 9 files changed, 103 insertions(+), 66 deletions(-) create mode 100644 .vitepress/hooks/rss.ts delete mode 100644 .vitepress/rss.ts diff --git a/.vitepress/config.mts b/.vitepress/config.mts index d01d01f21..adcb05ae4 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -1,8 +1,9 @@ import { defineConfig } from "vitepress"; import UnoCSS from "unocss/vite"; import { presetUno, presetAttributify, presetIcons } from "unocss"; +import consola from "consola"; import { commitRef, feedback, meta, socials } from "./constants"; -import { generateImages, generateMeta } from "./hooks"; +import { generateImages, generateMeta, generateFeed } from "./hooks"; import { toggleStarredPlugin } from "./markdown/toggleStarred"; import { base64DecodePlugin } from "./markdown/base64"; @@ -35,7 +36,9 @@ export default defineConfig({ ], transformHead: async (context) => generateMeta(context, meta.hostname), buildEnd: async (context) => { - generateImages(context); + generateImages(context) + .then(() => generateFeed(context)) + .finally(() => consola.success("Success!")); }, vite: { plugins: [ diff --git a/.vitepress/constants.ts b/.vitepress/constants.ts index f2a1cedd4..8fac62b8d 100644 --- a/.vitepress/constants.ts +++ b/.vitepress/constants.ts @@ -3,7 +3,7 @@ import type { DefaultTheme } from "vitepress"; export const meta = { name: "FreeMediaHeckYeah", description: "The largest collection of free stuff on the internet!", - hostname: "https://fmhy.pages.dev", + hostname: "https://fmhy.net", keywords: ["stream", "movies", "gaming", "reading", "anime"], }; diff --git a/.vitepress/hooks/index.ts b/.vitepress/hooks/index.ts index c107def90..029a1996e 100644 --- a/.vitepress/hooks/index.ts +++ b/.vitepress/hooks/index.ts @@ -4,3 +4,5 @@ export * from "./meta"; export * from "./opengraph"; +export * from "./rss"; +export * from "./satoriConfig"; diff --git a/.vitepress/hooks/opengraph.ts b/.vitepress/hooks/opengraph.ts index 3ce54d47f..e6424a6dd 100644 --- a/.vitepress/hooks/opengraph.ts +++ b/.vitepress/hooks/opengraph.ts @@ -5,6 +5,7 @@ import { createContentLoader } from "vitepress"; import type { ContentData, SiteConfig } from "vitepress"; import { type SatoriOptions, satoriVue } from "x-satori/vue"; import { renderAsync } from "@resvg/resvg-js"; +import consola from "consola"; const __dirname = dirname(fileURLToPath(import.meta.url)); const __fonts = resolve(__dirname, "../fonts"); @@ -48,6 +49,7 @@ export async function generateImages(config: SiteConfig): Promise { fonts, }); } + return consola.info("Generated opengraph images."); } interface GenerateImagesOptions { @@ -90,5 +92,5 @@ async function generateImage({ await mkdir(outputFolder, { recursive: true }); - return await writeFile(outputFile, render.asPng()); + await writeFile(outputFile, render.asPng()); } diff --git a/.vitepress/hooks/rss.ts b/.vitepress/hooks/rss.ts new file mode 100644 index 000000000..671b943c1 --- /dev/null +++ b/.vitepress/hooks/rss.ts @@ -0,0 +1,42 @@ +import path from "node:path"; +import { writeFileSync } from "node:fs"; +import { Feed } from "feed"; +import { createContentLoader, type ContentData, type SiteConfig } from "vitepress"; +import consola from "consola"; +import { meta } from "../constants"; + +export async function generateFeed(config: SiteConfig): Promise { + const feed: Feed = new Feed({ + id: meta.hostname, + link: meta.hostname, + title: `FMHY blog`, + description: meta.description, + language: "en-US", + image: "https://github.com/fmhy.png", + favicon: `${meta.hostname}/favicon.ico`, + copyright: `Copyright (c) 2023-present FMHY`, + }); + + const posts: ContentData[] = await createContentLoader("posts/*.md", { + excerpt: true, + render: true, + transform: (rawData) => { + return rawData.sort((a, b) => { + return Number(new Date(b.frontmatter.date)) - Number(new Date(a.frontmatter.date)); + }); + }, + }).load(); + + for (const { url, frontmatter, html } of posts) { + feed.addItem({ + title: frontmatter.title as string, + id: `${meta.hostname}${url.replace(/\/\d+\./, "/")}`, + link: `${meta.hostname}${url.replace(/\/\d+\./, "/")}`, + date: frontmatter.date, + content: html!, + }); + } + + writeFileSync(path.join(config.outDir, "feed.rss"), feed.rss2()); + return consola.info("Generated rss feed."); +} diff --git a/.vitepress/rss.ts b/.vitepress/rss.ts deleted file mode 100644 index d013d7011..000000000 --- a/.vitepress/rss.ts +++ /dev/null @@ -1,39 +0,0 @@ -import path from "path"; -import { writeFileSync } from "fs"; -import { Feed } from "feed"; -import { createContentLoader, type SiteConfig } from "vitepress"; -import { meta } from "./constants"; - -export async function genFeed(config: SiteConfig) { - const feed = new Feed({ - title: "FMHY • Monthy Posts", - description: meta.description, - id: meta.hostname, - link: meta.hostname, - language: "en", - image: "https://github.com/fmhy.png", - copyright: "", - }); - - const posts = await createContentLoader("posts/**/*.md", { - excerpt: true, - render: true, - }).load(); - - posts.sort( - (a, b) => +new Date(b.frontmatter.date as string) - +new Date(a.frontmatter.date as string), - ); - - for (const { url, excerpt, frontmatter, html } of posts) { - feed.addItem({ - title: frontmatter.title, - id: `${meta.hostname}${url}`, - link: `${meta.hostname}${url.split("/posts")[1]}`, - description: excerpt, - content: html, - date: frontmatter.date, - }); - } - - writeFileSync(path.join(config.outDir, "feed.rss"), feed.rss2()); -} diff --git a/.vitepress/theme/Posts.vue b/.vitepress/theme/Posts.vue index f1c915d5c..c8f87ad05 100644 --- a/.vitepress/theme/Posts.vue +++ b/.vitepress/theme/Posts.vue @@ -16,6 +16,12 @@ const formatDate = (raw: string): string => {

Posts

Everything from Monthly Updates to fmhy updates.

+ + We also have a + +
+ + diff --git a/package.json b/package.json index 4b0cf577f..76d9e22d4 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,14 @@ "api:build": "nitropack build", "api:preview": "node .output/server/index.mjs", "og:dev": "x-satori -t ./.vitepress/hooks/Template.vue -c ./.vitepress/hooks/satoriConfig.ts --dev", - "format": "prettier -w --cache .", + "format": "prettier -w --cache --check .", "lint": "eslint .vitepress -f pretty --cache", "postinstall": "nitropack prepare" }, "dependencies": { "@headlessui/vue": "^1.7.16", "@resvg/resvg-js": "^2.6.0", + "consola": "^3.2.3", "feed": "^4.2.2", "fs-extra": "^11.2.0", "itty-fetcher": "^0.9.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0cf03c3fa..a4bce387f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ dependencies: '@resvg/resvg-js': specifier: ^2.6.0 version: 2.6.0 + consola: + specifier: ^3.2.3 + version: 3.2.3 feed: specifier: ^4.2.2 version: 4.2.2 @@ -37,7 +40,7 @@ dependencies: version: 0.57.1(postcss@8.4.32)(vite@4.5.1) vitepress: specifier: npm:@taskylizard/vitepress@1.0.4 - version: /@taskylizard/vitepress@1.0.4(@types/node@20.8.9)(nprogress@0.2.0)(postcss@8.4.32)(search-insights@2.13.0)(typescript@5.3.3) + version: /@taskylizard/vitepress@1.0.4(@algolia/client-search@4.20.0)(@types/node@20.8.9)(nprogress@0.2.0)(postcss@8.4.32)(search-insights@2.13.0)(typescript@5.3.3) vue: specifier: ^3.3.7 version: 3.3.7(typescript@5.3.3) @@ -81,51 +84,47 @@ packages: engines: {node: '>=0.10.0'} dev: true - /@algolia/autocomplete-core@1.9.3(algoliasearch@4.20.0)(search-insights@2.13.0): + /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.13.0): resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(algoliasearch@4.20.0)(search-insights@2.13.0) - '@algolia/autocomplete-shared': 1.9.3(algoliasearch@4.20.0) + '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.13.0) + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - search-insights dev: false - /@algolia/autocomplete-plugin-algolia-insights@1.9.3(algoliasearch@4.20.0)(search-insights@2.13.0): + /@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.13.0): resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} peerDependencies: search-insights: '>= 1 < 3' dependencies: - '@algolia/autocomplete-shared': 1.9.3(algoliasearch@4.20.0) + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) search-insights: 2.13.0 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch dev: false - /@algolia/autocomplete-preset-algolia@1.9.3(algoliasearch@4.20.0): + /@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0): resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - peerDependenciesMeta: - '@algolia/client-search': - optional: true dependencies: - '@algolia/autocomplete-shared': 1.9.3(algoliasearch@4.20.0) + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) + '@algolia/client-search': 4.20.0 algoliasearch: 4.20.0 dev: false - /@algolia/autocomplete-shared@1.9.3(algoliasearch@4.20.0): + /@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0): resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - peerDependenciesMeta: - '@algolia/client-search': - optional: true dependencies: + '@algolia/client-search': 4.20.0 algoliasearch: 4.20.0 dev: false @@ -453,10 +452,10 @@ packages: resolution: {integrity: sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==} dev: false - /@docsearch/js@3.5.2(search-insights@2.13.0): + /@docsearch/js@3.5.2(@algolia/client-search@4.20.0)(search-insights@2.13.0): resolution: {integrity: sha512-p1YFTCDflk8ieHgFJYfmyHBki1D61+U9idwrLh+GQQMrBSP3DLGKpy0XUJtPjAOPltcVbqsTjiPFfH7JImjUNg==} dependencies: - '@docsearch/react': 3.5.2(search-insights@2.13.0) + '@docsearch/react': 3.5.2(@algolia/client-search@4.20.0)(search-insights@2.13.0) preact: 10.18.1 transitivePeerDependencies: - '@algolia/client-search' @@ -466,7 +465,7 @@ packages: - search-insights dev: false - /@docsearch/react@3.5.2(search-insights@2.13.0): + /@docsearch/react@3.5.2(@algolia/client-search@4.20.0)(search-insights@2.13.0): resolution: {integrity: sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' @@ -483,8 +482,8 @@ packages: search-insights: optional: true dependencies: - '@algolia/autocomplete-core': 1.9.3(algoliasearch@4.20.0)(search-insights@2.13.0) - '@algolia/autocomplete-preset-algolia': 1.9.3(algoliasearch@4.20.0) + '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.13.0) + '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) '@docsearch/css': 3.5.2 algoliasearch: 4.20.0 search-insights: 2.13.0 @@ -1723,7 +1722,7 @@ packages: - supports-color dev: true - /@taskylizard/vitepress@1.0.4(@types/node@20.8.9)(nprogress@0.2.0)(postcss@8.4.32)(search-insights@2.13.0)(typescript@5.3.3): + /@taskylizard/vitepress@1.0.4(@algolia/client-search@4.20.0)(@types/node@20.8.9)(nprogress@0.2.0)(postcss@8.4.32)(search-insights@2.13.0)(typescript@5.3.3): resolution: {integrity: sha512-sYoG2KEvIVE3na69TyUbLs91/0AO7geVmlev4AaxGNqZPEqXBz1otKbtMLVMkBr9oOZH3YreRZ4Lb5VSWueXWQ==} hasBin: true peerDependencies: @@ -1736,7 +1735,7 @@ packages: optional: true dependencies: '@docsearch/css': 3.5.2 - '@docsearch/js': 3.5.2(search-insights@2.13.0) + '@docsearch/js': 3.5.2(@algolia/client-search@4.20.0)(search-insights@2.13.0) '@types/markdown-it': 13.0.7 '@vitejs/plugin-vue': 5.0.2(vite@5.0.10)(vue@3.4.3) '@vue/devtools-api': 6.5.1