From 5d3ea7da26766c89b42c54cbd3a6289489053d2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pontus=20=C3=96stlund?= <ponost@roxen.com>
Date: Mon, 14 Nov 2016 08:59:26 +0100
Subject: [PATCH] Major redesign of the refdoc. Also removed some obsolete
 stuff.

---
 .../Standalone.pmod/autodoc_to_html.pike      |  577 ++++---
 .../autodoc_to_split_html.pike                | 1366 ++++++++---------
 .../Standalone.pmod/pike_to_html.pike         |  324 ++++
 refdoc/Makefile                               |   71 +-
 refdoc/chapters/autodoc.xml                   |  290 ++--
 refdoc/chapters/compatibility.xml             |    2 +-
 refdoc/chapters/hilfe.xml                     |    8 +-
 refdoc/keywords.txt                           |   46 +-
 refdoc/presentation/make_html.pike            |    5 +
 refdoc/presentation/tree-split-autodoc.pike   |    5 +
 refdoc/src_images/eye-slash.svg               |    1 +
 refdoc/src_images/pike-logo-blue.svg          |    1 +
 refdoc/src_images/pike-logo-white.svg         |    1 +
 refdoc/src_images/pike-logo.png               |  Bin 0 -> 4711 bytes
 refdoc/src_images/pike-logo.svg               |    1 +
 refdoc/structure/caudium_modref.html          |   31 -
 refdoc/structure/chapters.html                |   12 +
 refdoc/structure/modref.css                   |  647 +++++++-
 refdoc/structure/modref.html                  |   94 +-
 refdoc/structure/modref.js                    |  641 ++++++++
 refdoc/structure/module_modref.html           |   63 -
 refdoc/structure/pelix_modref.html            |  112 --
 22 files changed, 2847 insertions(+), 1451 deletions(-)
 create mode 100644 lib/modules/Tools.pmod/Standalone.pmod/pike_to_html.pike
 create mode 100644 refdoc/src_images/eye-slash.svg
 create mode 100644 refdoc/src_images/pike-logo-blue.svg
 create mode 100644 refdoc/src_images/pike-logo-white.svg
 create mode 100644 refdoc/src_images/pike-logo.png
 create mode 100644 refdoc/src_images/pike-logo.svg
 delete mode 100644 refdoc/structure/caudium_modref.html
 create mode 100644 refdoc/structure/chapters.html
 create mode 100644 refdoc/structure/modref.js
 delete mode 100644 refdoc/structure/module_modref.html
 delete mode 100644 refdoc/structure/pelix_modref.html

diff --git a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike
index 5e5431b158..c08c5c8b1d 100644
--- a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike
+++ b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike
@@ -17,40 +17,41 @@ Tools.AutoDoc.Flags flags = Tools.AutoDoc.FLAG_NORMAL;
 
 int verbosity = Tools.AutoDoc.FLAG_VERBOSE; //NORMAL;
 
-function resolve_reference; 
+function resolve_reference;
 string image_path = "images/";
 string dest_path;
 string default_ns;
 
 //! Layout template headers and trailers.
 mapping lay = ([
- "docgroup" : "\n\n<hr clear='all' size='1' noshadow='noshadow' />\n<dl>",
+
+ "docgroup" : "\n\n<hr />\n<dl class='group--doc'>",
  "_docgroup" : "</dl>\n",
  "ndochead" : "<dd><p>",
  "_ndochead" : "</p></dd>\n",
 
- "dochead" : "\n<dt style='font-family: sans-serif'>",
+ "dochead" : "\n<dt class='head--doc'>",
  "_dochead" : "</dt>\n",
- "typehead" : "\n<dt style='font-family: sans-serif'>",
+ "typehead" : "\n<dt class='head--type'>",
  "_typehead" : "</dt>\n",
- "docbody" : "<dd style='font-family: sans-serif'>",
+ "docbody" : "<dd class='body--doc'>",
  "_docbody" : "</dd>",
- "fixmehead" : "<dt style='font-family: sans-serif; color: red'>",
+ "fixmehead" : "<dt class='head--fixme'>",
  "_fixmehead" : "</dt>\n",
- "fixmebody" : "<dd style='font-family: sans-serif; color: red'>",
+ "fixmebody" : "<dd class='body--fixme'>",
  "_fixmebody" : "</dd>",
 
- "parameter" : "<tt><font color='#8000F0'>",
- "_parameter" : "</font></tt>",
- "example" : "<dd><pre>",
+ "parameter" : "<code class='parameter'>",
+ "_parameter" : "</code>",
+ "example" : "<dd class='example'><pre>",
  "_example" : "</pre></dd>",
 
- "pre" : "<font face='courier'><pre>",
- "_pre" : "</pre></font>",
- "code" : "<font face='courier'><pre><code>",
- "_code" : "</code></pre></font>",
- "expr" : "<font face='courier'><code>",
- "_expr" : "</code></font>",
+ "pre" : "<pre>",
+ "_pre" : "</pre>",
+ "code" : "<pre><code>",
+ "_code" : "</code></pre>",
+ "expr" : "<code class='expr'>",
+ "_expr" : "</code>",
 
 ]);
 
