Index: clang-tools-extra/clang-doc/Generators.h =================================================================== --- clang-tools-extra/clang-doc/Generators.h +++ clang-tools-extra/clang-doc/Generators.h @@ -27,6 +27,7 @@ // Write out the decl info in the specified format. virtual llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) = 0; + virtual bool createResources(ClangDocContext CDCtx) = 0; }; typedef llvm::Registry GeneratorRegistry; Index: clang-tools-extra/clang-doc/HTMLGenerator.cpp =================================================================== --- clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -34,6 +34,7 @@ TAG_UL, TAG_LI, TAG_A, + TAG_LINK, }; HTMLTag() = default; @@ -114,6 +115,7 @@ bool HTMLTag::IsSelfClosing() const { switch (Value) { case HTMLTag::TAG_META: + case HTMLTag::TAG_LINK: return true; case HTMLTag::TAG_TITLE: case HTMLTag::TAG_DIV: @@ -137,6 +139,7 @@ case HTMLTag::TAG_H3: case HTMLTag::TAG_LI: case HTMLTag::TAG_A: + case HTMLTag::TAG_LINK: return true; case HTMLTag::TAG_DIV: case HTMLTag::TAG_P: @@ -167,6 +170,8 @@ return llvm::SmallString<16>("li"); case HTMLTag::TAG_A: return llvm::SmallString<16>("a"); + case HTMLTag::TAG_LINK: + return llvm::SmallString<16>("link"); } } @@ -546,6 +551,7 @@ static const char *Format; llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) override; + bool createResources(ClangDocContext CDCtx) override; }; const char *HTMLGenerator::Format = "html"; @@ -592,12 +598,39 @@ F.Children.emplace_back( llvm::make_unique(HTMLTag::TAG_TITLE, InfoTitle)); + auto LinkNode = llvm::make_unique(HTMLTag::TAG_LINK); + LinkNode->Attributes.try_emplace("rel", "stylesheet"); + SmallString<128> StylesheetPath = computeRelativePath("", I->Path); + llvm::sys::path::append(StylesheetPath, "clang-doc-default-stylesheet.css"); + LinkNode->Attributes.try_emplace("href", StylesheetPath); + F.Children.emplace_back(std::move(LinkNode)); F.Children.emplace_back(std::move(MainContentNode)); F.Render(OS); return llvm::Error::success(); } +bool HTMLGenerator::createResources(ClangDocContext CDCtx) { + llvm::outs() << "Generating stylesheet for docs...\n"; + llvm::SmallString<128> StylesheetPathWrite; + llvm::sys::path::native(CDCtx.OutDirectory, StylesheetPathWrite); + llvm::sys::path::append(StylesheetPathWrite, + "clang-doc-default-stylesheet.css"); + llvm::SmallString<128> StylesheetPathRead; + llvm::sys::path::native("clang-tools-extra/clang-doc/stylesheets/" + "clang-doc-default-stylesheet.css", + StylesheetPathRead); + std::error_code OK; + std::error_code FileErr = + llvm::sys::fs::copy_file(StylesheetPathRead, StylesheetPathWrite); + if (FileErr != OK) { + llvm::errs() << "Error creating stylesheet file: " << FileErr.message() + << "\n"; + return false; + } + return true; +} + static GeneratorRegistry::Add HTML(HTMLGenerator::Format, "Generator for HTML output."); Index: clang-tools-extra/clang-doc/MDGenerator.cpp =================================================================== --- clang-tools-extra/clang-doc/MDGenerator.cpp +++ clang-tools-extra/clang-doc/MDGenerator.cpp @@ -255,6 +255,7 @@ static const char *Format; llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) override; + bool createResources(ClangDocContext CDCtx) override { return true; } }; const char *MDGenerator::Format = "md"; Index: clang-tools-extra/clang-doc/Representation.h =================================================================== --- clang-tools-extra/clang-doc/Representation.h +++ clang-tools-extra/clang-doc/Representation.h @@ -349,6 +349,7 @@ struct ClangDocContext { tooling::ExecutionContext *ECtx; bool PublicOnly; + std::string OutDirectory; }; } // namespace doc Index: clang-tools-extra/clang-doc/YAMLGenerator.cpp =================================================================== --- clang-tools-extra/clang-doc/YAMLGenerator.cpp +++ clang-tools-extra/clang-doc/YAMLGenerator.cpp @@ -244,6 +244,7 @@ static const char *Format; llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) override; + bool createResources(ClangDocContext CDCtx) override { return true; } }; const char *YAMLGenerator::Format = "yaml"; Index: clang-tools-extra/clang-doc/stylesheets/clang-doc-default-stylesheet.css =================================================================== --- /dev/null +++ clang-tools-extra/clang-doc/stylesheets/clang-doc-default-stylesheet.css @@ -0,0 +1,205 @@ +body,div { + margin: 0; + padding: 0; +} + +body[no-overflow] { + overflow: hidden; +} + +li>p:first-child { + margin-top: 0; +} + +li>p:last-child { + margin-bottom: 0; +} + +html { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +*,*::before,*::after { + -webkit-box-sizing: inherit; + box-sizing: inherit; +} + +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%; +} + +body[devsite-framebox] { + overflow: hidden; + padding: 20px; +} + +body[sitemask--active] { + overflow: hidden; +} + +p { + margin: 16px 0; + padding: 0; +} + +:link,:visited { + color: #039be5; + outline: 0; + text-decoration: none; +} + +ul { + margin: 0; + padding-left: 40px; +} + +ul { + list-style: disc outside; +} + +li,li p { + margin: 12px 0; + padding: 0; +} + +*[visually-hidden] { + opacity: 0 !important; + pointer-events: none !important; + visibility: hidden !important; +} + +*[hidden] { + display: none !important; +} + +[render-hidden] { + display: inline !important; + position: absolute !important; + visibility: hidden !important; +} + +*[no-scroll] { + overflow: hidden; +} + +@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; + } +} + +@media screen and (max-width: 840px) { + body[devsite-book-nav--open] { + overflow: hidden; + } +} + +h1,h2,h3,h4,h5,h6 { + overflow: hidden; + padding: 0; + text-overflow: ellipsis; +} + +h1 { + color: #80868b; + font: 300 34px/40px Roboto,sans-serif; + letter-spacing: -0.01em; + margin: 40px 0 20px; +} + +[layout=docs] h2 { + border-bottom: 1px solid #e8eaed; + padding-bottom: 3px; +} + +h2 { + font: 300 24px/32px Roboto,sans-serif; + letter-spacing: -0.01em; + margin: 40px 0 20px; +} + +h3 { + font: 400 20px/32px Roboto,sans-serif; + margin: 32px 0 16px; +} + +h4,h5,h6 { + margin: 32px 0 16px; +} + +h4 { + font: 500 16px/24px Roboto,sans-serif; +} + +h5 { + font: 700 14px/24px Roboto,sans-serif; +} + +h6 { + font: 500 14px/24px Roboto,sans-serif; +} + +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; +} + +@media screen and (max-width: 600px) { + h1 { + font: 300 24px/32px Roboto,sans-serif; + } +} + +[scrollbars]::-webkit-scrollbar { + height: 8px; + width: 8px; +} + +[scrollbars]::-webkit-scrollbar-thumb { + background: rgba(128,134,139,.26); + border-radius: 8px; +} + +[no-horizontal-scrollbars]::-webkit-scrollbar { + height: 0; + width: 0; +} + +[scrollbars]::-webkit-scrollbar-corner { + background: 0; +} + +[background] h2 { + 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; + } + + :link, :visited { + text-decoration: underline; + } +} + +@page { + margin: .75in; +} 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 @@ -196,7 +196,7 @@ // Mapping phase llvm::outs() << "Mapping decls...\n"; clang::doc::ClangDocContext CDCtx = {Exec->get()->getExecutionContext(), - PublicOnly}; + PublicOnly, OutDirectory}; auto Err = Exec->get()->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster); if (Err) { @@ -239,5 +239,8 @@ llvm::errs() << toString(std::move(Err)) << "\n"; } + if (!G->get()->createResources(CDCtx)) + return 1; + return 0; } 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 @@ -43,6 +43,7 @@ std::string Expected = R"raw( namespace Namespace +

namespace Namespace

Namespaces

@@ -100,6 +101,7 @@ std::string Expected = R"raw( class r +

class r

@@ -157,6 +159,7 @@ std::string Expected = R"raw( +

f

@@ -194,6 +197,7 @@ std::string Expected = R"raw( +

enum class e

    @@ -254,6 +258,7 @@ std::string Expected = R"raw( +

    f