DiegoAstiazaran updated this revision to Diff 215642.
DiegoAstiazaran marked 3 inline comments as done.
DiegoAstiazaran added a comment.

Add comments.
Fix clang-doc version.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66353/new/

https://reviews.llvm.org/D66353

Files:
  clang-tools-extra/clang-doc/HTMLGenerator.cpp
  clang-tools-extra/clang-doc/Representation.cpp
  clang-tools-extra/clang-doc/Representation.h
  clang-tools-extra/clang-doc/assets/clang-doc-default-stylesheet.css
  clang-tools-extra/clang-doc/assets/index.js
  clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
  clang-tools-extra/docs/clang-doc.rst
  clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp

Index: clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
+++ clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
@@ -10,11 +10,15 @@
 #include "Generators.h"
 #include "Representation.h"
 #include "Serialize.h"
+#include "clang/Basic/Version.h"
 #include "gtest/gtest.h"
 
 namespace clang {
 namespace doc {
 
+static const std::string ClangDocVersion =
+    clang::getClangToolFullVersion("clang-doc");
+
 std::unique_ptr<Generator> getHTMLGenerator() {
   auto G = doc::findGeneratorByName("html");
   if (!G)
@@ -25,7 +29,8 @@
 ClangDocContext
 getClangDocContext(std::vector<std::string> UserStylesheets = {},
                    StringRef RepositoryUrl = "") {
-  ClangDocContext CDCtx{{}, {}, {}, {}, RepositoryUrl, UserStylesheets, {}};
+  ClangDocContext CDCtx{
+      {}, "test-project", {}, {}, {}, RepositoryUrl, UserStylesheets, {}};
   CDCtx.UserStylesheets.insert(
       CDCtx.UserStylesheets.begin(),
       "../share/clang/clang-doc-default-stylesheet.css");
@@ -61,67 +66,76 @@
 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
 <link rel="stylesheet" href="user-provided-stylesheet.css"/>
 <script src="index.js"></script>
-<div id="index" path=""></div>
-<ul>
-  <li>
-    <span>
-      <a href="#Namespaces">Namespaces</a>
-    </span>
-  </li>
-  <li>
-    <span>
-      <a href="#Records">Records</a>
-    </span>
-  </li>
-  <li>
-    <span>
-      <a href="#Functions">Functions</a>
-    </span>
+<header id="project-title">test-project</header>
+<main>
+  <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
+  <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
+    <h1>namespace Namespace</h1>
+    <h2 id="Namespaces">Namespaces</h2>
     <ul>
       <li>
-        <span>
-          <a href="#0000000000000000000000000000000000000000">OneFunction</a>
-        </span>
+        <a href="Namespace/ChildNamespace.html">ChildNamespace</a>
       </li>
     </ul>
-  </li>
-  <li>
-    <span>
-      <a href="#Enums">Enums</a>
-    </span>
+    <h2 id="Records">Records</h2>
     <ul>
       <li>
-        <span>
-          <a href="#0000000000000000000000000000000000000000">OneEnum</a>
-        </span>
+        <a href="Namespace/ChildStruct.html">ChildStruct</a>
       </li>
     </ul>
-  </li>
-</ul>
-<div>
-  <h1>namespace Namespace</h1>
-  <h2 id="Namespaces">Namespaces</h2>
-  <ul>
-    <li>
-      <a href="Namespace/ChildNamespace.html">ChildNamespace</a>
-    </li>
-  </ul>
-  <h2 id="Records">Records</h2>
-  <ul>
-    <li>
-      <a href="Namespace/ChildStruct.html">ChildStruct</a>
-    </li>
-  </ul>
-  <h2 id="Functions">Functions</h2>
-  <div>
-    <h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
-    <p>OneFunction()</p>
+    <h2 id="Functions">Functions</h2>
+    <div>
+      <h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
+      <p>OneFunction()</p>
+    </div>
+    <h2 id="Enums">Enums</h2>
+    <div>
+      <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
+    </div>
   </div>
-  <h2 id="Enums">Enums</h2>
-  <div>
-    <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
+  <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right">
+    <ol>
+      <li>
+        <span>
+          <a href="#Namespaces">Namespaces</a>
+        </span>
+      </li>
+      <li>
+        <span>
+          <a href="#Records">Records</a>
+        </span>
+      </li>
+      <li>
+        <span>
+          <a href="#Functions">Functions</a>
+        </span>
+        <ul>
+          <li>
+            <span>
+              <a href="#0000000000000000000000000000000000000000">OneFunction</a>
+            </span>
+          </li>
+        </ul>
+      </li>
+      <li>
+        <span>
+          <a href="#Enums">Enums</a>
+        </span>
+        <ul>
+          <li>
+            <span>
+              <a href="#0000000000000000000000000000000000000000">OneEnum</a>
+            </span>
+          </li>
+        </ul>
+      </li>
+    </ol>
   </div>
-</div>
+</main>
+<footer>
+  <span class="no-break">)raw" +
+                         ClangDocVersion + R"raw(</span>
+</footer>
 )raw";
 
   EXPECT_EQ(Expected, Actual.str());
@@ -162,80 +176,89 @@
 <title>class r</title>
 <link rel="stylesheet" href="../../../clang-doc-default-stylesheet.css"/>
 <script src="../../../index.js"></script>
-<div id="index" path="X/Y/Z"></div>
-<ul>
-  <li>
-    <span>
-      <a href="#Members">Members</a>
-    </span>
-  </li>
-  <li>
-    <span>
-      <a href="#Records">Records</a>
-    </span>
-  </li>
-  <li>
-    <span>
-      <a href="#Functions">Functions</a>
-    </span>
+<header id="project-title">test-project</header>
+<main>
+  <div id="sidebar-left" path="X/Y/Z" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
+  <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
+    <h1>class r</h1>
+    <p>
+      Defined at line 
+      <a href="http://www.repository.com/dir/test.cpp#10";>10</a>
+       of file 
+      <a href="http://www.repository.com/dir/test.cpp";>test.cpp</a>
+    </p>
+    <p>
+      Inherits from 
+      <a href="../../../path/to/F.html">F</a>
+      , G
+    </p>
+    <h2 id="Members">Members</h2>
     <ul>
       <li>
-        <span>
-          <a href="#0000000000000000000000000000000000000000">OneFunction</a>
-        </span>
+        private 
+        <a href="../int.html">int</a>
+         X
       </li>
     </ul>
-  </li>
-  <li>
-    <span>
-      <a href="#Enums">Enums</a>
-    </span>
+    <h2 id="Records">Records</h2>
     <ul>
       <li>
-        <span>
-          <a href="#0000000000000000000000000000000000000000">OneEnum</a>
-        </span>
+        <a href="r/ChildStruct.html">ChildStruct</a>
       </li>
     </ul>
-  </li>
-</ul>
-<div>
-  <h1>class r</h1>
-  <p>
-    Defined at line 
-    <a href="http://www.repository.com/dir/test.cpp#10";>10</a>
-     of file 
-    <a href="http://www.repository.com/dir/test.cpp";>test.cpp</a>
-  </p>
-  <p>
-    Inherits from 
-    <a href="../../../path/to/F.html">F</a>
-    , G
-  </p>
-  <h2 id="Members">Members</h2>
-  <ul>
-    <li>
-      private 
-      <a href="../int.html">int</a>
-       X
-    </li>
-  </ul>
-  <h2 id="Records">Records</h2>
-  <ul>
-    <li>
-      <a href="r/ChildStruct.html">ChildStruct</a>
-    </li>
-  </ul>
-  <h2 id="Functions">Functions</h2>
-  <div>
-    <h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
-    <p>public OneFunction()</p>
+    <h2 id="Functions">Functions</h2>
+    <div>
+      <h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
+      <p>public OneFunction()</p>
+    </div>
+    <h2 id="Enums">Enums</h2>
+    <div>
+      <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
+    </div>
   </div>
-  <h2 id="Enums">Enums</h2>
-  <div>
-    <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
+  <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right">
+    <ol>
+      <li>
+        <span>
+          <a href="#Members">Members</a>
+        </span>
+      </li>
+      <li>
+        <span>
+          <a href="#Records">Records</a>
+        </span>
+      </li>
+      <li>
+        <span>
+          <a href="#Functions">Functions</a>
+        </span>
+        <ul>
+          <li>
+            <span>
+              <a href="#0000000000000000000000000000000000000000">OneFunction</a>
+            </span>
+          </li>
+        </ul>
+      </li>
+      <li>
+        <span>
+          <a href="#Enums">Enums</a>
+        </span>
+        <ul>
+          <li>
+            <span>
+              <a href="#0000000000000000000000000000000000000000">OneEnum</a>
+            </span>
+          </li>
+        </ul>
+      </li>
+    </ol>
   </div>
-</div>
+</main>
+<footer>
+  <span class="no-break">)raw" +
+                         ClangDocVersion + R"raw(</span>
+</footer>
 )raw";
 
   EXPECT_EQ(Expected, Actual.str());
