aboutsummaryrefslogtreecommitdiff
path: root/barf
diff options
context:
space:
mode:
Diffstat (limited to 'barf')
-rwxr-xr-xbarf305
1 files changed, 179 insertions, 126 deletions
diff --git a/barf b/barf
index c53ed7b..c19ec94 100755
--- a/barf
+++ b/barf
@@ -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 &middot; <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 &middot; <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/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&#39;/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/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&#39;/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/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&#39;/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/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&#39;/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"