aboutsummaryrefslogblamecommitdiff
path: root/v2/src/bin/html
blob: 7e6809c4784806b3c0e7e7487de6326a9e15878d (plain) (tree)
1
2
3
4
5
6
7
8


         


                      

                               





                    
 


                                                 
                                                                   



                                                                    




                                                   
                                                            

































                                 
            

                 
                                           
 
 
                             
                        




                   












                                                      
                 
                    



















                                                   


                              
                                           
                               











                                                              
                                                                            

                          
                                                                                   



                                                                            
                                                                                      
                                                           
                                                                   







                                                              


                                                                                                       














                                                                  
                                                         






















                                                                                                                                                                                             
                                                                                   


                                                     

                                                                                               
                                                         

                                                                                                                                                        



                                            
                                                      





                                      
                                     





                                            
                                
                                          
                                 
#!/bin/sh
set -eu

usage() {
	cat <<-'EOF'
		Usage:
		  html FILENAME
		  html -h
	EOF
}

help() {
	cat <<-'EOF'


		Options:
		  -h, --help    show this message

		  FILENAME      the name of the input file .md file


		Process the FILENAME, and generate a full HTML page.


		Examples:

		  Generate the HTML for a pastebin:

		    $ html src/a-paste.md > src/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/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"
	printf '' > "$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 "^$INDENT<h[2-6]>"; then
				printf '%s\n' "$line"
				continue
			fi
			LVL="$(printf '%s' "$line" | sed "s|^$INDENT<h\(.\)>.*|\1|")"
			HEADING="$(printf '%s' "$line" | sed "s|^$INDENT<h.>\(.*\)</h.>$|\1|")"
			SLUG="$(slugify_once "$HEADING")"
			printf '%s<h%s class="header-anchor" id="%s">%s<a href="#%s" aria-hidden="true"><img class="svg-icon" src="%s" /></a></h%s>\n' \
				"$INDENT"  \
				"$LVL"     \
				"$SLUG"    \
				"$HEADING" \
				"$SLUG"    \
				"${icon_link_url:?}" \
				"$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 | tee "${FILENAME%.md}.htmlbody"
envsubst < src/lib/postamble.html