@@ -270,17 +293,25 @@
 <title></title>
 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
 <script src="index.js"></script>
-<div id="index" path=""></div>
-<div>
-  <h3 id="0000000000000000000000000000000000000000">f</h3>
-  <p>
-    <a href="path/to/float.html">float</a>
-     f(
-    <a href="path/to/int.html">int</a>
-     P)
-  </p>
-  <p>Defined at line 10 of file dir/test.cpp</p>
-</div>
+<header id="project-title">test-project</header>
+<main>
+  <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
+  <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
+    <h3 id="0000000000000000000000000000000000000000">f</h3>
+    <p>
+      <a href="path/to/float.html">float</a>
+       f(
+      <a href="path/to/int.html">int</a>
+       P)
+    </p>
+    <p>Defined at line 10 of file dir/test.cpp</p>
+  </div>
+  <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div>
+</main>
+<footer>
+  <span class="no-break">)raw" +
+                         ClangDocVersion + R"raw(</span>
+</footer>
 )raw";
 
   EXPECT_EQ(Expected, Actual.str());
@@ -309,19 +340,27 @@
 <title></title>
 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
 <script src="index.js"></script>
-<div id="index" path=""></div>
-<div>
-  <h3 id="0000000000000000000000000000000000000000">enum class e</h3>
-  <ul>
-    <li>X</li>
-  </ul>
-  <p>
-    Defined at line 
-    <a href="https://www.repository.com/test.cpp#10";>10</a>
-     of file 
-    <a href="https://www.repository.com/test.cpp";>test.cpp</a>
-  </p>
-</div>
+<header id="project-title">test-project</header>
+<main>
+  <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
+  <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
+    <h3 id="0000000000000000000000000000000000000000">enum class e</h3>
+    <ul>
+      <li>X</li>
+    </ul>
+    <p>
+      Defined at line 
+      <a href="https://www.repository.com/test.cpp#10";>10</a>
+       of file 
+      <a href="https://www.repository.com/test.cpp";>test.cpp</a>
+    </p>
+  </div>
+  <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div>
+</main>
+<footer>
+  <span class="no-break">)raw" +
+                         ClangDocVersion + R"raw(</span>
+</footer>
 )raw";
 
   EXPECT_EQ(Expected, Actual.str());
@@ -386,19 +425,27 @@
 <title></title>
 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
 <script src="index.js"></script>
-<div id="index" path=""></div>
-<div>
-  <h3 id="0000000000000000000000000000000000000000">f</h3>
-  <p>void f(int I, int J)</p>
-  <p>Defined at line 10 of file test.cpp</p>
-  <div>
+<header id="project-title">test-project</header>
+<main>
+  <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
+  <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
+    <h3 id="0000000000000000000000000000000000000000">f</h3>
+    <p>void f(int I, int J)</p>
+    <p>Defined at line 10 of file test.cpp</p>
     <div>
-      <p> Brief description.</p>
-      <p> Extended description that continues onto the next line.</p>
-      <p> Comment with html entities: &amp;, &lt;, &gt;, &quot;, &apos;.</p>
+      <div>
+        <p> Brief description.</p>
+        <p> Extended description that continues onto the next line.</p>
+        <p> Comment with html entities: &amp;, &lt;, &gt;, &quot;, &apos;.</p>
+      </div>
     </div>
   </div>
-</div>
+  <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div>
+</main>
+<footer>
+  <span class="no-break">)raw" +
+                         ClangDocVersion + R"raw(</span>
+</footer>
 )raw";
 
   EXPECT_EQ(Expected, Actual.str());
Index: clang-tools-extra/docs/clang-doc.rst
===================================================================
--- clang-tools-extra/docs/clang-doc.rst
+++ clang-tools-extra/docs/clang-doc.rst
@@ -89,6 +89,7 @@
     --ignore-map-errors         - Continue if files are not mapped correctly.
     --output=<string>           - Directory for outputting generated files.
     -p=<string>                 - Build path
+    --project-name=<string>     - Name of project.
     --public                    - Document only public declarations.
     --repository=<string>       -
                                   URL of repository that hosts code.
Index: clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
===================================================================
--- clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -52,6 +52,10 @@
 static llvm::cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
 static llvm::cl::OptionCategory ClangDocCategory("clang-doc options");
 
