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> Children; // List of child nodes - llvm::StringMap> + std::vector, 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> Out; for (const auto &FilePath : CDCtx.UserStylesheets) { auto LinkNode = std::make_unique(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 genLink(const Twine &Text, const Twine &Link) { auto LinkNode = std::make_unique(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> Out; Out.emplace_back(std::make_unique(HTMLTag::TAG_H2, "Enums")); - Out.back()->Attributes.try_emplace("id", "Enums"); + Out.back()->Attributes.emplace_back("id", "Enums"); Out.emplace_back(std::make_unique(HTMLTag::TAG_DIV)); auto &DivBody = Out.back(); for (const auto &E : Enums) { @@ -362,7 +379,7 @@ std::vector> Out; Out.emplace_back(std::make_unique(HTMLTag::TAG_H2, "Functions")); - Out.back()->Attributes.try_emplace("id", "Functions"); + Out.back()->Attributes.emplace_back("id", "Functions"); Out.emplace_back(std::make_unique(HTMLTag::TAG_DIV)); auto &DivBody = Out.back(); for (const auto &F : Functions) { @@ -381,7 +398,7 @@ std::vector> Out; Out.emplace_back(std::make_unique(HTMLTag::TAG_H2, "Members")); - Out.back()->Attributes.try_emplace("id", "Members"); + Out.back()->Attributes.emplace_back("id", "Members"); Out.emplace_back(std::make_unique(HTMLTag::TAG_UL)); auto &ULBody = Out.back(); for (const auto &M : Members) { @@ -405,7 +422,7 @@ std::vector> Out; Out.emplace_back(std::make_unique(HTMLTag::TAG_H2, Title)); - Out.back()->Attributes.try_emplace("id", Title); + Out.back()->Attributes.emplace_back("id", Title); Out.emplace_back(std::make_unique(HTMLTag::TAG_UL)); auto &ULBody = Out.back(); for (const auto &R : References) { @@ -431,23 +448,29 @@ std::make_unique(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(" of file ")); auto LocFileNode = std::make_unique( 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> -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> +genFileHeadNodes(StringRef Title, StringRef InfoPath, + const ClangDocContext &CDCtx) { std::vector> Out; auto MetaNode = std::make_unique(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(HTMLTag::TAG_TITLE, Title)); std::vector> StylesheetsNodes = @@ -456,14 +479,87 @@ std::vector> JsNodes = genJsScriptsHTML(InfoPath, CDCtx); AppendVector(std::move(JsNodes), Out); - // An empty
is generated but the index will be then rendered here - auto IndexNode = std::make_unique(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 genFileHeaderNode(StringRef ProjectName) { + auto HeaderNode = std::make_unique(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 genInfoFileMainNode( + StringRef InfoPath, + std::vector> &MainContentInnerNodes, + const Index &InfoIndex) { + auto MainNode = std::make_unique(HTMLTag::TAG_MAIN); + + auto LeftSidebarNode = std::make_unique(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(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(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> 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 genFileFooterNode() { + auto FooterNode = std::make_unique(HTMLTag::TAG_FOOTER); + auto SpanNode = std::make_unique( + 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> &MainContentNodes, + const Index &InfoIndex, const ClangDocContext &CDCtx) { + HTMLFile F; + + std::vector> HeadNodes = + genFileHeadNodes(Title, InfoPath, CDCtx); + std::unique_ptr HeaderNode = genFileHeaderNode(CDCtx.ProjectName); + std::unique_ptr MainNode = + genInfoFileMainNode(InfoPath, MainContentNodes, InfoIndex); + std::unique_ptr 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 ::value>> static Index genInfoIndexItem(const std::vector &Infos, StringRef Title) { @@ -474,8 +570,8 @@ return Idx; } -static std::vector> genHTML(const Index &Index, - StringRef InfoPath) { +static std::vector> +genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList) { std::vector> Out; if (!Index.Name.empty()) { Out.emplace_back(std::make_unique(HTMLTag::TAG_SPAN)); @@ -488,11 +584,13 @@ } if (Index.Children.empty()) return Out; - Out.emplace_back(std::make_unique(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(ListHTMLTag)); const auto &UlBody = Out.back(); for (const auto &C : Index.Children) { auto LiBody = std::make_unique(HTMLTag::TAG_LI); - std::vector> Nodes = genHTML(C, InfoPath); + std::vector> 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(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 Node = genEnumMembersBlock(I.Members); if (Node) @@ -575,8 +673,8 @@ Out.emplace_back(std::make_unique(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(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(HTMLTag::TAG_DIV); + std::vector> MainContentNodes; Index InfoIndex; switch (I->IT) { - case InfoType::IT_namespace: { - std::vector> Nodes = - genHTML(*static_cast(I), InfoIndex, CDCtx, - InfoTitle); - AppendVector(std::move(Nodes), MainContentNode->Children); + case InfoType::IT_namespace: + MainContentNodes = genHTML(*static_cast(I), + InfoIndex, CDCtx, InfoTitle); break; - } - case InfoType::IT_record: { - std::vector> Nodes = genHTML( - *static_cast(I), InfoIndex, CDCtx, InfoTitle); - AppendVector(std::move(Nodes), MainContentNode->Children); + case InfoType::IT_record: + MainContentNodes = genHTML(*static_cast(I), + InfoIndex, CDCtx, InfoTitle); break; - } - case InfoType::IT_enum: { - std::vector> Nodes = - genHTML(*static_cast(I), CDCtx); - AppendVector(std::move(Nodes), MainContentNode->Children); + case InfoType::IT_enum: + MainContentNodes = genHTML(*static_cast(I), CDCtx); break; - } - case InfoType::IT_function: { - std::vector> Nodes = + case InfoType::IT_function: + MainContentNodes = genHTML(*static_cast(I), CDCtx, ""); - AppendVector(std::move(Nodes), MainContentNode->Children); break; - } case InfoType::IT_default: return llvm::make_error("Unexpected info type.\n", llvm::inconvertibleErrorCode()); } - std::vector> BasicNodes = - genCommonFileNodes(InfoTitle, I->Path, CDCtx); - AppendVector(std::move(BasicNodes), F.Children); - std::vector> 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 genIndexFileMainNode() { + auto MainNode = std::make_unique(HTMLTag::TAG_MAIN); + + auto LeftSidebarNode = std::make_unique(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> BasicNodes = - genCommonFileNodes("Index", "", CDCtx); - AppendVector(std::move(BasicNodes), F.Children); + + std::vector> HeadNodes = + genFileHeadNodes("Index", "", CDCtx); + std::unique_ptr HeaderNode = genFileHeaderNode(CDCtx.ProjectName); + std::unique_ptr MainNode = genIndexFileMainNode(); + std::unique_ptr 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; } 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 UserStylesheets, std::vector 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 UserStylesheets, std::vector 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/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,"); + 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,"); +} + +.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,"); + 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/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/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 + ProjectName("project-name", llvm::cl::desc("Name of project."), + llvm::cl::cat(ClangDocCategory)); + static llvm::cl::opt 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/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= - Directory for outputting generated files. -p= - Build path + --project-name= - Name of project. --public - Document only public declarations. --repository= - URL of repository that hosts code. 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 getHTMLGenerator() { auto G = doc::findGeneratorByName("html"); if (!G) @@ -25,7 +29,8 @@ ClangDocContext getClangDocContext(std::vector 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 @@ -
- -
-

namespace Namespace

-

Namespaces

- -

Records

- -

Functions

-
-

OneFunction

-

OneFunction()

+

Functions

+
+

OneFunction

+

OneFunction()

+
+

Enums

+
+

enum OneEnum

+
-

Enums

-
-

enum OneEnum

+ -
+ +
+ )raw" + + ClangDocVersion + R"raw( +
)raw"; EXPECT_EQ(Expected, Actual.str()); @@ -162,80 +176,89 @@ class r -
- -
-

class r

-

- Defined at line - 10 - of file - test.cpp -

-

- Inherits from - F - , G -

-

Members

-
    -
  • - private - int - X -
  • -
-

Records

- -

Functions

-
-

OneFunction

-

public OneFunction()

+

Functions

+
+

OneFunction

+

public OneFunction()

+
+

Enums

+
+

enum OneEnum

+
-

Enums

-
-

enum OneEnum

+ -
+ +
+ )raw" + + ClangDocVersion + R"raw( +
)raw"; EXPECT_EQ(Expected, Actual.str()); @@ -270,17 +293,25 @@ -
-
-

f

-

- float - f( - int - P) -

-

Defined at line 10 of file dir/test.cpp

-
+
test-project
+
+ +
+

f

+

+ float + f( + int + P) +

+

Defined at line 10 of file dir/test.cpp

+
+ +
+
+ )raw" + + ClangDocVersion + R"raw( +
)raw"; EXPECT_EQ(Expected, Actual.str()); @@ -309,19 +340,27 @@ -
-
-

enum class e

-
    -
  • X
  • -
-

- Defined at line - 10 - of file - test.cpp -

-
+
test-project
+
+ +
+

enum class e

+
    +
  • X
  • +
+

+ Defined at line + 10 + of file + test.cpp +

+
+ +
+
+ )raw" + + ClangDocVersion + R"raw( +
)raw"; EXPECT_EQ(Expected, Actual.str()); @@ -386,19 +425,27 @@ -
-
-

f

-

void f(int I, int J)

-

Defined at line 10 of file test.cpp

-
+
test-project
+
+ +
+

f

+

void f(int I, int J)

+

Defined at line 10 of file test.cpp

-

Brief description.

-

Extended description that continues onto the next line.

-

Comment with html entities: &, <, >, ", '.

+
+

Brief description.

+

Extended description that continues onto the next line.

+

Comment with html entities: &, <, >, ", '.

+
-
+ + + )raw"; EXPECT_EQ(Expected, Actual.str());