Skip to content
Browse files

javascript search option

  • Loading branch information
adamdruppe committed Mar 11, 2017
1 parent 89d7de6 commit 8b9f718eb1c2ca6ce697adc894cc042683978b93
Showing with 431 additions and 7 deletions.
  1. +5 −1
  2. +41 −2 doc2.d
  3. +2 −0 locate.d
  4. +26 −0 search-docs.html
  5. +351 −0 search-docs.js
  6. +6 −4 skeleton-default.html
@@ -9,10 +9,14 @@ so define some basic colors. You can choose from the three I set or create your

The rest of the css file is a monster, so you probably don't get to get far into it.

Once you are ready, run `./doc2 path/to/your/package` For example, `./doc2 ~/code/arsd`.
Once you are ready, run `./doc2 -i path/to/your/package` For example, `./doc2 ~/code/arsd`.
The generator will scan it automatically for .d files and generate output in a new `generated-docs`
folder it will create.

NOTE: the `-i` flag means "generate search index". It will create a full-text search index that can be loaded by `locate.d` or by javascript (the default skeleton includes a search form that will work with the JS search). The JS search kinda sucks but can be used offline (just open the file in your browser) or on a static site like github pages.

You may omit the -i if you choose, the file it generates can be quite large so you don't always want it, but then the search form won't work unless you build locate.d and configure your setup to serve it (currently not supported for third parties, but that is what I do on

Then open one of the resulting files in your browser and you should see the results.

Syntax is currently described here:
43 doc2.d
@@ -795,6 +795,7 @@ Document writeHtml(Decl decl, bool forReal = true) {
} else {
/+ commented pending removal
// this is for building the module nav when doing an incremental
// rebuild. It loads the index.xml made with the special option below.
static bool attemptedXmlLoad;
@@ -814,6 +815,7 @@ Document writeHtml(Decl decl, bool forReal = true) {
foreach(im; indexedModules)
if(im.packageName == tm.packageName)
navArray ~= im;

@@ -2515,7 +2517,31 @@ void main(string[] args) {
// we need the listing and the search index
File index;
int id;
index = File(buildPath(outputDirectory, "index.xml"), "wt");

static import std.file;

// write out the landing page for JS search,
// see the comment in the source of that html
// for more details
std.file.write(outputDirectory ~ "search-docs.html", import("search-docs.html"));

// the search index is a HTML page containing some script
// and the index XML. See the source of search-docs.js for more info.
index = File(buildPath(outputDirectory, "search-results.html"), "wt");

auto skeletonDocument = new Document();
skeletonDocument.parseUtf8(std.file.readText(skeletonFile), true, true);
auto skeletonText = skeletonDocument.toString();

auto idx = skeletonText.indexOf("</body>");
if(idx == -1) throw new Exception("skeleton missing body element");

// write out the skeleton...
index.writeln(skeletonText[0 .. idx]);

// and then the data container for the xml
index.writeln(`<script type="text/xml" id="search-index-container">`);


@@ -2527,6 +2553,8 @@ void main(string[] args) {

id = 0;

// also making the search index
foreach(decl; moduleDeclsGenerate) {
writeln("Generating search for ",;
@@ -2538,14 +2566,25 @@ void main(string[] args) {

foreach(term, arr; searchTerms) {
index.write("<term value=\""~term~"\">");
index.write("<term value=\""~xmlEntitiesEncode(term)~"\">");
foreach(item; arr) {
index.write("<result decl=\""~to!string(item.declId)~"\" score=\""~to!string(item.score)~"\" />");

// finish the container

// write the script that runs the search

// and close the skeleton

@@ -1,3 +1,5 @@
// FIXME: load the new search-results.html and pull out the xml from there

import ps = PorterStemmer;
import arsd.cgi;
import arsd.dom;
@@ -0,0 +1,26 @@
<!DOCTYPE html>
The purpose of this file is to be a lightweight landing page for standard
forms that will redirect to the JS searcher using a #!term thing.
Since the JS searcher is a heavyweight page (it includes the search index
inline so it doesn't have to XHR, which would break on file:// urls), we
want it to be cached. Normal ?query urls would bust the cache. I don't mind
busting the cache on this little file, but we really want to avoid that on
the big index file.
Hence, the redirect hack.
location.href = "search-results.html#!" +"?searchTerm=".length);
<p>The "offline" searcher requires Javascript.</p>
<p>To get search without JS, build the `locate.d` file (see the adrdox makefile) and use it as a CGI program on a regular web server, or build with -version=embedded_httpd to embed its own server and run that.</p>
<p>Then, configure the server to call that script instead of loading this file, or change your skeleton.html search form action to point to it.</p>

0 comments on commit 8b9f718

Please sign in to comment.
You can’t perform that action at this time.