From 55b206d3f2de6a69e3e614207558faa475b0ccf9 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Wed, 12 Jan 2022 02:01:45 +0100 Subject: build(deps): add feed package --- package.json | 1 + yarn.lock | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/package.json b/package.json index f20aa74..927b3a5 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@types/mdx": "^2.0.1", "@types/prismjs": "^1.16.6", "babel-plugin-prismjs": "^2.1.0", + "feed": "^4.2.2", "graphql": "^16.1.0", "graphql-request": "^3.7.0", "modern-normalize": "^1.1.0", diff --git a/yarn.lock b/yarn.lock index 6ca5fd1..1c78c56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4129,6 +4129,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +feed@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e" + integrity sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ== + dependencies: + xml-js "^1.6.11" + figures@^3.0.0, figures@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -7660,6 +7667,11 @@ sass@^1.45.0: immutable "^4.0.0" source-map-js ">=0.6.2 <2.0.0" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + saxes@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" @@ -8912,6 +8924,13 @@ ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== +xml-js@^1.6.11: + version "1.6.11" + resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" + integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== + dependencies: + sax "^1.2.4" + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" -- cgit v1.2.3 From 65a4cb6ce9387c52c4274fddde9320baadbf017f Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Wed, 12 Jan 2022 02:02:54 +0100 Subject: chore: generate feed I could loop until hasNextPage is false, but I'm not sure if it is the best solution. So, for now, only the first 100 posts will be added to the file. --- .env.example | 6 ++++++ src/utils/helpers/rss.ts | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/utils/helpers/rss.ts diff --git a/.env.example b/.env.example index c4ddb0e..efeb49d 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,12 @@ +FRONTEND_URL="https://www.frontend.com" BACKEND_URL="https://www.backend.com" GRAPHQL_ENDPOINT="/graphql" +AUTHOR_NAME="Your Name" +AUTHOR_EMAIL="your@email.com" +AUTHOR_URL="https://www.yourWebsite.com/" +FEED_DESCRIPTION="What you want..." + NEXT_PUBLIC_GRAPHQL_API="$BACKEND_URL$GRAPHQL_ENDPOINT" # Use this only in development mode. It prevents "unable to verify the first diff --git a/src/utils/helpers/rss.ts b/src/utils/helpers/rss.ts new file mode 100644 index 0000000..42560cb --- /dev/null +++ b/src/utils/helpers/rss.ts @@ -0,0 +1,54 @@ +import { config } from '@config/website'; +import { getPublishedPosts } from '@services/graphql/queries'; +import { ArticlePreview } from '@ts/types/articles'; +import { Feed } from 'feed'; +import { writeFileSync } from 'fs'; + +const getAllPosts = async (): Promise => { + const posts: ArticlePreview[] = []; + const postsList = await getPublishedPosts({ first: 100 }); + posts.push(...postsList.posts); + + return posts; +}; + +export const generateFeed = async () => { + const websiteUrl = process.env.FRONTEND_URL ? process.env.FRONTEND_URL : ''; + const author = { + name: config.name, + email: process.env.AUTHOR_EMAIL, + link: websiteUrl, + }; + const copyright = `${config.name} CC BY SA ${config.copyright.startYear} - ${config.copyright.endYear}`; + const title = `${config.name} | ${config.baseline}`; + + const feed = new Feed({ + author, + copyright, + description: process.env.FEED_DESCRIPTION, + feedLinks: { + json: `${websiteUrl}/feed/json`, + atom: `${websiteUrl}/feed/atom`, + }, + generator: 'Feed & NextJS', + id: websiteUrl, + language: config.defaultLocale, + link: websiteUrl, + title, + }); + + const posts = await getAllPosts(); + + posts.forEach((post) => { + feed.addItem({ + content: post.intro, + date: new Date(post.dates.publication), + description: post.intro, + id: post.id, + link: `${websiteUrl}/article/${post.slug}`, + title: post.title, + }); + }); + + writeFileSync('./public/feed.xml', feed.rss2(), 'utf8'); +}; -- cgit v1.2.3 From a32f7b146c216f4159f65d5c0b9a7189d31b2f5a Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 13 Jan 2022 18:15:41 +0100 Subject: chore: add different feed formats (feed.xml, atom.xml, feed.json) --- src/pages/atom.xml.tsx | 20 ++++++++++++++++++++ src/pages/feed.json.tsx | 20 ++++++++++++++++++++ src/pages/feed.xml.tsx | 20 ++++++++++++++++++++ src/utils/helpers/rss.ts | 3 +-- 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/pages/atom.xml.tsx create mode 100644 src/pages/feed.json.tsx create mode 100644 src/pages/feed.xml.tsx diff --git a/src/pages/atom.xml.tsx b/src/pages/atom.xml.tsx new file mode 100644 index 0000000..e6908bd --- /dev/null +++ b/src/pages/atom.xml.tsx @@ -0,0 +1,20 @@ +import { generateFeed } from '@utils/helpers/rss'; +import { GetServerSideProps } from 'next'; + +const Feed = () => null; + +export const getServerSideProps: GetServerSideProps = async ({ res }) => { + const feed = await generateFeed(); + + if (res) { + res.setHeader('Content-Type', 'text/xml'); + res.write(`${feed.atom1()}`); + res.end(); + } + + return { + props: {}, + }; +}; + +export default Feed; diff --git a/src/pages/feed.json.tsx b/src/pages/feed.json.tsx new file mode 100644 index 0000000..e113b46 --- /dev/null +++ b/src/pages/feed.json.tsx @@ -0,0 +1,20 @@ +import { generateFeed } from '@utils/helpers/rss'; +import { GetServerSideProps } from 'next'; + +const Feed = () => null; + +export const getServerSideProps: GetServerSideProps = async ({ res }) => { + const feed = await generateFeed(); + + if (res) { + res.setHeader('Content-Type', 'application/json'); + res.write(`${feed.json1()}`); + res.end(); + } + + return { + props: {}, + }; +}; + +export default Feed; diff --git a/src/pages/feed.xml.tsx b/src/pages/feed.xml.tsx new file mode 100644 index 0000000..093cab8 --- /dev/null +++ b/src/pages/feed.xml.tsx @@ -0,0 +1,20 @@ +import { generateFeed } from '@utils/helpers/rss'; +import { GetServerSideProps } from 'next'; + +const Feed = () => null; + +export const getServerSideProps: GetServerSideProps = async ({ res }) => { + const feed = await generateFeed(); + + if (res) { + res.setHeader('Content-Type', 'text/xml'); + res.write(`${feed.rss2()}`); + res.end(); + } + + return { + props: {}, + }; +}; + +export default Feed; diff --git a/src/utils/helpers/rss.ts b/src/utils/helpers/rss.ts index 42560cb..3e7258a 100644 --- a/src/utils/helpers/rss.ts +++ b/src/utils/helpers/rss.ts @@ -2,7 +2,6 @@ import { config } from '@config/website'; import { getPublishedPosts } from '@services/graphql/queries'; import { ArticlePreview } from '@ts/types/articles'; import { Feed } from 'feed'; -import { writeFileSync } from 'fs'; const getAllPosts = async (): Promise => { const posts: ArticlePreview[] = []; @@ -50,5 +49,5 @@ export const generateFeed = async () => { }); }); - writeFileSync('./public/feed.xml', feed.rss2(), 'utf8'); + return feed; }; -- cgit v1.2.3 From 553225bac64f762ce0a9ac5094ce6e3348f88f41 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 13 Jan 2022 18:23:01 +0100 Subject: chore: add feed formats to document head --- src/components/Layouts/Layout.tsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/components/Layouts/Layout.tsx b/src/components/Layouts/Layout.tsx index 35e7d27..8a57cf6 100644 --- a/src/components/Layouts/Layout.tsx +++ b/src/components/Layouts/Layout.tsx @@ -4,6 +4,8 @@ import Header from '@components/Header/Header'; import Main from '@components/Main/Main'; import Breadcrumb from '@components/Breadcrumb/Breadcrumb'; import { t } from '@lingui/macro'; +import Head from 'next/head'; +import { config } from '@config/website'; const Layout = ({ children, @@ -14,6 +16,26 @@ const Layout = ({ }) => { return ( <> + + + + + {t`Skip to content`}
{children}
-- cgit v1.2.3 From 295c9b4bb33bfc21f12715bb9cdaed2ca4d1dd4d Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 13 Jan 2022 18:23:35 +0100 Subject: chore: add a redirection from /feed to /feed.xml --- next.config.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/next.config.js b/next.config.js index 25db587..59ca4f4 100644 --- a/next.config.js +++ b/next.config.js @@ -14,6 +14,14 @@ const nextConfig = { }, poweredByHeader: false, reactStrictMode: true, + async rewrites() { + return [ + { + source: '/feed', + destination: '/feed.xml', + }, + ]; + }, sassOptions: { includePaths: [ path.join(__dirname, 'styles'), -- cgit v1.2.3 From 320b5782f348d42f6a2bb74a70d4d114525355e4 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 13 Jan 2022 18:34:27 +0100 Subject: chore: add all posts from CMS to feed --- src/utils/helpers/rss.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/utils/helpers/rss.ts b/src/utils/helpers/rss.ts index 3e7258a..7851ff8 100644 --- a/src/utils/helpers/rss.ts +++ b/src/utils/helpers/rss.ts @@ -1,12 +1,20 @@ import { config } from '@config/website'; import { getPublishedPosts } from '@services/graphql/queries'; import { ArticlePreview } from '@ts/types/articles'; +import { PostsList } from '@ts/types/blog'; import { Feed } from 'feed'; const getAllPosts = async (): Promise => { const posts: ArticlePreview[] = []; - const postsList = await getPublishedPosts({ first: 100 }); - posts.push(...postsList.posts); + let hasNextPage = true; + let after = undefined; + + do { + const postsList: PostsList = await getPublishedPosts({ first: 10, after }); + posts.push(...postsList.posts); + hasNextPage = postsList.pageInfo.hasNextPage; + after = postsList.pageInfo.endCursor; + } while (hasNextPage); return posts; }; -- cgit v1.2.3