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:
parent
5f0252aedc
commit
05b50d5c5f
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
|
dst
|
||||||
tmp
|
tmp
|
||||||
|
13
Makefile
Normal file
13
Makefile
Normal 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
|
66
README.md
66
README.md
@ -1,26 +1,20 @@
|
|||||||
# Anarchy Planet web site
|
# Anarchy Planet web site
|
||||||
|
|
||||||
This repo is to generate a static site for anarchyplanet.org to
|
This repo includes markdown files for [the Anarchy Planet web
|
||||||
replace the existing site. The goal is to generate the site from
|
site](https://anarchyplanet.org/) and tools to generate a static
|
||||||
markdown files by converting the markdown to html and applying minimal
|
HTML site from the source files.
|
||||||
styling.
|
|
||||||
|
|
||||||
The advantage to this method is that all of the content can be
|
You can see this method in action at
|
||||||
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
|
|
||||||
[https://testing.anarchyplanet.org](https://testing.anarchyplanet.org).
|
[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
|
## Dependencies
|
||||||
|
|
||||||
We use [lowdown](https://kristaps.bsd.lv/lowdown/) for markdown
|
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
|
* [lowdown(5)](https://kristaps.bsd.lv/lowdown/lowdown.5.html) which
|
||||||
describes the lanuage syntax
|
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
|
## TODOs
|
||||||
|
|
||||||
### TODO discuss and decide on sections
|
* [ ] TODO discuss and decide on sections
|
||||||
|
- notnull's proposals for the sections are:
|
||||||
notnull's proposals for the sections are:
|
* home
|
||||||
|
* projects (not services)
|
||||||
- home
|
* webring (instead of 'others')
|
||||||
- projects (not services)
|
* contact (probably just a mailto: link)
|
||||||
- webring (instead of 'others')
|
* [ ] write copy for sections
|
||||||
- contact (probably just a mailto: link)
|
- What rocinante has done on
|
||||||
|
[anarchist news](https://anarchistnews.org/content/anarchy-planet)
|
||||||
### TODO write copy for sections
|
is already pretty great. Maybe these could be more verbose, but
|
||||||
|
maybe they are fine the way they are!
|
||||||
What rocinante has done on
|
* [ ] add a favicon
|
||||||
[anarchist news](https://anarchistnews.org/content/anarchy-planet) is
|
* [ ] use an automatic toc generator
|
||||||
already pretty great. Maybe these could be more verbose, but maybe
|
- and add to Makefile (make toc)
|
||||||
they are fine the way they are!
|
- see https://github.com/ekalinin/github-markdown-toc
|
||||||
|
|
||||||
### TODO we need a favicon
|
|
||||||
|
10
config.mk
Normal file
10
config.mk
Normal 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
|
@ -1,5 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
6
nav.html
6
nav.html
@ -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>
|
|
30
publish.sh
30
publish.sh
@ -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
7
src/_header.html
Normal 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
275
ssg6
Executable 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 " — " 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 "$@"
|
Loading…
Reference in New Issue
Block a user