Title: Build-a-blog Date: 2024-06-17T14:46:36-04:00 --- I want to share my thought process for how to go about building a static blog generator from scratch. The goal is to take 1 afternoon + caffeine + some DIY spirit → _something_ resembling a static site/blog generator. Lets see how hard this will be. Here's what a blog is/requirements: * Generate an index with recent list of posts. * Generate each individual post written in markdown -> html * Support some metadata in each post * A post title should have a slug * Generate RSS That boils down to: 1. Read some files 2. Parse markdown, maybe parse a header with some key/values. 3. Template strings So there is 1 "exotic" feature in parsing/rendering Markdown as HTML that will need some thought. The rest is just file and string manipulation. Most scripting languages would be fine tools for this task. But how to handle Markdown? ## Picking the tool for the job I've had [Crystal][1] in the back of my mind for this task. It is a nice general purpose language that included Markdown in the stdlib! But unfortunately Markdown was removed in [0.31.0][2]. Other than that, I'm not sure any other languages include a well rounded Markdown implementation out of the box. I'll likely end up building the site in docker with an alpine image down the road, so just a quick search in alpines repos to see what could be useful: ```shell ❯ docker run --rm -it alpine / # apk update fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.18/community/x86_64/APKINDEX.tar.gz v3.18.6-263-g77db018514d [https://dl-cdn.alpinelinux.org/alpine/v3.18/main] v3.18.6-263-g77db018514d [https://dl-cdn.alpinelinux.org/alpine/v3.18/community] OK: 20079 distinct packages available / # apk search markdown discount-2.2.7c-r1 discount-dev-2.2.7c-r1 discount-libs-2.2.7c-r1 kdepim-addons-23.04.3-r0 markdown-1.0.1-r3 markdown-doc-1.0.1-r3 py3-docstring-to-markdown-0.12-r1 py3-docstring-to-markdown-pyc-0.12-r1 py3-html2markdown-0.1.7-r3 py3-html2markdown-pyc-0.1.7-r3 py3-markdown-3.4.3-r1 py3-markdown-it-py-2.2.0-r1 py3-markdown-it-py-pyc-2.2.0-r1 py3-markdown-pyc-3.4.3-r1 ``` [`py3-markdown` in alpine][3] is the popular [`python-markdown`][4]. It's mature and available as a package in my [home distro][5]. Incredible. ## Let's build First, lets read 1 post file and render some html. I'll store posts in `posts/` like `posts/build_a_blog.md`. And we'll store the HTML output in the same directory: `posts/build_a_blog.html`. ```python import re import logging import markdown destpath_re = re.compile(r'\.md$') logging.basicConfig(encoding='utf-8', level=logging.INFO) def render_post(fpath): destpath = destpath_re.sub('.html', fpath) logging.info("opening %s for parsing, dest %s", fpath, destpath) # from: https://python-markdown.github.io/reference/ with open(fpath, "r", encoding="utf-8") as input_file: logging.info("reading %s", fpath) text = input_file.read() logging.info("parsing %s", fpath) out = markdown.markdown(text) with open(destpath, "w", encoding="utf-8", errors="xmlcharrefreplace") as output_file: logging.info("writing to %s", destpath) output_file.write(out) if __name__ == '__main__': render_post('posts/build_a_blog.md') ``` And if we run it. ```shell ❯ python3 ./main.py INFO:root:opening posts/build_a_blog.md for parsing, dest posts/build_a_blog.html INFO:root:reading posts/build_a_blog.md INFO:root:parsing posts/build_a_blog.md INFO:root:writing to posts/build_a_blog.html ❯ head posts/build_a_blog.html

Build-a-blog

I want to share my thought process for how one would go about building a static blog generator from scratch.