#!/bin/sh set -eu 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)) . src/development/lib.sh FILENAME="${1:-}" eval "$(assert_arg "$FILENAME" 'FILENAME')" . "${FILENAME%.md}.conf" # # Utility functions # 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 } 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|^\(
\)\(.*\)$|\2|' |
					htmlesc -d > "$OUT"
			fi
		done < "$F"

		BLOCK_NUMBER=0
		while read -r line; do
			printf '%s\n' "$line"

			if [ "$line" = '
' ]; 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, /^(
)(.*)$/, 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 "\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 '^'; 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%.md}.entry-content" |
		markdown_to_html           |
		extract_plaintext_snippets |
		add_line_numbers           |
		add_headings_anchors
}





#
# Main: generate the HTML to STDOUT.
#

cat <<-EOF
	
	
	  
	    
	    
	    
	    

	    $$title_html

	    
	    
	    
	    

	    
	    
	  
	  
	    

\$(emit_body)
EOF exit .md.rehtml: F="$<"; . "$${F%.md}.conf"; envsubst < src/lib/reamble."$$lang".html > $@ .md.osthtml: F="$<"; . "$${F%.md}.conf"; envsubst < src/lib/ostamble."$$lang".html > $@
EOF # 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?
%s%s
%s%s