aboutsummaryrefslogblamecommitdiff
path: root/v2/src/development/genhtml.sh
blob: f3a6e3ac66b27fed59c79361d9c3ae4ca80bed28 (plain) (tree)
1
2
3


         
































































                                                                                     
                        

                 
                                           
 
 
                             
                        




                   












                                                      
                 
                    



















                                                   


                              

                                           











                                                              
                                                                            

                          
                                                                                   



                                                                            
                                                                                      
                                                           
                                                                   







                                                              


                                                                                                       














                                                                  
                                                         


































                                                                                                                                                                                             
                                                                





                                      
                                     





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


# shellcheck source=/dev/null
. "${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
}

INDENT='        '
markdown_to_html() {
	md2html | awk -vINDENT="$INDENT" '
		BEGIN {
			in_block = 0
		}

		{
			if (in_block == 0) {
				printf "%s", INDENT
			}
			print
		}

		/^<\/code><\/pre>$/ {
			in_block = 0
		}

		/^<pre><code/ {
			in_block = 1
		}
	'
}

extract_plaintext_snippets() {
	SNIPPETS="${FILENAME%.md}.snippets"
	rm -f "$SNIPPETS"
	F="$(mkstemp)"
	cat > "$F"
	(
		IFS=''
		BLOCK_NUMBER=0
		IN_BLOCK=
		while read -r line; do
			if [ "$line" = '</code></pre>' ]; then
				IN_BLOCK=
			fi

			if [ -n "$IN_BLOCK" ]; then
				printf '%s\n' "$line" | htmlesc -d >> "$OUT"
			fi

			if printf '%s' "$line" | grep -q "^$INDENT<pre><code"; then
				IN_BLOCK=1
				OUT="${FILENAME%.md}.html.$BLOCK_NUMBER.txt"
				BLOCK_NUMBER=$((BLOCK_NUMBER + 1))
				printf '%s\n' "$line" |
					sed "s|^\($INDENT<pre><code.*>\)\(.*\)$|\2|" |
					htmlesc -d > "$OUT"
				printf '%s\n' "$OUT" >> "$SNIPPETS"
			fi
		done < "$F"

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

			if [ "$line" = '</code></pre>' ]; then
				printf '%s<p class="plaintext-link"><a href="%s">plaintext</a></p>\n' \
					"$INDENT" \
					"$(basename "${url_part:?}").$BLOCK_NUMBER.txt"
				BLOCK_NUMBER=$((BLOCK_NUMBER + 1))
			fi
		done < "$F"
	)

}

add_line_numbers() {
	awk '
		/^<\/code><\/pre>$/ {
			in_block = 0
			printf "</tbody></table>%s\n", $0
			next
		}

		match($0, /^( +<pre><code.*>)(.*)$/, a) {
			printf "%s<table rules=columns class=\"code-block\"><tbody>", a[1]

			n = 1
			block_count++
			printf "<tr><td class=\"line-number\"><a id=\"B%s-L%s\" href=\"#B%s-L%s\">%s</a></td><td class=\"code-line\">%s</td></tr>\n", block_count, n, block_count, n, n, a[2]
			in_block = 1
			next
		}

		in_block == 1 {
			n++
			printf "<tr><td class=\"line-number\"><a id=\"B%s-L%s\" href=\"#B%s-L%s\">%s</a></td><td class=\"code-line\">%s</td></tr>\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 '^<h[2-6]>'; then
				printf '%s\n' "$line"
				continue
			fi
			LVL="$(printf '%s' "$line" | sed 's|^<h\(.\)>.*|\1|')"
			HEADING="$(printf '%s' "$line" | sed 's|^<h.>\(.*\)</h.>$|\1|')"
			SLUG="$(slugify_once "$HEADING")"
			printf '<h%s class="header-anchor" id="%s">%s<a href="#%s" aria-hidden="true"><img class="svg-icon" src="%s" /></a></h%s>\n' \
				"$LVL"     \
				"$SLUG"    \
				"$HEADING" \
				"$SLUG"    \
				"$(url-for 'static/link.svg')" \
				"$LVL"
		done
	)
}

emit_body() {
	< "${FILENAME%.md}.content" \
		markdown_to_html           |
		extract_plaintext_snippets |
		add_line_numbers           |
		add_headings_anchors
}

envsubst < src/lib/preamble.html
emit_body
envsubst < src/lib/postamble.html