+static llvm::cl::opt<std::string>
+    ProjectName("project-name", llvm::cl::desc("Name of project."),
+                llvm::cl::cat(ClangDocCategory));
+
 static llvm::cl::opt<bool> IgnoreMappingFailures(
     "ignore-map-errors",
     llvm::cl::desc("Continue if files are not mapped correctly."),
@@ -205,6 +209,7 @@
 
   clang::doc::ClangDocContext CDCtx = {
       Exec->get()->getExecutionContext(),
+      ProjectName,
       PublicOnly,
       OutDirectory,
       SourceRoot,
Index: clang-tools-extra/clang-doc/assets/index.js
===================================================================
--- clang-tools-extra/clang-doc/assets/index.js
+++ clang-tools-extra/clang-doc/assets/index.js
@@ -39,7 +39,7 @@
   return ANode;
 }
 
-function genHTMLOfIndex(Index, CurrentDirectory) {
+function genHTMLOfIndex(Index, CurrentDirectory, IsOutermostList) {
   // Out will store the HTML elements that Index requires to be generated
   var Out = [];
   if (Index.Name) {
@@ -50,24 +50,26 @@
   }
   if (Index.Children.length == 0)
     return Out;
-  var UlNode = document.createElement("ul");
+  // Only the outermost list should use ol, the others should use ul
+  var ListNodeName = IsOutermostList ? "ol" : "ul";
+  var ListNode = document.createElement(ListNodeName);
   for (Child of Index.Children) {
     var LiNode = document.createElement("li");
-    ChildNodes = genHTMLOfIndex(Child, CurrentDirectory);
+    ChildNodes = genHTMLOfIndex(Child, CurrentDirectory, false);
     for (Node of ChildNodes)
       LiNode.appendChild(Node);
-    UlNode.appendChild(LiNode);
+    ListNode.appendChild(LiNode);
   }
-  Out.push(UlNode);
+  Out.push(ListNode);
   return Out;
 }
 
 function createIndex(Index) {
   // Get the DOM element where the index will be created
-  var IndexDiv = document.getElementById("index");
+  var IndexDiv = document.getElementById("sidebar-left");
   // Get the relative path of this file
   CurrentDirectory = IndexDiv.getAttribute("path");
-  var IndexNodes = genHTMLOfIndex(Index, CurrentDirectory);
+  var IndexNodes = genHTMLOfIndex(Index, CurrentDirectory, true);
   for (Node of IndexNodes)
     IndexDiv.appendChild(Node);
 }
Index: clang-tools-extra/clang-doc/assets/clang-doc-default-stylesheet.css
===================================================================
--- clang-tools-extra/clang-doc/assets/clang-doc-default-stylesheet.css
+++ clang-tools-extra/clang-doc/assets/clang-doc-default-stylesheet.css
@@ -1,205 +1,969 @@
-body,div {
+.dark-primary-color    { background: #1976D2; }
+.default-primary-color { background: #2196F3; }
+.light-primary-color   { background: #BBDEFB; }
+.text-primary-color    { color: #FFFFFF; }
+.accent-color          { background: #00BCD4; }
+.primary-text-color    { color: #212121; }
+.secondary-text-color  { color: #727272; }
+.divider-color         { border-color: #B6B6B6; }
+
+/* for layout */
+html,
+body {
   margin: 0;
   padding: 0;
+  height: 100%;
+  width: 100%;
+  overflow: hidden;
+  box-sizing: border-box;
 }
 
-body[no-overflow] {
-  overflow: hidden;
+*, *:before, *:after {
+  box-sizing: inherit;
 }
 
-li>p:first-child {
-  margin-top: 0;
+body {
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
 }
 
-li>p:last-child {
-  margin-bottom: 0;
+header {
+  flex: 0 0 50px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding-left: 30px;
 }
 
-html {
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
+header ol {
+  list-style: none;
+  margin: 0;
+  padding: 0;
 }
 
-*,*::before,*::after {
-  -webkit-box-sizing: inherit;
-  box-sizing: inherit;
+header ol li {
+  display: inline;
 }
 
-body,html {
-  color: #202124;
-  font: 400 16px/24px Roboto,sans-serif;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-font-smoothing: antialiased;
-  height: 100%;
-  margin: 36px;
-  -webkit-text-size-adjust: 100%;
-  -moz-text-size-adjust: 100%;
-  -ms-text-size-adjust: 100%;
-  text-size-adjust: 100%;
+header form {
+  display: flex;
+  flex: 1;
+  justify-content: flex-end;
+  padding-right: 30px;
 }
 
-body[devsite-framebox] {
-  overflow: hidden;
+header#header-search-sidebar {
+  height: 50px;
+  margin-bottom: 25px;
+}
+
+footer {
+  flex: 0 0 16px;
+  text-align: center;
+  padding: 16px 20px;
+}
+
+main {
+  flex: 1;
+  display: flex;
+  flex-direction: row;
   padding: 20px;
+  min-height: 0;
 }
 
-body[sitemask--active] {
-  overflow: hidden;
+.sidebar-offcanvas-left {
+  flex: 0 1 230px;
+  overflow-y: scroll;
+  padding: 20px 0 15px 30px;
+  margin: 5px 20px 0 0;
+  visibility: visible; /* shown by Javascript after scroll position restore */
 }
 
-p {
-  margin: 16px 0;
+::-webkit-scrollbar-button{ display: none; height: 13px; border-radius: 0px; background-color: #AAA; }
+::-webkit-scrollbar-button:hover{ background-color: #AAA; }
+::-webkit-scrollbar-thumb{ background-color: #CCC; }
+::-webkit-scrollbar-thumb:hover{ background-color: #CCC; }
+::-webkit-scrollbar{ width: 4px; }
+/* ::-webkit-overflow-scrolling: touch; */
+
+.main-content::-webkit-scrollbar{ width: 8px; }
+
+.main-content {
+  flex: 1;
+  overflow-y: scroll;
+  padding: 10px 20px 0 20px;
+  visibility: visible; /* shown by Javascript after scroll position restore */
+}
+
+.sidebar-offcanvas-right {
+  flex: 0 1 12em;
+  overflow-y: scroll;
+  padding: 20px 15px 15px 15px;
+  margin-top: 5px;
+  margin-right: 20px;
+  visibility: visible; /* shown by Javascript after scroll position restore */
+}
+/* end for layout */
+
+body {
+  -webkit-text-size-adjust: 100%;
+  overflow-x: hidden;
+  font-family: Roboto, sans-serif;
+  font-size: 16px;
+  line-height: 1.42857143;
+  color: #111111;
+  background-color: #fff;
+}
+
+/* some of this is to reset bootstrap */
+nav.navbar {
+  background-color: inherit;
+  min-height: 50px;
+  border: 0;
+}
+
+@media (max-width: 768px) {
+  .hidden-xs {
+    display: none !important;
+  }
+}
+
+@media (min-width: 769px) {
+  .hidden-l {
+    display: none !important;
+  }
+}
+
+nav.navbar .row {
+  padding-top: 8px;
+}
+
+nav .container {
+  white-space: nowrap;
+}
+
+header {
+  background-color: #eeeeee;
+  box-shadow: 0 3px 5px rgba(0,0,0,0.1);
+}
+
+header#project-title {
+  background-color: #fff;
+  font-size: 200%;
+  padding-top: 0.25em;
+  padding-bottom: 0.25em;
+  /* padding: 0em; */
+}
+
+header.header-fixed nav.navbar-fixed-top {
+  box-shadow: 0 3px 5px rgba(0,0,0,0.1);
+}
+
+header.container-fluid {
   padding: 0;
 }
 
-:link,:visited {
-  color: #039be5;
-  outline: 0;
+header .masthead {
+  padding-top: 64px;
+}
+
+header .contents {
+  padding: 0;
+}
+
+@media screen and (max-width:768px) {
+  header .contents {
+    padding-left: 15px;
+    padding-right: 15px;
+  }
+}
+
+a {
   text-decoration: none;
 }
 
-ul {
+.body {
+  margin-top: 90px;
+}
+
+section {
+  margin-bottom: 36px;
+}
+
+dl {
   margin: 0;
-  padding-left: 40px;
 }
 
-ul {
-  list-style: disc outside;
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  font-family: Roboto, sans-serif;
+  font-weight: 400;
+  margin-top: 1.5em;
+  color: #111111;
 }
 
-li,li p {
-  margin: 12px 0;
-  padding: 0;
+h1.title {
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+h1 {
+  font-size: 37px;
+  margin-top: 0;
+  margin-bottom: 0.67em;
 }
 
-*[visually-hidden] {
-  opacity: 0 !important;
-  pointer-events: none !important;
-  visibility: hidden !important;
+h2 {
+  font-size: 28px;
 }
 
-*[hidden] {
-  display: none !important;
+h5 {
+  font-size: 16px;
 }
 
-[render-hidden] {
-  display: inline !important;
-  position: absolute !important;
-  visibility: hidden !important;
+.subtitle {
+  font-size: 17px;
+  min-height: 1.4em;
 }
 
-*[no-scroll] {
-  overflow: hidden;
+.title-description .subtitle {
+  white-space: nowrap;
+  overflow-x: hidden;
+  text-overflow: ellipsis;
+}
+
+p {
+  margin-bottom: 1em;
+  margin-top: 0;
+}
+
+a {
+  color: #0175C2;
+}
+
+a:hover {
+  color: #13B9FD;
+}
+
+pre.prettyprint {
+  font-family: 'Source Code Pro', Menlo, monospace;
+  color: black;
+  border-radius: 0;
+  font-size: 15px;
+  word-wrap: normal;
+  line-height: 1.4;
+  border: 0;
+  margin: 16px 0 16px 0;
+  padding: 8px;
+}
+
+pre code {
+  white-space: pre;
+  word-wrap: initial;
+  font-size: 100%
+}
+
+.fixed {
+  white-space: pre;
 }
 
-@supports (display: flex) {
-  body[ready] .devsite-wrapper {
-    display: -webkit-box;
-    display: -ms-flexbox;
-    display: flex;
-    -webkit-box-orient: vertical;
-    -webkit-box-direction: normal;
-    -ms-flex-direction: column;
-    flex-direction: column;
+pre {
+  border: 1px solid #ddd;
+  background-color: #eee;
+  font-size: 14px;
+}
+
+code {
+  font-family: 'Source Code Pro', Menlo, monospace;
+  /* overriding bootstrap */
+  color: inherit;
+  padding: 0.2em 0.4em;
+  font-size: 85%;
+  background-color: rgba(27,31,35,0.05);
+  border-radius: 3px;
+}
+
+@media(max-width: 768px) {
+  nav .container {
+    width: 100%
+  }
+
+  h1 {
+    font-size: 24px;
+  }
+
+  pre {
+    margin: 16px 0;
   }
 }
 
-@media screen and (max-width: 840px) {
-  body[devsite-book-nav--open] {
-    overflow: hidden;
+@media (min-width: 768px) {
+  ul.subnav li {
+    font-size: 17px;
   }
 }
 
-h1,h2,h3,h4,h5,h6 {
-  overflow: hidden;
-  padding: 0;
+header h1 {
+  font-weight: 400;
+  margin-bottom: 16px;
+}
+
+header a,
+header p,
+header li {
+  color: #111111;
+}
+
+header a:hover {
+  color: #0175C2;
+}
+
+header h1 .kind {
+  color: #555;
+}
+
+dt {
+  font-weight: normal;
+}
+
+dd {
+  color: #212121;
+  margin-bottom: 1em;
+  margin-left: 0;
+}
+
+dd.callable, dd.constant, dd.property {
+  margin-bottom: 24px;
+}
+
+dd p {
+  overflow-x: hidden;
   text-overflow: ellipsis;
+  margin-bottom: 0;
 }
 
-h1 {
-  color: #80868b;
-  font: 300 34px/40px Roboto,sans-serif;
-  letter-spacing: -0.01em;
-  margin: 40px 0 20px;
+/* indents wrapped lines */
+section.summary dt {
+  margin-left: 24px;
+  text-indent: -24px;
 }
 
-[layout=docs] h2 {
-  border-bottom: 1px solid #e8eaed;
-  padding-bottom: 3px;
+.dl-horizontal dd {
+  margin-left: initial;
 }
 
-h2 {
-  font: 300 24px/32px Roboto,sans-serif;
-  letter-spacing: -0.01em;
-  margin: 40px 0 20px;
+dl.dl-horizontal dt {
+  font-style: normal;
+  text-align: left;
+  color: #727272;
+  margin-right: 20px;
+  width: initial;
 }
 
-h3 {
-  font: 400 20px/32px Roboto,sans-serif;
-  margin: 32px 0 16px;
+dt .name {
+  font-weight: 500;
 }
 
-h4,h5,h6 {
-  margin: 32px 0 16px;
+dl dt.callable .name {
+  float: none;
+  width: auto;
 }
 
-h4 {
-  font: 500 16px/24px Roboto,sans-serif;
+.parameter {
+  white-space: nowrap;
 }
 
-h5 {
-  font: 700 14px/24px Roboto,sans-serif;
+.type-parameter {
+  white-space: nowrap;
 }
 
-h6 {
-  font: 500 14px/24px Roboto,sans-serif;
+.multi-line-signature .type-parameter .parameter {
+  margin-left: 0px;
+  display: unset;
 }
 
-h1+h1,h1+h2,h1+h3,h1+h4,h1+h5,h1+h6,h2+h1,h2+h2,h2+h3,h2+h4,h2+h5,h2+h6,h3+h1,h3+h2,h3+h3,h3+h4,h3+h5,h3+h6,h4+h1,h4+h2,h4+h3,h4+h4,h4+h5,h4+h6,h5+h1,h5+h2,h5+h3,h5+h4,h5+h5,h5+h6,h6+h1,h6+h2,h6+h3,h6+h4,h6+h5,h6+h6 {
-  margin-top: 0;
+.signature {
+  color: #727272;
 }
 
-@media screen and (max-width: 600px) {
-  h1 {
-    font: 300 24px/32px Roboto,sans-serif;
+.signature a {
+  /* 50% mix of default-primary-color and primary-text-color. */
+  color: #4674a2;
+}
+
+.optional {
+  font-style: italic;
+}
+
+.undocumented {
+  font-style: italic;
+}
+
+.is-const {
+  font-style: italic;
+}
+
+.deprecated {
+  text-decoration: line-through;
+}
+
+.category.linked {
+  font-weight: bold;
+  opacity: 1;
+}
+
+/* Colors for category based on categoryOrder in dartdoc_options.config. */
+.category.cp-0 {
+  background-color: #54b7c4
+}
+
+.category.cp-1 {
+  background-color: #54c47f
+}
+
+.category.cp-2 {
+  background-color: #c4c254
+}
+
+.category.cp-3 {
+  background-color: #c49f54
+}
+
+.category.cp-4 {
+  background-color: #c45465
+}
+
+.category.cp-5 {
+  background-color: #c454c4
+}
+
+.category a {
+  color: white;
+}
+
+.category {
+  padding: 2px 4px;
+  font-size: 12px;
+  border-radius: 4px;
+  background-color: #999;
+  text-transform: uppercase;
+  color: white;
+  opacity: .5;
+}
+
+h1 .category {
+  vertical-align: middle;
+}
+
+.source-link {
+  padding: 18px 4px;
+  vertical-align: middle;
+}
+
+.source-link .material-icons {
+  font-size: 18px;
+}
+
+@media (max-width: 768px) {
+  .source-link {
+    padding: 7px 2px;
+    font-size: 10px;
   }
 }
 
-[scrollbars]::-webkit-scrollbar {
-  height: 8px;
-  width: 8px;
+#external-links {
+  float: right;
+}
+
+.btn-group {
+  position: relative;
+  display: inline-flex;
+  vertical-align: middle;
 }
 
-[scrollbars]::-webkit-scrollbar-thumb {
-  background: rgba(128,134,139,.26);
-  border-radius: 8px;
+p.firstline {
+  font-weight: bold;
 }
 
-[no-horizontal-scrollbars]::-webkit-scrollbar {
-  height: 0;
-  width: 0;
+footer {
+  color: #fff;
+  background-color: #111111;
+  width: 100%;
 }
 
-[scrollbars]::-webkit-scrollbar-corner {
-  background: 0;
+footer p {
+  margin: 0;
 }
 
-[background] h2 {
+footer .no-break {
+  white-space: nowrap;
+}
+
+footer .container,
+footer .container-fluid {
+  padding-left: 0;
+  padding-right: 0;
+}
+
+footer a, footer a:hover {
   color: #fff;
 }
 
-@media print {
-  body,  html,  :link,  :visited,  h1,  h2,  h3,  h4,  h5,  h6 {
-    color: #000 !important;
-    padding-left: 0 !important;
-    padding-right: 0 !important;
+.markdown.desc {
+  max-width: 700px;
+}
+
+.markdown h1 {
+  font-size: 24px;
+  margin-bottom: 8px;
+}
+
+.markdown h2 {
+  font-size: 20px;
+  margin-top: 24px;
+  margin-bottom: 8px;
+}
+
+.markdown h3 {
+  font-size: 18px;
+  margin-bottom: 8px;
+}
+
+.markdown h4 {
+  font-size: 16px;
+  margin-bottom: 0;
+}
+
+.markdown li p {
+  margin: 0;
+}
+
+.gt-separated {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+}
+
+.gt-separated li {
+  display: inline-block;
+}
+
+.gt-separated li:before {
+  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path fill='%23DDDDDD' d='M6.7,4L5.7,4.9L8.8,8l-3.1,3.1L6.7,12l4-4L6.7,4z'/></svg>");
+  background-position: center;
+  content: "\00a0";
+  margin: 0 6px 0 4px;
+  padding: 0 3px 0 0;
+}
+
+.gt-separated.dark li:before {
+  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path fill='%23727272' d='M6.7,4L5.7,4.9L8.8,8l-3.1,3.1L6.7,12l4-4L6.7,4z'/></svg>");
+}
+
+.gt-separated li:first-child:before {
+  background-image: none;
+  content: "";
+  margin: 0;
+}
+
+/* The slug line under a declaration for things like "const", "read-only", etc. */
+.features {
+  font-style: italic;
+  color: #727272;
+}
+
+.multi-line-signature {
+  font-size: 17px;
+  color: #727272;
+}
+
+.multi-line-signature .parameter {
+  margin-left: 24px;
+  display: block;
+}
+
+.breadcrumbs {
+  padding: 0;
+  margin: 8px 0 8px 0;
+  white-space: nowrap;
+  line-height: 1;
+}
+
+@media screen and (min-width: 768px) {
+  nav ol.breadcrumbs {
+    float: left;
   }
+}
 
-  :link,  :visited {
-    text-decoration: underline;
+@media screen and (max-width: 768px) {
+  .breadcrumbs {
+    margin: 0 0 24px 0;
+    overflow-x: hidden;
   }
 }
 
-@page {
-  margin: .75in;
+.self-crumb {
+  color: #555;
+}
+
+.self-name {
+  color: #555;
+  display: none;
+}
+
+.annotation-list {
+  list-style: none;
+  padding: 0;
+  display: inline;
+}
+
+.comma-separated {
+  list-style: none;
+  padding: 0;
+  display: inline;
+}
+
+.comma-separated li {
+  display: inline;
+}
+
+.comma-separated li:after {
+  content: ", ";
+}
+
+.comma-separated li:last-child:after {
+  content: "";
+}
+
+.end-with-period li:last-child:after {
+  content: ".";
 }
+
+.container > section:first-child {
+  border: 0;
+}
+
+.constructor-modifier {
+  font-style: italic;
+}
+
+section.multi-line-signature div.parameters {
+  margin-left: 24px;
+}
+
+/* subnav styles */
+
+ul.subnav {
+  overflow: auto;
+  white-space: nowrap;
+  padding-left: 0;
+  min-height: 25px;
+}
+
+ul.subnav::-webkit-scrollbar {
+  display: none;
+}
+
+ul.subnav li {
+  display: inline-block;
+  text-transform: uppercase;
+}
+
+ul.subnav li a {
+  color: #111;
+}
+
+ul.subnav li {
+  margin-right: 24px;
+}
+
+ul.subnav li:last-of-type {
+  margin-right: 0;
+}
+
+@media(max-width: 768px) {
+  ul.subnav li {
+    margin-right: 16px;
+  }
+}
+
+/* sidebar styles */
+
+.sidebar ol {
+  list-style: none;
+  line-height: 22px;
+  margin-top: 0;
+  margin-bottom: 0;
+  padding: 0 0 15px 0;
+}
+
+.sidebar h5 a,
+.sidebar h5 a:hover {
+  color: #727272;
+}
+
+.sidebar h5,
+.sidebar ol li {
+  text-overflow: ellipsis;
+  overflow: hidden;
+  padding: 3px 0;
+}
+
+.sidebar h5 {
+  color: #727272;
+  font-size: 18px;
+  margin: 0 0 25px 0;
+  padding-top: 0;
+}
+
+.sidebar ol li.section-title {
+  font-size: 18px;
+  font-weight: normal;
+  text-transform: uppercase;
+  padding-top: 25px;
+}
+
+.sidebar ol li.section-subtitle a {
+  color: inherit;
+}
+
+.sidebar ol li.section-subtitle {
+  font-weight: 400;
+  text-transform: uppercase;
+}
+
+.sidebar ol li.section-subitem {
+  margin-left: 12px;
+}
+
+.sidebar ol li:first-child {
+  padding-top: 0;
+  margin-top: 0;
+}
+
+button {
+  padding: 0;
+}
+
+#sidenav-left-toggle {
+  display: none;
+  vertical-align: text-bottom;
+  padding: 0;
+}
+
+/* left-nav disappears, and can transition in from the left */
+@media screen and (max-width:768px) {
+  #sidenav-left-toggle {
+    display: inline;
+    background: no-repeat url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path fill='%23111' d='M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z'/></svg>");
+    background-position: center;
+    width: 24px;
+    height: 24px;
+    border: none;
+    margin-right: 24px;
+  }
+
+  #overlay-under-drawer.active {
+    opacity: 0.4;
+    height: 100%;
+    z-index: 1999;
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: black;
+    display: block;
+  }
+
+  .sidebar-offcanvas-left {
+    left: -100%;
+    position: fixed;
+    -webkit-transition:all .25s ease-out;
+    -o-transition:all .25s ease-out;
+    transition:all .25s ease-out;
+    z-index: 2000;
+    top: 0;
+    width: 280px; /* works all the way down to an iphone 4 */
+    height: 90%;
+    background-color: white;
+    overflow-y: scroll; /* TODO: how to hide scroll bars? */
+    padding: 10px;
+    margin: 10px 10px;
+    box-shadow: 5px 5px 5px 5px #444444;
+    visibility: hidden; /* shown by Javascript after scroll position restore */
+  }
+
+  ol#sidebar-nav {
+    font-size: 18px;
+    white-space: pre-line;
+  }
+
+  .sidebar-offcanvas-left.active {
+    left: 0; /* this animates our drawer into the page */
+  }
+
+  .self-name {
+    display: inline-block;
+  }
+}
+
+.sidebar-offcanvas-left h5 {
+  margin-bottom: 10px;
+}
+
+.sidebar-offcanvas-left h5:last-of-type {
+  border: 0;
+  margin-bottom: 25px;
+}
+
+/* the right nav disappears out of view when the window shrinks */
+@media screen and (max-width: 992px) {
+  .sidebar-offcanvas-right {
+     display: none;
+   }
+}
+
+#overlay-under-drawer {
+  display: none;
+}
+
+/* find-as-you-type search box */
+
+/* override bootstrap defaults */
+.form-control {
+  border-radius: 0;
+  border: 0;
+}
+
+@media screen and (max-width: 768px) {
+  form.search {
+    display: none;
+  }
+}
+
+.typeahead,
+.tt-query,
+.tt-hint {
+  width: 200px;
+  height: 20px;
+  padding: 2px 7px 1px 7px;
+  line-height: 20px;
+  outline: none;
+}
+
+.typeahead {
+  background-color: #fff;
+  border-radius: 2px;
+}
+
+.tt-query {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.tt-hint {
+  color: #999
+}
+
+.navbar-right .tt-menu {
+  right:0;
+  left: inherit !important;
+  width: 422px;
+  max-height: 250px;
+  overflow-y: scroll;
+}
+
+.tt-menu {
+  font-size: 14px;
+  margin: 0;
+  padding: 8px 0;
+  background-color: #fff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+     -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+          box-shadow: 0 5px 10px rgba(0,0,0,.2);
+}
+
+.tt-suggestion {
+  padding: 3px 20px;
+  color: #212121;
+}
+
+.tt-suggestion:hover {
+  cursor: pointer;
+  color: #fff;
+  background-color: #0097cf;
+}
+
+.tt-suggestion:hover .search-from-lib {
+  color: #ddd;
+}
+
+.tt-suggestion.tt-cursor {
+  color: #fff;
+  background-color: #0097cf;
+}
+
+.tt-suggestion.tt-cursor .search-from-lib {
+  color: #ddd;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+.search-from-lib {
+  font-style: italic;
+  color: gray;
+}
+
+#search-box {
+  background-color: #ffffff;
+}
+
+.search-body {
+  border: 1px solid #7f7f7f;
+  max-width: 400px;
+  box-shadow: 3px 3px 5px rgba(0,0,0,0.1);
+}
+
+section#setter {
+  border-top: 1px solid #ddd;
+  padding-top: 36px;
+}
+
+li.inherited a {
+  opacity: 0.65;
+  font-style: italic;
+}
+
+#instance-methods dt.inherited .name,
+#instance-properties dt.inherited .name,
+#operators dt.inherited .name {
+  font-weight: 300;
+  font-style: italic;
+}
+
+#instance-methods dt.inherited .signature,
+#instance-properties dt.inherited .signature,
+#operators dt.inherited .signature {
+  font-weight: 300;
+}
+
+@media print {
+  .subnav, .sidebar {
+    display:none;
+  }
+
+  a[href]:after {
+   content:"" !important;
+  }
+}
\ No newline at end of file
Index: clang-tools-extra/clang-doc/Representation.h
===================================================================
--- clang-tools-extra/clang-doc/Representation.h
+++ clang-tools-extra/clang-doc/Representation.h
@@ -413,12 +413,13 @@
 
 struct ClangDocContext {
   ClangDocContext() = default;
-  ClangDocContext(tooling::ExecutionContext *ECtx, bool PublicOnly,
-                  StringRef OutDirectory, StringRef SourceRoot,
+  ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
+                  bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
                   StringRef RepositoryUrl,
                   std::vector<std::string> UserStylesheets,
                   std::vector<std::string> JsScripts);
   tooling::ExecutionContext *ECtx;
+  std::string ProjectName; // Name of project clang-doc is documenting.
   bool PublicOnly; // Indicates if only public declarations are documented.
   std::string OutDirectory; // Directory for outputting generated files.
   std::string SourceRoot;   // Directory where processed files are stored. Links
Index: clang-tools-extra/clang-doc/Representation.cpp
===================================================================
--- clang-tools-extra/clang-doc/Representation.cpp
+++ clang-tools-extra/clang-doc/Representation.cpp
@@ -274,12 +274,14 @@
 }
 
 ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
-                                 bool PublicOnly, StringRef OutDirectory,
-                                 StringRef SourceRoot, StringRef RepositoryUrl,
+                                 StringRef ProjectName, bool PublicOnly,
+                                 StringRef OutDirectory, StringRef SourceRoot,
+                                 StringRef RepositoryUrl,
                                  std::vector<std::string> UserStylesheets,
                                  std::vector<std::string> JsScripts)
-    : ECtx(ECtx), PublicOnly(PublicOnly), OutDirectory(OutDirectory),
-      UserStylesheets(UserStylesheets), JsScripts(JsScripts) {
+    : ECtx(ECtx), ProjectName(ProjectName), PublicOnly(PublicOnly),
+      OutDirectory(OutDirectory), UserStylesheets(UserStylesheets),
+      JsScripts(JsScripts) {
   llvm::SmallString<128> SourceRootDir(SourceRoot);
   if (SourceRoot.empty())
     // If no SourceRoot was provided the current path is used as the default
Index: clang-tools-extra/clang-doc/HTMLGenerator.cpp
===================================================================
--- clang-tools-extra/clang-doc/HTMLGenerator.cpp
+++ clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -8,6 +8,7 @@
 
 #include "Generators.h"
 #include "Representation.h"
+#include "clang/Basic/Version.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/FileSystem.h"
@@ -29,12 +30,16 @@
   enum TagType {
     TAG_A,
     TAG_DIV,
+    TAG_FOOTER,
     TAG_H1,
     TAG_H2,
     TAG_H3,
+    TAG_HEADER,
     TAG_LI,
     TAG_LINK,
+    TAG_MAIN,
     TAG_META,
+    TAG_OL,
     TAG_P,
     TAG_SCRIPT,
     TAG_SPAN,
@@ -84,7 +89,7 @@
 
   HTMLTag Tag; // Name of HTML Tag (p, div, h1)
   std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes
-  llvm::StringMap<llvm::SmallString<16>>
+  std::vector<std::pair<llvm::SmallString<16>, llvm::SmallString<16>>>
       Attributes; // List of key-value attributes for tag
 
   void Render(llvm::raw_ostream &OS, int IndentationLevel) override;
@@ -112,10 +117,14 @@
     return true;
   case HTMLTag::TAG_A:
   case HTMLTag::TAG_DIV:
+  case HTMLTag::TAG_FOOTER:
   case HTMLTag::TAG_H1:
   case HTMLTag::TAG_H2:
   case HTMLTag::TAG_H3:
+  case HTMLTag::TAG_HEADER:
   case HTMLTag::TAG_LI:
+  case HTMLTag::TAG_MAIN:
+  case HTMLTag::TAG_OL:
   case HTMLTag::TAG_P:
   case HTMLTag::TAG_SCRIPT:
   case HTMLTag::TAG_SPAN:
@@ -132,18 +141,26 @@
     return llvm::SmallString<16>("a");
   case HTMLTag::TAG_DIV:
     return llvm::SmallString<16>("div");
+  case HTMLTag::TAG_FOOTER:
+    return llvm::SmallString<16>("footer");
   case HTMLTag::TAG_H1:
     return llvm::SmallString<16>("h1");
   case HTMLTag::TAG_H2:
     return llvm::SmallString<16>("h2");
   case HTMLTag::TAG_H3:
     return llvm::SmallString<16>("h3");
+  case HTMLTag::TAG_HEADER:
+    return llvm::SmallString<16>("header");
   case HTMLTag::TAG_LI:
     return llvm::SmallString<16>("li");
   case HTMLTag::TAG_LINK:
     return llvm::SmallString<16>("link");
+  case HTMLTag::TAG_MAIN:
+    return llvm::SmallString<16>("main");
   case HTMLTag::TAG_META:
     return llvm::SmallString<16>("meta");
+  case HTMLTag::TAG_OL:
+    return llvm::SmallString<16>("ol");
   case HTMLTag::TAG_P:
     return llvm::SmallString<16>("p");
   case HTMLTag::TAG_SCRIPT:
@@ -174,7 +191,7 @@
   OS.indent(IndentationLevel * 2);
   OS << "<" << Tag.ToString();
   for (const auto &A : Attributes)
-    OS << " " << A.getKey() << "=\"" << A.getValue() << "\"";
+    OS << " " << A.first << "=\"" << A.second << "\"";
   if (Tag.IsSelfClosing()) {
     OS << "/>";
     return;
@@ -255,13 +272,13 @@
   std::vector<std::unique_ptr<TagNode>> Out;
   for (const auto &FilePath : CDCtx.UserStylesheets) {
     auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_LINK);
-    LinkNode->Attributes.try_emplace("rel", "stylesheet");
+    LinkNode->Attributes.emplace_back("rel", "stylesheet");
     SmallString<128> StylesheetPath = computeRelativePath("", InfoPath);
     llvm::sys::path::append(StylesheetPath,
                             llvm::sys::path::filename(FilePath));
     // Paths in HTML must be in posix-style
     llvm::sys::path::native(StylesheetPath, llvm::sys::path::Style::posix);
-    LinkNode->Attributes.try_emplace("href", StylesheetPath);
+    LinkNode->Attributes.emplace_back("href", StylesheetPath);
     Out.emplace_back(std::move(LinkNode));
   }
   return Out;
@@ -276,7 +293,7 @@
     llvm::sys::path::append(ScriptPath, llvm::sys::path::filename(FilePath));
     // Paths in HTML must be in posix-style
     llvm::sys::path::native(ScriptPath, llvm::sys::path::Style::posix);
-    ScriptNode->Attributes.try_emplace("src", ScriptPath);
+    ScriptNode->Attributes.emplace_back("src", ScriptPath);
     Out.emplace_back(std::move(ScriptNode));
   }
   return Out;
@@ -284,7 +301,7 @@
 
 static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {
   auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_A, Text);
-  LinkNode->Attributes.try_emplace("href", Link.str());
+  LinkNode->Attributes.emplace_back("href", Link.str());
   return LinkNode;
 }
 
@@ -333,7 +350,7 @@
 
   std::vector<std::unique_ptr<TagNode>> Out;
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Enums"));
-  Out.back()->Attributes.try_emplace("id", "Enums");
+  Out.back()->Attributes.emplace_back("id", "Enums");
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
   auto &DivBody = Out.back();
   for (const auto &E : Enums) {
@@ -362,7 +379,7 @@
 
   std::vector<std::unique_ptr<TagNode>> Out;
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions"));
-  Out.back()->Attributes.try_emplace("id", "Functions");
+  Out.back()->Attributes.emplace_back("id", "Functions");
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
   auto &DivBody = Out.back();
   for (const auto &F : Functions) {
@@ -381,7 +398,7 @@
 
   std::vector<std::unique_ptr<TagNode>> Out;
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Members"));
-  Out.back()->Attributes.try_emplace("id", "Members");
+  Out.back()->Attributes.emplace_back("id", "Members");
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
   auto &ULBody = Out.back();
   for (const auto &M : Members) {
@@ -405,7 +422,7 @@
 
   std::vector<std::unique_ptr<TagNode>> Out;
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
-  Out.back()->Attributes.try_emplace("id", Title);
+  Out.back()->Attributes.emplace_back("id", Title);
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
   auto &ULBody = Out.back();
   for (const auto &R : References) {
@@ -431,23 +448,29 @@
       std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber));
   // The links to a specific line in the source code use the github /
   // googlesource notation so it won't work for all hosting pages.
-  LocNumberNode->Attributes.try_emplace(
+  LocNumberNode->Attributes.emplace_back(
       "href", (FileURL + "#" + std::to_string(L.LineNumber)).str());
   Node->Children.emplace_back(std::move(LocNumberNode));
   Node->Children.emplace_back(std::make_unique<TextNode>(" of file "));
   auto LocFileNode = std::make_unique<TagNode>(
       HTMLTag::TAG_A, llvm::sys::path::filename(FileURL));
-  LocFileNode->Attributes.try_emplace("href", FileURL);
+  LocFileNode->Attributes.emplace_back("href", FileURL);
   Node->Children.emplace_back(std::move(LocFileNode));
   return Node;
 }
 
 static std::vector<std::unique_ptr<TagNode>>
-genCommonFileNodes(StringRef Title, StringRef InfoPath,
-                   const ClangDocContext &CDCtx) {
+genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList);
+
+// Generates a list of child nodes for the HTML head tag
+// It contains a meta node, link nodes to import CSS files, and script nodes to
+// import JS files
+static std::vector<std::unique_ptr<TagNode>>
+genFileHeadNodes(StringRef Title, StringRef InfoPath,
+                 const ClangDocContext &CDCtx) {
   std::vector<std::unique_ptr<TagNode>> Out;
   auto MetaNode = std::make_unique<TagNode>(HTMLTag::TAG_META);
-  MetaNode->Attributes.try_emplace("charset", "utf-8");
+  MetaNode->Attributes.emplace_back("charset", "utf-8");
   Out.emplace_back(std::move(MetaNode));
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_TITLE, Title));
   std::vector<std::unique_ptr<TagNode>> StylesheetsNodes =
@@ -456,14 +479,87 @@
   std::vector<std::unique_ptr<TagNode>> JsNodes =
       genJsScriptsHTML(InfoPath, CDCtx);
   AppendVector(std::move(JsNodes), Out);
-  // An empty <div> is generated but the index will be then rendered here
-  auto IndexNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
-  IndexNode->Attributes.try_emplace("id", "index");
-  IndexNode->Attributes.try_emplace("path", InfoPath);
-  Out.emplace_back(std::move(IndexNode));
   return Out;
 }
 
+// Generates a header HTML node that can be used for any file
+// It contains the project name
+static std::unique_ptr<TagNode> genFileHeaderNode(StringRef ProjectName) {
+  auto HeaderNode = std::make_unique<TagNode>(HTMLTag::TAG_HEADER, ProjectName);
+  HeaderNode->Attributes.emplace_back("id", "project-title");
+  return HeaderNode;
+}
+
+// Generates a main HTML node that has all the main content of an info file
+// It contains both indexes and the info's documented information
+// This function should only be used for the info files (not for the file that
+// only has the general index)
+static std::unique_ptr<TagNode> genInfoFileMainNode(
+    StringRef InfoPath,
+    std::vector<std::unique_ptr<TagNode>> &MainContentInnerNodes,
+    const Index &InfoIndex) {
+  auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
+
+  auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
+  LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
+  LeftSidebarNode->Attributes.emplace_back("path", InfoPath);
+  LeftSidebarNode->Attributes.emplace_back(
+      "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
+
+  auto MainContentNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
+  MainContentNode->Attributes.emplace_back("id", "main-content");
+  MainContentNode->Attributes.emplace_back(
+      "class", "col-xs-12 col-sm-9 col-md-8 main-content");
+  AppendVector(std::move(MainContentInnerNodes), MainContentNode->Children);
+
+  auto RightSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
+  RightSidebarNode->Attributes.emplace_back("id", "sidebar-right");
+  RightSidebarNode->Attributes.emplace_back(
+      "class", "col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right");
+  std::vector<std::unique_ptr<TagNode>> InfoIndexHTML =
+      genHTML(InfoIndex, InfoPath, true);
+  AppendVector(std::move(InfoIndexHTML), RightSidebarNode->Children);
+
+  MainNode->Children.emplace_back(std::move(LeftSidebarNode));
+  MainNode->Children.emplace_back(std::move(MainContentNode));
+  MainNode->Children.emplace_back(std::move(RightSidebarNode));
+
+  return MainNode;
+}
+
+// Generates a footer HTML node that can be used for any file
+// It contains clang-doc's version
+static std::unique_ptr<TagNode> genFileFooterNode() {
+  auto FooterNode = std::make_unique<TagNode>(HTMLTag::TAG_FOOTER);
+  auto SpanNode = std::make_unique<TagNode>(
+      HTMLTag::TAG_SPAN, clang::getClangToolFullVersion("clang-doc"));
+  SpanNode->Attributes.emplace_back("class", "no-break");
+  FooterNode->Children.emplace_back(std::move(SpanNode));
+  return FooterNode;
+}
+
+// Generates a complete HTMLFile for an Info
+static HTMLFile
+genInfoFile(StringRef Title, StringRef InfoPath,
+            std::vector<std::unique_ptr<TagNode>> &MainContentNodes,
+            const Index &InfoIndex, const ClangDocContext &CDCtx) {
+  HTMLFile F;
+
+  std::vector<std::unique_ptr<TagNode>> HeadNodes =
+      genFileHeadNodes(Title, InfoPath, CDCtx);
+  std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
+  std::unique_ptr<TagNode> MainNode =
+      genInfoFileMainNode(InfoPath, MainContentNodes, InfoIndex);
+  std::unique_ptr<TagNode> FooterNode = genFileFooterNode();
+
+  AppendVector(std::move(HeadNodes), F.Children);
+  F.Children.emplace_back(std::move(HeaderNode));
+  F.Children.emplace_back(std::move(MainNode));
+  F.Children.emplace_back(std::move(FooterNode));
+
+  return F;
+}
+
 template <typename T,
           typename = std::enable_if<std::is_base_of<T, Info>::value>>
 static Index genInfoIndexItem(const std::vector<T> &Infos, StringRef Title) {
@@ -474,8 +570,8 @@
   return Idx;
 }
 
-static std::vector<std::unique_ptr<TagNode>> genHTML(const Index &Index,
-                                                     StringRef InfoPath) {
+static std::vector<std::unique_ptr<TagNode>>
+genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList) {
   std::vector<std::unique_ptr<TagNode>> Out;
   if (!Index.Name.empty()) {
     Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_SPAN));
@@ -488,11 +584,13 @@
   }
   if (Index.Children.empty())
     return Out;
-  Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
+  // Only the outermost list should use ol, the others should use ul
+  HTMLTag ListHTMLTag = IsOutermostList ? HTMLTag::TAG_OL : HTMLTag::TAG_UL;
+  Out.emplace_back(std::make_unique<TagNode>(ListHTMLTag));
   const auto &UlBody = Out.back();
   for (const auto &C : Index.Children) {
     auto LiBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
-    std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(C, InfoPath);
+    std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(C, InfoPath, false);
     AppendVector(std::move(Nodes), LiBody->Children);
     UlBody->Children.emplace_back(std::move(LiBody));
   }
@@ -546,8 +644,8 @@
 
   Out.emplace_back(
       std::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
-  Out.back()->Attributes.try_emplace("id",
-                                     llvm::toHex(llvm::toStringRef(I.USR)));
+  Out.back()->Attributes.emplace_back("id",
+                                      llvm::toHex(llvm::toStringRef(I.USR)));
 
   std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members);
   if (Node)
@@ -575,8 +673,8 @@
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
   // USR is used as id for functions instead of name to disambiguate function
   // overloads.
-  Out.back()->Attributes.try_emplace("id",
-                                     llvm::toHex(llvm::toStringRef(I.USR)));
+  Out.back()->Attributes.emplace_back("id",
+                                      llvm::toHex(llvm::toStringRef(I.USR)));
 
   Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
   auto &FunctionHeader = Out.back();
@@ -738,48 +836,32 @@
 
 llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
                                               const ClangDocContext &CDCtx) {
-  HTMLFile F;
   std::string InfoTitle;
-  auto MainContentNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
+  std::vector<std::unique_ptr<TagNode>> MainContentNodes;
   Index InfoIndex;
   switch (I->IT) {
-  case InfoType::IT_namespace: {
-    std::vector<std::unique_ptr<TagNode>> Nodes =
-        genHTML(*static_cast<clang::doc::NamespaceInfo *>(I), InfoIndex, CDCtx,
-                InfoTitle);
-    AppendVector(std::move(Nodes), MainContentNode->Children);
+  case InfoType::IT_namespace:
+    MainContentNodes = genHTML(*static_cast<clang::doc::NamespaceInfo *>(I),
+                               InfoIndex, CDCtx, InfoTitle);
     break;
-  }
-  case InfoType::IT_record: {
-    std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(
-        *static_cast<clang::doc::RecordInfo *>(I), InfoIndex, CDCtx, InfoTitle);
-    AppendVector(std::move(Nodes), MainContentNode->Children);
+  case InfoType::IT_record:
+    MainContentNodes = genHTML(*static_cast<clang::doc::RecordInfo *>(I),
+                               InfoIndex, CDCtx, InfoTitle);
     break;
-  }
-  case InfoType::IT_enum: {
-    std::vector<std::unique_ptr<TagNode>> Nodes =
-        genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx);
-    AppendVector(std::move(Nodes), MainContentNode->Children);
+  case InfoType::IT_enum:
+    MainContentNodes = genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx);
     break;
-  }
-  case InfoType::IT_function: {
-    std::vector<std::unique_ptr<TagNode>> Nodes =
+  case InfoType::IT_function:
+    MainContentNodes =
         genHTML(*static_cast<clang::doc::FunctionInfo *>(I), CDCtx, "");
-    AppendVector(std::move(Nodes), MainContentNode->Children);
     break;
-  }
   case InfoType::IT_default:
     return llvm::make_error<llvm::StringError>("Unexpected info type.\n",
                                                llvm::inconvertibleErrorCode());
   }
 
-  std::vector<std::unique_ptr<TagNode>> BasicNodes =
-      genCommonFileNodes(InfoTitle, I->Path, CDCtx);
-  AppendVector(std::move(BasicNodes), F.Children);
-  std::vector<std::unique_ptr<TagNode>> InfoIndexHTML =
-      genHTML(InfoIndex, I->Path);
-  AppendVector(std::move(InfoIndexHTML), F.Children);
-  F.Children.emplace_back(std::move(MainContentNode));
+  HTMLFile F =
+      genInfoFile(InfoTitle, I->Path, MainContentNodes, InfoIndex, CDCtx);
   F.Render(OS);
 
   return llvm::Error::success();
@@ -832,6 +914,24 @@
   return true;
 }
 
+// Generates a main HTML node that has the main content of the file that shows
+// only the general index
+// It contains the general index with links to all the generated files
+static std::unique_ptr<TagNode> genIndexFileMainNode() {
+  auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
+
+  auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
+  LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left");
+  LeftSidebarNode->Attributes.emplace_back("path", "");
+  LeftSidebarNode->Attributes.emplace_back(
+      "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
+  LeftSidebarNode->Attributes.emplace_back("style", "flex: 0 100%;");
+
+  MainNode->Children.emplace_back(std::move(LeftSidebarNode));
+
+  return MainNode;
+}
+
 static bool GenIndex(const ClangDocContext &CDCtx) {
   std::error_code FileErr, OK;
   llvm::SmallString<128> IndexPath;
@@ -842,11 +942,22 @@
     llvm::errs() << "Error creating main index: " << FileErr.message() << "\n";
     return false;
   }
+
   HTMLFile F;
-  std::vector<std::unique_ptr<TagNode>> BasicNodes =
-      genCommonFileNodes("Index", "", CDCtx);
-  AppendVector(std::move(BasicNodes), F.Children);
+
+  std::vector<std::unique_ptr<TagNode>> HeadNodes =
+      genFileHeadNodes("Index", "", CDCtx);
+  std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName);
+  std::unique_ptr<TagNode> MainNode = genIndexFileMainNode();
+  std::unique_ptr<TagNode> FooterNode = genFileFooterNode();
+
+  AppendVector(std::move(HeadNodes), F.Children);
+  F.Children.emplace_back(std::move(HeaderNode));
+  F.Children.emplace_back(std::move(MainNode));
+  F.Children.emplace_back(std::move(FooterNode));
+
   F.Render(IndexOS);
+
   return true;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to