#!/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; } 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; } 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; } ' # 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 "

" } ' find . ! \( -path '*/.*' -prune \) -name '*.gmi' -type f | while read file; do printf 'convert %s\n' "${file%.gmi}.html" ( 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 '
' ) > "${file%.gmi}.html" done printf '' > atom.xml printf '' >> atom.xml printf '%s' "$BASE_URL" >> atom.xml printf '%s' "$TITLE" >> atom.xml printf '%s' "$(date -Iseconds)" >> atom.xml printf '' "${BASE_URL}atom.xml" >> atom.xml printf '' >> atom.xml printf '%s' "$AUTHOR" >> atom.xml printf '%s' "$EMAIL" >> atom.xml printf '' >> atom.xml printf '%s' "${BASE_URL}$(relpath "$PWD" "$(realpath "$0")")" "$0" >> atom.xml 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 'atom %s\n' "$file" printf '' >> atom.xml printf '%s' "$(sed -n 's/^#[^#][[:space:]]*//p' "$file" | head -1)" >> atom.xml printf '' "$url" >> atom.xml printf '%s' "$url" >> atom.xml printf '%s' "$(date -Iseconds -d "$published")" >> atom.xml printf '%s' "$(date -Iseconds -d "$updated")" >> atom.xml printf '' >> atom.xml done printf '' >> atom.xml