diff options
author | Bradley Taunt <bt@btxx.org> | 2024-06-10 09:41:25 -0400 |
---|---|---|
committer | Bradley Taunt <bt@btxx.org> | 2024-06-10 09:41:25 -0400 |
commit | 07e4a2dafe248280b5610f8c7d09b0f30b530f54 (patch) | |
tree | 8a145d1d4d07e1278a837ff15dadccc322d27515 /barf | |
parent | 16d28628aca9b2d356de31c319f5e7bc0f5b2b02 (diff) |
Initial modifications to rebuilt only changed files based on mod date, performance updates
Diffstat (limited to 'barf')
-rwxr-xr-x | barf | 305 |
1 files changed, 179 insertions, 126 deletions
@@ -1,158 +1,211 @@ #!/bin/sh +start_time=$(date +%s) domain="https://btxx.org" - -# Check the operating system -os_name=$(uname -s) - -if [ "$os_name" = "OpenBSD" ]; then - alias sed=gsed - alias date=gdate - alias rsync=openrsync -elif [ "$os_name" = "Darwin" ]; then - alias sed=gsed - alias date=gdate -fi +timestamp_file="timestamps.tsv" + +# Check the operating system and set aliases +case $(uname -s) in + OpenBSD) + alias sed=gsed + alias date=gdate + alias rsync=openrsync + ;; + Darwin) + alias sed=gsed + alias date=gdate + ;; +esac set -eu MARKDOWN=lowdown -IFS=' ' - -# Create tab separated file with filename, title, creation date, last update -index_tsv() { - for f in "$1"/*.md - do - title=$(sed -n '/^# /{s/# //p; q}' "$f") - printf '%s\t%s\t%s\t%s\n' "$f" "${title:="No Title"}" - done +IFS=$'\t' + +# Precompute values used in multiple places +header_title=$(sed -n '/^# /{s/# //p; q}' index.md) +git_user_name=$(git config user.name) +first_commit_date=$(git log --pretty='format:%ai' . | cut -d ' ' -f1 | tail -1) +now=$(date +%FT%TZ) +now_rss=$(date -u +"%a, %d %b %Y %H:%M:%S %z") + +# Update the timestamp for a markdown file +update_timestamp() { + local filename=$1 + local timestamp=$(date -r "$filename" +%s) + # Remove old timestamp and add new + awk -v file="$filename" -v ts="$timestamp" '$1 != file {print $0}' "$timestamp_file" > "${timestamp_file}.tmp" + echo "$filename $timestamp" >> "${timestamp_file}.tmp" + mv "${timestamp_file}.tmp" "$timestamp_file" } -index_html() { - # Print header - title=$(sed -n '/^# /{s/# //p; q}' index.md) - sed "s/{{TITLE}}/$title/" header.html - - # Intro text - $MARKDOWN index.md - - echo "<div>" +# Check if the markdown file needs rebuilding +needs_rebuilding() { + local filename=$1 + local last_mod=$(date -r "$filename" +%s) + local last_build=$(awk -v file="$filename" '$1 == file {print $2}' "$timestamp_file") + + if [ "$last_mod" -gt "${last_build:-0}" ]; then + return 0 # needs rebuilding + else + return 1 # does not need rebuilding + fi +} - # Posts - while read -r f title created; do - link=$(echo "$f" | sed -E 's|.*/(.*).md|\1/|') - created=$(echo $(head -3 "$f" | tail -1)) - echo "<span>$created · <a href=\"$link\">$title</a></span><br>" - done < "$1" | sort -r +# Define write_page function +write_page() { + local filename=$1 + local title=$2 + local category=$3 # Category determines if it's a post or a page + + if needs_rebuilding "$filename"; then + local directory + if [ "$category" = "posts" ]; then + directory="build/posts/$(basename "$filename" .md)" + else + directory="build/$(basename "$filename" .md)" + fi + mkdir -p "$directory" + local target="${directory}/index.html" + local created=$(head -3 "$filename" | tail -1) + + { + sed "s|{{TITLE}}|$title|" header.html + $MARKDOWN "$filename" + cat footer.html + } > "$target" + update_timestamp "$filename" + + echo "Rebuilt: $filename" + fi +} - echo "<div>" +# Create tab separated file with filename, title +index_tsv() { + for f in "$1"/*.md; do + title=$(sed -n '/^# /{s/# //p; q}' "$f") + printf '%s\t%s\n' "$f" "${title:="No Title"}" + done +} - # Print footer after post list - cat footer.html +# Generate index.html +index_html() { + sed "s/{{TITLE}}/$header_title/" header.html + $MARKDOWN index.md + echo "<div>" + + while read -r f title; do + link="${f%.md}/" + created=$(head -3 "$f" | tail -1) + echo "<span>$created · <a href=\"$link\">$title</a></span><br>" + done < "$1" | sort -r + + echo "</div>" + cat footer.html } +# Generate atom.xml atom_xml() { - uri=$(sed -rn '/atom.xml/ s/.*href="([^"]*)".*/\1/ p' header.html) - first_commit_date=$(git log --pretty='format:%ai' . | cut -d ' ' -f1 | tail -1) - - cat <<EOF -<?xml version="1.0" encoding="utf-8"?> -<feed xmlns="http://www.w3.org/2005/Atom"> - <title>$(sed -n '/^# /{s/# //p; q}' index.md)</title> - <link href="$domain/atom.xml" rel="self" /> - <updated>$(date +%FT%TZ)</updated> - <author> - <name>$(git config user.name)</name> - </author> - <id>$domain,$first_commit_date:default-atom-feed/</id> -EOF - - while read -r f title created; do - - content=$($MARKDOWN "$f" | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g') - post_link=$(echo "$f" | sed -E 's|posts/(.*).md|\1|') - basic_date=$(echo $(head -3 "$f" | tail -1)) - published_date=$(date -d $basic_date -u +%Y-%m-%dT10:%M:%SZ) - - cat <<EOF - <entry> - <title>$title</title> - <content type="html">$content</content> - <link href="$domain/$post_link"/> - <id>$domain/$post_link</id> - <updated>$published_date</updated> - <published>$published_date</published> - </entry> -EOF - done < "$1" - - echo '</feed>' + echo "<?xml version=\"1.0\" encoding=\"utf-8\"?> +<feed xmlns=\"http://www.w3.org/2005/Atom\"> + <title>$header_title</title> + <link href=\"$domain/atom.xml\" rel=\"self\" /> + <updated>$now</updated> + <author> + <name>$git_user_name</name> + </author> + <id>$domain,$first_commit_date:default-atom-feed</id>" + + while read -r f title; do + content=$($MARKDOWN "$f" | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g') + post_link="${f%.md}" + basic_date=$(head -3 "$f" | tail -1) + published_date=$(date -d "$basic_date" -u +%Y-%m-%dT10:%M:%SZ) + echo " <entry> + <title>$title</title> + <content type=\"html\">$content</content> + <link href=\"$domain/$post_link\"/> + <id>$domain/$post_link</id> + <updated>$published_date</updated> + <published>$published_date</published> + </entry>" + done < "$1" + echo '</feed>' } +# Generate RSS rss_xml() { - uri=$(sed -rn '/rss.xml/ s/.*href="([^"]*)".*/\1/ p' header.html) - first_commit_date=$(git log --pretty='format:%ai' . | cut -d ' ' -f1 | tail -1) + uri=$(sed -rn '/rss.xml/ s/.*href="([^"]*)".*/\1/ p' header.html) + first_commit_date=$(git log --pretty='format:%ai' . | cut -d ' ' -f1 | tail -1) - cat <<EOF + cat <<EOF <?xml version="1.0" encoding="utf-8"?> <rss version="2.0"> - <channel> - <title>$(sed -n '/^# /{s/# //p; q}' index.md)</title> - <link>$domain/rss.xml</link> - <description>Feed description here</description> - <lastBuildDate>$(date -u +"%a, %d %b %Y %H:%M:%S %z")</lastBuildDate> - <pubDate>$(date -u +"%a, %d %b %Y %H:%M:%S %z")</pubDate> - <generator>Custom RSS Generator</generator> - <ttl>1800</ttl> + <channel> + <title>$(sed -n '/^# /{s/# //p; q}' index.md)</title> + <link>$domain/rss.xml</link> + <description>Feed description here</description> + <lastBuildDate>$(date -u +"%a, %d %b %Y %H:%M:%S %z")</lastBuildDate> + <pubDate>$(date -u +"%a, %d %b %Y %H:%M:%S %z")</pubDate> + <generator>Custom RSS Generator</generator> + <ttl>1800</ttl> EOF - while read -r f title created; do - content=$($MARKDOWN "$f" | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g') - post_link=$(echo "$f" | sed -E 's|posts/(.*).md|\1|') - basic_date=$(echo $(head -3 "$f" | tail -1)) - published_date=$(date -d "$basic_date" -u +"%a, %d %b %Y %H:%M:%S %z") - - cat <<EOF - <item> - <title>$title</title> - <description>$content</description> - <link>$domain/$post_link</link> - <guid isPermaLink="false">$domain/$post_link</guid> - <pubDate>$published_date</pubDate> - </item> + while read -r f title created; do + content=$($MARKDOWN "$f" | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g') + post_link=$(echo "$f" | sed -E 's|posts/(.*).md|\1|') + basic_date=$(echo $(head -3 "$f" | tail -1)) + published_date=$(date -d "$basic_date" -u +"%a, %d %b %Y %H:%M:%S %z") + + cat <<EOF + <item> + <title>$title</title> + <description>$content</description> + <link>$domain/$post_link</link> + <guid isPermaLink="false">$domain/$post_link</guid> + <pubDate>$published_date</pubDate> + </item> EOF - done < "$1" + done < "$1" - echo '</channel>' - echo '</rss>' + echo '</channel>' + echo '</rss>' } -write_page() { - filename=$1 - directory=$(echo $(basename "$filename" .md)) - $(mkdir -p build/$directory) - target=$(echo "$filename" | sed -r 's|\w+/(.*).md|build/\1/index.html|') - created=$(echo $(head -3 "$filename" | tail -1)) - title=$2 - - $MARKDOWN "$filename" | \ - cat header.html - |\ - sed "s|{{TITLE}}|$title|" \ - > "$target" && cat footer.html >> "$target" +# Initialize timestamps for all Markdown files if not already done +initialize_timestamps() { + if [ ! -f "$timestamp_file" ] || [ ! -s "$timestamp_file" ]; then + echo "Initializing timestamps..." + for f in index.md posts/*.md pages/*.md; do + update_timestamp "$f" + done + echo "Timestamps initialized for all Markdown files." + fi } -rm -rf build && mkdir build +# Main operations +mkdir -p build/posts build/pages +initialize_timestamps -# Blog posts -index_tsv posts | sort -rt " " -k 3 > build/posts.tsv -index_html build/posts.tsv > build/index.html -atom_xml build/posts.tsv > build/atom.xml -rss_xml build/posts.tsv > build/rss.xml -while read -r f title created; do - write_page "$f" "$title" "$created" +index_tsv posts > build/posts.tsv +index_tsv pages > build/pages.tsv + +while read -r f title; do + write_page "$f" "$title" "posts" done < build/posts.tsv -# Pages -index_tsv pages > build/pages.tsv -while read -r f title created; do - write_page "$f" "$title" "$created" +while read -r f title; do + write_page "$f" "$title" "pages" done < build/pages.tsv + +if needs_rebuilding "index.md"; then + index_html build/posts.tsv > build/index.html + echo "Rebuilt index.html due to changes in index.md" + update_timestamp "index.md" +fi + +atom_xml build/posts.tsv > build/atom.xml +rss_xml build/posts.tsv > build/rss.xml + +end_time=$(date +%s) +elapsed_time=$((end_time - start_time)) +echo "Total time: ${elapsed_time}s" |