]> git.plutz.net Git - cgilite/commitdiff
link and image syntax allowing whitespace URLs, repace use of non-posix gensub()
authorPaul Hänsch <paul@plutz.net>
Sun, 8 Oct 2023 23:34:14 +0000 (01:34 +0200)
committerPaul Hänsch <paul@plutz.net>
Sun, 8 Oct 2023 23:34:14 +0000 (01:34 +0200)
markdown.awk

index 7ec1280d34784d35377afd860d88b81f47df4906..75f182746bd29d9375c7af1b1e52c39737fb2a58 100755 (executable)
@@ -122,13 +122,6 @@ function URL ( text, sharp ) {
 }
 
 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 <em> (underline)
-  isu = "__([^_[:space:]]|[^_[:space:]]" nu "[^_[:space:]])__"                # inner <strong> (underline)
-  iea =    "\\*([^\\*[:space:]]|[^\\*[:space:]]" na "[^\\*[:space:]])\\*"     # inner <em> (asterisk)
-  isa = "\\*\\*([^\\*[:space:]]|[^\\*[:space:]]" na "[^\\*[:space:]])\\*\\*"  # inner <strong> (asterisk)
-
   if ( line ~ /^$/ ) {  # Recursion End
     return "";
 
@@ -185,20 +178,22 @@ function inline( line, LOCAL, len, text, code, href, guard ) {
     return substr( line, 1, len) inline(substr(line, len + 1));
 
   # inline links
-  #                                 ,_______________________Image____________________________,
-  } else if ( match(line, /^\[([^]]+|!\[[^]]*\]\([^"\)]+([ \t]+"[^"]+")?\)(\{[a-zA-Z \t-]*\})?)\]\(([^"\)]+)([[:space:]]+"([^"]+)")?\)/) ) {
+  } else if ( match(line, "^" lii "\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)") ) {
     len = RLENGTH;
-    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 "<a href=\"" URL(href) "\" title=\"" HTML(title) "\">" inline( text ) "</a>" inline( substr( line, len + 1) );
-    } else {
-      return "<a href=\"" URL(href) "\">" inline( text ) "</a>" inline( substr( line, len + 1) );
-    }
+    text = href = title = substr( line, 1, len);
+    sub("^\\[", "", text); sub("\\]\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)$", "", text);
+    sub("^" lii "\\([\\n\\t ]*", "", href); sub("([\\n\\t ]+" lit ")?[\\n\\t ]*\\)$", "", href);
+    sub("^" lii "\\([\\n\\t ]*" lid, "", title); sub("[\\n\\t ]*\\)$", "", title); sub("^[\\n\\t ]+", "", title);
+
+    if ( match(href, /^<.*>$/) ) { sub(/^</, "", href); sub(/>$/, "", href); }
+         if ( match(title, /^".*"$/) ) { sub(/^"/, "", title); sub(/"$/, "", title); }
+    else if ( match(title, /^'.*'$/) ) { sub(/^'/, "", title); sub(/'$/, "", title); }
+    else if ( match(title, /^\(.*\)$/) ) { sub(/^\(/, "", title); sub(/\)$/, "", title); }
+
+    gsub(/\\/, "", href); gsub(/\\/, "", title); gsub(/[\n\t]+/, " ", title);
+
+    return "<a href=\"" URL(href) "\"" (title?" title=\"" HTML(title) "\"":"") ">" \
+           inline( text ) "</a>" inline( substr( line, len + 1) );
 
   # reference style links
   } else if ( match(line, /^\[([^]]+)\] ?\[([^]]*)\]/ ) ) {
@@ -215,25 +210,32 @@ function inline( line, LOCAL, len, text, code, href, guard ) {
     }
 
   # inline images
-  } 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) );
-    if ( title && attrib ) {
-      return "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\" title=\"" HTML(title) "\" class=\"" HTML(attrib) "\">" \
-             inline( substr( line, len + 1) );
-    } else if ( title ) {
-      return "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\" title=\"" HTML(title) "\">" \
-             inline( substr( line, len + 1) );
-    } else if ( attrib ) {
-      return "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\" class=\"" HTML(attrib) "\">" \
-             inline( substr( line, len + 1) );
-    } else {
-      return "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\">" \
-             inline( substr( line, len + 1) );
-    }
+  } else if ( match(line, "^!" lix "\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?") ) {
+    len = RLENGTH; text = href = title = attrib = substr( line, 1, len);
+
+    sub("^!\\[", "", text);
+    sub("\\]\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?$", "", text);
+
+    sub("^!" lix "\\([\\n\\t ]*", "", href);
+    sub("([\\n\\t ]+" lit ")?[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?$", "", href);
+
+    sub("^!" lix "\\([\\n\\t ]*" lid, "", title);
+    sub("[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?$", "", title);
+    sub("^[\\n\\t ]+", "", title);
+
+    sub("^!" lix "\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)", "", attrib);
+    sub(/^\{[ \t]*/, "", attrib); sub(/[ \t]*\}$/, "", attrib); gsub(/[ \t]+/, " ", attrib);
+
+    if ( match(href, /^<.*>$/) ) { sub(/^</, "", href); sub(/>$/, "", href); }
+         if ( match(title, /^".*"$/) ) { sub(/^"/, "", title); sub(/"$/, "", title); }
+    else if ( match(title, /^'.*'$/) ) { sub(/^'/, "", title); sub(/'$/, "", title); }
+    else if ( match(title, /^\(.*\)$/) ) { sub(/^\(/, "", title); sub(/\)$/, "", title); }
+
+    gsub(/\\/, "", href); gsub(/\\/, "", title); gsub(/[\n\t]+/, " ", title);
+
+    return "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\"" \
+           (title?" title=\"" HTML(title) "\"":"") (attrib?" class=\"" HTML(attrib) "\"":"") \
+           ">" inline( substr( line, len + 1) );
 
   # reference style images
   } else if ( match(line, /^!\[([^]]*)\] ?\[([^]]*)\]/ ) ) {
@@ -636,35 +638,36 @@ function _block( block, LOCAL, st, len, text, title, attrib, href, guard, code,
     return headline( n, text, 0 ) _block( substr( block, len + 1) );
 
   # block images (wrapped in <figure>)
-  } 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 "<figure data-src=\"" URL(href, 1) "\" class=\"" HTML(attrib) "\">" \
-               "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\" class=\"" HTML(attrib) "\">" \
-               "<figcaption>" inline(title) "</figcaption>" \
-             "</figure>\n\n" \
-             _block( substr( block, len + 1) );
-    } else if ( title ) {
-      return "<figure data-src=\"" URL(href, 1) "\">" \
-               "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\">" \
-               "<figcaption>" inline(title) "</figcaption>" \
-             "</figure>\n\n" \
-             _block( substr( block, len + 1) );
-    } else if ( attrib ) {
-      return "<figure data-src=\"" URL(href, 1) "\" class=\"" HTML(attrib) "\">" \
-               "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\" class=\"" HTML(attrib) "\">" \
-             "</figure>\n\n" \
-             _block( substr( block, len + 1) );
-    } else {
-      return "<figure data-src=\"" URL(href, 1) "\">" \
-               "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\">" \
-             "</figure>\n\n" \
-             _block( substr( block, len + 1) );
-    }
+  } else if ( match(block, "^!" lix "\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?(\\n|$)") ) {
+    len = RLENGTH; text = href = title = attrib = substr( block, 1, len);
+
+    sub("^!\\[", "", text);
+    sub("\\]\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?(\\n.*)?$", "", text);
+
+    sub("^!" lix "\\([\\n\\t ]*", "", href);
+    sub("([\\n\\t ]+" lit ")?[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?(\\n.*)?$", "", href);
+
+    sub("^!" lix "\\([\\n\\t ]*" lid, "", title);
+    sub("[\\n\\t ]*\\)(\\{[a-zA-Z \\t-]*\\})?(\\n.*)?$", "", title);
+    sub("^[\\n\\t ]+", "", title);
+
+    sub("^!" lix "\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\)", "", attrib);
+    sub("(\\n.*)?$", "", attrib);
+    sub(/^\{[ \t]*/, "", attrib); sub(/[ \t]*\}$/, "", attrib); gsub(/[ \t]+/, " ", attrib);
+
+    if ( match(href, /^<.*>$/) ) { sub(/^</, "", href); sub(/>$/, "", href); }
+         if ( match(title, /^".*"$/) ) { sub(/^"/, "", title); sub(/"$/, "", title); }
+    else if ( match(title, /^'.*'$/) ) { sub(/^'/, "", title); sub(/'$/, "", title); }
+    else if ( match(title, /^\(.*\)$/) ) { sub(/^\(/, "", title); sub(/\)$/, "", title); }
+
+    gsub(/\\/, "", href);
+
+    return "<figure data-src=\"" URL(href, 1) "\"" (attrib?" class=\"" HTML(attrib) "\"":"") ">" \
+           "<img src=\"" URL(href, 1) "\" alt=\"" HTML(text) "\"" \
+           (attrib?" class=\"" HTML(attrib) "\"":"") ">" \
+           (title?"<figcaption>" inline(title) "</figcaption>":"") \
+           "</figure>\n\n" \
+           _block( substr( block, len + 1) );
 
   # reference style images (block)
   } else if ( match(line, /^!\[([^]]*)\] ?\[([^]]*)\](\n|$)/ ) ) {
@@ -822,6 +825,20 @@ BEGIN {
   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";
 
+  # Universal Patterns
+  nu = "(\\\\\\\\|\\\\[^\\\\]|[^\\\\_]|_[[:alnum:]])*"    # not underline (except when escaped)
+  na = "(\\\\\\\\|\\\\[^\\\\]|[^\\\\\\*])*"  # not asterisk (except when escaped)
+  ieu =  "_([^_[:space:]]|[^_[:space:]]" nu "[^_[:space:]])_"                 # inner <em> (underline)
+  isu = "__([^_[:space:]]|[^_[:space:]]" nu "[^_[:space:]])__"                # inner <strong> (underline)
+  iea =    "\\*([^\\*[:space:]]|[^\\*[:space:]]" na "[^\\*[:space:]])\\*"     # inner <em> (asterisk)
+  isa = "\\*\\*([^\\*[:space:]]|[^\\*[:space:]]" na "[^\\*[:space:]])\\*\\*"  # inner <strong> (asterisk)
+
+  lix="\\[(\\\\[^\\n]|[^]\\n\\\\[])*\\]"  # link text
+  lid="(<(\\\\[^\\n]|[^\\n<>\\\\])*>|([^<\\n\\t ()\\\\]|\\\\[^\\n])(\\\\[\\n]|[^\\n\\t ()\\\\])*)"  # link dest
+  lit="(\"(\\\\.|[^\"\\\\])*\"|'(\\\\.|[^'\\\\])*'|\\((\\\\.|[^()\\\\])*\\))"  # link text
+  # link text with image def
+  lii="\\[(\\\\[^\\n]|[^]\\n\\\\[])*(!" lix "\\([\\n\\t ]*" lid "([\\n\\t ]+" lit ")?[\\n\\t ]*\\))?(\\\\[^\\n]|[^]\\n\\\\[])*\\]"
+
   # Buffering of full file ist necessary, e.g. to find reference links
   while (getline) { file = file $0 "\n"; }
   # Clean up MS-DOS line breaks