mirror of
https://github.com/LemmyNet/joinlemmy-site.git
synced 2024-11-23 21:01:20 +00:00
Generate RSS feed from markdown news (#282)
* generate rss feed from markdown news * Fix comments * also add auto discovery to news sub page, add feed butto next to news title
This commit is contained in:
parent
e83637e1f0
commit
24e1b3e06e
8 changed files with 152 additions and 4 deletions
|
@ -38,6 +38,7 @@ COPY tsconfig.json \
|
||||||
webpack.config.js \
|
webpack.config.js \
|
||||||
.babelrc \
|
.babelrc \
|
||||||
generate_translations.mjs \
|
generate_translations.mjs \
|
||||||
|
generate_rss_feed.mjs \
|
||||||
tailwind.config.js \
|
tailwind.config.js \
|
||||||
./
|
./
|
||||||
|
|
||||||
|
|
63
generate_rss_feed.mjs
Normal file
63
generate_rss_feed.mjs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import fs from "fs-extra";
|
||||||
|
import MarkdownIt from "markdown-it";
|
||||||
|
import { Builder } from "xml2js";
|
||||||
|
|
||||||
|
async function generateRSSFeed() {
|
||||||
|
const md = new MarkdownIt();
|
||||||
|
const posts = [];
|
||||||
|
const files = await fs.readdir("./src/assets/news"); // a folder with markdown files
|
||||||
|
const newestFirstFiles = Array.from(files).reverse();
|
||||||
|
|
||||||
|
for (const file of newestFirstFiles) {
|
||||||
|
if (file.endsWith(".md")) {
|
||||||
|
const content = await fs.readFile(`./src/assets/news/${file}`, "utf8");
|
||||||
|
const lines = content.split("\n");
|
||||||
|
const title = lines[0].replace(/^# /, "");
|
||||||
|
const dateFromFileName = file.slice(0, 10);
|
||||||
|
const date = new Date(dateFromFileName).toUTCString();
|
||||||
|
const htmlContent = md.render(content);
|
||||||
|
const link = `https://join-lemmy.org/news/${file
|
||||||
|
.replace(".md", "")
|
||||||
|
.replaceAll(" ", "_")}`;
|
||||||
|
|
||||||
|
posts.push({ title, date, content: htmlContent, link });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rss = {
|
||||||
|
rss: {
|
||||||
|
$: {
|
||||||
|
version: "2.0",
|
||||||
|
"xmlns:atom": "http://www.w3.org/2005/Atom",
|
||||||
|
},
|
||||||
|
channel: [
|
||||||
|
{
|
||||||
|
"atom:link": {
|
||||||
|
$: {
|
||||||
|
href: "https://join-lemmy.org/feed.xml",
|
||||||
|
rel: "self",
|
||||||
|
type: "application/rss+xml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
title: "join-lemmy.org News",
|
||||||
|
link: "https://join-lemmy.org/",
|
||||||
|
description: "News about Lemmy, a link aggregator for the fediverse.",
|
||||||
|
item: posts.map(post => ({
|
||||||
|
title: post.title,
|
||||||
|
link: post.link,
|
||||||
|
description: post.content,
|
||||||
|
pubDate: post.date,
|
||||||
|
guid: post.link,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const builder = new Builder();
|
||||||
|
const xml = builder.buildObject(rss);
|
||||||
|
|
||||||
|
await fs.writeFile("./dist/feed.xml", xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateRSSFeed().then(() => console.log("RSS feed generated successfully."));
|
|
@ -10,8 +10,9 @@
|
||||||
"crawl": "node crawl.mjs",
|
"crawl": "node crawl.mjs",
|
||||||
"update-donations": "node update_donations.mjs",
|
"update-donations": "node update_donations.mjs",
|
||||||
"lint": "node generate_translations.mjs && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"",
|
"lint": "node generate_translations.mjs && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"",
|
||||||
"prebuild:dev": "yarn clean && node generate_translations.mjs && yarn tailwind",
|
"prebuild:dev": "yarn clean && node generate_translations.mjs && yarn tailwind && yarn generate_rss_feed",
|
||||||
"prebuild:prod": "yarn clean && node generate_translations.mjs && yarn tailwind",
|
"prebuild:prod": "yarn clean && node generate_translations.mjs && yarn tailwind && yarn generate_rss_feed",
|
||||||
|
"generate_rss_feed": "node generate_rss_feed.mjs",
|
||||||
"tailwind": "tailwindcss -i ./src/style.css -o ./dist/styles/styles.css --minify",
|
"tailwind": "tailwindcss -i ./src/style.css -o ./dist/styles/styles.css --minify",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"start": "yarn build:dev --watch & yarn tailwind --watch"
|
"start": "yarn build:dev --watch & yarn tailwind --watch"
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
"countries-list": "^3.0.6",
|
"countries-list": "^3.0.6",
|
||||||
"daisyui": "^3.9.4",
|
"daisyui": "^3.9.4",
|
||||||
"express": "~4.18.2",
|
"express": "~4.18.2",
|
||||||
|
"fs-extra": "^11.2.0",
|
||||||
"i18next": "^23.6.0",
|
"i18next": "^23.6.0",
|
||||||
"inferno": "^8.2.2",
|
"inferno": "^8.2.2",
|
||||||
"inferno-create-element": "^8.2.2",
|
"inferno-create-element": "^8.2.2",
|
||||||
|
@ -50,7 +52,8 @@
|
||||||
"tailwindcss": "^3.3.5",
|
"tailwindcss": "^3.3.5",
|
||||||
"webpack": "5.89.0",
|
"webpack": "5.89.0",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack-node-externals": "^3.0.0"
|
"webpack-node-externals": "^3.0.0",
|
||||||
|
"xml2js": "^0.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/express": "^4.17.20",
|
"@types/express": "^4.17.20",
|
||||||
|
|
17
src/assets/images/rss.svg
Normal file
17
src/assets/images/rss.svg
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 455.731 455.731" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<rect x="0" y="0" style="fill:#F78422;" width="455.731" height="455.731"/>
|
||||||
|
<g>
|
||||||
|
<path style="fill:#FFFFFF;" d="M296.208,159.16C234.445,97.397,152.266,63.382,64.81,63.382v64.348
|
||||||
|
c70.268,0,136.288,27.321,185.898,76.931c49.609,49.61,76.931,115.63,76.931,185.898h64.348
|
||||||
|
C391.986,303.103,357.971,220.923,296.208,159.16z"/>
|
||||||
|
<path style="fill:#FFFFFF;" d="M64.143,172.273v64.348c84.881,0,153.938,69.056,153.938,153.939h64.348
|
||||||
|
C282.429,270.196,184.507,172.273,64.143,172.273z"/>
|
||||||
|
<circle style="fill:#FFFFFF;" cx="109.833" cy="346.26" r="46.088"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 898 B |
|
@ -17,6 +17,7 @@ server.use(express.urlencoded({ extended: false }) as RequestHandler);
|
||||||
server.use("/static", express.static(path.resolve("./dist")));
|
server.use("/static", express.static(path.resolve("./dist")));
|
||||||
server.use("/docs", express.static(path.resolve("./dist/assets/docs")));
|
server.use("/docs", express.static(path.resolve("./dist/assets/docs")));
|
||||||
server.use("/api", express.static(path.resolve("./dist/assets/api")));
|
server.use("/api", express.static(path.resolve("./dist/assets/api")));
|
||||||
|
server.use("/feed.xml", express.static(path.resolve("./dist/feed.xml")));
|
||||||
|
|
||||||
function erudaInit(): string {
|
function erudaInit(): string {
|
||||||
if (process.env["NODE_ENV"] == "development") {
|
if (process.env["NODE_ENV"] == "development") {
|
||||||
|
|
|
@ -490,6 +490,12 @@ export class Main extends Component<Props, State> {
|
||||||
<InstancePicker reset={this.state.resetInstancePicker} />
|
<InstancePicker reset={this.state.resetInstancePicker} />
|
||||||
<Helmet title={title}>
|
<Helmet title={title}>
|
||||||
<meta property={"title"} content={title} />
|
<meta property={"title"} content={title} />
|
||||||
|
<link
|
||||||
|
rel="alternate"
|
||||||
|
type="application/rss+xml"
|
||||||
|
title="RSS Feed for join-lemmy.org"
|
||||||
|
href="/feed.xml"
|
||||||
|
/>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<img
|
<img
|
||||||
src="/static/assets/images/world_background.svg"
|
src="/static/assets/images/world_background.svg"
|
||||||
|
|
|
@ -45,7 +45,12 @@ function previewMarkdown(markdown: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
const TitleBlock = () => (
|
const TitleBlock = () => (
|
||||||
<div className="pt-16 text-center text-4xl font-bold mb-8">{title}</div>
|
<div className="pt-16 text-center text-4xl font-bold mb-8">
|
||||||
|
{title}
|
||||||
|
<a href="/feed.xml" className="ml-4 inline-block">
|
||||||
|
<img src="/static/assets/images/rss.svg" width={24} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const NewsCards = () => buildNewsInfoArray().map(n => <NewsCard news={n} />);
|
const NewsCards = () => buildNewsInfoArray().map(n => <NewsCard news={n} />);
|
||||||
|
@ -99,6 +104,12 @@ export class News extends Component<any, any> {
|
||||||
<div className="container mx-auto px-4">
|
<div className="container mx-auto px-4">
|
||||||
<Helmet title={title}>
|
<Helmet title={title}>
|
||||||
<meta property={"title"} content={title} />
|
<meta property={"title"} content={title} />
|
||||||
|
<link
|
||||||
|
rel="alternate"
|
||||||
|
type="application/rss+xml"
|
||||||
|
title="RSS Feed for join-lemmy.org"
|
||||||
|
href="/feed.xml"
|
||||||
|
/>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<TitleBlock />
|
<TitleBlock />
|
||||||
<NewsCards />
|
<NewsCards />
|
||||||
|
|
46
yarn.lock
46
yarn.lock
|
@ -3949,6 +3949,15 @@ from2@^2.1.0:
|
||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
readable-stream "^2.0.0"
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
fs-extra@^11.2.0:
|
||||||
|
version "11.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b"
|
||||||
|
integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==
|
||||||
|
dependencies:
|
||||||
|
graceful-fs "^4.2.0"
|
||||||
|
jsonfile "^6.0.1"
|
||||||
|
universalify "^2.0.0"
|
||||||
|
|
||||||
fs-minipass@^1.2.7:
|
fs-minipass@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
|
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
|
||||||
|
@ -4236,6 +4245,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
|
||||||
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
|
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
|
||||||
|
|
||||||
|
graceful-fs@^4.2.0:
|
||||||
|
version "4.2.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||||
|
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||||
|
|
||||||
graceful-fs@~4.1.11:
|
graceful-fs@~4.1.11:
|
||||||
version "4.1.15"
|
version "4.1.15"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
||||||
|
@ -5121,6 +5135,15 @@ json5@^2.2.3:
|
||||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||||
|
|
||||||
|
jsonfile@^6.0.1:
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||||
|
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
|
||||||
|
dependencies:
|
||||||
|
universalify "^2.0.0"
|
||||||
|
optionalDependencies:
|
||||||
|
graceful-fs "^4.1.6"
|
||||||
|
|
||||||
jsonparse@^1.2.0:
|
jsonparse@^1.2.0:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
||||||
|
@ -7400,6 +7423,11 @@ sass@^1.69.5:
|
||||||
immutable "^4.0.0"
|
immutable "^4.0.0"
|
||||||
source-map-js ">=0.6.2 <2.0.0"
|
source-map-js ">=0.6.2 <2.0.0"
|
||||||
|
|
||||||
|
sax@>=0.6.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0"
|
||||||
|
integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==
|
||||||
|
|
||||||
schema-utils@^3.1.1:
|
schema-utils@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
|
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
|
||||||
|
@ -8393,6 +8421,11 @@ unique-string@^1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
crypto-random-string "^1.0.0"
|
crypto-random-string "^1.0.0"
|
||||||
|
|
||||||
|
universalify@^2.0.0:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
|
||||||
|
integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==
|
||||||
|
|
||||||
unpipe@1.0.0, unpipe@~1.0.0:
|
unpipe@1.0.0, unpipe@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||||
|
@ -8799,6 +8832,19 @@ xdg-basedir@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
|
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
|
||||||
integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=
|
integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=
|
||||||
|
|
||||||
|
xml2js@^0.6.2:
|
||||||
|
version "0.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499"
|
||||||
|
integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==
|
||||||
|
dependencies:
|
||||||
|
sax ">=0.6.0"
|
||||||
|
xmlbuilder "~11.0.0"
|
||||||
|
|
||||||
|
xmlbuilder@~11.0.0:
|
||||||
|
version "11.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
|
||||||
|
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
|
||||||
|
|
||||||
xtend@~4.0.1:
|
xtend@~4.0.1:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||||
|
|
Loading…
Reference in a new issue