X-Git-Url: http://git.plutz.net/?a=blobdiff_plain;f=markdown.awk;h=5915f011ece716dc8ab33825017226bf368e3a19;hb=ca22f379dcbc2047479fd165d56f8c5c938dac43;hp=a2bb989bd3d6e0af3752578695656d37941ef67d;hpb=925f0423dcc9040fa530e9090db2b7c914243451;p=cgilite diff --git a/markdown.awk b/markdown.awk index a2bb989..5915f01 100755 --- a/markdown.awk +++ b/markdown.awk @@ -40,6 +40,7 @@ # ---------------------------- # - [x] Automatic
-wrapping (custom) # - ? Heading identifiers (php md, pandoc) +# - [x] Heading attributes (custom) # - [x] Automatic heading identifiers (custom) # - [x] Fenced code blocks (php md, pandoc) # - [x] Fenced code attributes @@ -53,7 +54,7 @@ # - [x] Pipe table (php md, pandoc) # - [x] Line blocks (pandoc) # - [x] Task lists (pandoc, custom) -# - [ ] Definition lists (php md, pandoc) +# - [x] Definition lists (php md, pandoc) # - [-] Numbered example lists (pandoc) # - [-] Metadata blocks (pandoc) # - [x] Metadata blocks (custom) @@ -307,39 +308,42 @@ function inline( line, LOCAL, len, code, href, guard ) { } } -function headline( hlvl, htxt, LOCAL, sec, n, HL) { - split( gensub( /^(.* )?(([0-9]+ ){5}[0-9]+)$/, "\\2" ,"1", hstack), HL); +function headline( hlvl, htxt, attrib, LOCAL, sec, n, HL) { + split( gensub( /^(.* )?([0-9]+( [0-9]+){5})$/, "\\2" ,"1", hstack), HL); for ( n = hlvl; n <= 6; n++ ) { sec = sec (HL[n]?"
":""); } HL[hlvl]++; for ( n = hlvl + 1; n <= 6; n++) { HL[n] = 0;} - hid = HL[1]; for ( n = 2; n <= hlvl; n++) { hid = hid "." HL[n] ; } - # hid = hid ":" URL(htxt, 1); + 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 = HL[1] " " HL[2] " " HL[3] " " HL[4] " " HL[5] " " HL[6]; + hstack = gensub( /^(.* )?([0-9]+( [0-9]+){5})$/, "\\1" ,"1", hstack) \ + HL[1] " " HL[2] " " HL[3] " " HL[4] " " HL[5] " " HL[6]; - return sec "
10)?"":" id=\"" hid "\"") ">" \ - "

" inline( htxt ) \ - ((blvl > 0)?"":"") \ - "

