From f580ed9caba43b4e3c06c54fc5c6f2e194892094 Mon Sep 17 00:00:00 2001
From: "N0\\A" " cap(lkind) " " lines[k] ""; in_bq = 1 }
+ sub(/^>[[:space:]]?/, "", $0)
+ print $0
+ next
+}
+{
+ if (in_bq) { print "
"; in_bq = 0 }
+ print
+}
+END {
+ if (in_bq) print ""
+}
diff --git a/awk/blockquote_to_admonition.awk b/awk/blockquote_to_admonition.awk
new file mode 100644
index 0000000..36bde00
--- /dev/null
+++ b/awk/blockquote_to_admonition.awk
@@ -0,0 +1,46 @@
+function cap(s) { return toupper(substr(s, 1, 1)) tolower(substr(s, 2)) }
+BEGIN { count = 0 }
+{ lines[++count] = $0 }
+END {
+ i = 1
+ while (i <= count) {
+ if (lines[i] == "") {
+ j = i + 1
+ while (j <= count && lines[j] != "
") j++
+ if (j <= count) {
+ first = ""
+ first_idx = 0
+ for (k = i + 1; k < j; k++) {
+ if (lines[k] != "") {
+ first = lines[k]
+ first_idx = k
+ break
+ }
+ }
+ if (first ~ /^\[![A-Za-z]+\]$/) {
+ kind = first
+ sub(/^\[!/, "", kind)
+ sub(/\]$/, "", kind)
+ lkind = tolower(kind)
+ if (lkind == "note" || lkind == "tip" || lkind == "important" || lkind == "warning" || lkind == "caution") {
+ print "
"
+ else print $0
+ prev = $0
+}
diff --git a/awk/fenced_code.awk b/awk/fenced_code.awk
new file mode 100644
index 0000000..eaef47f
--- /dev/null
+++ b/awk/fenced_code.awk
@@ -0,0 +1,27 @@
+BEGIN { in_fence = 0; first_line = 0 }
+{
+ if (!in_fence && $0 ~ /^```/) {
+ in_fence = 1
+ first_line = 1
+ next
+ }
+ if (in_fence && $0 ~ /^```[[:space:]]*$/) {
+ print ""
+ in_fence = 0
+ next
+ }
+ if (in_fence) {
+ if (first_line) {
+ first_line = 0
+ if ($0 == "") next
+ print "
"
+}
diff --git a/awk/generate_sidebar.awk b/awk/generate_sidebar.awk
index 00296f1..50ab4b3 100644
--- a/awk/generate_sidebar.awk
+++ b/awk/generate_sidebar.awk
@@ -4,6 +4,34 @@ function title_from_name(name) {
return name
}
+function compare_paths(p1, p2, parts1, parts2, n1, n2, i, name1, name2, lname1, lname2, w1, w2) {
+ n1 = split(p1, parts1, "/")
+ n2 = split(p2, parts2, "/")
+ for (i = 1; i <= n1 && i <= n2; i++) {
+ name1 = parts1[i]
+ name2 = parts2[i]
+ if (i == n1) gsub(/\.md$/, "", name1)
+ if (i == n2) gsub(/\.md$/, "", name2)
+ lname1 = tolower(name1)
+ lname2 = tolower(name2)
+
+ if (lname1 == "index" && i == n1 && lname2 != "index") return -1
+ if (lname2 == "index" && i == n2 && lname1 != "index") return 1
+
+ w1 = (lname1 in custom_order ? custom_order[lname1] : 999999)
+ w2 = (lname2 in custom_order ? custom_order[lname2] : 999999)
+
+ if (w1 < w2) return -1
+ if (w1 > w2) return 1
+
+ if (lname1 < lname2) return -1
+ if (lname1 > lname2) return 1
+ }
+ if (n1 < n2) return -1
+ if (n1 > n2) return 1
+ return 0
+}
+
BEGIN {
n_dlines = split(dinfo, dlines, "\n")
for (i = 1; i <= n_dlines; i++) {
@@ -39,33 +67,6 @@ BEGIN {
has_index[dir] = 1
}
}
-function compare_paths(p1, p2, parts1, parts2, n1, n2, i, name1, name2, lname1, lname2, w1, w2) {
- n1 = split(p1, parts1, "/")
- n2 = split(p2, parts2, "/")
- for (i = 1; i <= n1 && i <= n2; i++) {
- name1 = parts1[i]
- name2 = parts2[i]
- if (i == n1) gsub(/\.md$/, "", name1)
- if (i == n2) gsub(/\.md$/, "", name2)
- lname1 = tolower(name1)
- lname2 = tolower(name2)
-
- if (lname1 == "index" && i == n1 && lname2 != "index") return -1
- if (lname2 == "index" && i == n2 && lname1 != "index") return 1
-
- w1 = (lname1 in custom_order ? custom_order[lname1] : 999999)
- w2 = (lname2 in custom_order ? custom_order[lname2] : 999999)
-
- if (w1 < w2) return -1
- if (w1 > w2) return 1
-
- if (lname1 < lname2) return -1
- if (lname1 > lname2) return 1
- }
- if (n1 < n2) return -1
- if (n1 > n2) return 1
- return 0
-}
END {
for (i = 0; i < count - 1; i++) {
@@ -78,7 +79,6 @@ END {
}
}
-
print "" $0
+ } else {
+ print
+ }
+ } else {
+ print
+ }
+}
+END {
+ if (in_fence) print ""
if ("index.md" in all_paths) {
print "
" }
diff --git a/awk/lists.awk b/awk/lists.awk
new file mode 100644
index 0000000..36c0b9a
--- /dev/null
+++ b/awk/lists.awk
@@ -0,0 +1,66 @@
+BEGIN {
+ depth = 0
+ in_pre = 0
+}
+
+{
+ if ($0 ~ /^/) {
+ in_pre = 1
+ if (has_prev && prev != "") { print prev; has_prev = 0 }
+ print
+ next
+ }
+ if (in_pre) {
+ if ($0 ~ /<\/code><\/pre>/) in_pre = 0
+ print
+ next
+ }
+
+ if ($0 ~ /^=+$/ && has_prev && prev != "" && prev !~ /^<[a-z]/) {
+ print "" prev "
"
+ has_prev = 0
+ } else if ($0 ~ /^-+$/ && has_prev && prev != "" && prev !~ /^<[a-z]/) {
+ print "" prev "
"
+ has_prev = 0
+ } else {
+ if (has_prev) {
+ line = prev
+ if (line ~ /^# /) {
+ sub(/^# /, "", line); print "" line "
"
+ } else if (line ~ /^## /) {
+ sub(/^## /, "", line); print "" line "
"
+ } else if (line ~ /^### /) {
+ sub(/^### /, "", line); print "" line "
"
+ } else if (line ~ /^#### /) {
+ sub(/^#### /, "", line); print "" line "
"
+ } else if (line ~ /^##### /) {
+ sub(/^##### /, "", line); print "" line "
"
+ } else if (line ~ /^###### /) {
+ sub(/^###### /, "", line); print "" line "
"
+ } else {
+ print prev
+ }
+ }
+ prev = $0
+ has_prev = 1
+ }
+}
+END {
+ if (has_prev) {
+ line = prev
+ if (line ~ /^# /) {
+ sub(/^# /, "", line); print "" line "
"
+ } else {
+ print prev
+ }
+ }
+}
diff --git a/awk/indented_code.awk b/awk/indented_code.awk
new file mode 100644
index 0000000..b5e7407
--- /dev/null
+++ b/awk/indented_code.awk
@@ -0,0 +1,9 @@
+BEGIN { in_code = 0 }
+/^ | / {
+ if (!in_code) { print "
"; in_code = 0 } print }
+END { if (in_code) print ""; in_code = 1 }
+ sub(/^ | /, "", $0)
+ gsub(/&/, "&"); gsub(/, "<"); gsub(/>/, ">")
+ print; next
+}
+{ if (in_code) { print "/) in_pre = 1
+ if (in_pre) {
+ while (depth > 0) { print "" cur_type[depth] ">"; depth-- }
+ print
+ if ($0 ~ /<\/pre>/) in_pre = 0
+ next
+ }
+
+ line = $0
+ type = ""
+ # match list marker and its preceding spaces
+ if (line ~ /^[ \t]*[*+-] /) {
+ type = "ul"
+ match(line, /^[ \t]*[*+-] /)
+ marker_len = RLENGTH
+ } else if (line ~ /^[ \t]*[0-9]+\. /) {
+ type = "ol"
+ match(line, /^[ \t]*[0-9]+\. /)
+ marker_len = RLENGTH
+ }
+
+ if (type != "") {
+ content = substr(line, marker_len + 1)
+ # get indentation level
+ match(line, /^[ \t]*/)
+ indent = RLENGTH
+
+ if (depth == 0 || indent > cur_indent[depth]) {
+ depth++
+ cur_indent[depth] = indent
+ cur_type[depth] = type
+ print "<" type ">"
+ } else {
+ while (depth > 1 && indent < cur_indent[depth]) {
+ print "" cur_type[depth] ">"
+ depth--
+ }
+ if (type != cur_type[depth]) {
+ print "" cur_type[depth] ">"
+ cur_type[depth] = type
+ print "<" type ">"
+ }
+ }
+
+ print "/) {
+ in_pre = 1
+ }
+
+ if (in_pre) {
+ print
+ if ($0 ~ /<\/pre>/) {
+ in_pre = 0
+ }
+ next
+ }
+
+ line = $0
+
+ # automatic links
+ while (match(line, /"
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+ while (match(line, /!!\[[^\]]*\]\([^\)]+\)/)) {
+ start = RSTART; len = RLENGTH
+ token = substr(line, start, len)
+ match(token, /\[[^\]]*\]/); alt = substr(token, RSTART + 1, RLENGTH - 2)
+ match(token, /\([^\)]+/); src = substr(token, RSTART + 1, RLENGTH - 1)
+ repl = "
"
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+
+ # inline image
+ while (match(line, /!\[[^\]]*\]\([^\)]+ "[^"]*"\)/)) {
+ start = RSTART; len = RLENGTH
+ if (start > 1 && substr(line, start - 1, 1) == "\\") break
+ token = substr(line, start, len)
+ match(token, /\[[^\]]*\]/); alt = substr(token, RSTART + 1, RLENGTH - 2)
+ match(token, /"[^"]*"/); title = substr(token, RSTART + 1, RLENGTH - 2)
+ match(token, /\([^\)]+/); inner = substr(token, RSTART + 1, RLENGTH - 1)
+ sub(/[[:space:]]*"[^"]*"/, "", inner); src = inner
+ repl = "
"
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+ while (match(line, /!\[[^\]]*\]\([^\)]+\)/)) {
+ start = RSTART; len = RLENGTH
+ if (start > 1 && substr(line, start - 1, 1) == "\\") break
+ token = substr(line, start, len)
+ match(token, /\[[^\]]*\]/); alt = substr(token, RSTART + 1, RLENGTH - 2)
+ match(token, /\([^\)]+/); src = substr(token, RSTART + 1, RLENGTH - 1)
+ repl = "
"
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+
+ # inline link
+ while (match(line, /\[[^\]]*\]\([^\)]+ "[^"]*"\)/)) {
+ start = RSTART; len = RLENGTH
+ if (start > 1 && (substr(line, start - 1, 1) == "\\" || substr(line, start - 1, 1) == "!")) break
+ token = substr(line, start, len)
+ match(token, /\[[^\]]*\]/); text = substr(token, RSTART + 1, RLENGTH - 2)
+ match(token, /"[^"]*"/); title = substr(token, RSTART + 1, RLENGTH - 2)
+ match(token, /\([^\)]+/); inner = substr(token, RSTART + 1, RLENGTH - 1)
+ sub(/[[:space:]]*"[^"]*"/, "", inner); href = inner
+ repl = "" text ""
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+ while (match(line, /\[[^\]]*\]\([^\)]+\)/)) {
+ start = RSTART; len = RLENGTH
+ if (start > 1 && (substr(line, start - 1, 1) == "\\" || substr(line, start - 1, 1) == "!")) break
+ token = substr(line, start, len)
+ match(token, /\[[^\]]*\]/); text = substr(token, RSTART + 1, RLENGTH - 2)
+ match(token, /\([^\)]+/); href = substr(token, RSTART + 1, RLENGTH - 1)
+ repl = "" text ""
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+
+ # MFM font syntax
+ while (match(line, /\$\[font\.serif [^\]]+\]/)) {
+ start = RSTART; len = RLENGTH
+ content = substr(line, start + 13, len - 14)
+ line = substr(line, 1, start - 1) "" content "" substr(line, start + len)
+ }
+ while (match(line, /\$\[font\.monospace [^\]]+\]/)) {
+ start = RSTART; len = RLENGTH
+ content = substr(line, start + 17, len - 18)
+ line = substr(line, 1, start - 1) "" content "" substr(line, start + len)
+ }
+ while (match(line, /\$\[font\.sans [^\]]+\]/)) {
+ start = RSTART; len = RLENGTH
+ content = substr(line, start + 12, len - 13)
+ line = substr(line, 1, start - 1) "" content "" substr(line, start + len)
+ }
+
+ # Bold, Italic, Strikethrough (BRE-like logic in AWK)
+ # Strong Bold **
+ while (match(line, /\*\*[^*]+\*\*/)) {
+ start = RSTART; len = RLENGTH
+ content = substr(line, start + 2, len - 4)
+ repl = "" content ""
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+ # Strong Bold __
+ while (match(line, /__[^_]+__/)) {
+ start = RSTART; len = RLENGTH
+ content = substr(line, start + 2, len - 4)
+ repl = "" content ""
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+ # Italic *
+ while (match(line, /\*[^*]+\*/)) {
+ start = RSTART; len = RLENGTH
+ content = substr(line, start + 1, len - 2)
+ repl = "" content ""
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+ # Italic _
+ while (match(line, /_[^_]+_/)) {
+ start = RSTART; len = RLENGTH
+ if (start > 1 && substr(line, start - 1, 1) == "\\") break
+ content = substr(line, start + 1, len - 2)
+ repl = "" content ""
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+ # Strikethrough ~~
+ while (match(line, /~~[^~]+~~/)) {
+ start = RSTART; len = RLENGTH
+ content = substr(line, start + 2, len - 4)
+ repl = "
" content ""
+ line = substr(line, 1, start - 1) repl substr(line, start + len)
+ }
+
+ # special characters
+ if (line !~ /&[A-Za-z0-9#]+;/) {
+ gsub(/&/, "&", line)
+ }
+
+ p = 1
+ while (match(substr(line, p), /)) {
+ start = p + RSTART - 1
+ next_char = substr(line, start + 1, 1)
+ if (next_char !~ /^[\/A-Za-z]/) {
+ line = substr(line, 1, start - 1) "<" substr(line, start + 1)
+ p = start + 4
+ } else {
+ p = start + 1
+ }
+ }
+
+ print line
+}
diff --git a/awk/mask_inline_code.awk b/awk/mask_inline_code.awk
new file mode 100644
index 0000000..022381d
--- /dev/null
+++ b/awk/mask_inline_code.awk
@@ -0,0 +1,85 @@
+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(/, "\034P13\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(/\\, "\034P13\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
+}
diff --git a/awk/mask_plain.awk b/awk/mask_plain.awk
new file mode 100644
index 0000000..15a8276
--- /dev/null
+++ b/awk/mask_plain.awk
@@ -0,0 +1,52 @@
+function find_unescaped_tag(s, tag, p, off, pos) {
+ p = 1
+ while (1) {
+ off = index(substr(s, p), tag)
+ if (off == 0) return 0
+ pos = p + off - 1
+ if (pos == 1 || substr(s, pos - 1, 1) != "\\") return pos
+ p = pos + 1
+ }
+}
+
+function mask_plain(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)
+ return t
+}
+BEGIN { in_plain = 0 }
+{
+ line = $0
+ out = ""
+ while (1) {
+ if (!in_plain) {
+ pos = find_unescaped_tag(line, "/) in_pre = 1
+
+ if (in_pre) {
+ if (in_p) { print "
" + in_p = 1 + } + print +} + +END { + if (in_p) print "
" +} diff --git a/awk/pipe_tables.awk b/awk/pipe_tables.awk new file mode 100644 index 0000000..8e9005b --- /dev/null +++ b/awk/pipe_tables.awk @@ -0,0 +1,143 @@ +function trim(s) { + sub(/^[[:space:]]+/, "", s) + sub(/[[:space:]]+$/, "", s) + return s +} + +function is_table_row(line, t) { + t = line + return (t ~ /^[[:space:]]*\|/ && t ~ /\|[[:space:]]*$/) +} + +function is_table_sep(line, t) { + if (!is_table_row(line)) return 0 + t = line + gsub(/[|:\-[:space:]]/, "", t) + return (t == "" && line ~ /-/) +} + +function split_row(line, out, n, i, raw) { + raw = line + sub(/^[[:space:]]*\|/, "", raw) + sub(/\|[[:space:]]*$/, "", raw) + n = split(raw, out, /\|/) + for (i = 1; i <= n; i++) out[i] = trim(out[i]) + return n +} + +function align_for(sep, t) { + t = trim(sep) + if (t ~ /^:-+:$/) return "center" + if (t ~ /^:-+$/) return "left" + if (t ~ /^-+:$/) return "right" + return "" +} + +function render_cell(cell, inner) { + inner = trim(cell) + if (inner ~ /^```.*```$/) { + sub(/^```[[:space:]]*/, "", inner) + sub(/[[:space:]]*```$/, "", inner) + return "" inner ""
+ }
+ return inner
+}
+
+BEGIN { count = 0 }
+{ lines[++count] = $0 }
+
+END {
+ in_pre = 0
+ i = 1
+ while (i <= count) {
+ if (lines[i] ~ /^/) {
+ in_pre = 1
+ print lines[i]
+ i++
+ continue
+ }
+ if (in_pre) {
+ print lines[i]
+ if (lines[i] ~ /^<\/code><\/pre>/) in_pre = 0
+ i++
+ continue
+ }
+
+ if (i < count && is_table_row(lines[i]) && is_table_sep(lines[i + 1])) {
+ n_header = split_row(lines[i], header)
+ n_sep = split_row(lines[i + 1], sep)
+ n_cols = (n_header > n_sep ? n_header : n_sep)
+
+ print ""
+ print ""
+ print ""
+ for (c = 1; c <= n_cols; c++) {
+ cell = (c <= n_header ? render_cell(header[c]) : "")
+ a = (c <= n_sep ? align_for(sep[c]) : "")
+ if (a != "") print "" cell " "
+ else print "" cell " "
+ }
+ print " "
+ print ""
+
+ j = i + 2
+ print ""
+ while (j <= count && is_table_row(lines[j])) {
+ n_body = split_row(lines[j], body)
+ print ""
+ for (c = 1; c <= n_cols; c++) {
+ cell = (c <= n_body ? render_cell(body[c]) : "")
+ a = (c <= n_sep ? align_for(sep[c]) : "")
+ if (a != "") print "" cell " "
+ else print "" cell " "
+ }
+ print " "
+ j++
+ }
+ print ""
+ print "
"
+
+ i = j
+ continue
+ }
+
+ if (is_table_sep(lines[i]) && i < count && is_table_row(lines[i + 1])) {
+ n_sep = split_row(lines[i], sep)
+ n_cols = n_sep
+
+ print ""
+ print ""
+ print ""
+ for (c = 1; c <= n_cols; c++) {
+ a = align_for(sep[c])
+ if (a != "") print " "
+ else print " "
+ }
+ print " "
+ print ""
+
+ j = i + 1
+ print ""
+ while (j <= count && is_table_row(lines[j])) {
+ n_body = split_row(lines[j], body)
+ print ""
+ for (c = 1; c <= n_cols; c++) {
+ cell = (c <= n_body ? render_cell(body[c]) : "")
+ a = (c <= n_sep ? align_for(sep[c]) : "")
+ if (a != "") print "" cell " "
+ else print "" cell " "
+ }
+ print " "
+ j++
+ }
+ print ""
+ print "
"
+
+ i = j
+ continue
+ }
+
+ print lines[i]
+ i++
+ }
+}
diff --git a/awk/update_site_conf.awk b/awk/update_site_conf.awk
new file mode 100644
index 0000000..9bd31e8
--- /dev/null
+++ b/awk/update_site_conf.awk
@@ -0,0 +1,10 @@
+BEGIN { done = 0 }
+/^title[[:space:]]*=/ {
+ print "title = \"" new_title "\""
+ done = 1
+ next
+}
+{ print }
+END {
+ if (!done) print "title = \"" new_title "\""
+}
diff --git a/kewt.sh b/kewt.sh
index bdc1064..192baa4 100755
--- a/kewt.sh
+++ b/kewt.sh
@@ -82,18 +82,7 @@ create_new_site() {
printf "# _kewt_ website\n" > "$new_dir/index.md"
if [ -n "$new_title" ]; then
- awk -v new_title="$new_title" '
- BEGIN { done = 0 }
- /^title[[:space:]]*=/ {
- print "title = \"" new_title "\""
- done = 1
- next
- }
- { print }
- END {
- if (!done) print "title = \"" new_title "\""
- }
- ' "$new_dir/site.conf" > "$new_dir/site.conf.tmp" && mv "$new_dir/site.conf.tmp" "$new_dir/site.conf"
+ awk -v new_title="$new_title" -f "$awk_dir/update_site_conf.awk" "$new_dir/site.conf" > "$new_dir/site.conf.tmp" && mv "$new_dir/site.conf.tmp" "$new_dir/site.conf"
fi
echo "Created new site at '$new_dir'."
@@ -101,7 +90,7 @@ create_new_site() {
}
generate_nav() {
- dinfo=$(find "$1" -not -path '*/.*' | sort | awk -v src="$1" -f "$awk_dir/collect_dir_info.awk")
+ dinfo=$(find "$1" ! -path '*/.*' | sort | awk -v src="$1" -f "$awk_dir/collect_dir_info.awk")
find "$1" -name "*.md" | sort | awk -v src="$1" -v single_file_index="$single_file_index" -v flatten="$flatten" -v order="$order" -v dinfo="$dinfo" -f "$awk_dir/generate_sidebar.awk"
}
@@ -314,9 +303,9 @@ find "$src" -type d | sort | while read -r dir; do
if [ ! -f "$dir/index.md" ]; then
if [ "$single_file_index" = "true" ]; then
- md_count=$(find "$dir" -maxdepth 1 -name "*.md" | wc -l)
+ md_count=$(find "$dir" ! -name "$(basename "$dir")" -prune -name "*.md" | wc -l)
if [ "$md_count" -eq 1 ]; then
- md_file=$(find "$dir" -maxdepth 1 -name "*.md")
+ md_file=$(find "$dir" ! -name "$(basename "$dir")" -prune -name "*.md")
render_markdown "$md_file" > "$out_dir/index.html"
continue
fi
@@ -327,7 +316,7 @@ find "$src" -type d | sort | while read -r dir; do
[ -z "$display_dir" ] && display_dir="/"
echo "# Index of $display_dir" > "$temp_index"
echo "" >> "$temp_index"
- find "$dir" -maxdepth 1 -not -path '*/.*' -not -path "$dir" | sort | while read -r entry; do
+ find "$dir" ! -name "$(basename "$dir")" -prune ! -path '*/.*' | sort | while read -r entry; do
name="${entry##*/}"
case "$name" in
template.html|site.conf|style.css|index.md) continue ;;
@@ -359,7 +348,7 @@ find "$src" -type f | sort | while IFS= read -r file; do
esac
if [ "$single_file_index" = "true" ] && [ "${file%.md}" != "$file" ] && [ ! -f "$(dirname "$file")/index.md" ]; then
- md_count=$(find "$(dirname "$file")" -maxdepth 1 -name "*.md" | wc -l)
+ md_count=$(find "$(dirname "$file")" ! -name "$(basename "$(dirname "$file")")" -prune -name "*.md" | wc -l)
[ "$md_count" -eq 1 ] && continue
fi
diff --git a/markdown.sh b/markdown.sh
index 5b39287..048eb14 100755
--- a/markdown.sh
+++ b/markdown.sh
@@ -3,34 +3,6 @@
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
awk_dir="$script_dir/awk"
-sed_ere() {
- if sed -E '' /dev/null 2>&1; then
- sed -E "$@"
- else
- sed -r "$@"
- fi
-}
-
-sed_ere_inplace() {
- script="$1"
- file="$2"
- tmp="${file}.tmp.$$"
- sed_ere "$script" "$file" > "$tmp" && mv "$tmp" "$file" || {
- rm -f "$tmp"
- return 1
- }
-}
-
-sed_ere_inplace_n() {
- script="$1"
- file="$2"
- tmp="${file}.tmp.$$"
- sed_ere -n "$script" "$file" > "$tmp" && mv "$tmp" "$file" || {
- rm -f "$tmp"
- return 1
- }
-}
-
sed_inplace() {
script="$1"
file="$2"
@@ -44,711 +16,49 @@ 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(/, "\034P13\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(/\\, "\034P13\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) {
- off = index(substr(s, p), tag)
- if (off == 0) return 0
- pos = p + off - 1
- if (pos == 1 || substr(s, pos - 1, 1) != "\\") return pos
- p = pos + 1
- }
-}
-
-function mask_plain(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)
- return t
-}
-BEGIN { in_plain = 0 }
-{
- line = $0
- out = ""
- while (1) {
- if (!in_plain) {
- pos = find_unescaped_tag(line, "")
- if (pos == 0) {
- out = out line
- break
- }
- out = out substr(line, 1, pos - 1) ""
- line = substr(line, pos + 7)
- in_plain = 1
- } else {
- pos = find_unescaped_tag(line, " ")
- if (pos == 0) {
- out = out mask_plain(line)
- line = ""
- break
- }
- out = out mask_plain(substr(line, 1, pos - 1)) ""
- line = substr(line, pos + 8)
- in_plain = 0
- }
- }
- print out
-}
-' "$temp_file" > "$temp_file.plain.$$" && mv "$temp_file.plain.$$" "$temp_file"
+# Mask
+awk -f "$awk_dir/mask_inline_code.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+awk -f "$awk_dir/mask_plain.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+# Reference links
+refs=$(cat "$@" | awk '/^\[[^\]]+\]: +/')
IFS='
'
-refs=$(sed_ere -n "/^\[.+\]: +/p" "$@")
-for ref in $refs
-do
- ref_id=$(printf %s "$ref" | sed_ere -n "s/^\[(.+)\]: .*/\1/p" | tr -d '\n')
- ref_url=$(printf %s "$ref" | sed_ere -n "s/^\[.+\]: (.+)/\1/p" | cut -d' ' -f1 | tr -d '\n')
- ref_title=$(printf %s "$ref" | sed_ere -n "s/^\[.+\]: (.+) \"(.+)\"/\2/p" | sed 's@|@!@g' | tr -d '\n')
+for ref in $refs; do
+ ref_id=$(echo "$ref" | sed 's/^\[\(.*\)\]: .*/\1/')
+ ref_url=$(echo "$ref" | sed 's/^\[.*\]: \([^ ]*\).*/\1/')
+ ref_title=$(echo "$ref" | sed -n 's/^\[.*\]: [^ ]* "\(.*\)"/\1/p' | sed 's@|@!@g')
+ sed_inplace "s|!\[\([^]]*\)\]\[$ref_id\]|
|g" "$temp_file"
+ sed_inplace "s|\[\([^]]*\)\]\[$ref_id\]|\1|g" "$temp_file"
+ sed_inplace "s|!\[$ref_id\]\[\]|
|g" "$temp_file"
+ sed_inplace "s|\[$ref_id\]\[\]|$ref_id|g" "$temp_file"
+done
+sed_inplace "/^\[[^\]]*\]: +/d" "$temp_file"
- # reference-style image using the label
- sed_ere_inplace "s|!\[([^]]+)\]\[($ref_id)\]|
|g" "$temp_file"
- # reference-style link using the label
- sed_ere_inplace "s|\[([^]]+)\]\[($ref_id)\]|\1|g" "$temp_file"
+# Blocks
+sed_inplace "s/^>!\[/> [!/g" "$temp_file"
+sed_inplace "s/^>\[!/> [!/g" "$temp_file"
- # implicit reference-style
- sed_ere_inplace "s|!\[($ref_id)\]\[\]|
|g" "$temp_file"
- # implicit reference-style
- sed_ere_inplace "s|\[($ref_id)\]\[\]|\1|g" "$temp_file"
+while grep '^>' "$temp_file" >/dev/null; do
+ awk -f "$awk_dir/blockquote.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
done
-# delete the reference lines
-sed_ere_inplace "/^\[.+\]: +/d" "$temp_file"
-
-# normalize GitHub admonition shorthand in blockquotes
-sed_ere_inplace '
-/^>!\[/s/^>!\[/> [!/
-/^>\[!/s/^>\[!/> [!/
-s/^>([^[:space:]>])/> \1/
-' "$temp_file"
-
-# blockquotes
-# use grep to find all the nested blockquotes
-while grep '^> ' "$temp_file" >/dev/null
-do
- sed_ere_inplace_n '
-/^$/b blockquote
-
-H
-$ b blockquote
-b
-
-:blockquote
-x
-s/(\n+)(> .*)/\1\n\2\n<\/blockquote>/ # wrap the tags in a blockquote
-p
-' "$temp_file"
-
- sed_inplace '1 d' "$temp_file" # cleanup superfluous first line
-
- # cleanup blank lines and remove subsequent blockquote characters
- sed_ere_inplace '
-/^> /s/^> (.*)/\1/
-' "$temp_file"
-done
-
-# convert [!TYPE] blockquotes into admonition blocks
-awk '
-function cap(s) { return toupper(substr(s, 1, 1)) tolower(substr(s, 2)) }
-BEGIN { count = 0 }
-{ lines[++count] = $0 }
-END {
- i = 1
- while (i <= count) {
- if (lines[i] == "") {
- j = i + 1
- while (j <= count && lines[j] != "
") j++
- if (j <= count) {
- first = ""
- first_idx = 0
- for (k = i + 1; k < j; k++) {
- if (lines[k] != "") {
- first = lines[k]
- first_idx = k
- break
- }
- }
- if (first ~ /^\[![A-Za-z]+\]$/) {
- kind = first
- sub(/^\[!/, "", kind)
- sub(/\]$/, "", kind)
- lkind = tolower(kind)
- if (lkind == "note" || lkind == "tip" || lkind == "important" || lkind == "warning" || lkind == "caution") {
- print ""
- print "" cap(lkind) "
"
- has_body = 0
- for (k = first_idx + 1; k < j; k++) {
- if (lines[k] != "") {
- print "" lines[k] "
"
- has_body = 1
- }
- }
- if (!has_body) print ""
- print ""
- i = j + 1
- continue
- }
- }
- }
- }
- print lines[i]
- i++
- }
-}
-' "$temp_file" > "$temp_file.admon.$$" && mv "$temp_file.admon.$$" "$temp_file"
-
-# Setext-style headers
-sed_ere_inplace_n '
-# Setext-style headers need to be wrapped around newlines
-/^$/ b print
-
-# else, append to holding area
-H
-$ b print
-b
-
-:print
-x
-/=+$/{
-s/\n(.*)\n=+$/\n\1<\/h1>/
-p
-b
-}
-/\-+$/{
-s/\n(.*)\n\-+$/\n\1<\/h2>/
-p
-b
-}
-p
-' "$temp_file"
-
-sed_inplace '1 d' "$temp_file" # cleanup superfluous first line
-
-# atx-style headers and other block styles
-sed_ere_inplace '
-/^#+ /s/ #+$// # kill all ending header characters
-/^# /s/# ([A-Za-z0-9 ]*)(.*)/\1\2<\/h1>/g # H1
-/^#{2} /s/#{2} ([A-Za-z0-9 ]*)(.*)/\1\2<\/h2>/g # H2
-/^#{3} /s/#{3} ([A-Za-z0-9 ]*)(.*)/\1\2<\/h3>/g # H3
-/^#{4} /s/#{4} ([A-Za-z0-9 ]*)(.*)/\1\2<\/h4>/g # H4
-/^#{5} /s/#{5} ([A-Za-z0-9 ]*)(.*)/\1\2<\/h5>/g # H5
-/^#{6} /s/#{6} ([A-Za-z0-9 ]*)(.*)/\1\2<\/h6>/g # H6
-
-/^\*\*\*+$/s/\*\*\*+/
/ # hr with *
-/^---+$/s/---+/
/ # hr with -
-/^___+$/s/___+/
/ # hr with _
-
-' "$temp_file"
-
-# unordered lists
-# use grep to find all the nested lists
-while grep '^[\*\+\-] ' "$temp_file" >/dev/null
-do
-sed_ere_inplace_n '
-# wrap the list
-/^$/b list
-
-# wrap the li tags then add to the hold buffer
-# use uli instead of li to avoid collisions when processing nested lists
-/^[\*\+\-] /s/[\*\+\-] (.*)/<\/uli>\n\n\1/
-
-H
-$ b list # if at end of file, check for the end of a list
-b # else, branch to the end of the script
-
-# this is where a list is checked for the pattern
-:list
-# exchange the hold space into the pattern space
-x
-# look for the list items, if there wrap the ul tags
-//{
-s/(.*)/\n\1\n<\/uli>\n<\/ul>/ # close the ul tags
-s/\n<\/uli>// # kill the first superfluous closing tag
-p
-b
-}
-p
-' "$temp_file"
-
-sed_inplace '1 d' "$temp_file" # cleanup superfluous first line
-
-# convert to the proper li to avoid collisions with nested lists
-sed_inplace 's/uli>/li>/g' "$temp_file"
-
-# prepare any nested lists
-sed_ere_inplace '/^[\*\+\-] /s/(.*)/\n\1\n/' "$temp_file"
-done
-
-# ordered lists
-# use grep to find all the nested lists
-while grep -E '^[1-9]+\. ' "$temp_file" >/dev/null
-do
-sed_ere_inplace_n '
-# wrap the list
-/^$/b list
-
-# wrap the li tags then add to the hold buffer
-# use oli instead of li to avoid collisions when processing nested lists
-/^[1-9]+\. /s/[1-9]+\. (.*)/<\/oli>\n\n\1/
-
-H
-$ b list # if at end of file, check for the end of a list
-b # else, branch to the end of the script
-
-:list
-# exchange the hold space into the pattern space
-x
-# look for the list items, if there wrap the ol tags
-//{
-s/(.*)/\n\1\n<\/oli>\n<\/ol>/ # close the ol tags
-s/\n<\/oli>// # kill the first superfluous closing tag
-p
-b
-}
-p
-' "$temp_file"
-
-sed_inplace '1 d' "$temp_file" # cleanup superfluous first line
-
-# convert list items into proper list items to avoid collisions with nested lists
-sed_inplace 's/oli>/li>/g' "$temp_file"
-
-# prepare any nested lists
-sed_ere_inplace '/^[1-9]+\. /s/(.*)/\n\1\n/' "$temp_file"
-done
-
-# make escaped periods literal
-sed_ere_inplace '/^[1-9]+\\. /s/([1-9]+)\\. /\1\. /' "$temp_file"
-
-# fenced code blocks (triple backticks)
-awk '
-BEGIN { in_fence = 0; first_line = 0 }
-{
- if (!in_fence && $0 ~ /^```/) {
- printf ""
- in_fence = 1
- first_line = 1
- next
- }
- if (in_fence && $0 ~ /^```[[:space:]]*$/) {
- print "
"
- in_fence = 0
- next
- }
- if (in_fence) {
- if (first_line) {
- first_line = 0
- if ($0 == "") next
- }
- print
- } else {
- print
- }
-}
-END {
- if (in_fence) print "
"
-}
-' "$temp_file" > "$temp_file.fence.$$" && mv "$temp_file.fence.$$" "$temp_file"
-
-
-# code blocks
-sed_ere_inplace_n '
-# if at end of file, append the current line to the hold buffer and print it
-${
-H
-b code
-}
-
-# wrap the code block on any non code block lines
-/^\t| {4}/!b code
-
-# else, append to the holding buffer and do nothing
-H
-b # else, branch to the end of the script
-
-:code
-# exchange the hold space with the pattern space
-x
-# look for the code items, if there wrap the pre-code tags
-/\t| {4}/{
-s/(\t| {4})(.*)/\n\1\2\n<\/code><\/pre>/ # wrap the ending tags
-p
-b
-}
-p
-' "$temp_file"
-
-sed_inplace '1 d' "$temp_file" # cleanup superfluous first line
-
-# convert html characters inside pre-code tags into printable representations
-sed_ere_inplace '
-# get inside pre-code tags
-/^/{
-:inside
-n
-# if you found the end tags, branch out
-/^<\/code><\/pre>/!{
-s/&/\&/g # ampersand
-s/\</g # less than
-s/>/\>/g # greater than
-b inside
-}
-}
-' "$temp_file"
-
-# remove the first tab (or 4 spaces) from the code lines
-sed_ere_inplace 's/^\t| {4}(.*)/\1/' "$temp_file"
-
-# markdown pipe tables
-awk '
-function trim(s) {
- sub(/^[[:space:]]+/, "", s)
- sub(/[[:space:]]+$/, "", s)
- return s
-}
-
-function is_table_row(line, t) {
- t = line
- return (t ~ /^[[:space:]]*\|/ && t ~ /\|[[:space:]]*$/)
-}
-
-function is_table_sep(line, t) {
- if (!is_table_row(line)) return 0
- t = line
- gsub(/[|:\-[:space:]]/, "", t)
- return (t == "" && line ~ /-/)
-}
-
-function split_row(line, out, n, i, raw) {
- raw = line
- sub(/^[[:space:]]*\|/, "", raw)
- sub(/\|[[:space:]]*$/, "", raw)
- n = split(raw, out, /\|/)
- for (i = 1; i <= n; i++) out[i] = trim(out[i])
- return n
-}
-
-function align_for(sep, t) {
- t = trim(sep)
- if (t ~ /^:-+:$/) return "center"
- if (t ~ /^:-+$/) return "left"
- if (t ~ /^-+:$/) return "right"
- return ""
-}
-
-function render_cell(cell, inner) {
- inner = trim(cell)
- if (inner ~ /^```.*```$/) {
- sub(/^```[[:space:]]*/, "", inner)
- sub(/[[:space:]]*```$/, "", inner)
- return "" inner "
"
- }
- return inner
-}
-
-BEGIN { count = 0 }
-{ lines[++count] = $0 }
-
-END {
- in_pre = 0
- i = 1
- while (i <= count) {
- if (lines[i] ~ /^/) {
- in_pre = 1
- print lines[i]
- i++
- continue
- }
- if (in_pre) {
- print lines[i]
- if (lines[i] ~ /^<\/code><\/pre>/) in_pre = 0
- i++
- continue
- }
-
- if (i < count && is_table_row(lines[i]) && is_table_sep(lines[i + 1])) {
- n_header = split_row(lines[i], header)
- n_sep = split_row(lines[i + 1], sep)
- n_cols = (n_header > n_sep ? n_header : n_sep)
-
- print ""
- print ""
- print ""
- for (c = 1; c <= n_cols; c++) {
- cell = (c <= n_header ? render_cell(header[c]) : "")
- a = (c <= n_sep ? align_for(sep[c]) : "")
- if (a != "") print "" cell " "
- else print "" cell " "
- }
- print " "
- print ""
-
- j = i + 2
- print ""
- while (j <= count && is_table_row(lines[j])) {
- n_body = split_row(lines[j], body)
- print ""
- for (c = 1; c <= n_cols; c++) {
- cell = (c <= n_body ? render_cell(body[c]) : "")
- a = (c <= n_sep ? align_for(sep[c]) : "")
- if (a != "") print "" cell " "
- else print "" cell " "
- }
- print " "
- j++
- }
- print ""
- print "
"
-
- i = j
- continue
- }
-
- if (is_table_sep(lines[i]) && i < count && is_table_row(lines[i + 1])) {
- n_sep = split_row(lines[i], sep)
- n_cols = n_sep
-
- print ""
- print ""
- print ""
- for (c = 1; c <= n_cols; c++) {
- a = align_for(sep[c])
- if (a != "") print " "
- else print " "
- }
- print " "
- print ""
-
- j = i + 1
- print ""
- while (j <= count && is_table_row(lines[j])) {
- n_body = split_row(lines[j], body)
- print ""
- for (c = 1; c <= n_cols; c++) {
- cell = (c <= n_body ? render_cell(body[c]) : "")
- a = align_for(sep[c])
- if (a != "") print "" cell " "
- else print "" cell " "
- }
- print " "
- j++
- }
- print ""
- print "
"
-
- i = j
- continue
- }
-
- print lines[i]
- i++
- }
-}
-' "$temp_file" > "$temp_file.table.$$" && mv "$temp_file.table.$$" "$temp_file"
-
-# br tags
-sed_ere_inplace '
-# if an empty line, append it to the next line, then check on whether there is two in a row
-/^$/ {
-N
-N
-/^\n{2}/s/(.*)/\n
\1/
-}
-' "$temp_file"
-
-# emphasis and strong emphasis and strikethrough
-sed_ere_inplace_n '
-# batch up the entire stream of text until a line break in the action
-/^$/b emphasis
-
-H
-$ b emphasis
-b
-
-:emphasis
-x
-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"
-
-sed_inplace '1 d' "$temp_file" # cleanup superfluous first line
-
-# paragraphs
-sed_ere_inplace_n '
-# if an empty line, check the paragraph
-/^$/ b para
-# else append it to the hold buffer
-H
-# at end of file, check paragraph
-$ b para
-# now branch to end of script
-b
-# this is where a paragraph is checked for the pattern
-:para
-# return the entire paragraph into the pattern space
-x
-# look for non block-level elements, if there - print the p tags
-/\n<(div|table|pre|p|[ou]l|h[1-6]|[bh]r|blockquote|li)/!{
-s/(\n+)(.*)/\1\n\2\n<\/p>/
-p
-b
-}
-p
-' "$temp_file"
-
-sed_inplace '1 d' "$temp_file" # cleanup superfluous first line
-
-# cleanup area where P tags have broken nesting
-sed_ere_inplace_n '
-# if the line looks like like an end tag
-/^<\/(div|table|pre|p|[ou]l|h[1-6]|[bh]r|blockquote)>/{
-h
-# if EOF, print the line
-$ {
-x
-b done
-}
-# fetch the next line and check on whether or not it is a P tag
-n
-/^<\/p>/{
-G
-b done
-}
-# else, append the line to the previous line and print them both
-H
-x
-}
-:done
-p
-' "$temp_file"
-
-# inline styles and special characters
-sed_ere_inplace '
-/^
/,/^<\/code><\/pre>/b
-
-s/<(http[s]?:\/\/.*)>/\1<\/a>/g # automatic links
-s/<(.*@.*\..*)>/\1<\/a>/g # automatic email address links
-
-# force-inline image syntax (double bang)
-s/!!\[([^]]*)\]\(([^)]*) \"([^\"]*)\"\)/
/g
-s/!!\[([^]]*)\]\(([^)]*)\)/
/g
-
-s/(^|[^\\])!\[([^]]*)\]\(([^)]*) \"([^\"]*)\"\)/\1
/g # inline image with title
-s/(^|[^\\])!\[([^]]*)\]\(([^)]*)\)/\1
/g # inline image without title
-
-s/(^|[^\\!])\[([^]]*)\]\(([^)]*) \"([^\"]*)\"\)/\1\2<\/a>/g # inline link with title
-s/(^|[^\\!])\[([^]]*)\]\(([^)]*)\)/\1\2<\/a>/g # inline link
-
-# MFM font syntax
-s/\$\[font\.serif ([^]]+)\]/\1<\/span>/g
-s/\$\[font\.monospace ([^]]+)\]/\1<\/span>/g
-s/\$\[font\.sans ([^]]+)\]/\1<\/span>/g
-
-# special characters
-/&.+;/!s/&/\&/g # ampersand
-/<[\/a-zA-Z]/!s/\</g# less than bracket
-' "$temp_file"
-
-# display and cleanup
+awk -f "$awk_dir/blockquote_to_admonition.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+awk -f "$awk_dir/fenced_code.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+awk -f "$awk_dir/indented_code.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+awk -f "$awk_dir/pipe_tables.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+awk -f "$awk_dir/headers.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+awk -f "$awk_dir/lists.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+
+sed_inplace "s/^\*\*\*+$/
/g" "$temp_file"
+sed_inplace "s/^---+$/
/g" "$temp_file"
+sed_inplace "s/^___+$/
/g" "$temp_file"
+
+# Spacing
+awk -f "$awk_dir/breaks.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+awk -f "$awk_dir/paragraphs.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
+
+# Inline styles
+awk -f "$awk_dir/markdown_inline.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
awk -v input_file="$1" -v site_root="$MARKDOWN_SITE_ROOT" -v fallback_file="$MARKDOWN_FALLBACK_FILE" -f "$awk_dir/markdown_embed.awk" "$temp_file"
rm "$temp_file"