From 05b50d5c5f1db5478e50ff50b3e86cdad03ca8ef Mon Sep 17 00:00:00 2001 From: sceox Date: Tue, 4 Jan 2022 09:39:23 -0800 Subject: [PATCH] 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. --- .gitignore | 1 + Makefile | 13 ++ README.md | 66 +++++---- config.mk | 10 ++ foot.html | 2 - head.html | 5 - nav.html | 6 - publish.sh | 30 ---- src/_header.html | 7 + {md => src}/index.md | 0 {md => src}/projects.md | 0 style.css => src/style.css | 0 {md => src}/webring.md | 0 ssg6 | 275 +++++++++++++++++++++++++++++++++++++ tail.html | 2 - 15 files changed, 337 insertions(+), 80 deletions(-) create mode 100644 Makefile create mode 100644 config.mk delete mode 100644 foot.html delete mode 100644 head.html delete mode 100644 nav.html delete mode 100755 publish.sh create mode 100644 src/_header.html rename {md => src}/index.md (100%) rename {md => src}/projects.md (100%) rename style.css => src/style.css (100%) rename {md => src}/webring.md (100%) create mode 100755 ssg6 delete mode 100644 tail.html diff --git a/.gitignore b/.gitignore index a9a5aec..f59e889 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +dst tmp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b975eca --- /dev/null +++ b/Makefile @@ -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 diff --git a/README.md b/README.md index 23e5cf6..4154ee9 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..8032150 --- /dev/null +++ b/config.mk @@ -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 diff --git a/foot.html b/foot.html deleted file mode 100644 index 921ba2a..0000000 --- a/foot.html +++ /dev/null @@ -1,2 +0,0 @@ - diff --git a/head.html b/head.html deleted file mode 100644 index d8de143..0000000 --- a/head.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/nav.html b/nav.html deleted file mode 100644 index 31d5658..0000000 --- a/nav.html +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/publish.sh b/publish.sh deleted file mode 100755 index 6d343ea..0000000 --- a/publish.sh +++ /dev/null @@ -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 • Anarchy Planet" >> tmp/head.html - echo " " >> tmp/head.html - echo " " >> 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 diff --git a/src/_header.html b/src/_header.html new file mode 100644 index 0000000..b711279 --- /dev/null +++ b/src/_header.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/md/index.md b/src/index.md similarity index 100% rename from md/index.md rename to src/index.md diff --git a/md/projects.md b/src/projects.md similarity index 100% rename from md/projects.md rename to src/projects.md diff --git a/style.css b/src/style.css similarity index 100% rename from style.css rename to src/style.css diff --git a/md/webring.md b/src/webring.md similarity index 100% rename from md/webring.md rename to src/webring.md diff --git a/ssg6 b/ssg6 new file mode 100755 index 0000000..e609ce1 --- /dev/null +++ b/ssg6 @@ -0,0 +1,275 @@ +#!/bin/sh -e +# +# https://rgz.ee/bin/ssg6 +# Copyright 2018-2019 Roman Zolotarev +# +# 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 " — " title + } + n = split(ENVIRON["HEADER"], header, /\n/) + for (i = 1; i <= n; i++) { + if (match(tolower(header[i]), "")) { + head = substr(header[i], 1, RSTART - 1) + tail = substr(header[i], RSTART + RLENGTH) + print head "" 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 '' + echo '' + echo "$urls" | + sed -E 's#^(.*)$#'"$base_url"'/\1'"$date"'1.0#' + echo '' +} +render_nav() { + urls="$1" + base_url="$2" + title="$3" + contact_email="$4" # optional + + echo '
' + echo '' + echo '
' + echo '
' +} + +main "$@" diff --git a/tail.html b/tail.html deleted file mode 100644 index b605728..0000000 --- a/tail.html +++ /dev/null @@ -1,2 +0,0 @@ - -