#!/usr/bin/env python3

# This is free and unencumbered software released into the public domain.

from argparse import ArgumentParser

aparser = ArgumentParser(description="""
Compiles a Markdown file into a complete HTML file with a table of
contents. Requires markdown to be installed.
""")
aparser.add_argument('mdfile')
args = aparser.parse_args()

from subprocess import run
from html.parser import HTMLParser
from io import StringIO
from re import compile

proc = run(['markdown', args.mdfile], capture_output=True)
output = proc.stdout.decode('utf8')

hpat = compile(r'h([123456])')
hlinepat = compile(r'<h[23456]>')
alnum = compile(r'[a-zA-Z0-9_]+')

def makeid(data):
	chunks = []
	for m in alnum.finditer(data):
		chunks.append(m.group(0))
	return ''.join(chunks).lower()

class Parser(HTMLParser):
	def __init__(self):
		self.title = ''
		self.tree = []
		self.idlist = []
		self.hlevel = None
		super().__init__()

	def handle_starttag(self, tag, attrs):
		if (m := hpat.match(tag)):
			self.hlevel = int(m.group(1))
			self.content = ''

	def handle_data(self, data):
		if self.hlevel:
			self.content += data

	def handle_endtag(self, tag):
		if (m := hpat.match(tag)):
			if m.group(1) == '1':
				self.title = self.content
			else:
				tree = self.tree
				idsrc = ''
				for _ in range(2, self.hlevel):
					idsrc += tree[-1][0] + '_'
					tree = tree[-1][2]
				idsrc += self.content
				self.idlist.append(makeid(idsrc))
				tree.append((self.content, makeid(idsrc), []))
			self.hlevel = None

parser = Parser()
parser.feed(output)

print("""<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>%s</title>
<style>
body {
	max-width: 50rem;
	margin: auto;
	padding-left: 0.5rem;
	padding-right: 0.5rem;
}
</style>
</head>
<body>
""" % parser.title)

def print_tree(tree):
	print('<ul>')
	for label, id_, subtree in tree:
		print('<li>')
		print(f'<a href="#{id_}">{label}</a>')
		if subtree:
			print_tree(subtree)
		print('</li>')
	print('</ul>')

hindex = 0
for line in output.split('\n'):
	if (m := hlinepat.search(line)):
		if hindex == 0:
			print('<nav>')
			print('<h2>Contents</h2>')
			print_tree(parser.tree)
			print('</nav>\n')
		start, end = m.span()
		id_ = parser.idlist[hindex]
		print(line[:end - 1] + f' id="{id_}"' + line[end - 1:])
		hindex += 1
	else:
		print(line)

print("</body>\n</html>")
