A Simple Static Site Generator

no hurry, no pause.

Last update: 2024-08-26

New Workflow

I recently changed my workflow around authoring and publishing my site notes. Here’s the rundown.

I write new notes in obsidian.md as usual. When I want to publish them, I synchronize my .md and .bib files between obsidian and codeberg directories using the rsync command and pandoc takes care of converting .md files to .html files. The html files are in my git repo, which are then committed, and pushed to Codeberg. I use four bash scripts1 to accomplish this.

Steps

  1. Synchronize .md and .bib files between obsidian-zettelkasten and codeberg directories using the rsync command.
  2. Convert .md files to .html files using pandoc.
  3. Generate an RSS feed.
  4. Push changes to the remote repository using git.

Synchronize .md and .bib Files

#!/bin/bash
clear
# Synchronize .md files between two directories using the rsync command

# Source directory containing the markdown files
SOURCE_DIR="/Documents/obsidian-zettelkasten/"

# Destination directory where files will be synchronized
DEST_DIR="/Documents/temp/codeberg/"

# Perform the synchronization with rsync
rsync -a --include="*.md" --include="*.bib" --exclude="*" "$SOURCE_DIR" "$DEST_DIR"

echo "Synchronized .md files from $SOURCE_DIR to $DEST_DIR."

#Explanation:
#   •   rsync -av:
#   •   -a (archive mode) preserves file attributes like timestamps, permissions, and symbolic links.
#   •   -v (verbose) gives detailed output during the operation.
#   •   --include="*.md": Includes only .md files in the synchronization.
#   •   --exclude="*": Excludes everything else, so only .md files and directories are considered.
#   •   "${SOURCE_DIR}" and "${DEST_DIR}" represent the source and destination directories, respectively. Ensure that these paths end with a slash (/) to avoid any path concatenation issues.

Convert .md Files to .html Files

#!/bin/bash

# Directory containing the Markdown files
DIR="/Documents/temp/codeberg"
HTML="/Documents/temp/codeberg/pages"

# Store the current working directory
CURRENT_DIR=$(pwd)

# Change to the directory containing the Markdown files
cd "$DIR" || exit

# Find the latest 50 modified .md files in the current directory only
LATEST_FILES=$(find . -maxdepth 1 -name "*.md" -type f -exec stat -f "%m %N" {} + | sort -nr | head -50 | cut -d' ' -f2-)

# Loop over the files and convert each to HTML
for FILE in $LATEST_FILES; do
    # Convert to HTML (using pandoc)
    OUTPUT_FILE="${HTML}/${FILE%.md}.html"

    # Convert only if the output HTML doesn't exist or the MD file is newer
    if [ ! -f "$OUTPUT_FILE" ] || [ "$FILE" -nt "$OUTPUT_FILE" ]; then
        pandoc --standalone --mathjax --template template.html --bibliography ./refs.bib --citeproc --csl ./apa.csl "$FILE" -o "$OUTPUT_FILE"
        echo "Converted $FILE to ${FILE%.md}.html."
    else
        echo "Skipping conversion; ${FILE%.md}.html is up-to-date."
    fi
done

# Change back to the original directory
cd "$CURRENT_DIR" || exit

Generate RSS Feed

#!/bin/bash

# Define the output file for the RSS feed
OUTPUT_FILE="/Documents/temp/codeberg/pages/feed.rss"

# Set the variables
TITLE="Continuum"
DESCRIPTION="No hurry, no pause."
LINK="https://continuum.codeberg.page"
LANGUAGE="en-ca"
DATE=$(date +"%a, %d %b %Y %T %z") # Current date and time in RFC-822 format
NOTE="Thank you for keeping RSS alive."
GENERATOR="Custom RSS Generator"

# Find the last 11 HTML files in the root directory
ROOT_DIR="/Documents/temp/codeberg/pages/"
HTML_FILES=$(find $ROOT_DIR -maxdepth 1 -name "*.html" -type f -exec stat -f "%m %N" {} + | sort -nr | head -11 | cut -d' ' -f2-)

# Start writing the RSS feed  
echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
<rss version=\"2.0\">
<channel>
<title>$TITLE</title>
<description>$DESCRIPTION</description>
<link>$LINK</link>
<language>$LANGUAGE</language>
<lastBuildDate>$DATE</lastBuildDate>
<note>$NOTE</note>
<generator>$GENERATOR</generator>" > "$OUTPUT_FILE"

# Loop through each HTML file and extract required fields
for FILE in $HTML_FILES; do
    MOD_TIME=$(date -R -r "$FILE")
    TITLE=$(grep -o '<title>[^<]*' "$FILE" | sed 's/<title>//')
    DESCRIPTION=$(grep -o '<meta name="description" content="[^"]*' "$FILE" | sed 's/<meta name="description" content="//')
    DESCRIPTION=${DESCRIPTION:-"No hurry, no pause."}
    URL="https://continuum.codeberg.page/$(basename "$FILE")"
    guid="$URL"
    # Write item to RSS feed
    echo "<item>
    <pubDate>$MOD_TIME</pubDate>
    <title>$TITLE</title>
    <link>$URL</link>
    <description>$DESCRIPTION</description>
    <guid>$guid</guid>
    </item>" >> "$OUTPUT_FILE"
done

# Close the RSS feed
echo "</channel>
</rss>" >> "$OUTPUT_FILE"

echo "Generated $OUTPUT_FILE successfully."

Push Changes to the Remote Repository

#!/bin/bash

# Change to the directory of your Git repository
REPO_DIR="/Documents/temp/codeberg/pages"
cd "$REPO_DIR" || exit

# Stage all changes (new, modified, deleted files)
git add .

# Commit changes with a message
COMMIT_MESSAGE="Automated commit: $(date +'%Y-%m-%d %H:%M:%S')"
git commit -m "$COMMIT_MESSAGE"

# Push changes to the remote repository (Codeberg in this case)
git push origin main

echo "Changes have been pushed to the repository."

Static Site Generator

Putting it all together:

#!/bin/bash
clear

# Echo the name of the script
echo "Running script: $0"

# Synchronize .md and .bib files between obsidian-zettelkasten and codeberg using the rsync command
./sync_md_bib_files.sh

# Convert .md files to .html files:
./convert_to_html.sh

# Generate RSS feed
./feed.sh

# Push changes to the remote repository
./push_changes.sh

Footnotes


  1. Written with the help of ChatGPT↩︎