+
+HTML_HEAD
+
+ # --- Body content pipeline ---
+ # Step A: replace GitHub :shortcodes: with emoji
+ # Step B: HTML-escape (&, <, >) to preserve literal layout
+ # Step C: auto-link http(s) URLs (done after escaping so survives)
+ awk '
+ BEGIN { OFS=""; RS="\n"; ORS="\n" }
+ {
+ gsub(":white_check_mark:", "โ
")
+ gsub(":closed_lock_with_key:", "๐")
+ gsub(":small_red_triangle:", "๐บ")
+ gsub(":key:", "๐")
+ gsub(":question:", "โ")
+ gsub(":sos:", "๐")
+ gsub(":alarm_clock:", "โฐ")
+ gsub(":timer_clock:", "โฒ๏ธ")
+ gsub(":exclamation:", "โ")
+ gsub(":eight_spoked_asterisk:", "โณ๏ธ")
+ gsub(":crystal_ball:", "๐ฎ")
+ gsub(":lock:", "๐")
+ gsub(":arrow_up:", "โฌ๏ธ")
+ gsub(":wrench:", "๐ง")
+ gsub(":new:", "๐")
+ print
+ }
+ ' "$tmp_md" |
+ awk '
+ # HTML-escape in correct order
+ { gsub(/&/, "&"); gsub(/, "<"); gsub(/>/, ">"); print }
+ ' |
+ awk '
+ # Auto-link URLs using POSIX awk (ERE), no gensub needed.
+ # Allowed URL chars kept conservative; onion links are fine.
+ {
+ line = $0
+ re = "https?://[A-Za-z0-9._~:/?#@!$&()*+,;=%-]+"
+ out = ""
+ while (match(line, re)) {
+ pre = substr(line, 1, RSTART-1)
+ url = substr(line, RSTART, RLENGTH)
+ line = substr(line, RSTART+RLENGTH)
+ out = out pre "" url ""
+ }
+ $0 = out line
+ print
+ }
+ '
+
+ # --- TAIL ---
+ cat <<'HTML_TAIL'
+
+%s\n' "Last uopdated on $(date +'%A, %B %d, %Y at %H:%M %Z')"
+
+