@@ -58,7 +59,7 @@ mapping lay = ([
 string image_prefix()
 {
   return image_path;
-} 
+}
 
 class Position {
   string file;
@@ -124,7 +125,8 @@ string low_parse_chapter(Node n, int chapter) {
       break;
 
     case "example":
-      ret += "<p><pre>" + quote(c->value_of_node()) + "</pre></p>\n";
+      ret += "<p></p><pre>" + quote(c->value_of_node()) +
+             "</pre><p></p>\n";
       break;
 
     case "ul":
@@ -154,13 +156,11 @@ string low_parse_chapter(Node n, int chapter) {
 	error("Section inside subsection.\n");
       section = (int)c->get_attributes()->number;
       ret += "</dd>\n<dt><a name='" + section + "'></a>\n"
-	"<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-	"<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; " + chapter + "." + section +
+	"<h2 class='header'>" + chapter + "." + section +
 	". " + quote(c->get_attributes()->title ||
 		     // The following for bug compat.
 		     c->get_attributes()->name) +
-	"</font></td></tr></table><br />\n"
-	"</dt>\n<dd>";
+	"</h2></dt>\n<dd>";
       ret += low_parse_chapter(c, chapter);
       section = 0;
       break;
@@ -172,11 +172,9 @@ string low_parse_chapter(Node n, int chapter) {
 	error("Subsection inside subsection.\n");
       subsection = (int)c->get_attributes()->number;
       ret += "</dd><dt>"
-	"<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-	"<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; " + chapter + "." + section + "." + subsection +
+	"<h3 class='header'>" + chapter + "." + section + "." + subsection +
 	". " + quote(c->get_attributes()->title) +
-	"</font></td></tr></table><br />\n"
-	"</dt><dd>";
+	"</h3></dt><dd>";
       ret += low_parse_chapter(c, chapter);
       subsection = 0;
       break;
@@ -218,19 +216,18 @@ string parse_chapter(Node n, void|int noheader) {
   string ret = "";
   if(!noheader) {
     ret += "<dl><dt>"
-      "<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-      "<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; ";
+      "<h1 class='header'>";
     if(n->get_attributes()->number)
       ret += n->get_attributes()->number + ". ";
     ret += quote(n->get_attributes()->title) +
-      "</font></td></tr></table><br />\n"
+      "</h1>"
       "</dt><dd>";
   }
 
   ret += low_parse_chapter(n, (int)n->get_attributes()->number);
 
   if(!noheader)
-    ret = ret + "</dd></dl>"; 
+    ret = ret + "</dd></dl>";
 
   return ret;
 }
@@ -239,10 +236,9 @@ string parse_appendix(Node n, void|int noheader) {
   string ret ="";
   if(!noheader)
     ret += "<dl><dt>"
-      "<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-      "<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; Appendix " +
+      "<h2 class='header'>Appendix " +
       (string)({ 64+(int)n->get_attributes()->number }) + ". " +
-      n->get_attributes()->name + "</font></td></tr></table><br />\n"
+      n->get_attributes()->name + "</h2>\n"
       "</dt><dd>";
 
   Node c = n->get_first_element("doc");
@@ -257,7 +253,7 @@ string parse_appendix(Node n, void|int noheader) {
 #endif
 
   if(!noheader)
-    ret = ret + "</dd></dl>"; 
+    ret = ret + "</dd></dl>";
 
   return ret;
 }
@@ -292,14 +288,13 @@ string parse_namespace(Node n, void|int noheader)
   int(0..1) header = !noheader && !(m->hidden) && m->name!=default_ns;
   if(header)
     ret += "<dl><dt>"
-      "<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-      "<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; Namespace <b>" +
-      m->name + "::</b></font></td></tr></table><br />\n"
+      "<h2 class='header'>Namespace <b class='ms datatype'>" +
+      m->name + "::</b></h2>\n"
       "</dt><dd>";
 
   Node c = n->get_first_element("doc");
   if(c)
-    ret += "<dl>" + parse_doc(c) + "</dl>";
+    ret += "<dl class='group--doc'>" + parse_doc(c) + "</dl>";
 
   if((sizeof(n->get_elements("doc"))>1) &&
      ((flags & (Tools.AutoDoc.FLAG_KEEP_GOING|Tools.AutoDoc.FLAG_DEBUG)) ==
@@ -313,7 +308,7 @@ string parse_namespace(Node n, void|int noheader)
   ret += parse_children(n, "module", parse_module, noheader);
 
   if(header)
-    ret += "</dd></dl>"; 
+    ret += "</dd></dl>";
 
   return ret;
 }
@@ -325,14 +320,13 @@ string parse_module(Node n, void|int noheader) {
   int(0..1) header = !noheader && !(m->hidden);
   if(header)
     ret += "<dl><dt>"
-      "<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-      "<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; Module <b>" +
-      m->class_path + m->name + "</b></font></td></tr></table><br />\n"
+      "<h2 class='header'>Module <b class='ms datatype'>" +
+      m->class_path + m->name + "</b></h2>\n"
       "</dt><dd>";
 
   Node c = n->get_first_element("doc");
   if(c)
-    ret += "<dl>" + parse_doc(c) + "</dl>";
+    ret += "<dl class='group--doc'>" + parse_doc(c) + "</dl>";
 
   if((sizeof(n->get_elements("doc"))>1) &&
      ((flags & (Tools.AutoDoc.FLAG_KEEP_GOING|Tools.AutoDoc.FLAG_DEBUG)) ==
@@ -356,17 +350,16 @@ string parse_class(Node n, void|int noheader) {
   string ret ="";
   if(!noheader)
     ret += "<dl><dt>"
-      "<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-      "<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; CLASS <b><font color='#005080'>" +
+      "<h2 class='header'>Class <b class='ms datatype'>" +
       n->get_attributes()->class_path + n->get_attributes()->name +
-      "</font></b></font></td></tr></table><br />\n"
+      "</b></h2>\n"
       "</dt><dd>";
 
   Node c = n->get_first_element("doc");
   old_class_name->push(class_name);
   class_name = n->get_attributes()->class_path+n->get_attributes()->name;
   if(c)
-    ret += "<dl>" + parse_doc(c) + "</dl>";
+    ret += "<dl class='group--doc'>" + parse_doc(c) + "</dl>";
 
   if((sizeof(n->get_elements("doc"))>1) &&
      ((flags & (Tools.AutoDoc.FLAG_KEEP_GOING|Tools.AutoDoc.FLAG_DEBUG)) ==
@@ -375,7 +368,7 @@ string parse_class(Node n, void|int noheader) {
   }
 
   ret += parse_children(n, "docgroup", parse_docgroup);
-  ret += parse_children(n, "enum", parse_enum);
+  ret += parse_children(n, "enum", parse_enum, noheader);
   ret += parse_children(n, "class", parse_class, noheader);
   ret += parse_children(n, "module", parse_module, noheader);
 
@@ -387,18 +380,18 @@ string parse_class(Node n, void|int noheader) {
 
 string parse_enum(Node n, void|int noheader) {
   string ret ="";
-  if(!noheader)
+  if(!noheader) {
     ret += "<dl><dt>"
-      "<table width='100%' cellpadding='3' cellspacing='0' border='0'><tr>"
-      "<td bgcolor='#EEEEEE'><font size='+3'>&nbsp; ENUM <b><font color='#005080'>" +
+      "<h2 class='header'>Enum <b class='ms datatype'>" +
       n->get_attributes()->class_path + n->get_attributes()->name +
-      "</font></b></font></td></tr></table><br />\n"
+      "</b></h2>\n"
       "</dt><dd>";
+  }
 
   Node c = n->get_first_element("doc");
 
   if(c)
-    ret += "<dl>" + parse_doc(c) + "</dl>";
+    ret += "<dl class='group--doc'>" + parse_doc(c) + "</dl>";
 
   if((sizeof(n->get_elements("doc"))>1) &&
      ((flags & (Tools.AutoDoc.FLAG_KEEP_GOING|Tools.AutoDoc.FLAG_DEBUG)) ==
@@ -414,61 +407,70 @@ string parse_enum(Node n, void|int noheader) {
 }
 
 string layout_matrix( array(array(string)) rows ) {
-  string ret = "<table bgcolor='black' border='0' cellspacing='0' cellpadding='0'><tr><td>\n"
-    "<table cellspacing='1' cellpadding='3' border='0' bgcolor='black'>\n";
+
+  string ret =
+    "<table class='box'>\n";
+
 
   int dim;
   foreach(rows, array row)
     dim = max(dim, sizeof(row));
 
   foreach(rows, array row) {
-    ret += "<tr valign='top'>";
+    ret += "<tr>";
     if(sizeof(row)<dim)
-      ret += "<td bgcolor='white'>" + row[..sizeof(row)-2]*"</td><td bgcolor='white'>" +
-	"</td><td bgcolor='white' colspan='"+ (dim-sizeof(row)) + "'>" + row[-1] + "</td>";
+      ret += "<td>" + row[..sizeof(row)-2]*"</td><td>" +
+	"</td><td colspan='"+ (dim-sizeof(row)) + "'>" + row[-1] + "</td>";
     else
-      ret += "<td bgcolor='white'>" + row*"</td><td bgcolor='white'>" + "</td>";
+      ret += "<td>" + row*"</td><td>" + "</td>";
     ret += "</tr>\n";
   }
 
-  return ret + "</table></td></tr></table><br />\n";
+  return ret + "</table>\n";
 }
 
 // ({  ({ array(string)+, void|string  })* })
 void nicebox(array rows, String.Buffer ret) {
-  ret->add( "<table bgcolor='black' border='0' cellspacing='0' cellpadding='0'><tr><td>\n"
-	    "<table cellspacing='1' cellpadding='3' border='0' bgcolor='black'>\n" );
+  ret->add("<table class='box'>");
 
   int dim;
-  foreach(rows, array row)
+  foreach (rows, array row) {
     dim = max(dim, sizeof(row));
+  }
 
-  foreach(rows, array row) {
-    if(sizeof(row)==1) {
-      if(stringp(row[0]))
-	ret->add( "<tr valign='top'><td bgcolor='white' colspan='", (string)dim, "'>",
-		  row[0], "</td></tr>\n" );
-      else
-	foreach(row[0], string elem)
-	  ret->add( "<tr valign='top'><td bgcolor='white'><tt>", elem, "</tt></td>",
-		    (dim==2?"<td bgcolor='white'>&nbsp;</td>":""), "</tr>\n" );
+  foreach (rows, array row) {
+    if (sizeof(row) == 1) {
+      if (stringp(row[0])) {
+        ret->add("<tr><td colspan='", (string)dim, "'>", row[0], "</td></tr>\n");
+      }
+      else {
+        foreach (row[0], string elem) {
+          ret->add("<tr><td><code>", elem, "</code></td>",
+                   (dim == 2 ? "<td>&nbsp;</td>" : ""), "</tr>\n");
+        }
+      }
+    }
+    else if (sizeof(row[0]) == 1) {
+      ret->add("<tr><td><code>", row[0][0], "</code></td>",
+               "<td>", row[1], "</td></tr>\n");
     }
-    else if(sizeof(row[0])==1)
-      ret->add( "<tr valign='top'><td bgcolor='white'><tt>", row[0][0],
-		"</tt></td><td bgcolor='white'>", row[1], "</td></tr>\n" );
     else {
-      ret->add( "<tr valign='top'><td bgcolor='white'><tt>", row[0][0],
-		"</tt></td><td bgcolor='white' rowspan='", (string)sizeof(row[0]), "'>",
-		row[1], "</td></tr>\n" );
-      foreach(row[0][1..], string elem)
-	ret->add( "<tr valign='top'><td bgcolor='white'><tt>", elem, "</tt></td></tr>\n" );
+      ret->add("<tr><td><code>", row[0][0], "</code></td>",
+               "<td rowspan='", (string)sizeof(row[0]), "'>",
+               row[1], "</td></tr>\n");
+      foreach (row[0][1..], string elem) {
+        ret->add("<tr><td><code>", elem, "</code></td></tr>\n");
+      }
     }
   }
 
-  ret->add( "</table></td></tr></table><br />\n" );
+  ret->add("</table>");
 }
 
 void build_box(Node n, String.Buffer ret, string first, string second, function layout, void|string header) {
+
+        //werror("build_box: %O\n", n);
+
   array rows = ({});
   if(header) rows += ({ ({ header }) });
   foreach(n->get_elements(first), Node d) {
@@ -508,13 +510,80 @@ string range_type( string type, Node min, Node max )
     return type+"("+low+".."+high+")";
 }
 
+Tools.Standalone.pike_to_html code_highlighter;
+
+// Normalizes indentation of @code ... @endcode blocks.
+// Also tries to syntax highlight code that looks like Pike.
+string parse_code(Node n, void|String.Buffer ret)
+{
+  string text;
+  if (n->get_tag_name() != "code") {
+    return parse_text(n, ret);
+  }
+
+  array(string) lines = n->get_children()[0]->get_children()->value_of_node();
+
+  if (!sizeof(lines)) {
+    return parse_text(n, ret);
+  }
+
+  if (sizeof(lines) && lines[-1] == "\n") {
+    lines[0..<1];
+  }
+
+  if (sizeof(lines) > 1) {
+    for (int i = 0; i < sizeof(lines); i++) {
+      string ln = map(lines[i]/"\n", lambda (string s) {
+        if (has_prefix(s, " "))
+          s = s[1..];
+        return s;
+      }) * "\n";
+
+      if (!has_suffix(ln, "\n"))
+        ln += "\n";
+
+      lines[i] = ln;
+    }
+
+    text = lines*"";
+  }
+  else {
+    text = lines*"";
+  }
+
+  if (sizeof(text) && text[-1] == '\n');
+    text = text[..<1];
+
+  while (text[-1] == '\n')
+    text = text[..<1];
+
+  if (has_value(text, "->") ||
+      (has_value(text, "{") && has_value(text, "}")) ||
+      (has_value(text, "(") && has_value(text, "\"")) ||
+      (has_value(text, ".") && has_value(text, "=")))
+  {
+    if (!code_highlighter) {
+      code_highlighter = Tools.Standalone.pike_to_html();
+    }
+
+    if (catch(text = code_highlighter->convert(text))) {
+      text = text;
+    }
+  }
+
+  if (ret) {
+    ret->add(text);
+  }
+  else return quote(text);
+}
+
 //! Typically called with a <group/> node or a sub-node that is a container.
 string parse_text(Node n, void|String.Buffer ret) {
   if(n->get_node_type()==XML_TEXT && n->get_text()) {
     if(ret)
-      ret->add(quote(n->get_text()));
+      ret->add("parse_text:#1:", quote(n->get_text()));
     else
-      return quote(n->get_text());
+      return quote("parse_text:#1:" + n->get_text());
   }
 
   int cast;
@@ -568,7 +637,7 @@ string parse_text(Node n, void|String.Buffer ret) {
 
     case "code":
       ret->add(lay->code);
-      parse_text(c, ret);
+      parse_code(c, ret);
       ret->add(lay->_code);
       break;
 
@@ -584,7 +653,7 @@ string parse_text(Node n, void|String.Buffer ret) {
       string ref;
       //ref = c->get_attributes()->resolved;
       if(!ref) ref = parse_text(c);
-      ret->add("<font face='courier'>", ref, "</font>");
+      ret->add("<code>", ref, "</code>");
       break;
 
     case "rfc":
@@ -612,7 +681,7 @@ string parse_text(Node n, void|String.Buffer ret) {
       break;
 
     case "dl":
-      ret->add("<dl>", map(c->get_elements("group"), parse_text)*"", "</dl>");
+      ret->add("<dl class='group--doc'>", map(c->get_elements("group"), parse_text)*"", "</dl>");
       break;
 
     case "item":
@@ -637,7 +706,7 @@ string parse_text(Node n, void|String.Buffer ret) {
 		  Node nn = n->get_first_element("index");
 		  if (nn) {
 		    res +=
-		      "<font color='green'>" + parse_text(nn) + "</font> : ";
+		      "<code class='key'>" + parse_text(nn) + "</code> : ";
 		  }
 		  nn = n->get_first_element("type");
 		  if (nn) {
@@ -661,23 +730,23 @@ string parse_text(Node n, void|String.Buffer ret) {
 		      index += parse_text(n->get_first_element("maxindex"));
 		  }
 		  return parse_type(get_first_element(n->get_first_element("type"))) +
-		    " <font color='green'>" + index + "</font>"; }, "Array" );
+		    " <code class='key'>" + index + "</code>"; }, "Array" );
       break;
 
     case "int":
       build_box(c, ret, "group", "value",
 		lambda(Node n) {
-           return "<font color='green'>" +
+           return "<code class='key'>" +
                range_type( parse_text(n),
                            n->get_first_element("minvalue"),
                            n->get_first_element("maxvalue"))+
-               "</font>";
+               "</code>";
 		} );
       break;
 
     case "mixed":
       if(c->get_attributes()->name)
-	ret->add("<tt>", c->get_attributes()->name, "</tt> can have any of the following types:<br />");
+	ret->add("<code>", c->get_attributes()->name, "</code> can have any of the following types:<br />");
       rows = ({});
       foreach(c->get_elements("group"), Node d)
 	rows += ({ ({
@@ -690,19 +759,19 @@ string parse_text(Node n, void|String.Buffer ret) {
     case "string": // Not in XSLT
       build_box(c, ret, "group", "value",
 		lambda(Node n) {
-            return "<font color='green'>" +
+            return "<code class='key'>" +
                 range_type( parse_text(n),
                             n->get_first_element("min"),
                             n->get_first_element("max")) +
-                "</font>";
+                "</code>";
 		} );
       break;
 
     case "multiset": // Not in XSLT
       build_box(c, ret, "group", "index",
 		lambda(Node n) {
-		  return "<font color='green'>" +
-		    parse_text(n->get_first_element("value")) + "</font>";
+		  return "<code class='key'>" +
+		    parse_text(n->get_first_element("value")) + "</code>";
 		} );
       break;
 
@@ -777,9 +846,9 @@ string parse_text(Node n, void|String.Buffer ret) {
       break;
 
     case "fixme":
-      ret->add("<font color='red'>FIXME: ");
+      ret->add("<span class='fixme'>FIXME: ");
       parse_text(c, ret);
-      ret->add("</font>");
+      ret->add("</span>");
       break;
 
     // Not really allowed
@@ -812,20 +881,24 @@ string parse_doc(Node n, void|int no_text) {
   string ret ="";
 
   Node c = n->get_first_element("text");
-  if(c)
+  if(c) {
     ret += lay->dochead + "Description" + lay->_dochead +
       lay->docbody + parse_text(c) + lay->_docbody;
+  }
+
+#define MAKE_ID(N) ("<span id='p-" + N + "'></span>")
 
   foreach(n->get_elements("group"), Node c) {
     Node header = c->get_first_element();
     string name = header->get_any_name();
     switch(name) {
     case "param":
-      foreach(c->get_elements("param"), Node d)
-	ret += lay->dochead + "Parameter " + lay->parameter +
-	  quote(d->get_attributes()->name || "") +
-	  lay->_parameter + lay->_dochead +
+      foreach(c->get_elements("param"), Node d) {
+        string name = quote(d->get_attributes()->name || "");
+	ret += lay->dochead + MAKE_ID(name) + "Parameter " +
+          lay->parameter + name + lay->_parameter + lay->_dochead +
 	  "<dd></dd>";
+      }
       if (c = c->get_first_element("text")) {
 	ret += lay->docbody + parse_text(c) + lay->_docbody;
       }
@@ -899,18 +972,19 @@ string parse_type(Node n, void|string debug) {
   case "object":
     if(n->count_children()) {
       if (resolve_reference) {
-	ret += "<font color='#005080'>" +
+	ret += "<code class='object resolved'>" +
 	  resolve_reference(n->value_of_node(), n->get_attributes()) +
-	  "</font>";
+	  "</code>";
       } else {
-	ret += "<font color='#005080'>" + n->value_of_node() + "</font>";
+	ret += "<code class='object unresolved'>" +
+               n->value_of_node() + "</code>";
       }
     } else
-      ret += "<font color='#202020'>object</font>";
+      ret += "<code class='datatype'>object</code>";
     break;
 
   case "type":
-    ret += "<font color='#202020'>type</font>";
+    ret += "<code class='type'>type</code>";
     if (n->count_children() && (c = get_first_element(n)) &&
 	(c->get_any_name() != "mixed")) {
       ret += "(" + parse_type(c) + ")";
@@ -918,19 +992,19 @@ string parse_type(Node n, void|string debug) {
     break;
 
   case "multiset":
-    ret += "<font color='#202020'>multiset</font>";
+    ret += "<code class='datatype'>multiset</code>";
     c = n->get_first_element("indextype");
     if(c) ret += "(" + parse_type( get_first_element(c) ) + ")";
     break;
 
   case "array":
-    ret += "<font color='#202020'>array</font>";
+    ret += "<code class='datatype'>array</code>";
     c = n->get_first_element("valuetype");
     if(c) ret += "(" + parse_type( get_first_element(c) ) + ")";
     break;
 
   case "mapping":
-    ret += "<font color='#202020'>mapping</font>";
+    ret += "<code class='datatype'>mapping</code>";
     c = n->get_first_element("indextype");
     d = n->get_first_element("valuetype");
     if(c && d)
@@ -943,7 +1017,7 @@ string parse_type(Node n, void|string debug) {
     break;
 
   case "function":
-    ret += "<font color='#202020'>function</font>";
+    ret += "<code class='datatype'>function</code>";
     array(Node) args = n->get_elements("argtype");
     d = n->get_first_element("returntype");
     // Doing different than the XSL here. Must both
@@ -953,7 +1027,7 @@ string parse_type(Node n, void|string debug) {
       if(args) ret += map(args->get_children() * ({}), parse_type)*", ";
       ret += ":";
       if(d) ret += parse_type( get_first_element(d) );
-      else ret += "<font color='#202020'>void</font>";
+      else ret += "<code class='datatype void'>void</code>";
       ret += ")";
     }
     break;
@@ -975,16 +1049,16 @@ string parse_type(Node n, void|string debug) {
 
   case "void": case "program": case "mixed": case "float":
   case "zero":
-    ret += "<font color='#202020'>" + n->get_any_name() + "</font>";
+    ret += "<code class='datatype'>" + n->get_any_name() + "</code>";
     break;
 
   case "string":
   case "int":
-      ret += ("<font color='#202020'>" +
+      ret += ("<code class='datatype'>" +
               range_type( n->get_any_name(),
                           n->get_first_element("min"),
                           n->get_first_element("max")) +
-              "</font>");
+              "</code>");
     break;
 
   case "attribute":
@@ -993,12 +1067,14 @@ string parse_type(Node n, void|string debug) {
       parse_type(n->get_first_element("subtype")->get_first_element());
     if (n->get_first_element("prefix")) {
       if (attr == "\"deprecated\"") {
-	ret += "<font color='#600000'>__deprecated__</font> " + subtype;
+	ret += "<code class='deprecated'>__deprecated__</code> " +
+               subtype;
       } else {
 	ret += sprintf("__attribute__(%s) %s", attr, subtype);
       }
     } else if (attr == "\"deprecated\"") {
-      ret += "<font color='#600000'>__deprecated__</font>(" + subtype + ")";
+      ret += "<code class='deprecated'>__deprecated__</code>(" +
+             subtype + ")";
     } else {
       ret += sprintf("__attribute__(%s, %s)", attr, subtype);
     }
@@ -1006,31 +1082,31 @@ string parse_type(Node n, void|string debug) {
 
     // Modifiers:
   case "extern": // Not in XSLT
-    ret += "extern ";
+    ret += "<code class='modifier'>extern</code> ";
     break;
   case "final": // Not in XSLT
   case "nomask": // Not in XSLT
-    ret += "final ";
+    ret += "<code class='modifier'>final</code> ";
     break;
   case "inline": // Not in XSLT
   case "local": // Not in XSLT
-    ret += "local ";
+    ret += "<code class='modifier'>local</code> ";
     break;
   case "optional": // Not in XSLT
-    ret += "optional ";
+    ret += "<code class='modifier'>optional</code> ";
     break;
   case "private": // Not in XSLT
-    ret += "private ";
+    ret += "<code class='modifier'>private</code> ";
     break;
   case "protected": // Not in XSLT
   case "static": // Not in XSLT
-    ret += "protected ";
+    ret += "<code class='modifier'>protected</code> ";
     break;
   case "public": // Not in XSLT
     // Ignored.
     break;
   case "variant": // Not in XSLT
-    ret += "variant ";
+    ret += "<code class='modifier'>variant</code> ";
     break;
 
   default:
@@ -1190,6 +1266,7 @@ string render_class_path(Node n,int|void class_only)
 #endif /* 0 */
 string class_name = "";
 
+#define HTML_ENC(S) (Parser.encode_html_entities(S))
 
 string parse_not_doc(Node n) {
   string ret = "";
@@ -1213,7 +1290,7 @@ string parse_not_doc(Node n) {
       continue;
 
     case "method":
-      if(method++) ret += "<br />\n";
+      if(method++) ret += "<br>\n";
 #if 0
       if(!c->get_first_element("returntype"))
 	error( "No returntype element in method element.\n" );
@@ -1221,16 +1298,16 @@ string parse_not_doc(Node n) {
 
       void emit_default_func()
       {
-          ret += "<tt>";
+          ret += "<code>";
           cc = c->get_first_element("modifiers");
           if(cc) ret += map(cc->get_children(), parse_type)*" " + " ";
           ret += parse_type(get_first_element(c->get_first_element("returntype")));
           ret += " ";
           ret += c->get_attributes()->class_path;
-          ret += "<b><font color='#000066'>" + c->get_attributes()->name + "</font>(</b>";
+          ret += "<b><span class='method'>" + HTML_ENC(c->get_attributes()->name) + "</span>(</b>";
           ret += parse_not_doc( c->get_first_element("arguments") );
           ret += "<b>)</b>";
-          ret += "</tt>";
+          ret += "</code>";
       };
       if( class_name == "" )
       {
@@ -1239,24 +1316,25 @@ string parse_not_doc(Node n) {
       else switch( string method = c->get_attributes()->name )
       {
         case "_get_iterator":
-          ret += "<tt><font color='#202020'>"+class_name+"</font> <font color='#000066'>a</font>;<br/>\n";
+          ret += "<code><span class='class'>"+class_name+"</span> "
+                 "<span class='method'>a</span>;<br>\n";
           /* NOTE: We could get index and value types from the
              iterator type here.  Doing so might be somewhat hard,
              however.
           */
-          ret += "foreach( a; index; value ) or<br></tt>";
+          ret += "foreach( a; index; value ) or<br></code>";
           emit_default_func();
           break;
 
         case "pow":
-          ret += "<tt>"+parse_type(get_first_element(c->get_first_element("returntype")));
-          ret += " res = "+method+"(<font color='#000066'>["+class_name+"]a</font>, b) or <br></tt>";
+          ret += "<code>"+parse_type(get_first_element(c->get_first_element("returntype")));
+          ret += " res = "+method+"([<span class='class'>"+class_name+"</span>]a, b) or <br></code>";
           emit_default_func();
           break;
 
         case "sqrt":
-          ret += "<tt>"+parse_type(get_first_element(c->get_first_element("returntype")));
-          ret += " res = "+method+"(<font color='#000066'>["+class_name+"]a</font>) or <br></tt>";
+          ret += "<code>"+parse_type(get_first_element(c->get_first_element("returntype")));
+          ret += " res = "+method+"([<span class='class'>"+class_name+"</span>]a) or <br></code>";
           emit_default_func();
           break;
 /*
@@ -1268,11 +1346,11 @@ string parse_not_doc(Node n) {
           break;
 */
 	case "create":
-	  ret += "<tt>" +class_name; // Check for more children
-	  ret += " ";
-	  ret += class_name+"<b>(</b>";
+	  ret += "<code><span class='object'>" +class_name; // Check for more children
+	  ret += "</span> <span class='class'>";
+	  ret += class_name+"</span><b>(</b>";
 	  ret += parse_not_doc( c->get_first_element("arguments") );
-	  ret += "<b>)</b></tt>";
+	  ret += "<b>)</b></code>";
 	  break;
 
         case "__hash":
@@ -1284,56 +1362,58 @@ string parse_not_doc(Node n) {
         case "_indices":
         case "_values":
           /* simple overload type lfuns. */
-          ret += "<tt>";
+          ret += "<code>";
           ret += parse_type(get_first_element(c->get_first_element("returntype")));
           ret += " ";
-          ret += "<b><font color='#000066'>"+method[1..]+"</font>(</b> ";
-          ret += "<font color='#202020'>"+class_name+"</font> <font color='#f000f0'>arg</font>";
-          ret += " <b>)</b>";
+          ret += "<b><span class='method'>"+method[1..]+"</span>(</b> ";
+          ret += "<span class='class'>"+class_name+"</span> <span class='argument'>arg</span>";
+          ret += " <b>)</b></code>";
           break;
 
         case "_m_delete":
         case "_equal":
         case "_search":
-          ret += "<tt>";
+          ret += "<code>";
           ret += parse_type(get_first_element(c->get_first_element("returntype")));
-          ret += " <b><font color='#000066'>"+method[1..];
-          ret += "</font>(</b>"+class_name+" <font color='#F000F0'>from</font>, ";
+          ret += " <b><span class='method'>"+method[1..];
+          ret += "</span>(</b><span class='class'>"+class_name+"</span> "
+                 "<span class='argument'>from</span>, ";
           ret += parse_not_doc( c->get_first_element("arguments") );
-          ret += "<b>)</b></tt>";
+          ret += "<b>)</b></code>";
           break;
 
         case "_sprintf":
-          ret += "<tt>";
-          ret += "<font color='#202020'>string</font> ";
-          ret += ("<b><font color='#000066'>sprintf</font>("
-                  "</b><font color='#202020'>string</font> "
-                  "<font color='#F000F0'>format</font>, ... <font color='#202020'>"
-                  +class_name+"</font> <font color='#F000F0'>"
-                  "arg</font> ... <b>)</b>");
+          //ret += "<tt>";
+          ret += "<code><span class='datatype'>string</span> ";
+          ret += ("<b><span class='method'>sprintf</span>("
+                  "</b><span class='datatype'>string</span> "
+                  "<span class='constant'>format</span>, ... <span class='class'>"
+                  +class_name+"</span> <span class='constant'>"
+                  "arg</span> ... <b>)</b></code>");
           break;
 
         case "_decode":
-          ret += "<tt>";
-          ret += "<font color='#202020'>"+class_name+"</font> ";
-          ret += ("<b><font color='#000066'>decode_value</font>("
-                  "</b><font color='#202020'>string(8bit)</font> "
-                  "<font color='#F000F0'>data</font>)</b>");
+          ret += "<code>";
+          ret += "<span class='class'>"+class_name+"</span> ";
+          ret += ("<b><span class='method'>decode_value</span>("
+                  "</b><span class='datatype'>string(8bit)</span> "
+                  "<span class='argument'>data</span>)</b></code>");
           break;
         case "_encode":
-          ret += "<tt>";
-          ret += "<font color='#202020'>string(8bit)</font> ";
-          ret += ("<b><font color='#000066'>encode_value</font>("
-                  "</b><font color='#202020'>"+class_name+"</font> "
-                  "<font color='#F000F0'>data</font>)</b>");
+          ret += "<code>";
+          ret += "<span class='datatype'>string(8bit)</span> ";
+          ret += ("<b><span class='method'>encode_value</span>("
+                  "</b><span class='class'>"+class_name+"</span> "
+                  "<span class='argument'>data</span>)</b></code>");
           break;
 
         case "cast":
           {
-            ret += "<tt>";
+            ret += "<code>";
 
             string base =
-              "<b>(</b>_@_TYPE_@_<b>)</b><font color='#202020'>"+class_name+"</font>()";
+              "<b>(</b><span class='datatype'>_@_TYPE_@_</span>"
+              "<b>)</b><span class='class'>"+class_name+"</span>()";
 
             multiset seen = (<>);
             void add_typed( string type )
@@ -1382,6 +1462,8 @@ string parse_not_doc(Node n) {
                              true);
             if( !sizeof(seen) )
               add_typed("mixed");
+
+            ret += "</code>";
           };
           break;
 
@@ -1390,7 +1472,8 @@ string parse_not_doc(Node n) {
           {
             Node a = c->get_first_element("arguments") ;
             array(Node) args = a->get_elements("argument");
-            mapping repl = (["OBJ":"<font color='#000066'>"+class_name+"()</font>"]);
+            mapping repl = (["OBJ":"<code class='class'>"+
+                                   class_name+"()</code>"]);
             /* there are a few cases:  obj OP arg - we do not want types
                RET func(op,ARG) - we do want types.
 
@@ -1399,21 +1482,24 @@ string parse_not_doc(Node n) {
             */
             if( sizeof(args) > 0 )
             {
-              repl->x = "<font color='#005080'>"+args[0]->get_attributes()->name+"</font>";
+              repl->x = "<code class='class'>"+
+                        args[0]->get_attributes()->name+"</code>";
             }
             if( sizeof(args) > 1 )
             {
-              repl->y = "<font color='#005080'>"+args[1]->get_attributes()->name+"</font>";
+              repl->y = "<code class='class'>"+
+                        args[1]->get_attributes()->name+"</code>";
             }
 
-            ret += "<tt>";
+            ret += "<code>";
             if( method != "`+=" && method != "`[]=" && method != "`->=")
             {
               ret += parse_type(get_first_element(c->get_first_element("returntype")));
               ret += " res = ";
             }
-            ret += replace( pat, repl );
-            ret += "</tt>";
+
+            ret += replace(HTML_ENC(pat), repl );
+            ret += "</code>";
             break;
           }
           emit_default_func( );
@@ -1424,75 +1510,83 @@ string parse_not_doc(Node n) {
     case "argument":
       if(argument++) ret += ", ";
       cc = c->get_first_element("value");
-      if(cc) ret += "<font color='green'>" + cc->value_of_node() + "</font>";
+      string arg_name = cc && cc->value_of_node();
+      if (arg_name) {
+        ret += "<code class='argument'>" + arg_name + "</code>";
+      }
       else if( !c->count_children() );
       else if( get_first_element(c)->get_any_name()=="type") {
 	ret += parse_type(get_first_element(get_first_element(c)));
-	if(c->get_attributes()->name)
-	  ret += " <font color='#005080'>" +
-	    c->get_attributes()->name + "</font>";
+        arg_name = c->get_attributes()->name;
+	if(arg_name) {
+	  ret += " <code class='argument'>" + arg_name + "</code>";
+        }
       }
       else
 	error( "Malformed argument element.\n" + c->html_of_node() + "\n" );
       break;
 
     case "variable":
-      if(variable++) ret += "<br />\n";
-      ret += "<tt>";
+      if(variable++) ret += "<br>\n";
+      ret += "<code>";
       cc = c->get_first_element("modifiers");
       if(cc) ret += map(cc->get_children(), parse_type)*" " + " ";
       if (c->get_first_element("type")) {
 	ret += parse_type(get_first_element(c->get_first_element("type")),
 			  "variable") + " " +
-	  c->get_attributes()->class_path + "<b><font color='#F000F0'>" +
-	  c->get_attributes()->name + "</font></b></tt>";
+	  c->get_attributes()->class_path + "<b><span class='variable'>" +
+	  c->get_attributes()->name + "</span></b></code>";
       } else
 	error("Malformed variable element.\n" + c->html_of_node() + "\n");
       break;
 
     case "constant":
-      if(num_const++) ret += "<br />\n";
-      ret += "<tt>";
+      if(num_const++) ret += "<br>\n";
+      ret += "<code><code class='datatype'>";
       cc = c->get_first_element("modifiers");
       if(cc) ret += map(cc->get_children(), parse_type)*" " + " ";
-      ret += "constant ";
+      ret += "constant</code> ";
       if (Node type = c->get_first_element ("type"))
 	ret += parse_type (get_first_element (type), "constant") + " ";
       ret += c->get_attributes()->class_path;
-      ret += "<font color='#F000F0'>" + c->get_attributes()->name + "</font>";
+      ret += "<code class='constant'>" + c->get_attributes()->name + "</code>";
       cc = c->get_first_element("typevalue");
-      if(cc) ret += " = " + parse_type(get_first_element(cc));
-      ret += "</tt>";
+      if(cc) {
+        ret += " = <code class='value'>" +
+               parse_type(get_first_element(cc)) + "</code>";
+      }
+      ret += "</code>";
       break;
 
     case "typedef":
-      if(typedf++) ret += "<br />\n";
-      ret += "<tt>";
+      if(typedf++) ret += "<br>\n";
+      ret += "<code><code class='datatype'>";
       cc = c->get_first_element("modifiers");
       if(cc) ret += map(cc->get_children(), parse_type)*" " + " ";
-      ret += "typedef ";
+      ret += "typedef</code> ";
       ret += parse_type(get_first_element(c->get_first_element("type")), "typedef") + " " +
-	c->get_attributes()->class_path + "<font color='#F000F0'>" + c->get_attributes()->name +
-	"</font></tt>";
+	c->get_attributes()->class_path +
+        "<code class='typedef'>" + c->get_attributes()->name + "</code></code>";
       break;
 
     case "inherit":
-      ret += "<font face='courier'>";
+      ret += "<code><span class='datatype'>";
       cc = c->get_first_element("modifiers");
       if(cc) ret += map(cc->get_children(), parse_type)*" " + " ";
       ret += "inherit ";
       Node n = c->get_first_element("classname");
       if (resolve_reference) {
-	ret += "</font>" +
+	ret += "</span>" +
 	  resolve_reference(n->value_of_node(), n->get_attributes());
       } else {
-	ret += Parser.encode_html_entities(n->value_of_node()) + "</font>";
+	ret += Parser.encode_html_entities(n->value_of_node()) + "</span>";
       }
       if (c->get_attributes()->name) {
-	ret += "<font face='courier'> : " + "<font color='#F000F0'>" +
+	ret += " : " + "<span class='inherit'>" +
 	  Parser.encode_html_entities(c->get_attributes()->name) +
-	  "</font></font>";
+	  "</span>";
       }
+      ret += "</code>";
       break;
 
     // We don't need import information.
@@ -1500,9 +1594,9 @@ string parse_not_doc(Node n) {
       break;
 
     case "directive":
-      if(cppdir++) ret += "<br />\n";
-      ret += "<tt><font color='#006666'>" + quote(c->get_attributes()->name) +
-	"</font></tt>";
+      if(cppdir++) ret += "<br>\n";
+      ret += "<code class='directive'>" + quote(c->get_attributes()->name) +
+	     "</code>";
       break;
 
     default:
@@ -1528,13 +1622,13 @@ string parse_docgroup(Node n) {
   if(lay->typehead) {
     ret += lay->typehead;
     if(m["homogen-type"]) {
-      string type = "<font face='Helvetica'>" +
+      string type = "<span class='homogen--type'>" +
 	quote(String.capitalize(m["homogen-type"])) +
-	"</font>\n";
+	"</span>\n";
       if(m["homogen-name"]) {
-	ret += type + "<font size='+1'><b>" +
+	ret += type + "<span class='homogen--name'><b>" +
 	  quote((m->belongs?m->belongs+" ":"") + m["homogen-name"]) +
-	  "</b></font>\n";
+	  "</b></span>\n";
       } else {
 	array(string) names =
 	  Array.uniq(map(n->get_elements(m["homogen-type"]),
@@ -1544,7 +1638,7 @@ string parse_docgroup(Node n) {
 			 }));
 	foreach(names, string name)
 	  ret += type +
-	    "<font size='+1'><b>" + quote(name) + "</b></font><br />\n";
+	    "<span class='homogen--name'><b>" + quote(name) + "</b></span><br>\n";
       }
     }
     else
@@ -1572,13 +1666,16 @@ string parse_children(Node n, string tag, function cb, mixed ... args) {
   return ret;
 }
 
+// This can be overridden by passing --template=template.html to main
+string html_template =
+        "<!doctype html><html><head><title>$title$</title>\n"
+        "<meta charset='utf-8'></head>\n"
+        "<body>$contents$</body></html>";
 string manual_title = "Pike Reference Manual";
 string frame_html(string res, void|string title) {
   title = title || manual_title;
-  return "<html><head><title>" + quote(title) + "</title>\n"
-    "<meta charset='utf-8' /></head>\n"
-    "<body bgcolor='white' text='black'>\n" + res +
-    "</body></html>";
+  return replace(html_template, ([ "$title$" : quote(title),
+                                   "$contents$" : res ]));
 }
 
 string layout_toploop(Node n, Git.Export|void exporter) {
@@ -1596,7 +1693,7 @@ string layout_toploop(Node n, Git.Export|void exporter) {
       {
         cwd=getcwd();
         cd(dest_path);
-      }  
+      }
       Stdio.mkdirhier(c->get_attributes()->name);
       layout_toploop(c);
       if(cwd)
@@ -1617,7 +1714,7 @@ string layout_toploop(Node n, Git.Export|void exporter) {
       {
         cwd=getcwd();
         cd(dest_path);
-      }  
+      }
       Stdio.write_file( c->get_attributes()->name,
 			string_to_utf8(frame_html(layout_toploop(c))) );
       if(cwd)
@@ -1708,18 +1805,36 @@ int low_main(string title, string input_file, string|void output_file,
   return 0;
 }
 
+void help(void|string err)
+{
+  string msg = #"pike -x autodoc_to_html [args] <input file> [<output file>]
+--img=<image path>
+--dest=<destination path>
+
+--title=<document title>
+
+--template=<template.html path>
+";
+
+  if( err )
+    exit(1, err+"\n"+msg);
+  write(msg);
+  exit(0);
+}
+
 int main(int num, array args) {
 
-  string title;
+  string title, template;
 
   foreach(Getopt.find_all_options(args, ({
-    ({ "img",     Getopt.HAS_ARG, "--img"   }),
-    ({ "dest",    Getopt.HAS_ARG, "--dest"  }),
-    ({ "title",   Getopt.HAS_ARG, "--title" }),
-    ({ "defns",   Getopt.HAS_ARG, "--default-ns" }),
-    ({ "verbose", Getopt.NO_ARG,  "-v,--verbose"/"," }),
-    ({ "quiet",   Getopt.NO_ARG,  "-q,--quiet"/"," }),
-    ({ "help",    Getopt.NO_ARG,  "--help"  }),
+    ({ "img",      Getopt.HAS_ARG, "--img"   }),
+    ({ "dest",     Getopt.HAS_ARG, "--dest"  }),
+    ({ "title",    Getopt.HAS_ARG, "--title" }),
+    ({ "template", Getopt.HAS_ARG, "--template" }),
+    ({ "defns",    Getopt.HAS_ARG, "--default-ns" }),
+    ({ "verbose",  Getopt.NO_ARG,  "-v,--verbose"/"," }),
+    ({ "quiet",    Getopt.NO_ARG,  "-q,--quiet"/"," }),
+    ({ "help",     Getopt.NO_ARG,  "--help"  }),
   })), array opt)
     switch(opt[0]) {
     case "img":
@@ -1731,6 +1846,9 @@ int main(int num, array args) {
     case "title":
       title = opt[1];
       break;
+    case "template":
+      template = opt[1];
+      break;
     case "defns":
       default_ns = opt[1];
       break;
@@ -1745,18 +1863,29 @@ int main(int num, array args) {
       verbosity = Tools.AutoDoc.FLAG_QUIET;
       break;
     case "help":
-      write(#"pike -x autodoc_to_html [args] <input file> [<output file>]
---img=<image path>
---dest=<destination path>
-
---title=<document title>
-");
+      help();
       break;
     }
   args = Getopt.get_args(args)[1..];
 
   if(!sizeof(args))
-    error( "No input file given.\n" );
+  {
+    help( "No input file given.\n" );
+  }
+
+  if (template && Stdio.exist(template)) {
+    string dir = dirname(template);
+    html_template = Stdio.read_file(template);
+    Parser.HTML p = Parser.HTML();
+    p->add_tag("link", lambda (Parser.HTML pp, mapping attr) {
+      if (attr->href && attr["data-inline"]) {
+        return "<style>" + (Stdio.read_file(combine_path(dir, attr->href))) +
+               "</style>";
+      }
+    });
+
+    html_template = p->feed(html_template)->finish()->read();
+  }
 
   return low_main(title, @args);
 }
diff --git a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike
index 2f98910b32..37420a4a3d 100644
--- a/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike
+++ b/lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike
@@ -32,224 +32,11 @@ mapping profiling = ([]);
 #define ENDPROFILE(X) profiling[(X)] += gethrtime()-profilet;
 
 constant navigation_js = #"
-/* Functions for rendering the navigation. */
-
-/* The variable current is assumed to have been set to the node
- * representing the current document.
- */
-
-/* These are all arrays of nodes. */
-var module_children = [];
-var class_children = [];
-var enum_children = [];
-var directive_children = [];
-var method_children = [];
-var member_children = [];
-var operator_children = [];
-var namespace_children = [];
-var appendix_children = [];
-var children = [];
-var siblings = [];
-
-function clear_children()
-{
-  module_children = [];
-  class_children = [];
-  enum_children = [];
-  directive_children = [];
-  method_children = [];
-  operator_children = [];
-  member_children = [];
-  namespace_children = [];
-  appendix_children = [];
-  children = [];
-}
-
-function cmp_nodes(/* node */a, /* node */b)
-{
-  return (a.name > b.name) - (b.name > a.name);
-}
-
-function merge_node_lists(/* array(node) */old, /* array(node) */nodes)
-{
-  var i;
-  var hash = {};
-  for (i=0; i < old.length; i++) {
-    var node = old[i];
-
-    hash[node.name] = i+1;
-  }
-  for (i = 0; i < nodes.length; i++) {
-    var node = nodes[i];
-    var j = hash[node.name];
-    if (j) {
-      old[j-1] = node;
-    } else {
-      old[old.length] = node;
-    }
-  }
-  old.sort(cmp_nodes);
-  return old;
-}
-
-function add_module_children(/* array(node) */children)
-{
-  module_children = merge_node_lists(module_children, children);
-}
-
-function add_class_children(/* array(node) */children)
-{
-  class_children = merge_node_lists(class_children, children);
-}
-
-function add_enum_children(/* array(node) */children)
-{
-  enum_children = merge_node_lists(enum_children, children);
-}
-
-function add_directive_children(/* array(node) */children)
-{
-  directive_children = merge_node_lists(directive_children, children);
-}
-
-function add_method_children(/* array(node) */children)
-{
-  method_children = merge_node_lists(method_children, children);
-}
-
-function add_operator_children(/* array(node) */children)
-{
-  operator_children = merge_node_lists(operator_children, children);
-}
-
-function add_namespace_children(/* array(node) */children)
-{
-  namespace_children = merge_node_lists(namespace_children, children);
-}
-
-function add_appendix_children(/* array(node) */children)
-{
-  appendix_children = merge_node_lists(appendix_children, children);
-}
-
-function add_member_children(/* array(node) */children)
-{
-  member_children = merge_node_lists(member_children, children);
-}
-
-function low_end_inherit(/* array(node) */nodes)
-{
-  var i;
-  for (i=0; i < nodes.length; i++) {
-    nodes[i].inherited = 1;
-  }
-}
-
-function end_inherit()
-{
-  low_end_inherit(module_children);
-  low_end_inherit(class_children);
-  low_end_inherit(enum_children);
-  low_end_inherit(directive_children);
-  low_end_inherit(method_children);
-  low_end_inherit(operator_children);
-  low_end_inherit(member_children);
-  low_end_inherit(namespace_children);
-  low_end_inherit(appendix_children);
-}
-
-function emit_end_inherit()
-{
-  document.write(\"<script language='javascript'>\\n\" +
-                 \"end_inherit();\\n\" +
-                 \"</script>\\n\");
-}
-
-function escapehtml(/* string */text)
-{
-  text = text.split('&').join('&amp;');
-  text = text.split('<').join('&lt;');
-  return text.split('>').join('&gt;');
-}
-
-function basedir(/* string */path)
-{
-  var i = path.lastIndexOf('/');
-  if (i < 1) return '';
-  return path.substring(0, i);
-}
-
-function has_prefix(/* string */prefix, /* string */other)
-{
-  return other.substring(0, prefix.length) == prefix;
-}
-
-function adjust_link(/* string */link)
-{
-  var reldir = basedir(current.link);
-  var dots = '';
-  while (reldir != '' && !has_prefix(link, reldir + '/')) {
-    dots += '../';
-    reldir = basedir(reldir);
-  }
-  return dots + link.substring(reldir.length);
-}
-
-function emit_load_js(/* string */link)
-{
-  document.write(\"<script language='javascript' src='\" +
-                 adjust_link(link) + \"' >\\n\" +
-                 \"</script>\\n\");
-}
-
-function low_navbar(/* Document */document, /* string */heading,
-                    /* array(node) */nodes, /* string */suffix)
-{
-  if (!nodes || !nodes.length) return;
-
-  document.write('<br /><b>' + escapehtml(heading) + '</b>\\n');
-
-  document.write('<div style=\"margin-left:0.5em;\">\\n');
-  var i;
-  for (i=0; i < nodes.length; i++) {
-    var n = nodes[i];
-    var name = escapehtml(n.name + suffix);
-    if (!n.inherited) {
-      name = '<b>' + name + '</b>';
-    }
-    if (n.link == current.link) {
-      document.write(name);
-    } else {
-      document.write('<a href=\"' + adjust_link(n.link) + '\">');
-      document.write(name);
-      document.write('</a>');
-    }
-    document.write('<br />\\n');
-  }
-  document.write('</div>\\n');
-}
-
-/* Render the left navigation bar. */
-function navbar(/* Document */document)
-{
-  document.write('<div class=\"sidebar\">\\n');
-  low_navbar(document, 'Modules', module_children, '');
-  low_navbar(document, 'Classes', class_children, '');
-  low_navbar(document, 'Enums', enum_children, '');
-  low_navbar(document, 'Directives', directive_children, '');
-  low_navbar(document, 'Methods', method_children, '()');
-  low_navbar(document, 'Operators', operator_children, '()');
-  low_navbar(document, 'Members', member_children, '()');
-  low_navbar(document, 'Namespaces', namespace_children, '::');
-  low_navbar(document, 'Appendices', appendix_children, '');
-  document.write('</div>\\n');
-}
-";
+/* Functions for rendering the navigation has been moved to a script */";
 
 string encode_json(mixed val)
 {
-  return Standards.JSON.encode(val,
-    Standards.JSON.HUMAN_READABLE|Standards.JSON.PIKE_CANONICAL);
+  return Standards.JSON.encode(val,Standards.JSON.PIKE_CANONICAL);
 }
 
 string cquote(string n)
@@ -275,22 +62,22 @@ array(string) split_reference(string what) {
     array(string) r = what/".";
 
     for (int i = 1; i < sizeof(r) - 1; i++) {
-	if (r[i] == "") {
-	    int j = i+1;
+        if (r[i] == "") {
+            int j = i+1;
 
-	    while (j < sizeof(r) - 1 && r[j] == "") j++;
+            while (j < sizeof(r) - 1 && r[j] == "") j++;
 
-	    r[i-1] = sprintf("%s.%s%s", r[i-1], "."*(j-i), r[j]);
-	    r = r[..i-1] + r[j+1..];
-	    i--;
-	}
+            r[i-1] = sprintf("%s.%s%s", r[i-1], "."*(j-i), r[j]);
+            r = r[..i-1] + r[j+1..];
+            i--;
+        }
     }
 
     return r;
 }
 
 string create_reference(string from, string to, string text,
-			string|void xlink_namespace_prefix) {
+                        string|void xlink_namespace_prefix) {
   array a = (to/"::");
   switch(sizeof(a)) {
   case 2:
@@ -310,12 +97,11 @@ string create_reference(string from, string to, string text,
     error("Bad reference: %O\n", to);
   }
   if (!xlink_namespace_prefix) xlink_namespace_prefix = "";
-  return "<a style='font-family:courier;' " +
+  return "<a class='ms reference' " +
     xlink_namespace_prefix +
     "href='" +
     "../"*max(sizeof(from/"/") - 2, 0) + map(a, cquote)*"/" + ".html'>" +
-    text +
-    "</a>";
+    String.trim_all_whites(text) + "</a>";
 }
 
 multiset missing = (< "foreach", "catch", "throw", "sscanf", "gauge", "typeof" >);
@@ -336,6 +122,7 @@ class Node
   array(Node) operator_children = ({ });
   array(array(string|Node)) inherits = ({});
   array(Node) children = ({});
+  array(string) modifiers = ({});
 
   Node parent;
 
@@ -345,14 +132,42 @@ class Node
 
   void create(string _type, string _name, string _data, void|Node _parent)
   {
+    //if (_type == "class" && search(_data, "<modifiers>") > -1) {
+    //  werror("\n\n\n----\n%s\n-------\n\n\n", _data);
+    //}
+    if ((< "method", "enum", "variable", "constant" >)[_type]  &&
+        search(_data, "<modifiers>") > -1)
+    {
+      //werror("%s:%s: %s\n", _type, _name, _data);
+      Parser.HTML pp = Parser.HTML();
+      function cb_modifier = lambda (Parser.HTML p, mapping m, string cc) {
+        modifiers += ({ p->tag_name() });
+        return ({ "" });
+      };
+
+      pp->add_containers(([
+        "modifiers": lambda (Parser.HTML p, mapping a, string cc) {
+          pp->clear_containers();
+          pp->add_tags(([
+            "protected" : cb_modifier,
+            "private "  : cb_modifier,
+            "static"    : cb_modifier
+          ]));
+          return cc;
+        }
+      ]));
+      pp->finish(_data);
+    }
+
     if(!_type || !_name) throw( ({ "No type or name\n", backtrace() }) );
     type = _type;
     name = _name;
     parent = _parent;
+
     data = get_parser()->finish( _data )->read();
 
     string path = raw_class_path();
-    refs[path] = this_object();
+    refs[path] = this;
 
     sort(class_children->name, class_children);
     sort(module_children->name, module_children);
@@ -374,10 +189,10 @@ class Node
       {
         /*if( m->name == "create" )
           _children -= ({ m });*/
-	string d;
-	sscanf(m->data, "%*s<docgroup%s/docgroup>", d);
-	if(d)
-	  data += "<docgroup" + d + "/docgroup>";
+        string d;
+        sscanf(m->data, "%*s<docgroup%s/docgroup>", d);
+        if(d)
+          data += "<docgroup" + d + "/docgroup>";
       }
     }
     method_children -= ({0});
@@ -389,66 +204,67 @@ class Node
     array names = children->name;
     foreach(Array.uniq(names), string n)
       if(sizeof(filter(names, lambda(string in) { return in==n; }))!=1) {
-	string d="";
-	Parser.HTML parser = Parser.HTML();
-	parser->case_insensitive_tag(1);
-	parser->xml_tag_syntax(3);
-	parser->add_container("docgroup",
+        string d="";
+        Parser.HTML parser = Parser.HTML();
+        parser->case_insensitive_tag(1);
+        parser->xml_tag_syntax(3);
+        parser->add_container("docgroup",
           lambda(Parser.HTML p, mapping m, string c) {
-	    d += sprintf("%s%s</docgroup>", render_tag("docgroup", m), c);
-	    return "";
-	  });
-
-	foreach(children, Node c)
-	  if(c->name==n) parser->feed(c->data);
-	parser->finish();
-	d = make_faked_wrapper(d);
-
-	foreach(children; int i; Node c)
-	  if(c->name==n) {
-	    if(d) {
-	      c->data = d;
-	      d = 0;
-	    }
-	    else children[i] = 0;
-	  }
-	children -= ({ 0 });
+            d += sprintf("%s%s</docgroup>", render_tag("docgroup", m), c);
+            return "";
+          });
+
+        foreach(children, Node c)
+          if(c->name==n) parser->feed(c->data);
+        parser->finish();
+        d = make_faked_wrapper(d);
+
+        foreach(children; int i; Node c)
+          if(c->name==n) {
+            if(d) {
+              c->data = d;
+              d = 0;
+            }
+            else children[i] = 0;
+          }
+        children -= ({ 0 });
       }
     return children;
   }
 
   protected string parse_node(Parser.HTML p, mapping m, string c) {
     if(!m->name) error("Unnamed %O %O\n", p->tag_name(), m);
-    this_object()[p->tag_name()+"_children"] +=
-      ({ Node( p->tag_name(), m->name, c, this_object() ) });
+
+    this[p->tag_name()+"_children"] +=
+      ({ Node( p->tag_name(), m->name, c, this ) });
     return "";
   }
 
   protected void add_ref(string path, string type, string name,
-			 string data, Node n, string c)
+                         string data, Node n, string c)
   {
     refs[path + name] = Node(type, name, data, n);
     if (type == "inherit") {
       Parser.HTML()->
-	add_containers(([ "classname":
-			  lambda(Parser.HTML p, mapping m, string c) {
-			    string resolved;
-			    if (resolved = m->resolved) {
-			      resolved = Parser.parse_html_entities(resolved);
-			      Node nn = refs[resolved];
-			      if (nn) {
-				nn->children += ({ n });
-			      } else {
-				pending_inherits->push(({ resolved, n }));
-			      }
-			    }
-			    n->inherits += ({
-			      ({
-				name, c, resolved,
-			      })
-			    });
-			  },
-		       ]) )->finish(c);
+        add_containers(([ "classname":
+                          lambda(Parser.HTML p, mapping m, string c) {
+                            string resolved;
+                            if (resolved = m->resolved) {
+                              resolved = Parser.parse_html_entities(resolved);
+                              Node nn = refs[resolved];
+                              if (nn) {
+                                nn->children += ({ n });
+                              } else {
+                                pending_inherits->push(({ resolved, n }));
+                              }
+                            }
+                            n->inherits += ({
+                              ({
+                                name, c, resolved,
+                              })
+                            });
+                          },
+                       ]) )->finish(c);
     }
   }
 
@@ -461,91 +277,92 @@ class Node
       switch( m["homogen-type"] ) {
 
       case "method":
-	if( m["homogen-name"] ) {
-	  string name = m["homogen-name"];
-	  if(m->belongs) {
-	    if(m->belongs[-1]==':') name = m->belongs + name;
-	    else name = m->belongs + "." + name;
-	  }
-	  method_children +=
-	    ({ Node( "method", name, c, this_object() ) });
-	  return ({ "" });
-	}
-
-	// Several different methods documented with the same blurb.
-	array names = ({});
-	Parser.HTML parser = Parser.HTML();
-	parser->case_insensitive_tag(1);
-	parser->xml_tag_syntax(3);
-	parser->add_tag("method",
-			lambda(Parser.HTML p, mapping m) {
-			  names += ({ Parser.parse_html_entities(m->name) });
-			} );
-	parser->finish(c);
-	foreach(Array.uniq(names) - ({ 0, "" }), string name) {
-	  method_children +=
-	    ({ Node( "method", name, c, this_object() ) });
-	}
-	return ({ "" });
-	break;
+        if( m["homogen-name"] ) {
+          string name = m["homogen-name"];
+          if(m->belongs) {
+            if(m->belongs[-1]==':') name = m->belongs + name;
+            else name = m->belongs + "." + name;
+          }
+          method_children +=
+            ({ Node( "method", name, c, this ) });
+          return ({ "" });
+        }
+
+        // Several different methods documented with the same blurb.
+        array names = ({});
+        Parser.HTML parser = Parser.HTML();
+        parser->case_insensitive_tag(1);
+        parser->xml_tag_syntax(3);
+        parser->add_tag("method",
+                        lambda(Parser.HTML p, mapping m) {
+                          names += ({ Parser.parse_html_entities(m->name) });
+                        } );
+        parser->finish(c);
+        foreach(Array.uniq(names) - ({ 0, "" }), string name) {
+          method_children +=
+            ({ Node( "method", name, c, this ) });
+        }
+        return ({ "" });
+        break;
 
       case "directive":
-	if( m["homogen-name"] ) {
-	  string name = m["homogen-name"];
-	  directive_children +=
-	    ({ Node( "directive", name, c, this_object() ) });
-	  return ({ "" });
-	}
-
-	// Several different directives documented with the same blurb.
-	array directives = ({});
-	Parser.HTML dirparser = Parser.HTML();
-	dirparser->case_insensitive_tag(1);
-	dirparser->xml_tag_syntax(3);
-	dirparser->add_tag("directive",
-			   lambda(Parser.HTML p, mapping m) {
-			     directives += ({
-			       Parser.parse_html_entities(m->name)
-			     });
-			   } );
-	dirparser->finish(c);
-	foreach(Array.uniq(directives) - ({ 0, "" }), string name) {
-	  directive_children +=
-	    ({ Node( "directive", name, c, this_object() ) });
-	}
-	return ({ "" });
-	break;
+        if( m["homogen-name"] ) {
+          string name = m["homogen-name"];
+          directive_children +=
+            ({ Node( "directive", name, c, this ) });
+          return ({ "" });
+        }
+
+        // Several different directives documented with the same blurb.
+        array directives = ({});
+        Parser.HTML dirparser = Parser.HTML();
+        dirparser->case_insensitive_tag(1);
+        dirparser->xml_tag_syntax(3);
+        dirparser->add_tag("directive",
+                           lambda(Parser.HTML p, mapping m) {
+                             directives += ({
+                               Parser.parse_html_entities(m->name)
+                             });
+                           } );
+        dirparser->finish(c);
+        foreach(Array.uniq(directives) - ({ 0, "" }), string name) {
+          directive_children +=
+            ({ Node( "directive", name, c, this ) });
+        }
+        return ({ "" });
+        break;
 
       case "constant":
       case "variable":
       case "inherit":
-	string path = raw_class_path();
-	if(sizeof(path) && (path[-1] != ':')) path += ".";
-	if(!m["homogen-name"]) {
-	  Parser.HTML()->add_tags
-	    ( ([ "constant":
-		 lambda(Parser.HTML p, mapping m, string c) {
-		   string name = Parser.parse_html_entities(m->name);
-		   add_ref(path, "constant", name, "", this_object(), c);
-		 },
-		 "variable":
-		 lambda(Parser.HTML p, mapping m, string c) {
-		   string name = Parser.parse_html_entities(m->name);
-		   add_ref(path, "variable", name, "", this_object(), c);
-		 },
-		 "inherit":
-		 lambda(Parser.HTML p, mapping m, string c) {
-		   if (m->name) {
-		     string name = Parser.parse_html_entities(m->name);
-		     add_ref(path, "inherit", name, "", this_object(), c);
-		   }
-		 },
-	    ]) )->finish(c);
-	}
-	else
-	  add_ref(path, m["homogen-type"], m["homogen-name"],
-		  "", this_object(), c);
-	break;
+        string path = raw_class_path();
+        if(sizeof(path) && (path[-1] != ':')) path += ".";
+
+        if(!m["homogen-name"]) {
+          Parser.HTML()->add_tags
+            ( ([ "constant":
+                 lambda(Parser.HTML p, mapping m, string c) {
+                   string name = Parser.parse_html_entities(m->name);
+                   add_ref(path, "constant", name, "", this, c);
+                 },
+                 "variable":
+                 lambda(Parser.HTML p, mapping m, string c) {
+                   string name = Parser.parse_html_entities(m->name);
+                   add_ref(path, "variable", name, "", this, c);
+                 },
+                 "inherit":
+                 lambda(Parser.HTML p, mapping m, string c) {
+                   if (m->name) {
+                     string name = Parser.parse_html_entities(m->name);
+                     add_ref(path, "inherit", name, "", this, c);
+                   }
+                 }
+            ]) )->finish(c);
+        }
+        else
+          add_ref(path, m["homogen-type"], m["homogen-name"],
+                  "", this, c);
+        break;
 
       }
     }
@@ -571,16 +388,16 @@ class Node
   {
     if (type=="appendix")
       return "<appendix name='" + Parser.encode_html_entities(name) + "'>" +
-	s + "</appendix>";
+        s + "</appendix>";
 
     if((type == "method") || (type == "directive"))
       s = sprintf("<docgroup homogen-type='%s' homogen-name='%s'>\n"
-		  "%s\n</docgroup>\n",
-		  type,
-		  Parser.encode_html_entities(name), s);
+                  "%s\n</docgroup>\n",
+                  type,
+                  Parser.encode_html_entities(name), s);
     else
       s = sprintf("<%s name='%s'>\n%s\n</%s>\n",
-		  type, Parser.encode_html_entities(name), s, type);
+                  type, Parser.encode_html_entities(name), s, type);
     if(parent)
       return parent->make_faked_wrapper(s);
     else
@@ -643,7 +460,7 @@ class Node
   array(Node) get_ancestors()
   {
     PROFILE();
-    array tmp = ({ this_object() }) + parent->get_ancestors();
+    array tmp = ({ this }) + parent->get_ancestors();
     ENDPROFILE("get_ancestors");
     return tmp;
   }
@@ -655,62 +472,65 @@ class Node
       _reference = _reference[sizeof(default_namespace)+2..];
 
     if(vars->param)
-      return "<font face='courier'>" + _reference + "</font>";
+      return "<code class='reference param'>" + _reference + "</code>";
 
     if (resolved) {
       foreach (resolved, string resolution) {
-	Node res_obj;
-
-	if(res_obj = refs[resolution]) {
-	  while(res_obj && (<"constant","variable">)[res_obj->type]) {
-	    res_obj = res_obj->parent;
-	  }
-	  if (!res_obj && verbosity) {
-	    werror("Found no page to link to for reference %O (%O)\n",
-		   _reference, resolution);
-	    return sprintf("<font face='courier'>" + _reference + "</font>");
-	  }
-	  // FIXME: Assert that the reference is correct?
-	  return create_reference(make_filename(),
-				  res_obj->raw_class_path(),
-				  _reference);
-	}
-
-	// Might be a reference to a parameter.
-	// Try cutting of the last section, and retry.
-	array(string) tmp = resolution/".";
-	if ((sizeof(tmp) > 1) && (res_obj = refs[tmp[..sizeof(tmp)-2]*"."])) {
-	  if (res_obj == this_object()) {
-	    return sprintf("<font face='courier'>" + _reference + "</font>");
-	  }
-	  return create_reference(make_filename(),
-				  res_obj->raw_class_path(),
-				  _reference);
-	}
-
-	if (has_index(refs, resolution) &&
-	    (verbosity >= Tools.AutoDoc.FLAG_VERBOSE)) {
-	  werror("Reference %O (%O) is %O!\n",
-		 _reference, resolution, refs[resolution]);
-	}
+        Node res_obj;
+
+        if(res_obj = refs[resolution]) {
+          while(res_obj && (<"constant","variable">)[res_obj->type]) {
+            res_obj = res_obj->parent;
+          }
+          if (!res_obj && verbosity) {
+            werror("Found no page to link to for reference %O (%O)\n",
+                   _reference, resolution);
+            return "<code class='reference nolink'>" + _reference +
+                   "</code>";
+          }
+          // FIXME: Assert that the reference is correct?
+          return create_reference(make_filename(),
+                                  res_obj->raw_class_path(),
+                                  _reference);
+        }
+
+        // Might be a reference to a parameter.
+        // Try cutting of the last section, and retry.
+        array(string) tmp = resolution/".";
+        if ((sizeof(tmp) > 1) && (res_obj = refs[tmp[..sizeof(tmp)-2]*"."])) {
+          if (res_obj == this) {
+            return "<code class='reference paramref'>" + _reference +
+                   "</code>";
+          }
+          return create_reference(make_filename(),
+                                  res_obj->raw_class_path(),
+                                  _reference);
+        }
+
+        if (has_index(refs, resolution) &&
+            (verbosity >= Tools.AutoDoc.FLAG_VERBOSE)) {
+          werror("Reference %O (%O) is %O!\n",
+                 _reference, resolution, refs[resolution]);
+        }
       }
       if (!missing[vars->resolved] && !has_prefix(_reference, "lfun::") &&
-	  verbosity) {
-	werror("Missed reference %O (%{%O, %}) in %s\n",
-	       _reference, resolved||({}), make_class_path());
+          verbosity) {
+        werror("Missed reference %O (%{%O, %}) in %s\n",
+               _reference, resolved||({}), make_class_path());
 #if 0
-	werror("Potential refs:%O\n",
-	       sort(map(resolved,
-			lambda (string resolution) {
-			  return filter(indices(refs),
-					glob(resolution[..sizeof(resolution)/2]+
-					     "*", indices(refs)[*]));
-			}) * ({})));
+        werror("Potential refs:%O\n",
+               sort(map(resolved,
+                        lambda (string resolution) {
+                          return filter(indices(refs),
+                                        glob(resolution[..sizeof(resolution)/2]+
+                                             "*", indices(refs)[*]));
+                        }) * ({})));
 #endif /* 0 */
       }
       unresolved++;
     }
-    return "<font face='courier'>" + _reference + "</font>";
+    return "<code class='reference unresolved'>" + _reference +
+           "</code>";
   }
 
   string _make_class_path;
@@ -726,17 +546,17 @@ class Node
     {
       // Hide most namepaces from the class path.
       if (n->type == "namespace") {
-	_raw_class_path += n->name + "::";
-	if ((<"","lfun">)[n->name]) {
-	  _make_class_path += n->name + "::";
-	}
+        _raw_class_path += n->name + "::";
+        if ((<"","lfun">)[n->name]) {
+          _make_class_path += n->name + "::";
+        }
       } else {
-	_raw_class_path += n->name + ".";
-	_make_class_path += n->name;
-	if(n->type=="class")
-	  _make_class_path += "()->";
-	else if(n->type=="module")
-	  _make_class_path += ".";
+        _raw_class_path += n->name + ".";
+        _make_class_path += n->name;
+        if(n->type=="class")
+          _make_class_path += "()->";
+        else if(n->type=="module")
+          _make_class_path += ".";
       }
     }
     _make_class_path += name;
@@ -759,35 +579,36 @@ class Node
   }
 
   string low_make_classic_navbar(array(Node) children, string what,
-				 int|void extra_levels)
+                                 int|void extra_levels)
   {
     if(!sizeof(children)) return "";
 
     String.Buffer res = String.Buffer(3000);
-    res->add("<br /><b>", what, "</b>\n"
-	     "<div style='margin-left:0.5em;'>\n");
+    res->add("<b class='head'>", what, "</b>\n"
+             "<div class='sidebar'>"
+             "<div style='margin-left:0.5em;'>\n");
 
     foreach(children, Node node)
     {
       string my_name = Parser.encode_html_entities(node->name);
       if(node->type=="method") {
-	my_name+="()";
-	if (node == this_object()) {
-	  my_name="<b>"+my_name+"</b>";
-	}
+        my_name+="()";
+        if (node == this) {
+          my_name="<b class='head'>"+my_name+"</b>";
+        }
       } else if (node->type == "namespace") {
-	my_name="<b>"+my_name+"::</b>";
+        my_name="<b>"+my_name+"::</b>";
       }
       else
-	my_name="<b>"+my_name+"</b>";
+        my_name="<b>"+my_name+"</b>";
 
-      if(node==this_object())
-	res->add( my_name, "<br />\n" );
+      if(node==this)
+        res->add(my_name);
       else
-	res->add( "<a href='", make_link(node, extra_levels), "'>",
-		  my_name, "</a><br />\n" );
+        res->add( "<a href='", make_link(node, extra_levels), "'>",
+                  my_name, "</a>\n" );
     }
-    res->add("</div>\n");
+    res->add("</div></div>\n");
     return (string)res;
   }
 
@@ -798,19 +619,32 @@ class Node
     if(node)
     {
       if(node->type=="namespace" && node->name==default_namespace)
-	node = node->parent;
+        node = node->parent;
       res += make_hier_list(node->parent, extra_levels);
 
       string my_class_path =
-	(node->is_TopNode)?"[Top]":node->make_class_path();
+        (node->is_TopNode)?"Top":node->make_class_path();
 
-      if(node == this_object())
-	res += sprintf("<b>%s</b><br />\n",
-		       Parser.encode_html_entities(my_class_path));
-      else
-	res += sprintf("<a href='%s'><b>%s</b></a><br />\n",
-		       make_link(node, extra_levels),
-		       Parser.encode_html_entities(my_class_path));
+      string eclass = node->is_TopNode ? "top" : "";
+
+//werror("my_class_path: %s\n", my_class_path);
+
+      if(node == this) {
+        if (eclass == "")
+          eclass = "selected";
+
+        res += sprintf("<b class='%s head'>%s</b>\n", eclass,
+                       Parser.encode_html_entities(my_class_path));
+      }
+      else {
+        if (eclass != "")
+          eclass = " class='" + eclass + " head'";
+        else
+          eclass = " class='head'";
+        res += sprintf("<a href='%s'><b%s>%s</b></a>\n",
+                       make_link(node, extra_levels), eclass,
+                       Parser.encode_html_entities(my_class_path));
+      }
     }
     return res;
   }
@@ -819,7 +653,7 @@ class Node
   {
     string res="";
 
-    res += make_hier_list(this_object(), extra_levels);
+    res += make_hier_list(this, extra_levels);
 
     res += low_make_classic_navbar(module_children, "Modules", extra_levels);
     res += low_make_classic_navbar(class_children, "Classes", extra_levels);
@@ -834,7 +668,7 @@ class Node
     res += make_hier_list(root);
 
     return res +
-      "<script language='javascript'>navbar(document)</script>\n"
+      "<script></script>\n"
       "<noscript>\n"
       "<div class='sidebar'>\n"
       "<a href='" + low_make_link(make_index_filename() + ".html") + "'>"
@@ -848,7 +682,7 @@ class Node
     if((type == "method") || (type == "directive"))
       return make_navbar_low(parent);
     else
-      return make_navbar_low(this_object());
+      return make_navbar_low(this);
   }
 
   string low_make_index_js(string name, array(Node) nodes)
@@ -856,20 +690,58 @@ class Node
     if (!sizeof(nodes)) return "";
     array(mapping(string:string)) a =
       map(nodes,
-	  lambda(Node n) {
-	    return ([ "name":n->name,
-		      "link":n->make_filename() ]);
-	  });
+          lambda(Node n) {
+            return ([ "name":n->name,
+                      "link":n->make_filename() ]);
+          });
     sort(a->name, a);
     return sprintf("add_%s(%s);\n", name, encode_json(a));
   }
 
+  string low_make_index_js2(string name, array(Node) nodes)
+  {
+    if (!sizeof(nodes)) return "";
+    array(mapping(string:string)) a =
+      map(nodes,
+          lambda(Node n) {
+            return ([ "name":n->name,
+                      "link":n->make_filename(),
+                      "modifiers":sizeof(n->modifiers) && n->modifiers || Val.null ]);
+          });
+    sort(a->name, a);
+    return sprintf(".addChildren('%s', %s)\n", name, encode_json(a));
+  }
+
   string make_index_js()
   {
+#if 1
+    string cp = make_class_path();
+    string res = "// Class path " + cp + "\n";
+
+
+    res += "PikeDoc.registerSymbol('" + cp + "', PikeDoc.isInline)\n";
+
+    #define LOW_MAKE_INDEX_JS(CHILDREN) do { \
+      res += low_make_index_js2(((#CHILDREN)/"_")[0], CHILDREN); \
+    } while (0)
+
+    LOW_MAKE_INDEX_JS(module_children);
+    LOW_MAKE_INDEX_JS(class_children);
+    LOW_MAKE_INDEX_JS(enum_children);
+    LOW_MAKE_INDEX_JS(directive_children);
+    LOW_MAKE_INDEX_JS(method_children);
+    LOW_MAKE_INDEX_JS(operator_children);
+    LOW_MAKE_INDEX_JS(member_children);
+
+    res += ".finish();\n";
+
+    return res;
+
+#else
     string res = "// Direct symbols for " + make_class_path() + ".\n\n";
 
-#define LOW_MAKE_INDEX_JS(CHILDREN) do {				\
-      res += low_make_index_js(#CHILDREN, CHILDREN);			\
+#define LOW_MAKE_INDEX_JS(CHILDREN) do {                                \
+      res += low_make_index_js(#CHILDREN, CHILDREN);                    \
     } while (0)
 
     LOW_MAKE_INDEX_JS(module_children);
@@ -887,38 +759,54 @@ class Node
       "                                  method_children,\n"
       "                                  operator_children,\n"
       "                                  member_children);\n";
+#endif
   }
 
   string make_load_index_js()
   {
     string res = "";
+    array(string) js_inherits;
+
     if (sizeof(inherits)) {
+      js_inherits = ({});
       foreach(inherits, array(string|Node) inh) {
-	Node n = objectp(inh[2])?inh[2]:refs[inh[2]];
-	if (!n) continue;
-
-	res += sprintf("// Inherit %s.\n"
-		       "emit_load_js(%q);\n"
-		       "\n",
-		       n->make_class_path(),
-		       n->make_load_index_filename());
+        Node n = objectp(inh[2])?inh[2]:refs[inh[2]];
+        if (!n) continue;
+
+        string cls_path = n->make_class_path();
+        js_inherits += ({ cls_path });
+
+        res += sprintf("// Inherit %s.\n"
+                       "PikeDoc.loadScript(%q, %[0]q);\n"
+                       "\n",
+                       cls_path,
+                       n->make_load_index_filename());
       }
       if (sizeof(res)) {
-	res = sprintf("// Load the symbols from our inherits.\n"
-		      "\n"
-		      "%s"
-		      "emit_end_inherit();\n"
-		      "\n",
-		      res);
+        #if 0
+        res = sprintf("// Load the symbols from our inherits.\n"
+                      "\n"
+                      "%s"
+                      "emit_end_inherit();\n"
+                      "\n",
+                      res);
+
+        res += sprintf("// New \n"
+                       "PikeDoc.end_inherit('%s');\n\n",
+                       make_class_path());
+        #endif
       }
     }
     res = sprintf("// Indirect loader of the symbol index for %s.\n"
-		  "\n"
-		  "%s"
-		  "emit_load_js(%q);\n",
-		  make_class_path(),
-		  res,
-		  make_index_filename() + ".js");
+                  "\n"
+                  "%s"
+                  "PikeDoc.loadScript(%q, %s, %s);\n",
+                  make_class_path(),
+                  res,
+                  make_index_filename() + ".js",
+                  sizeof(res) ? "false" : "true",
+                  js_inherits &&
+                  sizeof(js_inherits) ? encode_json(js_inherits) : "null");
     return res;
   }
 
@@ -942,7 +830,7 @@ class Node
   Node find_prev_node()
   {
     array(Node) siblings = find_siblings();
-    int index = search( siblings, this_object() );
+    int index = search( siblings, this );
 
     Node tmp;
 
@@ -963,7 +851,7 @@ class Node
       return find_children()[0];
 
     array(Node) siblings = find_siblings();
-    int index = search( siblings, this_object() );
+    int index = search( siblings, this );
 
     Node tmp;
     if(index==sizeof(siblings)-1)
@@ -999,28 +887,28 @@ class Node
       closure[ref] = weight;
       Node n = refs[ref];
       if (!n) {
-	forward_deps[ref] = (<>);
-	continue;
+        forward_deps[ref] = (<>);
+        continue;
       }
       names[ref] = n->raw_class_path();
       multiset(string) inhs = (<>);
       if (sizeof(n->inherits)) {
-	foreach(n->inherits, array(string) entry) {
-	  if (entry[2] == ref) {
-	    if (verbosity && (ref == this_ref)) {
-	      werror("Circular inherit in %s.\n", this_ref);
-	    }
-	    continue;	// Infinite loop averted.
-	  }
-	  q->put(({ weight + 1 }) + entry);
-	  inhs[entry[2]||entry[1]] = 1;
-	}
-	foreach(inhs; string inh_ref;) {
-	  if (!backward_deps[inh_ref]) {
-	    backward_deps[inh_ref] = (<>);
-	  }
-	  backward_deps[inh_ref][ref] = 1;
-	}
+        foreach(n->inherits, array(string) entry) {
+          if (entry[2] == ref) {
+            if (verbosity && (ref == this_ref)) {
+              werror("Circular inherit in %s.\n", this_ref);
+            }
+            continue;   // Infinite loop averted.
+          }
+          q->put(({ weight + 1 }) + entry);
+          inhs[entry[2]||entry[1]] = 1;
+        }
+        foreach(inhs; string inh_ref;) {
+          if (!backward_deps[inh_ref]) {
+            backward_deps[inh_ref] = (<>);
+          }
+          backward_deps[inh_ref][ref] = 1;
+        }
       }
       forward_deps[ref] = inhs;
     }
@@ -1034,31 +922,31 @@ class Node
     int no_predef_strip;
     foreach(values(names), string name) {
       if ((!has_prefix(name, "predef::") && has_value(name, "::")) ||
-	  name == "predef::") {
-	no_predef_strip = 1;
+          name == "predef::") {
+        no_predef_strip = 1;
       }
     }
     foreach(names; string ref; string name) {
       if (!no_predef_strip && has_prefix(name, "predef::")) {
-	name = name[sizeof("predef::")..];
+        name = name[sizeof("predef::")..];
       }
       name = Parser.encode_html_entities(name);
 #ifdef NO_SVG
       if (ref == this_ref) {
-	name = "<b style='font-family:courier;'>" + name + "</b>";
+        name = "<b style='font-family:monospace;'>" + name + "</b>";
       } else if (refs[ref]) {
-	name = create_reference(make_filename(), ref, name);
+        name = create_reference(make_filename(), ref, name);
       } else {
-	name = "<span style='font-family:courier;'>" + name + "</span>";
+        name = "<span style='font-family:monospace;'>" + name + "</span>";
       }
 #else
       if (ref == this_ref) {
-	name = "<tspan style='font-family:courier; font-weight:bold;'>" +
-	  name + "</tspan>";
+        name = "<tspan style='font-family:monospace; font-weight:bold;'>" +
+          name + "</tspan>";
       } else if (refs[ref]) {
-	name = create_reference(make_filename(), ref, name, "xlink:");
+        name = create_reference(make_filename(), ref, name, "xlink:");
       } else {
-	name = "<tspan style='font-family:courier;'>" + name + "</tspan>";
+        name = "<tspan style='font-family:monospace;'>" + name + "</tspan>";
       }
 #endif
       names[ref] = name;
@@ -1082,7 +970,7 @@ class Node
 
     foreach(forward_deps; string ref; multiset(string) deps) {
       if (!sizeof(deps)) {
-	pq->push(priorities[ref], ref);
+        pq->push(priorities[ref], ref);
       }
     }
 
@@ -1092,14 +980,13 @@ class Node
     contents->add("<pre style='margin-left:40px;'>\n");
 #else
     // FIXME: Why isn't height=100% good enough for Firefox?
-    contents->add(sprintf("<svg"
-			  " xmlns='http://www.w3.org/2000/svg'"
-			  " version='1.1'"
-			  " xmlns:xlink='http://www.w3.org/1999/xlink'"
-			  " xml:space='preserve'"
-			  " style='margin-left:40px;'"
-			  " width='100%%' height='%dpx'>\n",
-			  (sizeof(references) + sizeof(children))*20 + 5));
+    contents->add(sprintf("<div class='inheritance-graph'><svg"
+                          " xmlns='http://www.w3.org/2000/svg'"
+                          " version='1.1'"
+                          " xmlns:xlink='http://www.w3.org/1999/xlink'"
+                          " xml:space='preserve'"
+                          " width='100%%' height='%dpx'>\n",
+                          (sizeof(references) + sizeof(children))*20 + 5));
 #endif
 
     int pos;
@@ -1114,86 +1001,86 @@ class Node
       ystart[pos] = pos * 20 + 25;
       multiset(int) inherit_positions = (<>);
       if (n) {
-	foreach(n->inherits, array(string) entry) {
-	  inherit_positions[positions[entry[2]||entry[1]]] = 1;
-	}
+        foreach(n->inherits, array(string) entry) {
+          inherit_positions[positions[entry[2]||entry[1]]] = 1;
+        }
       }
 
 #ifdef NO_SVG
       if (pos) {
-	for(int i = 0; i < pos; i++) {
-	  if (sizeof(backward_deps[rev_positions[i]])) {
-	    contents->add("&nbsp;|&nbsp;&nbsp;");
-	  } else {
-	    contents->add("&nbsp;&nbsp;&nbsp;&nbsp;");
-	  }
-	}
-	contents->add("\n");
-	int got;
-	for(int i = 0; i < pos; i++) {
-	  if (got) {
-	    contents->add("-");
-	  } else {
-	    contents->add("&nbsp;");
-	  }
-	  if (inherit_positions[i]) {
-	    contents->add("+--");
-	    got++;
-	    backward_deps[rev_positions[i]][ref] = 0;
-	  } else if (got) {
-	    contents->add("---");
-	  } else if (sizeof(backward_deps[rev_positions[i]])) {
-	    contents->add("|&nbsp;&nbsp;");
-	  } else {
-	    contents->add("&nbsp;&nbsp;&nbsp;");
-	  }
-	}
+        for(int i = 0; i < pos; i++) {
+          if (sizeof(backward_deps[rev_positions[i]])) {
+            contents->add("&nbsp;|&nbsp;&nbsp;");
+          } else {
+            contents->add("&nbsp;&nbsp;&nbsp;&nbsp;");
+          }
+        }
+        contents->add("\n");
+        int got;
+        for(int i = 0; i < pos; i++) {
+          if (got) {
+            contents->add("-");
+          } else {
+            contents->add("&nbsp;");
+          }
+          if (inherit_positions[i]) {
+            contents->add("+--");
+            got++;
+            backward_deps[rev_positions[i]][ref] = 0;
+          } else if (got) {
+            contents->add("---");
+          } else if (sizeof(backward_deps[rev_positions[i]])) {
+            contents->add("|&nbsp;&nbsp;");
+          } else {
+            contents->add("&nbsp;&nbsp;&nbsp;");
+          }
+        }
       }
       contents->add(names[ref], "\n");
 #else
       if (pos) {
-	int got;
-	for(int i = 0; i < pos; i++) {
-	  if (inherit_positions[i]) {
-	    if (!got) {
-	      // Draw the horizontal line.
-	      contents->
-		add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
-			    i*40 + 4, pos*20 + 15,
-			    pos*40 - 5, pos*20 + 15));
-	    }
-	    got++;
-	    backward_deps[rev_positions[i]][ref] = 0;
-	    if (!sizeof(backward_deps[rev_positions[i]])) {
-	      // Draw the inherit line.
-	      contents->
-		add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
-			    i*40 + 5, ystart[i],
-			    i*40 + 5, pos*20 + 16));
-	    }
-	  } else if (got && sizeof(backward_deps[rev_positions[i]])) {
-	    // We have to jump over the line!
-	    contents->
-	      add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
-			  i*40 + 5, ystart[i],
-			  i*40 + 5, pos*20 + 12));
-	    ystart[i] = pos*20 + 18;
-	  }
-	}
+        int got;
+        for(int i = 0; i < pos; i++) {
+          if (inherit_positions[i]) {
+            if (!got) {
+              // Draw the horizontal line.
+              contents->
+                add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
+                            i*40 + 4, pos*20 + 15,
+                            pos*40 - 5, pos*20 + 15));
+            }
+            got++;
+            backward_deps[rev_positions[i]][ref] = 0;
+            if (!sizeof(backward_deps[rev_positions[i]])) {
+              // Draw the inherit line.
+              contents->
+                add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
+                            i*40 + 5, ystart[i],
+                            i*40 + 5, pos*20 + 16));
+            }
+          } else if (got && sizeof(backward_deps[rev_positions[i]])) {
+            // We have to jump over the line!
+            contents->
+              add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
+                          i*40 + 5, ystart[i],
+                          i*40 + 5, pos*20 + 12));
+            ystart[i] = pos*20 + 18;
+          }
+        }
       }
       contents->add(sprintf("<text x='%d' y='%d'>%s</text>\n",
-			    pos*40, pos*20 + 20,
-			    names[ref]));
+                            pos*40, pos*20 + 20,
+                            names[ref]));
 #endif
       pos++;
 
       foreach(backward_deps[ref] || (<>); string dep_ref;) {
-	multiset(string) refs = forward_deps[dep_ref];
-	refs[ref] = 0;
-	if (!sizeof(refs)) {
-	  // All dependencies satisfied.
-	  pq->push(priorities[dep_ref], dep_ref);
-	}
+        multiset(string) refs = forward_deps[dep_ref];
+        refs[ref] = 0;
+        if (!sizeof(refs)) {
+          // All dependencies satisfied.
+          pq->push(priorities[dep_ref], dep_ref);
+        }
       }
     }
 
@@ -1202,23 +1089,23 @@ class Node
       int ppos = sizeof(closure) - 1;
 #ifdef NO_SVG
       foreach(sort(children->raw_class_path()), string ref) {
-	contents->add("&nbsp;&nbsp;&nbsp;&nbsp;"*ppos,
-		      "&nbsp;|&nbsp;&nbsp;&nbsp;\n");
-	contents->add("&nbsp;&nbsp;&nbsp;&nbsp;"*ppos,
-		      "&nbsp;+--",
-		      names[ref], "\n");
+        contents->add("&nbsp;&nbsp;&nbsp;&nbsp;"*ppos,
+                      "&nbsp;|&nbsp;&nbsp;&nbsp;\n");
+        contents->add("&nbsp;&nbsp;&nbsp;&nbsp;"*ppos,
+                      "&nbsp;+--",
+                      names[ref], "\n");
       }
 #else
       contents->add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
-			    ppos*40 + 5, ystart[ppos],
-			    ppos*40 + 5, (ppos + sizeof(children))*20 + 16));
+                            ppos*40 + 5, ystart[ppos],
+                            ppos*40 + 5, (ppos + sizeof(children))*20 + 16));
       foreach(sort(children->raw_class_path()); int i; string ref) {
-	contents->add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
-			      ppos*40 + 4, (ppos + i)*20 + 35,
-			      ppos*40 + 35, (ppos + i)*20 + 35,));
-	contents->add(sprintf("<text x='%d' y='%d'>%s</text>\n",
-			      ppos*40 + 40, (ppos + i)*20 + 40,
-			      names[ref]));
+        contents->add(sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' />\n",
+                              ppos*40 + 4, (ppos + i)*20 + 35,
+                              ppos*40 + 35, (ppos + i)*20 + 35,));
+        contents->add(sprintf("<text x='%d' y='%d'>%s</text>\n",
+                              ppos*40 + 40, (ppos + i)*20 + 40,
+                              names[ref]));
       }
 #endif
     }
@@ -1226,7 +1113,7 @@ class Node
 #ifdef NO_SVG
     contents->add("</pre>\n");
 #else
-    contents->add("</svg>\n");
+    contents->add("</svg></div>\n");
 #endif
   }
 
@@ -1267,9 +1154,9 @@ class Node
   {
     String.Buffer res = String.Buffer(3500);
     foreach(children, Node node)
-      res->add("&nbsp;<a href='", make_link(node, extra_levels), "'>",
-	       Parser.encode_html_entities(node->name),
-	       "()</a><br />\n");
+      res->add("<li><a href='", make_link(node, extra_levels), "'>",
+               Parser.encode_html_entities(node->name),
+               "()</a></li>\n");
     return (string)res;
   }
 
@@ -1280,19 +1167,13 @@ class Node
     string contents = "";
 
     foreach(({ enum_children, directive_children, method_children }),
-	    array(Node) children) {
+            array(Node) children)
+    {
 
       if (children && sizeof(children)) {
-	if (sizeof(contents)) {
-	  contents += "<tr><td colspan='4'><hr /></td></tr>\n";
-	}
-
-	contents += "<tr>\n";
-	foreach(children/( sizeof(children)/4.0 ), array(Node) children) {
-	  contents += "<td nowrap='nowrap' valign='top'>" +
-	    make_link_list(children, extra_levels) + "</td>";
-	}
-	contents += "</tr>\n";
+        foreach(children/( sizeof(children)/4.0 ), array(Node) children) {
+          contents += make_link_list(children, extra_levels);
+        }
       }
     }
 
@@ -1304,9 +1185,9 @@ class Node
     string contents = low_make_index_page(extra_levels);
     if (sizeof(contents)) {
       contents =
-	"<nav><table class='sidebar' style='width:100%;'>\n" +
-	contents +
-	"</table></nav>";
+        "<nav><ul class='multicol'>\n" +
+        contents +
+        "</ul></nav>";
     }
     return contents;
   }
@@ -1340,24 +1221,27 @@ class Node
       int num_segments = sizeof(index/"/")-1;
       string extra_prefix = "../"*num_segments;
       string style = low_make_link("style.css", 1);
+      string script = low_make_link("site.js", 1);
       string imagedir = low_make_link(low_image_prefix(), 1);
 
       index_html =
-	replace(template,
-		(["$navbar$": make_classic_navbar(1),
-		  "$contents$": index_html,
-		  "$prev_url$": "",
-		  "$prev_title$": "",
-		  "$next_url$": "",
-		  "$next_title$": "",
-		  "$type$": String.capitalize("Index of " + type),
-		  "$title$": _Roxen.html_encode_string(make_class_path(1)),
-		  "$style$": style,
-		  "$dotdot$": extra_prefix,
-		  "$imagedir$":imagedir,
-		  "$filename$": _Roxen.html_encode_string(index),
-		  "$extra_headers$": "<meta charset='utf-8' />\n",
-		]));
+        replace(template,
+                (["$navbar$": make_classic_navbar(1),
+                  "$contents$": index_html,
+                  "$prev_url$": "",
+                  "$prev_title$": "",
+                  "$next_url$": "",
+                  "$next_title$": "",
+                  "$type$": String.capitalize("Index of " + type),
+                  "$title$": _Roxen.html_encode_string(make_class_path(1)),
+                  "$style$": style,
+                  "$script$": script,
+                  "$dotdot$": extra_prefix,
+                  "$imagedir$":imagedir,
+                  "$filename$": _Roxen.html_encode_string(index),
+                  "$extra_headers$": "",
+                  "$extra_footer$": ""
+                ]));
 
       if (exporter) {
         exporter->filemodify(Git.MODE_FILE, path + "/" + index);
@@ -1377,6 +1261,7 @@ class Node
 
     int num_segments = sizeof(make_filename()/"/")-1;
     string style = ("../"*num_segments)+"style.css";
+    string script = ("../"*num_segments)+"site.js";
     extra_prefix = "../"*num_segments;
 
     Node prev = find_prev_node();
@@ -1392,47 +1277,44 @@ class Node
     }
 
     string extra_headers =
-      "<meta charset='utf-8' />\n" +
       sprintf("<style type='text/css'>\n"
-	      "svg line { stroke:#343434; stroke-width:2; }\n"
-	      "svg text { fill:#343434; }\n"
-	      "svg a { fill:#0768b2; text-decoration: underline; }\n"
-	      "</style>\n") +
-      sprintf("<script language='javascript'>\n"
-	      "var current = %s;\n"
-	      "</script>\n",
-	      replace(encode_json(([ "name":name,
-				     "link":make_filename()
-				  ])),
+              "svg line { stroke:#343434; stroke-width:2; }\n"
+              "svg text { fill:#343434; }\n"
+              "svg a { fill:#0768b2; text-decoration: underline; }\n"
+              "</style>\n");
+
+    string extra_footer =
+      sprintf("<script>"
+              "PikeDoc.current = %s;"
+              "</script>\n",
+              replace(encode_json(([ "name":name,
+                                     "link":make_filename()
+                                  ])),
                       ({ "&", "<", ">" }), ({ "&amp;", "&lt;", "&gt;" }))) +
-      sprintf("<script language='javascript' src='%s'>\n"
-	      "</script>\n",
-	      low_make_link("navigation.js")) +
-      sprintf("<script language='javascript' src='%s'>\n"
-	      "</script>\n",
-	      low_make_link(make_parent_index_filename() + ".js")) +
-      sprintf("<script language='javascript'>\n"
-	      "siblings = children;\n"
-	      "clear_children();\n"
-	      "</script>\n") +
-      sprintf("<script language='javascript' src='%s'>\n"
-	      "</script>\n",
-	      low_make_link(make_load_index_filename()));
+      sprintf("<script src='%s'>"
+              "</script>\n",
+              low_make_link(make_parent_index_filename() + ".js")) +
+      sprintf("<script src='%s'>"
+              "</script>",
+              low_make_link(make_load_index_filename()));
+
 
     string res = replace(template,
       (["$navbar$": make_navbar(),
-	"$contents$": make_content(),
-	"$prev_url$": prev_url,
-	"$prev_title$": _Roxen.html_encode_string(prev_title),
-	"$next_url$": next_url,
-	"$next_title$": _Roxen.html_encode_string(next_title),
-	"$type$": String.capitalize(type),
-	"$title$": _Roxen.html_encode_string(make_class_path(1)),
-	"$style$": style,
-	"$dotdot$": extra_prefix,
-	"$imagedir$":image_prefix(),
-	"$filename$": _Roxen.html_encode_string(make_filename()),
-	"$extra_headers$": extra_headers,
+        "$contents$": make_content(),
+        "$prev_url$": prev_url,
+        "$prev_title$": _Roxen.html_encode_string(prev_title),
+        "$next_url$": next_url,
+        "$next_title$": _Roxen.html_encode_string(next_title),
+        "$type$": String.capitalize(type),
+        "$title$": _Roxen.html_encode_string(make_class_path(1)),
+        "$style$": style,
+        "$script$": script,
+        "$dotdot$": extra_prefix,
+        "$imagedir$":image_prefix(),
+        "$filename$": _Roxen.html_encode_string(make_filename()),
+        "$extra_headers$": extra_headers,
+        "$extra_footer$": extra_footer
       ]));
 
     if (exporter) {
@@ -1458,14 +1340,17 @@ class TopNode {
   string make_index_js()
   {
     string res = ::make_index_js();
+    res -= "\n.finish();";
 
-#define LOW_MAKE_INDEX_JS(CHILDREN) do {				\
-      res += low_make_index_js(#CHILDREN, CHILDREN);			\
+#define LOW_MAKE_INDEX_JS(CHILDREN) do {                                \
+      res += low_make_index_js2(((#CHILDREN)/"_")[0], CHILDREN); \
     } while (0)
 
     LOW_MAKE_INDEX_JS(namespace_children);
     LOW_MAKE_INDEX_JS(appendix_children);
 
+    res += ".finish();";
+
     return res;
   }
 
@@ -1474,22 +1359,22 @@ class TopNode {
     mapping m = localtime(time());
     timestamp = sprintf("%4d-%02d-%02d", m->year+1900, m->mon+1, m->mday);
     pending_inherits = ADT.Stack();
-    pending_inherits->push(0);	// End sentinel.
+    pending_inherits->push(0);  // End sentinel.
     Parser.HTML parser = Parser.HTML();
     parser->case_insensitive_tag(1);
     parser->xml_tag_syntax(3);
     parser->add_container("manual",
-			  lambda(Parser.HTML p, mapping args, string c) {
-			    if (args->version)
-			      pike_version = args->version;
-			    if (args["time-stamp"])
-			      timestamp = args["time-stamp"];
-			    return UNDEFINED;
-			  });
+                          lambda(Parser.HTML p, mapping args, string c) {
+                            if (args->version)
+                              pike_version = args->version;
+                            if (args["time-stamp"])
+                              timestamp = args["time-stamp"];
+                            return UNDEFINED;
+                          });
     parser->add_container("autodoc",
-			  lambda(Parser.HTML p, mapping args, string c) {
-			    return ({ c });
-			  });
+                          lambda(Parser.HTML p, mapping args, string c) {
+                            return ({ c });
+                          });
 
     _data = parser->finish(_data)->read();
     ::create("autodoc", "", _data);
@@ -1497,14 +1382,14 @@ class TopNode {
     sort(appendix_children->name, appendix_children);
     foreach(namespace_children, Node x)
       if(x->type=="namespace" && x->name==default_namespace) {
-	//	namespace_children -= ({ x });
-	class_children += x->class_children;
-	module_children += x->module_children;
-	enum_children += x->enum_children;
-	directive_children += x->directive_children;
-	method_children += x->method_children;
-	operator_children += x->operator_children;
-	member_children += x->member_children;
+        //      namespace_children -= ({ x });
+        class_children += x->class_children;
+        module_children += x->module_children;
+        enum_children += x->enum_children;
+        directive_children += x->directive_children;
+        method_children += x->method_children;
+        operator_children += x->operator_children;
+        member_children += x->member_children;
       }
 
     array(string|Node) inh;
@@ -1512,7 +1397,7 @@ class TopNode {
       [string ref, Node child] = inh;
       Node parent = refs[ref];
       if (parent) {
-	parent->children += ({ child });
+        parent->children += ({ child });
       }
     }
     type = "autodoc";
@@ -1534,9 +1419,9 @@ class TopNode {
   string make_class_path(void|int(0..1) header) {
     if(header && (sizeof(method_children) + sizeof(directive_children) + sizeof(operator_children))) {
       if(default_namespace)
-	return "namespace "+default_namespace;
+        return "namespace "+default_namespace;
       else
-	return "Namespaces";
+        return "Namespaces";
     }
     return "";
   }
@@ -1549,9 +1434,9 @@ class TopNode {
     string res = ::make_classic_navbar(extra_levels);
 
     res += low_make_classic_navbar(namespace_children, "Namespaces",
-				   extra_levels);
+                                   extra_levels);
     res += low_make_classic_navbar(appendix_children, "Appendices",
-				   extra_levels);
+                                   extra_levels);
 
     return res;
   }
@@ -1565,12 +1450,12 @@ class TopNode {
   {
     string contents = ::low_make_index_page(extra_levels);
     string doc = parse_children(Parser.XML.Tree.parse_input(data),
-				"docgroup", parse_docgroup, 1);
+                                "docgroup", parse_docgroup, 1);
 
     if (sizeof(doc)) {
       doc = "<tr><td colspan='4' nowrap='nowrap'>" + doc + "</td></tr>\n";
       if (sizeof(contents)) {
-	contents += "<tr><td colspan='4'><hr /></td></tr>\n";
+        contents += "<tr><td colspan='4'><hr /></td></tr>\n";
       }
     }
     return contents + doc;
@@ -1584,13 +1469,6 @@ class TopNode {
 
   void make_html(string template, string path, Git.Export|void exporter) {
     PROFILE();
-    if (exporter) {
-      exporter->filemodify(Git.MODE_FILE, path + "/navigation.js");
-      exporter->data(string_to_utf8(navigation_js));
-    } else {
-      Stdio.mkdirhier(path);
-      Stdio.write_file(path + "/navigation.js", string_to_utf8(navigation_js));
-    }
     appendix_children->make_html(template, path, exporter);
     namespace_children->make_html(template, path, exporter);
     ::make_html(template, path, exporter);
@@ -1599,7 +1477,7 @@ class TopNode {
 }
 
 int low_main(string doc_file, string template_file, string outdir,
-	     Git.Export|void exporter)
+             Git.Export|void exporter)
 {
   PROFILE();
   if (verbosity >= Tools.AutoDoc.FLAG_VERBOSE)
@@ -1622,41 +1500,41 @@ int low_main(string doc_file, string template_file, string outdir,
     werror("Splitting to destination directory %s...\n", outdir);
 
   TopNode top = TopNode(doc);
-  if (flags & Tools.AutoDoc.FLAG_NO_DYNAMIC) {
-    // Attempt to keep down the number of changed files by
-    // using a client-sice include for the version and date.
-    string pike_version_js =
-      sprintf("document.write(%q);\n", top->pike_version);
-    string timestamp_js =
-      sprintf("document.write(%q);\n",
-	      sprintf("<time pubdate=''>%s</time>", top->timestamp));
-    if (exporter) {
-      exporter->filemodify(Git.MODE_FILE, outdir + "/pike_version.js");
-      exporter->data(pike_version_js);
-      exporter->filemodify(Git.MODE_FILE, outdir + "/timestamp.js");
-      exporter->data(timestamp_js);
-    } else {
-      Stdio.mkdirhier(outdir);
-      Stdio.write_file(outdir + "/pike_version.js", pike_version_js);
-      Stdio.write_file(outdir + "/timestamp.js", timestamp_js);
-    }
 
-    // Reduce updating of all files to once a year and when the language
-    // changes name.
-    string product_name = "Pike";
-    sscanf(top->pike_version, "%[^0-9 _]", product_name);
-    int year = localtime(time())->year + 1900;
-    sscanf(top->timestamp, "%d-", year);
+  string js_constants = sprintf(
+    "PikeDoc.VERSION = '%s';\n"
+    "PikeDoc.PUBDATE = '%s';\n"
+    "PikeDoc.GENERATED = %d;\n",
+    top->pike_version,
+    top->timestamp,
+    time());
+
+  if (exporter) {
+    exporter->filemodify(Git.MODE_FILE, outdir + "/constants.js");
+    exporter->data(js_constants);
+  } else {
+    Stdio.mkdirhier(outdir);
+    Stdio.write_file(outdir + "/constants.js", js_constants);
+  }
 
+  if (flags & Tools.AutoDoc.FLAG_NO_DYNAMIC) {
+    // Attempt to keep down the number of changed files by
+    // using a client-side include for the version and date.
     template = replace(template,
-		       ([ "$version$":"<script type='text/javascript' src='$dotdot$pike_version.js' ></script><noscript>" + product_name + "</noscript>",
-			  "$date$":"<script type='text/javascript' src='$dotdot$timestamp.js' ></script><noscript>" + year + "</noscript>",
-		       ]) );
+                       ([ "$constants$":"<script src='$dotdot$constants.js'></script>",
+                          "$version$":"",
+                          "$date$":"",
+                          "$generated$":"",
+                          "$nodynamic$":""
+                       ]) );
   } else {
     template = replace(template,
-		       ([ "$version$":top->pike_version,
-			  "$date$":top->timestamp,
-		       ]) );
+                       ([ "$constants$":"<script src='$dotdot$constants.js'></script>",
+                          "$version$":top->pike_version,
+                          "$date$":top->timestamp,
+                          "$generated$":time()+"",
+                          "$nodynamic$":"<script>PikeDoc.NO_DYNAMIC = false;</script>"
+                       ]) );
   }
 
   if (flags & Tools.AutoDoc.FLAG_COMPAT) {
@@ -1665,27 +1543,33 @@ int low_main(string doc_file, string template_file, string outdir,
     // The canonic Pike site has moved from
     // pike.roxen.com to pike.ida.liu.se to pike.lysator.liu.se.
     template = replace(template,
-		       ({ "pike.roxen.com", "pike.ida.liu.se" }),
-		       ({ "pike.lysator.liu.se", "pike.lysator.liu.se" }));
+                       ({ "pike.roxen.com", "pike.ida.liu.se" }),
+                       ({ "pike.lysator.liu.se", "pike.lysator.liu.se" }));
 
     // These first two affect commits prior to and including 7.3.11.
     template = replace(template,
-		       "<img src=\"images/",
-		       "<img src=\"$imagedir$");
+                       "<img src=\"images/",
+                       "<img src=\"$imagedir$");
     template = replace(template,
-		       "<td background=\"images/",
-		       "<td background=\"$imagedir$");
+                       "<td background=\"images/",
+                       "<td background=\"$imagedir$");
 
     // This one however affects quite a few more.
     template = replace(template,
-		       ({ "$dotdot$/images/" }),
-		       ({ "$imagedir$" }));
+                       ({ "$dotdot$/images/" }),
+                       ({ "$imagedir$" }));
 
     if (!has_value(template, "$extra_headers$")) {
       template = replace(template,
-			 ({ "<head>" }),
-			 ({ "<head>\n"
-			    "$extra_headers$" }));
+                         ({ "<head>" }),
+                         ({ "<head>\n"
+                            "$extra_headers$" }));
+    }
+    if (!has_value(template, "$extra_footer$")) {
+      template = replace(template,
+                         ({ "</html>" }),
+                         ({ "$extra_footer$\n"
+                            "</html>" }));
     }
   }
 
@@ -1698,7 +1582,7 @@ int low_main(string doc_file, string template_file, string outdir,
   if (verbosity >= Tools.AutoDoc.FLAG_NORMAL) {
     werror("%d unresolved references.\n", unresolved);
     werror("%d documented constants/variables/functions/classes/modules.\n",
-	   sizeof(refs));
+           sizeof(refs));
   }
   return 0;
 }
@@ -1714,8 +1598,8 @@ int main(int argc, array(string) argv)
     switch(opt[0]) {
     case "verbose":
       if (verbosity < Tools.AutoDoc.FLAG_DEBUG) {
-	verbosity += 1;
-	flags = (flags & ~Tools.AutoDoc.FLAG_VERB_MASK) | verbosity;
+        verbosity += 1;
+        flags = (flags & ~Tools.AutoDoc.FLAG_VERB_MASK) | verbosity;
       }
       break;
     case "quiet":
@@ -1724,8 +1608,8 @@ int main(int argc, array(string) argv)
       break;
     case "help":
       write("pike -x autodoc_to_split_html [-v|--verbose] [-q|--quiet]\n"
-	    "\t[--help] <input-file> <template-file> <output-dir>"
-	    " [<namespace>]\n");
+            "\t[--help] <input-file> <template-file> <output-dir>"
+            " [<namespace>]\n");
       return 0;
     case "compat":
       flags |= Tools.AutoDoc.FLAG_COMPAT;
@@ -1734,9 +1618,9 @@ int main(int argc, array(string) argv)
   argv = Getopt.get_args(argv)[1..];
   if(sizeof(argv)<4) {
     werror("Too few arguments.\n"
-	   "pike -x autodoc_to_split_html [-v|--verbose] [-q|--quiet]\n"
-	   "\t[--help] <input-file> <template-file> <output-dir>"
-	   " [<namespace>]\n");
+           "pike -x autodoc_to_split_html [-v|--verbose] [-q|--quiet]\n"
+           "\t[--help] <input-file> <template-file> <output-dir>"
+           " [<namespace>]\n");
     return 1;
   }
   if(sizeof(argv)>3) default_namespace=argv[3];
diff --git a/lib/modules/Tools.pmod/Standalone.pmod/pike_to_html.pike b/lib/modules/Tools.pmod/Standalone.pmod/pike_to_html.pike
new file mode 100644
index 0000000000..f9099a99a6
--- /dev/null
+++ b/lib/modules/Tools.pmod/Standalone.pmod/pike_to_html.pike
@@ -0,0 +1,324 @@
+#pike __REAL_VERSION__
+
+//! Convert Pike code to HTML with syntax highlighting
+//!
+//! @code
+//! pike -x pike_to_html /path/to/file.pike > file.html
+//! @endcode
+
+constant description = "Pike code to syntax highlighted HTML converter";
+
+constant HELP = #"
+Converts either a string of code or a Pike file into syntax highlighted HTML.
+The generated HTML will be written to stdout.
+
+Usage:
+  pike -x pike_to_html \"path to file or string of code\"
+";
+
+string delimiters = ",;:.>-+=()|[]&%#!<>^~*/`{}\\";
+string res_words = "if|else|while|for|foreach|do|return|continue|break|"
+                   "switch|case|default|goto|catch|lambda|gauge|inherit|import";
+string type = "enum|float|int|typedef|void|object|class|mapping|string|"
+              "array|multiset|mixed|function|program|bool|auto";
+string modifiers = "public|protected|private|static|constant|local|final|"
+                   "optional|variant|inline";
+string constants  = "UNDEFINED|__LINE__|__FILE__|__DIR__|__func__|"
+                    "__VERSION__|__MAJOR__|__MINOR__|__BUILD__|"
+                    "__REAL_VERSION__|__REAL_MAJOR__|__REAL_MINOR__|"
+                    "__REAL_BUILD__|__DATE__|__TIME__|__AUTO_BIGNUM__|__NT__|"
+                    "__PIKE__|__amigaos__|true|false|this|this_program";
+string known_macros = "if|ifdef|define|elif|else|endif|pike|require|include|"
+                      "pragma";
+
+string namespaces = #"ADT
+Apple
+Arg
+Array
+Audio
+Builtin
+Bz2
+Cache
+Calendar
+Charset
+Colors
+CommonLog
+Concurrent
+Crypto
+DVB
+Debug
+DefaultCompilerEnvironment
+Error
+Filesystem
+Float
+Function
+Fuse
+GDK
+GDK2
+GL
+GLU
+GLUE
+GLUT
+GSSAPI
+GTK
+GTK2
+Gdbm
+Geography
+Getopt
+Git
+Gmp
+Gnome2
+Graphics
+Gz
+HPack
+HTTPLoop
+Image
+Int
+Java
+Languages
+Local
+Locale
+MIME
+Mapping
+Math
+Msql
+Multiset
+Mysql
+NetUtils
+Nettle
+Object
+Odbc
+PDF
+Pango
+Parser
+Pike
+Pipe
+Postgres
+Process
+Program
+Protocols
+Regexp
+Remote
+SANE
+SDL
+SSL
+Search
+Serializer
+Shuffler
+Sql
+Standards
+Stdio
+String
+System
+Thread
+Tools
+Unicode
+VCDiff
+Val
+Web
+Yabu
+Yp
+ZXID
+_Ffmpeg
+__builtin";
+
+protected multiset(string) delims, reserved, types, consts, ns, mods, macros;
+
+final int(0..1) main(int argc, array(string) argv)
+{
+  if (argc == 1) {
+    werror("Missing argument.%s\n", HELP);
+    return 1;
+  }
+
+  string h = #"<!doctype html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <title>%s</title>
+    <style>
+      html, body { font-family: sans-serif; font-size: 100%%; }
+      pre { font-family: menlo, monospace; font-size: .8rem; }
+      .comment { color: #999; }
+      .type { color: #00007B; font-weight: bold; }
+      .string { color: #037F00; }
+      .macro { color: #B04700; font-weight: bold; }
+      .lang, .const, .mod { color: #863069; font-weight: bold; }
+      .const { color: #0000ff; }
+      .delim { color: #00008e; }
+      .ns { font-weight: bold; }
+      .nested { opacity: .7; transition: opacity .2s ease-in; }
+      .nested:hover { opacity: 1; }
+    </style>
+  </head>
+  <body>
+    <pre lang='pike'>%s</pre>
+  </body>
+</html>";
+
+  //string code = Stdio.exist(argv[1]) ? Stdio.read_file(argv[1]) : argv[1];
+
+  string code, title;
+
+  if (Stdio.is_file(argv[1])) {
+    code = Stdio.read_file(argv[1]);
+    title = basename(argv[1]);
+  }
+  else {
+    code = argv[1];
+    title = "Pike code";
+  }
+
+  write(sprintf(h, title, convert(code)));
+  return 0;
+}
+
+//! Turn @[code] into HTML.
+//!
+//! The following css classes will be used:
+//!
+//! @ul
+//!  @item
+//!   Delimiters:        delim
+//!  @item
+//!   Reserved words:    lang
+//!  @item
+//!   Data types:        type
+//!  @item
+//!   Constants:         const
+//!  @item
+//!   Modifiers:         mods
+//!  @item
+//!   Root namespaces:   ns
+//!  @item
+//!   Strings:           string
+//!  @item
+//!   Comments:          comment
+//!  @item
+//!   Macros:            macro
+//! @endul
+//!
+//! @param code
+string convert(string code)
+{
+  delims   = (multiset)(delimiters/1);
+  reserved = (multiset)(res_words/"|");
+  types    = (multiset)(type/"|");
+  consts   = (multiset)(constants/"|");
+  ns       = (multiset)(namespaces/"\n");
+  mods     = (multiset)(modifiers/"|");
+  macros   = (multiset)(known_macros/"|");
+
+  return make_html(Parser.Pike.split(code));
+}
+
+#define ADDTAG(TYP) add("<span class='" + TYP + "'>" +  \
+                        replace(tok, ([ "&" : "&amp;",  \
+                                        "<" : "&lt;",   \
+                                        ">" : "&gt;" ])) + "</span>")
+#define ADD() add(replace(tok, ([ "&" : "&amp;", "<" : "&lt;", ">" : "&gt;" ])))
+
+protected string first_non_white(array(string) s)
+{
+  for (int i; i < sizeof(s); i++) {
+    if (!(< " ", "\t", "\n" >)[s[i]])
+      return s[i];
+  }
+}
+
+protected string make_html(array(string) tokens)
+{
+  String.Buffer buf = String.Buffer();
+  function add = buf->add;
+
+  tokens = ({ 0 }) + tokens + ({ "  ", "  " });
+
+  int i;
+  int len = sizeof(tokens) - 2;
+
+  for (i = 1; i < len; i++) {
+    string tok = tokens[i];
+
+    if (delims[tok]) {
+      ADDTAG("delim");
+    }
+    else if (mods[tok]) {
+      ADDTAG("mod");
+    }
+    else if (reserved[tok]) {
+      ADDTAG("lang");
+    }
+    else if (types[tok]) {
+      ADDTAG("type");
+    }
+    else if (consts[tok]) {
+      ADDTAG("const");
+    }
+    else if (ns[tok]) {
+      ADDTAG("ns");
+    }
+    else {
+      if (sizeof(tok) > 1) {
+        switch (tok[0])
+        {
+          case '\'':
+            /* fallthrough */
+          case '"':
+            ADDTAG("string");
+            break;
+
+          case '/':
+            ADDTAG("comment");
+            break;
+
+          case '#':
+            if (tok[1] == '"') {
+              ADDTAG("string");
+            }
+            else {
+              array(string) ntoks = Parser.Pike.split(tok[1..]);
+
+              if (!macros[first_non_white(ntoks)]) {
+                add("#", make_html(ntoks));
+                break;
+              }
+
+              tok = "#" + ntoks[0];
+              ADDTAG("macro");
+
+              if (ntoks[-1] == "\n")
+                ntoks = ntoks[..<1];
+
+              if (sizeof(ntoks) > 2 && (< "<", "\"" >)[ntoks[2]]) {
+                tok = ntoks[2..]*"";
+                add(ntoks[1]);
+                ADDTAG("string");
+              }
+              else if (ntoks[0] == "!") {
+                tok = ntoks[1..]*"";
+                ADDTAG("macro");
+              }
+              else if (sizeof(ntoks) > 1) {
+                tok = "";
+                if (ntoks[-1][-1] == '\n' && tokens[i+1] == "\n") {
+                  ntoks[-1] = ntoks[-1][..<1];
+                }
+                add(make_html(ntoks[1..]));
+              }
+            }
+
+            break;
+
+          default:
+            ADD();
+            break;
+        }
+      }
+      else {
+        ADD();
+      }
+    }
+  }
+
+  return buf->get();
+}
diff --git a/refdoc/Makefile b/refdoc/Makefile
index d2d23d2de5..4a453e5c51 100644
--- a/refdoc/Makefile
+++ b/refdoc/Makefile
@@ -4,73 +4,62 @@
 # Henrik Grubbstr�m 2001-02-02
 #
 
+# make devel can be used if changes are made only to the CSS or JS and you
+# don't feel like recompiling the entire doc to test the changes
+
 BUILDDIR=
 DESTDIR=
 PIKE=pike
 
 all: modref traditional
 
-pike.ida.liu.se: modref pelix_modref traditional
-
-caudium.net: modref caudium_modref traditional
+pike.ida.liu.se: modref traditional
 
 # These are the actual build targets for making manuals...
 
 modref: $(BUILDDIR)/modref.xml structure/modref.css structure/modref.html \
-	  presentation/make_html.pike presentation/tree-split-autodoc.pike
+	  structure/modref.js presentation/make_html.pike presentation/tree-split-autodoc.pike
 	@$(MAKE) PIKE="$(PIKE)" BUILDDIR="$(BUILDDIR)" DESTDIR="$(DESTDIR)" low_modref
 
-module_modref: $(BUILDDIR)/module_modref.xml structure/modref.css structure/module_modref.html \
-	  presentation/make_html.pike presentation/tree-split-autodoc.pike
+module_modref: $(BUILDDIR)/module_modref.xml structure/modref.css structure/modref.html \
+	  structure/modref.js presentation/make_html.pike presentation/tree-split-autodoc.pike
 	@$(MAKE) PIKE="$(PIKE)" BUILDDIR="$(BUILDDIR)" DESTDIR="$(DESTDIR)" low_module_modref
 
 low_module_modref:
 	-rm -rf $(DESTDIR)modref
 	@mkdir $(DESTDIR)modref
 	@cp structure/modref.css $(DESTDIR)modref/style.css
+	@cp structure/modref.js $(DESTDIR)modref/site.js
 	@$(PIKE) presentation/tree-split-autodoc.pike \
-	  $(BUILDDIR)/module_modref.xml structure/module_modref.html $(DESTDIR)modref predef
+	  $(BUILDDIR)/module_modref.xml structure/modref.html $(DESTDIR)modref predef
 	@mkdir $(DESTDIR)modref/images
 	-cp $(BUILDDIR)/doc_build/images/* $(DESTDIR)modref/images
-	@for file in pike_logo.gif next.gif prev.gif unit.gif \
-          pike_line_left.gif pike_line_middle.gif pike_line_right.gif ; do \
+	@for file in pike-logo.svg pike-logo.png next.gif prev.gif unit.gif \
+          pike_line_left.gif pike_line_middle.gif pike_line_right.gif \
+          eye-slash.svg; do \
 	  cp src_images/$$file $(DESTDIR)modref/images/ ; done
 
 low_modref:
 	-rm -rf $(DESTDIR)modref
 	@test -d $(DESTDIR)modref || mkdir modref
-	@cp structure/modref.css modref/style.css
+	@cp structure/modref.css $(DESTDIR)modref/style.css
+	@cp structure/modref.js $(DESTDIR)modref/site.js
 	@$(PIKE) presentation/tree-split-autodoc.pike \
 	  $(BUILDDIR)/modref.xml structure/modref.html $(DESTDIR)modref predef
 	@test -d $(DESTDIR)modref/images || mkdir $(DESTDIR)modref/images
 	-cp $(BUILDDIR)/doc_build/images/* $(DESTDIR)modref/images
-	@for file in pike_logo.gif next.gif prev.gif unit.gif \
-          pike_line_left.gif pike_line_middle.gif pike_line_right.gif ; do \
+	@for file in pike-logo.svg pike-logo.png next.gif prev.gif unit.gif \
+          pike_line_left.gif pike_line_middle.gif pike_line_right.gif \
+          eye-slash.svg; do \
 	  cp src_images/$$file $(DESTDIR)modref/images/ ; done
 
-pelix_modref: $(BUILDDIR)/modref.xml structure/pelix_modref.html \
-	        presentation/make_html.pike presentation/tree-split-autodoc.pike
-	@$(MAKE) PIKE="$(PIKE)" BUILDDIR="$(BUILDDIR)" low_pelix_modref
-
-low_pelix_modref:
-	-rm -rf pelix_modref
-	@mkdir pelix_modref
-	@$(PIKE) presentation/tree-split-autodoc.pike \
-	  $(BUILDDIR)/modref.xml structure/pelix_modref.html pelix_modref predef
-	@mkdir pelix_modref/images
-	cp $(BUILDDIR)/doc_build/images/* pelix_modref/images
-
-caudium_modref: $(BUILDDIR)/modref.xml structure/caudium_modref.html \
-		presentation/make_html.pike presentation/tree-split-autodoc.pike
-	@$(MAKE) PIKE="$(PIKE)" BUILDDIR="$(BUILDDIR)" low_caudium_modref
-
-low_caudium_modref:
-	-rm -rf caudium_modref
-	@mkdir caudium_modref
-	@$(PIKE) presentation/tree-split-autodoc.pike \
-	  $(BUILDDIR)/modref.xml structure/caudium_modref.html caudium_modref predef
-	@mkdir pelix_modref/images
-	cp $(BUILDDIR)/doc_build/images/* caudium_modref/images
+devel:
+	@cp structure/modref.css $(DESTDIR)modref/style.css
+	@cp structure/modref.js $(DESTDIR)modref/site.js
+	@for file in pike-logo.svg pike-logo.png next.gif prev.gif unit.gif \
+          pike_line_left.gif pike_line_middle.gif pike_line_right.gif \
+          eye-slash.svg; do \
+	  cp src_images/$$file $(DESTDIR)modref/images/ ; done
 
 one_page: onepage $(BUILDDIR)/onepage.xml presentation/make_html.pike
 	@$(MAKE) PIKE="$(PIKE)" BUILDDIR="$(BUILDDIR)" low_one_page
@@ -84,15 +73,17 @@ traditional: traditional_manual $(BUILDDIR)/traditional.xml presentation/make_ht
 
 low_traditional:
 	cp $(BUILDDIR)/doc_build/images/* $(DESTDIR)traditional_manual/images/
-	@$(PIKE) presentation/make_html.pike --dest=$(DESTDIR) --img=images/ $(BUILDDIR)/traditional.xml
+	cp structure/modref.css traditional_manual/modref.css
+	@$(PIKE) presentation/make_html.pike --dest=$(DESTDIR) --img=images/ \
+		--template=structure/chapters.html $(BUILDDIR)/traditional.xml
 
 # Sub targets used by the above targets.
 
 always:
 
-images: $(BUILDDIR)/doc_build/src/post_modules/GTK/refdoc/images
-	@cp ../src/post_modules/GTK/refdoc/images/*.png \
-	  $(BUILDDIR)/doc_build/src/post_modules/GTK/refdoc/images
+images: $(BUILDDIR)/doc_build/src/post_modules/GTK2/refdoc/images
+	@cp ../src/post_modules/GTK2/refdoc/images/*.png \
+	  $(BUILDDIR)/doc_build/src/post_modules/GTK2/refdoc/images
 
 # Directories
 
@@ -116,4 +107,4 @@ touch-mirardoc:
 # Cleanup
 
 clean:
-	-rm -r modref onepage traditional_manual pelix_modref autodoc.xml
+	-rm -fr modref onepage traditional_manual pelix_modref
diff --git a/refdoc/chapters/autodoc.xml b/refdoc/chapters/autodoc.xml
index fff2e2e3cb..a31522bc18 100644
--- a/refdoc/chapters/autodoc.xml
+++ b/refdoc/chapters/autodoc.xml
@@ -5,8 +5,8 @@
 <subsection title="Line orientation">
 
 <p>The markup is line oriented. If you need to write a line which is very
-long, it can be broken into several lines. A trailing @ on the line
-indicates that it continues on the next line. The @ and the newline
+long, it can be broken into several lines. A trailing <tt>@</tt> on the line
+indicates that it continues on the next line. The <tt>@</tt> and the newline
 character will be discarded, and the lines merged. Thus:</p>
 
 <example>
@@ -50,12 +50,12 @@ paragraph break. Thus:</p>
 
 <subsection title="Keywords">
 
-<p>Keywords always begin with an at-sign: @. A @ is quoted by writing two
-of them: @@. There are four types of keywords (the keywords in []'s
+<p>Keywords always begin with an at-sign: <tt>@</tt>. A <tt>@</tt> is quoted by writing two
+of them: <tt>@@</tt>. There are four types of keywords (the keywords in []'s
 are examples of keywords of the different types):</p>
 
 <ol>
-<li><p> Meta keywords [@decl, @class, @endclass, @module and @endmodule]
+<li><p> Meta keywords <tt>[@decl, @class, @endclass, @module and @endmodule]</tt>
  Must stand alone on one line, preceded only by whitespace. These are
  not really part of the markup. They must come before any text or
  other keywords in the doc block. They provide information about what
@@ -63,31 +63,31 @@ are examples of keywords of the different types):</p>
  documentation. Meta keywords have keyword specific parameter
  syntaxes.</p></li>
 
-<li><p> Delimiter keywords [@param, @member, @item, @note, ...]
+<li><p> Delimiter keywords <tt>[@param, @member, @item, @note, ...]</tt>
  Must stand alone on one line, preceded only by whitespace. These are
  keywords that begin a section inside their block. They have no end
  marker, but rather the section ends when the next delimiter keyword
  on the same level is found. Can have parameters.</p></li>
 
-<li><p> Block/endblock keywords [@dl - @enddl, @mapping - @endmapping, ...]
+<li><p> Block/endblock keywords <tt>[@dl - @enddl, @mapping - @endmapping, ...]</tt>
  Must stand alone on one line, preceded only by whitespace. These open
  or close a block. If a block is started with @foo, it must end with a
  matching @endfoo. The lines inside the block can be divided into
  sections by using delimiter keywords. The start keyword can have
  parameters, but the corresponding end keyword can not.</p></li>
 
-<li><p> Short markup keywords [@ref{..@}, @i{..@}, ...]
+<li><p> Short markup keywords <tt>[@ref{..@}, @i{..@}, ...]</tt>
  These are used in the text to perform cosmetic tasks, for example
- changing text to italic (@i), teletype(@tt) or marking a word as a
- reference to a pike entity (@ref). They can be nested, but a short
+ changing text to italic (<tt>@i</tt>), teletype(<tt>@tt</tt>) or marking a word as a
+ reference to a pike entity (<tt>@ref</tt>). They can be nested, but a short
  markup keyword can not contain a keyword of types 1-3. They begin
- with @keyword{ and end with @}.</p></li>
+ with <tt>@keyword{ and end with @}</tt>.</p></li>
 
-<li><p> The magic keyword @xml{ ... @}
+<li><p> The magic keyword <tt>@xml{ ... @}</tt>
  This is a special keyword that provides an escape to XML. All ordinary
  text inside it is passed unquoted to the output. However, the short
  markup keywords are still valid and may be used inside it, and thus
- @ must still be quoted with @@. &lt; and &gt; must also be quoted unless
+ <tt>@</tt> must still be quoted with <tt>@@</tt>. <tt>&lt;</tt> and <tt>&gt;</tt> must also be quoted unless
  the intention really is to write XML. For example:</p>
 
  <example>
@@ -120,7 +120,7 @@ consecutive lines. For example, when documenting a method:</p>
   //!   The coordinates of the vector.
 </example>
 
-<p>Above, the two @param's x and y are grouped together and share the
+<p>Above, the two <tt>@param</tt>'s x and y are grouped together and share the
 same docstring: "The coordinates of the vector.". It is an error to
 try to group together different keywords:</p>
 
@@ -135,7 +135,7 @@ try to group together different keywords:</p>
 
 <subsection title="Keyword parameters">
 
-<p>After the leading @keyword (that may be preceded only by whitespace)
+<p>After the leading <tt>@keyword</tt> (that may be preceded only by whitespace)
 on the line, the rest of the line is interpreted as a parameter list.
 The syntax of this parameter list can be different depending on the
 keyword:</p>
@@ -172,7 +172,7 @@ keyword:</p>
    //! @wrong "Aww, come on now, this worked fine in C64 basic!
 </example>
 
- <p>If a quoted parameter is too long to fit in one line, use the @ at
+ <p>If a quoted parameter is too long to fit in one line, use the <tt>@</tt> at
  the end of the line to merge it with the following:</p>
 
 <example>
@@ -198,7 +198,7 @@ keyword:</p>
 <subsection title="Grammar">
 
 <p>Here comes a BNF-ish grammar for documentation blocks. Note that
-before the parsing of the block, all lines ending with a @ will be
+before the parsing of the block, all lines ending with a <tt>@</tt> will be
 merged with the next line (see (a) above)</p>
 
 <p><pre>
@@ -297,8 +297,8 @@ the final Pike namespace.</p>
    */
 </example>
 
-<p>Note that only lines that start with *! count, so above are only two
-doc lines. Any whitespace before the leading *! is skipped, so that
+<p>Note that only lines that start with <tt>*!</tt> count, so above are only two
+doc lines. Any whitespace before the leading <tt>*!</tt> is skipped, so that
 the lines can be indented freely.</p>
 
 <p>In the C files, no parsing of the surrounding code is done. The
@@ -334,9 +334,9 @@ Pike entity the doc is about.</p>
   /*! @endmodule */
 </example>
 
-<p>The @module and @class too keywords are to work like segment
-directives in assembler source files. That is, you can have "@module
-foo" in several C files, if the module source is spread over multiple
+<p>The <tt>@module</tt> and <tt>@class</tt> too keywords are to work like segment
+directives in assembler source files. That is, you can have <tt>@module
+foo</tt> in several C files, if the module source is spread over multiple
 files. However, if you write doc for the module itself in several
 places, an error will be triggered.</p>
 
@@ -352,7 +352,7 @@ places, an error will be triggered.</p>
 </example>
 
 <p>To be considered one doc block, the comments must be separated only by
-whitespace and _one_ "\n", that is they have to be on adjacent lines
+whitespace and <em>one</em> <tt>\n</tt>, that is they have to be on adjacent lines
 in the code. Each doc block in the Pike code has one or more targets;
 the Pike entities (modules, classes, variables etc.) that the doc
 block is documenting. The target of a doc comment is the coherent
@@ -401,7 +401,7 @@ the code, without intervening blank lines. Examples:</p>
   int even_shorter() { return 0; }
 </example>
 
-<p>In Pike files, you can not use @class or @module to tell which module
+<p>In Pike files, you can not use <tt>@class</tt> or <tt>@module</tt> to tell which module
 or class you are in. To document a class, you simply write:</p>
 
 <example>
@@ -410,20 +410,20 @@ or class you are in. To document a class, you simply write:</p>
   {
     //! You can even document inherits!
     inherit Earth : earth;
-  
+
     //! Doc for CheeseMaker-&gt;a()
     int a()
     {
       ...
     }
-  
+
     void create(string s) { ... }
   }
 </example>
 
-<p>The parser will automatically identify a() as a member method of the
-class CheeseMaker, and will detect that Earth is inherited by
-CheeseMaker. If a class has no documentation comment, it's internals
+<p>The parser will automatically identify <tt>a()</tt> as a member method of the
+class <tt>CheeseMaker</tt>, and will detect that <tt>Earth</tt> is inherited by
+<tt>CheeseMaker</tt>. If a class has no documentation comment, it's internals
 will not be examined, thus it is an error if a class contains
 documentation comments but is itself undocumented:</p>
 
@@ -437,7 +437,7 @@ documentation comments but is itself undocumented:</p>
 
 <p>A special inlining case is that of functions and classes. When documenting
 these, the doc comment can be put between the head of the function/class,
-and the opening "{", like this:</p>
+and the opening <tt>{</tt>, like this:</p>
 
 <example>
   class Roy
@@ -445,7 +445,7 @@ and the opening "{", like this:</p>
   {
     ....
   }
-  
+
   int un_randomize(int x)
   //! This function takes a random number, and transforms it into
   //! a predictable number.
@@ -457,9 +457,9 @@ and the opening "{", like this:</p>
 <p>If a doc block is the first in a file, and it has no target, then it
 is treated as doc for the file (or rather: the module/class that the
 file compiles into) itself. In any other case it is an error to have a
-targetless doc block. A target can also be set with the @decl meta
-keyword. If a doc comment begins with some @decl keywords, these
-@decl's act just like real declarations standing next to the doc.
+targetless doc block. A target can also be set with the <tt>@decl</tt> meta
+keyword. If a doc comment begins with some <tt>@decl</tt> keywords, these
+<tt>@decl</tt>'s act just like real declarations standing next to the doc.
 Thus:</p>
 
 <example>
@@ -482,10 +482,10 @@ Thus:</p>
   }
 </example>
 
-<p>In _one_ case it is legal to have both an adjacent declaration and
-the @decl keyword at the block beginning. That is when you document
+<p>In <em>one</em> case it is legal to have both an adjacent declaration and
+the <tt>@decl</tt> keyword at the block beginning. That is when you document
 "polymorph" methods. Then the adjacent declaration must be a method,
-and all @decl's must be methods that have the same name as the real
+and all <tt>@decl</tt>'s must be methods that have the same name as the real
 method:</p>
 
 <example>
@@ -500,11 +500,11 @@ method:</p>
   }
 </example>
 
-<p>The real method prototype is discarded in favour to the @decl'ed
+<p>The real method prototype is discarded in favour to the <tt>@decl</tt>'ed
 variants, who will be shown in the documentation instead.</p>
 
-<p>One problem that is unsolved so far is how to handle #if .. #else ..
-#endif constructions. The approach so far has been to ignore
+<p>One problem that is unsolved so far is how to handle <tt>#if .. #else ..
+#endif</tt> constructions. The approach so far has been to ignore
 preprocessor directives totally. For example, the parser does not
 handle:</p>
 
@@ -521,22 +521,22 @@ handle:</p>
 
 <p>It a portion of the code is unextractable because it contains too much
 preprocessor macros and stuff, you can make the extractor skip it by using
-@ignore:</p>
+<tt>@ignore</tt>:</p>
 
 <example>
   //! @ignore
-  
+
   HERE_ARE_SOME_STRANGE_THINGS
   #ifdef A
   A
   #endif
-  
+
   //! @endignore
 </example>
 
-<p>All @ignore-@endignore sections of the file are removed before any extraction
-is done, so they can cross class boundaries and the like. You can nest @ignore
-inside eachother. Another application for @ignore is to hide actual class
+<p>All <tt>@ignore-@endignore</tt> sections of the file are removed before any extraction
+is done, so they can cross class boundaries and the like. You can nest <tt>@ignore</tt>
+inside eachother. Another application for <tt>@ignore</tt> is to hide actual class
 boundaries from the extractor:</p>
 
 <example>
@@ -561,9 +561,9 @@ boundaries from the extractor:</p>
 semantics. Seen from the parser, there are two main construct levels:</p>
 
 <ul>
-<li><p> The "what-are-we-documenting level" constructs; @decl for Pike files
-  and @module, @endmodule, @class and @endclass on top of that for C
-  files. These are the meta level tags covered in section a).</p></li>
+<li><p> The "what-are-we-documenting level" constructs; <tt>@decl</tt> for Pike files
+  and <tt>@module</tt>, <tt>@endmodule</tt>, <tt>@class</tt> and <tt>@endclass</tt>
+  on top of that for C files. These are the meta level tags covered in section a).</p></li>
 
 <li><p> Inside-of-comment level constructs for documentation markup,
   covered in sections b), c) and d).</p></li>
@@ -574,14 +574,14 @@ and semantics; there are three categories here (with examples):</p>
 
 <ul>
 <li><p> Grouping constructs that mark the opening/closing of a section of
-  some sort (@mapping/@endmapping, @dl/@enddl, @module/@endmodule).
+  some sort (<tt>@mapping/@endmapping, @dl/@enddl, @module/@endmodule</tt>).
   Most of these not already covered by secion a) appear in b).</p></li>
 
 <li><p> subdividers that break up an outer grouping construct into
-  subsections (@member, @item, @param)</p></li>
+  subsections (<tt>@member, @item, @param</tt>)</p></li>
 
 <li><p> short text markup constructs that basically map to XML containers
-  (@i{...@}, @ref{...@})</p></li>
+  (<tt>@i{...@}, @ref{...@}</tt>)</p></li>
 </ul>
 
 <subsection title="Meta level tags">
@@ -597,7 +597,7 @@ Legal for: C files only (neither needed nor legal for Pike files)
 Arguments: (the last segment of) the module name (ie no "." allowed)
 </pre></p>
 
-<p>Example: To document the module Parser.XML module, you need two
+<p>Example: To document the module <tt>Parser.XML</tt> module, you need two
 consecutive module tags:</p>
 
 <example>
@@ -605,8 +605,8 @@ consecutive module tags:</p>
   /*! @module XML */
 </example>
 
-<p>A @module keyword sets the scope of documentation comments following
-it. @module tags nest, as shown in the example above, and must be
+<p>A <tt>@module</tt> keyword sets the scope of documentation comments following
+it. <tt>@module</tt> tags nest, as shown in the example above, and must be
 ended with a matching number of @endmodule tags, as in:</p>
 
 <example>
@@ -614,7 +614,7 @@ ended with a matching number of @endmodule tags, as in:</p>
   /*! @endmodule Parser */
 </example>
 
-<p>A @module keyword may also have a text child documenting the module
+<p>A <tt>@module</tt> keyword may also have a text child documenting the module
 itself:</p>
 
 <example>
@@ -625,10 +625,10 @@ itself:</p>
    */
 </example>
 
-<p>There are two special @module targets available; the "predef::" module
-and the "lfun::" module. The predef:: module, although more of a scope
+<p>There are two special @module targets available; the <tt>predef::</tt> module
+and the <tt>lfun::</tt> module. The <tt>predef::</tt> module, although more of a scope
 than a module, contains the definitions for all methods in Pike's
-predef:: scope, as in:</p>
+<tt>predef::</tt> scope, as in:</p>
 
 <example>
 /*! @module predef::
@@ -638,7 +638,7 @@ predef:: scope, as in:</p>
  */
 </example>
 
-<p>The "lfun::" module scope does not legally exist in Pike, but it
+<p>The <tt>lfun::</tt> module scope does not legally exist in Pike, but it
 houses the docs for all lfuns (the virtual methods for fulfilling the
 Pike object API). An example:</p>
 
@@ -650,9 +650,9 @@ Pike object API). An example:</p>
  */
 </example>
 
-<p>This also means that referencing (via @ref{...@} or @[...]) the lfun
-documentation strings can be done using @[lfun::`!=] and the like, as
-can predefs via @[predef::sort()] et cetera.</p>
+<p>This also means that referencing (via <tt>@ref{...@}</tt> or <tt>@[...]</tt>) the lfun
+documentation strings can be done using <tt>@[lfun::`!=]</tt> and the like, as
+can predefs via <tt>@[predef::sort()]</tt> et cetera.</p>
 
 <p><pre>
 Keyword:   @endmodule
@@ -660,9 +660,9 @@ Legal for: C files only (neither needed nor legal for Pike files)
 Arguments: (the last segment of) the module name (optional)
 </pre>></p>
 
-<p>When the optional argument to @endmodule is given (for code clarity),
+<p>When the optional argument to <tt>@endmodule</tt> is given (for code clarity),
 the extractor will verify that the module scope you close was indeed
-the one you opened, as in the @module example above. The following
+the one you opened, as in the <tt>@module</tt> example above. The following
 would trigger an error:</p>
 
 <example>
@@ -690,21 +690,21 @@ Legal for: C files only (neither needed nor legal for Pike files)
 Arguments: (the last segment of) the class name (ie no "." allowed)
 </pre></p>
 
-<p>Example: to document the Process.create_process class, you would use:</p>
+<p>Example: to document the <tt>Process.create_process</tt> class, you would use:</p>
 
 <example>
   /*! @module Process
    *! @class create_process */
 </example>
 
-<p>And end the scope similar to @module:</p>
+<p>And end the scope similar to <tt>@module</tt>:</p>
 
 <example>
   /*! @endclass create_process
    *! @endmodule Process */
 </example>
 
-<p>Like @module tags, @class tags may be nested any number of levels
+<p>Like <tt>@module</tt> tags, <tt>@class</tt> tags may be nested any number of levels
 (when documenting subclasses to subclasses to subclasses to ...).</p>
 
 <p><pre>
@@ -713,9 +713,9 @@ Legal for: C files only (neither needed nor legal for Pike files)
 Arguments: (the last segment of) the class name (optional)
 </pre></p>
 
-<p>When the optional argument to @endclass is given (for code clarity),
+<p>When the optional argument to <tt>@endclass</tt> is given (for code clarity),
 the extractor will verify that the class scope you close was indeed
-the one you opened, just as with @endmodule above.</p>
+the one you opened, just as with <tt>@endmodule</tt> above.</p>
 
 <p><pre>
 Keyword:   @decl
@@ -723,7 +723,7 @@ Legal for: All source code (C and Pike files)
 Arguments: (the last segment of) the identifier name (ie "." illegal)
 </pre></p>
 
-<p>The @decl keyword is used to target a specific (...more to come! :-)</p>
+<p>The <tt>@decl</tt> keyword is used to target a specific (...more to come! :-)</p>
 
 </subsection>
 </section>
@@ -740,7 +740,7 @@ Arguments: (the last segment of) the identifier name (ie "." illegal)
 a) Introduction
 ----------------------------------------------------------------------
 
-When a piece of documentation is viewed in human-readable format, it 
+When a piece of documentation is viewed in human-readable format, it
 has gone through the following states:
 
   1. Doc written in comments in source code (C or Pike).
@@ -751,13 +751,13 @@ has gone through the following states:
 
   4. A repository of smaller and more manageable XML files.
 
-  5. A HTML page rendered from one such file. 
+  5. A HTML page rendered from one such file.
      (Or a PDF file, or whatever).
 
-The transition from state 1 to state 2 is the extraction of 
+The transition from state 1 to state 2 is the extraction of
 documentation from source files. There are several (well, at
 least two) markup formats, and there are occasions where it is
-handy to generate documentation automatically &amp;c. This document 
+handy to generate documentation automatically &amp;c. This document
 describes how a file in state 2 should be structured in order to
 be handled correctly by subsequent passes and presented in a
 consistent manner.
@@ -767,10 +767,10 @@ b) Overall structure
 ----------------------------------------------------------------------
 
 Each source file adds some number of entities to the whole hierarchy.
-It can contain a class or a module. It can contain an empty module, 
+It can contain a class or a module. It can contain an empty module,
 that has its methods and members defined in some other source file,
 and so on. Suppose we have a file containing documentation for the
-class Class in the module Module. The XML skeleton of the file 
+class Class in the module Module. The XML skeleton of the file
 would then be:
 
   &lt;module name=""&gt;
@@ -784,17 +784,17 @@ would then be:
       &lt;/module&gt;
   &lt;/module&gt;
 
-The &lt;module name=""&gt; refers to the top module. That element, and its 
-child &lt;module name="Module"&gt;, exist only to put the &lt;class name="Class"&gt; 
+The &lt;module name=""&gt; refers to the top module. That element, and its
+child &lt;module name="Module"&gt;, exist only to put the &lt;class name="Class"&gt;
 in its correct position in the hierarchy. So we can divide the elements
-in the XML file into two groups: skeletal elements and content elements. 
+in the XML file into two groups: skeletal elements and content elements.
 
 Each actual module/class/whatever in the Pike hierarchy maps to at most
-one content element, however it can map to any number of skeletal elements. 
+one content element, however it can map to any number of skeletal elements.
 For example, the top module is mapped to a skeletal element in each XML
-file extracted from a single source file. To get from state 2 to state 3 
+file extracted from a single source file. To get from state 2 to state 3
 in the list above, all XML files are merged into one big. All the elements
-that a module or class map to are merged into one, and if one of those 
+that a module or class map to are merged into one, and if one of those
 elements contains documentation (=is a content element), then that
 documentation becomes a child of the merger of the elements.
 
@@ -802,15 +802,15 @@ documentation becomes a child of the merger of the elements.
 c) Grouping
 ----------------------------------------------------------------------
 
-Classes and modules always appear as &lt;module&gt; and &lt;class&gt; elements. 
-Methods, variables, constants &amp;c, however, can be grouped in the 
+Classes and modules always appear as &lt;module&gt; and &lt;class&gt; elements.
+Methods, variables, constants &amp;c, however, can be grouped in the
 source code:
 
   //! Two variables:
   int a;
   int b;
-  
-Even a single variable is considered as a group with one member. 
+
+Even a single variable is considered as a group with one member.
 Continuing the example in the previous section, suppose that Module.Class
 has two member variables, a and b, that are documented as a group:
 
@@ -822,7 +822,7 @@ has two member variables, a and b, that are documented as a group:
         &lt;docgroup homogen-type="variable"&gt;
           &lt;variable name="a"&gt;&lt;type&gt;&lt;int/&gt;&lt;/type&gt;&lt;/variable&gt;
           &lt;variable name="b"&gt;&lt;type&gt;&lt;int/&gt;&lt;/type&gt;&lt;/variable&gt;
-          &lt;doc&gt; 
+          &lt;doc&gt;
             ... documentation for Module.Class.a and Module.Class.b ...
           &lt;/doc&gt;
         &lt;/docgroup&gt;
@@ -834,12 +834,12 @@ has two member variables, a and b, that are documented as a group:
     &lt;/module&gt;
   &lt;/module&gt;
 
-If all the children of a &lt;docgroup&gt; are of the same type, e.g. all are 
-&lt;method&gt; elements, then the &lt;docgroup&gt; has the attribute homogen-type 
-(="method" in the example). If all the children have identical name="..." 
+If all the children of a &lt;docgroup&gt; are of the same type, e.g. all are
+&lt;method&gt; elements, then the &lt;docgroup&gt; has the attribute homogen-type
+(="method" in the example). If all the children have identical name="..."
 attributes, then the &lt;docgroup&gt; gets a homogen-name="..." attribute aswell.
 
-The &lt;docgroup&gt; has a &lt;doc&gt; child containing the docmentation for the other 
+The &lt;docgroup&gt; has a &lt;doc&gt; child containing the docmentation for the other
 children of the &lt;docgroup&gt;. An entity that cannot be grouped (class, module,
 enum), has a &lt;doc&gt; child of its own instead.
 
@@ -849,7 +849,7 @@ d) Pike entities
 
 Pike entities - classes, modules, methods, variables, constants, &amp;c, have some
 things in common, and many parts of the xml format are the same for all of
-these entities. All entities are represented with an XML element, namely one 
+these entities. All entities are represented with an XML element, namely one
 of:
 
   &lt;class&gt;
@@ -857,19 +857,19 @@ of:
   &lt;enum&gt;
   &lt;inherit&gt;
   &lt;method&gt;
-  &lt;modifier&gt;    
+  &lt;modifier&gt;
   &lt;module&gt;
   &lt;typedef&gt;
-  &lt;variable&gt; 
+  &lt;variable&gt;
 
-The names speak for themselves, except: &lt;modifier&gt; which is used for modifier 
-ranges: 
+The names speak for themselves, except: &lt;modifier&gt; which is used for modifier
+ranges:
 
   //! Some variables:
   protected final {
-    int x, y; 
+    int x, y;
 
-    string n;  
+    string n;
   }
 
 A Pike entity may also have the following properties:
@@ -895,9 +895,9 @@ A Pike entity may also have the following properties:
       &lt;/modifiers&gt;
       ...
     &lt;/variable&gt;
-  The source position is the place in the code tree where the entity is 
+  The source position is the place in the code tree where the entity is
   declared or defined. For a method, the attribute last-line="..." can be
-  added to &lt;source-position&gt; to give the range of lines that the method 
+  added to &lt;source-position&gt; to give the range of lines that the method
   body spans in the source code.
 
 And then there are some things that are specific to each of the types of
@@ -905,12 +905,12 @@ entities:
 
 &lt;class&gt;
    All inherits of the class are given as child elements &lt;inherit&gt;. If there
-   is doc for the inherits, the &lt;inherit&gt; is repeated inside the appropriate 
+   is doc for the inherits, the &lt;inherit&gt; is repeated inside the appropriate
    &lt;docgroup&gt;:
 
-     class Bosse { 
-       inherit "arne.pike" : Arne; 
-       inherit Benny;   
+     class Bosse {
+       inherit "arne.pike" : Arne;
+       inherit Benny;
 
        //! Documented inherit
        inherit Sven;
@@ -932,7 +932,7 @@ entities:
        &lt;/docgroup&gt;
        ...
      &lt;/class&gt;
- 
+
 &lt;constant&gt;
    Only has a name. The element is empty (or has a &lt;source-position&gt; child.)
 
@@ -946,7 +946,7 @@ entities:
      {
        //! Three constants:
        a, b, c,
-     
+
        //! One more:
        d
      }
@@ -966,23 +966,23 @@ entities:
              &lt;constant name="d"/&gt;
          &lt;/docgroup&gt;
      &lt;/enum&gt;
-     
-   Both the &lt;enum&gt; element and the &lt;constant&gt; elements could have 
+
+   Both the &lt;enum&gt; element and the &lt;constant&gt; elements could have
    &lt;source-position&gt; children, of course.
 
-&lt;inherit&gt; 
+&lt;inherit&gt;
    The name="..." attribute gives the name after the colon, if any. The name
    of the inherited class is given in a &lt;classname&gt; child. If a file name is
    used, the class name is the file name surrounded by quotes (see &lt;class&gt;).
 
 &lt;method&gt;
-   The arguments are given inside an &lt;arguments&gt; child. Each argument is 
+   The arguments are given inside an &lt;arguments&gt; child. Each argument is
    given as an &lt;argument name="..."&gt; element. Each &lt;argument&gt; has a &lt;type&gt;
-   child, with the type of the argument. The return type of the method is 
+   child, with the type of the argument. The return type of the method is
    given inside a &lt;returntype&gt; container:
 
      int a(int x, int y);
-  
+
      &lt;method name="a"&gt;
        &lt;arguments&gt;
          &lt;argument name="x"&gt;&lt;type&gt;&lt;int/&gt;&lt;/type&gt;&lt;/argument&gt;
@@ -990,7 +990,7 @@ entities:
        &lt;/arguments&gt;
        &lt;returntype&gt;&lt;int/&gt;&lt;/returntype&gt;
      &lt;/method&gt;
-                 
+
 &lt;modifier&gt;
    Works as a container ... ???
 
@@ -1001,12 +1001,12 @@ entities:
    The type is given in a &lt;type&gt; child:
 
      typedef float Boat;
-     
+
      &lt;typedef name="Boat"&gt;&lt;type&gt;&lt;float/&gt;&lt;/type&gt;&lt;/typedef&gt;
 
 &lt;variable&gt;
    The type of the variable is given in a &lt;type&gt; child:
-     
+
      int x;
 
      &lt;variable name="x"&gt;&lt;type&gt;&lt;int/&gt;&lt;/type&gt;&lt;/variable&gt;
@@ -1025,7 +1025,7 @@ the form &lt;foo/&gt;:
   &lt;string/&gt;
   &lt;void/&gt;
 
-The same goes for mapping, array, function, object, multiset, &amp;c that have 
+The same goes for mapping, array, function, object, multiset, &amp;c that have
 no narrowing type qualification: &lt;mapping/&gt;, &lt;array/&gt;, &lt;function/&gt; ...
 
 The complex types are represented as follows:
@@ -1034,12 +1034,12 @@ array
    If the type of the elements of the array is specified it is given in a
    &lt;valuetype&gt; child element:
 
-     array(int) 
- 
+     array(int)
+
      &lt;array&gt;&lt;valuetype&gt;&lt;int/&gt;&lt;/valuetype&gt;&lt;/array&gt;
 
 function
-   The types of the arguments and the return type are given (the order 
+   The types of the arguments and the return type are given (the order
    of the &lt;argtype&gt; elements is significant, of course):
 
      function(int, string: mixed)
@@ -1049,13 +1049,13 @@ function
        &lt;argtype&gt;&lt;string/&gt;&lt;/argtype&gt;
        &lt;returntype&gt;&lt;mixed/&gt;&lt;/returntype&gt;
      &lt;/function&gt;
-   
+
 int
    An int type can have a min and/or max value. The values can be numbers or
    identifiers:
 
      int(0..MAX)
-   
+
      &lt;int&gt;&lt;min&gt;0&lt;/min&gt;&lt;max&gt;MAX&lt;/max&gt;&lt;/int&gt;
 
 mapping
@@ -1069,15 +1069,15 @@ mapping
 
 multiset
    The type of the indices is given:
-  
+
      multiset(string)
 
      &lt;multiset&gt;
        &lt;indextype&gt;&lt;string/&gt;&lt;/indextype&gt;
      &lt;/multiset&gt;
 
-object 
-   If the program/class is specified, it is given as the text child of 
+object
+   If the program/class is specified, it is given as the text child of
    the &lt;object&gt; element:
 
      object(Foo.Bar.Ippa)
@@ -1132,8 +1132,8 @@ image
 g) XML generated from the doc markup
 ----------------------------------------------------------------------
 
-The documentation for an entity is put in a &lt;doc&gt; element. The &lt;doc&gt; element 
-is either a child of the element representing the entity (in the case of 
+The documentation for an entity is put in a &lt;doc&gt; element. The &lt;doc&gt; element
+is either a child of the element representing the entity (in the case of
 &lt;class&gt;, &lt;module&gt;, &lt;enum&gt;, or &lt;modifiers&gt;) or a child of the &lt;docgroup&gt; that
 contains the element representing the entity.
 
@@ -1151,13 +1151,13 @@ the previous subsection. Consider e.g.:
   //!     The coordinates of its physical location.
   //! @endmapping
 
-Here @mapping and @endmapping create a container, and each @member start a 
+Here @mapping and @endmapping create a container, and each @member start a
 new subsection. The two latter @member are grouped together and thus they
-form ONE new subsection together. Each subsection is a &lt;group&gt;, and the 
+form ONE new subsection together. Each subsection is a &lt;group&gt;, and the
 &lt;group&gt; has one or more &lt;member&gt; children, and a &lt;text&gt; child that contains
 the text that describes the &lt;member&gt;s:
 
-  &lt;mapping&gt; 
+  &lt;mapping&gt;
       &lt;group&gt;
           &lt;member&gt;&lt;type&gt;&lt;int/&gt;&lt;/type&gt;&lt;index&gt;"ip"&lt;/index&gt;&lt;/member&gt;
           &lt;text&gt;
@@ -1180,7 +1180,7 @@ the text that describes the &lt;member&gt;s:
   &lt;/mapping&gt;
 
 Inside a &lt;text&gt; element, there can not only be text, but also a nested level
-of, say @mapping - @endmapping. In that case, the &lt;mapping&gt; element is put in 
+of, say @mapping - @endmapping. In that case, the &lt;mapping&gt; element is put in
 the document order place as a sibling of the &lt;p&gt; that contain the text:
 
   //! @mapping
@@ -1190,9 +1190,9 @@ the document order place as a sibling of the &lt;p&gt; that contain the text:
   //!       @member string "zip-code"
   //!         The zip code.
   //!     @endmapping
-  //!     And some more text ... 
+  //!     And some more text ...
   //! @endmapping
-    
+
   becomes:
 
   &lt;mapping&gt;
@@ -1213,23 +1213,23 @@ the document order place as a sibling of the &lt;p&gt; that contain the text:
       &lt;/group&gt;
   &lt;/mapping&gt;
 
-Inside the &lt;p&gt; elements, there may also be some more "layout-ish" tags like 
+Inside the &lt;p&gt; elements, there may also be some more "layout-ish" tags like
 &lt;b&gt;, &lt;code&gt;, &lt;tt&gt;, &lt;i&gt;, needed to make the text more readable. Those tags are
-expressed as @i{ ... @} in the doc markup. However there are no &lt;br&gt;. A 
-paragraph break is done by ending the &lt;p&gt; and beginning a new. A &lt;/p&gt;&lt;p&gt; is 
+expressed as @i{ ... @} in the doc markup. However there are no &lt;br&gt;. A
+paragraph break is done by ending the &lt;p&gt; and beginning a new. A &lt;/p&gt;&lt;p&gt; is
 inserted for each sequence of blank lines in the doc markup:
 
   //! First paragraph.
-  //! 
+  //!
   //! Second paragraph.
-  //! 
-  //! 
+  //!
+  //!
 
   becomes:
 
   &lt;p&gt;First paragraph.&lt;/p&gt;&lt;p&gt;Second paragraph.&lt;/p&gt;
 
-Note that the text is trimmed from leading and ending whitespaces, and there 
+Note that the text is trimmed from leading and ending whitespaces, and there
 are never any empty &lt;p&gt; elements.
 
 In the example above the keyword `@mapping' translated into &lt;mapping&gt;, whereas
@@ -1239,9 +1239,9 @@ the keyword `@member string "zip-code"' translated into:
 The translation of keyword-&gt;XML is done differently for each keyword. How it
 is done can be seen in lib/modules/Tools.pmod/AutoDoc.pmod/DocParser.pmod. Most
 keywords just interpret the arguments as a space-separated list, and put their
-values in attributes to the element. In some cases (such as @member) though, 
-some more intricate parsing must be done, and the arguments may be complex 
-(like Pike types) and are represented as child elements of the element. 
+values in attributes to the element. In some cases (such as @member) though,
+some more intricate parsing must be done, and the arguments may be complex
+(like Pike types) and are represented as child elements of the element.
 
 ======================================================================
 h) Top level sections of different Pike entities.
@@ -1253,7 +1253,7 @@ be opened in it. E.g.:
   //! A method.
   //! @param x
   //!   The horizontal coordinate.
-  //! @param y 
+  //! @param y
   //!   The vertical coordinate.
   //! @returns
   //!   Nothing :)
@@ -1281,7 +1281,7 @@ becomes:
          ......
       &lt;/method&gt;
   &lt;/docgroup&gt;
-  
+
 Which "top container" subsections are allowed depends on what type of entity is
 documented:
 
diff --git a/refdoc/chapters/compatibility.xml b/refdoc/chapters/compatibility.xml
index 71fe122e97..c99410398e 100644
--- a/refdoc/chapters/compatibility.xml
+++ b/refdoc/chapters/compatibility.xml
@@ -59,7 +59,7 @@
         <r><c><ref>7.8::Yabu.table</ref></c>
            <c><ref>Yabu.Table</ref></c></r>
         <r><c><ref>7.8::_PGsql</ref></c>
-           <c>(deleted></c></r>
+           <c>(deleted)</c></r>
         <r><c><ref>7.8:_files</ref></c>
            <c><ref>_Stdio</ref></c></r>
       </matrix>
diff --git a/refdoc/chapters/hilfe.xml b/refdoc/chapters/hilfe.xml
index 2873a38721..f35bd5a89d 100644
--- a/refdoc/chapters/hilfe.xml
+++ b/refdoc/chapters/hilfe.xml
@@ -155,10 +155,10 @@ Enter "help me more" for further Hilfe help.
 that can be given to help to see other help pages. "<tt>help me
 more</tt>" returns a brief summary of everything in this manual
 chapter. "<tt>help hilfe todo</tt>" shows the items in the bug section
-below. "<tt>help about hilfe</tt>" show the Hilfe CVS id string and
-some other version information. In addition to these three arguments
-it is also possible to type help follow with the name of any other
-command. That will display the documentation for that command.</p>
+below. "<tt>help about hilfe</tt>" show version information. In
+addition to these three arguments it is also possible to type help
+follow with the name of any other command. That will display the
+documentation for that command.</p>
 
 </subsection>
 
diff --git a/refdoc/keywords.txt b/refdoc/keywords.txt
index 0bbb48a745..d493c199ea 100644
--- a/refdoc/keywords.txt
+++ b/refdoc/keywords.txt
@@ -151,6 +151,19 @@ Examples:
 
 _______________________________________________________________________________
 
+Keyword:      @endenum
+Description:  Leave the enum scope entered by @enum.
+Arguments:    [name]
+              Where:
+                [name] if present, must be the same as the argument to
+                  @enum.
+Children:
+Groups with:  -
+Examples:
+              /*! @endenum Flags */
+
+_______________________________________________________________________________
+
 Keyword:      @endmodule
 Description:  Leave the module scope entered by @module
 Arguments:    [name]
@@ -179,6 +192,30 @@ Examples:
 
 _______________________________________________________________________________
 
+Keyword:      @enum
+Description:  Declare and enter a new scope for an enum. Only in C
+              mode. Until an @endenum is found, all declarations will
+              be regarded as children of the enum. The only valid
+	      child declarations are declarations of constants.
+
+Arguments:    <name>
+              Where:
+                <name> is a valid Pike identifier. Not the "absolute"
+                  name with dots.
+
+Children:     Documentation for the enum, or empty.
+Groups with:  -
+Examples:
+              /*! @enum Flags
+               *!   Some flags controlling behavior.
+	       */
+	      /*! @decl constant FLAG_FLAG = 1
+	       */
+	      /*! @endenum
+	       */
+
+_______________________________________________________________________________
+
 Keyword:      @inherit
 Description:  Tell which classes are inherited into this class.
 Arguments:    <name>
@@ -655,13 +692,18 @@ XML:          <ref>...</ref>
 _______________________________________________________________________________
 
 Keyword:      @rfc{ ... @}
-Description:  A reference to an RFC.
-Children:     RFC number.
+Description:  Reference to an RFC and optionally a section or appendix.
+Children:     RFC number and optionally a colon followed by section number
+              or appendix letter.
 Groups with:  -
 
 Examples:
               The @[MIME] module implements @rfc{1521@}.
 
+              See @rfc{7540:5.3@} for details about @[ADT.TreeScheduler].
+
+              The list of static headers for HPack is defined in @rfc{7541:A@}.
+
 XML:          <rfc>...</rfc>
 _______________________________________________________________________________
 
diff --git a/refdoc/presentation/make_html.pike b/refdoc/presentation/make_html.pike
index 53b9475d0a..7a4d9ed96d 100644
--- a/refdoc/presentation/make_html.pike
+++ b/refdoc/presentation/make_html.pike
@@ -2,4 +2,9 @@
  * Compat place-holder.
  */
 
+#if 1
 inherit Tools.Standalone.autodoc_to_html;
+#else /* For dev purposes */
+inherit __DIR__ + "/../../lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_html.pike";
+Tools.AutoDoc.Flags flags = Tools.AutoDoc.FLAG_NORMAL|Tools.AutoDoc.FLAG_NO_DYNAMIC;
+#endif
diff --git a/refdoc/presentation/tree-split-autodoc.pike b/refdoc/presentation/tree-split-autodoc.pike
index 0aa83cd205..42520fc395 100644
--- a/refdoc/presentation/tree-split-autodoc.pike
+++ b/refdoc/presentation/tree-split-autodoc.pike
@@ -2,4 +2,9 @@
  * Compat place-holder.
  */
 
+#if 1
 inherit Tools.Standalone.autodoc_to_split_html;
+#else /* For dev purposes */
+inherit __DIR__ + "/../../lib/modules/Tools.pmod/Standalone.pmod/autodoc_to_split_html.pike";
+Tools.AutoDoc.Flags flags = Tools.AutoDoc.FLAG_NORMAL|Tools.AutoDoc.FLAG_NO_DYNAMIC;
+#endif
diff --git a/refdoc/src_images/eye-slash.svg b/refdoc/src_images/eye-slash.svg
new file mode 100644
index 0000000000..9301318e5f
--- /dev/null
+++ b/refdoc/src_images/eye-slash.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="511.626" height="511.627" viewBox="0 0 511.626 511.627" class="icon"><path class="icon" d="M361.16 291.652c15.038-21.796 22.56-45.922 22.56-72.375 0-7.422-.76-15.417-2.285-23.984l-79.938 143.32c24.738-9.512 44.628-25.175 59.664-46.96zM372.872 94.22c.19-.377.28-1.234.28-2.567 0-3.237-1.522-5.802-4.57-7.715-.57-.38-2.424-1.475-5.57-3.287a526.374 526.374 0 0 1-8.988-5.28 192.794 192.794 0 0 0-9.422-5.28c-3.426-1.81-6.375-3.285-8.846-4.428-2.48-1.14-4.19-1.713-5.14-1.713-3.427 0-6.093 1.524-7.995 4.568L307.21 96.214c-17.316-3.234-34.45-4.854-51.39-4.854-51.202 0-98.405 12.946-141.614 38.83-43.208 25.89-79.37 61.196-108.496 105.925C1.904 242.02 0 248.586 0 255.82c0 7.23 1.903 13.8 5.71 19.697 16.75 26.073 36.593 49.396 59.53 69.95 22.935 20.56 48.01 37.017 75.228 49.395-8.375 14.273-12.562 22.556-12.562 24.842 0 3.425 1.524 6.088 4.57 7.99 23.22 13.33 35.97 19.985 38.256 19.985 3.422 0 6.09-1.53 7.992-4.576l13.99-25.406c20.177-35.967 50.248-89.93 90.222-161.878 39.972-71.95 69.95-125.815 89.936-161.6zM158.456 362.886c-49.486-22.27-90.126-57.955-121.91-107.063 28.932-44.92 65.19-78.518 108.778-100.783-11.61 19.79-17.417 41.205-17.417 64.236 0 20.365 4.66 39.68 13.99 57.955 9.327 18.275 22.27 33.4 38.83 45.393l-22.27 40.262zm107.07-206.998c-2.663 2.667-5.907 4-9.713 4-16.368 0-30.36 5.807-41.97 17.415-11.614 11.615-17.417 25.603-17.417 41.97 0 3.812-1.336 7.045-4 9.71-2.667 2.668-5.9 4-9.706 4-3.81 0-7.045-1.334-9.71-4-2.667-2.665-4-5.902-4-9.71 0-23.79 8.52-44.205 25.554-61.24 17.034-17.035 37.447-25.554 61.24-25.554 3.807 0 7.044 1.336 9.714 4 2.662 2.663 3.996 5.9 3.996 9.706 0 3.808-1.333 7.044-3.99 9.703z"/><path class="icon" d="M505.916 236.114c-10.853-18.08-24.603-35.594-41.255-52.534-16.645-16.94-34.02-31.496-52.104-43.68l-17.987 31.977c31.784 21.888 58.624 49.87 80.51 83.94-23.025 35.78-51.724 65-86.07 87.647-34.36 22.66-71.713 35.693-112.066 39.115l-21.13 37.687c42.258 0 82.18-9.038 119.77-27.12 37.59-18.077 70.668-43.49 99.216-76.226 13.322-15.42 23.695-29.218 31.12-41.4 3.807-6.476 5.71-13.046 5.71-19.702-.004-6.66-1.906-13.228-5.714-19.704z"/></svg>
\ No newline at end of file
diff --git a/refdoc/src_images/pike-logo-blue.svg b/refdoc/src_images/pike-logo-blue.svg
new file mode 100644
index 0000000000..7b1c68f4e6
--- /dev/null
+++ b/refdoc/src_images/pike-logo-blue.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="47.908" width="203.74" viewBox="0 0 203.73994 47.907825"><g stroke="#0a50a1" stroke-width=".5" fill="#0a50a1"><path d="M17.936 16.415c.238-.875.368-1.576 1.355-2.276a5.347 5.347 0 0 1 2.946-.919c3.86 0 2.596 4.421 2.096 6.259-.346 1.27-.897 2.845-1.721 4.071-.812 1.182-2.094 1.838-3.81 1.838-2.941 0-2.75-2.057-2.32-3.633l1.454-5.34zM8.005 8.098L0 37.513h12.133l2.573-9.455c1.363 1.97 4.067 2.845 7.314 2.845 4.35 0 8.052-1.663 10.8-4.333 2.25-2.189 3.576-5.034 4.255-7.529 1.429-5.253.156-11.381-8.67-11.381-4.166 0-7.848.919-9.873 3.633h-.123l.87-3.195H8.005zM49.289 30.465H37.156l6.087-22.367h12.133l-6.087 22.367zm6.67-24.512H43.827L45.446 0H57.58l-1.62 5.953zM80.777 15.802l6.55 14.664H74.642L71.2 21.493l-3.826 2.801-1.68 6.172H53.56L61.733.438h12.133l-4.407 16.195 3.314-2.495 8.997-6.041h10.54l-11.533 7.705z"/><path d="M102.143 16.633c.438-2.057 2.213-3.852 5.399-3.852 3.432 0 3.959 1.663 3.364 3.852h-8.763zm7.976 5.822c-1.015 1.926-2.761 2.714-5.52 2.714-3.676 0-4.425-1.751-3.586-4.158h20.958l.32-1.182c2.002-7.354-3.061-12.168-13.478-12.168-4.473 0-9.551 1.094-13.381 3.458-3.524 2.145-6.072 5.428-6.895 8.448-.87 3.196.074 6.26 2.86 8.404 2.947 2.232 7.229 2.933 11.826 2.933 7.415 0 14.834-2.495 18.21-7.922l-11.314-.527z"/></g><g fill="#404040"><path d="M124.273 8.018h-.736v2.355h-.686V8.018h-.745v-.582h2.167v.582zM126.403 10.373h-.471l-.716-2.394h-.008v2.394h-.578V7.436h1.074l.514 1.76.54-1.76h1.075v2.938h-.686V7.979h-.018l-.726 2.394z"/></g><g fill="#404040"><path d="M194.783 1.856c-.05-.386-3.471.589-7.848 2.18-1.288.507-9.864 3.751-11.253 4.395.118-.537.184-1.712-.297-3.183-.733-2.241-2.39-2.167-3.99-1.598-2.126.755-3.37 1.739-4.53 2.703a19.54 19.54 0 0 0-2.398 2.397c-1.148.223-2.078.625-2.726 1.013-.733.439-1.638 1.248-1.982 1.91-.128.243-.23.401-.127.435.22.071 2.327-.602 2.586-.673.103-.029.216-.06.33-.09-.868 1.359-2.125 3.422-2.067 3.541.077.162.213-.018.213-.018s1.512-1.701 2.938-3.239c.63.991 1.194 1.72 1.68 2.151.502.445 1.354.961 2.19 1.168.72.179 2.154.193 2.359.144.467-.027.654-.198.61-.308-.044-.11-1.51-.259-2.031-.37-.524-.11-1.196-.353-1.747-.772-.422-.321-.958-.799-1.354-1.631-.182-.375-.413-1.284-.413-1.284s1.24-.277 1.89-.297a6.251 6.251 0 0 1 1.652.185c.287.077.854.412.854.412s-.43.683-.397 1.085c0 .799.28 1.102.843 1.389.578.248 1.166.204 1.63-.237.303.198.513.572.893.784.399.297.826.262 1.079-.02.172-.188.006-.907.006-.907s-.162-.201-.396-.497c-.106-.136-.46-.731-.761-1.22-.452-.73-.61-.98-1.26-1.54-.894-.772-2.196-1.201-4.114-1.275 1.054-.779 2.122-1.417 3.52-1.854 1.312-.411 2.385-.314 2.803.196.419.509.532 1.53.467 2.126-.056.5-.312.912-.37 1.397-.06.486-.102.8.088.919.3.192 2.439-1.122 2.84-1.337.51-.274 2.259-1.046 3.459-1.599 1.859-.857 4.719-2.083 6.348-2.765 1.604-.672 7.91-3.077 8.337-3.305.422-.227.563-.432.446-.511zm-24.507 9.923s.479.48.567.7c-.16.159-.17.13-.326.225-.17-.188-.551-.464-.551-.464l.31-.461zM159.723 9.175c-.145-.289-4.352 1.091-4.737 1.163-.553.104-1.438.039-2.054-.241-.274-.125-4.313-2.312-4.313-2.312s-3.83-2.505-4.266-2.686c-.647-.271-1.306-.43-2.034-.173-1.464.516-3.153 1.659-4.224 2.481-1.972 1.513-3.246 3.665-3.36 4.181-.168.767-.192 1.156.603 1.803 1.322 1.077 6.685 3.667 6.87 3.692.189.025 1.169.175 1.508.089.34-.086.809-.241.825-.462.016-.222-.451-.067-1.117-.406-.732-.373-5.371-3.058-5.645-3.278-.137-.11-.88-.466-.804-1.028.067-.498 1.544-2.133 2.358-2.697 1.572-1.086 2.764-1.532 3.17-1.635.853-.215 1.959.011 2.539.299.58.287 3.717 1.812 4.707 2.285.988.474 3.102 1.387 3.588 1.446.329.04 1.548-.03 2.322-.406.317-.155 2.15-1.088 2.447-1.199.3-.112 1.764-.627 1.617-.916z"/><path d="M141.473 8.716l1.96-.678 6.93 4.909zM139.203 10.184l1.65-1.202 6.8 4.977zM137.593 12.039l1.09-1.308 6.79 4.503zM144.223 30.766c.307.212-4.73 6.173-6.285 8.361-1.604 2.252-4.197 6.021-4.197 6.021s-.254.426.138.544c.392.119 4.147.218 4.147.218s4.503.201 5.133-.176c.629-.376 1.836-3.904 2.047-4.5.21-.597 2.549-7.668 2.553-6.512.004 1.159-.995 6.371-.995 6.371s-.79 3.459-1.001 4.056c-.212.597-.684 2.019-3.28 2.495-2.593.475-8.137.176-10.181.114-2.043-.062-1.326-2.235-1.03-2.781.297-.546 5.16-6.688 6.294-7.893 1.655-1.758 6.349-6.53 6.657-6.318z"/><path d="M140.693 45.338l1.31.03 4.02-10.721zM137.913 45.243l1.45-.004 4.4-10.091zM134.913 45.133l1.6.029 5.53-9.652zM158.543 22.944c.359.561-3.006 2.716-4.887 5.871-.287.58-1.422 2.677-1.334 3.886.088 1.208 1.199 2.449 2.51 2.623 1.313.175 4.595-.728 5.87-1.268 1.276-.541 3.062-1.354 3.462-1.492 2.772-.773 3.414.041 3.414.041s-2.596.622-3.395 1.041c-.798.419-4.938 2.517-6.708 3.11-1.73.579-5.156.943-6.495.375-1.336-.566-1.503-1.646-1.48-2.268.054-2.656 1.259-4.927 2.84-7.091 1.562-2.133 4.339-4.175 4.689-4.373.35-.197 1.113-.752 1.514-.455zM191.893 32.087s-10.09-.235-12.516-.381c-2.427-.146-5.885-.937-6.932-.781-1.047.157-3.102 1.763-3.102 1.763s1.565-.251 1.829-.21c.264.042.774.203.87.432.094.23.268 1.345.268 1.345s2.21-.993 2.94-1.251c.732-.257 1.966-.389 2.267-.066.297.322.063 1.686.105 1.855.043.171.3.324.3.324s.968-.896 1.205-1.102c.237-.205 1.7-1.009 2.287-1.122.588-.113 1.286.218 1.397.515s-.108.859-.108.859.313-.003.46-.09c.148-.084 1.01-.644 1.215-.732.328-.14 1.42-.398 1.906-.482.484-.083 4.62-.336 4.986-.465.367-.129.623-.411.623-.411zM141.663 19.5s-12.443 10.321-12.877 10.756c-.433.436-6.215 6.208-6.92 6.566-.705.36-1.744.405-2.016.475-.272.069-2.407.791-3.163 1.09-.757.301-1.802 1.18-1.944 1.616-.145.434-.084.961.455 1.513.537.552 2.386.845 2.386.845s1.926.599 2.42.98c.495.381.302 1.191.345 1.506s.602 1.804 1.088 2.006c.484.203.79-.164 1.164-.403.375-.24 1.21-2.371 1.21-2.371s.43-1.882.997-2.93c.568-1.049 2.463-2.291 2.463-2.291s-.21 1.391-.006 1.629c.206.237 2.707.039 3.406-.066.697-.104.772-.452.953-1.31.198-.937.31-1.924.47-2.436.145-.46.589-1.036 1.09-1.344.502-.308 2.05-.914 2.05-.914s-2.061-.13-4.943 1.07c-1.277.531-2.318 1.419-3.016 1.813-.697.394-3.228 2.41-3.703 3.254-.474.844-.803 1.833-.996 2.497-.195.665-.381 1.219-.695 1.262-.314.044-.197-.349-.307-.501-.112-.153.1-.605-.064-.962-.162-.357-1.8-1.247-2.94-1.465s-2.24-.556-2.386-.7c-.145-.144-.222-.306-.104-.553s1.309-.838 1.998-1.122c.688-.282 2.347-.883 2.72-.833.376.05.479.168.48.458 0 .289-.134 1.048-.134 1.048s1.782-2.262 2.376-2.92c.594-.656 8.48-7.975 10.843-9.948 2.36-1.974 5.979-4.558 7.15-5.214 1.15-.643 1.974-1.009 1.974-1.009l-1.824-1.092zm-13.13 18.276c.612-.806 2.73-1.668 2.73-1.668s-.352.397-.514 1.833c-.072.641-.205 1.193-.635 1.355-.43.163-1.826.353-1.881.078-.068-.345-.068-1.11.3-1.598z"/><path d="M128.763 39.257l1.05-.123.09-2.102zM191.253 30.041l.453-2.37-1.807 1.905c-2.377-.878-5.476-2.26-5.476-2.26s-4.293-1.915-4.51-2.227c-.171-.247-.02-.647-.02-.647s-1.954.567-2.092.747c-.136.179-.065.451.079.595.145.145 4.772 2.124 5.574 2.428.8.304 7.166 2.278 7.473 2.345.307.068 1.074.235 1.277.184.204-.052.417-.214.279-.469-.185.048-.636-.049-1.23-.231zM202.933 25.506c-.104-.077-.383-.19-.772-.323l-.727-3.202-.821 2.725c-.202-.059-.41-.119-.622-.178l-.684-2.764-.753 2.368c-1.264-.343-2.402-.639-2.758-.743-.888-.258-7.43-2.031-7.904-1.609.718.254 10.299 2.994 13.164 4.514.438.232.7.692.512 1.301-.454 1.074-1.826 1.9-3.888 2.522a3.217 3.217 0 0 1-.48.096l-.428-2.42-1.116 2.416c-.413-.047-.84-.081-1.172.084-.314.157-.484.593-.266 1.1.275.635 2.267.301 2.89.191 1.63-.286 3.554-1.008 4.767-1.912 1.066-.795 1.564-1.544 1.73-2.104.246-.822.205-1.409-.672-2.062zM203.353.74c-.283-.398-.582-.652-1.672-.667-.793-.01-1.771.284-2.578.544-1.573.507-5.225 2.435-7.497 4.142-2.616 1.966-6.862 5.502-8.866 7.458-.953.932-7.76 7.534-8.336 8.12-1.096 1.11-.445 2.248-.24 2.486.207.241 1.748 1.262 1.98 1.312.307.067.758.134.995-.071.208-.179.254-.281-.07-.706-.155-.204-.778-.757-.922-.926-.308-.356-.206-.817-.037-1.004.17-.188 3.222-3.535 4.133-4.413.59-.57 2.667-2.514 4.945-4.526l1.348 1.612-.072-2.728c.36-.311.716-.613 1.069-.911l1 1.656.387-2.795c.363-.292.718-.57 1.047-.817.93-.698 2.605-1.902 4.144-2.965l.927 2.005.299-2.84c.297-.199.576-.384.83-.548l1.033 2.388.21-3.128c1.007-.52 1.767-.696 2.705-.738.462-.02 1.062.464 1.024 1.044-.057.919-2.16 3.624-2.533 4.008-.374.384-5.78 6.205-6.213 6.641-.441.443-4.006 4.345-4.522 5.019-.518.674-.813 1.509-.813 1.509s6.859-6.95 7.572-7.71c.412-.44 2.045-1.995 3.642-3.602l1.512 2.15-.101-3.601c.21-.223.41-.437.599-.644l1.379 3.093-.136-4.573c.813-1.055 2.044-2.779 2.13-3.942.04-.55-.021-.933-.302-1.332zM155.493 12.786l-2.82.258-9.29 5.634 1.9 2.095-5.24 2.702-8.24 6.611-7.83 7.412 4.01-3.042-.25 1.005 1.82-2.269.12 1.054 1.25-2.488.04 1.583 1.3-2.574-.11 1.839 1.74-3.122-.11 2.13 1.78-3.275-.01 2.537 1.72-3.768.15 2.571 1.74-3.7-.14 2.861 1.89-4.245-.11 3.286 1.85-4.16-.34 3.271 2.12-4.229-.28 3.474 2.22-4.4-.14 3.441 2.91-5.372-.53 4.19 2.81-5.201-.31 3.917 2.77-5.627-.02 4.206 2.35-5.592.28 4.563 3.5-7.628-2.3 1.205 1.3-2.983z"/></g></svg>
\ No newline at end of file
diff --git a/refdoc/src_images/pike-logo-white.svg b/refdoc/src_images/pike-logo-white.svg
new file mode 100644
index 0000000000..3d4996701d
--- /dev/null
+++ b/refdoc/src_images/pike-logo-white.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="47.908" width="203.74" viewBox="0 0 203.73994 47.907825"><g fill="#fff"><g stroke-opacity="0" stroke="none" stroke-width=".5"><path d="M17.936 16.415c.238-.875.368-1.576 1.355-2.276a5.347 5.347 0 0 1 2.946-.919c3.86 0 2.596 4.421 2.096 6.259-.346 1.27-.897 2.845-1.721 4.071-.812 1.182-2.094 1.838-3.81 1.838-2.941 0-2.75-2.057-2.32-3.633l1.454-5.34zM8.005 8.098L0 37.513h12.133l2.573-9.455c1.363 1.97 4.067 2.845 7.314 2.845 4.35 0 8.052-1.663 10.8-4.333 2.25-2.189 3.576-5.034 4.255-7.529 1.429-5.253.156-11.381-8.67-11.381-4.166 0-7.848.919-9.873 3.633h-.123l.87-3.195H8.005zM49.289 30.465H37.156l6.087-22.367h12.133l-6.087 22.367zm6.67-24.512H43.827L45.446 0H57.58l-1.62 5.953zM80.777 15.802l6.55 14.664H74.642L71.2 21.493l-3.826 2.801-1.68 6.172H53.56L61.733.438h12.133l-4.407 16.195 3.314-2.495 8.997-6.041h10.54l-11.533 7.705z"/><path d="M102.143 16.633c.438-2.057 2.213-3.852 5.399-3.852 3.432 0 3.959 1.663 3.364 3.852h-8.763zm7.976 5.822c-1.015 1.926-2.761 2.714-5.52 2.714-3.676 0-4.425-1.751-3.586-4.158h20.958l.32-1.182c2.002-7.354-3.061-12.168-13.478-12.168-4.473 0-9.551 1.094-13.381 3.458-3.524 2.145-6.072 5.428-6.895 8.448-.87 3.196.074 6.26 2.86 8.404 2.947 2.232 7.229 2.933 11.826 2.933 7.415 0 14.834-2.495 18.21-7.922l-11.314-.527z"/></g><path d="M124.273 8.018h-.736v2.355h-.686V8.018h-.745v-.582h2.167v.582zM126.403 10.373h-.471l-.716-2.394h-.008v2.394h-.578V7.436h1.074l.514 1.76.54-1.76h1.075v2.938h-.686V7.979h-.018l-.726 2.394z"/><g><path d="M194.783 1.856c-.05-.386-3.471.589-7.848 2.18-1.288.507-9.864 3.751-11.253 4.395.118-.537.184-1.712-.297-3.183-.733-2.241-2.39-2.167-3.99-1.598-2.126.755-3.37 1.739-4.53 2.703a19.54 19.54 0 0 0-2.398 2.397c-1.148.223-2.078.625-2.726 1.013-.733.439-1.638 1.248-1.982 1.91-.128.243-.23.401-.127.435.22.071 2.327-.602 2.586-.673.103-.029.216-.06.33-.09-.868 1.359-2.125 3.422-2.067 3.541.077.162.213-.018.213-.018s1.512-1.701 2.938-3.239c.63.991 1.194 1.72 1.68 2.151.502.445 1.354.961 2.19 1.168.72.179 2.154.193 2.359.144.467-.027.654-.198.61-.308-.044-.11-1.51-.259-2.031-.37-.524-.11-1.196-.353-1.747-.772-.422-.321-.958-.799-1.354-1.631-.182-.375-.413-1.284-.413-1.284s1.24-.277 1.89-.297a6.251 6.251 0 0 1 1.652.185c.287.077.854.412.854.412s-.43.683-.397 1.085c0 .799.28 1.102.843 1.389.578.248 1.166.204 1.63-.237.303.198.513.572.893.784.399.297.826.262 1.079-.02.172-.188.006-.907.006-.907s-.162-.201-.396-.497c-.106-.136-.46-.731-.761-1.22-.452-.73-.61-.98-1.26-1.54-.894-.772-2.196-1.201-4.114-1.275 1.054-.779 2.122-1.417 3.52-1.854 1.312-.411 2.385-.314 2.803.196.419.509.532 1.53.467 2.126-.056.5-.312.912-.37 1.397-.06.486-.102.8.088.919.3.192 2.439-1.122 2.84-1.337.51-.274 2.259-1.046 3.459-1.599 1.859-.857 4.719-2.083 6.348-2.765 1.604-.672 7.91-3.077 8.337-3.305.422-.227.563-.432.446-.511zm-24.507 9.923s.479.48.567.7c-.16.159-.17.13-.326.225-.17-.188-.551-.464-.551-.464l.31-.461zM159.723 9.175c-.145-.289-4.352 1.091-4.737 1.163-.553.104-1.438.039-2.054-.241-.274-.125-4.313-2.312-4.313-2.312s-3.83-2.505-4.266-2.686c-.647-.271-1.306-.43-2.034-.173-1.464.516-3.153 1.659-4.224 2.481-1.972 1.513-3.246 3.665-3.36 4.181-.168.767-.192 1.156.603 1.803 1.322 1.077 6.685 3.667 6.87 3.692.189.025 1.169.175 1.508.089.34-.086.809-.241.825-.462.016-.222-.451-.067-1.117-.406-.732-.373-5.371-3.058-5.645-3.278-.137-.11-.88-.466-.804-1.028.067-.498 1.544-2.133 2.358-2.697 1.572-1.086 2.764-1.532 3.17-1.635.853-.215 1.959.011 2.539.299.58.287 3.717 1.812 4.707 2.285.988.474 3.102 1.387 3.588 1.446.329.04 1.548-.03 2.322-.406.317-.155 2.15-1.088 2.447-1.199.3-.112 1.764-.627 1.617-.916z"/><path d="M141.473 8.716l1.96-.678 6.93 4.909zM139.203 10.184l1.65-1.202 6.8 4.977zM137.593 12.039l1.09-1.308 6.79 4.503zM144.223 30.766c.307.212-4.73 6.173-6.285 8.361-1.604 2.252-4.197 6.021-4.197 6.021s-.254.426.138.544c.392.119 4.147.218 4.147.218s4.503.201 5.133-.176c.629-.376 1.836-3.904 2.047-4.5.21-.597 2.549-7.668 2.553-6.512.004 1.159-.995 6.371-.995 6.371s-.79 3.459-1.001 4.056c-.212.597-.684 2.019-3.28 2.495-2.593.475-8.137.176-10.181.114-2.043-.062-1.326-2.235-1.03-2.781.297-.546 5.16-6.688 6.294-7.893 1.655-1.758 6.349-6.53 6.657-6.318z"/><path d="M140.693 45.338l1.31.03 4.02-10.721zM137.913 45.243l1.45-.004 4.4-10.091zM134.913 45.133l1.6.029 5.53-9.652zM158.543 22.944c.359.561-3.006 2.716-4.887 5.871-.287.58-1.422 2.677-1.334 3.886.088 1.208 1.199 2.449 2.51 2.623 1.313.175 4.595-.728 5.87-1.268 1.276-.541 3.062-1.354 3.462-1.492 2.772-.773 3.414.041 3.414.041s-2.596.622-3.395 1.041c-.798.419-4.938 2.517-6.708 3.11-1.73.579-5.156.943-6.495.375-1.336-.566-1.503-1.646-1.48-2.268.054-2.656 1.259-4.927 2.84-7.091 1.562-2.133 4.339-4.175 4.689-4.373.35-.197 1.113-.752 1.514-.455zM191.893 32.087s-10.09-.235-12.516-.381c-2.427-.146-5.885-.937-6.932-.781-1.047.157-3.102 1.763-3.102 1.763s1.565-.251 1.829-.21c.264.042.774.203.87.432.094.23.268 1.345.268 1.345s2.21-.993 2.94-1.251c.732-.257 1.966-.389 2.267-.066.297.322.063 1.686.105 1.855.043.171.3.324.3.324s.968-.896 1.205-1.102c.237-.205 1.7-1.009 2.287-1.122.588-.113 1.286.218 1.397.515s-.108.859-.108.859.313-.003.46-.09c.148-.084 1.01-.644 1.215-.732.328-.14 1.42-.398 1.906-.482.484-.083 4.62-.336 4.986-.465.367-.129.623-.411.623-.411zM141.663 19.5s-12.443 10.321-12.877 10.756c-.433.436-6.215 6.208-6.92 6.566-.705.36-1.744.405-2.016.475-.272.069-2.407.791-3.163 1.09-.757.301-1.802 1.18-1.944 1.616-.145.434-.084.961.455 1.513.537.552 2.386.845 2.386.845s1.926.599 2.42.98c.495.381.302 1.191.345 1.506s.602 1.804 1.088 2.006c.484.203.79-.164 1.164-.403.375-.24 1.21-2.371 1.21-2.371s.43-1.882.997-2.93c.568-1.049 2.463-2.291 2.463-2.291s-.21 1.391-.006 1.629c.206.237 2.707.039 3.406-.066.697-.104.772-.452.953-1.31.198-.937.31-1.924.47-2.436.145-.46.589-1.036 1.09-1.344.502-.308 2.05-.914 2.05-.914s-2.061-.13-4.943 1.07c-1.277.531-2.318 1.419-3.016 1.813-.697.394-3.228 2.41-3.703 3.254-.474.844-.803 1.833-.996 2.497-.195.665-.381 1.219-.695 1.262-.314.044-.197-.349-.307-.501-.112-.153.1-.605-.064-.962-.162-.357-1.8-1.247-2.94-1.465s-2.24-.556-2.386-.7c-.145-.144-.222-.306-.104-.553s1.309-.838 1.998-1.122c.688-.282 2.347-.883 2.72-.833.376.05.479.168.48.458 0 .289-.134 1.048-.134 1.048s1.782-2.262 2.376-2.92c.594-.656 8.48-7.975 10.843-9.948 2.36-1.974 5.979-4.558 7.15-5.214 1.15-.643 1.974-1.009 1.974-1.009l-1.824-1.092zm-13.13 18.276c.612-.806 2.73-1.668 2.73-1.668s-.352.397-.514 1.833c-.072.641-.205 1.193-.635 1.355-.43.163-1.826.353-1.881.078-.068-.345-.068-1.11.3-1.598z"/><path d="M128.763 39.257l1.05-.123.09-2.102zM191.253 30.041l.453-2.37-1.807 1.905c-2.377-.878-5.476-2.26-5.476-2.26s-4.293-1.915-4.51-2.227c-.171-.247-.02-.647-.02-.647s-1.954.567-2.092.747c-.136.179-.065.451.079.595.145.145 4.772 2.124 5.574 2.428.8.304 7.166 2.278 7.473 2.345.307.068 1.074.235 1.277.184.204-.052.417-.214.279-.469-.185.048-.636-.049-1.23-.231zM202.933 25.506c-.104-.077-.383-.19-.772-.323l-.727-3.202-.821 2.725c-.202-.059-.41-.119-.622-.178l-.684-2.764-.753 2.368c-1.264-.343-2.402-.639-2.758-.743-.888-.258-7.43-2.031-7.904-1.609.718.254 10.299 2.994 13.164 4.514.438.232.7.692.512 1.301-.454 1.074-1.826 1.9-3.888 2.522a3.217 3.217 0 0 1-.48.096l-.428-2.42-1.116 2.416c-.413-.047-.84-.081-1.172.084-.314.157-.484.593-.266 1.1.275.635 2.267.301 2.89.191 1.63-.286 3.554-1.008 4.767-1.912 1.066-.795 1.564-1.544 1.73-2.104.246-.822.205-1.409-.672-2.062zM203.353.74c-.283-.398-.582-.652-1.672-.667-.793-.01-1.771.284-2.578.544-1.573.507-5.225 2.435-7.497 4.142-2.616 1.966-6.862 5.502-8.866 7.458-.953.932-7.76 7.534-8.336 8.12-1.096 1.11-.445 2.248-.24 2.486.207.241 1.748 1.262 1.98 1.312.307.067.758.134.995-.071.208-.179.254-.281-.07-.706-.155-.204-.778-.757-.922-.926-.308-.356-.206-.817-.037-1.004.17-.188 3.222-3.535 4.133-4.413.59-.57 2.667-2.514 4.945-4.526l1.348 1.612-.072-2.728c.36-.311.716-.613 1.069-.911l1 1.656.387-2.795c.363-.292.718-.57 1.047-.817.93-.698 2.605-1.902 4.144-2.965l.927 2.005.299-2.84c.297-.199.576-.384.83-.548l1.033 2.388.21-3.128c1.007-.52 1.767-.696 2.705-.738.462-.02 1.062.464 1.024 1.044-.057.919-2.16 3.624-2.533 4.008-.374.384-5.78 6.205-6.213 6.641-.441.443-4.006 4.345-4.522 5.019-.518.674-.813 1.509-.813 1.509s6.859-6.95 7.572-7.71c.412-.44 2.045-1.995 3.642-3.602l1.512 2.15-.101-3.601c.21-.223.41-.437.599-.644l1.379 3.093-.136-4.573c.813-1.055 2.044-2.779 2.13-3.942.04-.55-.021-.933-.302-1.332zM155.493 12.786l-2.82.258-9.29 5.634 1.9 2.095-5.24 2.702-8.24 6.611-7.83 7.412 4.01-3.042-.25 1.005 1.82-2.269.12 1.054 1.25-2.488.04 1.583 1.3-2.574-.11 1.839 1.74-3.122-.11 2.13 1.78-3.275-.01 2.537 1.72-3.768.15 2.571 1.74-3.7-.14 2.861 1.89-4.245-.11 3.286 1.85-4.16-.34 3.271 2.12-4.229-.28 3.474 2.22-4.4-.14 3.441 2.91-5.372-.53 4.19 2.81-5.201-.31 3.917 2.77-5.627-.02 4.206 2.35-5.592.28 4.563 3.5-7.628-2.3 1.205 1.3-2.983z"/></g></g></svg>
\ No newline at end of file
diff --git a/refdoc/src_images/pike-logo.png b/refdoc/src_images/pike-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..52812a4a155b3ed7f9c26a97292306cd2da201b0
GIT binary patch
literal 4711
zcmeAS@N?(olHy`uVBq!ia0y~yU^v6Tz+k|^#=yW3TQqe70|Ns~v6E*A2L}g74M$1`
z0|NtRfk$L90|W1M5N34Jm|elZz#v)T8c`CQpH@<ySd_|8US6)3nU`IhoLG>mmtT}V
z`<;yx1B2ibPZ!6KiaBrRmhT9?I`i25qpn>+tj#YX1d<tDlZ?VP9BE?hHMMd)>(FD-
z$$B(JsCTAIZ`vZY!Z#Zi_0P)K@L)xUt(0K(VF^<!Lr2Ghev?0)mVa-xb9SwN^z(Vu
z`ZmS)o<Fp_Q+w_E+x)kCPlaFSjACVcqxJF%%cO8;j^pVsnwK=Iwz9~Tw+lQ|-;$po
z%5LCt$!=1cSCq=jNqtjSxG{)NZYwVSa#-l4J&RR&NWFB1J;U6F!wu?PJ<ZR<t~zc=
zPx}2k%JaViM`EUuFSE8~gZ`;m$2dIeCw-Z*Wd2EOFGg;awQ~RWyDcx9x`B_uY|55G
zrjtsZ{m<6Domg@EPfPX!W`-}Ud`x|v&3nb<W-~2kJny+HR!%<MLrUzwoYqTU&vuVj
ziYxnVCaS!=cJ153yNo^lA<N&Ly;#mHrt;~=ip9TfH?ZWe#4zie*)#d)fel(O_cQpg
z#PyV1XR>Buv@kT5d&cyg;rf#o^BJEp{JpiTJ(uIb_s-_OQ)K?m>-@65G$cOU?TF(x
z{SWOH9eK=VxreLgvgl}i%v-1Je4F!zb>H-(2Z|4rH{AR9``&@Ml5z8yo-@5>vOoX9
z(xh&Gee{=&XBl}|_s#jRzP#_>og<vZf$m>RQ<*og8Z16x9L4fS{KD40@2?o|%-VU}
z=|SOxzy!}d*OCmG%~<NV_VDVk<}tcGxy8fyPo}b_Ep*S`M$V7FeIGryI*{|Awd$)j
z=SM{zmTNBr7<CSFcM3ntmQ~G`b4XtxZ=g_Gz!ZP*-u&DTt9D8iaBQeb&Ej0G7diEX
z@dNz>?lZINnab9!E!V!YTK+@Ilb`hmSQhv{`z`#a{PYLEOQJul3i9`SWBkCK(5$qF
zpUJNC%Xxuv_dT<DPi}eLQ+~0(aXQy^?PH1!#wxjCsqyvlPCG0w@lM+^e~GM0u6Aau
zr|-;dpH=rNzvT2Z_nal=w4g~RS!F5DgWpaZ;VCb!_kCYu_HR>2(0+kK>Y`7ibYHH}
z`cbR&vPa<1ZP6cJr*B!kWNk`v$&4lcCVk>QtK=!~JxlXtrl-H>tT3Or9F=(8mnxp+
z9>10@;hf~wBJeNDZJNSMCeK!jYwVNGP5CnKjm=J<pm<OFDO)D1q&)tyMc~l<(_c3q
z`Fm}`mj;`(WnNO!PBZ3a8%JD{{`7mN$0fl}pDTSYtyhVi-#_zc-JF%re%#$T$&X*L
zCeEeJZ_>JnB{P<+eOhR%a(~^74|g|A4AFICZ2l0oOQ(_V&3C=mKM&k4<mx+fQGTY!
z{O{|YK7Gj>6Q{bqy7BAj4^j*={5Bn-olze(KS(F6R{Fj}HiCNxQw9HyE~V84eb1Il
z-ZN)<+%TVUH^cYDuP@XcgbjpdNZr=!ELs!Y^4#Hp#)IgY*}D^}A3u(%pT>Ni+5NGj
ze!}ON*)I<?RxA*I?HvAKna^+K?yaY{>=$^yZ2s~6=XI~!dGDzH`o6REK!(hd)uQhM
zlL8oR8_x?@=(4jttB9GdalZew&FsAm`$G>tPF|xde)sAJ7t8ruT31TxFzYewN_l50
zXMg<Sf$bZ*!Y+Mge$zN#dE)i7h__7o1<ehDH!A96*8gGpCwiODJ9+=QgIQNCBY3MA
z`qwg)9FJSAbC2~M`?~|jsvO&1E1%u?@x9~$J<($Y@(&jB#Gkmib?3MAN1QtZ4Y>7L
zu2y<(l#9?!ySzqv8=J9)(T)aYp`SMM7xN#m?zGvat>m5<9vRmtcIu7R57#+<f7QL@
z_!;i5u6n4OI!Ch7=a}2yy9a(%Y`EVk-fXz>t-%AOgqXHE=Lb9wQf)4-JNE9*x&!5f
zF;CszoU5JmjI}VvukVfCKluZB2mVcoXfY~z&8Y9X%X~v_N$AXP%NhC^_ddE`tzv7v
zN3@KkOk2r2%j%4N(U)k|OZ6NkPb+#3-J9;UV$13^>^74${Id&6uj=oOJa*1x_0{{w
zgrB|tv9sr_&E?aN_se~ZO1z%=(5J)ZIAi_MSBc>X6?^_En4M5(^q*MyE#m8Lx%UzB
zfi7pYi`FX!#(hZo=dma5%1OcBKRg!7pFFV2$#ivwTt4%3rvIJnKhsS=>{!%cvtIqv
z4Q2QLdtH7-8*SOUqAq+U*P8HWJNb^TO5a)``ue@}gV>eYaw}H8dTM6c(>VFVs{InH
zwQN7WD>5z+FZ_Na`RRw8{Tsip;{M?LAk(HoJpGAef9{-n2O<(`mb{j{9q)AJ{$cA=
zk0Z85GsHwYzDu-lV+m8OX56oN`JaJJV)plYOvys=CyE}hr<6Q9k#2oSmZAS?Ma~S5
z{S)qlart;ZDfC$)?OD3}l=}@mjg@K)@hZN$bC^oB55Hf@5*L2Wf^XZAccB~3nz60k
z{yOPvM*ghck8jp(u%7p3=?0eDd3R4r{GYf@JuYYd(X2~;F58Qyq_=o6+>lybak}xc
z(RJ^)I@OO)2Hie4DbYmpVJgF&fVS&rx~^zH`YKb~zU1(O8_uSEZJTy`O<Abk7ah{Q
z)8Raq&3gX_->WR+rZ&j3>bu3&v+NUEzn*Q)%uMqMugdnH-)MVf=^5MK3A5AV6FzID
z{4p}%U!C`Ob;f?)u<uo&zh%4(R~>bbi*36vFI>5I!s7h*B{RMk`UP&ivA!$4DsvIf
z_8`k{#nkr5nBN^g(&d@T_Sv*<ZSy>GRqnQ;`lU;{bB-VW`1#hgQ<Ep>9<O-sdSGGb
zmirR>AMg9R<L5L^{U(hR&%ga!rivy+wQb{EFQq9lZTJ7m&Mzw~Rvh|#r}5UCgH?-M
z8`hZ~X#2a+LT!`q*?TJ%eLrUXEc=G_Hklin`Zm4k%6;nkB<H%&+v`WW3+8*}t`<#5
zdUSfnexCKFp4$`8oxG4g-{ZHQrFBzU=px;~ODovwZu5O#-!kdqpQy(BZ%aesc-FDR
z9o#r0pP~GEU|V3s-8ipOYj1s-?<+Mw?+CH=$=d62l2duP_mXROQ+oehNm`$IQ$%_W
z-)2{({-}bajolV!pB^aNQLkzfuJ7hhzvfhpTIK?;<x;lV%h%7*6;F!QeyMD!yHu{I
zXWHeOU0zb+PCJ%5{Z`xgEj5WFG0rw+g{mxD!fT^HL37#VCwb}|X<Q;AGjaF-z|JpQ
zlQ><QrdXsVrye+B)!V-?;%FWJjs7(A0>;yY3yQ=Fj5cm#v9PTBwtlkA;*7Fj`Eb><
z-`4J}-zfA{FiY>`8n*Y|Rr_v;-%y<u<zC>-kyyCoy{e{aUBjFm(_LTX%{-dpnH_#}
z+vX*YRch_aYXf+{+d5rZZF*tqVd=H03~!XxPw7nwf2FQ6ca5laLjJV*H`lAKRei5F
zX|klK(~R3umP&QHE4!BzJ8^_gO=uBVmV7??`L3yRCQsvIE^wEO6Beq}Reh%H`m4{Q
zo$+{~-;uBKnm=Yt`)aO!z2JY>%HI}|9|dII-;i@ZV}9u5)KdNV2WE167hEW+l_{P*
zd*aW+J&*X0-CM4<==Dxrht2IDT3mM3S)BOA93ySo7IQ9f+1tjC#TAxqD_<J8GACIy
zSzAxMu4*Z_*0)`9o(I2~UwdkWO=PD+JEx`OzOZH<>9C5I*1@rEpW7=A{&2Ib6Mc7;
zRr+mlLv!Qf57oL7zxp4|n)<l$|G~nUMT%{D7Mz<yTPt_$$mW`NWO3G$i@Z13ckrlZ
z#I;;5{`G+Kzg5|E|78&jGjCl=j8iCQ34HRofOVHm+Qp*My!RzD+B0V=PLMLG?LPDQ
z0KdIyh83^1_NVvD_4{h{b^P}+<t=ualr)p^D!=<dc~-N|JqIR#_55?r@6hh^7c0uM
zwGO|J|KRt9JxV$<|JhFIvyqpgubvY3pAcKP=S^%*dt>ec)&qS<JNi7T*Z)7V*+Tnk
ziA?P}kv*r96?IR0yq?Hc9Iw=$FJ7s(*R#B-#`gH*LoQVXZ<5&jg7$DPKe~L1dBf(V
z*|H9^9~j*`U8wX}d*bugAOEXAj(y6pXLZOaF9|=NrX{De&bw4{AN;7Tx#@<=r>sLa
zS^s+%dpyZY2-ugn%6+w5gi~IFYh>SAml=nz$kdi!3jel<%_>t<gTepVi{BIWMQ;<E
ztTDMPDDgngp~~d;M^k1vNq$;w@u5PN?^xO5t}o>eyd!LDnz)2lhdto=F#oZ__nHU$
zH4|s6e3E7Pv+lzGH{x5RPOLo`lki=r$<ObJsiFJ+aHZOlMNxY~mnR*U>F@PCU$KJq
zJrn!Zqz0Mh%kSHhdlMzssaA@m`>bi4%M-e?GJ<z@>)i{luV{rg{aJn7ZcmT$|8T~5
zt&7{1{F;$%Zen-4e3N+a<wUzBJ7u<t-Er^y6tPFOZo-ND(=z>^g<tCHd_KS=XQDYH
zrp3QL#^9>hjOO5%*<LC~j=eo<5m;87v;NHC-KRhPn9w=t<2E51>%`p!mTzl(1nbgw
zKQ4M>xufgTY?sHf{Tt_tEWABU)OPFLjb1z-=H?u}QZnP@#G9^5US2cS*tj|+<)&ib
zw5lbCr_?Sy&@c2;m$_@+g--7Z^@;m5o@^9Q&y@4)4V@Y|uc^>pmVd^~iQhFNw%%;g
z3V$qf|M8+Z+plUx+cu~l=h)+Xu4De>hS^<P=Jp(xoVzi+AgyNla<7?F*yae$pVU^A
z!}0KwhjqlIiId7Enz&q=^@-Ea<JWGPmg<m8vWhL@t6w~LH%aRmYwCv@j)#|cYQujn
znJn`D!uL~i`I=Y%@w)b7`hh6|hhkGJ)~RKtTSn|zxx`l`S7GJuFdjMmDZyU%CiNTE
zdR}@wX&#@Vj@J}T{lf{Km!CZNymV6D#QRrcJkvd+M4T#?^VDjT-QwRC`cH{ne>=D0
znT*~!Us<lX@lBZjeT%@MuRBha@2R==NqZ98iB0wj^Yx5vPcL|PeEB7|c@zHUFW6ct
zHT7qHQ}1u>jfM8|t8dN@Oe#NfQQog}hG3aF^PV8}$k`uGPBq@x^;PDag&n`O(zm1A
z+!QNrPd7SR?)u}u^|rfleY?+WT>48b=FR-3V;@(pws^E;Mr-I<=MCcT_hhMgEwSf2
zv79k=zy6<?BfXqPritli`!`xwpRcIpmDx7qOjqi;2hHJHy5G7t{`zefc5>N+o@s?w
zJ{hYmS$;TXPR(StFsTPqf6TRbaXjgEs!iy%_JsF0=T5PEve^18<A>#|9$Xh^pLxHF
z`4@{<#g&4Pf5JJ|{D=Emzdqh8mT>*ku^UtOD){v+{%|gM^6b4c1XjK@V88P881EMA
zf~C*iSackFe4_gQp@c)nfA$@T+bCuz{2=6w-22(P<u+v9=X@U*>7#LIIsb?J9bp-E
zd>M6Hxqh0fEnk%+`o_1YeG&8R@ZT}3*j~Og@YX06h+@{(f8;Wwd9OqAhsx8;j}z<#
z<mYT>n4fa<ku3B5{`>sLUj=`!*lTWgc3FYj%?V16p9wyge#82!kBs~24Zo|FTYXt;
zcXe{;ofYejFE`sz#I*id@y5MYlXf^Kh<_LUvE<~-1M9smh#Q?h{%FfmwWK%Q5xHJI
zM|y<|yk;7j==;qJeOF#?b^2;ns`k~Q8JFBPnFP2$klFP2X~4n0No=R}F2DTb_`&x;
zWYN+W<*K$C|1aHo>srw}ng8d$kag=~y)TKYoMmG3cqOLpFYn2v*l_jR-Y19mRC~-)
z&zx3M@XK4V<!SEa&umg24BG<pj<rv^-~75NPp#O`#ExZA!L=Kr5v<aEn<sphe5|~2
zdZv}1^~{d9Q-mLX7k->qY&KI~DQiLFR5=SjL-}gk>nCIGPkVOwTic@>rw`wFY$Ce+
z$Q|xIGaj3BJa4FNm@Iw%NV}k%bm&gT8_8lDF4`{J`}>XqvnliP&3{&$`JVkyIePg6
zr*(ffEUXvSbG%`Bc^ms#d%IE#JH<~qZ<zL(ZnKoHKEkE`d&}`eWnPm2`3LuNBl{LV
z6o35Wu;0%2_Dh@GHQ!0JCT)~%*!uX%%huIe{C&Gm|K0eP^+(KxtG9Ob^O^*NyO_Sp
zm^0<4B_G>6v9~?tD<7%U*G#YpEPdTxZ<MTaE=h07+j;$$U+i|-`u3hzjdVuBQnq!j
zJK6u6c`sa+zMjj(`m&7j&#W!c^NzOt3(0xHe_-81yB%zDNoM)XylXBU5d7=9BdSO)
z^%TP+ml>k!2P%K0%v$<G;|4R=tC%~nc^xLK`O&9meP@%3xO$*#KYL|Z>$d4f%e)K!
zp2(QPdPi3No2}6{Yq{rHwZ_}#`|ka;MJi*#;>OiB%YzrjG@M%Aqjx~>*_(w5^BI3{
z3y-&wdb#o}@0ubG#gJ;fo2iqkP9M#-RavW+-XxMWn@eu{e$QFTFBLtnw+h@_Gk=S=
b`9H?1W%tdZ87G2<kr+H({an^LB{Ts55v2y=

literal 0
HcmV?d00001

diff --git a/refdoc/src_images/pike-logo.svg b/refdoc/src_images/pike-logo.svg
new file mode 100644
index 0000000000..3d4996701d
--- /dev/null
+++ b/refdoc/src_images/pike-logo.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="47.908" width="203.74" viewBox="0 0 203.73994 47.907825"><g fill="#fff"><g stroke-opacity="0" stroke="none" stroke-width=".5"><path d="M17.936 16.415c.238-.875.368-1.576 1.355-2.276a5.347 5.347 0 0 1 2.946-.919c3.86 0 2.596 4.421 2.096 6.259-.346 1.27-.897 2.845-1.721 4.071-.812 1.182-2.094 1.838-3.81 1.838-2.941 0-2.75-2.057-2.32-3.633l1.454-5.34zM8.005 8.098L0 37.513h12.133l2.573-9.455c1.363 1.97 4.067 2.845 7.314 2.845 4.35 0 8.052-1.663 10.8-4.333 2.25-2.189 3.576-5.034 4.255-7.529 1.429-5.253.156-11.381-8.67-11.381-4.166 0-7.848.919-9.873 3.633h-.123l.87-3.195H8.005zM49.289 30.465H37.156l6.087-22.367h12.133l-6.087 22.367zm6.67-24.512H43.827L45.446 0H57.58l-1.62 5.953zM80.777 15.802l6.55 14.664H74.642L71.2 21.493l-3.826 2.801-1.68 6.172H53.56L61.733.438h12.133l-4.407 16.195 3.314-2.495 8.997-6.041h10.54l-11.533 7.705z"/><path d="M102.143 16.633c.438-2.057 2.213-3.852 5.399-3.852 3.432 0 3.959 1.663 3.364 3.852h-8.763zm7.976 5.822c-1.015 1.926-2.761 2.714-5.52 2.714-3.676 0-4.425-1.751-3.586-4.158h20.958l.32-1.182c2.002-7.354-3.061-12.168-13.478-12.168-4.473 0-9.551 1.094-13.381 3.458-3.524 2.145-6.072 5.428-6.895 8.448-.87 3.196.074 6.26 2.86 8.404 2.947 2.232 7.229 2.933 11.826 2.933 7.415 0 14.834-2.495 18.21-7.922l-11.314-.527z"/></g><path d="M124.273 8.018h-.736v2.355h-.686V8.018h-.745v-.582h2.167v.582zM126.403 10.373h-.471l-.716-2.394h-.008v2.394h-.578V7.436h1.074l.514 1.76.54-1.76h1.075v2.938h-.686V7.979h-.018l-.726 2.394z"/><g><path d="M194.783 1.856c-.05-.386-3.471.589-7.848 2.18-1.288.507-9.864 3.751-11.253 4.395.118-.537.184-1.712-.297-3.183-.733-2.241-2.39-2.167-3.99-1.598-2.126.755-3.37 1.739-4.53 2.703a19.54 19.54 0 0 0-2.398 2.397c-1.148.223-2.078.625-2.726 1.013-.733.439-1.638 1.248-1.982 1.91-.128.243-.23.401-.127.435.22.071 2.327-.602 2.586-.673.103-.029.216-.06.33-.09-.868 1.359-2.125 3.422-2.067 3.541.077.162.213-.018.213-.018s1.512-1.701 2.938-3.239c.63.991 1.194 1.72 1.68 2.151.502.445 1.354.961 2.19 1.168.72.179 2.154.193 2.359.144.467-.027.654-.198.61-.308-.044-.11-1.51-.259-2.031-.37-.524-.11-1.196-.353-1.747-.772-.422-.321-.958-.799-1.354-1.631-.182-.375-.413-1.284-.413-1.284s1.24-.277 1.89-.297a6.251 6.251 0 0 1 1.652.185c.287.077.854.412.854.412s-.43.683-.397 1.085c0 .799.28 1.102.843 1.389.578.248 1.166.204 1.63-.237.303.198.513.572.893.784.399.297.826.262 1.079-.02.172-.188.006-.907.006-.907s-.162-.201-.396-.497c-.106-.136-.46-.731-.761-1.22-.452-.73-.61-.98-1.26-1.54-.894-.772-2.196-1.201-4.114-1.275 1.054-.779 2.122-1.417 3.52-1.854 1.312-.411 2.385-.314 2.803.196.419.509.532 1.53.467 2.126-.056.5-.312.912-.37 1.397-.06.486-.102.8.088.919.3.192 2.439-1.122 2.84-1.337.51-.274 2.259-1.046 3.459-1.599 1.859-.857 4.719-2.083 6.348-2.765 1.604-.672 7.91-3.077 8.337-3.305.422-.227.563-.432.446-.511zm-24.507 9.923s.479.48.567.7c-.16.159-.17.13-.326.225-.17-.188-.551-.464-.551-.464l.31-.461zM159.723 9.175c-.145-.289-4.352 1.091-4.737 1.163-.553.104-1.438.039-2.054-.241-.274-.125-4.313-2.312-4.313-2.312s-3.83-2.505-4.266-2.686c-.647-.271-1.306-.43-2.034-.173-1.464.516-3.153 1.659-4.224 2.481-1.972 1.513-3.246 3.665-3.36 4.181-.168.767-.192 1.156.603 1.803 1.322 1.077 6.685 3.667 6.87 3.692.189.025 1.169.175 1.508.089.34-.086.809-.241.825-.462.016-.222-.451-.067-1.117-.406-.732-.373-5.371-3.058-5.645-3.278-.137-.11-.88-.466-.804-1.028.067-.498 1.544-2.133 2.358-2.697 1.572-1.086 2.764-1.532 3.17-1.635.853-.215 1.959.011 2.539.299.58.287 3.717 1.812 4.707 2.285.988.474 3.102 1.387 3.588 1.446.329.04 1.548-.03 2.322-.406.317-.155 2.15-1.088 2.447-1.199.3-.112 1.764-.627 1.617-.916z"/><path d="M141.473 8.716l1.96-.678 6.93 4.909zM139.203 10.184l1.65-1.202 6.8 4.977zM137.593 12.039l1.09-1.308 6.79 4.503zM144.223 30.766c.307.212-4.73 6.173-6.285 8.361-1.604 2.252-4.197 6.021-4.197 6.021s-.254.426.138.544c.392.119 4.147.218 4.147.218s4.503.201 5.133-.176c.629-.376 1.836-3.904 2.047-4.5.21-.597 2.549-7.668 2.553-6.512.004 1.159-.995 6.371-.995 6.371s-.79 3.459-1.001 4.056c-.212.597-.684 2.019-3.28 2.495-2.593.475-8.137.176-10.181.114-2.043-.062-1.326-2.235-1.03-2.781.297-.546 5.16-6.688 6.294-7.893 1.655-1.758 6.349-6.53 6.657-6.318z"/><path d="M140.693 45.338l1.31.03 4.02-10.721zM137.913 45.243l1.45-.004 4.4-10.091zM134.913 45.133l1.6.029 5.53-9.652zM158.543 22.944c.359.561-3.006 2.716-4.887 5.871-.287.58-1.422 2.677-1.334 3.886.088 1.208 1.199 2.449 2.51 2.623 1.313.175 4.595-.728 5.87-1.268 1.276-.541 3.062-1.354 3.462-1.492 2.772-.773 3.414.041 3.414.041s-2.596.622-3.395 1.041c-.798.419-4.938 2.517-6.708 3.11-1.73.579-5.156.943-6.495.375-1.336-.566-1.503-1.646-1.48-2.268.054-2.656 1.259-4.927 2.84-7.091 1.562-2.133 4.339-4.175 4.689-4.373.35-.197 1.113-.752 1.514-.455zM191.893 32.087s-10.09-.235-12.516-.381c-2.427-.146-5.885-.937-6.932-.781-1.047.157-3.102 1.763-3.102 1.763s1.565-.251 1.829-.21c.264.042.774.203.87.432.094.23.268 1.345.268 1.345s2.21-.993 2.94-1.251c.732-.257 1.966-.389 2.267-.066.297.322.063 1.686.105 1.855.043.171.3.324.3.324s.968-.896 1.205-1.102c.237-.205 1.7-1.009 2.287-1.122.588-.113 1.286.218 1.397.515s-.108.859-.108.859.313-.003.46-.09c.148-.084 1.01-.644 1.215-.732.328-.14 1.42-.398 1.906-.482.484-.083 4.62-.336 4.986-.465.367-.129.623-.411.623-.411zM141.663 19.5s-12.443 10.321-12.877 10.756c-.433.436-6.215 6.208-6.92 6.566-.705.36-1.744.405-2.016.475-.272.069-2.407.791-3.163 1.09-.757.301-1.802 1.18-1.944 1.616-.145.434-.084.961.455 1.513.537.552 2.386.845 2.386.845s1.926.599 2.42.98c.495.381.302 1.191.345 1.506s.602 1.804 1.088 2.006c.484.203.79-.164 1.164-.403.375-.24 1.21-2.371 1.21-2.371s.43-1.882.997-2.93c.568-1.049 2.463-2.291 2.463-2.291s-.21 1.391-.006 1.629c.206.237 2.707.039 3.406-.066.697-.104.772-.452.953-1.31.198-.937.31-1.924.47-2.436.145-.46.589-1.036 1.09-1.344.502-.308 2.05-.914 2.05-.914s-2.061-.13-4.943 1.07c-1.277.531-2.318 1.419-3.016 1.813-.697.394-3.228 2.41-3.703 3.254-.474.844-.803 1.833-.996 2.497-.195.665-.381 1.219-.695 1.262-.314.044-.197-.349-.307-.501-.112-.153.1-.605-.064-.962-.162-.357-1.8-1.247-2.94-1.465s-2.24-.556-2.386-.7c-.145-.144-.222-.306-.104-.553s1.309-.838 1.998-1.122c.688-.282 2.347-.883 2.72-.833.376.05.479.168.48.458 0 .289-.134 1.048-.134 1.048s1.782-2.262 2.376-2.92c.594-.656 8.48-7.975 10.843-9.948 2.36-1.974 5.979-4.558 7.15-5.214 1.15-.643 1.974-1.009 1.974-1.009l-1.824-1.092zm-13.13 18.276c.612-.806 2.73-1.668 2.73-1.668s-.352.397-.514 1.833c-.072.641-.205 1.193-.635 1.355-.43.163-1.826.353-1.881.078-.068-.345-.068-1.11.3-1.598z"/><path d="M128.763 39.257l1.05-.123.09-2.102zM191.253 30.041l.453-2.37-1.807 1.905c-2.377-.878-5.476-2.26-5.476-2.26s-4.293-1.915-4.51-2.227c-.171-.247-.02-.647-.02-.647s-1.954.567-2.092.747c-.136.179-.065.451.079.595.145.145 4.772 2.124 5.574 2.428.8.304 7.166 2.278 7.473 2.345.307.068 1.074.235 1.277.184.204-.052.417-.214.279-.469-.185.048-.636-.049-1.23-.231zM202.933 25.506c-.104-.077-.383-.19-.772-.323l-.727-3.202-.821 2.725c-.202-.059-.41-.119-.622-.178l-.684-2.764-.753 2.368c-1.264-.343-2.402-.639-2.758-.743-.888-.258-7.43-2.031-7.904-1.609.718.254 10.299 2.994 13.164 4.514.438.232.7.692.512 1.301-.454 1.074-1.826 1.9-3.888 2.522a3.217 3.217 0 0 1-.48.096l-.428-2.42-1.116 2.416c-.413-.047-.84-.081-1.172.084-.314.157-.484.593-.266 1.1.275.635 2.267.301 2.89.191 1.63-.286 3.554-1.008 4.767-1.912 1.066-.795 1.564-1.544 1.73-2.104.246-.822.205-1.409-.672-2.062zM203.353.74c-.283-.398-.582-.652-1.672-.667-.793-.01-1.771.284-2.578.544-1.573.507-5.225 2.435-7.497 4.142-2.616 1.966-6.862 5.502-8.866 7.458-.953.932-7.76 7.534-8.336 8.12-1.096 1.11-.445 2.248-.24 2.486.207.241 1.748 1.262 1.98 1.312.307.067.758.134.995-.071.208-.179.254-.281-.07-.706-.155-.204-.778-.757-.922-.926-.308-.356-.206-.817-.037-1.004.17-.188 3.222-3.535 4.133-4.413.59-.57 2.667-2.514 4.945-4.526l1.348 1.612-.072-2.728c.36-.311.716-.613 1.069-.911l1 1.656.387-2.795c.363-.292.718-.57 1.047-.817.93-.698 2.605-1.902 4.144-2.965l.927 2.005.299-2.84c.297-.199.576-.384.83-.548l1.033 2.388.21-3.128c1.007-.52 1.767-.696 2.705-.738.462-.02 1.062.464 1.024 1.044-.057.919-2.16 3.624-2.533 4.008-.374.384-5.78 6.205-6.213 6.641-.441.443-4.006 4.345-4.522 5.019-.518.674-.813 1.509-.813 1.509s6.859-6.95 7.572-7.71c.412-.44 2.045-1.995 3.642-3.602l1.512 2.15-.101-3.601c.21-.223.41-.437.599-.644l1.379 3.093-.136-4.573c.813-1.055 2.044-2.779 2.13-3.942.04-.55-.021-.933-.302-1.332zM155.493 12.786l-2.82.258-9.29 5.634 1.9 2.095-5.24 2.702-8.24 6.611-7.83 7.412 4.01-3.042-.25 1.005 1.82-2.269.12 1.054 1.25-2.488.04 1.583 1.3-2.574-.11 1.839 1.74-3.122-.11 2.13 1.78-3.275-.01 2.537 1.72-3.768.15 2.571 1.74-3.7-.14 2.861 1.89-4.245-.11 3.286 1.85-4.16-.34 3.271 2.12-4.229-.28 3.474 2.22-4.4-.14 3.441 2.91-5.372-.53 4.19 2.81-5.201-.31 3.917 2.77-5.627-.02 4.206 2.35-5.592.28 4.563 3.5-7.628-2.3 1.205 1.3-2.983z"/></g></g></svg>
\ No newline at end of file
diff --git a/refdoc/structure/caudium_modref.html b/refdoc/structure/caudium_modref.html
deleted file mode 100644
index 852aed1310..0000000000
--- a/refdoc/structure/caudium_modref.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<use file="/caudium.tmpl">
-<page title="$title$" ecss="caudiumref.css" parent="/developer/pikeref/index.html" showwiki="yes">
-
-<table>
-  <tr>
-    <td width='180' valign='top' bgcolor='#f0f0f0'>$navbar$</td>
-    <td width='520' valign='top'>
-
-    <table border="0" width="520" bgcolor="#e0e0e0"
-           cellpadding="0" cellspacing="4" class='sidebar'>
-      <tr>
-        <td valign="middle">
-	  <a href="$prev_url$"><img src="/img/prev.png" hspace="3"
-	         border="0" alt="previous" >$prev_title$</a>
-          <br>
-	</td>
-	<td align="right" valign="middle">
-	  <a href="$next_url$">$next_title$<img src="/img/next.png" hspace="3"
-	          border="0" alt="next" ></a>
-	  <br>
-	</td>
-      </tr>
-    </table>
-
-    <h1>$type$ $title$</h1>
-    $contents$
-
-    </td>
-  </tr>
-</table>
-</page>
diff --git a/refdoc/structure/chapters.html b/refdoc/structure/chapters.html
new file mode 100644
index 0000000000..50ed181318
--- /dev/null
+++ b/refdoc/structure/chapters.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<html>
+  <head>
+    <meta content="width=device-width, initial-scale=1" name="viewport">
+    <meta charset="utf8">
+    <title>$title$</title>
+    <link rel="stylesheet" href="modref.css" data-inline="">
+  </head>
+  <body class="traditional">
+    $contents$
+  </body>
+</html>
\ No newline at end of file
diff --git a/refdoc/structure/modref.css b/refdoc/structure/modref.css
index 237cdbfdb1..c683f619ad 100644
--- a/refdoc/structure/modref.css
+++ b/refdoc/structure/modref.css
@@ -1,9 +1,167 @@
-body {
+*, *:after, *:before {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+
+html { font-size: 90%; }
+
+html, body {
 	margin: 0;
+	padding: 0;
+	height: 100%;
+	max-width: 100%;
+	min-width: 100%;
+}
+
+body {
 	color: #343434;
-	background: #ffffff;
-	font-family: arial,helvetica,sans-serif;
-	font-size: 13px;
+	background: #f3f3f3;
+	font-family: arial, helvetica, sans-serif;
+	font-size: 1rem;
+	line-height: 1.5;
+	width: 100%;
+}
+
+.traditional {
+	padding: 20px;
+	background: white;
+}
+
+.traditional pre {
+	position: relative;
+	overflow: auto;
+}
+
+.traditional > dl > dd {
+	margin-right: 40px;
+}
+
+/* First H in page */
+.traditional > dl > dt:first-child * {
+	margin-top: 0;
+}
+
+.traditional > dl > dd:last-child {
+	margin-bottom: 40px;
+}
+
+.traditional .header {
+	padding: .6rem 1.5rem;
+	background: #eee;
+}
+
+.traditional h1.header,
+	.traditional h2.header,
+	.traditional h3.header {
+		margin: .8rem 0;
+	}
+
+.traditional h1.header {
+	font-size: 2.6rem;
+}
+	.traditional h1.header .ms {
+		font-size: 2.3rem;
+	}
+
+.traditional h2.header {
+	font-size: 2.2rem;
+	font-weight: normal;
+}
+	.traditional h2.header .ms {
+		font-size: 1.9rem;
+	}
+
+.traditional h3.header {
+	font-size: 1.8rem;
+	font-weight: normal;
+}
+	.traditional h3.header .ms {
+		font-size: 1.5rem;
+	}
+
+.traditional dd {
+	max-width: 100%;
+	overflow: auto;
+}
+.traditional dl dl dt {
+	font-weight: bold;
+}
+
+header {
+	padding: 20px;
+	background: #323232;
+	border-bottom: 6px solid #555;
+}
+
+header::after {
+	display: block;
+	content: ' ';
+	clear: both;
+}
+header h1 { margin: 0; vertical-align: middle; }
+header a.logo {
+	opacity: .7;
+	display: inline-block;
+	width: 160px;
+	height: 28px;
+	margin-bottom: -5px;
+	background: transparent url(images/pike-logo.png) left center no-repeat;
+	background-image: linear-gradient(transparent, transparent), url(images/pike-logo.svg);
+	background-size: contain;
+	transition: opacity .2s ease-in;
+}
+header a.logo:hover {
+	opacity: 1;
+}
+
+/* Hides the Pike text in the logo */
+header a span {
+	display: none;
+}
+
+header #version {
+	float: right;
+	font-size: smaller;
+	color: #999;
+	margin-top: 5px;
+}
+
+footer {
+	position: relative;
+	z-index: 1;
+	clear: both;
+	padding: 20px;
+	background: #f3f3f3;
+	border-top: 1px solid #ddd;
+}
+
+footer #build-date {
+	color: #999;
+	font-size: smaller;
+}
+
+a {
+	color: #0768b2;
+	transition: color .2s ease-in;
+}
+
+a:hover, a:visited:hover {
+	color: #111;
+}
+
+a:active {
+	color: rgb(70, 104, 178);
+}
+
+a:visited {
+	color: #627F94;
+}
+
+#page {
+	padding: 0;
+	background: #f3f3f3;
+	overflow: hidden;
 }
 
 blockquote { margin-bottom: 14px; }
@@ -16,7 +174,7 @@ em {
 }
 
 .error {
-        color: #cc0000;
+	color: #cc0000;
 }
 
 .newsDate {
@@ -26,79 +184,251 @@ em {
 }
 
 .navbar {
-	background: #f0f0f0;
+	overflow: auto;
 	float: left;
-	margin-left: 22px;
-	margin-top: 3px;
-	min-width: 181px;
-	overflow: hidden;
+	width: 25%;
+	border-right: 1px solid #ddd;
+	margin-right: 0px;
+	position: relative;
+}
+
+.navbar nav .inner {
+	padding: 20px;
 }
 
-.sidebar {
-	background: #f0f0f0;
-	font-size: 95%;
-	margin: 3px;
+.navbar .head {
+	border-left: 5px solid #ddd;
+	background: #e5e5e5;
+	display: block;
+	margin-bottom: 1px;
+	padding: 5px 10px;
 	overflow: hidden;
-	padding: 3px;
+	text-overflow: ellipsis;
+	transition: background .2s ease-in, border-color .2s ease-in;
+}
+.navbar .heading {
+	display: block;
+	color: #666;
+	border-bottom: 1px dashed #aaa;
+	margin-bottom: 6px;
+	padding-bottom: 4px;
+	margin-top: 24px;
+	vertical-align: text-top;
+}
+.navbar .heading:before {
+	content: '●';
+	margin-right: 5px;
+	font-size: large;
+	color: #666;
+	vertical-align: top;
+	margin-top: 0px;
+	display: inline-block;
+	line-height: 1;
+	color: #999;
+}
+.navbar div + .head {
+	margin-top: 18px;
 }
 
-.left {
-	float: left;
+.navbar .head + div {
+	margin-top: 6px;
+}
+
+.navbar a .head:hover {
+	background: #ccc;
+	border-color: #bbb;
+}
+
+.navbar .top:before {
+	content: '\27A4';
+	margin-right: 4px;
+	display: inline-block;
+	transform: rotate(-90deg);
+}
+.navbar nav {
+	position: relative;
+	width: auto;
+}
+
+.navbar.sticky {
+	position: fixed;
+	overflow: auto;
+	height: 100%;
+	top: 0px;
+	left: 0px;
+}
+
+.navbar.sticky .inner {
+	padding-bottom: 75px;
+}
+
+.navbar .sidebar {
+	opacity: 1;
+	transition: opacity .5s ease-out;
+}
+.navbar .sidebar.init {
+	opacity: 0;
+}
+
+.navbar .sidebar a { display: block; text-decoration: none; }
+
+.sidebar a.mod-protected {
+	color: #999;
+}
+
+.sidebar .mod-protected::before {
+	content: ' ';
+	display: inline-block;
+	opacity: .4;
+	width: 15px;
+	height: 15px;
+	margin-right: 5px;
+	margin-top: -1px;
+	vertical-align: middle;
+	background: url(images/eye-slash.svg) 0 50% no-repeat;
+	background-size: contain;
+	text-decoration: none;
 }
 
-.right {
+.content {
+	width: 75%;
 	float: right;
-	text-align:right;
+	position: relative;
 }
 
 .contentbox {
-	margin-right: 23px;
-	min-width: 520px;
 	overflow: hidden;
-	padding-left: 23px;
-	padding-right: 23px,
+	padding: 0 20px 20px 20px;
+	border-left: 1px solid #ddd;
+	margin-left: -1px;
+}
+
+.contentbox::after {
+	display: block;
+	clear: both;
+	content: ' ';
 }
 
 .navbox {
-	margin-right: 23px;
-	min-width: 520px;
-	overflow: hidden;
+	width: auto;
+	overflow: auto;
+	padding: 15px 20px;
+	background: #e9e9e9;
+	border-bottom: 1px solid #ddd;
 }
 
 .navbox .sidebar {
-	background: #e0e0e0;
 }
 
-pre,code {
-	font-family: "andale mono", "monotype.com", "courier new", monospace;
-	font-size: 90%;
+/* Prev/next arrows */
+.prev, .next {
+	text-decoration: none;
+	font-family: monospace;
+	font-size: 14px;
+}
+
+.prev {
+	float: left;
+}
+
+.next {
+	float: right;
+}
+
+.prev span, .next span {
+	display: inline-block;
+	vertical-align: middle;
+	margin-top: -2px;
+}
+
+.prev span {
+	transform: rotate(180deg);
+	-webkit-transform: rotate(180deg);
+	-moz-transform: rotate(180deg);
+	margin-right: 6px;
+}
+
+.next span {
+	margin-left: 6px;
+}
+
+/* Muli-column for all built-in methods on the start page */
+ul.multicol {
+	list-style: none;
+	margin: 0;
+	padding: 0;
+	position: relative;
+  -webkit-column-count: 4;
+  -moz-column-count: 4;
+  column-count: 4;
+  -webkit-column-gap: 3em;
+  -moz-column-gap: 3em;
+  column-gap: 3em;
+}
+ul.multicol li {
+	margin: 0;
+	padding: 0;
+	position: relative;
+}
+ul.multicol a {
+	display: block;
+	position: relative;
+	-webkit-backface-visibility: hidden;
+	transition: transform .2s ease-out;
+}
+ul.multicol a:hover {
+	text-decoration: none;
+	// font-weight: bold;
+	-webkit-backface-visibility: hidden;
+}
+
+pre, code, tt, .monospace, .ms {
+	font-family: menlo, monospace;
+	font-size: .95rem;
+}
+
+svg a, svg tspan, svg text, svg .reference {
+	font-size: 1rem;
+	font-family: monospace !important;
+}
+
+hr {
+	border: none;
+	height: 1px;
+	background: #ddd;
+	color: #ddd;
+	margin: 25px 0;
+}
+
+h1, h2, h3, h4 {
+	color: #323232;
+	line-height: 1;
 }
 
 h1 {
-	font-size: 26px;
-	font-weight: bold;
-	color: #000066;
+	font-size: 1.7rem;
+}
+
+/* The first H1 in the contentbox */
+.contentbox article:first-child > h1:first-child {
+	margin-top: 25px;
 }
 
 h2 {
-	font-size: 125%;
-	font-weight: bold;
-	color: #000066;
+	font-size: 1.45rem;
 	margin-bottom: 4px;
 }
 
 h3 {
-	font-size: 110%;
-	font-weight: bold;
-	color: #000066;
+	font-size: 1.10rem;
 }
 
 small {
-	font-size: 75%;
+	font-size: .8rem;
 }
 
 a.small {
-	font-size: 75%;
+	font-size: .8rem;
 	text-decoration: none;
 }
 
@@ -124,3 +454,238 @@ textarea.small {
 	font-family: "andale mono", "monotype.com", "courier new", monospace;
 	font-size: 75%;
 }
+
+/* Code doc */
+
+.fixme { color: #a00; }
+.expr { color: #8E3DD3; }
+.reference { color: #777; }
+a.reference, a.reference:visited { color: #0087cc; }
+.modifier { color: purple; font-weight: bold; }
+.datatype { color: purple; font-weight: bold; }
+.variable, .constant, .typedef, .inherit, .directive {
+	color: #F000F0;
+	font-weight: bold;
+}
+.parameter, .argument, .argument a { color: #0087cc; font-size: 1rem; }
+.argument a { text-decoration: none; }
+.method { color: #000066; }
+.key { color: green; }
+
+.head--doc,
+  .head--fixme { font-weight: bold; color: #777; }
+.head--fixme { color: #900; }
+.homogen--name { font-size: large; }
+.group--doc { margin-bottom: 0; }
+.group--doc + hr { margin-top: 10px; }
+dd[class^='body--'],
+dd.example,
+dt[class^='head--'] + dd {
+	max-width: 100%;
+	overflow-x: auto;
+}
+
+.inheritance-graph {
+	position: relative;
+	width: 100%;
+	max-width: 100%;
+	overflow-x: auto;
+	padding-left: 40px;
+}
+
+table.box {
+	color: #555;
+	margin: 6px 0 12px;
+	width: auto;
+	border-collapse: collapse;
+	border: 1px solid #ccc;
+}
+table.box tr {
+	border-bottom: 1px dashed #bbb;
+}
+table.box td {
+	vertical-align: top;
+	padding: 10px 12px;
+	border-left: 1px dashed #bbb;
+}
+table.box td *:first-child { margin-top: 0; }
+table.box td *:last-child { margin-bottom: 0; }
+table.box table.box { width: 100%; }
+
+pre code .comment { color: #999; }
+pre code .type { color: #00007B; font-weight: bold; }
+pre code .string { color: #037F00; }
+pre code .macro { color: #B04700; font-weight: bold; }
+pre code .lang,
+	pre code .const,
+	pre code .mod { color: #863069; font-weight: bold; }
+pre code .const { color: #0000ff; }
+pre code .delim { color: #00008e; }
+pre code .ns { font-weight: bold; }
+pre code .nested { opacity: .7; transition: opacity .2s ease-in; }
+pre code .nested:hover { opacity: 1; }
+
+#burger {
+	display: none;
+	color: white;
+}
+
+@media screen and (max-width: 1024px) {
+	ul.multicol {
+	  -webkit-column-count: 3;
+	  -moz-column-count: 3;
+	  column-count: 3;
+	}
+}
+
+@media screen and (max-width: 800px) {
+	.content {
+		width: 100%;
+		float: none;
+	}
+	.contentbox {
+		border-left: none;
+		margin-left: 0;
+	}
+	ul.multicol {
+	  -webkit-column-count: 2;
+	  -moz-column-count: 2;
+	  column-count: 2;
+	}
+	#version { display: none; }
+	.navbox .prev, .navbox .next {
+		float: none;
+		display: block;
+		text-align: center;
+		white-space: nowrap;
+		overflow: hidden;
+		text-overflow: ellipsis;
+	}
+	.navbox .next {
+		// text-align: right;
+	}
+
+	.inheritance-graph {
+		padding-left: 0px;
+	}
+
+	#burger {
+		display: block;
+		float: right;
+		color: white;
+		padding: 10px 15px;
+		margin-right: -15px;
+		margin-top: -2px;
+		cursor: pointer;
+		border-radius: 2px;
+		opacity: .6;
+		transition: transform .3s ease-in-out;
+	}
+
+	body {
+		padding-top: 65px;
+		transition: padding-top .4s ease-out;
+	}
+	header {
+		padding: 10px 20px;
+		position:fixed;
+		width: 100%;
+		top: 0;
+		left: 0;
+		z-index: 1;
+		transition: padding .3s ease-in;
+	}
+
+	header h1 {
+		display: inline-block;
+		margin-top: 7px;
+	}
+
+	header a {
+		height: 26px;
+		width: 120px;
+		transition: transform .3s ease-in;
+	}
+
+	body.scrolled {
+		padding-top: 46px;
+	}
+
+	body.scrolled header {
+		box-shadow: 0px 1px 5px 0px rgba(0,0,0,.4);
+		padding: 0px 20px;
+	}
+
+	body.scrolled header a {
+		transform: scale(.9);
+	}
+
+	.menu-open {
+		overflow: hidden;
+	}
+
+	.menu-open .navbar {
+		display: block;
+	}
+
+	.menu-open #burger {
+		transform: rotate(90deg);
+	}
+
+	.navbar {
+		position: fixed;
+		bottom: 0;
+		top: 60px;
+		right: -100%;
+		left: 100%;
+		min-width: 100.3%;
+		z-index: 2;
+		background: #323232;
+		color: #ccc;
+		overflow-y: auto;
+		transition: right .2s ease-out, left .2s ease-in-out;
+	}
+
+	body.scrolled .navbar {
+		top: 40px;
+	}
+
+	.menu-open .navbar {
+		left: 0;
+		right: 0;
+	}
+
+	.navbar .heading {
+		color: #ccc;
+	}
+
+	.navbar .head {
+		background: #424242;
+		border-left-color: #3a3a3a;
+	}
+
+	.navbar a {
+		color: #999;
+	}
+
+	.navbar .selected {
+		color: #ccc;
+	}
+
+	dd[class^='body--'],
+	dd.example,
+	dt[class^='head--'] + dd {
+		margin-left: 0px;
+	}
+}
+
+@media screen and (max-width: 600px) {
+	.traditional {
+		padding: 10px;
+	}
+
+	.traditional dl dd {
+		margin-left: 10px;
+		margin-right: 0px;
+	}
+}
diff --git a/refdoc/structure/modref.html b/refdoc/structure/modref.html
index 5c255952d8..5b633d1c4a 100644
--- a/refdoc/structure/modref.html
+++ b/refdoc/structure/modref.html
@@ -1,60 +1,60 @@
+<!doctype html>
 <html>
   <head>
-    <title>Pike Reference Manual - $title$</title>
-    <link rel='stylesheet' href='$style$' />
+    <meta content="width=device-width, initial-scale=1" name="viewport">
+    <meta charset="utf-8">
+    <title>$title$ - Pike Reference Manual</title>
+    <!-- 221-->
+    <link rel='stylesheet' href='$style$'>
+    <script src='$script$'></script>
+    $constants$
+    $nodynamic$
     $extra_headers$
   </head>
-  <body link="#0768b2" alink="#002040" vlink="#0768b2">
+  <body>
     <header>
-      <div>
-	<div style="text-align:right;">Extracted from $version$ as of $date$.</div>
-	<div style="overflow:hidden;">
-	  <a href="http://pike.lysator.liu.se/"
-	     style="float:left; width:181px; height:41px; margin:10px;
-		    margin-left:22px; margin-right:25px;
-		    background-image:url('$imagedir$pike_logo.gif');"></a>
-	  <div style="margin:10px; height:11px;
-		      margin-top:26px; margin-right:19px;
-		      overflow:hidden;
-		      background-image:url('$imagedir$pike_line_middle.gif');">
-	    <span style="float:left; width:5px; height:11px;
-			 background-image:url('$imagedir$pike_line_left.gif');">&nbsp;</span>
-	    <span style="float:right; width:5px; height:11px;
-			 background-image:url('$imagedir$pike_line_right.gif');">&nbsp;</span>
-	  </div>
-	</div>
+      <div class="header">
+        <div id="version"><strong data-id="version">$version$</strong></div>
+        <div id="burger">&#9776;</div><!-- Hamburger icon -->
+        <h1>
+          <a href="http://pike.lysator.liu.se/" class="logo">
+            <span>Pike programming language</span>
+          </a>
+        </h1>
       </div>
     </header>
-
-    <div>
+    <div id="page">
       <div class="navbar">
-	<nav>
-	  $navbar$
-	</nav>
+        <nav>
+          <div class="inner" id="navbar">
+            $navbar$
+          </div>
+        </nav>
       </div>
-      <div class="navbox">
-	<nav>
-	  <div class="sidebar">
-	    <a href="$prev_url$" class="left"
-	       ><img src="$imagedir$prev.gif" hspace="3"
-		     border="0" alt="previous"
-		     >$prev_title$</a>
-	    <a href="$next_url$" class="right"
-	       >$next_title$<img src="$imagedir$next.gif" hspace="3"
-				 border="0" alt="next"
-				 ></a>
-	  </div>
-	</nav>
-      </div>
-      <div class="contentbox">
-	<article>
-	  <h1>$type$ $title$</h1>
-	  $contents$
-	</article>
-	<footer>
-	  <hr size="1" noshade="1" />
-	</footer>
+      <div class="content">
+        <div class="navbox">
+          <nav>
+            <div class="sidebar">
+              <a href="$prev_url$" class="prev"><span>&#10148;</span> $prev_title$</a>
+              <a href="$next_url$" class="next">$next_title$ <span>&#10148;</span></a>
+            </div>
+          </nav>
+        </div>
+        <div class="contentbox">
+          <article>
+            <h1>$type$ $title$</h1>
+            $contents$
+          </article>
+        </div>
       </div>
     </div>
+    <footer>
+      <div id="build-date">Extracted from <strong data-id="version">$version$</strong> as of <strong data-id="date" data-timestamp="$generated$">$date$</strong>.</div>
+    </footer>
+    $extra_footer$
+    <script>
+      // Tell PikeDoc that next actions are from loaded scripts
+      PikeDoc.isInline = false;
+    </script>
   </body>
 </html>
diff --git a/refdoc/structure/modref.js b/refdoc/structure/modref.js
new file mode 100644
index 0000000000..d644339c59
--- /dev/null
+++ b/refdoc/structure/modref.js
@@ -0,0 +1,641 @@
+/* jshint undef: true, unused: true */
+/* globals window, document, requestAnimationFrame */
+/* exported PikeDoc */
+
+var PikeDoc = null;
+
+if (!window.console) {
+  window.console = { log: function(){}, error: function(){} };
+}
+
+/*
+  Encapsulate so we don't clutter the global scope
+*/
+(function(window, document) {
+'use strict';
+
+var doDebug = false;
+var isdebug = document.location.search.indexOf('debug=1') > -1 || doDebug;
+var wdebug  = isdebug ? window.console.log : function(){};
+
+// The scroll position at which the navbar sticks. This actually gets
+// calculated dynamically upon page load.
+var stickyScrollBreak = 70,
+    // Window width when we go to mobile mode
+    mobileBreakPoint = 800,
+    // The navbar to the left, HTMLElement
+    navbar, innerNavbar,
+    // Content wrapper, HTMLElement
+    content,
+    // The page footer
+    footer,
+    // The height of the navbar
+    navbarHeight,
+    // The height of the window
+    windowHeight,
+    // The height of the header
+    headerHeight,
+    // The height of the footer
+    footerHeight,
+    // The menu hamburger when in mobile mode
+    burger,
+    // Optimization®
+    objectKeys = Object.keys,
+    // Functions to run when DOM is ready
+    onDOMReadyQueue = [];
+
+// Hide the navbox when on the start page where the prev and next links
+// doesn't lead anywhere
+function maybeHideNavbox() {
+  var navbox = document.getElementsByClassName('navbox')[0];
+  var prev   = navbox.getElementsByClassName('prev')[0];
+  var next   = navbox.getElementsByClassName('next')[0];
+  prev       = prev.getAttribute('href');
+  next       = next.getAttribute('href');
+
+  if (!next && !prev) {
+    navbox.style.display = 'none';
+    hideTopLink();
+  }
+}
+
+// And if on the start page hide the Top link in the side navbar
+function hideTopLink() {
+  var top = document.getElementsByClassName('top head');
+  top[0].style.display = 'none';
+}
+
+// Called when DOM is ready
+function onPageLoad() {
+  var versionElems, dateElems, i, max;
+
+  maybeHideNavbox();
+  navbar       = document.getElementsByClassName('navbar')[0];
+  content      = document.getElementsByClassName('content')[0];
+  footer       = document.getElementsByTagName('footer')[0];
+  footerHeight = footer.offsetHeight;
+  windowHeight = window.outerHeight;
+  headerHeight = document.getElementsByTagName('header')[0].offsetHeight;
+  navbarHeight = windowHeight - content.offsetTop - footerHeight;
+  innerNavbar  = document.getElementById('navbar');
+  burger       = document.getElementById('burger');
+
+  // When the doc is compiled with FLAG_NO_DYNAMIC the version and publish date
+  // will not be written to the pages but inserted with JS. If the NO_DYNAMIC
+  // symbol is true we need to put the version and pubdate in the elements with
+  // attributes data-id="version" and data-id="date".
+  if (PikeDoc.NO_DYNAMIC) {
+    versionElems = document.querySelectorAll('[data-id="version"]');
+    dateElems = document.querySelectorAll('[data-id="date"]');
+    max = Math.max(versionElems.length, dateElems.length);
+
+    for (i = 0; i < max; i++) {
+      if (versionElems[i] !== undefined) {
+        versionElems[i].innerHTML = PikeDoc.VERSION;
+      }
+      if (dateElems[i] !== undefined) {
+        dateElems[i].innerHTML = PikeDoc.PUBDATE;
+      }
+    }
+  }
+
+  stickyScrollBreak = headerHeight;
+}
+
+var iAmSticky;
+// Invoked when DOM is ready, and use as callback for onscroll.
+function onPageScroll() {
+  // If scrollY is larger than the sticky position ...
+  if (window.scrollY > stickyScrollBreak) {
+    // ... see if we're already sticky and return if so ...
+    if (iAmSticky) {
+      return;
+    }
+    // ... or else set to sticky.
+    iAmSticky = true;
+    content.style.minHeight = (windowHeight - headerHeight) + 'px';
+    navbar.classList.add('sticky');
+  }
+  // If scrollY is less than the sticky position ...
+  else {
+    // ... see if we're explicitly non-sticky and return if so ...
+    if (iAmSticky === false) {
+      return;
+    }
+    // ... else set to explicitly non-sticky
+    iAmSticky = false;
+    navbar.classList.remove('sticky');
+    content.style.minHeight = 0;
+  }
+}
+
+var iAmScrolled;
+function onMobilePageScroll() {
+  if (window.scrollY > 1) {
+    if (iAmScrolled) {
+      return;
+    }
+    iAmScrolled = true;
+    document.body.classList.add('scrolled');
+  }
+  else {
+    if (iAmScrolled === false) {
+      return;
+    }
+    iAmScrolled = false;
+    document.body.classList.remove('scrolled');
+  }
+}
+
+function onBurgerClick() {
+  document.body.classList.toggle('menu-open');
+  return false;
+}
+
+function setMobileMode() {
+  document.removeEventListener('scroll', onPageScroll);
+  document.addEventListener('scroll', onMobilePageScroll, false);
+  burger.removeEventListener('click', onBurgerClick);
+  burger.addEventListener('click', onBurgerClick, false);
+  navbar.classList.remove('sticky');
+  iAmSticky = false;
+}
+
+function setDesktopMode() {
+  document.removeEventListener('scroll', onMobilePageScroll);
+  document.addEventListener('scroll', onPageScroll, false);
+  burger.removeEventListener('click', onBurgerClick);
+  document.body.classList.remove('menu-open');
+}
+
+var iAmMobile = false;
+function onWindowResize() {
+  if (document.body.offsetWidth < mobileBreakPoint) {
+    if (iAmMobile) {
+      return;
+    }
+    iAmMobile = true;
+    document.body.classList.add('mobile');
+    setMobileMode();
+  }
+  else {
+    if (iAmMobile === false) {
+      return;
+    }
+    iAmMobile = false;
+    document.body.classList.remove('mobile');
+    setDesktopMode();
+  }
+}
+
+// We only care about fairly modern browsers
+if (document.addEventListener) {
+  // Fire when the DOM is ready
+  document.addEventListener('DOMContentLoaded', function() {
+    onPageLoad();
+    cacheFactory.setMenu();
+    PikeDoc.domReady(true);
+    onWindowResize();
+    window.addEventListener('resize', onWindowResize, false);
+    document.addEventListener('scroll', iAmMobile ? onMobilePageScroll
+                                                  : onPageScroll,
+                                        false);
+  }, false);
+}
+
+// During a session each generated menu is cached locally in a sessionStorage
+// (if available). This one handles that.
+var cacheFactory = (function() {
+  // Don't use cache if the page isn't served through a server.
+  // The cache seems buggy as hell when the pages are view directly from
+  // the file system.
+  var cache = document.location.hostname && window.sessionStorage;
+  var m, isChecked = false;
+
+  function init() {
+    if (m || PikeDoc.current.link === 'index.html') {
+      return true;
+    }
+
+    if (!cache || (isChecked && !m)) {
+      return false;
+    }
+
+    m = cache.getItem(PikeDoc.current.link);
+    isChecked = true;
+
+    if (m) {
+      m = JSON.parse(m);
+      var ok = validateDate(m.time);
+      if (!ok) {
+        isChecked = false;
+        cache.removeItem(PikeDoc.current.link);
+      }
+
+      return ok;
+    }
+
+    return false;
+  }
+
+  function validateDate(time) {
+    return getPubDate() < new Date(time);
+  }
+
+  function getPubDate() {
+    return new Date(PikeDoc.GENERATED*1000);
+  }
+
+  function store() {
+    if (cache) {
+      var obj = {
+	      time: Date.now(),
+        value: innerNavbar.innerHTML
+      };
+
+      cache.setItem(PikeDoc.current.link||'root', JSON.stringify(obj));
+    }
+  }
+
+  function setMenu() {
+    if (m && validateDate(m.time)) {
+      //window.console.log('Set menu');
+      innerNavbar.innerHTML = m.value;
+      requestAnimationFrame(function() {
+        innerNavbar.querySelector('.sidebar').classList.remove('init');
+      });
+    }
+  }
+
+  return {
+    hasCache: init,
+    store: store,
+    setMenu: setMenu
+  };
+}());
+
+// Create a document element
+//
+// @param string name
+//  Tag name
+// @param object|string attr
+//  If a string treated as a text node, otherwise as tag attributes
+// @param string text
+function createElem(name, attr, text) {
+  var e = document.createElement(name);
+  if (attr && typeof attr === 'object') {
+    objectKeys(attr).forEach(function(k) {
+      e.setAttribute(k, attr[k]);
+    });
+  }
+  else if (typeof attr === 'string') {
+    e.appendChild(document.createTextNode(attr));
+  }
+
+  if (text) {
+    e.appendChild(document.createTextNode(text));
+  }
+
+  return e;
+}
+
+var helpers = (function() {
+  // Returns basedir of `path`
+  function basedir(path) {
+    var i = path.lastIndexOf('/');
+    if (i < 1) return '';
+    return path.substring(0, i);
+  }
+
+  // Check if `other` starts with `prefix`
+  function hasPrefix(prefix, other) {
+    return other.substring(0, prefix.length) === prefix;
+  }
+
+  function adjustLink(link) {
+    var reldir = basedir(PikeDoc.current.link);
+    var dots = '';
+    while (reldir !== '' && !hasPrefix(link, reldir + '/')) {
+      dots += '../';
+      reldir = basedir(reldir);
+    }
+    return dots + link.substring(reldir.length);
+  }
+
+  // Merge two sets of nodes. If a node exists in both `oldNodes` and
+  // `newNodes` the latter will overwrite the former.
+  function mergeChildren(oldNodes, newNodes) {
+    var hash = {};
+    oldNodes.forEach(function(n) {
+      hash[n.name] = n;
+    });
+
+    newNodes.forEach(function(n) {
+      var j = hash[n.name];
+      if (j) j = n;
+      else hash[n.name] = n;
+    });
+
+    return objectKeys(hash).map(function(k) { return hash[k]; })
+                           .sort(function(a, b) {
+                             return (a.name > b.name) - (b.name > a.name);
+                           });
+  }
+
+  return {
+    basedir:       basedir,
+    hasPrefix:     hasPrefix,
+    adjustLink:    adjustLink,
+    mergeChildren: mergeChildren
+  };
+}());
+
+// Main object for generating the navigation
+PikeDoc = (function() {
+  var symbols     = [],
+      symbolsMap  = {},
+      endInherits = [],
+      inheritList = [],
+      isDomReady  = false,
+      isAllLoaded = false,
+      isInline    = true,
+      current;
+
+  function Symbol(name) {
+    this.name = name;
+    this._children = {};
+    this.children = [];
+  }
+
+  Symbol.prototype = {
+    addChildren: function(type, children) {
+      this._children[type] = children;
+      return this;
+    },
+    finish: function() {
+      var my = this;
+
+      // window.console.log('### Symbol.finish(', this.name, ')');
+
+      objectKeys(this._children).forEach(function(k) {
+        my.children = my.children.concat(my._children[k]);
+      });
+
+      lowSetInherit();
+    },
+    setInherited: function() {
+      this.children.forEach(function(c) {
+        c.inherited = 1;
+      });
+    }
+  };
+
+  function lowSetInherit() {
+    endInherits = endInherits.filter(function(a) {
+      var ss = symbolsMap[a];
+      if (ss) {
+        ss.setInherited();
+        return false;
+      }
+
+      return true;
+    });
+  }
+
+  /* This is called from the generated javascripts (index.js) that's being
+   * loaded on the fly.
+   *
+   * @param string name
+   *  The name of the symbol (Namespace, module e.t.c)
+   * @param boolean isInline
+   *  Is this being called from a script loaded directly in the page
+   *  or being called from a loaded script.
+   */
+  function registerSymbol(name, isInline) {
+    // Only the parent namespace/module/class is loaded inline, and we don't
+    // care about that one. Also, when on the TOP page the navigation is
+    // written to the page, so we don't care for that either.
+    if (isInline || !name) {
+      return new Symbol(name);
+    }
+    var s = new Symbol(name);
+    symbols.push(s);
+    //window.console.log('   + Register symbol: ', name);
+    symbolsMap[name] = s;
+    return s;
+  }
+
+  function endInherit(which) { endInherits.push(which); }
+  function addInherit(which) { inheritList = inheritList.concat(which); }
+
+  var types = {};
+  function finish() {
+    // window.console.log('finish(', endInherits.length, ')');
+    if (endInherits.length === 0) {
+      var merge = helpers.mergeChildren;
+      objectKeys(symbolsMap).forEach(function(k) {
+        var ch = symbolsMap[k]._children;
+        objectKeys(ch).forEach(function(sk) {
+          types[sk] = merge(types[sk]||[], ch[sk]);
+        });
+      });
+
+      isAllLoaded = true;
+      maybeRenderNavbar();
+    }
+  }
+
+  var jsMap = {};
+  var scriptQueue = 0;
+
+  function loadScript(link, namespace, inherits) {
+    wdebug('load: ', link);
+    if (cacheFactory.hasCache()) {
+      return;
+    }
+
+    link = helpers.adjustLink(link);
+
+    // Already loaded
+    if (jsMap[link]) {
+      wdebug('Already loaded: ', link);
+      return;
+    }
+
+    wdebug('+++ Load:', link);
+
+    jsMap[link] = true;
+
+    if (inherits) {
+      addInherit(inherits);
+    }
+
+    scriptQueue += 1;
+
+    var s = createElem('script', { src: link });
+    //s.async = false;
+    document.head.appendChild(s);
+
+    (function(scr, ns) {
+      scr.addEventListener('load', function() {
+        scriptQueue -= 1;
+
+        if (ns) {
+          if (ns === true) { finish(); }
+          else { endInherit(ns); }
+        }
+        else {
+          finish();
+        }
+      }, false);
+    }(s, namespace));
+  }
+
+  function domReady() {
+    isDomReady = true;
+    onDOMReadyQueue.forEach(function(f) {
+      if (typeof f === 'function') {
+        f();
+      }
+    });
+    maybeRenderNavbar();
+  }
+
+  function lowNavbar(container, heading, nodes, suffix) {
+    if (!nodes || !nodes.length) {
+      return;
+    }
+
+    var curlnk = PikeDoc.current.link;
+    var adjlnk = helpers.adjustLink;
+    var c      = container;
+    var div    = createElem('div', { style: 'margin-left:0.5em' });
+
+    nodes.forEach(function(n) {
+      var name, tnode, tmp;
+      name = n.name + suffix;
+      tnode = document.createTextNode(name);
+
+      if (!n.inherited) {
+        tnode = createElem('b', name);
+      }
+
+      if (n.link !== curlnk) {
+        tmp = createElem('a', { href: adjlnk(n.link) });
+        tmp.appendChild(tnode);
+        tnode = tmp;
+      }
+
+      if (n.modifiers) {
+        n.modifiers.forEach(function(mod) {
+          if (n.name !== 'create') {
+            tnode.classList.add('mod-' + mod);
+          }
+        });
+      }
+
+      div.appendChild(tnode);
+    });
+
+    c.appendChild(createElem('b', { class: 'heading' }, heading));
+    c.appendChild(div);
+  }
+
+  /* Render the left navigation bar. */
+  function navbar() {
+    var s = createElem('div', { class: 'sidebar init' });
+    // If the cache already has set the menu, then clear it. The cache is
+    // almost certainly run before this method.
+    var old = innerNavbar.querySelectorAll('.sidebar');
+    var i, tmp;
+    if (old.length) {
+      wdebug('Clear cached menu and regenerate', old);
+      for (i = 0; i < old.length; i++) {
+        tmp = old[i];
+        tmp.parentNode.removeChild(tmp);
+      }
+    }
+
+    innerNavbar.appendChild(s);
+
+    lowNavbar(s, 'Modules',    types.module,    '');
+    lowNavbar(s, 'Classes',    types.class,     '');
+    lowNavbar(s, 'Enums',      types.enum,      '');
+    lowNavbar(s, 'Directives', types.directive, '');
+    lowNavbar(s, 'Methods',    types.method,    '()');
+    lowNavbar(s, 'Operators',  types.operator,  '()');
+    lowNavbar(s, 'Members',    types.member,    '()');
+    lowNavbar(s, 'Namespaces', types.namespace, '::');
+    lowNavbar(s, 'Appendices', types.appendix,  '');
+
+    cacheFactory.store();
+  }
+
+  function maybeRenderNavbar() {
+    wdebug('maybeRenderNavbar(', isAllLoaded, isDomReady, scriptQueue, ')');
+    if (isAllLoaded && isDomReady && scriptQueue === 0) {
+      navbar();
+      requestAnimationFrame(function() {
+        innerNavbar.querySelector('.sidebar').classList.remove('init');
+      });
+    }
+  }
+
+  (function() {
+    // If the refdoc lives in pike.lysator.liu.se we add some custom Google
+    // searchability.
+    if (document.location.hostname === 'pike.lysator.liu.se' ||
+        document.location.hostname === 'pike.local') // for dev purposes
+    {
+      onDOMReadyQueue.push(function() {
+        // When this is run on pike.lysator.liu.se the script below will replace
+        // the content of #version with a search field. Since the script below
+        // is loaded async there might be the case where the version is
+        // briefly shown before it's replaced, which will produce an unpleasant
+        // flicker. This hack will minimize that "unpleasantry".
+        var v = document.getElementById('version');
+        if (!v.classList.contains('search')) {
+          v.innerHTML = '';
+        }
+      });
+
+      var s  = document.getElementsByTagName('script')[0];
+      var el = createElem('script', {
+        src: '/assets/js/local/refdoc-search.min.js',
+        async: true
+      });
+
+      s.parentNode.insertBefore(el, s);
+
+      var el2 = createElem('script', {
+        src: '/assets/js/local/disqus.min.js',
+        async: true
+      });
+
+      s.parentNode.insertBefore(el2, s);
+
+      var f = createElem('link', {
+        href: '/assets/img/favicon.png',
+        rel: 'shortcut icon'
+      });
+
+      document.head.appendChild(f);
+    }
+  }());
+
+  return {
+    registerSymbol: registerSymbol,
+    endInherit:     endInherit,
+    loadScript:     loadScript,
+    domReady:       domReady,
+    isInline:       isInline,
+    current:        current,
+    finish:         finish
+  };
+}());
+
+// This is explicitly set to false in the HTML page if the docs are generated
+// with inlined Pike version and timestamp.
+PikeDoc.FLAG_NO_DYNAMIC = true;
+
+}(window, document));
diff --git a/refdoc/structure/module_modref.html b/refdoc/structure/module_modref.html
deleted file mode 100644
index 0038cabb4d..0000000000
--- a/refdoc/structure/module_modref.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<html><head><title>Pike Reference Manual - $title$</title>
-<link rel='stylesheet' href='$style$' /></head>
-<body topmargin='0' leftmargin='0' marginheight='0' marginwidth='0'
-      bgcolor='#ffffff' text='#000000' link='#000099' alink='#002040'
-      vlink='#000099'>
-
-<table width="100%">
-  <tr>
-    <td colspan='3'></td>
-    <td colspan='2' align='right'>Extracted at $date$.</td>
-  </tr>
-  <tr>
-    <td width="0%"><img src="$dotdot$/images/unit.gif" alt="" width="10" height="1"></td>
-    <td width="1%">
-      <a href="http://pike.lysator.liu.se/"><img src="$dotdot$/images/pike_logo.gif"
-      border="0" alt="pike.lysator.liu.se" width="181" height="41" hspace="5"></a></td>
-    <td width="0%"><img src="$dotdot$/images/unit.gif" alt="" width="10" height="1"></td>
-    <td width="99%">
-      <table align="center" border="0" width="100%" cellspacing="0" cellpadding="0" valign="middle">
-        <tr>
-          <td width="1%" align="right"><img src="$dotdot$/images/pike_line_left.gif" alt="" border="0" width="5" height="11"></td>
-          <td background="$dotdot$/images/pike_line_middle.gif" width="98%"><img src="$dotdot$/images/unit.gif" alt="" border="0" width="11" height="11"></td>
-          <td width="1%" align="left"><img src="$dotdot$/images/pike_line_right.gif" alt="" border="0" width="5" height="11"></td>
-        </tr>
-      </table>
-    </td>
-    <td width="0%"><img src="$dotdot$/images/unit.gif" alt="" width="10" height="1"></td>
-  </tr>
-  <tr>
-    <td colspan="5"><img src="$dotdot$/images/unit.gif" alt="" width="1" height="10"></td>
-  </tr>
-</table>
-
-<table>
-  <tr>
-    <td width='180' valign='top' bgcolor='#f0f0f0'>$navbar$</td>
-    <td width='520' valign='top'>
-
-    <table border="0" width="520" bgcolor="#e0e0e0"
-           cellpadding="0" cellspacing="4" class='sidebar'>
-      <tr>
-        <td valign="middle">
-	  <a href="$prev_url$"><img src="$imagedir$prev.gif" hspace="3"
-	         border="0" alt="previous" >$prev_title$</a>
-          <br />
-	</td>
-	<td align="right" valign="middle">
-	  <a href="$next_url$">$next_title$<img src="$imagedir$next.gif" hspace="3"
-	          border="0" alt="next" ></a>
-	  <br />
-	</td>
-      </tr>
-    </table>
-
-    <h1>$type$ $title$</h1>
-    $contents$
-
-    <hr size='1' noshade='1' />
-    </td>
-  </tr>
-</table>
-</body>
-</html>
diff --git a/refdoc/structure/pelix_modref.html b/refdoc/structure/pelix_modref.html
deleted file mode 100644
index b94779ec34..0000000000
--- a/refdoc/structure/pelix_modref.html
+++ /dev/null
@@ -1,112 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head>
-  <title>pike.lysator.liu.se: $title$</title>
-  <base href="http://pike.lysator.liu.se/generated/manual/modref/$filename$" />
-
-<style type="text/css">
-body { font-family: arial, helvetica, sans-serif; font-size: 13px; }
-blockquote { margin-bottom: 14px; }
-h2         { margin-bottom: 4px; }
-.diff      { padding: 6px }
-.title     { font: 14px Arial, Helvetica; font-weight: bold; text-decoration: none }
-td         { font-family: arial, helvetica, sans-serif; font-size: 13px; }
-</style>
-
-  $extra_headers$
-
-</head>
-
-<body leftmargin="0" vlink="#0768b2" marginheight="0" bottommargin="0" bgcolor="white" marginwidth="0" text="#343434" link="#0768b2" topmargin="0" rightmargin="0" alink="#002040" >
-<a name="top"></a><br>
-
-<noindex><table border="0" cellpadding="0" cellspacing="0" width="100%">
-<tr><td width="0%"><img width="10" src="/R" height="1" alt=""></td>
-<td width="1%"><a href="/"><img hspace="5" border="0" width="181" src="/templates/img/pike_logo.gif" height="41" alt="pike.lysator.liu.se"></a></td>
-<td width="0%"><img width="10" src="/R" height="1" alt=""></td>
-
-<td width="99%">
-<table border="0" align="center" cellpadding="0" cellspacing="0" width="100%">
-
-<tr>
-<td align="right" colspan="3"><search-form action="/docs/search.xml"/></td>
-</tr>
-
-<tr>
-<td align="right" width="1%"><img border="0" width="5" src="/templates/img/pike_line_left.gif" alt="" height="11"></td>
-<td background="/templates/img/pike_line_middle.gif" width="98%"><img width="11" src="/R" alt="" height="11"></td>
-<td align="left" width="1%"><img border="0" width="5" src="/templates/img/pike_line_right.gif" alt="" height="11"></td>
-</tr>
-
-<tr><td align="right" colspan="2"><img width="1" src="/R" vspace="5" height="13" alt=""></td></tr>
-
-</table></td>
-
-<td width="0%"><img width="10" src="/R" height="1" alt=""></td>
-
-</tr>
-
-<tr><td colspan="5"><img width="1" src="/R" height="5" alt=""></td></tr>
-
-</table>
-
-<table width="1%" border="0" cellspacing="0" cellpadding="0">
-  <tr>
-    <td bgcolor="white">
-      <img src="/R" width="63" height="1" alt="" border="0"/>
-    </td>
-    <td><gtext font='franklin gothic heavyoblique' bgcolor='white'
-	 scale='0.47' black='black' xspacing='8' fgcolor='#686868'
-         magic='magic' hspace='2' magic-fgcolor='#0768b2' href='/'>Home</gtext></td>
-
-    <td><img src='/R' width='7' height='3' alt='' border='0'/><img src='/templates/img/pike_arrow_small.gif' alt='&gt;'
-	    width='7' height='9' border='0'/></td>
-
-    <td><gtext font='franklin gothic heavyoblique' bgcolor='white'
-	 scale='0.47' black='black' xspacing='8' fgcolor='#686868'
-         magic='magic' hspace='2' magic-fgcolor='#0768b2' href='/docs/'>Docs</gtext></td>
-
-    <td><img src='/R' width='7' height='3' alt='' border='0'/><img src='/templates/img/pike_arrow_small.gif' alt='&gt;'
-	    width='7' height='9' border='0'/></td>
-
-    <td><gtext font='franklin gothic heavyoblique' bgcolor='white'
-	 scale='0.47' black='black' xspacing='8' fgcolor='#686868'
-         magic='magic' hspace='2' magic-fgcolor='#0768b2' href='/generated/manual/modref/'>Pike reference</gtext></td>
-  </tr>
-</table>
-</noindex>
-
-<br clear="all"/>
-
-<table width="100%" border="0" cellspacing="0" cellpadding="3">
-  <tr>
-    <td width="1%">
-      <img src="/R" width="30" height="1" alt=""/>
-    </td>
-
-    <td width="1%" align="left" valign="top" bgcolor="#f0f0f0"><noindex>
-      $navbar$
-    </noindex></td>
-
-    <td width="1%">
-      <img src="/R" width="15" height="1" alt="" border="0"/>
-    </td>
-    <td width=100% align="left" valign="top">
-        <h1>$title$</h1>
-        $contents$
-    </td>
-
-    <td width="99%">
-      <img src="/R" width="1" height="1" alt=""/>
-    </td>
-  </tr>
-</table>
-
-<table width="100%" border="0" cellspacing="0" cellpadding="0">
-  <tr>
-    <td align=right><font size='-1'><i>Module reference for $version$, $date$&nbsp;</i></font><br/>&nbsp;</td>
-  </tr>
-  <tr><td><manual-comment page="$title$"/></td></tr>
-</table>
-</body>
-
-</html>
-- 
GitLab