--- /dev/null
+
+# TODO: Implement quoting properly
+function quote_html(s) { return s; }
+function quote_html_attribute(s) { return gensub("\"", """, "g", s) }
+
+BEGIN {
+ FS = ":"
+ num_rows = 0
+ num_cols = 0
+ read_header = 1
+ # h/t https://wabain.github.io/2019/10/13/css-rotated-table-header.html
+ print "<html><head><style>"
+ print "th, td { white-space: nowrap; }"
+ print "th { text-align: left; font-weight: normal; }"
+ print "table { border-collapse: collapse }"
+ print "tr.key > th { height: 8em; vertical-align: bottom; line-height: 1 }"
+ print "tr.key > th > div { width: 1em; }"
+ print "tr.key > th > div > div { width: 5em; transform-origin: bottom left; transform: translateX(1em) rotate(-65deg) }"
+ print "td { border: thin solid gray; }"
+ print "td.numeric { text-align: right; }"
+ print "td.yes { border: thin solid gray; background-color: gray; }"
+ print "td.spacer { border: none; }"
+ # h/t https://stackoverflow.com/questions/5687035/css-bolding-some-text-without-changing-its-containers-size/46452396#46452396
+ print ".highlight { text-shadow: -0.06ex 0 black, 0.06ex 0 black; }"
+ print "img { height: 1.2em; }"
+ print "</style><script>"
+ print "function highlight(id) { const e = document.getElementById(id); if (e) { e.classList.add(\"highlight\"); } }"
+ print "function clear_highlight(id) { const e = document.getElementById(id); if (e) { e.classList.remove(\"highlight\"); } }"
+ print "function h2(a, b) { highlight(a); highlight(b); }"
+ print "function ch2(a, b) { clear_highlight(a); clear_highlight(b); }"
+ print "</script></head><body><table><tbody>"
+}
+
+END {
+ printf "<tr class=\"key\"><th></th>"
+ for (i=0; i < num_cols; i++) {
+ printf "<th id=\"%s\"><div><div>%s</div></div></th>", quote_html_attribute(col_headers[i]), quote_html(col_headers[i])
+ }
+ print "</tr>";
+ for (i=1*skip_rows; i <= num_rows; i++) {
+ spacer_row = substr(row_headers[i], 1, 1) == "!"
+ row_header = spacer_row ? substr(row_headers[i], 2) : row_headers[i]
+ printf "<tr><th id=\"%s\">%s</th>", quote_html_attribute(row_header), quote_html(row_header)
+ for (j = 0;j < num_cols; j++) {
+ printf "<td "
+ printf "onmouseover=\"h2('%s','%s')\" ", quote_html_attribute(row_header), quote_html_attribute(col_headers[j])
+ printf "onmouseout=\"ch2('%s','%s')\" ", quote_html_attribute(row_header), quote_html_attribute(col_headers[j])
+ printf "class=\""
+ if (rows[i][j] == " ") { printf " yes " }
+ if (rows[i][j] ~ /^[0-9]+$/) { printf " numeric " }
+ if (spacer_row || substr(col_headers[j], 0, 4) == "<!--") { printf " spacer " }
+ printf "\">" rows[i][j] "</td>"
+ }
+ print "</tr>"
+ }
+ print "</tbody></table></body></html>"
+}
+
+{
+ if (/^$/) {
+ read_header = 1
+ num_rows++
+ } else {
+ if (read_header) {
+ read_header = 0
+ row_headers[num_rows] = $0
+ } else {
+ if (! ($1 in col_index)) {
+ col_headers[num_cols] = $1
+ col_index[$1] = num_cols++
+ }
+ rows[num_rows][col_index[$1]] = $2 ? $2 : " "
+ }
+ }
+}