\n\n"; + return sec "
" \ + "" inline( htxt ) \ + "" \ + "\n"; } # Nested Block, resets heading counters -function _nblock( block, LOCAL, hlsav, sec ) { +function _nblock( block, LOCAL, hlsav, sec, n ) { hlsav = hstack; - hstack = "0 0 0 0 0 0"; + hstack = hstack " 0 0 0 0 0 0"; # Block Level - blvl++; + blvl++; BL[blvl]++; + for ( n = blvl + 1; n in BL; n++) { delete BL[n]; } block = _block( block ); - split( gensub( /^(.* )?(([0-9]+ ){5}[0-9]+)$/, "\2" ,"1", hstack), HL); + split( gensub( /^(.* )?([0-9]+( [0-9]+){5})$/, "\\2" ,"1", hstack), HL); sec = ""; for ( n = 1; n <= 6; n++ ) { sec = sec (HL[n]?"
":""); } hstack = hlsav; blvl--; return block sec; } -function _block( block, LOCAL, st, len, hlvl, htxt, sec, guard, code, indent, attrib ) { - gsub( /^\n+|\n+$/, "", block ); +function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code, indent, list ) { + gsub( "(^\n+|\n+$)", "", block ); if ( block == "" ) { return ""; @@ -376,7 +380,7 @@ function _block( block, LOCAL, st, len, hlvl, htxt, sec, guard, code, indent, at } else if ( match( block, /^> /) ) { match( block, /(^|\n)[[:space:]]*(\n|$)/ ) || match(block, /$/); len = RLENGTH; st = RSTART; - return "
\n" _nblock( gensub( /(^|\n)> /, "\n", "g", substr(block, 1, st - 1) ) ) "
\n\n" \ + return "
" gensub( /^\n|\n$/, "", "g", _nblock( gensub( /(^|\n)> /, "\n", "g", substr(block, 1, st - 1) ) ) ) "
\n\n" \ _block( substr(block, st + len) ); # Pipe Tables (pandoc / php md / gfm ) @@ -510,11 +514,11 @@ function _block( block, LOCAL, st, len, hlvl, htxt, sec, guard, code, indent, at # Line Blocks (pandoc) } else if ( match(block, /^\| [^\n]*(\n|$)(\| [^\n]*(\n|$)|[ \t]+[^\n[:space:]][^\n]*(\n|$))*/) ) { len = RLENGTH; st = RSTART; - code = substr(block, 1, len); - gsub(/\n[[:space:]]+/, " ", code); - gsub(/\n\| /, "\n", code); - gsub(/^\| |\n$/, "", code); - return "
" gensub(/\n/, "
\n", "g", inline( code )) "
\n" \ + 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) ); # Indented Code Block @@ -529,7 +533,7 @@ function _block( block, LOCAL, st, len, hlvl, htxt, sec, guard, code, indent, at # Fenced Divs (pandoc, custom) } else if ( match( block, /^(:::+)/ ) ) { guard = substr( block, 1, RLENGTH ); - code = gensub(/^[^\n]+\n/, "", 1, block); + code = block; sub(/^[^\n]+\n/, "", code); attrib = gensub(/^:::+[ \t]*\{?[ \t]*([^\}\n]*)\}?[ \t]*\n.*$/, "\\1", 1, block); gsub(/[^a-zA-Z0-9_-]+/, " ", attrib); gsub(/(^ | $)/, "", attrib); @@ -562,52 +566,60 @@ function _block( block, LOCAL, st, len, hlvl, htxt, sec, guard, code, indent, at _block( substr(block, st + len) ); } - # Unordered list - } else if ( match( block, "^ ? ? ?[-+*][ \t]+[^\n]+(\n|$)" \ - "(([ \t]*\n)* ? ? ?[-+*][ \t]+[^\n]+(\n|$)" \ - "|([ \t]*\n)*( ? ? ?\t| +)[^\n]+(\n|$)" \ - "|[^\n]+(\n|$))*" ) ) { - list = substr( block, 1, RLENGTH); - block = substr( block, RLENGTH + 1); - indent = length( gensub(/[-+*][ \t]+[^\n]+.*$/, "", 1, list) ); - - gsub("(^|\n) {0," indent "}", "\n", list); - return "\n\n" _block( block ); - - # Ordered list - } else if ( match( block, "^ ? ? ?([0-9]+|#)\\.[ \t]+[^\n]+(\n|$)" \ - "(([ \t]*\n)* ? ? ?([0-9]+|#)\\.[ \t]+[^\n]+(\n|$)" \ - "|([ \t]*\n)*( ? ? ?\t| +)[^\n]+(\n|$)" \ - "|[^\n]+(\n|$))*" ) ) { - list = substr( block, 1, RLENGTH); - block = substr( block, RLENGTH + 1); - indent = length( gensub(/([0-9]+|#)\.[ \t]+[^\n]+.*$/, "", 1, list) ); + # 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) + gsub(/[^a-zA-Z0-9_-]+/, " ", attrib); gsub(/(^ | $)/, "", attrib); - gsub("(^|\n) {0," indent "}", "\n", list); - return "\n
    \n" _list( substr(list, 2) ) "
\n" _block( block ); + return headline(1, text, attrib) \ + _block( substr( block, len + 1 ) ); # First Order Heading H1 - } else if ( match( block, /^[^\n]+\n===+(\n|$)/ ) ) { + } else if ( match( block, /^([^\n]+)\n===+(\n|$)/ ) ) { len = RLENGTH; + text = gensub(/^([^\n]+)\n===+(\n.*)?$/, "\\1", 1, block) - return headline(1, gensub( /\n.*$/, "", "g", block )) \ + 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) + gsub(/[^a-zA-Z0-9_-]+/, " ", attrib); gsub(/(^ | $)/, "", attrib); + + return headline(2, text, attrib) \ + _block( substr( block, len + 1) ); + # Second Order Heading H2 - } else if ( match( block, /^[^\n]+\n---+(\n|$)/ ) ) { + } else if ( match( block, /^([^\n]+)\n---+(\n|$)/ ) ) { + len = RLENGTH; + text = gensub(/^([^\n]+)\n---+(\n.*)?$/, "\\1", 1, block) + + 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); + gsub(/[^a-zA-Z0-9_-]+/, " ", attrib); gsub(/(^ | $)/, "", attrib); - return headline(2, gensub( /\n.*$/, "", "g", block )) \ + return headline( length(n), text, attrib ) \ _block( substr( block, len + 1) ); # Nth Order Heading H1 H2 H3 H4 H5 H6 - } else if ( match( block, /^#{1,6}[ \t]*[^\n]+([ \t]*#*)(\n|$)/ ) ) { + } 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); - return headline( \ - length( gensub( /^(#{1,6}).*$/, "\\1", "g", block ) ), \ - gensub(/^#{1,6}[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[^\n#])+)([ \t]*#*)(\n.*)?$/, "\\1", 1, block) \ - ) \ + return headline( length(n), text, 0 ) \ _block( substr( block, len + 1) ); # block images (wrapped in
) @@ -668,69 +680,118 @@ function _block( block, LOCAL, st, len, hlvl, htxt, sec, guard, code, indent, at 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|$)" \ + "(([ \t]*\n)* ? ? ?:[ \t][^\n]+(\n|$)" \ + "|[^:\n \t][^\n]+(\n|$)" \ + "|( ? ? ?\t| +)[^\n]+(\n|$)" \ + "|([ \t]*\n)+( ? ? ?\t| +)[^\n]+(\n|$))*)+" \ + )) { + 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" _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 ); + # Split paragraphs } else if ( match( block, /(^|\n)[[:space:]]*(\n|$)/) ) { len = RLENGTH; st = RSTART; 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, last, LOCAL, p) { - if ( ! length(block) ) return ""; - gsub(/^([-+*]|[0-9]+\.|#\.)( ? ? ?|\t)/, "", block) +function _list (block, mark, LOCAL, len, st, text, indent, task) { + if ( match(block, "^([ \t]*\n)*$")) return; + match(block, "^" mark "[ \t]"); indent = RLENGTH; + sub("^" mark "[ \t]", "", block); - # slice next list item from input - if ( match( block, /\n([-+*]|[0-9]+\.|#\.)[ \t]+[^\n]+/) ) { - p = substr( block, 1, RSTART); - block = substr( block, RSTART + 1); - } else { - p = block; block = ""; - } - sub( /\n +([-+*]|[0-9]+\.|#\.)/, "\n&", p ); + 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; + text = substr(block, 1, st); block = substr(block, st + 1); - # if this should be a paragraph item - # either previous item (last) or current item (p) contains blank lines - if (match(last, /\n[[:space:]]*\n/) || match(p, /\n[[:space:]]*\n/) ) { - last = p; p = _nblock(p); - } else { - last = p; p = _nblock(p); - sub( /^

