From: Paul Hänsch Date: Wed, 30 Aug 2023 15:32:34 +0000 (+0200) Subject: Squashed 'cgilite/' changes from ca22f379..fc3451c3 X-Git-Url: https://git.plutz.net/?a=commitdiff_plain;h=d03c336720e5cc6d24cce791e161b16371b9bd4d;p=shellwiki Squashed 'cgilite/' changes from ca22f379..fc3451c3 fc3451c3 discriminate between different list markers 88228438 unified list code 8e79399f allow block lists (again) cc08744f reduce use of non-posix gensub 3d2d9755 simpler block nesting, fix: h2 after paragraph git-subtree-dir: cgilite git-subtree-split: fc3451c360c190736b7355c318f937fe304bb3c4 --- diff --git a/markdown.awk b/markdown.awk index 5915f01..c42aa5a 100755 --- a/markdown.awk +++ b/markdown.awk @@ -41,6 +41,7 @@ # - [x] Automatic
-wrapping (custom) # - ? Heading identifiers (php md, pandoc) # - [x] Heading attributes (custom) +# - [ ]
terminates section # - [x] Automatic heading identifiers (custom) # - [x] Fenced code blocks (php md, pandoc) # - [x] Fenced code attributes @@ -106,7 +107,7 @@ function URL ( text, sharp ) { return text; } -function inline( line, LOCAL, len, code, href, guard ) { +function inline( line, LOCAL, len, text, code, href, guard ) { nu = "(\\\\\\\\|\\\\[^\\\\]|[^\\\\_]|_[[:alnum:]])*" # not underline (except when escaped) na = "(\\\\\\\\|\\\\[^\\\\]|[^\\\\\\*])*" # not asterisk (except when escaped) ieu = "_([^_[:space:]]|[^_[:space:]]" nu "[^_[:space:]])_" # inner (underline) @@ -133,7 +134,7 @@ function inline( line, LOCAL, len, code, href, guard ) { code = substr( line, len + 1, match( substr(line, len + 1), guard ) - 1) len = 2 * length(guard) + length(code) # strip single surrounding white spaces - code = gensub( /^ | $/, "", "g" , code) + gsub( /^ | $/, "", code) # escape HTML within code span gsub( /&/, "\\&", code ); gsub( //, "\\>", code ); return "" code "" inline( substr( line, len + 1 ) ) @@ -309,16 +310,17 @@ function inline( line, LOCAL, len, code, href, guard ) { } function headline( hlvl, htxt, attrib, LOCAL, sec, n, HL) { - split( gensub( /^(.* )?([0-9]+( [0-9]+){5})$/, "\\2" ,"1", hstack), HL); + match(hstack, /([0-9]+( [0-9]+){5})$/); split( substr(hstack, RSTART), HL); for ( n = hlvl; n <= 6; n++ ) { sec = sec (HL[n]?"
":""); } HL[hlvl]++; for ( n = hlvl + 1; n <= 6; n++) { HL[n] = 0;} + hid = ""; for ( n = 2; n <= blvl; n++) { hid = hid BL[n] "/"; } hid = hid HL[1]; for ( n = 2; n <= hlvl; n++) { hid = hid "." HL[n] ; } hid = hid ":" URL(htxt, 1); - hstack = gensub( /^(.* )?([0-9]+( [0-9]+){5})$/, "\\1" ,"1", hstack) \ - HL[1] " " HL[2] " " HL[3] " " HL[4] " " HL[5] " " HL[6]; + sub(/([0-9]+( [0-9]+){5})$/, "", hstack); + hstack = hstack HL[1] " " HL[2] " " HL[3] " " HL[4] " " HL[5] " " HL[6]; return sec "
" \ "" inline( htxt ) \ @@ -327,8 +329,7 @@ function headline( hlvl, htxt, attrib, LOCAL, sec, n, HL) { } # Nested Block, resets heading counters -function _nblock( block, LOCAL, hlsav, sec, n ) { - hlsav = hstack; +function _nblock( block, LOCAL, sec, n ) { hstack = hstack " 0 0 0 0 0 0"; # Block Level @@ -336,9 +337,10 @@ function _nblock( block, LOCAL, hlsav, sec, n ) { for ( n = blvl + 1; n in BL; n++) { delete BL[n]; } block = _block( block ); - split( gensub( /^(.* )?([0-9]+( [0-9]+){5})$/, "\\2" ,"1", hstack), HL); + match(hstack, /([0-9]+( [0-9]+){5})$/); split( substr(hstack, RSTART), HL); sec = ""; for ( n = 1; n <= 6; n++ ) { sec = sec (HL[n]?"
":""); } - hstack = hlsav; blvl--; + + sub("( +[0-9]+){6} *$", "", hstack); blvl--; return block sec; } @@ -380,8 +382,9 @@ function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code, } else if ( match( block, /^> /) ) { match( block, /(^|\n)[[:space:]]*(\n|$)/ ) || match(block, /$/); len = RLENGTH; st = RSTART; - return "
" gensub( /^\n|\n$/, "", "g", _nblock( gensub( /(^|\n)> /, "\n", "g", substr(block, 1, st - 1) ) ) ) "
\n\n" \ - _block( substr(block, st + len) ); + text = substr(block, 1, st - 1); gsub( /(^|\n)> /, "\n", text ); + text = _nblock( text ); gsub( /^\n|\n$/, "", text ) + return "
" text "
\n\n" _block( substr(block, st + len) ); # Pipe Tables (pandoc / php md / gfm ) } else if ( match(block, "^((\\|)?([^\n]+\\|)+[^\n]+(\\|)?)\n" \ @@ -514,12 +517,12 @@ function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code, # Line Blocks (pandoc) } else if ( match(block, /^\| [^\n]*(\n|$)(\| [^\n]*(\n|$)|[ \t]+[^\n[:space:]][^\n]*(\n|$))*/) ) { len = RLENGTH; st = RSTART; - text = substr(block, 1, len); - gsub(/\n[[:space:]]+/, " ", text); - gsub(/\n\| /, "\n", text); - gsub(/^\| |\n$/, "", text); - return "
" gensub(/\n/, "
\n", "g", inline( text )) "
\n" \ - _block( substr( block, len + 1) ); + + text = substr(block, 1, len); gsub(/\n[[:space:]]+/, " ", text); + gsub(/\n\| /, "\n", text); gsub(/^\| |\n$/, "", text); + text = inline(text); gsub(/\n/, "
\n", text); + + return "
" text "
\n" _block( substr( block, len + 1) ); # Indented Code Block } else if ( match(block, /^( |\t)( *\t*[^ \t\n]+ *\t*)+(\n|$)(( |\t)[^\n]+(\n|$)|[ \t]*(\n|$))*/) ) { @@ -568,59 +571,55 @@ function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code, # First Order Heading H1 + Attrib } else if ( match( block, /^([^\n]+)([ \t]*\{([^\}\n]+)\})\n===+(\n|$)/ ) ) { - len = RLENGTH; - text = gensub(/^([^\n]+)([ \t]*\{([^\}\n]+)\})\n===+(\n.*)?$/, "\\1", 1, block) - attrib = gensub(/^([^\n]+)([ \t]*\{([^\}\n]+)\})\n===+(\n.*)?$/, "\\3", 1, block) + len = RLENGTH; text = attrib = block; + sub(/([ \t]*\{([^\}\n]+)\})\n===+(\n.*)?$/, "", text); + sub(/\}\n===+(\n.*)?$/, "", attrib); sub(/^([^\n]+)[ \t]*\{/, "", attrib); gsub(/[^a-zA-Z0-9_-]+/, " ", attrib); gsub(/(^ | $)/, "", attrib); - return headline(1, text, attrib) \ - _block( substr( block, len + 1 ) ); + return headline(1, text, attrib) _block( substr( block, len + 1 ) ); # First Order Heading H1 } else if ( match( block, /^([^\n]+)\n===+(\n|$)/ ) ) { - len = RLENGTH; - text = gensub(/^([^\n]+)\n===+(\n.*)?$/, "\\1", 1, block) + len = RLENGTH; text = substr(block, 1, len); + sub(/\n===+(\n.*)?$/, "", text); - return headline(1, text, 0) \ - _block( substr( block, len + 1 ) ); + return headline(1, text, 0) _block( substr( block, len + 1 ) ); # Second Order Heading H2 + Attrib } else if ( match( block, /^([^\n]+)([ \t]*\{([^\}\n]+)\})\n---+(\n|$)/ ) ) { - len = RLENGTH; - text = gensub(/^([^\n]+)([ \t]*\{([^\}\n]+)\})\n---+(\n.*)?$/, "\\1", 1, block) - attrib = gensub(/^([^\n]+)([ \t]*\{([^\}\n]+)\})\n---+(\n.*)?$/, "\\3", 1, block) + len = RLENGTH; text = attrib = block; + sub(/([ \t]*\{([^\}\n]+)\})\n---+(\n.*)?$/, "", text); + sub(/\}\n---+(\n.*)?$/, "", attrib); sub(/^([^\n]+)[ \t]*\{/, "", attrib); gsub(/[^a-zA-Z0-9_-]+/, " ", attrib); gsub(/(^ | $)/, "", attrib); - return headline(2, text, attrib) \ - _block( substr( block, len + 1) ); + return headline(2, text, attrib) _block( substr( block, len + 1) ); # Second Order Heading H2 } else if ( match( block, /^([^\n]+)\n---+(\n|$)/ ) ) { - len = RLENGTH; - text = gensub(/^([^\n]+)\n---+(\n.*)?$/, "\\1", 1, block) + len = RLENGTH; text = substr(block, 1, len); + sub(/\n---+(\n.*)?$/, "", text); - return headline(2, text, 0) \ - _block( substr( block, len + 1) ); + return headline(2, text, 0) _block( substr( block, len + 1) ); # Nth Order Heading H1 H2 H3 H4 H5 H6 + Attrib } else if ( match( block, /^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*([ \t]*\{([a-zA-Z \t-]*)\})(\n|$)/ ) ) { - len = RLENGTH; - n = gensub(/^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*([ \t]*\{([a-zA-Z \t-]*)\})(\n.*)?$/, "\\1", 1, block); - text = gensub(/^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*([ \t]*\{([a-zA-Z \t-]*)\})(\n.*)?$/, "\\2", 1, block); - attrib = gensub(/^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*([ \t]*\{([a-zA-Z \t-]*)\})(\n.*)?$/, "\\5", 1, block); + len = RLENGTH; text = attrib = substr(block, 1, len); + match(block, /^#{1,6}/); n = RLENGTH; + + sub(/^(#{1,6})[ \t]*/, "", text); sub(/[ \t]*#*([ \t]*\{([a-zA-Z \t-]*)\})(\n.*)?$/, "", text); + sub(/^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*[ \t]*\{/, "", attrib); + sub(/\})(\n.*)?$/, "", attrib); gsub(/[^a-zA-Z0-9_-]+/, " ", attrib); gsub(/(^ | $)/, "", attrib); - return headline( length(n), text, attrib ) \ - _block( substr( block, len + 1) ); + return headline( n, text, attrib ) _block( substr( block, len + 1) ); # Nth Order Heading H1 H2 H3 H4 H5 H6 } else if ( match( block, /^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*(\n|$)/ ) ) { - len = RLENGTH; - n = gensub(/^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*(\n.*)?$/, "\\1", 1, block); - text = gensub(/^(#{1,6})[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[ \t]*[^ \t\n#])+)[ \t]*#*(\n.*)?$/, "\\2", 1, block); + len = RLENGTH; text = substr(block, 1, len); + match(block, /^#{1,6}/); n = RLENGTH; + sub(/^(#{1,6})[ \t]*/, "", text); sub(/[ \t]*#*(\n.*)?$/, "", text); - return headline( length(n), text, 0 ) \ - _block( substr( block, len + 1) ); + return headline( n, text, 0 ) _block( substr( block, len + 1) ); # block images (wrapped in
) } else if ( match(block, /^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n|$)/) ) { @@ -680,11 +679,6 @@ function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code, text = gensub(/^<<(([^>]|>[^>])+)>>(\n.*)?$/, "\\1", 1, block); return macro(text) _block(substr(block, len + 1) ); - # Horizontal rule - } else if ( match( block, /(^|\n) ? ? ?((\* *){3,}|(- *){3,}|(_ *){3,})($|\n)/) ) { - len = RLENGTH; st = RSTART; - return _block(substr(block, 1, st - 1)) "
\n" _block(substr(block, st + len)); - # Definition list } else if (match( block, "^(([ \t]*\n)*[^:\n \t][^\n]+\n" \ "([ \t]*\n)* ? ? ?:[ \t][^\n]+(\n|$)" \ @@ -696,39 +690,23 @@ function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code, list = substr( block, 1, RLENGTH); block = substr( block, RLENGTH + 1); return "\n
\n" _dlist( list ) "
\n" _block( block ); - # Unordered list - } else if ( match( block, "(^|\n) ? ? ?[-+*][ \t][^\n]+(\n|$)" \ - "(([ \t]*\n)* ? ? ?[-+*][ \t][^\n]+(\n|$)" \ - "|([ \t]*\n)*( ? ? ?\t| +)[^\n]+(\n|$)" \ - "|[^\n \t][^\n]+(\n|$))*" ) ) { - st = RSTART; len = RLENGTH; list = substr( block, RSTART, RLENGTH); - sub("^\n", "", list); match(list, "^ ? ? ?[-+*]"); indent = RLENGTH; - gsub( "(^|\n) {0," indent - 1 "}", "\n", list); sub("^\n", "", list); - - text = substr(block, 1, st - 1); block = substr(block, st + len); - if (match( list, "\n([0-9]+\\.|#\\.)[ \t]" )) { - block = substr(list, RSTART + 1) block; - list = substr(list, 1, RSTART); - } - - return _block( text ) "
    \n" _list( list, "[-+*]" ) "
\n" _block( block ); - - # Ordered list - } else if ( match( block, "(^|\n) ? ? ?([0-9]+\\.|#\\.)[ \t][^\n]+(\n|$)" \ - "(([ \t]*\n)* ? ? ?([0-9]+\\.|#\\.)[ \t][^\n]+(\n|$)" \ - "|([ \t]*\n)*( ? ? ?\t| +)[^\n]+(\n|$)" \ - "|[^\n \t][^\n]+(\n|$))*" ) ) { - st = RSTART; len = RLENGTH; list = substr( block, RSTART, RLENGTH); - sub("^\n", "", list); match(list, "^ ? ? ?[0-9#]"); indent = RLENGTH; - gsub( "(^|\n) {0," indent - 1 "}", "\n", list); sub("^\n", "", list); - - text = substr(block, 1, st - 1); block = substr(block, st + len); - if (match( list, "\n[-+*][ \t]" )) { - block = substr(list, RSTART + 1) block; - list = substr(list, 1, RSTART); - } - - return _block( text ) "
    \n" _list( list, "([0-9]+\\.|#\\.)" ) "
\n" _block( block ); + # Unordered list types + } else if ( text = _startlist( block, "ul", "-", "([+*]|[0-9]+\\.|#\\.|[0-9]+\\)|#\\))") ) { + return text; + } else if ( text = _startlist( block, "ul", "\\+", "([-*]|[0-9]+\\.|#\\.|[0-9]+\\)|#\\))") ) { + return text; + } else if ( text = _startlist( block, "ul", "\\*", "([-+]|[0-9]+\\.|#\\.|[0-9]+\\)|#\\))") ) { + return text; + + # Ordered list types + } else if ( text = _startlist( block, "ol", "[0-9]+\\.", "([-+*]|#\\.|[0-9]+\\)|#\\))") ) { + return text; + } else if ( text = _startlist( block, "ol", "[0-9]+\\)", "([-+*]|[0-9]+\\.|#\\.|#\\))") ) { + return text; + } else if ( text = _startlist( block, "ol", "#\\.", "([-+*]|[0-9]+\\.|[0-9]+\\)|#\\))") ) { + return text; + } else if ( text = _startlist( block, "ol", "#\\)", "([-+*]|[0-9]+\\.|#\\.|[0-9]+\\))") ) { + return text; # Split paragraphs } else if ( match( block, /(^|\n)[[:space:]]*(\n|$)/) ) { @@ -736,22 +714,47 @@ function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code, return _block( substr(block, 1, st - 1) ) "\n" \ _block( substr(block, st + len) ); + # Horizontal rule + } else if ( match( block, /(^|\n) ? ? ?((\* *){3,}|(- *){3,}|(_ *){3,})($|\n)/) ) { + len = RLENGTH; st = RSTART; + return _block(substr(block, 1, st - 1)) "
\n" _block(substr(block, st + len)); + # Plain paragraph } else { return "

" inline(block) "

\n"; } } -function _list (block, mark, LOCAL, len, st, text, indent, task) { +function _startlist(block, type, mark, exclude, LOCAL, st, len, list, indent, text) { + if (match( block, "(^|\n) ? ? ?" mark "[ \t][^\n]+(\n|$)" \ + "(([ \t]*\n)* ? ? ?" mark "[ \t][^\n]+(\n|$)" \ + "|([ \t]*\n)*( ? ? ?\t| +)[^\n]+(\n|$)" \ + "|[^\n \t][^\n]+(\n|$))*" ) ) { + st = RSTART; len = RLENGTH; list = substr( block, RSTART, RLENGTH); + + sub("^\n", "", list); match(list, "^ ? ? ?"); indent = RLENGTH; + gsub( "(^|\n) {0," indent - 1 "}", "\n", list); sub("^\n", "", list); + + text = substr(block, 1, st - 1); block = substr(block, st + len); + if (match( list, "\n" exclude "[ \t]" )) { + block = substr(list, RSTART + 1) block; + list = substr(list, 1, RSTART); + } + + return _block( text ) "<" type ">\n" _list( list, mark ) "\n" _block( block ); + } else return 0; +} + +function _list (block, mark, p, LOCAL, len, st, text, indent, task) { if ( match(block, "^([ \t]*\n)*$")) return; + match(block, "^" mark "[ \t]"); indent = RLENGTH; sub("^" mark "[ \t]", "", block); - match( block, "\n" mark "[ \t][^\n]+(\n|$)" \ - "(([ \t]*\n)* ? ? ?" mark "[ \t][^\n]+(\n|$)" \ - "|([ \t]*\n)*( ? ? ?\t| +)[^\n]+(\n|$)" \ - "|[^\n \t][^\n]+(\n|$))*"); - (RLENGTH == -1) ? st = length(block) + 1 : st = RSTART; + if (match(block, /\n[ \t]*\n/)) p = 1; + + match( block, "\n" mark "[ \t][^\n]+(\n|$)" ); + st = (RLENGTH == -1) ? length(block) + 1 : RSTART; text = substr(block, 1, st); block = substr(block, st + 1); gsub("\n {0," indent "}", "\n", text); @@ -761,13 +764,13 @@ function _list (block, mark, LOCAL, len, st, text, indent, task) { match( text, /^\[\/\]/ ) ? "
  • " : \ match( text, /^\[\?\]/ ) ? "
  • " : \ match( text, /^\[[xX]\]/) ? "
  • " : "
  • "; - sub(/^\[[-? /xX]\]/, "", text); + sub(/^\[[-? \/xX]\]/, "", text); text = _nblock( text ); - if (match( text, "^

    (]|\n$" )) + if ( ! p && match( text, "^

    (]|\n$" )) gsub( "(^

    |

    \n$)", "", text); - return task text "
  • \n" _list(block, mark); + return task text "\n" _list(block, mark, p); } function _dlist (block, LOCAL, len, st, text, indent, p) {