#!/bin/bash

# Generate HTML from txt2tags (.t2t) and Markdown (.md)
# Usage:
# - update_html
#   Look for all .t2t and .md files in the current directory and below,
#   generating the output HTML when the source is newer than the HTML.
# - update_html path/to/file.t2t path/to/another.md
#   Generate HTML for the specified file(s), ignoring modification time.
#
# Requires:
# - txt2tags for .t2t files. Tested with 2.6.
# - pandoc for both .t2t and .md files. Tested with 1.16.0.2 and 2.3.1.
# - the template file `template.html` in the same directory as this script.
#
# Tested with Ubuntu 16.04 and macOS Mojave.
#
# See also clean_html for removing the files generated by this script.

# Path to directory where this script is
# https://stackoverflow.com/a/246128/98600
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

# HTML template
template="$DIR/template.html"

# Render txt2tags into html file
# Arguments:
# 1. txt2tags source file, e.g. download/index.t2t
# 2. html target file, e.g. download/index.html
function render_t2t_html {
  t2t="$1"
  html="$2"
  tmp="$2.tmp"
  relroot="$( dirname $t2t | sed -E 's/^.\///' | sed -E 's/[^/]+/../g' )"

  # First render with txt2tags to handle pre/post processing
  txt2tags \
    --target=html \
    --no-headers \
    --quiet \
    --outfile="$tmp" \
    --infile="$t2t"

  # Replace <A NAME="toc3"></A> with <div id="toc3"></div> so that Pandoc retains it
  # Do this for both cases since BSD sed doesn't support /i
  sed -i.bak "s/<a name=\"\(.*\)\"><\/a>/<div id=\"\1\"><\/div>/" "$tmp"
  sed -i.bak "s/<A NAME=\"\(.*\)\"><\/A>/<div id=\"\1\"><\/div>/" "$tmp"
  rm -f "$tmp.bak"

  # Capture first 3 lines of t2t file: title, author, date
  # Documentation here: https://txt2tags.org/userguide/headerarea
  l1=$(head -n 1 "$t2t")
  l2=$(tail -n+2 "$t2t" | head -n 1)
  l3=$(tail -n+3 "$t2t" | head -n 1)
  title=
  author=
  date=
  if [ -n "$l1" ] ; then
    title="$l1"
    if [ -n "$l2" ] ; then author="$l2" ; fi
    if [ -n "$l3" ] ; then date="$l3" ; fi
  fi

  # Run txt2tag's HTML through Pandoc for cleanup
  pandoc \
    --from=html \
    --to=html5 \
    --standalone \
    --template="$template" \
    --variable="lang:en" \
    --variable="rel-root:$relroot" \
    --metadata="title:$title" \
    --metadata="author:$author" \
    --metadata="date:$date" \
    "$tmp" \
    --output="$html"
  rm -f "$tmp"

  # Final post-processing
  if [ -f "$html" ] ; then
    sed -i.bak "s/<table/<table class=\"table\"/" "$html" && rm "$html.bak"
    echo "$html"
  fi
}

# Render markdown into html file
# Arguments:
# 1. markdown source file, e.g. download/index.md
# 2. html target file, e.g. download/index.html
function render_md_html {
  md="$1"
  html="$2"
  relroot="$( dirname $md | sed -E 's/^.\///' | sed -E 's/[^/]+/../g' )"

  # Look for `show-toc: true` in metadata (first ten lines of file)
  if head -n 10 "$md" | grep --quiet 'show-toc: true' ; then
    tocflag='--table-of-contents'
  else
    tocflag=''
  fi

  pandoc \
    --from=markdown \
    --to=html5 \
    --standalone \
    $tocflag \
    --template="$template" \
    --variable="lang:en" \
    --variable="rel-root:$relroot" \
    "$md" \
    --output="$html"

  # Final post-processing
  if [ -f "$html" ] ; then
    # add "table" class to tables
    sed -i.bak "s/<table/<table class=\"table\"/" "$html"
    # rewrite anchors that Pandoc 1.16 ignores: [content]{#anchor} -> <span id="anchor">content</span>
    sed -i.bak -E "s/\[(.*)\]\{#(.+)\}/<span id=\"\2\">\1<\/span>/" "$html"
    rm -f "$html.bak"
    echo "$html"
  fi
}

# Main entry point
# Script can be run in one of two modes:
if [ $# -gt 0 ] ; then
  # Render specific file(s) from args, ignoring dates
  for file in "$@" ; do
    ext="${file##*.}"
    html="${file%.$ext}.html"
    case $ext in
      "md")
        render_md_html "$file" "$html"
        ;;
      "t2t")
        render_t2t_html "$file" "$html"
        ;;
    esac
  done
else
  # Render all files found in cwd and deeper if source is newer
  find . -name '*.t2t' | while read file ; do
    html="${file%.t2t}.html"
    if [ "$file" -nt "$html" ] || [ "$template" -nt "$html" ] ; then
      render_t2t_html "$file" "$html"
    fi
  done
  find . -name '*.md' | while read file ; do
    if [[ "$file" == *"README.md" ]] ; then continue ; fi
    html="${file%.md}.html"
    if [ "$file" -nt "$html" ] || [ "$template" -nt "$html" ] ; then
      render_md_html "$file" "$html"
    fi
  done
fi
