From 723db0c2c3b9805923d0a1580034c2b3589579e0 Mon Sep 17 00:00:00 2001 From: "N0\\A" Date: Sat, 7 Mar 2026 18:06:03 +0100 Subject: [PATCH] Rendering fixes --- awk/markdown_embed.awk | 6 ++ markdown.sh | 130 +++++++++++++++++++++++++++++++++-------- 2 files changed, 112 insertions(+), 24 deletions(-) diff --git a/awk/markdown_embed.awk b/awk/markdown_embed.awk index 0d35ca7..289da1a 100644 --- a/awk/markdown_embed.awk +++ b/awk/markdown_embed.awk @@ -498,6 +498,12 @@ function restore_plain_markers(line) { gsub(/\034P6\034/, ")", line) gsub(/\034P7\034/, "!", line) gsub(/\034P8\034/, "$", line) + gsub(/\034P9\034/, "#", line) + gsub(/\034P10\034/, "+", line) + gsub(/\034P11\034/, "-", line) + gsub(/\034P12\034/, "\\\\", line) + gsub(/\034P13\034/, "\\<", line) + gsub(/\034P14\034/, "\\>", line) gsub(//, "", line) gsub(/<\/mfmplain>/, "", line) return line diff --git a/markdown.sh b/markdown.sh index 9409988..5b39287 100755 --- a/markdown.sh +++ b/markdown.sh @@ -44,7 +44,96 @@ sed_inplace() { temp_file="/tmp/markdown.$$" cat "$@" > "$temp_file" +# backslash escapes for literal characters and inline code masking awk ' +function mask(s, t) { + t = s + gsub(/\*/, "\034P0\034", t) + gsub(/_/, "\034P1\034", t) + gsub(/`/, "\034P2\034", t) + gsub(/\[/, "\034P3\034", t) + gsub(/\]/, "\034P4\034", t) + gsub(/\(/, "\034P5\034", t) + gsub(/\)/, "\034P6\034", t) + gsub(/!/, "\034P7\034", t) + gsub(/\$/, "\034P8\034", t) + gsub(/#/, "\034P9\034", t) + gsub(/\+/, "\034P10\034", t) + gsub(/-/, "\034P11\034", t) + gsub(/\\/, "\034P12\034", t) + gsub(//, "\034P14\034", t) + return t +} +{ + # backslash escapes + gsub(/\\\*/, "\034P0\034") + gsub(/\\_/, "\034P1\034") + gsub(/\\`/, "\034P2\034") + gsub(/\\\[/, "\034P3\034") + gsub(/\\\]/, "\034P4\034") + gsub(/\\\(/, "\034P5\034") + gsub(/\\\)/, "\034P6\034") + gsub(/\\!/, "\034P7\034") + gsub(/\\\$/, "\034P8\034") + gsub(/\\#/, "\034P9\034") + gsub(/\\\+/, "\034P10\034") + gsub(/\\\-/, "\034P11\034") + gsub(/\\\\/, "\034P12\034") + gsub(/\\/, "\034P14\034") + + # inline code (1 or 2 backticks) + line = $0 + if (line ~ /^```/) { + print line + next + } + out = "" + p = 1 + while (match(substr(line, p), /`+/)) { + pstart = p + RSTART - 1 + plen = RLENGTH + if (plen >= 3) { + out = out substr(line, p, pstart - p + plen) + p = pstart + plen + continue + } + + # Found 1 or 2 backticks at pstart + # Search for closing marker + marker = substr(line, pstart, plen) + tail = substr(line, pstart + plen) + mpos = index(tail, marker) + if (mpos > 0) { + # Check if it is followed by more backticks + if (substr(tail, mpos + plen, 1) == "`") { + # Not a match, treat as literal + out = out substr(line, p, pstart - p + plen) + p = pstart + plen + continue + } + + # Found match! + content = substr(tail, 1, mpos - 1) + out = out substr(line, p, pstart - p) + if (plen == 2 && substr(content, 1, 1) == " " && substr(content, length(content), 1) == " ") { + content = substr(content, 2, length(content) - 2) + } + out = out "" mask(content) "" + p = pstart + plen + mpos + plen - 1 + } else { + # No closing marker, treat as literal + out = out substr(line, p, pstart - p + plen) + p = pstart + plen + } + } + out = out substr(line, p) + print out +}' "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" + +awk ' + function find_unescaped_tag(s, tag, p, off, pos) { p = 1 while (1) { @@ -329,11 +418,12 @@ sed_ere_inplace '/^[1-9]+\\. /s/([1-9]+)\\. /\1\. /' "$temp_file" # fenced code blocks (triple backticks) awk ' -BEGIN { in_fence = 0 } +BEGIN { in_fence = 0; first_line = 0 } { if (!in_fence && $0 ~ /^```/) { - print "
"
+        printf "
"
         in_fence = 1
+        first_line = 1
         next
     }
     if (in_fence && $0 ~ /^```[[:space:]]*$/) {
@@ -341,7 +431,15 @@ BEGIN { in_fence = 0 }
         in_fence = 0
         next
     }
-    print
+    if (in_fence) {
+        if (first_line) {
+            first_line = 0
+            if ($0 == "") next
+        }
+        print
+    } else {
+        print
+    }
 }
 END {
     if (in_fence) print "
" @@ -565,11 +663,11 @@ b :emphasis x -s/\*\*(.+)\*\*/\1<\/strong>/g -s/__([^_]+)__/\1<\/strong>/g -s/\*([^\*]+)\*/\1<\/em>/g -s/([^\\])_([^_]+)_/\1\2<\/em>/g -s/\~\~(.+)\~\~/\1<\/strike>/g +s/\*\*([^\n]+)\*\*/\1<\/strong>/g +s/__([^_\n]+)__/\1<\/strong>/g +s/\*([^\*\n]+)\*/\1<\/em>/g +s/([^\\])_([^_\n]+)_/\1\2<\/em>/g +s/\~\~([^\n]+)\~\~/\1<\/strike>/g p ' "$temp_file" @@ -631,10 +729,6 @@ sed_ere_inplace ' s/<(http[s]?:\/\/.*)>/\1<\/a>/g # automatic links s/<(.*@.*\..*)>/\1<\/a>/g # automatic email address links -# inline code -s/([^\\])``+ *([^ ]*) *``+/\1\2<\/code>/g -s/([^\\])`([^`]*)`/\1\2<\/code>/g - # force-inline image syntax (double bang) s/!!\[([^]]*)\]\(([^)]*) \"([^\"]*)\"\)/\"\1\"/g s/!!\[([^]]*)\]\(([^)]*)\)/\"\1\"/g @@ -653,18 +747,6 @@ s/\$\[font\.sans ([^]]+)\]/\1<\/span>/g # special characters /&.+;/!s/&/\&/g # ampersand /<[\/a-zA-Z]/!s//\>/g # greater than bracket -s/\\\\/\\/g # backslash ' "$temp_file" # display and cleanup