Switch to Makefile + ssg build system; add a dynamic nav

The old build system worked, but ssg adds some features while still
being simple and easy to hack on:

* set page title from the h1 tag, rather than the file name
* generate a sitemap (which we adapt to also generate a nav)

This site doesn't need a dynamic nav, but the Anarchy Planet docs site
will have a lot of rapidly changing pages and will benefit from a
dynamic nav. This way we can use the same build system for both
sites.
This commit is contained in:
sceox 2022-01-04 09:39:23 -08:00
parent 5f0252aedc
commit 05b50d5c5f
15 changed files with 337 additions and 80 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
dst
tmp

13
Makefile Normal file
View File

@ -0,0 +1,13 @@
include config.mk
SRC ?= src
DST ?= dst
all: html
html:
$(SSG) $(SRC) $(DST) $(TITLE) $(BASE_URL) $(CONTACT_EMAIL)
clean:
@rm -f $(DST)/*
@rm -f $(DST)/.files

View File

@ -1,26 +1,20 @@
# Anarchy Planet web site
This repo is to generate a static site for anarchyplanet.org to
replace the existing site. The goal is to generate the site from
markdown files by converting the markdown to html and applying minimal
styling.
This repo includes markdown files for [the Anarchy Planet web
site](https://anarchyplanet.org/) and tools to generate a static
HTML site from the source files.
The advantage to this method is that all of the content can be
contained in a single directory without being obscured by the rest of
the code that's needed to make a website run (such as html). This will
(eventually!) make it easy to update content as well as export into
other formats or potential website generators.
This informal README will be replaced with an official README with
instructions for how to contribute to the site, but first we have to
figure out how ourselves! All methods are also open for discussion,
the only requirement that notnull hopes for is pure markdown files in
a single directory, but sceox is welcome to change publish.sh to a
make script. :)
You can see this method in action (maybe! if we didn't break it) at
You can see this method in action at
[https://testing.anarchyplanet.org](https://testing.anarchyplanet.org).
## Contributing
If you are familiar with editing markdown and using git, you should
already be able to figure out how to contribute.
TODO: write docs for someone who's not familiar with editing markdown
and/or using git.
## Dependencies
We use [lowdown](https://kristaps.bsd.lv/lowdown/) for markdown
@ -31,22 +25,24 @@ conversion. See its documentation:
* [lowdown(5)](https://kristaps.bsd.lv/lowdown/lowdown.5.html) which
describes the lanuage syntax
The rest of the heavy lifting is done by a modified version of
[ssg](https://www.romanzolotarev.com/ssg.html) which is included
in this source code.
## TODOs
### TODO discuss and decide on sections
notnull's proposals for the sections are:
- home
- projects (not services)
- webring (instead of 'others')
- contact (probably just a mailto: link)
### TODO write copy for sections
What rocinante has done on
[anarchist news](https://anarchistnews.org/content/anarchy-planet) is
already pretty great. Maybe these could be more verbose, but maybe
they are fine the way they are!
### TODO we need a favicon
* [ ] TODO discuss and decide on sections
- notnull's proposals for the sections are:
* home
* projects (not services)
* webring (instead of 'others')
* contact (probably just a mailto: link)
* [ ] write copy for sections
- What rocinante has done on
[anarchist news](https://anarchistnews.org/content/anarchy-planet)
is already pretty great. Maybe these could be more verbose, but
maybe they are fine the way they are!
* [ ] add a favicon
* [ ] use an automatic toc generator
- and add to Makefile (make toc)
- see https://github.com/ekalinin/github-markdown-toc

10
config.mk Normal file
View File

@ -0,0 +1,10 @@
TITLE = "Anarchy Planet"
BASE_URL = "anarchyplanet.org"
CONTACT_EMAIL = "contact@anarchyplanet.org"
# static site generator
SSG = ./ssg6
# source and destination directories
SRC = src
DST = dst

View File

@ -1,2 +0,0 @@
<footer>
</footer>

View File

@ -1,5 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">

View File

@ -1,6 +0,0 @@
<nav>
<a href="/index.html">home</a>
<a href="/projects.html">projects</a>
<a href="/webring.html">webring</a>
<a href="mailto:join@anarchyplanet.org">contact</a>
</nav>

View File

@ -1,30 +0,0 @@
#!/usr/bin/env bash
PUB_DIR=${1:-/home/html/planet/static}
MD_FILES=md/*.md
OTHER_FILES=*.css
if ! test -d $PUB_DIR; then
echo "error: PUB_DIR does not exist:" $PUB_DIR
exit 1
fi
test -d tmp || mkdir tmp
for f in $MD_FILES
do
filename=$(basename -- $f .md)
echo "publishing md/$filename.md to $PUB_DIR/$filename.html"
lowdown -o tmp/$filename.html $f
sed -i 's/^/ /' tmp/$filename.html
cp head.html tmp/
# set the title
title="$(echo $filename | awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,1,1)) substr($i,2) }}1')"
echo " <title>$title • Anarchy Planet</title>" >> tmp/head.html
echo " </head>" >> tmp/head.html
echo " <body>" >> tmp/head.html
# compile the elements in order
cat tmp/head.html nav.html tmp/$filename.html foot.html tail.html \
> $PUB_DIR/$filename.html
done
cp $OTHER_FILES $PUB_DIR

7
src/_header.html Normal file
View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<link rel="stylesheet" href="/style.css">
</head>

275
ssg6 Executable file
View File

@ -0,0 +1,275 @@
#!/bin/sh -e
#
# https://rgz.ee/bin/ssg6
# Copyright 2018-2019 Roman Zolotarev <hi@romanzolotarev.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
main() {
test -n "$1" || usage
test -n "$2" || usage
test -n "$3" || usage
test -n "$4" || usage
test -d "$1" || no_dir "$1"
test -d "$2" || no_dir "$2"
src=$(readlink_f "$1")
dst=$(readlink_f "$2")
tmp=/tmp/ssg
test -d $tmp || mkdir -p $tmp
IGNORE=$(
if ! test -f "$src/.ssgignore"; then
printf ' ! -path "*/.*"'
return
fi
while read -r x; do
test -n "$x" || continue
printf ' ! -path "*/%s*"' "$x"
done <"$src/.ssgignore"
)
# files
title="$3"
h_file="$src/_header.html"
nav_file="$tmp/_nav.html"
foot_file="$src/_footer.html"
test -n "$5" && contact_email="$5"
urls=$(list_pages "$src")
test -n "$urls" &&
render_nav "$urls" "$base_url" "$title" "$contact_email" >"$nav_file"
test -f "$foot_file" && FOOTER=$(cat "$foot_file") && export FOOTER
if test -f "$nav_file"; then
cat $h_file $nav_file > "$tmp/_header.html"
h_file="$tmp/_header.html"
fi
test -f "$h_file" && HEADER=$(cat "$h_file") && export HEADER
list_dirs "$src" |
(cd "$src" && cpio -pdu "$dst")
fs=$(
if test -f "$dst/.files"; then
list_affected_files "$src" "$dst/.files"
else
list_files "$1"
fi
)
if test -n "$fs"; then
echo "$fs" | tee "$dst/.files"
if echo "$fs" | grep -q '\.md$'; then
if test -x "$(which lowdown 2>/dev/null)"; then
echo "$fs" | grep '\.md$' |
render_md_files_lowdown "$src" "$dst" "$title"
else
if test -x "$(which Markdown.pl 2>/dev/null)"; then
echo "$fs" | grep '\.md$' |
render_md_files_Markdown_pl "$src" "$dst" "$title"
else
echo "couldn't find lowdown nor Markdown.pl"
exit 3
fi
fi
fi
echo "$fs" | grep '\.html$' |
render_html_files "$src" "$dst" "$title"
echo "$fs" | grep -Ev '\.md$|\.html$' |
(cd "$src" && cpio -pu "$dst")
fi
printf '[ssg] ' >&2
print_status 'file, ' 'files, ' "$fs" >&2
# sitemap
base_url="$4"
date=$(date +%Y-%m-%d)
test -n "$urls" &&
render_sitemap "$urls" "$base_url" "$date" >"$dst/sitemap.xml"
print_status 'url' 'urls' "$urls" >&2
echo >&2
}
readlink_f() {
file="$1"
cd "$(dirname "$file")"
file=$(basename "$file")
while test -L "$file"; do
file=$(readlink "$file")
cd "$(dirname "$file")"
file=$(basename "$file")
done
dir=$(pwd -P)
echo "$dir/$file"
}
print_status() {
test -z "$3" && printf 'no %s' "$2" && return
echo "$3" | awk -v singular="$1" -v plural="$2" '
END {
if (NR==1) printf NR " " singular
if (NR>1) printf NR " " plural
}'
}
usage() {
echo "usage: ${0##*/} src dst title base_url [contact_email]" >&2
exit 1
}
no_dir() {
echo "${0##*/}: $1: No such directory" >&2
exit 2
}
list_dirs() {
cd "$1" && eval "find . -type d ! -name '.' ! -path '*/_*' $IGNORE"
}
list_files() {
cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE"
}
list_dependant_files() {
e="\\( -name '*.html' -o -name '*.md' -o -name '*.css' -o -name '*.js' \\)"
cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE $e"
}
list_newer_files() {
cd "$1" && eval "find . -type f ! -name '.' $IGNORE -newer $2"
}
has_partials() {
grep -qE '^./_.*\.html$|^./_.*\.js$|^./_.*\.css$'
}
list_affected_files() {
fs=$(list_newer_files "$1" "$2")
if echo "$fs" | has_partials; then
list_dependant_files "$1"
else
echo "$fs"
fi
}
render_html_files() {
while read -r f; do
render_html_file "$3" <"$1/$f" >"$2/$f"
done
}
render_md_files_lowdown() {
while read -r f; do
lowdown \
--html-no-escapehtml \
--html-no-skiphtml \
--parse-no-metadata \
--parse-no-autolink <"$1/$f" |
render_html_file "$3" \
>"$2/${f%\.md}.html"
done
}
render_md_files_Markdown_pl() {
while read -r f; do
Markdown.pl <"$1/$f" |
render_html_file "$3" \
>"$2/${f%\.md}.html"
done
}
render_html_file() {
# h/t Devin Teske
awk -v title="$1" '
{ body = body "\n" $0 }
END {
body = substr(body, 2)
if (body ~ /<\/?[Hh][Tt][Mm][Ll]/) {
print body
exit
}
if (match(body, /<[[:space:]]*[Hh]1(>|[[:space:]][^>]*>)/)) {
t = substr(body, RSTART + RLENGTH)
sub("<[[:space:]]*/[[:space:]]*[Hh]1.*", "", t)
gsub(/^[[:space:]]*|[[:space:]]$/, "", t)
if (t) title = t " &mdash; " title
}
n = split(ENVIRON["HEADER"], header, /\n/)
for (i = 1; i <= n; i++) {
if (match(tolower(header[i]), "<title></title>")) {
head = substr(header[i], 1, RSTART - 1)
tail = substr(header[i], RSTART + RLENGTH)
print head "<title>" title "</title>" tail
} else print header[i]
}
print body
print ENVIRON["FOOTER"]
}'
}
list_pages() {
e="\\( -name '*.html' -o -name '*.md' \\)"
cd "$1" && eval "find . -type f ! -path '*/.*' ! -path '*/_*' $IGNORE $e" |
sed 's#^./##;s#.md$#.html#;s#/index.html$#/#'
}
render_sitemap() {
urls="$1"
base_url="$2"
date="$3"
echo '<?xml version="1.0" encoding="UTF-8"?>'
echo '<urlset'
echo 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
echo 'xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9'
echo 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"'
echo 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
echo "$urls" |
sed -E 's#^(.*)$#<url><loc>'"$base_url"'/\1</loc><lastmod>'"$date"'</lastmod><priority>1.0</priority></url>#'
echo '</urlset>'
}
render_nav() {
urls="$1"
base_url="$2"
title="$3"
contact_email="$4" # optional
echo '<header>'
echo '<nav>'
echo "<h2>${title}</h2>"
echo '<ul>'
echo "$urls" |
sed -E 's#^(.*)\.(.*)$# <li><a href="'"$base_url"'/\1.\2">\1</a></li>#'
test -n "$contact_email" &&
echo ' <li><a href="mailto:'"$contact_email"'">contact</a>'
echo '</ul>'
echo '</nav>'
echo '</header>'
echo '<main>'
}
main "$@"

View File

@ -1,2 +0,0 @@
</body>
</html>