git.m455.casa

m455.casa

clone url: git://git.m455.casa/m455.casa


html/posts/generating-a-list-of-posts-for-my-blog.html

1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
3 <head>
4 <meta charset="utf-8" />
5 <meta name="generator" content="pandoc" />
6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
7 <title>Generating a list of posts for my blog</title>
8 <style>
9 code{white-space: pre-wrap;}
10 span.smallcaps{font-variant: small-caps;}
11 span.underline{text-decoration: underline;}
12 div.column{display: inline-block; vertical-align: top; width: 50%;}
13 div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
14 ul.task-list{list-style: none;}
15 </style>
16 <link rel="stylesheet" href="/assets/archive.css">
17 </head>
18 <body>
19 <main>
20 <h2 id="generating-a-list-of-posts-for-my-blog">Generating a list of posts for my blog</h2>
21 <p>2020-11-17 00:00</p>
22 <h3 id="post-overview">Post overview</h3>
23 <!-- vim-markdown-toc GFM -->
24 <ul>
25 <li><a href="#about-the-script">About the script</a></li>
26 <li><a href="#retrieving-necessary-data-from-markdown-files">Retrieving necessary data from Markdown files</a></li>
27 <li><a href="#plopping-it-all-into-a-data-format">Plopping it all into a data format</a></li>
28 <li><a href="#sorting-the-data">Sorting the data</a></li>
29 <li><a href="#thou-shalt-order-thy-file-writing">Thou shalt order thy file writing</a></li>
30 <li><a href="#back-to-rss-generator-programming">Back to RSS-generator programming…</a></li>
31 <li><a href="#getting-meta">Getting meta</a></li>
32 </ul>
33 <!-- vim-markdown-toc -->
34 <p>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.</p>
35 <p>I wrote a little script to generate a list of blog posts, which I used to
36 write by hand. You can see the result by viewing <a href="/archive/">my posts page</a>, which is underwhelming, but that all used to be written by hand, and now it’s automated!</p>
37 <p>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!</p>
38 <p>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.</p>
39 <h3 id="about-the-script">About the script</h3>
40 <p>The script just recursively goes through my <code>convert/posts/</code> directory, and looks for files that end with an <code>.md</code> suffix that aren’t <code>index.md</code>, 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.</p>
41 <h3 id="retrieving-necessary-data-from-markdown-files">Retrieving necessary data from Markdown files</h3>
42 <p>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 <code># Hey, I'm a title</code>. The date is retrieved from the third line, which looks something like <code>Date published: 2020-11-21</code>. The link to the file is retrieved from the recursively constructed path, which looks something like <code>convert/posts/2020/hey-im-a-blog-post.md</code>.</p>
43 <p>The title, date, and link are then stripped as follows:</p>
44 <ul>
45 <li>The <code>#</code> is stripped from the <code># Hey, I'm a title</code>.</li>
46 <li>The <code>Date published:</code> is stripped from the <code>Date published: 2020-11-21</code>.</li>
47 <li>The <code>convert</code> is stripped from the <code>convert/posts/2020/hey-im-a-blog-post.md</code>.</li>
48 </ul>
49 <aside class="border">
50 <p>
51 <strong>Notice</strong>: Since this blog post, you may have noticed that I’ve changed my date format from <code>Date published: yyyy-mm-dd</code> to just <code>yyyy-mm-dd</code>.
52 </p>
53 </aside>
54 <h3 id="plopping-it-all-into-a-data-format">Plopping it all into a data format</h3>
55 <p>All of this is then mushed into a key-value table that looks similar to the one below:</p>
56 <pre><code>{:date &quot;2020-11-20&quot;
57 :title &quot;Title of the post&quot;
58 :link &quot;/posts/2020/some-blog-post.md&quot;}</code></pre>
59 <p>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:</p>
60 <pre><code>{:2020-11-21 &quot;[Title of the post](/posts/2020/title-of-the-post.md)&quot;
61 :2017-11-20 &quot;[Another title](/posts/2017/another-title.md)&quot;
62 :2017-11-21 &quot;[And yet another one](/posts/2017/and-yet-another-one.md)&quot;
63 :2018-11-20 &quot;[Running out of ideas](/posts/2018/running-out-of-ideas.md)&quot;
64 :2019-11-20 &quot;[Um](/posts/2019/um.md)&quot;
65 :2020-11-22 &quot;[Yep](/posts/2020/yep.md)&quot;
66 :2020-11-23 &quot;[Some title](/posts/2020/some-title.md)&quot;}</code></pre>
67 <h3 id="sorting-the-data">Sorting the data</h3>
68 <p>A sorting function takes this table, reverse sorts it by keys to create a table that looks something like the following table:</p>
69 <pre><code>{:2020-11-23 &quot;[Some title](/posts/2020/some-title.md)&quot;
70 :2020-11-22 &quot;[Yep](/posts/2020/yep.md)&quot;
71 :2020-11-21 &quot;[Title of the post](/posts/2020/title-of-the-post.md)&quot;
72 :2019-11-20 &quot;[Um](/posts/2019/um.md)&quot;
73 :2018-11-20 &quot;[Running out of ideas](/posts/2018/running-out-of-ideas.md)&quot;
74 :2017-11-21 &quot;[And yet another one](/posts/2017/and-yet-another-one.md)&quot;
75 :2017-11-20 &quot;[Another title](/posts/2017/another-title.md)&quot;}</code></pre>
76 <p>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.</p>
77 <p>The fancy (awful?) sorting function looks like the one below:</p>
78 <pre><code>(fn write-sorted-posts [tbl]
79 (let [key-seq []]
80 ;; Create a seq of keys from tbl
81 (each [k _ (pairs tbl)]
82 (table.insert key-seq k))
83
84 ;; Sort the keys from small to big
85 (table.sort key-seq)
86
87 ;; Start from the end (length of) seq-of-keys
88 ;; End on 1 (Starting of index)
89 ;; Step by -1
90 (for [i (# key-seq) 1 -1]
91 (let [date (. key-seq i)
92 post (. tbl date)]
93 (file-write destination post :a)))))</code></pre>
94 <h3 id="thou-shalt-order-thy-file-writing">Thou shalt order thy file writing</h3>
95 <p>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 <code>index.md</code> wipes outdated <code>index.md</code> and starts over.</p>
96 <h3 id="back-to-rss-generator-programming">Back to RSS-generator programming…</h3>
97 <p>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!</p>
98 <h3 id="getting-meta">Getting meta</h3>
99 <p>Okay, so, the ultimate test! Let’s see if this post is picked up and added to my <a href="/posts/">posts page</a>. I’ll add a line below this to let you know if it did the first time!</p>
100 <p>Edit: It worked!</p>
101 </main>
102 </body>
103 </html>