$title$

$body$

A static site generator in ~42 lines of Bash

Needed something basic to generate a few pages for this website. I could use an entire framework, but that would be overkill. Decided to write a static site generator in Bash.

Here is that bash script:

#!/bin/bash

# create the public/posts directory if it doesn't exist
mkdir -p public/posts

list=""

# --- COMPILE /posts DIRECTORY ---
for file in posts/*.html
do
    # get the filename without the extension
    filename=$(basename "$file" .html)
    
    # get the file contents
    content=$(cat "$file")

    # extract h1 from content
    title=$(sed -n 's/.*<h1>\(.*\)<\/h1>.*/\1/p' <<< "$content")
    
    # extract the date from the content
    date=$(sed -n 's/.*<time id="post-date" datetime="YYYY-MM-DD">\(.*\)<\/time>.*/\1/p' <<< "$content")

    # append the filename to the list of posts in 'list'
    list+="<li>$date - <a href=\"posts/$filename.html\">$title</a></li>\n"

    # get template contents before the insert comment, but not including
    before=$(sed -n '1,//p' template.html | head -n -1)

    # replace <title> tag with the title of the post in $before
    before=$(sed "s/<title>.*<\/title>/<title>$title | Kieren Funk<\/title>/" <<< "$before")

    echo "$before" > "public/posts/$filename.html"
    echo "$content" >> "public/posts/$filename.html"
    sed -n '//,$p' template.html | tail -n +2 >> "public/posts/$filename.html"
    
done

# --- COMPILE INDEX.HTML ---

# sort the list of posts by date which is <li><a href=".*">(YYYY-MM-DD).*</a></li>
list=$(echo -e "$list" | sort -r -t '>' -k2)

awk -v var="$list" '{gsub(/{{blogPosts}}/,var)}1' index.html > "public/index.html"
        

The script is pretty simple. It loops through all the files in the posts directory and extracts the title and date from the file. It then appends the filename to a list of posts. It then extracts the content from the file and inserts it into the template. It then writes the template to the public directory.

After all the posts are compiled, it sorts the list of posts by date and inserts it on to the home page.

It's not perfect and there are definitely some limitations. For example, However, for the most part it just works and if I need to add more functionality I can just add it to the script.