From ef47a42e878d7668aadeb1e14d9cb031303e92a3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Thu, 18 May 2023 14:05:58 +0200 Subject: [PATCH] Squashed 'cgilite/' changes from 970afdaf..01dadd76 01dadd76 enable block element Macros 697a1bb3 extesion: introduce
-wrapped images as block elements a8a5ea58 bugfix: enable image links ffe17caf W3C Validator compliance: introduce separate function for escaping URL references, omit superfluous trailing slashes (e.g. in
) git-subtree-dir: cgilite git-subtree-split: 01dadd76ff332d89503364a794423564f01805ea --- markdown.awk | 158 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 37 deletions(-) diff --git a/markdown.awk b/markdown.awk index 44d4e0d..b507266 100755 --- a/markdown.awk +++ b/markdown.awk @@ -42,6 +42,8 @@ # - [x] Automatic heading identifiers (custom) # - [x] Fenced code blocks (php md, pandoc) # - [x] Fenced code attributes +# - [x] Images (as block elements,
-wrapped) (custom) +# - [x] reference style block images # - [/] Tables # - ? Simple table (pandoc) # - ? Multiline table (pandoc) @@ -86,6 +88,20 @@ function HTML ( text ) { return text; } +function URL ( text ) { + gsub( /&/, "%26", text ); + gsub( /"/, "%22", text ); + gsub( /'/, "%27", text ); + gsub( /\?/, "%3F", text ); + gsub( /#/, "%23", text ); + gsub( /\[/, "%5B", text ); + gsub( /\]/, "%5D", text ); + gsub( / /, "%20", text ); + gsub( / /, "%09", text ); + gsub( /\\/, "%5C", text ); + return text; +} + function inline( line, LOCAL, len, code, href, guard ) { nu = "(\\\\\\\\|\\\\[^\\\\]|[^\\\\_]|_[[:alnum:]])*" # not underline (except when escaped) na = "(\\\\\\\\|\\\\[^\\\\]|[^\\\\\\*])*" # not asterisk (except when escaped) @@ -103,7 +119,7 @@ function inline( line, LOCAL, len, code, href, guard ) { # hard brakes } else if ( match(line, /^ \n/) ) { - return "
\n" inline( substr(line, RLENGTH + 1) ); + return "
\n" inline( substr(line, RLENGTH + 1) ); # ``code spans`` } else if ( match( line, /^`+/) ) { @@ -125,30 +141,34 @@ function inline( line, LOCAL, len, code, href, guard ) { 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) ); + return "" HTML(text) "" inline( substr( line, len + 1) ); # quick links ("automatic links" in md doc) } else if ( match( line, /^<[a-zA-Z]+:\/\/([-\.[:alnum:]]+)(:[0-9]*)?(\/[^>]*)?>/ ) ) { len = RLENGTH; - href = HTML( substr( line, 2, len - 2) ); + href = URL( substr( line, 2, len - 2) ); return "" href "" inline( substr( line, len + 1) ); # quick link email } else if ( match( line, /^<[a-zA-Z0-9.!#$%&'\''*+\/=?^_`{|}~-]+@[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*>/ ) ) { len = RLENGTH; - href = HTML( substr( line, 2, len - 2) ); + href = URL( substr( line, 2, len - 2) ); return "" href "" inline( substr( line, len + 1) ); # inline links - } else if ( match(line, /^\[([^]]+)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/) ) { + # ,_______________________Image____________________________, + } else if ( match(line, /^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/) ) { len = RLENGTH; - text = gensub(/^\[([^]]+)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, "\\1", 1, substr(line, 1, len) ); - href = gensub(/^\[([^]]+)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, "\\2", 1, substr(line, 1, len) ); - title = gensub(/^\[([^]]+)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, "\\4", 1, substr(line, 1, len) ); + text = gensub(/^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ + "\\1", 1, substr(line, 1, len) ); + href = gensub(/^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ + "\\4", 1, substr(line, 1, len) ); + title = gensub(/^\[([^]]+|!\[[^]]+\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/, \ + "\\6", 1, substr(line, 1, len) ); if ( title ) { - return "" inline( text ) "" inline( substr( line, len + 1) ); + return "" inline( text ) "" inline( substr( line, len + 1) ); } else { - return "" inline( text ) "" inline( substr( line, len + 1) ); + return "" inline( text ) "" inline( substr( line, len + 1) ); } # reference style links @@ -158,9 +178,9 @@ function inline( line, LOCAL, len, code, href, guard ) { id = gensub(/^\[([^\n]+)\] ?\[([^\n]*)\].*/, "\\2", 1, substr(line, 1, len) ); if ( ! id ) id = text; if ( rl_href[id] && rl_title[id] ) { - return "" inline(text) "" inline( substr( line, len + 1) ); + return "" inline(text) "" inline( substr( line, len + 1) ); } else if ( rl_href[id] ) { - return "" inline(text) "" inline( substr( line, len + 1) ); + return "" inline(text) "" inline( substr( line, len + 1) ); } else { return "" HTML(substr(line, 1, len)) inline( substr(line, len + 1) ); } @@ -173,13 +193,17 @@ function inline( line, LOCAL, len, code, href, guard ) { 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 "\""" inline( substr( line, len + 1) ); + return "\""" \ + inline( substr( line, len + 1) ); } else if ( title ) { - return "\""" inline( substr( line, len + 1) ); + return "\""" \ + inline( substr( line, len + 1) ); } else if ( attrib ) { - return "\""" inline( substr( line, len + 1) ); + return "\""" \ + inline( substr( line, len + 1) ); } else { - return "\""" inline( substr( line, len + 1) ); + return "\""" \ + inline( substr( line, len + 1) ); } # reference style images @@ -189,9 +213,11 @@ function inline( line, LOCAL, len, code, href, guard ) { id = gensub(/^!\[([^\n]+)\] ?\[([^\n]*)\].*/, "\\2", 1, substr(line, 1, len) ); if ( ! id ) id = text; if ( rl_href[id] && rl_title[id] ) { - return "\""" inline( substr( line, len + 1) ); + return "\""" \ + inline( substr( line, len + 1) ); } else if ( rl_href[id] ) { - return "\""" inline( substr( line, len + 1) ); + return "\""" \ + inline( substr( line, len + 1) ); } else { return "" HTML(substr(line, 1, len)) inline( substr(line, len + 1) ); } @@ -427,7 +453,7 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib gsub(/\n[[:space:]]+/, " ", code); gsub(/\n\| /, "\n", code); gsub(/^\| |\n$/, "", code); - return "
" gensub(/\n/, "
\n", "g", inline( code )) "
\n" \ + return "
" gensub(/\n/, "
\n", "g", inline( code )) "
\n" \ _block( substr( block, len + 1) ); # Indented Code Block @@ -503,20 +529,20 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib } 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 "

" \ + return "

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

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

" \ + return "

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

\n\n" \ + "\n\n" \ _block( substr( block, len + 1) ); # Nth Order Heading @@ -526,10 +552,68 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib 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 ) \ + return "" inline( htxt ) \ "\n\n" \ _block( substr( block, len + 1) ); + # block images (wrapped in
) + } 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); + if ( title && attrib ) { + return "
" \ + "\""" \ + "
" inline(title) "
" \ + "
\n\n" \ + _block( substr( block, len + 1) ); + } else if ( title ) { + return "
" \ + "\""" \ + "
" inline(title) "
" \ + "
\n\n" \ + _block( substr( block, len + 1) ); + } else if ( attrib ) { + return "
" \ + "\""" \ + "
\n\n" \ + _block( substr( block, len + 1) ); + } else { + return "
" \ + "\""" \ + "
\n\n" \ + _block( substr( block, len + 1) ); + } + + # reference style images (block) + } else if ( match(line, /^!\[([^]]+)\] ?\[([^]]*)\](\n|$)/ ) ) { + len = RLENGTH; + 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 "
" \ + "\""" \ + "
" inline(rl_title[id]) "
" \ + "
\n\n" \ + _block( substr( block, len + 1) ); + } else if ( rl_href[id] ) { + 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; @@ -539,7 +623,7 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent, attrib # 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)); + return _block(substr(block, 1, st - 1)) "
\n" _block(substr(block, st + len)); # Plain paragraph } else { @@ -572,25 +656,25 @@ function _list( block, last, LOCAL, p) { sub( /\n$/, "", p ); # Task List (pandoc, custom) - if ( p ~ /^\[ \].*/ ) { return "
  • " \ + if ( p ~ /^\[ \].*/ ) { return "
  • " \ substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[-\].*/ ) { return "
  • " \ + } else if ( p ~ /^\[-\].*/ ) { return "
  • " \ substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[\?\].*/ ) { return "
  • " \ + } else if ( p ~ /^\[\?\].*/ ) { return "
  • " \ substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[\/\].*/ ) { return "
  • " \ + } else if ( p ~ /^\[\/\].*/ ) { return "
  • " \ substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^\[[xX]\].*/ ) { return "
  • " \ + } else if ( p ~ /^\[[xX]\].*/ ) { return "
  • " \ substr(p, 4) "
  • \n" _list( block, last ); - } else if ( p ~ /^

    \[ \].*/ ) { return "

  • " \ + } else if ( p ~ /^

    \[ \].*/ ) { return "

  • " \ substr(p, 7) "

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

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

  • " \ + } else if ( p ~ /^

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

  • " \ substr(p, 7) "

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

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

  • " \ + } else if ( p ~ /^

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

  • " \ substr(p, 7) "

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

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

  • " \ + } else if ( p ~ /^

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

  • " \ substr(p, 7) "

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

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

  • " \ + } else if ( p ~ /^

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

  • " \ substr(p, 7) "

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