#!/bin/sh set -eu # FIXMEs: # - feeds # - link to next and/or previous in
# - translation support # - validate input variables: regex for date (same as _plugins/linter.rb) # - `date -d` isn't POSIX # - parse commonmark and use a custom HTML emitter over regex
# - handle mixture of personal scripts
# - sitemap? How does it even work?
# - dark mode
# - generate security.txt dynamically
# - config.env should depend on dynamic.mk?
usage() {
cat <<-'EOF'
Usage:
genhtml.sh FILENAME
genhtml.sh -h
EOF
}
help() {
cat <<-'EOF'
Options:
-h, --help show this message
FILENAME the name of the input file, to also be used as
URL
Process the FILENAME, and generate a full HTML page.
The FILENAME is used to infer the output URL, by removing the
`src/content/` prefix, and replacing the trailing `.md` with
`.html`. This URL is used to build the self-referencing
"canonical" link, extracting plaintext snippets, etc.
Examples:
Generate the HTML for a pastebin:
$ sh genhtml.sh src/content/a-paste.md > src/content/a-paste.html
EOF
}
for f in "$@"; do
case "$f" in
--)
break
;;
--help)
usage
help
exit
;;
*)
;;
esac
done
while getopts 'h' flag; do
case "$flag" in
h)
usage
help
exit
;;
*)
usage >&2
exit 2
;;
esac
done
shift $((OPTIND - 1))
FILENAME="${1:-}"
eval "$(assert-arg "$FILENAME" 'FILENAME')"
#
# Utility functions
#
translate() {
printf '%s' "$1"
}
_() {
translate "$1" | htmlesc
}
SEEN_SLUGS="$(mkstemp)"
slugify_once() {
SLUG="$(printf '%s' "$1" | slugify)${2:+-$2}"
if grep -q "^$SLUG$" "$SEEN_SLUGS"; then
N="${2:-0}"
N=$((N + 1))
slugify_once "$1" "$N"
else
printf '%s\n' "$SLUG" >> "$SEEN_SLUGS"
printf '%s' "$SLUG"
fi
}
extract_content() {
awk '
separator >= 2
/^---$/ { separator++ }
'
}
add_preamble() {
printf '%s\n%s\n' "$PREAMBLE" "$(cat -)"
}
markdown_to_html() {
md2html
}
extract_plaintext_snippets() {
F="$(mkstemp)"
cat > "$F"
(
IFS=''
BLOCK_NUMBER=0
IN_BLOCK=
while read -r line; do
if [ "$line" = '
' ]; then
IN_BLOCK=
fi
if [ -n "$IN_BLOCK" ]; then
printf '%s\n' "$line" | htmlesc -d >> "$OUT"
fi
if printf '%s' "$line" | grep -q '^'; then IN_BLOCK=1 OUT="${FILENAME%.md}.html.$BLOCK_NUMBER.txt" BLOCK_NUMBER=$((BLOCK_NUMBER + 1)) printf '%s\n' "$line" | sed 's|^\( ' ]; then printf '\n' "$(url-for "$URL")" "$BLOCK_NUMBER" BLOCK_NUMBER=$((BLOCK_NUMBER + 1)) fi done < "$F" ) } add_line_numbers() { awk ' /^<\/code><\/pre>$/ { in_block = 0 printf "%s\n", $0 next } match($0, /^(\)\(.*\)$|\2|' | htmlesc -d > "$OUT" fi done < "$F" BLOCK_NUMBER=0 while read -r line; do printf '%s\n' "$line" if [ "$line" = ' )(.*)$/, a) { printf "%s ", a[1] n = 1 block_count++ printf "
\n", block_count, n, block_count, n, n, a[2] in_block = 1 next } in_block == 1 { n++ printf " %s %s \n", block_count, n, block_count, n, n, $0 next } { print } ' } add_headings_anchors() { ( IFS='' while read -r line; do if ! printf '%s' "$line" | grep -q '^ %s %s '; then printf '%s\n' "$line" continue fi LVL="$(printf '%s' "$line" | sed 's|^ .*|\1|')" HEADING="$(printf '%s' "$line" | sed 's|^ \(.*\) $|\1|')" SLUG="$(slugify_once "$HEADING")" printf '%s \n' \ "$LVL" \ "$SLUG" \ "$HEADING" \ "$SLUG" \ "$(url-for 'static/link.svg')" \ "$LVL" done ) } emit_body() { cat "$FILENAME" | extract_content | add_preamble | markdown_to_html | extract_plaintext_snippets | add_line_numbers | add_headings_anchors } # # Environment variables # . src/development/config.env eval "$( awk ' /^---$/ { if (++separator > 1) exit; else next; } { print } ' "$FILENAME" )" SITE_NAME="$(_ "EuAndreh's website")" TITLE="$(_ "${TITLE:-$SITE_NAME}")" URI_TITLE="$(printf '%s' "$TITLE" | uri)" URL="$(printf '%s' "$FILENAME" | sed -e 's|^src/content/||' -e 's|md$|html|')" PREAMBLE="$( cat <<-EOF # $TITLE EOF )" # # Main: generate the HTML to STDOUT. # cat <<-EOF$TITLE
EOF $(emit_body)