X-Git-Url: http://git.plutz.net/?a=blobdiff_plain;f=markdown.awk;h=ffa225b477f6e8ff3dd1b157bc0f6e715df0a494;hb=1cf0dab1d218582457bce9c839e845b920fecee0;hp=fa60543b49d43ed013325bf939e2d93ed22e7a5b;hpb=697a1bb3a7823c889abe31df5168a57dd11f37d4;p=cgilite diff --git a/markdown.awk b/markdown.awk index fa60543..ffa225b 100755 --- a/markdown.awk +++ b/markdown.awk @@ -38,7 +38,9 @@ # # Extensions - Block elements: # ---------------------------- +# - [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 @@ -48,7 +50,8 @@ # - ? Simple table (pandoc) # - ? Multiline table (pandoc) # - [x] Grid table (pandoc) -# - [x] Pipe table (php md pandoc) +# - [x] Headerless +# - [x] Pipe table (php md, pandoc) # - [x] Line blocks (pandoc) # - [x] Task lists (pandoc, custom) # - [ ] Definition lists (php md, pandoc) @@ -64,7 +67,7 @@ # - [x] ^Superscript^ ~Subscript~ (pandoc) # - [-] Bracketed spans (pandoc) # - [-] Inline attributes (pandoc) -# - [x] Image attributes (custom, pandoc inspired, inline only) +# - [x] Image attributes (custom, pandoc inspired, not for reference style) # - [x] Wiki style links [[PageName]] / [[PageName|Link Text]] # - [-] TEX-Math (pandoc) # - ? Footnotes (php md) @@ -74,7 +77,7 @@ # - ? ... three-dot ellipsis (smartypants) # - [-] en-dash (smartypants) # - [ ] Automatic em-dash / en-dash -# - [ ] Automatic -> Arrows <- +# - [x] Automatic -> Arrows <- (custom) function debug(text) { printf "\n---\n%s\n---\n", text > "/dev/stderr"; } @@ -88,12 +91,13 @@ function HTML ( text ) { return text; } -function URL ( text ) { +function URL ( text, sharp ) { gsub( /&/, "%26", text ); gsub( /"/, "%22", text ); gsub( /'/, "%27", text ); + gsub( /`/, "%60", text ); gsub( /\?/, "%3F", text ); - gsub( /#/, "%23", text ); + if (sharp) gsub( /#/, "%23", text ); gsub( /\[/, "%5B", text ); gsub( /\]/, "%5D", text ); gsub( / /, "%20", text ); @@ -113,9 +117,9 @@ function inline( line, LOCAL, len, code, href, guard ) { if ( line ~ /^$/ ) { # Recursion End return ""; - # omit processing of escaped characters - } else if ( line ~ /^\\[]\\`\*_\{\}\(\)#\+-\.![]/) { - return substr(line, 2, 1) inline( substr(line, 3) ); + # omit processing of escaped characters + } else if ( line ~ /^\\./) { + return HTML(substr(line, 2, 1)) inline( substr(line, 3) ); # hard brakes } else if ( match(line, /^ \n/) ) { @@ -129,17 +133,17 @@ 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( / (.*) /, "\\1", "1" , code) + code = gensub( /^ | $/, "", "g" , code) # escape HTML within code span gsub( /&/, "\\&", code ); gsub( //, "\\>", code ); return "" code "" inline( substr( line, len + 1 ) ) } # Wiki style links - } else if ( match( line, /^\[\[([^\]\|]+)(\|([^\]]+))?\]\]/) ) { + } else if ( match( line, /^\[\[([^]|]+)(\|[^]]+)?\]\]/) ) { len = RLENGTH; - href = gensub(/^\[\[([^\]\|]+)(\|([^\]]+))?\]\]/, "\\1", 1, substr(line, 1, len) ); - text = gensub(/^\[\[([^\]\|]+)(\|([^\]]+))?\]\]/, "\\3", 1, substr(line, 1, len) ); + href = gensub(/^\[\[([^]|]+)(\|([^]]+))?\]\]/, "\\1", 1, substr(line, 1, len) ); + text = gensub(/^\[\[([^]|]+)(\|([^]]+))?\]\]/, "\\3", 1, substr(line, 1, len) ); if ( ! text ) text = href; return "" HTML(text) "" inline( substr( line, len + 1) ); @@ -157,13 +161,13 @@ function inline( line, LOCAL, len, code, href, guard ) { # inline links # ,_______________________Image____________________________, - } else if ( match(line, /^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/) ) { + } else if ( match(line, /^\[([^]]+|!\[[^]]*\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/) ) { len = RLENGTH; - text = gensub(/^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ + text = gensub(/^\[([^]]+|!\[[^]]*\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ "\\1", 1, substr(line, 1, len) ); - href = gensub(/^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ + href = gensub(/^\[([^]]+|!\[[^]]*\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ "\\4", 1, substr(line, 1, len) ); - title = gensub(/^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ + title = gensub(/^\[([^]]+|!\[[^]]*\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ "\\6", 1, substr(line, 1, len) ); if ( title ) { return "" inline( text ) "" inline( substr( line, len + 1) ); @@ -186,37 +190,37 @@ function inline( line, LOCAL, len, code, href, guard ) { } # inline images - } else if ( match(line, /^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/) ) { + } else if ( match(line, /^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/) ) { len = RLENGTH; - text = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\1", "g", substr(line, 1, len) ); - href = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\2", "g", substr(line, 1, len) ); - title = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\4", "g", substr(line, 1, len) ); - attrib = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\6", "g", substr(line, 1, len) ); + text = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\1", "g", substr(line, 1, len) ); + href = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\2", "g", substr(line, 1, len) ); + title = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\4", "g", substr(line, 1, len) ); + attrib = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?/, "\\6", "g", substr(line, 1, len) ); if ( title && attrib ) { - return "\""" \ + return "\""" \ inline( substr( line, len + 1) ); } else if ( title ) { - return "\""" \ + return "\""" \ inline( substr( line, len + 1) ); } else if ( attrib ) { - return "\""" \ + return "\""" \ inline( substr( line, len + 1) ); } else { - return "\""" \ + return "\""" \ inline( substr( line, len + 1) ); } # reference style images - } else if ( match(line, /^!\[([^]]+)\] ?\[([^]]*)\]/ ) ) { + } else if ( match(line, /^!\[([^]]*)\] ?\[([^]]*)\]/ ) ) { len = RLENGTH; - text = gensub(/^!\[([^\n]+)\] ?\[([^\n]*)\].*/, "\\1", 1, substr(line, 1, len) ); - id = gensub(/^!\[([^\n]+)\] ?\[([^\n]*)\].*/, "\\2", 1, substr(line, 1, len) ); + text = gensub(/^!\[([^\n]*)\] ?\[([^\n]*)\].*/, "\\1", 1, substr(line, 1, len) ); + id = gensub(/^!\[([^\n]*)\] ?\[([^\n]*)\].*/, "\\2", 1, substr(line, 1, len) ); if ( ! id ) id = text; if ( rl_href[id] && rl_title[id] ) { - return "\""" \ + return "\""" \ inline( substr( line, len + 1) ); } else if ( rl_href[id] ) { - return "\""" \ + return "\""" \ inline( substr( line, len + 1) ); } else { return "" HTML(substr(line, 1, len)) inline( substr(line, len + 1) ); @@ -286,6 +290,14 @@ function inline( line, LOCAL, len, code, href, guard ) { len = RLENGTH; return substr( line, 1, len ) inline(substr(line, len + 1)); + # Arrows + } else if ( line ~ /^-->( |$)/) { # ignore multidash-arrow + return "-->" inline( substr(line, 4) ); + } else if ( line ~ /^<-( |$)/) { + return "←" inline( substr(line, 3) ); + } else if ( line ~ /^->( |$)/) { + return "→" inline( substr(line, 3) ); + # Escape lone HTML character } else if ( match( line, /^[&<>"']/) ) { return HTML(substr(line, 1, 1)) inline(substr(line, 2)); @@ -296,7 +308,41 @@ function inline( line, LOCAL, len, code, href, guard ) { } } -function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib ) { +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 = ""; 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]; + + return sec "
" \ + "" inline( htxt ) \ + "" \ + "\n\n"; +} + +# Nested Block, resets heading counters +function _nblock( block, LOCAL, hlsav, sec, n ) { + hlsav = hstack; + hstack = hstack " 0 0 0 0 0 0"; + + # Block Level + blvl++; BL[blvl]++; + 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); + 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 ); if ( block == "" ) { @@ -334,7 +380,7 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib } else if ( match( block, /^> /) ) { match( block, /(^|\n)[[:space:]]*(\n|$)/ ) || match(block, /$/); len = RLENGTH; st = RSTART; - return "
\n" _block( 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 ) @@ -385,46 +431,65 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib return "" ttext "
\n" _block(block); # Grid Tables (pandoc) - } else if ( match(block, "^\\+(-+\\+)+\n" \ - "(\\|([^\n]+\\|)+\n)+" \ - "\\+(:?=+:?\\+)+\n" \ - "((\\|([^\n]+\\|)+\n)+" \ - "\\+(-+\\+)+(\n|$))+" \ - ) ) { + # (with, and without header) + } else if ( match( block, "^\\+(-+\\+)+\n" \ + "(\\|([^\n]+\\|)+\n)+" \ + "(\\+(:?=+:?\\+)+)\n" \ + "((\\|([^\n]+\\|)+\n)+" \ + "\\+(-+\\+)+(\n|$))+" \ + ) || \ + match( block, "^()()()" \ + "(\\+(:?-+:?\\+)+)\n" \ + "((\\|([^\n]+\\|)+\n)+" \ + "\\+(-+\\+)+(\n|$))+" \ + ) ) { len = RLENGTH; st = RSTART; #initialize empty arrays split("", talign); split("", tarray); split("", tread); cols = 0; cnt=0; ttext = ""; - # table header and alignment - block = substr(block, match(block, /(\n|$)/) + 1 ); - while ( match(block, "^\\|([^\n]+\\|)+\n") ) { - cols = split( gensub( /(^\||\|$)/, "", "g", \ - gensub( /(^|[^\\])\\\|/, "\\1\\|", "g", \ - substr(block, 1, match(block, /(\n|$)/)) \ - )), tread, /\|/); - block = substr(block, match(block, /(\n|$)/) + 1 ); - for (cnt = 1; cnt < cols; cnt++) - tarray[cnt] = tarray[cnt] "\n" tread[cnt]; - } + # Column Count + cols = split( gensub( "^(\\+(:?-+:?\\+)+)(\n.*)*$", "\\1", 1, block), tread, /\+/) - 2; + # debug(" Cols: " gensub( "^(\\+(:?-+:?\\+)+)(\n.*)*$", "\\1", 1, block )); - cols = split( \ - gensub( /(^\+|\+$)/, "", "g", \ - substr(block, 1, match(block, /(\n|$)/)) \ - ), talign, /\+/); - block = substr(block, match(block, /(\n|$)/) + 1 ); + # table alignment + split( gensub( "^(.*\n)?\\+((:?=+:?\\+|(:-+|-+:|:-+:)\\+)+)(\n.*)$", "\\2", "g", block ), talign, /\+/ ); + # debug("Align: " gensub( "^(.*\n)?\\+((:?=+:?\\+|(:-+|-+:|:-+:)\\+)+)(\n.*)$", "\\2", "g", block )); - for (cnt = 1; cnt < cols; cnt++) { - if (match(talign[cnt], /:=+:/)) talign[cnt]="center"; - else if (match(talign[cnt], /=+:/)) talign[cnt]="right"; - else if (match(talign[cnt], /:=+/ )) talign[cnt]="left"; + for (cnt = 1; cnt <= cols; cnt++) { + if (match(talign[cnt], /:(-+|=+):/)) talign[cnt]="center"; + else if (match(talign[cnt], /(-+|=+):/)) talign[cnt]="right"; + else if (match(talign[cnt], /:(-+|=+)/ )) talign[cnt]="left"; else talign[cnt]=""; } - ttext = "\n" - for (cnt = 1; cnt < cols; cnt++) - ttext = ttext "" _block(tarray[cnt]) "" - ttext = ttext "\n\n" + if ( match(block, "^\\+(-+\\+)+\n" \ + "(\\|([^\n]+\\|)+\n)+" \ + "\\+(:?=+:?\\+)+\n" \ + "((\\|([^\n]+\\|)+\n)+" \ + "\\+(-+\\+)+(\n|$))+" \ + ) ) { + # table header + block = substr(block, match(block, /(\n|$)/) + 1 ); + while ( match(block, "^\\|([^\n]+\\|)+\n") ) { + split( gensub( /(^\||\|$)/, "", "g", \ + gensub( /(^|[^\\])\\\|/, "\\1\\|", "g", \ + substr(block, 1, match(block, /(\n|$)/)) \ + )), tread, /\|/); + block = substr(block, match(block, /(\n|$)/) + 1 ); + for (cnt = 1; cnt <= cols; cnt++) + tarray[cnt] = tarray[cnt] "\n" tread[cnt]; + } + + ttext = "\n" + for (cnt = 1; cnt <= cols; cnt++) + ttext = ttext "" _nblock(tarray[cnt]) "" + ttext = ttext "\n" + } + + # table body + block = substr(block, match(block, /(\n|$)/) + 1 ); + ttext = ttext "\n" while ( match(block, /^((\|([^\n]+\|)+\n)+\+(-+\+)+(\n|$))+/ ) ){ split("", tarray); @@ -434,17 +499,17 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib substr(block, 1, match(block, /(\n|$)/)) \ )), tread, /\|/); block = substr(block, match(block, /(\n|$)/) + 1 ); - for (cnt = 1; cnt < cols; cnt++) + for (cnt = 1; cnt <= cols; cnt++) tarray[cnt] = tarray[cnt] "\n" tread[cnt]; } block = substr(block, match(block, /(\n|$)/) + 1 ); ttext = ttext "" - for (cnt = 1; cnt < cols; cnt++) - ttext = ttext "" _block(tarray[cnt]) "" + for (cnt = 1; cnt <= cols; cnt++) + ttext = ttext "" _nblock(tarray[cnt]) "" ttext = ttext "\n" } - return "" ttext "
\n" _block(block); + return "" ttext "
\n" _nblock(block); # Line Blocks (pandoc) } else if ( match(block, /^\| [^\n]*(\n|$)(\| [^\n]*(\n|$)|[ \t]+[^\n[:space:]][^\n]*(\n|$))*/) ) { @@ -474,7 +539,7 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib gsub(/(^ | $)/, "", attrib); if ( match(code, "(^|\n)" guard "+(\n|$)" ) ) { len = RLENGTH; st = RSTART; - return "
" _block( substr(code, 1, st - 1) ) "
\n" \ + return "
" _nblock( substr(code, 1, st - 1) ) "
\n" \ _block( substr( code, st + len ) ); } else { match( block, /(^|\n)[[:space:]]*(\n|$)/ ) || match( block, /$/ ); @@ -525,89 +590,120 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib gsub("(^|\n) {0," indent "}", "\n", list); return "\n
    \n" _list( substr(list, 2) ) "
