Split Build Encyclopedia into multiple pages.

--
MOS_MIGRATED_REVID=106092764
diff --git a/src/main/java/BUILD b/src/main/java/BUILD
index 69ddf85..9038458 100644
--- a/src/main/java/BUILD
+++ b/src/main/java/BUILD
@@ -594,11 +594,14 @@
 genrule(
     name = "gen_buildencyclopedia",
     srcs = [":docs_embedded_in_sources"],
-    outs = ["build-encyclopedia.html"],
-    cmd = ("$(location //src/main/java/com/google/devtools/build/docgen:docgen_bin)" +
-           " $$PWD/src/main/java/com/google/devtools/build/lib" +
-           " $$PWD" +
-           " && cp $$PWD/build-encyclopedia.html $@"),
+    outs = ["build-encyclopedia.zip"],
+    cmd = (
+        "mkdir -p $(@D)/be && " +
+        "$(location //src/main/java/com/google/devtools/build/docgen:docgen_bin)" +
+        " $$PWD/src/main/java/com/google/devtools/build/lib" +
+        " $(@D)/be &&" +
+        "zip -qj $@ $(@D)/be/*"
+    ),
     tools = [
         "//src/main/java/com/google/devtools/build/docgen:docgen_bin",
         "//src/main/java/com/google/devtools/build/docgen:docgen_javalib",
diff --git a/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java b/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java
index 9b1810d..66923b1 100644
--- a/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java
+++ b/src/main/java/com/google/devtools/build/docgen/BuildEncyclopediaProcessor.java
@@ -25,11 +25,13 @@
 import com.google.devtools.build.docgen.DocgenConsts.RuleType;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.util.Pair;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -61,74 +63,45 @@
 
   /**
    * Collects and processes all the rule and attribute documentation in inputDirs and
-   * generates the Build Encyclopedia into the outputRootDir.
-   * 
+   * generates the Build Encyclopedia into the outputDir.
+   *
    * @param inputDirs list of directory to scan for document in the source code
    * @param outputRootDir output directory where to write the build encyclopedia
    * @param blackList optional path to a file listing rules to not document
    */
-  public void generateDocumentation(String[] inputDirs, String outputRootDir, String blackList)
+  public void generateDocumentation(String[] inputDirs, String outputDir, String blackList)
       throws BuildEncyclopediaDocException, IOException {
-    File buildEncyclopediaPath = setupDirectories(outputRootDir);
-
-    Page page = TemplateEngine.newPage(
-        "com/google/devtools/build/docgen/templates/build-encyclopedia.vm");
+    writeStaticPage(outputDir, "make-variables");
+    writeStaticPage(outputDir, "predefined-python-variables");
+    writeStaticPage(outputDir, "functions");
+    writeCommonDefinitionsPage(outputDir);
 
     BuildDocCollector collector = new BuildDocCollector(ruleClassProvider, false);
     Map<String, RuleDocumentation> ruleDocEntries = collector.collect(inputDirs, blackList);
     warnAboutUndocumentedRules(
         Sets.difference(ruleClassProvider.getRuleClassMap().keySet(), ruleDocEntries.keySet()));
-    writeRuleClassDocs(ruleDocEntries.values(), page);
-    page.write(buildEncyclopediaPath);
+
+    writeRuleDocs(outputDir, ruleDocEntries.values());
   }
 
+  private void writeStaticPage(String outputDir, String name) throws IOException {
+    File file = new File(outputDir + "/" + name + ".html");
+    Page page = TemplateEngine.newPage(
+        "com/google/devtools/build/docgen/templates/be/" + name + ".vm");
+    page.write(file);
+  }
 
-  /**
-   * Categorizes, checks and prints all the rule-class documentations.
-   */
-  private void writeRuleClassDocs(Iterable<RuleDocumentation> docEntries, Page page)
+  private void writeCommonDefinitionsPage(String outputDir) throws IOException {
+    File file = new File(outputDir + "/common-definitions.html");
+    Page page = TemplateEngine.newPage(DocgenConsts.COMMON_DEFINITIONS_TEMPLATE);
+    page.add("commonAttributes", PredefinedAttributes.COMMON_ATTRIBUTES);
+    page.add("testAttributes", PredefinedAttributes.TEST_ATTRIBUTES);
+    page.add("binaryAttributes", PredefinedAttributes.BINARY_ATTRIBUTES);
+    page.write(file);
+  }
+
+  private void writeRuleDocs(String outputDir, Iterable<RuleDocumentation> docEntries)
       throws BuildEncyclopediaDocException, IOException {
-    Set<RuleDocumentation> binaryDocs = new TreeSet<>();
-    Set<RuleDocumentation> libraryDocs = new TreeSet<>();
-    Set<RuleDocumentation> testDocs = new TreeSet<>();
-    Set<RuleDocumentation> otherDocs = new TreeSet<>();
-
-    for (RuleDocumentation doc : docEntries) {
-      RuleClass ruleClass = ruleClassProvider.getRuleClassMap().get(doc.getRuleName());
-      if (!ruleClass.isDocumented()) {
-        continue;
-      }
-
-      if (doc.isLanguageSpecific()) {
-        switch(doc.getRuleType()) {
-          case BINARY:
-            binaryDocs.add(doc);
-            break;
-          case LIBRARY:
-            libraryDocs.add(doc);
-            break;
-          case TEST:
-            testDocs.add(doc);
-            break;
-          case OTHER:
-            otherDocs.add(doc);
-            break;
-        }
-      } else {
-        otherDocs.add(doc);
-      }
-    }
-
-    renderBeHeader(docEntries, page);
-
-    page.add("binaryDocs", binaryDocs);
-    page.add("libraryDocs", libraryDocs);
-    page.add("testDocs", testDocs);
-    page.add("otherDocs", otherDocs);
-  }
-
-  private void renderBeHeader(Iterable<RuleDocumentation> docEntries, Page page)
-      throws BuildEncyclopediaDocException {
     // Separate rule families into language-specific and generic ones.
     Set<String> languageSpecificRuleFamilies = new TreeSet<>();
     Set<String> genericRuleFamilies = new TreeSet<>();
@@ -138,26 +111,70 @@
     Map<String, ListMultimap<RuleType, RuleDocumentation>> ruleMapping = new HashMap<>();
     createRuleMapping(docEntries, ruleMapping);
 
+    // Pairs of (normalized rule family name, rule family name), which used for generating
+    // the BE navigation with rule families listed in the same order as those listed in
+    // the overview table.
+    List<Pair<String, String>> ruleFamilyNames = new ArrayList<>(
+        languageSpecificRuleFamilies.size() + genericRuleFamilies.size());
+
     List<SummaryRuleFamily> languageSpecificSummaryFamilies =
         new ArrayList<SummaryRuleFamily>(languageSpecificRuleFamilies.size());
     for (String ruleFamily : languageSpecificRuleFamilies) {
+      ListMultimap<RuleType, RuleDocumentation> ruleTypeMap = ruleMapping.get(ruleFamily);
+      String ruleFamilyId = RuleDocumentation.normalize(ruleFamily);
       languageSpecificSummaryFamilies.add(
-          new SummaryRuleFamily(ruleMapping.get(ruleFamily), ruleFamily));
+          new SummaryRuleFamily(ruleTypeMap, ruleFamily, ruleFamilyId));
+      writeRuleDoc(outputDir, ruleFamily, ruleFamilyId, ruleTypeMap);
+      ruleFamilyNames.add(Pair.<String, String>of(ruleFamilyId, ruleFamily));
     }
 
     List<SummaryRuleFamily> otherSummaryFamilies =
         new ArrayList<SummaryRuleFamily>(genericRuleFamilies.size());
     for (String ruleFamily : genericRuleFamilies) {
-      otherSummaryFamilies.add(
-          new SummaryRuleFamily(ruleMapping.get(ruleFamily), ruleFamily));
+      ListMultimap<RuleType, RuleDocumentation> ruleTypeMap = ruleMapping.get(ruleFamily);
+      String ruleFamilyId = RuleDocumentation.normalize(ruleFamily);
+      otherSummaryFamilies.add(new SummaryRuleFamily(ruleTypeMap, ruleFamily, ruleFamilyId));
+      writeRuleDoc(outputDir, ruleFamily, ruleFamilyId, ruleTypeMap);
+      ruleFamilyNames.add(Pair.<String, String>of(ruleFamilyId, ruleFamily));
     }
+    writeOverviewPage(outputDir, languageSpecificSummaryFamilies, otherSummaryFamilies);
+    writeBeNav(outputDir, ruleFamilyNames);
+  }
 
+  private void writeOverviewPage(String outputDir,
+      List<SummaryRuleFamily> languageSpecificSummaryFamilies,
+      List<SummaryRuleFamily> otherSummaryFamilies)
+      throws BuildEncyclopediaDocException, IOException {
+    File file = new File(outputDir + "/overview.html");
+    Page page = TemplateEngine.newPage(DocgenConsts.OVERVIEW_TEMPLATE);
     page.add("langSpecificSummaryFamilies", languageSpecificSummaryFamilies);
     page.add("otherSummaryFamilies", otherSummaryFamilies);
-    page.add("commonAttributes", PredefinedAttributes.COMMON_ATTRIBUTES);
-    page.add("testAttributes", PredefinedAttributes.TEST_ATTRIBUTES);
-    page.add("binaryAttributes", PredefinedAttributes.BINARY_ATTRIBUTES);
-    page.add(DocgenConsts.VAR_LEFT_PANEL, generateLeftNavigationPanel(docEntries));
+    page.write(file);
+  }
+
+  private void writeRuleDoc(String outputDir, String ruleFamily, String ruleFamilyId,
+      ListMultimap<RuleType, RuleDocumentation> ruleTypeMap)
+      throws BuildEncyclopediaDocException, IOException {
+    List<RuleDocumentation> rules = new LinkedList<>();
+    rules.addAll(ruleTypeMap.get(RuleType.BINARY));
+    rules.addAll(ruleTypeMap.get(RuleType.LIBRARY));
+    rules.addAll(ruleTypeMap.get(RuleType.TEST));
+    rules.addAll(ruleTypeMap.get(RuleType.OTHER));
+
+    File file = new File(outputDir + "/" + ruleFamilyId + ".html");
+    Page page = TemplateEngine.newPage(DocgenConsts.RULES_TEMPLATE);
+    page.add("ruleFamily", ruleFamily);
+    page.add("ruleFamilyId", ruleFamilyId);
+    page.add("ruleDocs", rules);
+    page.write(file);
+  }
+
+  private void writeBeNav(String outputDir, List<Pair<String, String>> ruleFamilyNames)
+      throws IOException {
+    File file = new File(outputDir + "/be-nav.html");
+    Page page = TemplateEngine.newPage(DocgenConsts.BE_NAV_TEMPLATE);
+    page.add("ruleFamilyNames", ruleFamilyNames);
+    page.write(file);
   }
 
   /**
@@ -205,35 +222,6 @@
     }
   }
 
-  private String generateLeftNavigationPanel(Iterable<RuleDocumentation> docEntries) {
-    // Order the rules alphabetically. At this point they are ordered according to
-    // RuleDocumentation.compareTo() which is not alphabetical.
-    TreeMap<String, String> ruleNames = new TreeMap<>();
-    for (RuleDocumentation ruleDoc : docEntries) {
-      String ruleName = ruleDoc.getRuleName();
-      ruleNames.put(ruleName.toLowerCase(), ruleName);
-    }
-    StringBuilder sb = new StringBuilder();
-    for (String ruleName : ruleNames.values()) {
-      RuleClass ruleClass = ruleClassProvider.getRuleClassMap().get(ruleName);
-      Preconditions.checkNotNull(ruleClass);
-      if (ruleClass.isDocumented()) {
-        sb.append(String.format("<a href=\"#%s\">%s</a><br/>\n", ruleName, ruleName));
-      }
-    }
-    return sb.toString();
-  }
-
-  private File setupDirectories(String outputRootDir) {
-    if (outputRootDir != null) {
-      File outputRootPath = new File(outputRootDir);
-      outputRootPath.mkdirs();
-      return new File(outputRootDir + File.separator + DocgenConsts.BUILD_ENCYCLOPEDIA_NAME);
-    } else {
-      return new File(DocgenConsts.BUILD_ENCYCLOPEDIA_NAME);
-    }
-  }
-
   private static void warnAboutUndocumentedRules(Iterable<String> rulesWithoutDocumentation) {
       Iterable<String> undocumentedRules = Iterables.filter(rulesWithoutDocumentation,
           RULE_WORTH_DOCUMENTING);
diff --git a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
index ec5b5fa..31a63ad 100644
--- a/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
+++ b/src/main/java/com/google/devtools/build/docgen/DocgenConsts.java
@@ -29,9 +29,14 @@
 
   public static final String LS = "\n";
 
-  public static final String HEADER_TEMPLATE = "templates/be-header.html";
-  public static final String FOOTER_TEMPLATE = "templates/be-footer.html";
-  public static final String BODY_TEMPLATE = "templates/be-body.html";
+  public static final String COMMON_DEFINITIONS_TEMPLATE =
+      "com/google/devtools/build/docgen/templates/be/common-definitions.vm";
+  public static final String OVERVIEW_TEMPLATE =
+      "com/google/devtools/build/docgen/templates/be/overview.vm";
+  public static final String RULES_TEMPLATE =
+      "com/google/devtools/build/docgen/templates/be/rules.vm";
+  public static final String BE_NAV_TEMPLATE =
+      "com/google/devtools/build/docgen/templates/be/be-nav.vm";
 
   public static final String SKYLARK_LIBRARY_TEMPLATE =
       "com/google/devtools/build/docgen/templates/skylark-library.vm";
diff --git a/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java b/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java
index 4d0a68b..a7105e3 100644
--- a/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java
+++ b/src/main/java/com/google/devtools/build/docgen/RuleDocumentation.java
@@ -13,6 +13,7 @@
 // limitations under the License.
 package com.google.devtools.build.docgen;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.docgen.DocgenConsts.RuleType;
@@ -104,6 +105,20 @@
   }
 
   /**
+   * Returns a "normalized" version of the input string. Used to convert rule family names into
+   * strings that are more friendly as file names. For example, "C / C++" is converted to
+   * "c-cpp".
+   */
+  @VisibleForTesting
+  static String normalize(String s) {
+    return s.toLowerCase()
+        .replace("+", "p")
+        .replaceAll("[()]", "")
+        .replaceAll("[\\s/]", "-")
+        .replaceAll("[-]+", "-");
+  }
+
+  /**
    * Returns the number of first line of the rule documentation in its declaration file.
    */
   int getStartLineCount() {
@@ -208,15 +223,22 @@
    */
   public String getAttributeSignature() {
     StringBuilder sb = new StringBuilder();
-    sb.append(String.format(
-        "%s(<a href=\"#%s.name\">name</a>, ",
-        ruleName, ruleName));
+    sb.append(String.format("%s(<a href=\"#%s.name\">name</a>, ", ruleName, ruleName));
     int i = 0;
     for (RuleDocumentationAttribute attributeDoc : attributes) {
       String attrName = attributeDoc.getAttributeName();
       // Generate the link for the attribute documentation
-      sb.append(String.format("<a href=\"#%s.%s\">%s</a>",
-          attributeDoc.getGeneratedInRule(ruleName).toLowerCase(), attrName, attrName));
+      if (attributeDoc.isCommonType()) {
+        sb.append(String.format("<a href=\"common-definitions.html#%s.%s\">%s</a>",
+            attributeDoc.getGeneratedInRule(ruleName).toLowerCase(),
+            attrName,
+            attrName));
+      } else {
+        sb.append(String.format("<a href=\"#%s.%s\">%s</a>",
+            attributeDoc.getGeneratedInRule(ruleName).toLowerCase(),
+            attrName,
+            attrName));
+      }
       if (i < attributes.size() - 1) {
         sb.append(", ");
       } else {
diff --git a/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java b/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
index 4021d34..9c46fd5 100644
--- a/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
+++ b/src/main/java/com/google/devtools/build/docgen/RuleDocumentationAttribute.java
@@ -44,16 +44,16 @@
       .put(Type.STRING, "String")
       .put(Type.STRING_LIST, "List of strings")
       .put(BuildType.TRISTATE, "Integer")
-      .put(BuildType.LABEL, "<a href=\"build-ref.html#labels\">Label</a>")
-      .put(BuildType.LABEL_LIST, "List of <a href=\"build-ref.html#labels\">labels</a>")
+      .put(BuildType.LABEL, "<a href=\"../build-ref.html#labels\">Label</a>")
+      .put(BuildType.LABEL_LIST, "List of <a href=\"../build-ref.html#labels\">labels</a>")
       .put(BuildType.LABEL_DICT_UNARY,
-          "Dictionary mapping strings to <a href=\"build-ref.html#labels\">labels</a>")
+          "Dictionary mapping strings to <a href=\"../build-ref.html#labels\">labels</a>")
       .put(BuildType.LABEL_LIST_DICT,
-          "Dictionary mapping strings to lists of <a href=\"build-ref.html#labels\">labels</a>")
-      .put(BuildType.NODEP_LABEL, "<a href=\"build-ref.html#name\">Name</a>")
-      .put(BuildType.NODEP_LABEL_LIST, "List of <a href=\"build-ref.html#name\">names</a>")
-      .put(BuildType.OUTPUT, "<a href=\"build-ref.html#filename\">Filename</a>")
-      .put(BuildType.OUTPUT_LIST, "List of <a href=\"build-ref.html#filename\">filenames</a>")
+          "Dictionary mapping strings to lists of <a href=\"../build-ref.html#labels\">labels</a>")
+      .put(BuildType.NODEP_LABEL, "<a href=\"../build-ref.html#name\">Name</a>")
+      .put(BuildType.NODEP_LABEL_LIST, "List of <a href=\"../build-ref.html#name\">names</a>")
+      .put(BuildType.OUTPUT, "<a href=\"../build-ref.html#filename\">Filename</a>")
+      .put(BuildType.OUTPUT_LIST, "List of <a href=\"../build-ref.html#filename\">filenames</a>")
       .build();
 
   private final Class<? extends RuleDefinition> definitionClass;
diff --git a/src/main/java/com/google/devtools/build/docgen/SummaryRuleFamily.java b/src/main/java/com/google/devtools/build/docgen/SummaryRuleFamily.java
index 7f1c78f..c55f146 100644
--- a/src/main/java/com/google/devtools/build/docgen/SummaryRuleFamily.java
+++ b/src/main/java/com/google/devtools/build/docgen/SummaryRuleFamily.java
@@ -30,14 +30,17 @@
 @Immutable
 public class SummaryRuleFamily {
   private final String name;
+  private final String id;
   private final ImmutableList<RuleDocumentation> binaryRules;
   private final ImmutableList<RuleDocumentation> libraryRules;
   private final ImmutableList<RuleDocumentation> testRules;
   private final ImmutableList<RuleDocumentation> otherRules1;
   private final ImmutableList<RuleDocumentation> otherRules2;
 
-  SummaryRuleFamily(ListMultimap<RuleType, RuleDocumentation> ruleTypeMap, String name) {
+  SummaryRuleFamily(ListMultimap<RuleType, RuleDocumentation> ruleTypeMap,
+      String name, String id) {
     this.name = name;
+    this.id = id;
     this.binaryRules = ImmutableList.copyOf(ruleTypeMap.get(RuleType.BINARY));
     this.libraryRules = ImmutableList.copyOf(ruleTypeMap.get(RuleType.LIBRARY));
     this.testRules = ImmutableList.copyOf(ruleTypeMap.get(RuleType.TEST));
@@ -58,6 +61,10 @@
     return name;
   }
 
+  public String getId() {
+    return id;
+  }
+
   public List<RuleDocumentation> getBinaryRules() {
     return binaryRules;
   }
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm b/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
deleted file mode 100644
index e10b1b5..0000000
--- a/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
+++ /dev/null
@@ -1,318 +0,0 @@
-<html>
-<head>
-
-  <title>Bazel BUILD Encyclopedia of Functions</title>
-  <link href="docs_style.css" rel="stylesheet" type="text/css" />
-</head>
-
-<body>
-<div style="width:100%;">
-<div id="left-panel" style="margin-left:-80px;height:97%;float:left;position:fixed;overflow-y:scroll;overflow-x:hidden;border-right:thin solid #000000;resize:horizontal;">
-<h3 style="margin-left:0px">Rules:</h3>
-
-${LEFT_PANEL}
-
-</div>
-<div id="main-panel" style="margin-left:200px">
-
-<h1>Bazel BUILD Encyclopedia of Functions</h1>
-<h2>Contents</h2>
-
-  <h3>Concepts and terminology</h3>
-  <table class="layout"><tr><td>
-  <ul class="be-toc">
-    <li><a href="#common-definitions">Common definitions</a>:
-      <ul>
-      <li><a href="#sh-tokenization">Bourne shell tokenization</a></li>
-      <li><a href="#label-expansion">Label expansion</a></li>
-      <li><a href="#common-attributes">Common attributes</a></li>
-      <li><a href="#common-attributes-tests">Common attributes for tests</a></li>
-      <li><a href="#common-attributes-binaries">Common attributes for binaries</a></li>
-      <li><a href="#configurable-attributes">Configurable attributes</a></li>
-      <li><a href="#implicit-outputs">Implicit output targets</a></li>
-      </ul>
-    </li>
-  </ul>
-  </td><td>
-  <ul class="be-toc">
-    <li><a href="#make_variables">"Make" variables</a>
-    <ul class="be-toc">
-      <li><a href="#make-var-substitution">"Make" variable substitution</a></li>
-      <li><a href="#predefined_variables">Predefined variables</a></li>
-
-    </ul>
-    <li><a href="#predefined-python-variables">Predefined Python Variables</a></li>
-  </ul>
-  </td><td>
-  <ul class="be-toc">
-    <li><a href="#load">load</a></li>
-
-    <li><a href="#package">package</a></li>
-    <li><a href="#package_group">package_group</a></li>
-
-    <li><a href="#licenses">licenses</a></li>
-    <li><a href="#exports_files">exports_files</a></li>
-    <li><a href="#glob">glob</a></li>
-    <li><a href="#select">select</a></li>
-    <li><a href="#workspace">workspace</a></li>
-  </ul>
-  </td></tr></table>
-
-  <h3>Rules</h3>
-
-<h4>Language-specific Rules</h4>
-
-#macro(summaryTable $ruleFamilies)
-  <tbody>
-  #foreach($ruleFamily in $ruleFamilies)
-    <tr>
-      <td class="lang">${ruleFamily.name}</td>
-      <td>
-    #foreach($ruleDoc in $ruleFamily.binaryRules)
-        <a href="#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
-          ${ruleDoc.ruleName}
-        </a>
-        <br />
-    #end
-      </td>
-      <td>
-    #foreach($ruleDoc in $ruleFamily.libraryRules)
-        <a href="#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
-          ${ruleDoc.ruleName}
-        </a>
-        <br />
-    #end
-      </td>
-      <td>
-    #foreach($ruleDoc in $ruleFamily.testRules)
-        <a href="#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
-          ${ruleDoc.ruleName}
-        </a>
-        <br />
-    #end
-      </td>
-      <td>
-    #foreach($ruleDoc in $ruleFamily.otherRules1)
-        <a href="#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
-          ${ruleDoc.ruleName}
-        </a>
-        <br />
-    #end
-      </td>
-      <td>
-    #foreach($ruleDoc in $ruleFamily.otherRules2)
-        <a href="#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
-          ${ruleDoc.ruleName}
-        </a>
-        <br />
-    #end
-      </td>
-    </tr>
-  #end
-  </tbody>
-#end
-
-<table class="table table-condensed table-striped" summary="Table of rules sorted by language">
-  <colgroup span="6" width="20%"></colgroup>
-  <thead>
-    <tr>
-      <th>Language</th>
-      <th>Binary rules</th>
-      <th>Library rules</th>
-      <th>Test rules</th>
-      <th>Other rules</th>
-      <th></th>
-    </tr>
-  </thead>
-#summaryTable($langSpecificSummaryFamilies)
-
-</table>
-<h4>Rules that do not apply to a specific programming language</h4>
-
-<table class="table table-condensed table-striped" summary="Table of rules not specific to a programming language">
-  <colgroup span="6" width="20%"></colgroup>
-#summaryTable($otherSummaryFamilies)
-
-</table>
-
-<h4>Rules implemented as Skylark extensions</h4>
-
-<p>
-The Bazel team provides a set of supported build rules written using the
-<a href="/docs/skylark/index.html">Skylark</a> rules framework. These rules
-should be explicitly <a href="#load">load</a>ed. They allow you to build the
-following:
-</p>
-
-<ul>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_rules/closure">
-    Closure libraries</a></li>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/docker">
-    Docker images</a></li>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/groovy">
-    Groovy projects</a></li>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_rules/appengine">
-    Java App Engine applications</a></li>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/d">
-    D projects</a></li>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_rules/rust">
-    Rust projects</a></li>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/jsonnet">
-    Jsonnet files</a></li>
-<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/scala">
-    Scala projects</a> - experimental</li>
-</ul>
-
-<h2 id="common-definitions">Common definitions</h2>
-
-<p>This section defines various terms and concepts that are common to
-many functions or build rules below.
-</p>
-
-<h3 id='sh-tokenization'>Bourne shell tokenization</h3>
-<p>
-  Certain string attributes of some rules are split into multiple
-  words according to the tokenization rules of the Bourne shell:
-  unquoted spaces delimit separate words, and single- and
-  double-quotes characters and backslashes are used to prevent
-  tokenization.
-</p>
-<p>
-  Those attributes that are subject to this tokenization are
-  explicitly indicated as such in their definitions in this document.
-</p>
-<p>
-  Attributes subject to "Make" variable expansion and Bourne shell
-  tokenization are typically used for passing arbitrary options to
-  compilers and other tools. Examples of such attributes are
-  <code>cc_library.copts</code> and <code>java_library.javacopts</code>.
-  Together these substitutions allow a
-  single string variable to expand into a configuration-specific list
-  of option words.
-</p>
-
-<h3 id='label-expansion'>Label expansion</h3>
-<p>
-  Some string attributes of a very few rules are subject to label
-  expansion: if those strings contain a valid label as a
-  substring, such as <code>//mypkg:target</code>, and that label is a
-  declared prerequisite of the current rule, it is expanded into the
-  pathname of the file represented by the target <code>//mypkg:target</code>.
-</p>
-
-<p>
-  Example attributes include <code>genrule.cmd</code> and
-  <code>cc_binary.linkopts</code>.  The details may vary significantly in
-  each case, over such issues as: whether relative labels are
-  expanded; how labels that expand to multiple files are
-  treated, etc.  Consult the rule attribute documentation for
-  specifics.
-</p>
-
-<h3 id="common-attributes">Attributes common to all build rules</h3>
-
-#macro(commonAttributeDoc $type $attributeMap)
-  <table class="table table-condensed table-bordered table-params">
-    <colgroup>
-      <col class="col-param" />
-      <col class="param-description" />
-    </colgroup>
-    <thead>
-      <tr>
-        <th>Attribute</th>
-        <th>Description</th>
-      </tr>
-    </thead>
-    <tbody>
-  #foreach ($name in $attributeMap.keySet())
-      <tr>
-        <td id="${type}.${name}"><code>${name}</code></td>
-        <td>${attributeMap.get($name).htmlDocumentation}</td>
-      </tr>
-  #end
-    </tbody>
-  </table>
-#end
-
-<p>This section describes attributes that are common to all build rules.<br/>
-Please note that it is an error to list the same label twice in a list of
-labels attribute.
-</p>
-
-#commonAttributeDoc("common" $commonAttributes)
-
-<h3 id="common-attributes-tests">Attributes common to all test rules (*_test)</h3>
-
-<p>This section describes attributes that are common to all test rules.</p>
-
-#commonAttributeDoc("test" $testAttributes)
-
-<h3 id="common-attributes-binaries">Attributes common to all binary rules (*_binary)</h3>
-
-<p>This section describes attributes that are common to all binary rules.</p>
-
-#commonAttributeDoc("binary" $binaryAttributes)
-
-<h3 id="configurable-attributes">Configurable attributes</h3>
-
-<p>
-  Most rule attributes can be "configured" so that their values can
-  depend on the command-line flags passed to Bazel. This can be used,
-  for example, to declare platform-dependent <code>srcs</code> or custom
-  compiler flags depending on the
-  <a href="bazel-user-manual.html#flag--compilation_mode">compilation
-  mode</a>. This feature is very close in spirit to
-  <a href="#cc_library.abi_deps">abi_deps</a>, except that it's not
-  limited to <code>cc_*</code> rules and the <code>deps</code> attribute.
-</p>
-
-</p>
-
-<h3 id="implicit-outputs">Implicit output targets</h3>
-
-<p>When you define a build rule in a BUILD file, you are explicitly
-  declaring a new, named rule target in a package.  Many build rule
-  functions also <i>implicitly</i> entail one or more output file
-  targets, whose contents and meaning are rule-specific.
-
-  For example, when you explicitly declare a
-  <code>java_binary(name='foo', ...)</code> rule, you are also
-  <i>implicitly</i> declaring an output file
-  target <code>foo_deploy.jar</code> as a member of the same package.
-  (This particular target is a self-contained Java archive suitable
-  for deployment.)
-</p>
-
-<p>
-  Implicit output targets are first-class members of the global
-  target graph.  Just like other targets, they are built on demand,
-  either when specified in the top-level built command, or when they
-  are necessary prerequisites for other build targets.  They can be
-  referenced as dependencies in BUILD files, and can be observed in
-  the output of analysis tools such as <code>bazel query</code>.
-</p>
-
-<p>
-  For each kind of build rule, the rule's documentation contains a
-  special section detailing the names and contents of any implicit
-  outputs entailed by a declaration of that kind of rule.
-</p>
-
-<p>
-  An important but somewhat subtle distinction between the
-  two namespaces used by the build system:
-  <a href="build-ref.html#labels">labels</a> identify <em>targets</em>,
-  which may be rules or files, and file targets may be divided into
-  either source (or input) file targets and derived (or output) file
-  targets.  These are the things you can mention in BUILD files,
-  build from the command-line, or examine using <code>bazel query</code>;
-  this is the <em>target namespace</em>.  Each file target corresponds
-  to one actual file on disk (the "file system namespace"); each rule
-  target may correspond to zero, one or more actual files on disk.
-  There may be files on disk that have no corresponding target; for
-  example, <code>.o</code> object files produced during C++ compilation
-  cannot be referenced from within BUILD files or from the command line.
-  In this way, the build tool may hide certain implementation details of
-  how it does its job. This is explained more fully in
-  the <a href="build-ref.html">BUILD Concept Reference</a>.
-</p>
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/be-nav.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/be-nav.vm
new file mode 100644
index 0000000..3f0df10
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/be-nav.vm
@@ -0,0 +1,35 @@
+#set ($path = "/docs/be")
+<h3>Build Encyclopedia</h3>
+<ul class="sidebar-nav">
+  <li><a href="${path}/overview.html">Overview</a></li>
+  <li>
+
+    <a data-toggle="collapse" href="#be-menu" aria-expanded="false"
+        aria-controls="be-menu">
+      Concepts <span class="caret"></span>
+    </a>
+    <ul class="collapse sidebar-nav sidebar-submenu" id="be-menu">
+      <li><a href="${path}/common-definitions.html">Common Definitions</a></li>
+      <li><a href="${path}/make-variables.html">"Make" variables</a></li>
+      <li><a href="${path}/predefined-python-variables.html">Predefined Python Variables</a></li>
+    </ul>
+  </li>
+  <li class="sidebar-nav-heading">Built-in Rules</li>
+  <li><a href="${path}/functions.html">Functions</a></li>
+  #foreach ($namePair in $ruleFamilyNames)
+  <li><a href="${path}/${namePair.getFirst()}.html">${namePair.getSecond()}</a></li>
+  #end
+
+  <li class="sidebar-nav-heading">Skylark Rules</li>
+  <li><a href="${path}/appengine.html">Java AppEngine</a></li>
+  <li><a href="${path}/closure.html">Closure Tools</a></li>
+  <li><a href="${path}/d.html">D</a></li>
+  <li><a href="${path}/docker.html">Docker</a></li>
+  <li><a href="${path}/groovy.html">Groovy</a></li>
+  <li><a href="${path}/go.html">Go</a></li>
+  <li><a href="${path}/jsonnet.html">Jsonnet</a></li>
+  <li><a href="${path}/pkg.html">Packaging</a></li>
+  <li><a href="${path}/rust.html">Rust</a></li>
+  <li><a href="${path}/sass.html">Sass</a></li>
+  <li><a href="${path}/scala.html">Scala</a></li>
+</ul>
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/common-definitions.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/common-definitions.vm
new file mode 100644
index 0000000..4b33058
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/common-definitions.vm
@@ -0,0 +1,169 @@
+#parse("com/google/devtools/build/docgen/templates/be/header.vm")
+
+<h1>Common definitions</h1>
+
+<p>This section defines various terms and concepts that are common to
+many functions or build rules below.
+</p>
+
+<div class="toc">
+  <h1>Contents</h1>
+  <ul>
+    <li><a href="#borne-shell-tokenization">Borne shell tokenization</a></li>
+    <li><a href="#label-expansion">Label Expansion</a></li>
+    <li><a href="#common-attributes">Attributes common to all build rules</a></li>
+    <li><a href="#common-attributes-tests">Attributes common to all test rules (*_test)</a></li>
+    <li><a href="#common-attributes-binaries">Attributes common to all binary rules (*_binary)</a></li>
+    <li><a href="#configurable-attributes">Configurable attributes</a></li>
+    <li><a href="#implicit-outputs">Implicit output targets</a></li>
+  </ul>
+</div>
+<h2 id='sh-tokenization'>Bourne shell tokenization</h2>
+<p>
+  Certain string attributes of some rules are split into multiple
+  words according to the tokenization rules of the Bourne shell:
+  unquoted spaces delimit separate words, and single- and
+  double-quotes characters and backslashes are used to prevent
+  tokenization.
+</p>
+<p>
+  Those attributes that are subject to this tokenization are
+  explicitly indicated as such in their definitions in this document.
+</p>
+<p>
+  Attributes subject to "Make" variable expansion and Bourne shell
+  tokenization are typically used for passing arbitrary options to
+  compilers and other tools. Examples of such attributes are
+  <code>cc_library.copts</code> and <code>java_library.javacopts</code>.
+  Together these substitutions allow a
+  single string variable to expand into a configuration-specific list
+  of option words.
+</p>
+
+<h2 id='label-expansion'>Label expansion</h2>
+<p>
+  Some string attributes of a very few rules are subject to label
+  expansion: if those strings contain a valid label as a
+  substring, such as <code>//mypkg:target</code>, and that label is a
+  declared prerequisite of the current rule, it is expanded into the
+  pathname of the file represented by the target <code>//mypkg:target</code>.
+</p>
+
+<p>
+  Example attributes include <code>genrule.cmd</code> and
+  <code>cc_binary.linkopts</code>.  The details may vary significantly in
+  each case, over such issues as: whether relative labels are
+  expanded; how labels that expand to multiple files are
+  treated, etc.  Consult the rule attribute documentation for
+  specifics.
+</p>
+
+<h2 id="common-attributes">Attributes common to all build rules</h2>
+
+#macro(commonAttributeDoc $type $attributeMap)
+  <table class="table table-condensed table-bordered table-params">
+    <colgroup>
+      <col class="col-param" />
+      <col class="param-description" />
+    </colgroup>
+    <thead>
+      <tr>
+        <th>Attribute</th>
+        <th>Description</th>
+      </tr>
+    </thead>
+    <tbody>
+  #foreach ($name in $attributeMap.keySet())
+      <tr>
+        <td id="${type}.${name}"><code>${name}</code></td>
+        <td>${attributeMap.get($name).htmlDocumentation}</td>
+      </tr>
+  #end
+    </tbody>
+  </table>
+#end
+
+<p>This section describes attributes that are common to all build rules.<br/>
+Please note that it is an error to list the same label twice in a list of
+labels attribute.
+</p>
+
+#commonAttributeDoc("common" $commonAttributes)
+
+<h2 id="common-attributes-tests">Attributes common to all test rules (*_test)</h2>
+
+<p>This section describes attributes that are common to all test rules.</p>
+
+#commonAttributeDoc("test" $testAttributes)
+
+<h2 id="common-attributes-binaries">Attributes common to all binary rules (*_binary)</h2>
+
+<p>This section describes attributes that are common to all binary rules.</p>
+
+#commonAttributeDoc("binary" $binaryAttributes)
+
+<h2 id="configurable-attributes">Configurable attributes</h2>
+
+<p>
+  Most rule attributes can be "configured" so that their values can
+  depend on the command-line flags passed to Bazel. This can be used,
+  for example, to declare platform-dependent <code>srcs</code> or custom
+  compiler flags depending on the
+  <a href="bazel-user-manual.html#flag--compilation_mode">compilation
+  mode</a>. This feature is very close in spirit to
+  <a href="#cc_library.abi_deps">abi_deps</a>, except that it's not
+  limited to <code>cc_*</code> rules and the <code>deps</code> attribute.
+</p>
+
+</p>
+
+<h2 id="implicit-outputs">Implicit output targets</h2>
+
+<p>When you define a build rule in a BUILD file, you are explicitly
+  declaring a new, named rule target in a package.  Many build rule
+  functions also <i>implicitly</i> entail one or more output file
+  targets, whose contents and meaning are rule-specific.
+
+  For example, when you explicitly declare a
+  <code>java_binary(name='foo', ...)</code> rule, you are also
+  <i>implicitly</i> declaring an output file
+  target <code>foo_deploy.jar</code> as a member of the same package.
+  (This particular target is a self-contained Java archive suitable
+  for deployment.)
+</p>
+
+<p>
+  Implicit output targets are first-class members of the global
+  target graph.  Just like other targets, they are built on demand,
+  either when specified in the top-level built command, or when they
+  are necessary prerequisites for other build targets.  They can be
+  referenced as dependencies in BUILD files, and can be observed in
+  the output of analysis tools such as <code>bazel query</code>.
+</p>
+
+<p>
+  For each kind of build rule, the rule's documentation contains a
+  special section detailing the names and contents of any implicit
+  outputs entailed by a declaration of that kind of rule.
+</p>
+
+<p>
+  An important but somewhat subtle distinction between the
+  two namespaces used by the build system:
+  <a href="build-ref.html#labels">labels</a> identify <em>targets</em>,
+  which may be rules or files, and file targets may be divided into
+  either source (or input) file targets and derived (or output) file
+  targets.  These are the things you can mention in BUILD files,
+  build from the command-line, or examine using <code>bazel query</code>;
+  this is the <em>target namespace</em>.  Each file target corresponds
+  to one actual file on disk (the "file system namespace"); each rule
+  target may correspond to zero, one or more actual files on disk.
+  There may be files on disk that have no corresponding target; for
+  example, <code>.o</code> object files produced during C++ compilation
+  cannot be referenced from within BUILD files or from the command line.
+  In this way, the build tool may hide certain implementation details of
+  how it does its job. This is explained more fully in
+  the <a href="build-ref.html">BUILD Concept Reference</a>.
+</p>
+
+#parse("com/google/devtools/build/docgen/templates/be/footer.vm")
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/footer.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/footer.vm
new file mode 100644
index 0000000..19c5ea8
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/footer.vm
@@ -0,0 +1,2 @@
+<!-- Generated footer -->
+
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be-footer.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/functions.vm
similarity index 70%
rename from src/main/java/com/google/devtools/build/docgen/templates/be-footer.vm
rename to src/main/java/com/google/devtools/build/docgen/templates/be/functions.vm
index cd308b4..548f005 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/be-footer.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/functions.vm
@@ -1,17 +1,67 @@
+#parse("com/google/devtools/build/docgen/templates/be/header.vm")
+
+<h1>Functions</h1>
+
+<div class="toc">
+  <h1>Contents</h1>
+  <ul>
+    <li><a href="#load">load</a></li>
+    <li><a href="#package">package</a></li>
+    <li><a href="#package_group">package_group</a></li>
+    <li><a href="#licenses">licenses</a></li>
+    <li><a href="#exports_files">exports_files</a></li>
+    <li><a href="#glob">glob</a></li>
+    <li><a href="#select">select</a></li>
+    <li><a href="#workspace">workspace</a></li>
+  </ul>
+</div>
+<!-- =================================================================
+                              load()
+     =================================================================
+-->
+
+<h2 id="load">load</h2>
+
+<pre>load(path, symbols...)</pre>
+
+<p><code>load()</code> is a statement that imports definitions from a
+  Skylark module (<code>.bzl</code> file). For example:
+</p>
+
+<pre class="code">
+load("/tools/build_rules/build_test", "build_test")
+
+build_test(name = ...)
+</pre>
+
+<p>This will execute the
+
+  Skylark
+  module <code>tools/build_rules/build_test.bzl</code> and import the symbol
+  <code>build_test</code> in the local environment. This is useful for
+  using macros or for sharing values between multiple BUILD files. By
+  using more arguments, you can load more symbols at once.</p>
+
+<p>Relative paths are allowed only to load a file from the same directory
+  (not a subdirectory), e.g.</p>
+
+<pre class="code">
+load("build_defs", "COMPILER_FLAGS", "LINKER_FLAGS")
+</pre>
 
 <!-- =================================================================
                               package()
      =================================================================
 -->
 
-<h3 id="package">package</h3>
+<h2 id="package">package</h2>
 
-<p><code>package(default_deprecation,
+<pre>package(default_deprecation,
 
   default_testonly,
   default_visibility,
-  features)</code>
-</p>
+  features)
+</pre>
 
 <p>This function declares metadata that applies to every subsequent rule in the
 package. It is used at most once within a package (BUILD file).</p>
@@ -19,47 +69,66 @@
 <p>It is recommended that the package function is called at the top of the
 file, before any rule.</p>
 
-<h4 id="package_args">Arguments</h4>
+<h3 id="package_args">Arguments</h3>
 
-<ul>
-  <li id="package.default_visibility"><code>default_visibility</code>:
-    The default visibility of the rules in this package.
-    <i>(List of <a href="build-ref.html#labels">labels</a>; optional)</i><br/>
+<table class="table table-condensed table-bordered table-params">
+  <colgroup>
+    <col class="col-param" />
+    <col class="param-description" />
+  </colgroup>
+  <thead>
+    <tr>
+      <th>Attribute</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td id="package.default_visibility"><code>default_visibility</code></td>
+      <td>
+        <p><code>List of <a href="build-ref.html#labels">labels</a>; optional</code></p>
+        <p>The default visibility of the rules in this package.</p>
+        <p>Every rule in this package has the visibility specified in this
+        attribute, unless otherwise specified in the <code>visibility</code>
+        attribute of the rule. For detailed information about the syntax of this
+        attribute, see the documentation of the <a href="#common.visibility">visibility</a>
+        attribute. The package default visibility does not apply to
+        <a href="#exports_files">exports_files</a>, which is
+        public by default.</p>
+      </td>
+    </tr>
+    <tr>
+      <td id="package.default_deprecation"><code>default_deprecation</code></td>
+      <td>
+        <p><code>String; optional</code></p>
+        <p>Sets the default <a href="#common.deprecation"><code>deprecation</code></a> message
+        for all rules in this package.</p>
+      </td>
+    </tr>
+    <tr>
+      <td id="package.default_testonly"><code>default_testonly</code></td>
+      <td>
+        <p><code>Boolean; optional; default is 0 except as noted</code></p>
+        <p>Sets the default <a href="#common.testonly"><code>testonly</code></a> property
+        for all rules in this package.</p>
+        <p>In packages under <code>javatests</code> the default value is 1.</p>
+      </td>
+    </tr>
+    <tr>
+      <td id="package.features"><code>features</code></td>
+      <td>
+        <p><code>List strings; optional</code></p>
+        <p>Sets various flags that affect the semantics of this BUILD file.</p>
+        <p>This feature is mainly used by the people working on the build system to
+        tag packages that need some kind of special handling. Do not use this unless
+        explicitly requested by someone working on the build system.</p>
+      </td>
+    </tr>
 
-    <p>Every rule in this package has the visibility specified in this
-    attribute, unless otherwise specified in the <code>visibility</code>
-    attribute of the rule. For detailed information about the syntax of this
-    attribute, see the documentation of the <a href="#common.visibility">visibility</a>
-    attribute. The package default visibility does not apply to
+  </tbody>
+</table>
 
-    <a href="#exports_files">exports_files</a>, which is
-    public by default.
-  </li>
-
-  <li id="package.default_deprecation"><code>default_deprecation</code>:
-    Sets the default <a href="#common.deprecation"><code>deprecation</code></a> message
-    for all rules in this package. <i>(String; optional)</i>
-  </li>
-
-  <li id="package.default_testonly"><code>default_testonly</code>:
-    Sets the default <a href="#common.testonly"><code>testonly</code></a> property
-    for all rules in this package. <i>(Boolean; optional; default is 0 except as noted)</i>
-
-    <p>In packages under <code>javatests</code> the default value is 1.</p>
-  </li>
-
-  <li id="package.features"><code>features</code>:
-    Sets various flags that affect the semantics of this BUILD file.
-    <i>(List strings; optional)</i>
-
-    <p>This feature is mainly used by the people working on the build system to
-    tag packages that need some kind of special handling. Do not use this unless
-    explicitly requested by someone working on the build system.</p>
-  </li>
-
-</ul>
-
-<h4 id="package_example">Examples</h4>
+<h3 id="package_example">Examples</h3>
 
 The declaration below declares that the rules in this package are
 visible only to members of package
@@ -75,9 +144,9 @@
      =================================================================
 -->
 
-<h3 id="package_group">package_group</h3>
+<h2 id="package_group">package_group</h2>
 
-<p><code>package_group(name, packages, includes)</code></p>
+<pre>package_group(name, packages, includes)</pre>
 
 <p>This function defines a set of packages and assigns a label to the
 group. The label can be referenced in <code>visibility</code> attributes.</p>
@@ -87,49 +156,67 @@
 in the same package. For more detailed description of the visibility system, see
 the <a href="#common.visibility">visibility</a> attribute.
 
-<h4 id="package_group_args">Arguments</h4>
+<h3 id="package_group_args">Arguments</h3>
 
-<ul>
-  <li id="package_group.name"><code>name</code>:
-    A unique name for this rule.
-    <i>(<a href="build-ref.html#name">Name</a>; required)</i>
-  </li>
+<table class="table table-condensed table-bordered table-params">
+  <colgroup>
+    <col class="col-param" />
+    <col class="param-description" />
+  </colgroup>
+  <thead>
+    <tr>
+      <th>Attribute</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td id="package_group.name"><code>name</code></td>
+      <td>
+        <p><code><a href="build-ref.html#name">Name</a>; required</code></p>
+        <p>A unique name for this rule.</p>
+      </td>
+    </tr>
+    <tr>
+      <td id="package_group.packages"><code>packages</code></td>
+      <td>
+        <p><code>List of <a href="build-ref.html#s4">Package</a>; optional</code></p>
+        <p>A complete enumeration of packages in this group.</p>
 
-  <li id="package_group.packages"><code>packages</code>:
-    A complete enumeration of packages in this group.
-    <i>(List of <a href="build-ref.html#s4">Package</a>; optional)</i><br/>
+        <p>Packages should be referred to using their full names,
+        starting with a double slash. For
+        example, <code>//foo/bar/main</code> is a valid element
+        of this list.</p>
 
-    <p>Packages should be referred to using their full names,
-    starting with a double slash. For
-    example, <code>//foo/bar/main</code> is a valid element
-    of this list.</p>
+        <p>You can also specify wildcards: the specification
+        <code>//foo/...</code> specifies every package under
+        <code>//foo</code>, including <code>//foo</code> itself.</p>
 
-    <p>You can also specify wildcards: the specification
-    <code>//foo/...</code> specifies every package under
-    <code>//foo</code>, including <code>//foo</code> itself.
+        <p>If this attribute is missing, the package group itself will contain
+        no packages (but it can still include other package groups).</p>
+      </td>
+    </tr>
+    <tr>
+      <td id="package_group.includes"><code>includes</code></td>
+      <td>
+        <p><code>List of <a href="build-ref.html#labels">labels</a>; optional</code></p>
+        <p>Other package groups that are included in this one.</p>
 
-    <p>If this attribute is missing, the package group itself will contain
-    no packages (but it can still include other package groups).</p>
-  </li>
+        <p>The labels in this attribute must refer to other package
+        groups. Packages in referenced package groups are taken to be part
+        of this package group. This is transitive, that is, if package
+        group <code>a</code> contains package group <code>b</code>,
+        and <code>b</code> contains package group <code>c</code>, every
+        package in <code>c</code> will also be a member of <code>a</code>.</p>
+      </td>
+    </tr>
+  </tbody>
+</table>
 
-  <li id="package_group.includes"><code>includes</code>:
-    Other package groups that are included in this one.
-    <i>(List of <a href="build-ref.html#labels">labels</a>; optional)</i><br/>
+<h3 id="package_group_example">Examples</h3>
 
-    <p>The labels in this attribute must refer to other package
-    groups. Packages in referenced package groups are taken to be part
-    of this package group. This is transitive, that is, if package
-    group <code>a</code> contains package group <code>b</code>,
-    and <code>b</code> contains package group <code>c</code>, every
-    package in <code>c</code> will also be a member of <code>a</code>.</p>
-  </li>
-</ul>
-
-
-<h4 id="package_group_example">Examples</h4>
-
-The following <code>package_group</code> declaration specifies a
-package group called "tropical" that contains tropical fruits.
+<p>The following <code>package_group</code> declaration specifies a
+package group called "tropical" that contains tropical fruits.</p>
 
 <pre class="code">
 package_group(
@@ -142,8 +229,8 @@
 )
 </pre>
 
-The following declarations specify the package groups of a fictional
-application:
+<p>The following declarations specify the package groups of a fictional
+application:</p>
 
 <pre class="code">
 package_group(
@@ -174,15 +261,54 @@
 )
 </pre>
 
+<!-- =================================================================
+                              licenses()
+     =================================================================
+-->
+
+<h2 id="licenses">licenses</h2>
+
+<pre>licenses(license_types)</pre>
+
+<p><code>licenses()</code> specifies the default license type (or types)
+   of the build rules in a <code>BUILD</code> file.
+
+   The <code>licenses()</code> directive should appear close to the
+   beginning of the <code>BUILD</code> file, before any build rules, as it
+   sets the <code>BUILD</code>-file scope default for build rule license
+   types.</p>
+
+<h3 id="licenses_args">Arguments</h3>
+
+<p>The argument, <code id="licenses.licence_types">license_types</code>,
+   is a list of license-type strings.
+   <!-- TODO(bazel-team): specify some examples -->
+
+</p>
+
+<h3 id="licenses_example">Examples</h3>
+
+<p>The following example specifies a single license type of
+  <code>"notice"</code>.  Third-party software licenses that do not require
+  publishing of source code changes but require some sort of copyright or
+  other public notice are included in this license type.
+</p>
+
+<pre class="code">
+
+licenses(["notice"])  # MIT license
+
+exports_files(["jquery-2.1.1.js"])
+</pre>
 
 <!-- =================================================================
                         exports_files([label, ...])
      =================================================================
   -->
 
-<h3 id="exports_files">exports_files</h3>
+<h2 id="exports_files">exports_files</h2>
 
-<p><code>exports_files([<i>label</i>, ...], visibility, licenses)</code></p>
+<pre>exports_files([<i>label</i>, ...], visibility, licenses)</pre>
 
 <p>
   <code>exports_files()</code> specifies a list of files belonging to
@@ -200,7 +326,7 @@
   shell scripts.)
 </p>
 
-<h4 id="exports_files_args">Arguments</h4>
+<h3 id="exports_files_args">Arguments</h3>
 
 <p>
   The argument is a list of names of files within the current package. A
@@ -211,7 +337,7 @@
   <a href="#common.licenses">licenses</a> can also be specified.
 </p>
 
-<h4 id="exports_files_example">Example</h4>
+<h3 id="exports_files_example">Example</h3>
 
 <p>
   The following example exports <code>golden.txt</code>, a
@@ -231,10 +357,9 @@
      =================================================================
   -->
 
-<h3 id="glob">glob</h3>
+<h2 id="glob">glob</h2>
 
-<p><code>glob(include, exclude=[], exclude_directories=1)</code>
-</p>
+<pre>glob(include, exclude=[], exclude_directories=1)</pre>
 
 <p>
 Glob is a helper function that can be used anywhere a list of filenames
@@ -321,7 +446,7 @@
 <a href="#expanded_glob_example">expanded glob example</a> section below.
 </p>
 
-<h4 id="glob_example">Glob Examples</h4>
+<h3 id="glob_example">Glob Examples</h3>
 
 <p> Create a Java library built from all java files in this directory,
 and all files generated by the <code>:gen_java_srcs</code> rule.</p>
@@ -356,7 +481,7 @@
 )
 </pre>
 
-<h4 id="recursive_glob_example">Recursive Glob Examples</h4>
+<h3 id="recursive_glob_example">Recursive Glob Examples</h3>
 
 <p>Create a library built from all java files in this directory and all
 subdirectories except those whose path includes a directory named testing.
@@ -383,7 +508,7 @@
 )
 </pre>
 
-<h4 id="expanded_glob_example">Expanded Glob Examples</h4>
+<h3 id="expanded_glob_example">Expanded Glob Examples</h3>
 
 <p>
 Create an individual genrule for *_test.cc in the current directory
@@ -412,91 +537,14 @@
 //foo:count_lines_c_test
 </pre>
 
-
-<!-- =================================================================
-                              licenses()
-     =================================================================
--->
-
-<h3 id="licenses">licenses</h3>
-
-<p><code>licenses(license_types)</code></p>
-
-<p><code>licenses()</code> specifies the default license type (or types)
-   of the build rules in a <code>BUILD</code> file.
-
-   The <code>licenses()</code> directive should appear close to the
-   beginning of the <code>BUILD</code> file, before any build rules, as it
-   sets the <code>BUILD</code>-file scope default for build rule license
-   types.</p>
-
-<h4 id="licenses_args">Arguments</h4>
-
-<p>The argument, <code id="licenses.licence_types">license_types</code>,
-   is a list of license-type strings.
-   <!-- TODO(bazel-team): specify some examples -->
-
-</p>
-
-<h4 id="licenses_example">Examples</h4>
-
-<p>The following example specifies a single license type of
-  <code>"notice"</code>.  Third-party software licenses that do not require
-  publishing of source code changes but require some sort of copyright or
-  other public notice are included in this license type.
-</p>
-
-<pre class="code">
-
-licenses(["notice"])  # MIT license
-
-exports_files(["jquery-2.1.1.js"])
-</pre>
-
-<!-- =================================================================
-                              load()
-     =================================================================
--->
-
-<h3 id="load">load</h3>
-
-<p><code>load(path, symbols...)</code></p>
-
-<p><code>load()</code> is a statement that imports definitions from a
-  Skylark module (<code>.bzl</code> file). For example:
-</p>
-
-<pre class="code">
-load("/tools/build_rules/build_test", "build_test")
-
-build_test(name = ...)
-</pre>
-
-<p>This will execute the
-
-  Skylark
-  module <code>tools/build_rules/build_test.bzl</code> and import the symbol
-  <code>build_test</code> in the local environment. This is useful for
-  using macros or for sharing values between multiple BUILD files. By
-  using more arguments, you can load more symbols at once.</p>
-
-<p>Relative paths are allowed only to load a file from the same directory
-  (not a subdirectory), e.g.</p>
-
-<pre class="code">
-load("build_defs", "COMPILER_FLAGS", "LINKER_FLAGS")
-</pre>
-
-
 <!-- =================================================================
                               select()
      =================================================================
 -->
 
-<h3 id="select">select</h3>
+<h2 id="select">select</h2>
 
-<p><code>select({conditionA: valuesA, conditionB: valuesB, ...})</code>
-</p>
+<pre>select({conditionA: valuesA, conditionB: valuesB, ...})</pre>
 
 <p><code>select()</code> is the helper function that makes an
   attribute for a
@@ -567,9 +615,9 @@
      =================================================================
 -->
 
-<h3 id="workspace">workspace</h3>
+<h2 id="workspace">workspace</h2>
 
-<p><code>workspace(name = "something")</code></p>
+<pre>workspace(name = "something")</pre>
 
 <p>This can only be used in the WORKSPACE file.</p>
 
@@ -587,7 +635,4 @@
   bar.runfiles/baz/qux/foo/bar).
 </p>
 
-</div>
-</div>
-</body>
-</html>
+#parse("com/google/devtools/build/docgen/templates/be/footer.vm")
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/header-comment.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/header.vm
similarity index 78%
rename from src/main/java/com/google/devtools/build/docgen/templates/header-comment.vm
rename to src/main/java/com/google/devtools/build/docgen/templates/be/header.vm
index 60504e8..311c2d5 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/header-comment.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/header.vm
@@ -1,7 +1,6 @@
-<!DOCTYPE html>
 <!--
  This document is synchronized with Bazel releases.
  To edit, submit changes to the Bazel source code.
 -->
 
-<!-- Generated by //src/main/java/com/google/devtools/build/docgen:build-encyclopedia.html -->
+<!-- Generated by //src/main/java/com/google/devtools/build/docgen:build-encyclopedia.zip -->
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/build-encyclopedia.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/make-variables.vm
similarity index 69%
rename from src/main/java/com/google/devtools/build/docgen/templates/build-encyclopedia.vm
rename to src/main/java/com/google/devtools/build/docgen/templates/be/make-variables.vm
index 2fbc20d..773dcdf 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/build-encyclopedia.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/make-variables.vm
@@ -1,102 +1,18 @@
-#parse("com/google/devtools/build/docgen/templates/header-comment.vm")
-
-#parse("com/google/devtools/build/docgen/templates/be-header.vm")
-
-#macro(ruledoc $ruleDocs)
-  #foreach ($rule in $ruleDocs)
-    <h3 id="${rule.ruleName}"#if($rule.isDeprecated()) class="deprecated"#end>
-      ${rule.ruleName}
-    </h3>
-
-    <pre class="rule-signature">${rule.attributeSignature}</pre>
-
-    $rule.htmlDocumentation
-
-    <h4 id="${rule.ruleName}_args">Arguments</h4>
-    <table class="table table-condensed table-bordered table-params">
-      <colgroup>
-        <col class="col-param" />
-        <col class="param-description" />
-      </colgroup>
-      <thead>
-        <tr>
-          <th>Attribute</th>
-          <th>Description</th>
-        </tr>
-      </thead>
-      <tbody>
-        <tr>
-          <td id="${rule.ruleName}.name"><code>name</code></td>
-          <td>
-            <p><code><a href="build-ref.html#name">Name</a>; required</code></p>
-            <p>A unique name for this rule.</p>
-            ${rule.nameExtraHtmlDoc}
-          </td>
-        </tr>
-      #foreach ($attribute in $rule.attributes)
-        #if (!$attribute.isCommonType())
-        <tr>
-          <td id="${rule.ruleName.toLowerCase()}.${attribute.attributeName}"#if($attribute.isDeprecated()) class="deprecated"#end>
-            <code>${attribute.attributeName}</code>
-          </td>
-          <td>
-            #if (!$attribute.synopsis.isEmpty())
-            <p><code>${attribute.synopsis}</code></p>
-            #end
-            $attribute.htmlDocumentation
-          </td>
-        </tr>
-        #end
-      #end
-      </tbody>
-    </table>
-    #if ($rule.isPublicByDefault())
-      The default visibility is public: <code>visibility = ["//visibility:public"]</code>.
-    #end
-  #end
-#end
-
-<!-- ============================================
-                      binary
-     ============================================
--->
-<h2 id="binary">*_binary</h2>
-
-<p>A <code>*_binary</code> rule compiles an application. This might be
-   an executable, a <code>.jar</code> file, and/or a collection of scripts.</p>
-
-#ruledoc($binaryDocs)
-
-<!-- ============================================
-                      library
-     ============================================
--->
-<h2 id="library">*_library</h2>
-
-<p>A <code>*_library()</code> rule compiles some sources into a library.
-   In general, a <code><var>language</var>_library</code> rule works like
-   the corresponding <code><var>language</var>_binary</code> rule, but
-   doesn't generate an executable.</p>
-
-#ruledoc($libraryDocs)
-
-<!-- ============================================
-                      test
-     ============================================
--->
-<h2 id="test">*_test</h2>
-
-<p>A <code>*_test</code> rule compiles a test.
-
-#ruledoc($testDocs)
+#parse("com/google/devtools/build/docgen/templates/be/header.vm")
 
 <!-- ============================================
                       variables
      ============================================
 -->
-<h2 id="make_variables">"Make" Variables</h2>
+<h1>"Make" Variables</h1>
 
-
+<div class="toc">
+  <ul>
+    <li><a href="#make-var-substitution">"Make" variable subsitution</a></li>
+    <li><a href="#predefined-variables">Predefined variables</a></li>
+    <li><a href="#location">"$(location)" substitution</a></li>
+  </ul>
+</div>
 <p>
   This section describes how to use a special class of built-in string variables
   that are called the "Make" environment.
@@ -116,7 +32,7 @@
   the <a href="#genrule.cmd"><code>cmd</code> attribute of a genrule</a>.
 </p>
 
-<h3 id='make-var-substitution'>"Make" variable substitution</h3>
+<h2 id='make-var-substitution'>"Make" variable substitution</h2>
 
 <p>Variables can be referenced in attributes
 
@@ -145,7 +61,7 @@
   explicitly indicated as such in their definitions in this document.
 </p>
 
-<h3 id="predefined_variables">Predefined "Make" Variables</h3>
+<h2 id="predefined_variables">Predefined "Make" Variables</h2>
 
 <p>Bazel defines a set of "Make" variables for you.</p>
 
@@ -279,21 +195,4 @@
   <code>*_test</code> or <code>*_binary</code> rule.
 </p>
 
-<h2 id="predefined-python-variables">Predefined Python Variables</h2>
-
-<h3 id="packagename">PACKAGE_NAME</h3>
-<p>
-  This is a string variable with the name
-  of the package being evaluated. The value is unaffected by subinclude.
-</p>
-
-<!-- ============================================
-                      other
-     ============================================
--->
-<h2 id="misc">Other Stuff</h2>
-
-#ruledoc($otherDocs)
-
-
-#parse("com/google/devtools/build/docgen/templates/be-footer.vm")
+#parse("com/google/devtools/build/docgen/templates/be/footer.vm")
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/overview.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/overview.vm
new file mode 100644
index 0000000..3a66308
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/overview.vm
@@ -0,0 +1,122 @@
+#parse("com/google/devtools/build/docgen/templates/be/header.vm")
+
+<h1>Bazel BUILD Encyclopedia of Functions</h1>
+<h2>Contents</h2>
+
+<h3>Concepts and terminology</h3>
+
+<ul>
+  <li>
+    <a href="common-definitions.html">Common definitions</a>
+    <ul>
+      <li><a href="common-definitions.html#sh-tokenization">Bourne shell tokenization</a></li>
+      <li><a href="common-definitions.html#label-expansion">Label expansion</a></li>
+      <li><a href="common-definitions.html#common-attributes">Common attributes</a></li>
+      <li><a href="common-definitions.html#common-attributes-tests">Common attributes for tests</a></li>
+      <li><a href="common-definitions.html#common-attributes-binaries">Common attributes for binaries</a></li>
+      <li><a href="common-definitions.html#configurable-attributes">Configurable attributes</a></li>
+      <li><a href="common-definitions.html#implicit-outputs">Implicit output targets</a></li>
+    </ul>
+  </li>
+  <li>
+    <a href="make-variables.html">"Make" variables</a>
+    <ul class="be-toc">
+      <li><a href="make-variables.html#make-var-substitution">"Make" variable substitution</a></li>
+      <li><a href="make-variables.html#predefined_variables">Predefined variables</a></li>
+
+    </ul>
+  </li>
+  <li><a href="predefined-python-variables.html">Predefined Python Variables</a></li>
+</ul>
+
+<h3>Functions</h3>
+
+<ul class="be-toc">
+  <li><a href="functions.html#load">load</a></li>
+
+  <li><a href="functions.html#package">package</a></li>
+  <li><a href="functions.html#package_group">package_group</a></li>
+
+  <li><a href="functions.html#licenses">licenses</a></li>
+  <li><a href="functions.html#exports_files">exports_files</a></li>
+  <li><a href="functions.html#glob">glob</a></li>
+  <li><a href="functions.html#select">select</a></li>
+  <li><a href="functions.html#workspace">workspace</a></li>
+</ul>
+
+<h3>Rules</h3>
+
+<h4>Language-specific Rules</h4>
+
+#macro(summaryTable $ruleFamilies)
+  <tbody>
+  #foreach($ruleFamily in $ruleFamilies)
+    <tr>
+      <td class="lang">${ruleFamily.name}</td>
+      <td>
+    #foreach($ruleDoc in $ruleFamily.binaryRules)
+      <a href="${ruleFamily.id}.html#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
+          ${ruleDoc.ruleName}
+        </a>
+        <br />
+    #end
+      </td>
+      <td>
+    #foreach($ruleDoc in $ruleFamily.libraryRules)
+      <a href="${ruleFamily.id}.html#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
+          ${ruleDoc.ruleName}
+        </a>
+        <br />
+    #end
+      </td>
+      <td>
+    #foreach($ruleDoc in $ruleFamily.testRules)
+      <a href="${ruleFamily.id}.html#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
+          ${ruleDoc.ruleName}
+        </a>
+        <br />
+    #end
+      </td>
+      <td>
+    #foreach($ruleDoc in $ruleFamily.otherRules1)
+      <a href="${ruleFamily.id}.html#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
+          ${ruleDoc.ruleName}
+        </a>
+        <br />
+    #end
+      </td>
+      <td>
+    #foreach($ruleDoc in $ruleFamily.otherRules2)
+      <a href="${ruleFamily.id}.html#${ruleDoc.ruleName}"#if($ruleDoc.isDeprecated()) class="deprecated"#end>
+          ${ruleDoc.ruleName}
+        </a>
+        <br />
+    #end
+      </td>
+    </tr>
+  #end
+  </tbody>
+#end
+
+<table class="table table-condensed table-striped" summary="Table of rules sorted by language">
+  <colgroup span="6" width="20%"></colgroup>
+  <thead>
+    <tr>
+      <th>Language</th>
+      <th>Binary rules</th>
+      <th>Library rules</th>
+      <th>Test rules</th>
+      <th>Other rules</th>
+      <th></th>
+    </tr>
+  </thead>
+#summaryTable($langSpecificSummaryFamilies)
+
+</table>
+<h4>Rules that do not apply to a specific programming language</h4>
+
+<table class="table table-condensed table-striped" summary="Table of rules not specific to a programming language">
+  <colgroup span="6" width="20%"></colgroup>
+#summaryTable($otherSummaryFamilies)
+
+</table>
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/predefined-python-variables.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/predefined-python-variables.vm
new file mode 100644
index 0000000..be0b196
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/predefined-python-variables.vm
@@ -0,0 +1,16 @@
+#parse("com/google/devtools/build/docgen/templates/be/header.vm")
+
+<h2 id="predefined-python-variables">Predefined Python Variables</h2>
+
+<div class="toc">
+  <h1>Contents</h1>
+  <ul>
+    <li><a href="#packagename">packagename</a></li>
+  </ul>
+</div>
+<h3 id="packagename">PACKAGE_NAME</h3>
+<p>
+  This is a string variable with the name
+  of the package being evaluated. The value is unaffected by subinclude.
+</p>
+
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be/rules.vm b/src/main/java/com/google/devtools/build/docgen/templates/be/rules.vm
new file mode 100644
index 0000000..4e5f6d3
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be/rules.vm
@@ -0,0 +1,69 @@
+#parse("com/google/devtools/build/docgen/templates/be/header.vm")
+
+<h1>${ruleFamily} Rules</h1>
+
+<div class="toc">
+  <h2>Rules</h2>
+  <ul>
+#foreach ($rule in $ruleDocs)
+    <li>
+      <a href="#${rule.ruleName}">
+        ${rule.ruleName}#if($rule.isDeprecated()) (deprecated)#end
+      </a>
+    </li>
+#end
+  </ul>
+</div>
+
+#foreach ($rule in $ruleDocs)
+  <h2 id="${rule.ruleName}"#if($rule.isDeprecated()) class="deprecated"#end>
+    ${rule.ruleName}
+  </h2>
+
+  <pre class="rule-signature">${rule.attributeSignature}</pre>
+
+  $rule.htmlDocumentation
+
+  <h3 id="${rule.ruleName}_args">Arguments</h3>
+  <table class="table table-condensed table-bordered table-params">
+    <colgroup>
+      <col class="col-param" />
+      <col class="param-description" />
+    </colgroup>
+    <thead>
+      <tr>
+        <th colspan="2">Attributes</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td id="${rule.ruleName}.name"><code>name</code></td>
+        <td>
+          <p><code><a href="../build-ref.html#name">Name</a>; required</code></p>
+          <p>A unique name for this rule.</p>
+          ${rule.nameExtraHtmlDoc}
+        </td>
+      </tr>
+    #foreach ($attribute in $rule.attributes)
+      #if (!$attribute.isCommonType())
+      <tr>
+        <td id="${rule.ruleName.toLowerCase()}.${attribute.attributeName}"#if($attribute.isDeprecated()) class="deprecated"#end>
+          <code>${attribute.attributeName}</code>
+        </td>
+        <td>
+          #if (!$attribute.synopsis.isEmpty())
+          <p><code>${attribute.synopsis}</code></p>
+          #end
+          $attribute.htmlDocumentation
+        </td>
+      </tr>
+      #end
+    #end
+    </tbody>
+  </table>
+  #if ($rule.isPublicByDefault())
+    The default visibility is public: <code>visibility = ["//visibility:public"]</code>.
+  #end
+#end
+
+#parse("com/google/devtools/build/docgen/templates/be/footer.vm")
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm b/src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm
index 250b5ee..5646e10 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/skylark-library.vm
@@ -4,7 +4,7 @@
 
 #if (!$module.methods.isEmpty())
 <div class="toc">
-  <h1>Methods</h1>
+  <h2>Methods</h2>
   <ul>
   #foreach ($method in $module.methods)
     #if ($method.documented())