From 3550da79ecdbc2b2a41aa305c659a5f90eb0b3c5 Mon Sep 17 00:00:00 2001 From: Diego Astiazaran Date: Fri, 16 Aug 2019 18:38:11 +0000 Subject: [PATCH] [clang-doc] Redesign of generated HTML files The new design includes a header (contains the project name), a main section, and a footer. The main section is divided into three subsections. Left, middle, right. The left section contains the general index, the middle contains the info's data, and the right contains the index for the info's content. The CSS has been updated. A flag --project-name is added. The Attributes attribute of the TagNode struct is now a vector of pairs because these attributes should be rendered in the insertion order. The functions (cpp and js) that converts an Index tree structure into HTML were slightly modified; the first ul tag created is now a ol tag. The inner lists are still ul. Differential Revision: https://reviews.llvm.org/D66353 llvm-svn: 369139 --- clang-tools-extra/clang-doc/HTMLGenerator.cpp | 231 +++-- clang-tools-extra/clang-doc/Representation.cpp | 10 +- clang-tools-extra/clang-doc/Representation.h | 5 +- .../assets/clang-doc-default-stylesheet.css | 996 ++++++++++++++++++--- clang-tools-extra/clang-doc/assets/index.js | 16 +- clang-tools-extra/clang-doc/tool/ClangDocMain.cpp | 5 + clang-tools-extra/docs/clang-doc.rst | 1 + .../unittests/clang-doc/HTMLGeneratorTest.cpp | 347 +++---- 8 files changed, 1272 insertions(+), 339 deletions(-) diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index 845a55b..72a8dab 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/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 @@ public: 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 @@ struct TagNode : public HTMLNode { 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 @@ bool HTMLTag::IsSelfClosing() const { 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 @@ llvm::SmallString<16> HTMLTag::ToString() const { 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 @@ void TagNode::Render(llvm::raw_ostream &OS, int IndentationLevel) { 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 @@ genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) { 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 @@ genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) { 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 @@ genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) { 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 @@ genEnumsBlock(const std::vector &Enums, 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 @@ genFunctionsBlock(const std::vector &Functions, 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 @@ genRecordMembersBlock(const llvm::SmallVector &Members, 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 @@ genReferencesBlock(const std::vector &References, 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 @@ writeFileDefinition(const Location &L, 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 @@ genCommonFileNodes(StringRef Title, StringRef InfoPath, 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 @@ static Index genInfoIndexItem(const std::vector &Infos, StringRef Title) { 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 @@ static std::vector> genHTML(const Index &Index, } 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 @@ genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) { 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 @@ genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx, 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 @@ const char *HTMLGenerator::Format = "html"; 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 @@ static bool SerializeIndex(ClangDocContext &CDCtx) { 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 @@ static bool GenIndex(const ClangDocContext &CDCtx) { 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; } diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index a70bf8c..bf3b1f7 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -274,12 +274,14 @@ void Index::sort() { } 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 diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 381ecd1..5585773 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -413,12 +413,13 @@ mergeInfos(std::vector> &Values); 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 diff --git a/clang-tools-extra/clang-doc/assets/clang-doc-default-stylesheet.css b/clang-tools-extra/clang-doc/assets/clang-doc-default-stylesheet.css index b334aae..8b33523 100644 --- a/clang-tools-extra/clang-doc/assets/clang-doc-default-stylesheet.css +++ b/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 diff --git a/clang-tools-extra/clang-doc/assets/index.js b/clang-tools-extra/clang-doc/assets/index.js index 2c5cae5..32f6556 100644 --- a/clang-tools-extra/clang-doc/assets/index.js +++ b/clang-tools-extra/clang-doc/assets/index.js @@ -39,7 +39,7 @@ function genLink(Ref, CurrentDirectory) { 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 @@ function genHTMLOfIndex(Index, CurrentDirectory) { } 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); } diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 5cb6e9e..b0c2113 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -52,6 +52,10 @@ using namespace clang; 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 @@ int main(int argc, const char **argv) { clang::doc::ClangDocContext CDCtx = { Exec->get()->getExecutionContext(), + ProjectName, PublicOnly, OutDirectory, SourceRoot, diff --git a/clang-tools-extra/docs/clang-doc.rst b/clang-tools-extra/docs/clang-doc.rst index c3be7ce..6f61970 100644 --- a/clang-tools-extra/docs/clang-doc.rst +++ b/clang-tools-extra/docs/clang-doc.rst @@ -89,6 +89,7 @@ Options --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. diff --git a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp index 6f64dad..e751d0b 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp +++ b/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 @@ std::unique_ptr getHTMLGenerator() { 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 @@ TEST(HTMLGeneratorTest, emitNamespaceHTML) { -
- -
-

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 @@ TEST(HTMLGeneratorTest, emitRecordHTML) { 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 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) { -
-
-

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 @@ TEST(HTMLGeneratorTest, emitEnumHTML) { -
-
-

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 @@ TEST(HTMLGeneratorTest, emitCommentHTML) { -
-
-

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()); -- 2.7.4