]> git.plutz.net Git - shellwiki/commitdiff
remodeling macro engine: do not depend on cgilite/markdown.awk to call macro functions
authorPaul Hänsch <paul@plutz.net>
Mon, 11 Sep 2023 13:42:37 +0000 (15:42 +0200)
committerPaul Hänsch <paul@plutz.net>
Mon, 11 Sep 2023 13:42:37 +0000 (15:42 +0200)
macros/toc
parsers/50_markdown.sh
parsers/60_macros.awk [new file with mode: 0755]

index 801347a9546a142b53e32e0e7baca77615fdbcf4..5f89936d45e9c7acd03061ed0863c6ae3c4c0dc5 100755 (executable)
 
 . "$_EXEC/cgilite/cgilite.sh"
 
-unset MD_MACROS
-
-if [ "$(which awk)" ]; then
-  md() { awk -f "$_EXEC/cgilite/markdown.awk"; }
-elif [ "$(which busybox)" ]; then
-  md() { busybox awk -f "$_EXEC/cgilite/markdown.awk"; }
-else
-  md() { cat; }
-fi
-
 min="$1" max="$2"
 [ "$min" -ge 1 -a "$min" -le 6 ] || min=1
 [ "$max" -ge "$min" ] || max="$min"
 [ "$max" -le 6 ] || max=6
 
-md |sed -nE '
+sed -nE '
   1i<ul class="macro toc">
   s;^.*<section class="(h[1-6])( [^"]+)?" id="([^"]*)"><h['${min}-${max}']>(([^<]|<[^aA]|<[aA][^ ])+)(<a class="anchor" href="[^>]*"></a>)?</h[1-6]>$;<li class="toc \1"><a href="#\3">\4</a></li>;p
   $i</ul>
index 63d8f0e4ab1d7be0ec57aab5c799cad01b0cfe51..8a21616107f4f69ae6184d5c69c7af75407e33f2 100755 (executable)
 # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 if which awk >/dev/null; then
-  awk -f "$_EXEC/md_macros.awk" -f "$_EXEC/cgilite/markdown.awk"
-  # | sed -E 's;(<[^>]+ )href="((/[^"/]+|[^"/]+[^:/]|)/([^"/]+/)*)"([^>]*>);\1href="\2:'"${LANGUAGE}"'"\5;g'
+  awk -f "$_EXEC/cgilite/markdown.awk"
 elif which busybox >/dev/null; then
-  busybox awk -f "$_EXEC/md_macros.awk" -f "$_EXEC/cgilite/markdown.awk"
-  # | sed -E 's;(<[^>]+ )href="((/[^"/]+|[^"/]+[^:/]|)/([^"/]+/)*)"([^>]*>);\1href="\2:'"${LANGUAGE}"'"\5;g'
+  busybox awk -f "$_EXEC/cgilite/markdown.awk"
 else
   cat
 fi
diff --git a/parsers/60_macros.awk b/parsers/60_macros.awk
new file mode 100755 (executable)
index 0000000..b72110b
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/awk -f
+#!/opt/busybox/awk -f
+
+# Copyright 2022 - 2023 Paul Hänsch
+# 
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+# 
+# THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+function sh_escape(arg){
+  return "'" gensub(/'/, "'\"'\"'", "g", arg) "'";
+}
+
+function argsplit(line, args, LOCAL, c, n, ctx) {
+  ctx="space"; n=0;
+
+  while ( length(line) > 0 ) {
+    c = substr(line, 1, 1);
+    line = substr(line, 2);
+    if (ctx == "space" )
+           if (c ~ /[ \t]/) ctx = "space";
+      else if (c ~ /\\/) { n++; ctx = "escbare"; }
+      else if (c ~ /"/)  { n++; ctx = "dquot"; }
+      else if (c ~ /'/)  { n++; ctx = "squot"; }
+      else   { n++; args[n] = c; ctx = "bare"; }
+    else if (ctx == "bare")
+           if (c ~ /[ \t]/) ctx = "space";
+      else if (c ~ /\\/)  ctx = "escbare";
+      else if (c ~ /"/)   ctx = "dquot";
+      else if (c ~ /'/)   ctx = "squot";
+      else args[n] = args[n] c;
+    else if (ctx == "dquot")
+           if (c ~ /"/)  ctx = "bare";
+      else if (c ~ /\\/) ctx = "escdquot";
+      else args[n] = args[n] c;
+    else if (ctx == "squot")
+      if (c ~ /'/)  ctx = "bare";
+      else args[n] = args[n] c;
+    else if (ctx == "escbare") {
+      args[n] = args[n] c;
+      ctx = "bare";
+    }
+    else if (ctx == "escdquot") {
+      args[n] = args[n] c;
+      ctx = "dquot";
+    }
+  }
+} 
+
+function HTML ( text ) {
+  gsub( /&/,  "\\&amp;",  text );
+  gsub( /</,  "\\&lt;",   text );
+  gsub( />/,  "\\&gt;",   text );
+  gsub( /"/,  "\\&quot;", text );
+  gsub( /'/,  "\\&#x27;", text );
+  gsub( /\\/, "\\&#x5C;", text );
+  return text;
+}
+
+function macro(call, LOCAL, line, args) {
+  argsplit(call, args);
+  call="";
+
+  for (n = 1; n in args; n++) call = call sh_escape(args[n]) " ";
+
+  if (args[1] in MACROS) {
+    printf "%s", file | sh_escape(ENVIRON["MD_MACROS"]) "/" call;
+    close(sh_escape(ENVIRON["MD_MACROS"]) "/" call);
+  } else {
+    printf "%s", HTML("<<" call ">>");
+  }
+}
+
+function unhtml ( text ) {
+  gsub( /&lt;/, "<", text);
+  gsub( /&gt;/, ">", text);
+  gsub( /&quot;/, "\"", text);
+  gsub( /&#x27;/, "'", text);
+  gsub( /&#x5c;/, "\\", text);
+  gsub( /&amp;/, "\\&", text);
+  return text;
+}
+
+function findmacro(line, LOCAL, st, len, pre, post) {
+  if ( match(line, /<code class="macro">[^\n]*<\/code>/) ) {
+    match(line, /<code class="macro">/); pre = substr( line, 1, RSTART - 1 );
+    line = substr( line, RSTART + RLENGTH);
+    match( line, /<\/code>/); post = substr(line, RSTART + RLENGTH);
+    line = substr(line, 1, RSTART - 1);
+
+    printf "%s", pre; macro( unhtml(line) ); findmacro( post );
+  } else {
+    printf "%s", line;
+  }
+}
+
+BEGIN {
+  if (ENVIRON["MD_MACROS"]) {
+    AllowMacros = "true";
+    "cd " sh_escape(ENVIRON["MD_MACROS"]) "; printf '%s/' *" |getline macro_list;
+    split(macro_list, MACROS, "/");
+    for (n in MACROS) { MACROS[MACROS[n]] = ""; delete MACROS[n]; }
+    delete MACROS[""];
+
+    file = ""; while ( getline ) { file = file $0 "\n"; }
+    findmacro( file );
+  }
+}