#!/bin/sh BASE_URL=https://ieks.cc/ TITLE=ieks.cc AUTHOR='Lucas Ieks' EMAIL=lucas@ieks.cc # TODO handle image links STYLE=' html { font-family: "Helvetica", "Arial", "Nimbus Sans L", sans-serif; background: #181408; color: #eeeeee; } body { max-width: 50rem; margin: 0 auto 25vh; } main { background: #eeeeee; color: #080808; padding: 1rem; } main a { color: darkblue; } @media (prefers-color-scheme: dark) { main { background: inherit; color: inherit; a { color: lightblue; } } } a { color: lightblue; text-decoration: none; } a:hover { color: grey; } h1 a, h2 a, h3 a, sup a { color: inherit; } nav, h1, h2, h3 { margin: 1rem 0; font-variant-caps: small-caps; text-wrap: balanced; } nav { margin-left: 1rem; padding-left: 0; } nav h1 { font-variant-caps: normal; } nav ul { margin: 0; padding: 0; } nav ul a::after { content: "\a0\2192"; } small { font-size: 0.75em; } nav ul, nav ol { list-style-type: none; padding: 0; margin: 0 0.5rem; } h1 { font-size: 2.618rem; } h2 { font-size: 1.618rem; } h3 { font-size: 1rem; } p, div, li, blockquote { line-height: 1.5; text-align: justify; hyphens: auto; text-wrap: pretty; } p { margin: 0; margin-top: 0.75rem; } img { width: 100%; } blockquote { margin: 0.5rem 1rem; } p:first-child, h1:first-child { margin-top: 0; } pre { padding-left: 1rem; line-height: 1.5; overflow-x: auto; } sup { line-height: 0; font-size: 0.618em; } footer { padding: 1rem; } footer p { font-size: 0.618rem; } ' # relpath file dir # slightly adjusted from https://stackoverflow.com/a/14914070 (CC BY-SA 3.0) relpath () { current="${2:+"$1"}" target="${2:-"$1"}" [ "$target" = . ] && target=/ target="/${target##/}" [ "$current" = . ] && current=/ current="${current:="/"}" current="/${current##/}" appendix="${target##/}" relative='' while appendix="${target#"$current"/}" [ "$current" != '/' ] && [ "$appendix" = "$target" ] do if [ "$current" = "$appendix" ]; then relative="${relative:-.}" printf '%s\n' "${relative#/}" return 0 fi current="${current%/*}" relative="$relative${relative:+/}.." done relative="$relative${relative:+${appendix:+/}}${appendix#/}" printf '%s\n' "$relative" } TABLE_OF_CONTENTS=' function esc(i) { gsub(/&/, "\\&", i) gsub(//, "\\>", i) gsub(/"/, "\\"", i) return i } function rep(i) { gsub(/&/, "\\&", i) gsub(/---/, "\\—", i) gsub(/--/, "\\–", i) gsub(/->/, "\\→", i) gsub(//, "\\>", i) gsub(/"/, "\\"", i) return i } BEGIN { print "" } ' BODY=' function esc(i) { gsub(/&/, "\\&", i) gsub(//, "\\>", i) gsub(/"/, "\\"", i) return i } function rep(i) { gsub(/&/, "\\&", i) gsub(/---/, "\\—", i) gsub(/--/, "\\–", i) gsub(/->/, "\\→", i) gsub(//, "\\>", i) gsub(/"/, "\\"", i) return i } BEGIN { MODE = "text" } MODE == "code" && /^```/ { print ""; MODE = "text"; next } MODE == "code" { print esc($0); next } /^```/ { if (MODE == "par") print "