\n" _block( block ); - # First Order Heading - } else if ( match( block, /^[^\n]+\n===+(\n|$)/ ) ) { + # 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); + + return headline(1, text, attrib) \ + _block( substr( block, len + 1 ) ); + + # First Order Heading H1 + } else if ( match( block, /^([^\n]+)\n===+(\n|$)/ ) ) { len = RLENGTH; - HL[1]++; HL[2] = 0; HL[3] = 0; HL[4] = 0; HL[5] = 0; HL[6] = 0; - return "

" \ - inline( gensub( /\n.*$/, "", "g", block ) ) \ - "

\n\n" \ + text = gensub(/^([^\n]+)\n===+(\n.*)?$/, "\\1", 1, block) + + return headline(1, text, 0) \ _block( substr( block, len + 1 ) ); - # Second Order Heading - } else if ( match( block, /^[^\n]+\n---+(\n|$)/ ) ) { + # Second Order Heading H2 + Attrib + } else if ( match( block, /^([^\n]+)([ \t]*\{([^\}\n]+)\})\n---+(\n|$)/ ) ) { len = RLENGTH; - HL[2]++; HL[3] = 0; HL[4] = 0; HL[5] = 0; HL[6] = 0; - return "

" \ - inline( gensub( /\n.*$/, "", "g", block ) ) \ - "

