aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Stück <adam@adast.dk>2024-09-14 22:27:15 +0200
committerAdam Stück <adam@adast.dk>2024-09-14 22:33:43 +0200
commitd57b985c382d3a88f1a22f354e0ec989d18caeb2 (patch)
tree47f649c028c78b057fd2cc62ad8f214b6d35fd25
parent732607ac04c2a21a9aeeb0f5e1aeb0952d7e86b0 (diff)
switch to wruby site generator
-rw-r--r--.build.yml17
-rw-r--r--LICENSE4
-rw-r--r--Makefile11
-rw-r--r--_config.yml21
-rwxr-xr-xbarf158
-rw-r--r--footer.html5
-rw-r--r--header.html8
-rw-r--r--index.md2
-rw-r--r--pages/posts.md3
-rw-r--r--wruby.rb150
10 files changed, 195 insertions, 184 deletions
diff --git a/.build.yml b/.build.yml
index ee27fdb..2f0766c 100644
--- a/.build.yml
+++ b/.build.yml
@@ -1,25 +1,28 @@
-image: alpine/edge
+image: alpine/latest
oauth: pages.sr.ht/PAGES:RW
packages:
+ - ruby
+ - ruby-dev
+ - go
- hut
- rsync
secrets:
- 4c5cebdb-c744-4dfb-a69a-30b9bdfe048c
sources:
- https://git.sr.ht/~adamski/adast.dk
- - https://git.sr.ht/~bt/smu
environment:
deploy: srht@adast.dk
mirror: mirror.adast.dk
site: adamski.srht.site
tasks:
-- smu: |
- cd smu
- sudo make install
-- package: |
+- install-gems: |
+ sudo gem install bundler 'kramdown:2.4.0' 'rss:0.3.0'
+- build: |
cd adast.dk
make build
- tar -C build -cvz . > ../site.tar.gz
+- package: |
+ cd adast.dk/build
+ tar -cvz . > ../../site.tar.gz
- upload: |
sshopts="ssh -o StrictHostKeyChecking=no"
rsync --rsh="$sshopts" -ruz --delete adast.dk/build/ $deploy:/var/www/adast.dk
diff --git a/LICENSE b/LICENSE
index 8653a47..81774c2 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
MIT License
-Copyright (c) 2023 Bradley Taunt
-Copyright (c) 2023 Adam Stück
+Copyright (c) 2024 Bradley Taunt
+Copyright (c) 2024 Adam Stück
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile b/Makefile
index b16a580..9d7e5a1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,8 @@
build:
- sh ./barf
- rsync -r public/ build/public
+ rm -rf build && mkdir build
+ ruby wruby.rb
clean:
rm -rf build/*
-watch:
- while true; do \
- ls -d .git/* * posts/* pages/* header.html | entr -cd make ;\
- done
-
-.PHONY: build clean watch
+.PHONY: build clean
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..1080622
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,21 @@
+site_url: 'https://adast.dk'
+site_name: 'adast'
+author_name: 'Adam Stück'
+
+directories:
+ posts: 'posts'
+ pages: 'pages'
+ public: 'public'
+ output: 'build'
+ posts_output: 'build/posts'
+ pages_output: 'build/'
+
+files:
+ header: 'header.html'
+ footer: 'footer.html'
+ root_index: 'index.md'
+ posts_index: 'pages/posts.md'
+ rss: 'build/index.rss'
+
+misc:
+ post_count: 5
diff --git a/barf b/barf
deleted file mode 100755
index 098ee07..0000000
--- a/barf
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/bin/sh
-
-domain="https://adast.dk"
-
-# 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
-
-set -eu
-MARKDOWN=smu
-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
-}
-
-index_html() {
- # Print header
- title=$(sed -n '/^# /{s/# //p; q}' index.md)
- sed "s/{{TITLE}}/$title/" header.html
-
- # Intro text
- $MARKDOWN index.md
-
- echo '<ul class="posts">'
-
- # Posts
- while read -r f title created; do
- link=$(echo "$f" | sed -E 's|.*/(.*).md|/\1|')
- created=$(echo $(head -3 "$f" | tail -1))
- echo "<li><span>$created</span><a href=\"$link\">$title</a></li>"
- done < "$1" | sort -r
-
- echo "</ul>"
-
- # Print footer after post list
- cat footer.html
-}
-
-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>'
-}
-
-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)
-
- 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>Adam Stück's blog</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>
-EOF
- done < "$1"
-
- 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"
-}
-
-rm -rf build && mkdir build
-
-# 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"
-done < build/posts.tsv
-
-# Pages
-index_tsv pages > build/pages.tsv
-while read -r f title created; do
- write_page "$f" "$title" "$created"
-done < build/pages.tsv
diff --git a/footer.html b/footer.html
index 301a703..ba57ae1 100644
--- a/footer.html
+++ b/footer.html
@@ -10,11 +10,12 @@
<li><a href="/now">Now</a></li>
<li><a href="/contact">Contact</a></li>
<li><a href="/donate">Donate</a></li>
+ <li><a href="/index.rss">RSS</a></li>
<li><a href="#top">↑ Top of the page</a></li>
</ul>
<small>
- Feeds: <a href="/atom.xml">Atom</a> | <a href="/rss.xml">RSS</a> <br>
- Built with <a href="https://barf.btxx.org">barf</a>. <br>
+ Built with <a href="https://wruby.btxx.org">wruby</a>. <br>
+ Maintained with ♥ for the web. <br>
The content for this site is <a href="https://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA</a>.<br>
The <a href="https://git.sr.ht/~adamski/adast.dk">code for this site</a> is <a href="https://git.sr.ht/~adamski/adast.dk/tree/main/item/LICENSE">MIT</a>.
</small>
diff --git a/header.html b/header.html
index b687008..971a627 100644
--- a/header.html
+++ b/header.html
@@ -6,12 +6,8 @@
<meta name="color-scheme" content="dark light">
<link rel="icon" href="data:,">
<title>{{TITLE}}</title>
- <link href="/atom.xml" type="application/atom+xml" rel="alternate" title="Atom feed for blog posts" />
- <link href="/rss.xml" type="application/rss+xml" rel="alternate" title="RSS feed for blog posts" />
- <style>*{box-sizing:border-box;}body{font-family:sans-serif;line-height:1.33;margin:0 auto;max-width:650px;padding:1rem;}blockquote{border-left:4px
- solid;padding-left:5px;}img{max-width:100%;}pre{border:1px solid;overflow:auto;padding:5px;}table{text-align:left;width:100%;}
- .posts,#menu{list-style:none;padding:0;}.posts li{margin-bottom:8px;}.posts li span{display:block;font-size:90%;}#menu li{display:inline-block;margin-right:8px;}.footnotes{font-size:90%;}
- a:link{text-decoration:none;}a:visited{text-decoration:none;}a:hover{text-decoration:underline;}a:active{text-decoration:underline;}</style>
+ <link href="/index.rss" type="application/rss+xml" rel="alternate" title="RSS feed for blog posts" />
+ <style>*{box-sizing:border-box;}body{font-family:sans-serif;line-height:1.33;margin:0 auto;max-width:650px;padding:1rem;}blockquote{border-left:4px solid;padding-left:5px;}img{max-width:100%;}pre{border:1px solid;overflow:auto;padding:5px;}table{text-align:left;width:100%;}.posts,#menu{list-style:none;padding:0;}.posts li{margin-bottom:8px;}.posts li span{display:block;font-size:90%;}#menu li{display:inline-block;margin-right:8px;}.footnotes{font-size:90%;}</style>
</head>
<nav id="top">
diff --git a/index.md b/index.md
index 1d90092..883dad4 100644
--- a/index.md
+++ b/index.md
@@ -6,4 +6,4 @@ I'm passionate about open source software, usability, performance, privacy, and
minimal design. Welcome to my corner of the web. You'll find one or two blog
posts, self-hosted web services, and other stuff. Have a look around!
----
+## Latest Posts
diff --git a/pages/posts.md b/pages/posts.md
new file mode 100644
index 0000000..c0a628b
--- /dev/null
+++ b/pages/posts.md
@@ -0,0 +1,3 @@
+# Posts
+
+This page contains a full list of all my blog posts.
diff --git a/wruby.rb b/wruby.rb
new file mode 100644
index 0000000..446d83f
--- /dev/null
+++ b/wruby.rb
@@ -0,0 +1,150 @@
+require 'bundler/inline'
+gemfile do
+ gem 'kramdown', '2.4.0'
+ gem 'rss', '0.3.0'
+end
+
+require 'kramdown'
+require 'fileutils'
+require 'date'
+require 'rss'
+require 'find'
+require 'yaml'
+
+# Load configuration
+config = YAML.load_file('_config.yml')
+
+site_url = config['site_url']
+site_name = config['site_name']
+author_name = config['author_name']
+
+posts_dir = config['directories']['posts']
+pages_dir = config['directories']['pages']
+public_dir = config['directories']['public']
+output_dir = config['directories']['output']
+posts_output_dir = config['directories']['posts_output']
+pages_output_dir = config['directories']['pages_output']
+
+header_file = config['files']['header']
+footer_file = config['files']['footer']
+root_index_file = config['files']['root_index']
+posts_index_file = config['files']['posts_index']
+rss_file = config['files']['rss']
+
+post_count = config['misc']['post_count']
+
+# Make sure output directories exist
+[posts_output_dir, pages_output_dir].each { |dir| FileUtils.mkdir_p(dir) }
+
+# Read the footer content
+footer_content = File.read(footer_file)
+
+# Replace the title meta tag in the header.html
+def replace_title_placeholder(header_content, title)
+ header_content.gsub('<title>{{TITLE}}</title>', "<title>#{title}</title>")
+end
+
+# Grab the title from each markdown file
+def extract_title_from_md(lines)
+ first_line = lines.first
+ first_line&.start_with?('# ') ? first_line[2..-1].strip : 'Blog Index'
+end
+
+# Convert markdown files
+def process_markdown_files(input_directory, output_directory, header_content, footer_content)
+ items = []
+
+ Find.find(input_directory) do |path|
+ next unless path =~ /\.md\z/
+
+ md_content = File.read(path)
+ lines = md_content.lines
+
+ title = extract_title_from_md(lines)
+ date = Date.parse(lines[2]&.strip || '') rescue Date.today
+ html_content = Kramdown::Document.new(md_content).to_html
+
+ relative_path = path.sub(input_directory + '/', '').sub('.md', '')
+ item_dir = File.join(output_directory, relative_path)
+ output_file = "#{item_dir}/index.html"
+ FileUtils.mkdir_p(item_dir)
+
+ header = replace_title_placeholder(header_content, title)
+ File.write(output_file, header + html_content + footer_content)
+
+ items << { title: title, date: date, link: relative_path + '/', content: html_content }
+ end
+
+ items
+end
+
+# Create the root index file
+def generate_index(posts, header_content, footer_content, root_index_file, post_count, output_dir, posts_dir)
+ root_index_content = File.read(root_index_file)
+ root_title = extract_title_from_md(root_index_content.lines)
+ root_html = Kramdown::Document.new(root_index_content).to_html
+
+ header = replace_title_placeholder(header_content, root_title)
+
+ index_content = header + root_html + "<ul class=\"posts\">\n"
+ posts.first(post_count).each { |post| index_content << "<li><span>#{post[:date]}</span><a href='/#{posts_dir}/#{post[:link]}'>#{post[:title]}</a></li>\n" }
+ index_content << "</ul>\n<p><a href='/#{posts_dir}'>View all posts &rarr;</a></p>\n" + footer_content
+
+ File.write("#{output_dir}/index.html", index_content)
+end
+
+# Create the full posts list page
+def generate_full_posts_list(posts, header_content, footer_content, posts_index_file, output_dir, posts_dir)
+ posts_index_content = File.read(posts_index_file)
+ posts_title = extract_title_from_md(posts_index_content.lines)
+ posts_html = Kramdown::Document.new(posts_index_content).to_html
+
+ header = replace_title_placeholder(header_content, posts_title)
+
+ list_content = header + posts_html + "<ul class=\"posts\">\n"
+ posts.each { |post| list_content << "<li><span>#{post[:date]}</span><a href='/#{posts_dir}/#{post[:link]}'>#{post[:title]}</a></li>\n" }
+ list_content << "</ul>\n" + footer_content
+
+ File.write("#{output_dir}/posts/index.html", list_content)
+end
+
+# Generate the RSS 2.0 feed
+def generate_rss(posts, rss_file, author_name, site_name, site_url, posts_dir)
+ rss = RSS::Maker.make("2.0") do |maker|
+ maker.channel.author = author_name
+ maker.channel.updated = Time.now.to_s
+ maker.channel.title = "#{site_name} RSS Feed"
+ maker.channel.description = "The official RSS Feed for #{site_url}"
+ maker.channel.link = site_url
+
+ posts.each do |post|
+ date = Date.parse(post[:date].to_s).to_time + 12*60*60 # Force time to midday
+ item_link = "#{site_url}/#{posts_dir}/#{post[:link]}"
+ item_title = post[:title]
+ item_content = post[:content]
+
+ maker.items.new_item do |item|
+ item.link = item_link
+ item.title = item_title
+ item.updated = date.to_s
+ item.pubDate = date.rfc822
+ item.description = item_content
+ end
+ end
+ end
+
+ File.write(rss_file, rss)
+end
+
+# Process header, posts, pages, etc.
+header_content = File.read(header_file)
+
+posts = process_markdown_files(posts_dir, posts_output_dir, header_content, footer_content).sort_by { |post| -post[:date].to_time.to_i }
+pages = process_markdown_files(pages_dir, pages_output_dir, header_content, footer_content)
+
+generate_index(posts, header_content, footer_content, root_index_file, post_count, output_dir, posts_dir)
+generate_full_posts_list(posts, header_content, footer_content, posts_index_file, output_dir, posts_dir)
+FileUtils.cp_r(public_dir, output_dir)
+generate_rss(posts, rss_file, author_name, site_name, site_url, posts_dir)
+
+puts "Blog built successfully in '#{output_dir}' folder. Have a great day!"