From 6153a4df213dfb8435a1667fcc9a32f56dce22c1 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Wed, 1 Jan 2025 10:42:49 +0200 Subject: feat(single): Implement lists --- single.awk | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'single.awk') diff --git a/single.awk b/single.awk index e7d55e4..34917bc 100644 --- a/single.awk +++ b/single.awk @@ -1,12 +1,12 @@ # Status: # [.] Inline HTML # [x] Autoescape -# [.] Block elements +# [x] Block elements # [x] Paragraph # [x] Line break # [x] Headers (atx and setex) # [x] Blockquotes -# [ ] Lists +# [x] Lists # [x] Code blocks # [x] Horizontal rules # [x] Span elements @@ -104,6 +104,7 @@ BEGIN { not_paragraph = 0 empty0 = empty($0) emptyP1 = empty(P1) + list_started = 0 } # Output is buffered on multiple lines, held in these variables: @@ -160,6 +161,68 @@ blockquote_level > 0 && empty0 { } /^>$/ { $0 = ""; not_paragraph = 1 } +# Lists +function end_list() { + if (list_level == 0) return + P2 = P2 ORS "" + --list_level +} +function start_list(level, type) { + ## Every two columns we define a new level + level = int((level + 2) / 2) + ## If list definition is the first line inside a code block + if (level - list_level >= 3) return + + ## Make list_level = level - 1 + while (list_level < level - 1) { + lists[++list_level] = "" + } + ## Make list_level = level + while (list_level > level) { + end_list() + } + + if (list_level == level && lists[list_level] != type) { + end_list() + } + if (list_level < level || lists[list_level] != type) { + P1 = P1 ORS "<" (type == "." ? "o" : "u") "l>
  • " + lists[level] = type + list_level = level + } + else { + PNappnd("
  • ") + P1 = P1 ORS "
  • " + } + not_paragraph = 1 + list_started = 1 +} +!inside_codeblock && /^[ \t]*[*+-] / { ## Unordered list + match($0, /^[ \t]*[*+-] /) + level = RLENGTH - 2 + type = char($0, RSTART + RLENGTH - 2) + sub(/^[^*+-]*[*+-] /, "") + + start_list(level, type) +} +!inside_codeblock && /^[ \t]*[0-9]+\. / { ## Ordered list + match($0, /^[ \t]*/) + level = RLENGTH + type = "." + sub(/^[^.]+\. /, "") + + start_list(level, type) +} +list_level > 0 && !list_started && /[^ \t]/ { ## Non-list line + match($0, /^[ \t]*/) + level = int((RLENGTH + 2) / 2) + while (list_level >= level) { + end_list() + } + $0 = substr($0, 2 * level - 1) + not_paragraph = 1 +} + # Code blocks /^ / { if (!inside_codeblock) { -- cgit v1.3.1-23-gd82d