Generating a list of posts for my blog

2020-11-17 00:00

Post overview

I just finished something that past-me would have had a really hard time with. It felt like some kind of programming koan for me, as I’m just a hobbyist programmer, but regardless, these little victories make me happy.

I wrote a little script to generate a list of blog posts, which I used to write by hand. You can see the result by viewing my posts page, which is underwhelming, but that all used to be written by hand, and now it’s automated!

I figured, when my blog posts end up getting to a number that is unmanageable by hand, I should make my computer do the work!

Okay, that’s not the reason why. I just wanted a little programming project, and writing short programming projects is totally what I love doing.

About the script

The script just recursively goes through my convert/posts/ directory, and looks for files that end with an .md suffix that aren’t index.md, because that’s the file to be generated or an old version of a previously generated file, or in this case, it was my original hand-written file.

Retrieving necessary data from Markdown files

The script has a function that opens up files to find the title, date, and link. The title is retrieved from the first line, which looks something like # Hey, I'm a title. The date is retrieved from the third line, which looks something like Date published: 2020-11-21. The link to the file is retrieved from the recursively constructed path, which looks something like convert/posts/2020/hey-im-a-blog-post.md.

The title, date, and link are then stripped as follows:

Plopping it all into a data format

All of this is then mushed into a key-value table that looks similar to the one below:

{:date "2020-11-20"
 :title "Title of the post"
 :link "/posts/2020/some-blog-post.md"}

Another function, uses the function above to construct another table using a loop. It recursively finds all files, scoops up the title, date, and link using the function above, and then creates an unordered list of date keys and Markdown link values, which look something like the following table:

{:2020-11-21 "[Title of the post](/posts/2020/title-of-the-post.md)"
 :2017-11-20 "[Another title](/posts/2017/another-title.md)"
 :2017-11-21 "[And yet another one](/posts/2017/and-yet-another-one.md)"
 :2018-11-20 "[Running out of ideas](/posts/2018/running-out-of-ideas.md)"
 :2019-11-20 "[Um](/posts/2019/um.md)"
 :2020-11-22 "[Yep](/posts/2020/yep.md)"
 :2020-11-23 "[Some title](/posts/2020/some-title.md)"}

Sorting the data

A sorting function takes this table, reverse sorts it by keys to create a table that looks something like the following table:

{:2020-11-23 "[Some title](/posts/2020/some-title.md)"
 :2020-11-22 "[Yep](/posts/2020/yep.md)"
 :2020-11-21 "[Title of the post](/posts/2020/title-of-the-post.md)"
 :2019-11-20 "[Um](/posts/2019/um.md)"
 :2018-11-20 "[Running out of ideas](/posts/2018/running-out-of-ideas.md)"
 :2017-11-21 "[And yet another one](/posts/2017/and-yet-another-one.md)"
 :2017-11-20 "[Another title](/posts/2017/another-title.md)"}

The sorting function then uses the ordered keys from this table as keys for the originally unsorted table, so it calls them in order. I had to use keys from the sorted table as keys for the unsorted table just because I couldn’t figure out how to do this any other way. It might be a Lua thing? Haha. Well, I’m working in Fennel, but same same, they are interoperable haha.

The fancy (awful?) sorting function looks like the one below:

(fn write-sorted-posts [tbl]
  (let [key-seq []]
   ;; Create a seq of keys from tbl
   (each [k _ (pairs tbl)]
     (table.insert key-seq k))

   ;; Sort the keys from small to big
   (table.sort key-seq)

   ;; Start from the end (length of) seq-of-keys
   ;; End on 1 (Starting of index)
   ;; Step by -1
   (for [i (# key-seq) 1 -1]
     (let [date (. key-seq i)
           post (. tbl date)]
       (file-write destination post :a)))))

Thou shalt order thy file writing

To create a header for this file, I just write to the file first, before any of that fancy parsing, and then use an append mode when writing the posts to the file. The initial writing of the title for the index.md wipes outdated index.md and starts over.

Back to RSS-generator programming…

Before, I was recursively doing the same thing to generate an RSS feed, but the feed wasn’t ordered, because, I figured “Hey, RSS feed readers will order this all for me! I’m not gonna bother ordering it!”, but then I figured (I say figured a lot, don’t I?) I should just use the same sorting trick to reverse sort my RSS feed as well, so that happened!

Getting meta

Okay, so, the ultimate test! Let’s see if this post is picked up and added to my posts page. I’ll add a line below this to let you know if it did the first time!

Edit: It worked!