From: Paul Hänsch Date: Wed, 7 Jul 2021 11:55:31 +0000 (+0200) Subject: HTML escaping, switchable HTML processing X-Git-Url: https://git.plutz.net/?p=cgilite;a=commitdiff_plain;h=cd49a5ce71b79c56477dc351607484b0718fa594 HTML escaping, switchable HTML processing --- diff --git a/markdown.awk b/markdown.awk index 9c548ec..785ece8 100755 --- a/markdown.awk +++ b/markdown.awk @@ -24,7 +24,7 @@ # - [x] Lists (ordered, unordered) # - [x] Code blocks (using indention) # - [x] Horizontal rules -# - [x] Verbatim HTML block (gfm) +# - [x] Verbatim HTML block (disabled by default) # # Basic Markdown - Inline elements: # --------------------------------- @@ -35,8 +35,10 @@ # - [x] Images / reference style images # - [x] # - [x] backslash escapes -# - [x] Verbatim HTML inline -# - [ ] HTML escaping +# - [x] Verbatim HTML inline (disabled by default) +# - [x] HTML escaping +# +# NOTE: Set the environment variable MD_HTML=true to enable verbatim HTML # # Extensions - Block elements: # ---------------------------- @@ -103,11 +105,6 @@ function inline( line, LOCAL, len, code, href, guard ) { } else if ( match(line, /^ \n/) ) { return "
\n" inline( substr(line, RLENGTH + 1) ); - # Verbatim inline HTML - } else if ( match( line, /^(|<\?([^\?]|\?[^>])*\?>|]*>|])*\]\]>|<\/[A-Za-z][A-Za-z0-9-]*[[:space:]]*>|<[A-Za-z][A-Za-z0-9-]*([[:space:]]+[A-Za-z_:][A-Za-z0-9_\.:-]*([[:space:]]*=[[:space:]]*([[:space:]"'=<>`]+|"[^"]*"|'[^']*'))?)*[[:space:]]*\/?>)/) ) { - len = RLENGTH; - return substr( line, 1, len) inline(substr(line, len + 1)); - # ``code spans`` } else if ( match( line, /^`+/) ) { len = RLENGTH @@ -229,6 +226,20 @@ function inline( line, LOCAL, len, code, href, guard ) { len = RLENGTH; return "" inline( substr( line, 2, len - 2 ) ) "" inline( substr( line, len + 1 ) ); + # Verbatim inline HTML + } else if ( AllowHTML && match( line, /^(|<\?([^\?]|\?[^>])*\?>|]*>|])*\]\]>|<\/[A-Za-z][A-Za-z0-9-]*[[:space:]]*>|<[A-Za-z][A-Za-z0-9-]*([[:space:]]+[A-Za-z_:][A-Za-z0-9_\.:-]*([[:space:]]*=[[:space:]]*([[:space:]"'=<>`]+|"[^"]*"|'[^']*'))?)*[[:space:]]*\/?>)/) ) { + len = RLENGTH; + return substr( line, 1, len) inline(substr(line, len + 1)); + + # Literal HTML entities + } else if ( match( line, /^&([a-zA-Z]{2,32}|#[0-9]{1,7}|#[xX][0-9a-fA-F]{1,6});/) ) { + len = RLENGTH; + return substr( line, 1, len ) inline(substr(line, len + 1)); + + # Escape lone HTML character + } else if ( match( line, /^[&<>"']/) ) { + return HTML(substr(line, 1, 1)) inline(substr(line, 2)); + # continue walk over string } else { return substr(line, 1, 1) inline( substr(line, 2) ); @@ -242,24 +253,24 @@ function _block( block, LOCAL, st, len, hlvl, htxt, guard, code, indent ) { return ""; # HTML #2 #3 #4 $5 - } else if ( match( block, /(^|\n) ? ? ?(|$)|<\?([^\?]|\?[^>])*(\?>|$)|]*(>|$)|])*(\]\]>|$))/) ) { + } else if ( AllowHTML && match( block, /(^|\n) ? ? ?(|$)|<\?([^\?]|\?[^>])*(\?>|$)|]*(>|$)|])*(\]\]>|$))/) ) { len = RLENGTH; st = RSTART; return _block(substr(block, 1, st - 1)) substr(block, st, len) _block(substr(block, st + len)); # HTML #6 - } else if ( match( tolower(block), /(^|\n) ? ? ?<\/?(address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[123456]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)([[:space:]\n>]|\/>)([^\n]|\n[ \t]*[^\n])*(\n[[:space:]]*\n|$)/) ) { + } else if ( AllowHTML && match( tolower(block), /(^|\n) ? ? ?<\/?(address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[123456]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)([[:space:]\n>]|\/>)([^\n]|\n[ \t]*[^\n])*(\n[[:space:]]*\n|$)/) ) { len = RLENGTH; st = RSTART; return _block(substr(block, 1, st - 1)) substr(block, st, len) _block(substr(block, st + len)); # HTML #1 - } else if ( match( tolower(block), /(^|\n) ? ? ?<(script|pre|style)([[:space:]\n>]).*(<\/script>|<\/pre>|<\/style>|$)/) ) { + } else if ( AllowHTML && match( tolower(block), /(^|\n) ? ? ?<(script|pre|style)([[:space:]\n>]).*(<\/script>|<\/pre>|<\/style>|$)/) ) { len = RLENGTH; st = RSTART; match( tolower(substr(block, st, len)), /(<\/script>|<\/pre>|<\/style>)/); len = RSTART + RLENGTH; return _block(substr(block, 1, st - 1)) substr(block, st, len) _block(substr(block, st + len)); # HTML #7 - } else if ( match( block, /^ ? ? ?(<\/[A-Za-z][A-Za-z0-9-]*[[:space:]]*>|<[A-Za-z][A-Za-z0-9-]*([[:space:]]+[A-Za-z_:][A-Za-z0-9_\.:-]*([[:space:]]*=[[:space:]]*([[:space:]"'=<>`]+|"[^"]*"|'[^']*'))?)*[[:space:]]*\/?>)([[:space:]]*\n)([^\n]|\n[ \t]*[^\n])*(\n[[:space:]]*\n|$)/) ) { + } else if ( AllowHTML && match( block, /^ ? ? ?(<\/[A-Za-z][A-Za-z0-9-]*[[:space:]]*>|<[A-Za-z][A-Za-z0-9-]*([[:space:]]+[A-Za-z_:][A-Za-z0-9_\.:-]*([[:space:]]*=[[:space:]]*([[:space:]"'=<>`]+|"[^"]*"|'[^']*'))?)*[[:space:]]*\/?>)([[:space:]]*\n)([^\n]|\n[ \t]*[^\n])*(\n[[:space:]]*\n|$)/) ) { len = RLENGTH; st = RSTART; return substr(block, st, len) _block(substr(block, st + len)); @@ -391,6 +402,7 @@ function _list( block, last, LOCAL, p) { BEGIN { # Global Vars file = ""; rl_href[""] = ""; rl_title[""] = ""; + if (ENVIRON["MD_HTML"] == "true") { AllowHTML = "true"; } # Buffering of full file ist necessary, e.g. to find reference links while (getline) { file = file $0 "\n"; }