Skip to content

Instantly share code, notes, and snippets.

@arkandas
Created July 25, 2024 18:43
Show Gist options
  • Save arkandas/3fd4d23e33c8bc87c9ef76ba50578173 to your computer and use it in GitHub Desktop.
Save arkandas/3fd4d23e33c8bc87c9ef76ba50578173 to your computer and use it in GitHub Desktop.
RSS Feed Generator
import fs from "fs-extra";
import xml from "xml";
import { load } from "cheerio";
import xmlFormat from "xml-formatter";
import { marked } from "marked";
import { POSTLIST } from "./post-list.js";
const blogUrl: string = "https://arkandas.com/";
const feedName: string = "feed.rss";
(async function createRssFeed() {
console.log("creating feed");
const feedObject = {
rss: [
{
_attr: {
version: "2.0",
"xmlns:content": "http://purl.org/rss/1.0/modules/content/",
"xmlns:webfeeds": "http://webfeeds.org/rss/1.0",
"xmlns:wfw": "http://wellformedweb.org/CommentAPI/",
"xmlns:dc": "http://purl.org/dc/elements/1.1/",
"xmlns:atom": "http://www.w3.org/2005/Atom",
"xmlns:sy": "http://purl.org/rss/1.0/modules/syndication/",
"xmlns:slash": "http://purl.org/rss/1.0/modules/slash/",
},
},
{
channel: [
{
title: "Arkandas",
},
{
"atom:link": {
_attr: {
href: blogUrl + "rss/" + feedName,
rel: "self",
type: "application/rss+xml",
},
},
},
{
link: blogUrl,
},
{ description: "Electronics, Programming and Ideas" },
{ lastBuildDate: new Date().toUTCString() },
{ "webfeeds:icon": blogUrl + "logo.svg" },
{
"webfeeds:cover": {
_attr: {
image: blogUrl + "cover.png",
},
},
},
{ "webfeeds:logo": blogUrl + "logo.svg" },
{ "webfeeds:accentColor": "#FFA45A" },
{ language: "en-US" },
{ generator: "arkandas rss-generator" },
{
image: [
{
url: blogUrl + "icons/" + "favicon-32.png",
},
{
title: "Arkandas",
},
{
link: blogUrl,
},
{
width: "32",
},
{
height: "32",
},
],
},
{
copyright: "All rights reserved 2024, Arkandas",
},
...generateFeedItems(POSTLIST),
],
},
],
};
const feed = '<?xml version="1.0" encoding="UTF-8"?>' + xml(feedObject);
await fs.writeFile(
"../public/rss/" + feedName,
xmlFormat(feed, { collapseContent: true }),
"utf8"
);
})();
function generateFeedItems(
posts: {
id: any;
permalink: any;
author: any;
title: any;
summary: any;
content: any;
banner: any;
miniature: any;
card: any;
date: any;
isPrivate: any;
categories: any[];
}[]
) {
const publicPosts = posts.filter(function (post) {
return !post.isPrivate;
});
const sortedPosts = publicPosts.sort(function (first, second) {
return new Date(second.date).getTime() - new Date(first.date).getTime();
});
const feedItems: any[] = [];
feedItems.push(
...sortedPosts.map(function (post) {
let postContent = fs
.readFileSync("../public/" + post.content, "utf8")
.toString()
.replaceAll("posts/", blogUrl + "posts/");
let categories: any[] = post.categories.map(function (category) {
return { category: { _cdata: category } };
});
const feedItem = {
item: [
{ title: post.title },
{ link: blogUrl + "blog/" + post.permalink + "/" },
{
"dc:creator": {
_cdata: "Arkandas",
},
},
{
pubDate: new Date(post.date as string).toUTCString(),
},
...categories,
{
guid: [
{ _attr: { isPermaLink: true } },
blogUrl + "blog/" + post.permalink + "/",
],
},
{
description: {
_cdata: post.summary,
},
},
{
"content:encoded": {
_cdata:
'<img src="' +
blogUrl +
post.card +
'" alt="' +
post.permalink +
" card" +
'" class="webfeedsFeaturedVisual" width="1200" height="630">' +
load(parsePostContent(postContent), { xmlMode: true }).html() +
'<p><a href="https://arkandas.com/blog/' +
post.permalink +
'/">🌐 Read more</a></p>',
},
},
{
enclosure: [
{
_attr: {
length: getImageSizeInBytes("../public/" + post.card),
},
},
{ _attr: { type: "image/png" } },
{ _attr: { url: blogUrl + post.card } },
],
},
],
};
return feedItem;
})
);
return feedItems;
}
function parsePostContent(postContent: string) {
return marked.parse(postContent.slice(0, 2500) + "...", {
async: false,
}) as string;
}
function getImageSizeInBytes(path: string) {
let stats = fs.statSync(path);
return stats.size;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment