Merge branch 'blog-feed' into 'main'

Blog feed

See merge request PronounsPage/PronounsPage!484
This commit is contained in:
Andrea Vos 2024-06-18 16:22:06 +00:00
commit fdb628cebc
6 changed files with 84 additions and 4 deletions

49
middleware/atom.js Normal file
View File

@ -0,0 +1,49 @@
import { Feed } from 'feed';
import parseMarkdown from '../src/parseMarkdown.js';
import fetch from 'node-fetch';
export default async function ({ app, route, res }) {
if (!process.server || route.path !== '/blog.atom') {
return;
}
const posts = await (await fetch(`${process.env.BASE_URL}/api/blog`)).json();
const feed = new Feed({
title: `${app.$t('title')}${app.$t('links.blog')}`,
description: app.$t('description'),
id: process.env.BASE_URL,
link: `${process.env.BASE_URL}/blog.atom`,
language: app.$config.locale,
image: `${process.env.BASE_URL}/icon.png`,
favicon: `${process.env.BASE_URL}/icon.png`,
updated: new Date(posts[0].date),
});
for (const post of posts) {
const parsed = await parseMarkdown(
(await import(`../locale/${app.$config.locale}/blog/${post.slug}.md`)).default,
app.$translator,
);
feed.addItem({
title: post.title,
id: `${process.env.BASE_URL}/${app.$config.links.blogRoute}/${post.slug}`,
link: `${process.env.BASE_URL}/${app.$config.links.blogRoute}/${post.slug}`,
description: parsed.intro,
content: parsed.content,
author: post.authors.map((author) => ({
name: author,
link: author.startsWith('@') ? `${process.env.BASE_URL}/${author}` : undefined,
})),
date: new Date(post.date),
image: post.hero ? `${process.env.BASE_URL}${post.hero}` : undefined,
});
}
res.setHeader('Content-Type', 'application/rss+xml; charset=utf-8');
res.end(feed.atom1());
return new Promise(() => {}); // halt execution
}

View File

@ -628,6 +628,7 @@ const nuxtConfig: NuxtConfig = {
routes.push({ name: 'all', path: '*', component: resolve(__dirname, 'routes/pronoun.vue') });
},
middleware: 'atom',
},
hooks: {
render: {

View File

@ -37,6 +37,7 @@
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-session": "^1.17.1",
"feed": "^4.2.2",
"generic-diff": "^1.0.1",
"grant": "^5.4.22",
"he-date": "^1.2.2",

21
pnpm-lock.yaml generated
View File

@ -74,6 +74,9 @@ dependencies:
express-session:
specifier: ^1.17.1
version: 1.17.3
feed:
specifier: ^4.2.2
version: 4.2.2
generic-diff:
specifier: ^1.0.1
version: 1.0.1
@ -8955,6 +8958,13 @@ packages:
pend: 1.2.0
dev: false
/feed@4.2.2:
resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==}
engines: {node: '>=0.4.0'}
dependencies:
xml-js: 1.6.11
dev: false
/figgy-pudding@3.5.2:
resolution: {integrity: sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==}
deprecated: This module is no longer supported.
@ -14867,6 +14877,10 @@ packages:
chokidar: 3.5.3
dev: true
/sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
dev: false
/saxes@6.0.0:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'}
@ -17116,6 +17130,13 @@ packages:
utf-8-validate:
optional: true
/xml-js@1.6.11:
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
hasBin: true
dependencies:
sax: 1.4.1
dev: false
/xml-name-validator@4.0.0:
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
engines: {node: '>=12'}

View File

@ -1,8 +1,16 @@
<template>
<Page>
<h2>
<h2 class="d-flex justify-content-between">
<span>
<Icon v="pen-nib" />
<T>links.blog</T>
</span>
<span>
<a href="/blog.atom" target="_blank" rel="noopener" class="btn btn-sm btn-outline-primary">
<Icon v="rss" />
Feed
</a>
</span>
</h2>
<AdPlaceholder :phkey="['content-0', 'content-mobile-0']" />
<BlogEntriesList :posts="posts" details />

View File

@ -16,7 +16,7 @@ const isBrowser = (userAgent: string | undefined): boolean => {
};
export default function (req: Request, res: Response, next: NextFunction): void {
if (process.env.NODE_ENV === 'production' && !req.url.startsWith('/card/@')) {
if (process.env.NODE_ENV === 'production' && !req.url.startsWith('/card/@') && !req.url.startsWith('/blog.atom')) {
res.spa = isBrowser(req.headers['user-agent']) || isHighLoadTime(global.config.locale);
}
next();