Commit bd3e248c7e

Loris Cro <kappaloris@gmail.com>
2023-04-15 18:26:20
autodoc: add initial support for linking decls mentioned in markdown
this works both on doc comments and guides
1 parent aa765c1
Changed files (1)
lib
docs
lib/docs/main.js
@@ -2762,7 +2762,7 @@ const NAV_MODES = {
     if (container.src != null) {
       let docs = getAstNode(container.src).docs;
       if (docs != null) {
-        domTldDocs.innerHTML = markdown(docs);
+        domTldDocs.innerHTML = markdown(docs, container);
         domTldDocs.classList.remove("hidden");
       }
     }
@@ -2845,13 +2845,13 @@ const NAV_MODES = {
           docs = docs.trim();
           var short = shortDesc(docs);
           if (short != docs) {
-            short = markdown(short);
-            var long = markdown(docs);
+            short = markdown(short, container);
+            var long = markdown(docs, container); // TODO: this needs to be the file top lvl struct
             tdDesc.innerHTML =
               "<div class=\"expand\" ><span class=\"button\" onclick=\"toggleExpand(event)\"></span><div class=\"sum-less\">" + short + "</div>" + "<div class=\"sum-more\">" + long + "</div></details>";
           }
           else {
-            tdDesc.innerHTML = markdown(short);
+            tdDesc.innerHTML = markdown(short, container);
           }
         } else {
           tdDesc.innerHTML = "<p><i>No documentation provided.</i><p>";
@@ -3389,7 +3389,7 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
     return markdown(shortDesc(docs));
   }
 
-  function markdown(input) {
+  function markdown(input, contextType) {
     const raw_lines = input.split("\n"); // zig allows no '\r', so we don't need to split on CR
 
     const lines = [];
@@ -3474,7 +3474,7 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
     // Render HTML from markdown lines.
     // Look at each line and emit fitting HTML code
 
-    function markdownInlines(innerText) {
+    function markdownInlines(innerText, contextType) {
       // inline types:
       // **{INLINE}**       : <strong>
       // __{INLINE}__       : <u>
@@ -3521,6 +3521,10 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
       let codetag = "";
       let in_code = false;
 
+      // state used to link decl references
+      let quote_start = undefined;
+      let quote_start_html = undefined;
+
       for (let i = 0; i < innerText.length; i++) {
         if (parsing_code && in_code) {
           if (innerText.substr(i, codetag.length) == codetag) {
@@ -3537,6 +3541,16 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
             parsing_code = false;
             innerHTML += "</code>";
             codetag = "";
+
+            // find out if this is a decl that should be linked
+            const maybe_decl_path = innerText.substr(quote_start, i-quote_start);
+            const decl_hash = detectDeclPath(maybe_decl_path, contextType);
+            if (decl_hash) {
+              const anchor_opening_tag = "<a href='"+ decl_hash +"'>";
+              innerHTML = innerHTML.slice(0, quote_start_html) 
+                + anchor_opening_tag
+                + innerHTML.slice(quote_start_html) + "</a>";
+            }
           } else {
             currentRun += innerText[i];
           }
@@ -3546,6 +3560,8 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
         if (innerText[i] == "`") {
           flushRun();
           if (!parsing_code) {
+            quote_start = i + 1;
+            quote_start_html = innerHTML.length;
             innerHTML += "<code>";
           }
           parsing_code = true;
@@ -3600,6 +3616,44 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
       return innerHTML;
     }
 
+    function detectDeclPath(text, context) {
+      let result = "";
+      let separator = ":";
+      const components = text.split(".");
+      let curDeclOrType = undefined;
+      
+      if (context) {
+        curDeclOrType = findSubDecl(context, components[0]);
+        if (curDeclOrType) {
+          separator = '.';
+          result = location.hash + separator + components[0];
+        }
+      } 
+
+      if (!curDeclOrType) {
+        for (let i = 0; i < zigAnalysis.packages.length; i += 1){
+          const p = zigAnalysis.packages[i];
+          if (p.name == components[0]) {
+            curDeclOrType = getType(p.main);
+            result += "#A;" + components[0];
+            break;
+          }
+        }
+      }
+
+      if (!curDeclOrType) return null;
+      
+      for (let i = 1; i < components.length; i += 1) {
+        curDeclOrType = findSubDecl(curDeclOrType, components[i]);
+        if (!curDeclOrType) return null;
+        result += separator + components[i];
+        separator = '.';
+      }
+
+      return result;
+      
+    }
+
     function previousLineIs(type, line_no) {
       if (line_no > 0) {
         return lines[line_no - 1].type == type;
@@ -3647,7 +3701,7 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
             "<" +
             line.type +
             ">" +
-            markdownInlines(line.text) +
+            markdownInlines(line.text, contextType) +
             "</" +
             line.type +
             ">\n";
@@ -3662,7 +3716,7 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
             html += "<" + line.type + ">\n";
           }
 
-          html += "<li>" + markdownInlines(line.text) + "</li>\n";
+          html += "<li>" + markdownInlines(line.text, contextType) + "</li>\n";
 
           if (
             !nextLineIs(line.type, line_no) ||
@@ -3676,7 +3730,7 @@ function addDeclToSearchResults(decl, declIndex, pkgNames, item, list, stack) {
           if (!previousLineIs("p", line_no)) {
             html += "<p>\n";
           }
-          html += markdownInlines(line.text) + "\n";
+          html += markdownInlines(line.text, contextType) + "\n";
           if (!nextLineIs("p", line_no)) {
             html += "</p>\n";
           }