#!/usr/bin/awk -f BEGIN { true = "true" false = "false" preformat_toggle = false preformat_start = false preformat_title = "" body_padding = " " if (LANG == "") { LANG = "en" } if (TOC == "") { TOC = false } if (INLINE == "") { INLINE = true } delete TABLE_OF_CONTENTS if (TOC == true) { create_toc(ARGV[1], TABLE_OF_CONTENTS) } print "<!DOCTYPE html>" print "<html lang=\"" LANG "\">" print " <head>" print " <meta charset=\"utf-8\">" print " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" print " <title>" basename(ARGV[1]) "</title>" print " <style>" print embedded_css(CSS) print " </style>" print " </head>" print " <body>" } function embedded_css(css_file, _embedded_css) { _embedded_css = "\ html {\n\ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;\n\ font-weight: 400;\n\ font-size: 16px;\n\ -ms-text-size-adjust: 100%;\n\ -webkit-text-size-adjust: 100%;\n\ margin: 16px;\n\ }\n\ \n\ body {\n\ line-height: 1.5rem;\n\ max-width: 64em;\n\ margin: auto;\n\ }\n\ \n\ h1, h2, h3, p, figure, blockquote, ul, li, a {\n\ /* Don't break out */\n\ overflow-wrap: break-word;\n\ word-wrap: break-word;\n\ margin-block-start: 0px;\n\ margin-block-end: 0px;\n\ }\n\ \n\ h1, h2, h3 {\n\ line-height: 1.2em;\n\ font-weight: bold;\n\ }\n\ \n\ h1 {\n\ font-size: 2.5em;\n\ }\n\ \n\ h2 {\n\ font-size: 2em;\n\ }\n\ \n\ h3 {\n\ font-size: 1.5em;\n\ }\n\ \n\ pre {\n\ overflow-x: scroll;\n\ background-color: rgb(245,245,245);\n\ padding-left: 1em;\n\ padding-right: 1em;\n\ padding-top: 0.5em;\n\ padding-bottom: 0.5em;\n\ margin-top: 0px;\n\ margin-bottom: 0px;\n\ line-height: 1.3em;\n\ font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;\n\ font-size: 0.95em;\n\ }\n\ \n\ figure {\n\ margin-inline-start: 0px;\n\ margin-inline-end: 0px;\n\ }\n\ \n\ figcaption {\n\ font-size: 0.75em;\n\ }\n\ \n\ blockquote:before, blockquote:after {\n\ content: \"\";\n\ }\n\ \n\ blockquote {\n\ border-left: 6px solid #ccc;\n\ padding-left: 0.5em;\n\ margin-top: 0px;\n\ margin-bottom: 0px;\n\ margin-left: 0.5em;\n\ }\n\ \n\ li {\n\ padding-top: 0px;\n\ }\n\ \n\ a {\n\ color: #33adff;\n\ outline: 0 none;\n\ text-decoration: none;\n\ }\n\ \n\ a:not([href^=\"#\"])::before {\n\ content: \"ยง \";\n\ }\n\ \n\ a[href^=\"#\"] {\n\ color: #4a5277;\n\ }\n\ \n\ img {\n\ max-width: 100%;\n\ }\n\ \n\ /* Mobile view */\n\ @media (max-width: 600px) {\n\ body {\n\ margin: 8px;\n\ }\n\ }\n\ \n\ @media print {\n\ a:not([href^=\"#\"]):not([data-noprint])::after {\n\ content: \" (\" attr(href) \") \";\n\ }\n\ }" if (css_file != "") { _embedded_css = "" while (getline <css_file > 0) { if (_embedded_css == "") { _embedded_css = _embedded_css " " $0 } else { _embedded_css = _embedded_css "\n " $0 } } close(css_file) } return _embedded_css } function escape_html(s) { gsub(/&/,"\\&",s) gsub(/</,"\\<",s) gsub(/>/,"\\>",s) return s } function escape_attribute(s) { escape_html(s) gsub(/"/,"\\"",s) return s } function basename(file, _a1, _a2, _n1) { _n1 = split(file, _a1, "/") split(_a1[_n1], _a2, ".") return _a2[1] } function is_image(url, _suffix) { sub(/^[ \t]+/,"",url) sub(/[ \t]+$/,"",url) _suffix = tolower(substr(url,length(url)-3)) if (_suffix == ".png" || _suffix == ".jpg") { return true } else { return false } } function print_heading(type, heading, _id) { heading = create_heading(heading) if (TOC == true) { _id = " id=\"" create_id(heading) "\"" } else { _id = "" } if (TOC == true) { print body_padding "<" type _id "><a href=\"#\">" escape_html(heading) "</a></" type ">" } else { print body_padding "<" type _id ">" escape_html(heading) "</" type ">" } } function create_heading(string) { sub(/^(###|##|#)[ \t]*/,"",string) sub(/^[ \t]+/,"",string) sub(/[ \t]+$/,"",string) return string } function create_id(string) { sub(/^[ \t]+/,"",string) sub(/[ \t]+$/,"",string) gsub(/[ \t]/,"-",string) gsub(/[^0-9a-zA-Z\-]/,"",string) return tolower(string) } function create_toc(file, toc, _preformat_toggle, _toc_count) { _preformat_toggle = false _toc_count = 0 while (getline <file > 0) { if ($0 ~ /^```/) { if (_preformat_toggle == false) { _preformat_toggle = true } else { _preformat_toggle = false } } else if ($0 ~ /^(###|##|#)[ \t]*/ && _preformat_toggle == false) { toc[++_toc_count] = $0 } } toc["size"] = _toc_count close(file) } function print_toc(toc, _heading, _id, _indent, _size, _i) { _size = toc["size"] for (_i = 1; _i <= _size; _i++) { _heading = toc[_i] _indent = "" if (_heading ~ /^###/) { _indent = ". . . . . . " } else if (_heading ~ /^##[ \t]*/) { _indent = ". . . " } else if (_heading ~ /^#[ \t]*/) { _indent = "" } _heading = create_heading(_heading) _id = create_id(_heading) print body_padding "<p><a href=\"#" _id "\">" escape_html(_indent _heading) "</a></p>" } print body_padding "<p><br></p>" } /^=>[ \t]*/ && preformat_toggle == false { sub(/^=>[ \t]*/, "") url = "" link_name = "" if (match($0,/[ \t]+/)) { url = substr($0,0,RSTART-1) link_name = substr($0,RSTART+RLENGTH) data_attribute = "" } else { url = $0 link_name = $0 data_attribute = "data-noprint " } if (INLINE == true && is_image(url) == true) { print body_padding "<p><img src=\"" url "\" alt=\"" escape_html(link_name) "\"></p>" } else { print body_padding "<p><a " data_attribute "href=\"" url "\">" escape_html(link_name) "</a></p>" } next } /^```/ && preformat_toggle == false { preformat_toggle = true preformat_start = true sub(/^```[ \t]*/, "") sub(/[ \t]+$/,"") if ($0 != "") { preformat_title = $0 if (preformat_title == "TOC" && TOC == true) { print_toc(TABLE_OF_CONTENTS) } } next } /^```/ && preformat_toggle == true { preformat_toggle = false if (preformat_start == true) { preformat_start = false } else { print "</pre>" if (preformat_title != "") { print body_padding " <figcaption id=\"" create_id(preformat_title) "\">" print body_padding " " escape_attribute(preformat_title) print body_padding " </figcaption>" print body_padding "</figure>" } } preformat_title = "" next } /^###/ && preformat_toggle == false { print_heading("h3", $0) next } /^##[ \t]*/ && preformat_toggle == false { print_heading("h2", $0) next } /^#[ \t]*/ && preformat_toggle == false { print_heading("h1", $0) next } /^\* / && preformat_toggle == false { sub(/^\* /, "") print body_padding "<ul><li>" escape_html($0) "</li></ul>" next } /^>/ && preformat_toggle == false { sub(/^>/, "") print body_padding "<blockquote>" escape_html($0) "</blockquote>" next } { if (preformat_toggle == true) { if (preformat_start == true) { preformat_start = false if (preformat_title == "") { print body_padding "<pre>" } else { print body_padding "<figure role=\"figure\" aria-labelledby=\"" create_id(preformat_title) "\">" print body_padding " <pre>" } } print escape_html($0) } else { if ($0 ~ /^[ \t]*$/) { print body_padding "<p><br></p>" } else { print body_padding "<p>" escape_html($0) "</p>" } } } END { print " </body>" print "</html>" }