Commit 9237461b24

Andrew Kelley <andrew@ziglang.org>
2019-10-07 19:57:01
generated docs: logo and basic search proof of concept
1 parent 2ccb48d
Changed files (2)
lib
std
special
lib/std/special/docs/index.html
@@ -20,6 +20,7 @@
             font-size:1em;
             background-color:#F5F5F5;
             padding:1em;
+            overflow-x: auto;
         }
         #listNav {
             list-style-type: none;
@@ -45,6 +46,16 @@
             background-color: #4CAF50;
         }
 
+        #logo {
+            width: 5em;
+            float: left;
+            padding: 0 1em 0 0;
+        }
+
+        #search {
+            width: 90%;
+        }
+
         @media (prefers-color-scheme: dark) {
             body{
                 background-color: #111;
@@ -60,12 +71,16 @@
     </style>
   </head>
   <body>
+    <img alt="ZIG" id="logo" src="data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxNTAgMTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxnIGZpbGw9IiNmN2E0MWQiPjxwYXRoIGQ9Im0wIDEwdjgwaDE5bDYtMTAgMTItMTBoLTE3di00MGgxNXYtMjB6bTQwIDB2MjBoNjJ2LTIwem05MSAwLTYgMTAtMTIgMTBoMTd2NDBoLTE1djIwaDM1di04MHptLTgzIDYwdjIwaDYydi0yMHoiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwYXRoIGQ9Im0zNyA3MC0xOCAyMHYtMTV6Ii8+PHBhdGggZD0ibTExMyAzMCAxOC0yMHYxNXoiLz48cGF0aCBkPSJtOTYuOTggMTAuNjMgMzYuMjgtMTAuNC04MC4yOSA4OS4xNy0zNi4yOCAxMC40eiIvPjwvZz48L3N2Zz4K"></img>
+    <input type="search" id="search" autocomplete="off" spellcheck="false" placeholder="`s` to search, `?` to see more options">
     <p id="status">Loading...</p>
     <div id="sectNav" class="hidden"><ul id="listNav"></ul></div>
     <div id="fnProto" class="hidden">
       <pre id="fnProtoCode"></pre>
     </div>
     <div id="fnDocs" class="hidden"></div>
+    <div id="sectSearchResults" class="hidden"><ul id="listSearchResults"></ul></div>
+    <div id="sectSearchNoResults" class="hidden"><p>No search results.</p></div>
     <div id="sectPkgs" class="hidden">
         <h2>Packages</h2>
         <ul id="listPkgs">
lib/std/special/docs/main.js
@@ -11,6 +11,13 @@
     var domFnProto = document.getElementById("fnProto");
     var domFnProtoCode = document.getElementById("fnProtoCode");
     var domFnDocs = document.getElementById("fnDocs");
+    var domSearch = document.getElementById("search");
+    var domSectSearchResults = document.getElementById("sectSearchResults");
+    var domListSearchResults = document.getElementById("listSearchResults");
+    var domSectSearchNoResults = document.getElementById("sectSearchNoResults");
+
+    var searchTimer = null;
+    var escapeHtmlReplacements = { "&": "&amp;", '"': "&quot;", "<": "&lt;", ">": "&gt;" };
 
     var typeKindTypeId;
     var typeKindFnId;
@@ -31,10 +38,13 @@
         // these will be all types, except the last one may be a type or a decl
         declObjs: [],
     };
+    var curNavSearch = "";
 
     var rootIsStd = detectRootIsStd();
     var typeTypeId = findTypeTypeId();
+    domSearch.addEventListener('keydown', onSearchKeyDown, false);
     window.addEventListener('hashchange', onHashChange, false);
+    window.addEventListener('keydown', onWindowKeyDown, false);
     onHashChange();
 
     function renderTitle() {
@@ -58,10 +68,14 @@
         domSectPkgs.classList.add("hidden");
         domSectTypes.classList.add("hidden");
         domSectFns.classList.add("hidden");
-
+        domSectSearchResults.classList.add("hidden");
 
         renderTitle();
 
+        if (curNavSearch !== "") {
+            return renderSearch();
+        }
+
         var pkg = zigAnalysis.packages[zigAnalysis.rootPkg];
         curNav.pkgObjs = [pkg];
         for (var i = 0; i < curNav.pkgNames.length; i += 1) {
@@ -99,16 +113,16 @@
         renderPkgList(lastPkg);
 
         var lastDecl = curNav.declObjs[curNav.declObjs.length - 1];
-        if (lastDecl.pubDecls != null) {
-            return renderContainer(lastDecl);
-        } else if (lastDecl.type != null) {
+        if (lastDecl.type != null) {
             var typeObj = zigAnalysis.types[lastDecl.type];
             if (typeObj.kind === typeKindFnId) {
                 return renderFn(lastDecl);
             }
             throw new Error("docs for this decl which is not a container");
-        } else {
-            throw new Error("docs for this decl which is a type");
+        }
+        renderType(lastDecl);
+        if (lastDecl.pubDecls != null) {
+            renderContainer(lastDecl);
         }
     }
 
@@ -164,10 +178,6 @@
     function render404() {
         domStatus.textContent = "404 Not Found";
         domStatus.classList.remove("hidden");
-        domSectPkgs.classList.add("hidden");
-        domSectTypes.classList.add("hidden");
-        domSectFns.classList.add("hidden");
-        domFnProto.classList.add("hidden");
     }
 
     function renderPkgList(pkg) {
@@ -183,9 +193,7 @@
             return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
         });
 
-        if (list.length === 0) {
-            domSectPkgs.classList.add("hidden");
-        } else {
+        if (list.length !== 0) {
             resizeDomList(domListPkgs, list.length, '<li><a href="#"></a></li>');
             for (var i = 0; i < list.length; i += 1) {
                 var liDom = domListPkgs.children[i];
@@ -228,6 +236,11 @@
         }
     }
 
+    function renderType(typeObj) {
+        domFnDocs.innerText = zigAnalysis.typeKinds[typeObj.kind] + ": " + typeObj.name;
+        domFnDocs.classList.remove("hidden");
+    }
+
     function renderContainer(container) {
         var typesList = [];
         var fnsList = [];
@@ -251,9 +264,7 @@
             return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
         });
 
-        if (typesList.length === 0) {
-            domSectTypes.classList.add("hidden");
-        } else {
+        if (typesList.length !== 0) {
             resizeDomList(domListTypes, typesList.length, '<li><a href="#"></a></li>');
             for (var i = 0; i < typesList.length; i += 1) {
                 var liDom = domListTypes.children[i];
@@ -265,9 +276,7 @@
             domSectTypes.classList.remove("hidden");
         }
 
-        if (fnsList.length === 0) {
-            domSectFns.classList.add("hidden");
-        } else {
+        if (fnsList.length !== 0) {
             resizeDomList(domListFns, fnsList.length, '<li><a href="#"></a></li>');
             for (var i = 0; i < fnsList.length; i += 1) {
                 var liDom = domListFns.children[i];
@@ -332,8 +341,19 @@
             declNames: [],
             declObjs: [],
         };
+        curNavSearch = "";
+
         if (location.hash[0] === '#' && location.hash.length > 1) {
-            var parts = location.hash.substring(1).split(";");
+            var nonSearchAndSearchParts = location.hash.substring(1).split("?");
+            var nonSearchPart;
+            if (nonSearchAndSearchParts.length === 1) {
+                nonSearchPart = nonSearchAndSearchParts[0];
+            } else {
+                nonSearchPart = nonSearchAndSearchParts[0];
+                curNavSearch = nonSearchAndSearchParts[1];
+            }
+
+            var parts = nonSearchPart.split(";");
             curNav.pkgNames = parts[0].split(".");
             if (parts[1] != null) {
                 curNav.declNames = parts[1].split(".");
@@ -388,10 +408,93 @@
         return list;
     }
 
-    var escapeHtmlReplacements = { "&": "&amp;", '"': "&quot;", "<": "&lt;", ">": "&gt;" };
     function markdown(mdText) {
         return mdText.replace(/[&"<>]/g, function (m) {
             return escapeHtmlReplacements[m];
         });
     }
+
+    function onSearchKeyDown(ev) {
+        switch (ev.which) {
+            case 27:
+                domSearch.value = "";
+                domSearch.blur();
+                ev.preventDefault();
+                break;
+        }
+        ev.stopPropagation();
+        startAsyncSearch();
+    }
+
+    function onWindowKeyDown(ev) {
+        switch (ev.which) {
+            case 83:
+                domSearch.focus();
+                ev.preventDefault();
+                ev.stopPropagation();
+                startAsyncSearch();
+                break;
+        }
+    }
+
+    function clearAsyncSearch() {
+        if (searchTimer != null) clearTimeout(searchTimer);
+    }
+
+    function startAsyncSearch() {
+        clearAsyncSearch();
+        searchTimer = setTimeout(startSearch, 50);
+    }
+    function startSearch() {
+        var parts = location.hash.split("?");
+        var newPart2 = (domSearch.value === "") ? "" : ("?" + domSearch.value);
+        if (parts.length === 1) {
+            location.hash = location.hash + newPart2;
+        } else {
+            location.hash = parts[0] + newPart2;
+        }
+    }
+    function renderSearch() {
+        if (domSearch.value !== curNavSearch) {
+            domSearch.value = curNavSearch;
+        }
+
+        var matchedDecls = [];
+        var terms = curNavSearch.split(/[ \r\n\t]+/);
+        decl_loop: for (var declIndex = 0; declIndex < zigAnalysis.decls.length; declIndex += 1) {
+            var decl = zigAnalysis.decls[declIndex];
+            for (var termIndex = 0; termIndex < terms.length; termIndex += 1) {
+                var term = terms[termIndex];
+                if (decl.name.indexOf(term) >= 0) {
+                    continue;
+                }
+                var astNode = zigAnalysis.astNodes[decl.src]
+                if (astNode.docs != null && astNode.docs.indexOf(term) >= 0) {
+                    continue;
+                }
+                var file = zigAnalysis.files[astNode.file];
+                if (file.indexOf(term) >= 0) {
+                    continue;
+                }
+
+                continue decl_loop;
+            }
+
+            matchedDecls.push(decl);
+        }
+
+        if (matchedDecls.length !== 0) {
+            resizeDomList(domListSearchResults, matchedDecls.length, '<li></li>');
+
+            for (var i = 0; i < matchedDecls.length; i += 1) {
+                var liDom = domListSearchResults.children[i];
+                var decl = matchedDecls[i];
+                liDom.textContent = decl.name;
+            }
+
+            domSectSearchResults.classList.remove("hidden");
+        } else {
+            domSectSearchNoResults.classList.remove("hidden");
+        }
+    }
 })();