Generate RSS from Markdown

· klm's blog


Original post is here: eklausmeier.goip.de

For this blog I wanted an RSS feed. Saaze does not provide this functionality. Saaze is supposed to be "stupidly simple" by design, which I consider a plus. Since 15-Aug-2022 Simplified Saaze can generate a RSS XML feed. Simplified Saaze, so to speak, is the successor of Saaze.

This post shows how you can generate an RSS feed without Simplified Saaze, but using just plain Perl.

Generating an RSS feed is simple. It contains a header with some fixed XML. Then each post is printed as so called "item" with

  1. link / URL
  2. publication date
  3. title
  4. an excerpt or even the full blog post

Finally the required closing XML tags. That's it.

Taking this information directly from Markdown file with some frontmatter seems to be the easiest approach. For example, the frontmatter for this blog post is:

1---
2date: "2021-05-30 20:00:00"
3title: "Generate RSS from Markdown"
4draft: false
5categories: ["www"]
6tags: ["RSS", "feed", "Markdown"]
7author: "Elmar Klausmeier"
8prismjs: true
9---

Below Perl script mkdwnrss implements this. As input files it wants those blog posts which should be part of the RSS feed. So usually you will "generate" the list of files. Implementing this in PHP would be equally simple.

The excerpt is restricted to either 9 lines of Markdown or less than 500 characters.

 1#!/bin/perl -W
 2# Create RSS XML file ("feed") based on Markdown files
 3#
 4# Input: List of Markdown files (order of files determines order of <item>))
 5# Output: RSS (description with 3 lines of Markdown as excerpt)
 6#
 7# Example:
 8#      mkdwnrss `find blog/2021 -type f | sort -r`
 9
10use strict;
11
12my $dt = localtime();
13print <<"EOT";
14<?xml version="1.0" encoding="utf-8"?>
15<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
16<channel>
17	<title>Elmar Klausmeier's Blog</title>
18	<description>Elmar Klausmeier's Blog</description>
19	<lastBuildDate>$dt</lastBuildDate>
20	<link>https://eklausmeier.goip.de</link>
21	<atom:link href="https://eklausmeier.goip.de/feed.xml" rel="self" type="application/rss+xml" />
22	<generator>mkdwnrss</generator>
23
24EOT
25
26
27sub item(@) {
28	my $f = $_[0];
29	open(F,"< $f") || die("Cannot open $f");
30
31	my $link = $f;
32	$link =~ s/\.md$/\//;
33	print "\t<item>\n"
34	. "\t\t<link>https://eklausmeier.goip.de/$link</link>\n"
35	. "\t\t<guid>https://eklausmeier.goip.de/$link</guid>\n";
36
37	my ($sep,$linecnt,$excerpt) = (0,0,"");
38	while (<F>) {
39		chomp;
40		if (/^\-\-\-$/) { $sep++ ; next; }
41		if ($sep == 1) {
42			if (/^title:\s+"(.+)"$/) {
43				printf("\t\t<title>%s</title>\n",$1);
44			} elsif (/^date:\s+"(.+)"$/) {
45				printf("\t\t<pubDate>%s</pubDate>\n",$1);
46			}
47		} elsif ($sep >= 2) {
48			next if (length($_) == 0);
49			if ($linecnt++ == 0) {
50				print "\t\t<description><![CDATA[";
51				$excerpt = $_;
52			} elsif ($linecnt < 9 || length($excerpt) < 500) {
53				$excerpt .= " " . $_;
54			} else {
55				last;
56			}
57		}
58	}
59	print $excerpt . "]]></description>\n" if ($linecnt > 0);
60	print "\t</item>\n";
61
62	close(F) || die("Cannot close $f");
63}
64
65
66while (<@ARGV>) {
67	item($_);
68}
69
70
71print "</channel>\n</rss>\n";

Source code for mkdwnrss is in GitHub.

During development I checked whether my RSS looks similar to the RSS feed in WordPress: feed. I also checked Alex Le's blog post on RSS feed: Create An RSS Feed From Scratch.

Added 08-Jul-2021: When checking the RSS in W3C Feed Validation Service the dates and descriptions were marked as non-compliant. This is now corrected. Checking now gives: Valid RSS

Added 17-Jan-2022: Also see Generate RSS from HTML.

Added 15-Aug-2022: Since today Simplified Saaze can generate RSS directly with the -r flag. The PHP code used in that is described here: RSS XML Feed.