/, "", p ); - sub( /<\/p>\n/, "", p ); + gsub("\n {0," indent "}", "\n", text); + + task = match( text, /^\[ \]/ ) ? "

  • " : \ + match( text, /^\[-\]/ ) ? "
  • " : \ + match( text, /^\[\/\]/ ) ? "
  • " : \ + match( text, /^\[\?\]/ ) ? "
  • " : \ + match( text, /^\[[xX]\]/) ? "
  • " : "
  • "; + sub(/^\[[-? /xX]\]/, "", text); + + text = _nblock( text ); + if (match( text, "^

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

    |

    \n$)", "", text); + + return task text "
  • \n" _list(block, mark); +} + +function _dlist (block, LOCAL, len, st, text, indent, p) { + if (match( block, "^([ \t]*\n)*[^:\n \t][^\n]+\n" )) { + len = RLENGTH; text = substr(block, 1, len); + gsub( "(^\n*|\n*$)", "", text ); + return "
    " inline( text ) "
    \n" _dlist( substr(block, len + 1) ); + } else if (match( block, "^([ \t]*\n)* ? ? ?:[ \t][^\n]+(\n|$)" \ + "([^:\n \t][^\n]+(\n|$)" \ + "|( ? ? ?\t| +)[^\n]+(\n|$)" \ + "|([ \t]*\n)+( ? ? ?\t| +)[^\n]+(\n|$))*" \ + )) { + len = RLENGTH; text = substr(block, 1, len); + sub( "^([ \t]*\n)*", "", text); + match(text, "^ ? ? ?:(\t| +)"); indent = RLENGTH; + sub( "^ ? ? ?:(\t| +)", "", text); + gsub( "(^|\n) {0," indent "}", "\n", text ); + + text = _nblock(text); + if (match( text, "^

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

    |

    \n$)", "", text); + + return "
    " text "
    \n" _dlist( substr(block, len + 1) ); } - sub( /\n$/, "", p ); - - # Task List (pandoc, custom) - if ( p ~ /^\[ \].*/ ) { return "
  • " \ - substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[-\].*/ ) { return "
  • " \ - substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[\?\].*/ ) { return "
  • " \ - substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[\/\].*/ ) { return "
  • " \ - substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[[xX]\].*/ ) { return "
  • " \ - substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^

    \[ \].*/ ) { return "

  • " \ - substr(p, 7) "

  • \n" _list( block, last ); - } else if ( p ~ /^

    \[-\].*/ ) { return "

  • " \ - substr(p, 7) "

  • \n" _list( block, last ); - } else if ( p ~ /^

    \[\?\].*/ ) { return "

  • " \ - substr(p, 7) "

  • \n" _list( block, last ); - } else if ( p ~ /^

    \[\/\].*/ ) { return "

  • " \ - substr(p, 7) "

  • \n" _list( block, last ); - } else if ( p ~ /^

    \[[xX]\].*/ ) { return "

  • " \ - substr(p, 7) "

  • \n" _list( block, last ); - } else { return "
  • " p "
  • \n" _list( block, last ); } } BEGIN {