\n\n" \ + 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) ); - # Nth Order Heading - } else if ( match( block, /^#{1,6}[ \t]*[^\n]+([ \t]*#*)(\n|$)/ ) ) { + # Second Order Heading H2 + } else if ( match( block, /^([^\n]+)\n---+(\n|$)/ ) ) { len = RLENGTH; - hlvl = length( gensub( /^(#{1,6}).*$/, "\\1", "g", block ) ); - htxt = gensub(/^#{1,6}[ \t]*(([^ \t\n]+|[ \t]+[^ \t\n#]|[ \t]+#+[^\n#])+)([ \t]*#*)(\n.*)?$/, "\\1", 1, block); - HL[hlvl]++; for ( n = hlvl + 1; n < 7; n++) { HL[n] = 0;} - hid = HL[1]; for ( n = 2; n <= hlvl; n++) { hid = hid "." HL[n] ; } - return "" inline( htxt ) \ - "\n\n" \ + 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( 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]*(([^ \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(n), text, 0 ) \ _block( substr( block, len + 1) ); # block images (wrapped in
) - } else if ( match(block, /^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n|$)/) ) { + } else if ( match(block, /^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n|$)/) ) { len = RLENGTH; - text = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\1", "g", block); - href = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\2", "g", block); - title = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\4", "g", block); - attrib = gensub(/^!\[([^]]+)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\6", "g", block); + text = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\1", "g", block); + href = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\2", "g", block); + title = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\4", "g", block); + attrib = gensub(/^!\[([^]]*)\]\(([^"\)]+)([ \t]+"([^"]+)")?\)(\{([a-zA-Z \t-]*)\})?(\n.*)?$/, "\\6", "g", block); if ( title && attrib ) { - return "
" \ - "\""" \ + return "
" \ + "\""" \ "
" inline(title) "
" \ "
\n\n" \ _block( substr( block, len + 1) ); } else if ( title ) { - return "
" \ - "\""" \ + return "
" \ + "\""" \ "
" inline(title) "
" \ "
\n\n" \ _block( substr( block, len + 1) ); } else if ( attrib ) { - return "
" \ - "\""" \ + return "
" \ + "\""" \ "
\n\n" \ _block( substr( block, len + 1) ); } else { - return "
" \ - "\""" \ + return "
" \ + "\""" \ "
\n\n" \ _block( substr( block, len + 1) ); } # reference style images (block) - } else if ( match(line, /^!\[([^]]+)\] ?\[([^]]*)\](\n|$)/ ) ) { + } else if ( match(line, /^!\[([^]]*)\] ?\[([^]]*)\](\n|$)/ ) ) { len = RLENGTH; - text = gensub(/^!\[([^\n]+)\] ?\[([^\n]*)\](\n.*)?$/, "\\1", 1, block); - id = gensub(/^!\[([^\n]+)\] ?\[([^\n]*)\](\n.*)?$/, "\\2", 1, block); + text = gensub(/^!\[([^\n]*)\] ?\[([^\n]*)\](\n.*)?$/, "\\1", 1, block); + id = gensub(/^!\[([^\n]*)\] ?\[([^\n]*)\](\n.*)?$/, "\\2", 1, block); if ( ! id ) id = text; if ( rl_href[id] && rl_title[id] ) { - return "
" \ - "\""" \ + return "
" \ + "\""" \ "
" inline(rl_title[id]) "
" \ "
\n\n" \ _block( substr( block, len + 1) ); } else if ( rl_href[id] ) { - return "
" \ - "\""" \ + return "
" \ + "\""" \ "
\n\n" \ _block( substr( block, len + 1) ); } else { return "

" HTML(substr(block, 1, len)) "

\n" _block( substr(block, len + 1) ); } + # Macros (standalone <> calls handled as block, so they are not wrapped in paragraph) + } else if ( AllowMacros && match( block, /^<<(([^>]|>[^>])+)>>(\n|$)/) ) { + len = RLENGTH; + text = gensub(/^<<(([^>]|>[^>])+)>>(\n.*)?$/, "\\1", 1, block); + return macro(text) _block(substr(block, len + 1) ); + # Split paragraphs } else if ( match( block, /(^|\n)[[:space:]]*(\n|$)/) ) { len = RLENGTH; st = RSTART; @@ -641,9 +737,9 @@ function _list( block, last, LOCAL, p) { # 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 = _block(p); + last = p; p = _nblock(p); } else { - last = p; p = _block(p); + last = p; p = _nblock(p); sub( /^

/, "", p ); sub( /<\/p>\n/, "", p ); } @@ -678,6 +774,7 @@ BEGIN { file = ""; rl_href[""] = ""; rl_title[""] = ""; if (ENVIRON["MD_HTML"] == "true") { AllowHTML = "true"; } HL[1] = 0; HL[2] = 0; HL[3] = 0; HL[4] = 0; HL[5] = 0; HL[6] = 0; + # hls = "0 0 0 0 0 0"; # Buffering of full file ist necessary, e.g. to find reference links while (getline) { file = file $0 "\n"; } @@ -701,5 +798,5 @@ BEGIN { # for (n in rl_href) { debug(n " | " rl_href[n] " | " rl_title[n] ); } # Run Block Processing -> The Actual Markdown! - printf "%s", _block( file ); + printf "%s", _nblock( file ); }