#!/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%.*}.conf" # # Utility functions # 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%.*}.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%.*}.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 "$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 ) warn_duplicate_ids() { F="$(mkstemp)" tee "$F" { grep "^$INDENT<h[2-6] class=\"header-anchor\" id=\"" | sed "s|^$INDENT<h[2-6] class=\"header-anchor\" id=\"\(.*\)\">.*<a href=.*$|\1|" | sort | uniq -c | awk -v F="$FILENAME" '$1 != 1 { printf "WARNING: duplicate header id: %s: %s\n", F, $2 }' } >&2 < "$F" rm "$F" } emit_body() { < "${FILENAME%.*}.content" \ markdown_to_html | extract_plaintext_snippets | add_line_numbers | add_headings_anchors | warn_duplicate_ids } if [ -r "$FILENAME".prev ]; then collection_head_prev_html="$( printf ' <link rel="prev" type="text/html" href="%s" />' \ "$(url-for < "$FILENAME".prev)" )" export collection_head_prev_html fi if [ -r "$FILENAME".next ]; then collection_head_next_html="$( printf ' <link rel="next" type="text/html" href="%s" />' \ "$(url-for < "$FILENAME".next)" )" export collection_head_next_html fi envsubst < src/lib/preamble.html | sed '/^$/d' emit_body | tee "${FILENAME%.*}.htmlbody" envsubst < src/lib/postamble.html | sed '/^$/d'