"; printf "
"; MODE = "code"; next }

	MODE != "list" && /^\*/ { if (MODE == "par") print "

"; print ""; MODE = "text" } /^###/ { sub(/^###[[:space:]]*/, "") h3++ LINK = h1 "." h2 "." h3 print "

" rep($0) "

" next } /^##[^#]/ { sub(/^##[[:space:]]*/, "") h2++ h3 = 0 LINK = h1 "." h2 print "

" rep($0) "

" next } /^#[^#]/ { sub(/^#[[:space:]]*/, "") h1++ h2 = 0 LINK = h1 print "

" rep($0) "

" next } /^[[:space:]]*$/ { if (MODE == "par") print "

"; MODE = "text"; next } /^>/ { if (MODE == "par") print "

" sub(/^>[[:space:]]*/, "") print "
" rep($0) "
" MODE = "text" next } MODE == "par" { print "
" } MODE == "text" { printf "

"; MODE = "par" } /^\[[[:lower:]]+\]/ { match($0, /\[[[:lower:]]+\]/) letter = substr($0, RSTART, RLENGTH) printf "%s", LINK, letter, rep($0) next } /^---/ { printf "%s", rep($0); next } /^=>/ && $2 ~ /\.(jpg|png)$/ { href = esc($2) sub(/^=>[[:space:]]*[^[:space:]]+[[:space:]]*/, "") if (match($0, /\[[[:lower:]]+\]/)) { letter = substr($0, RSTART, RLENGTH) $0 = "" rep($0) "" } else if (/^---/) { $0 = "" rep($0) "" } else { $0 = "\""" } print "" $0 "" next } /^=>/ { href = esc($2) if (href !~ /^gemini:\/\//) sub(/\.gmi$/, ".html", href) sub(/^=>[[:space:]]*[^[:space:]]+[[:space:]]*/, "") if (match($0, /\[[[:lower:]]+\]/)) { letter = substr($0, RSTART, RLENGTH) $0 = "" rep($0) "" } else if (/^---/) { $0 = "" rep($0) "" } else { $0 = rep($0) } print "" $0 "" next } { $0 = rep($0) gsub(/\[[[:lower:]]+\]/, "&") printf "%s", $0 MODE = "par" } END { if (MODE == "par") print "

" } ' rm -rf .out/www .out/gmi mkdir -p .out/www .out/gmi find . ! \( -path '*/.*' -prune \) ! \( -name '*.gmi' -o -name '*.html' -o -name '*.css' -o -name '*.js' \) -type f | while read file; do mkdir -p ".out/gmi/$(dirname "$file")" ".out/www/$(dirname "$file")" printf 'copy %s\n' "$file" >&2 cp "$file" .out/gmi/"$file" cp "$file" .out/www/"$file" done find . ! \( -path '*/.*' -prune \) -name '*.gmi' -type f | while read file; do published=$(sed -n 's/^Written:[[:space:]]*//p' "$file") updated=$(sed -n 's/^Revised:[[:space:]]*//p' "$file") [ "$updated" ] || updated=$published [ "$published" ] || [ "$(basename "$file")" = index.gmi ] || continue mkdir -p ".out/www/$(dirname "$file")" ".out/gmi/$(dirname "$file")" printf 'gmi %s\n' "$file" >&2 ( printf '=> / %s\n' "$TITLE" if [ "$(basename "$file")" != index.gmi ]; then printf '=> index.gmi up\n' elif [ "$(dirname "$file")" != . ]; then printf '=> ../ up\n' fi printf '\n' cat "$file" printf '\nCopyright © %s' "${published%-*-*}" [ "${published%-*-*}" != "${updated%-*-*}" ] && printf '–%s' "${updated%-*-*}" printf ' by Lucas Ieks.\n' printf 'Licensed under CC-BY-SA 4.0, unless stated otherwise.\n' printf 'Some rights reserved.\n' ) > ".out/gmi/$file" printf 'www %s\n' "${file%.gmi}.html" >&2 ( lang=$(sed -n 's/^Language:[[:space:]]*//p' "$file") printf '' printf '\n' printf '\n' "$TITLE" "${BASE_URL}atom.xml" printf '%s\n' "$(sed -n 's/^#[^#][[:space:]]*//p' "$file" | head -1)" printf '' "$STYLE" "${lang:-en}" printf '' printf '
' awk "$BODY" "$file" printf '
' printf '

' printf 'Copyright © %s' "${published%-*-*}" [ "${published%-*-*}" != "${updated%-*-*}" ] && printf '–%s' "${updated%-*-*}" printf ' by Lucas Ieks.
' printf 'Licensed under CC-BY-SA 4.0, unless stated otherwise.
' printf 'Some rights reserved.' printf '

' ) > ".out/www/${file%.gmi}.html" done find . ! \( -path '*/.*' -prune \) -name '*.html' -type f | while read file; do mkdir -p ".out/www/$(dirname "$file")" printf 'copy %s\n' "$file" >&2 cp "$file" .out/www/"$file" done ( printf '=> / %s\n\n' "$TITLE" printf '# %s\n' "$TITLE" find . ! \( -path '*/.*' -prune \) -name '*.gmi' -type f | while read file; do published=$(sed -n 's/^Written:[[:space:]]*//p' "$file") updated=$(sed -n 's/^Revised:[[:space:]]*//p' "$file") [ "$updated" ] || updated=$published [ "$published" ] || continue printf 'gmi feed %s\n' "$file" >&2 url="$(relpath "$PWD" "$(realpath "${file%.gmi}.html")")" title=$(sed -n 's/^#[^#][[:space:]]*//p' "$file" | head -1) printf '=> %s %s — %s\n' "$url" "$updated" "$title" done ) > .out/gmi/feed.gmi ( printf '' printf '' printf '%s' "$BASE_URL" printf '%s' "$TITLE" printf '%s' "$(date -Iseconds)" printf '' "${BASE_URL}atom.xml" printf '' printf '%s' "$AUTHOR" printf '%s' "$EMAIL" printf '' printf '%s' "${BASE_URL}$(relpath "$PWD" "$(realpath "$0")")" "$0" find . ! \( -path '*/.*' -prune \) -name '*.gmi' -type f | while read file; do published=$(sed -n 's/^Written:[[:space:]]*//p' "$file") updated=$(sed -n 's/^Revised:[[:space:]]*//p' "$file") [ "$updated" ] || updated=$published url="${BASE_URL}$(relpath "$PWD" "$(realpath "${file%.gmi}.html")")" [ "$published" ] || continue printf 'www feed %s\n' "$file" >&2 printf '' printf '%s' "$(sed -n 's/^#[^#][[:space:]]*//p' "$file" | head -1)" printf '' "$url" printf '%s' "$url" printf '%s' "$(date -Iseconds -d "$published")" printf '%s' "$(date -Iseconds -d "$updated")" printf '' done printf '' ) > .out/www/atom.xml cp gmiweb .out/gmi/gmiweb cp gmiweb .out/www/gmiweb ( cd .out/www tar -cz * > ../www.tar.gz ) ( cd .out/gmi tar -cz * > ../gmi.tar.gz )