11 #include "clang/Basic/Version.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/JSON.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/raw_ostream.h"
51 constexpr HTMLTag(TagType Value) : Value(Value) {}
53 operator TagType()
const {
return Value; }
54 operator bool() =
delete;
56 bool IsSelfClosing()
const;
57 llvm::SmallString<16> ToString()
const;
69 HTMLNode(NodeType Type) :
Type(
Type) {}
70 virtual ~HTMLNode() =
default;
72 virtual void Render(llvm::raw_ostream &
OS,
int IndentationLevel) = 0;
76 struct TextNode :
public HTMLNode {
77 TextNode(
const Twine &
Text)
78 : HTMLNode(NodeType::NODE_TEXT),
Text(
Text.str()) {}
81 void Render(llvm::raw_ostream &
OS,
int IndentationLevel)
override;
84 struct TagNode :
public HTMLNode {
85 TagNode(HTMLTag
Tag) : HTMLNode(NodeType::NODE_TAG),
Tag(
Tag) {}
86 TagNode(HTMLTag
Tag,
const Twine &Text) : TagNode(
Tag) {
87 Children.emplace_back(std::make_unique<TextNode>(
Text.str()));
91 std::vector<std::unique_ptr<HTMLNode>>
Children;
92 std::vector<std::pair<std::string, std::string>>
95 void Render(llvm::raw_ostream &
OS,
int IndentationLevel)
override;
98 constexpr
const char *kDoctypeDecl =
"<!DOCTYPE html>";
101 std::vector<std::unique_ptr<HTMLNode>>
Children;
102 void Render(llvm::raw_ostream &
OS) {
103 OS << kDoctypeDecl <<
"\n";
104 for (
const auto &
C : Children) {
113 bool HTMLTag::IsSelfClosing()
const {
115 case HTMLTag::TAG_META:
116 case HTMLTag::TAG_LINK:
119 case HTMLTag::TAG_DIV:
120 case HTMLTag::TAG_FOOTER:
121 case HTMLTag::TAG_H1:
122 case HTMLTag::TAG_H2:
123 case HTMLTag::TAG_H3:
124 case HTMLTag::TAG_HEADER:
125 case HTMLTag::TAG_LI:
126 case HTMLTag::TAG_MAIN:
127 case HTMLTag::TAG_OL:
129 case HTMLTag::TAG_SCRIPT:
130 case HTMLTag::TAG_SPAN:
131 case HTMLTag::TAG_TITLE:
132 case HTMLTag::TAG_UL:
135 llvm_unreachable(
"Unhandled HTMLTag::TagType");
138 llvm::SmallString<16> HTMLTag::ToString()
const {
141 return llvm::SmallString<16>(
"a");
142 case HTMLTag::TAG_DIV:
143 return llvm::SmallString<16>(
"div");
144 case HTMLTag::TAG_FOOTER:
145 return llvm::SmallString<16>(
"footer");
146 case HTMLTag::TAG_H1:
147 return llvm::SmallString<16>(
"h1");
148 case HTMLTag::TAG_H2:
149 return llvm::SmallString<16>(
"h2");
150 case HTMLTag::TAG_H3:
151 return llvm::SmallString<16>(
"h3");
152 case HTMLTag::TAG_HEADER:
153 return llvm::SmallString<16>(
"header");
154 case HTMLTag::TAG_LI:
155 return llvm::SmallString<16>(
"li");
156 case HTMLTag::TAG_LINK:
157 return llvm::SmallString<16>(
"link");
158 case HTMLTag::TAG_MAIN:
159 return llvm::SmallString<16>(
"main");
160 case HTMLTag::TAG_META:
161 return llvm::SmallString<16>(
"meta");
162 case HTMLTag::TAG_OL:
163 return llvm::SmallString<16>(
"ol");
165 return llvm::SmallString<16>(
"p");
166 case HTMLTag::TAG_SCRIPT:
167 return llvm::SmallString<16>(
"script");
168 case HTMLTag::TAG_SPAN:
169 return llvm::SmallString<16>(
"span");
170 case HTMLTag::TAG_TITLE:
171 return llvm::SmallString<16>(
"title");
172 case HTMLTag::TAG_UL:
173 return llvm::SmallString<16>(
"ul");
175 llvm_unreachable(
"Unhandled HTMLTag::TagType");
178 void TextNode::Render(llvm::raw_ostream &
OS,
int IndentationLevel) {
179 OS.indent(IndentationLevel * 2);
180 printHTMLEscaped(Text,
OS);
183 void TagNode::Render(llvm::raw_ostream &
OS,
int IndentationLevel) {
185 bool InlineChildren =
true;
186 for (
const auto &
C : Children)
187 if (
C->Type == NodeType::NODE_TAG) {
188 InlineChildren =
false;
191 OS.indent(IndentationLevel * 2);
192 OS <<
"<" <<
Tag.ToString();
194 OS <<
" " <<
A.first <<
"=\"" <<
A.second <<
"\"";
195 if (
Tag.IsSelfClosing()) {
202 bool NewLineRendered =
true;
203 for (
const auto &
C : Children) {
204 int ChildrenIndentation =
205 InlineChildren || !NewLineRendered ? 0 : IndentationLevel + 1;
206 C->Render(
OS, ChildrenIndentation);
207 if (!InlineChildren && (
C ==
Children.back() ||
208 (
C->Type != NodeType::NODE_TEXT ||
209 (&
C + 1)->get()->Type != NodeType::NODE_TEXT))) {
211 NewLineRendered =
true;
213 NewLineRendered =
false;
216 OS.indent(IndentationLevel * 2);
217 OS <<
"</" <<
Tag.ToString() <<
">";
220 template <
typename Derived,
typename Base,
221 typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
223 std::vector<Base> &Original) {
224 std::move(New.begin(), New.end(), std::back_inserter(Original));
236 if (Destination == Origin)
240 llvm::sys::path::const_iterator FileI = llvm::sys::path::begin(Destination);
241 llvm::sys::path::const_iterator FileE = llvm::sys::path::end(Destination);
242 llvm::sys::path::const_iterator DirI = llvm::sys::path::begin(Origin);
243 llvm::sys::path::const_iterator DirE = llvm::sys::path::end(Origin);
249 while (FileI != FileE && DirI != DirE && *FileI == *DirI) {
253 SmallString<128> Result;
256 while (DirI != DirE) {
257 llvm::sys::path::append(Result,
"..");
261 while (FileI != FileE) {
262 llvm::sys::path::append(Result, *FileI);
270 static std::vector<std::unique_ptr<TagNode>>
272 std::vector<std::unique_ptr<TagNode>>
Out;
274 auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_LINK);
275 LinkNode->Attributes.emplace_back(
"rel",
"stylesheet");
277 llvm::sys::path::append(StylesheetPath,
278 llvm::sys::path::filename(FilePath));
280 llvm::sys::path::native(StylesheetPath, llvm::sys::path::Style::posix);
281 LinkNode->Attributes.emplace_back(
"href", std::string(StylesheetPath.str()));
282 Out.emplace_back(std::move(LinkNode));
287 static std::vector<std::unique_ptr<TagNode>>
289 std::vector<std::unique_ptr<TagNode>>
Out;
290 for (
const auto &FilePath : CDCtx.
JsScripts) {
291 auto ScriptNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT);
293 llvm::sys::path::append(ScriptPath, llvm::sys::path::filename(FilePath));
295 llvm::sys::path::native(ScriptPath, llvm::sys::path::Style::posix);
296 ScriptNode->Attributes.emplace_back(
"src", std::string(ScriptPath.str()));
297 Out.emplace_back(std::move(ScriptNode));
302 static std::unique_ptr<TagNode>
genLink(
const Twine &Text,
const Twine &Link) {
303 auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_A,
Text);
304 LinkNode->Attributes.emplace_back(
"href", Link.str());
308 static std::unique_ptr<HTMLNode>
310 llvm::Optional<StringRef> JumpToSection = None) {
311 if (
Type.Path.empty() && !
Type.IsInGlobalNamespace) {
313 return std::make_unique<TextNode>(
Type.Name);
315 return genLink(
Type.Name,
"#" + JumpToSection.getValue());
317 llvm::SmallString<64>
Path =
Type.getRelativeFilePath(CurrentDirectory);
318 llvm::sys::path::append(
Path,
Type.getFileBaseName() +
".html");
321 llvm::sys::path::native(
Path, llvm::sys::path::Style::posix);
323 Path += (
"#" + JumpToSection.getValue()).str();
327 static std::vector<std::unique_ptr<HTMLNode>>
329 const StringRef &CurrentDirectory) {
330 std::vector<std::unique_ptr<HTMLNode>>
Out;
331 for (
const auto &R :
Refs) {
332 if (&R !=
Refs.begin())
333 Out.emplace_back(std::make_unique<TextNode>(
", "));
339 static std::vector<std::unique_ptr<TagNode>>
340 genHTML(
const EnumInfo &I,
const ClangDocContext &CDCtx);
341 static std::vector<std::unique_ptr<TagNode>>
342 genHTML(
const FunctionInfo &I,
const ClangDocContext &CDCtx,
343 StringRef ParentInfoDir);
345 static std::vector<std::unique_ptr<TagNode>>
351 std::vector<std::unique_ptr<TagNode>>
Out;
352 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2,
"Enums"));
353 Out.back()->Attributes.emplace_back(
"id",
"Enums");
354 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
355 auto &DivBody =
Out.back();
356 for (
const auto &
E : Enums) {
357 std::vector<std::unique_ptr<TagNode>> Nodes =
genHTML(
E, CDCtx);
363 static std::unique_ptr<TagNode>
368 auto List = std::make_unique<TagNode>(HTMLTag::TAG_UL);
369 for (
const auto &
M : Members)
370 List->Children.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_LI,
M));
374 static std::vector<std::unique_ptr<TagNode>>
377 if (Functions.empty())
380 std::vector<std::unique_ptr<TagNode>>
Out;
381 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2,
"Functions"));
382 Out.back()->Attributes.emplace_back(
"id",
"Functions");
383 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV));
384 auto &DivBody =
Out.back();
385 for (
const auto &F : Functions) {
386 std::vector<std::unique_ptr<TagNode>> Nodes =
387 genHTML(F, CDCtx, ParentInfoDir);
393 static std::vector<std::unique_ptr<TagNode>>
395 StringRef ParentInfoDir) {
399 std::vector<std::unique_ptr<TagNode>>
Out;
400 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2,
"Members"));
401 Out.back()->Attributes.emplace_back(
"id",
"Members");
402 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
403 auto &ULBody =
Out.back();
404 for (
const auto &
M : Members) {
405 std::string Access = getAccessSpelling(
M.Access).str();
407 Access = Access +
" ";
408 auto LIBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
409 LIBody->Children.emplace_back(std::make_unique<TextNode>(Access));
410 LIBody->Children.emplace_back(
genReference(
M.Type, ParentInfoDir));
411 LIBody->Children.emplace_back(std::make_unique<TextNode>(
" " +
M.Name));
412 ULBody->Children.emplace_back(std::move(LIBody));
417 static std::vector<std::unique_ptr<TagNode>>
419 llvm::StringRef Title, StringRef ParentPath) {
423 std::vector<std::unique_ptr<TagNode>>
Out;
424 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, Title));
425 Out.back()->Attributes.emplace_back(
"id", std::string(Title));
426 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL));
427 auto &ULBody =
Out.back();
429 auto LiNode = std::make_unique<TagNode>(HTMLTag::TAG_LI);
430 LiNode->Children.emplace_back(
genReference(R, ParentPath));
431 ULBody->Children.emplace_back(std::move(LiNode));
436 static std::unique_ptr<TagNode>
440 return std::make_unique<TagNode>(
441 HTMLTag::TAG_P,
"Defined at line " + std::to_string(L.LineNumber) +
442 " of file " + L.Filename);
444 llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename);
445 auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P);
446 Node->Children.emplace_back(std::make_unique<TextNode>(
"Defined at line "));
448 std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber));
451 LocNumberNode->Attributes.emplace_back(
452 "href", (FileURL +
"#" + std::to_string(L.LineNumber)).str());
453 Node->Children.emplace_back(std::move(LocNumberNode));
454 Node->Children.emplace_back(std::make_unique<TextNode>(
" of file "));
455 auto LocFileNode = std::make_unique<TagNode>(
456 HTMLTag::TAG_A, llvm::sys::path::filename(FileURL));
457 LocFileNode->Attributes.emplace_back(
"href", std::string(FileURL.str()));
458 Node->Children.emplace_back(std::move(LocFileNode));
462 static std::vector<std::unique_ptr<TagNode>>
468 static std::vector<std::unique_ptr<TagNode>>
471 std::vector<std::unique_ptr<TagNode>>
Out;
472 auto MetaNode = std::make_unique<TagNode>(HTMLTag::TAG_META);
473 MetaNode->Attributes.emplace_back(
"charset",
"utf-8");
474 Out.emplace_back(std::move(MetaNode));
475 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_TITLE, Title));
476 std::vector<std::unique_ptr<TagNode>> StylesheetsNodes =
479 std::vector<std::unique_ptr<TagNode>> JsNodes =
488 auto HeaderNode = std::make_unique<TagNode>(HTMLTag::TAG_HEADER,
ProjectName);
489 HeaderNode->Attributes.emplace_back(
"id",
"project-title");
499 std::vector<std::unique_ptr<TagNode>> &MainContentInnerNodes,
500 const Index &InfoIndex) {
501 auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
503 auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
504 LeftSidebarNode->Attributes.emplace_back(
"id",
"sidebar-left");
505 LeftSidebarNode->Attributes.emplace_back(
"path", std::string(InfoPath));
506 LeftSidebarNode->Attributes.emplace_back(
507 "class",
"col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
509 auto MainContentNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
510 MainContentNode->Attributes.emplace_back(
"id",
"main-content");
511 MainContentNode->Attributes.emplace_back(
512 "class",
"col-xs-12 col-sm-9 col-md-8 main-content");
513 AppendVector(std::move(MainContentInnerNodes), MainContentNode->Children);
515 auto RightSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
516 RightSidebarNode->Attributes.emplace_back(
"id",
"sidebar-right");
517 RightSidebarNode->Attributes.emplace_back(
518 "class",
"col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right");
519 std::vector<std::unique_ptr<TagNode>> InfoIndexHTML =
520 genHTML(InfoIndex, InfoPath,
true);
521 AppendVector(std::move(InfoIndexHTML), RightSidebarNode->Children);
523 MainNode->Children.emplace_back(std::move(LeftSidebarNode));
524 MainNode->Children.emplace_back(std::move(MainContentNode));
525 MainNode->Children.emplace_back(std::move(RightSidebarNode));
533 auto FooterNode = std::make_unique<TagNode>(HTMLTag::TAG_FOOTER);
534 auto SpanNode = std::make_unique<TagNode>(
535 HTMLTag::TAG_SPAN, clang::getClangToolFullVersion(
"clang-doc"));
536 SpanNode->Attributes.emplace_back(
"class",
"no-break");
537 FooterNode->Children.emplace_back(std::move(SpanNode));
544 std::vector<std::unique_ptr<TagNode>> &MainContentNodes,
548 std::vector<std::unique_ptr<TagNode>> HeadNodes =
551 std::unique_ptr<TagNode> MainNode =
556 F.Children.emplace_back(std::move(HeaderNode));
557 F.Children.emplace_back(std::move(MainNode));
558 F.Children.emplace_back(std::move(FooterNode));
563 template <
typename T,
564 typename = std::enable_if<std::is_base_of<T, Info>::value>>
566 Index Idx(Title, Title);
567 for (
const auto &
C : Infos)
568 Idx.
Children.emplace_back(
C.extractName(),
569 llvm::toHex(llvm::toStringRef(
C.USR)));
573 static std::vector<std::unique_ptr<TagNode>>
575 std::vector<std::unique_ptr<TagNode>>
Out;
577 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_SPAN));
578 auto &SpanBody =
Out.back();
582 SpanBody->Children.emplace_back(
588 HTMLTag ListHTMLTag = IsOutermostList ? HTMLTag::TAG_OL : HTMLTag::TAG_UL;
589 Out.emplace_back(std::make_unique<TagNode>(ListHTMLTag));
590 const auto &UlBody =
Out.back();
592 auto LiBody = std::make_unique<TagNode>(HTMLTag::TAG_LI);
593 std::vector<std::unique_ptr<TagNode>> Nodes =
genHTML(
C, InfoPath,
false);
595 UlBody->Children.emplace_back(std::move(LiBody));
601 if (I.
Kind ==
"FullComment") {
602 auto FullComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
603 for (
const auto &Child : I.
Children) {
604 std::unique_ptr<HTMLNode> Node =
genHTML(*Child);
606 FullComment->Children.emplace_back(std::move(Node));
608 return std::move(FullComment);
609 }
else if (I.
Kind ==
"ParagraphComment") {
610 auto ParagraphComment = std::make_unique<TagNode>(HTMLTag::TAG_P);
611 for (
const auto &Child : I.
Children) {
612 std::unique_ptr<HTMLNode> Node =
genHTML(*Child);
614 ParagraphComment->Children.emplace_back(std::move(Node));
616 if (ParagraphComment->Children.empty())
618 return std::move(ParagraphComment);
619 }
else if (I.
Kind ==
"TextComment") {
622 return std::make_unique<TextNode>(I.
Text);
627 static std::unique_ptr<TagNode>
genHTML(
const std::vector<CommentInfo> &
C) {
628 auto CommentBlock = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
629 for (
const auto &Child :
C) {
630 if (std::unique_ptr<HTMLNode> Node =
genHTML(Child))
631 CommentBlock->Children.emplace_back(std::move(Node));
636 static std::vector<std::unique_ptr<TagNode>>
638 std::vector<std::unique_ptr<TagNode>>
Out;
639 std::string EnumType;
641 EnumType =
"enum class ";
646 std::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.
Name));
647 Out.back()->Attributes.emplace_back(
"id",
648 llvm::toHex(llvm::toStringRef(I.
USR)));
652 Out.emplace_back(std::move(Node));
659 I.
DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
669 static std::vector<std::unique_ptr<TagNode>>
671 StringRef ParentInfoDir) {
672 std::vector<std::unique_ptr<TagNode>>
Out;
673 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H3, I.
Name));
676 Out.back()->Attributes.emplace_back(
"id",
677 llvm::toHex(llvm::toStringRef(I.
USR)));
679 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
680 auto &FunctionHeader =
Out.back();
682 std::string Access = getAccessSpelling(I.
Access).str();
684 FunctionHeader->Children.emplace_back(
685 std::make_unique<TextNode>(Access +
" "));
687 FunctionHeader->Children.emplace_back(
689 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(
" "));
691 FunctionHeader->Children.emplace_back(
692 std::make_unique<TextNode>(I.
Name +
"("));
694 for (
const auto &P : I.
Params) {
695 if (&P != I.
Params.begin())
696 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(
", "));
697 FunctionHeader->Children.emplace_back(
genReference(P.Type, ParentInfoDir));
698 FunctionHeader->Children.emplace_back(
699 std::make_unique<TextNode>(
" " + P.Name));
701 FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(
")"));
708 I.
DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
718 static std::vector<std::unique_ptr<TagNode>>
720 std::string &InfoTitle) {
721 std::vector<std::unique_ptr<TagNode>>
Out;
722 if (I.
Name.str() ==
"")
723 InfoTitle =
"Global Namespace";
725 InfoTitle = (
"namespace " + I.
Name).str();
727 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
735 std::vector<std::unique_ptr<TagNode>> ChildNamespaces =
738 std::vector<std::unique_ptr<TagNode>> ChildRecords =
742 std::vector<std::unique_ptr<TagNode>> ChildFunctions =
745 std::vector<std::unique_ptr<TagNode>> ChildEnums =
750 InfoIndex.
Children.emplace_back(
"Namespaces",
"Namespaces");
752 InfoIndex.
Children.emplace_back(
"Records",
"Records");
762 static std::vector<std::unique_ptr<TagNode>>
764 std::string &InfoTitle) {
765 std::vector<std::unique_ptr<TagNode>>
Out;
767 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle));
774 I.
DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()}));
781 std::vector<std::unique_ptr<HTMLNode>> Parents =
783 std::vector<std::unique_ptr<HTMLNode>> VParents =
785 if (!Parents.empty() || !VParents.empty()) {
786 Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P));
787 auto &PBody =
Out.back();
788 PBody->Children.emplace_back(std::make_unique<TextNode>(
"Inherits from "));
791 else if (VParents.empty())
795 PBody->Children.emplace_back(std::make_unique<TextNode>(
", "));
800 std::vector<std::unique_ptr<TagNode>> Members =
803 std::vector<std::unique_ptr<TagNode>> ChildRecords =
807 std::vector<std::unique_ptr<TagNode>> ChildFunctions =
810 std::vector<std::unique_ptr<TagNode>> ChildEnums =
815 InfoIndex.
Children.emplace_back(
"Members",
"Members");
817 InfoIndex.
Children.emplace_back(
"Records",
"Records");
832 llvm::Error generateDocForInfo(
Info *I, llvm::raw_ostream &
OS,
837 const char *HTMLGenerator::Format =
"html";
839 llvm::Error HTMLGenerator::generateDocForInfo(
Info *I, llvm::raw_ostream &
OS,
841 std::string InfoTitle;
842 std::vector<std::unique_ptr<TagNode>> MainContentNodes;
845 case InfoType::IT_namespace:
847 InfoIndex, CDCtx, InfoTitle);
849 case InfoType::IT_record:
851 InfoIndex, CDCtx, InfoTitle);
853 case InfoType::IT_enum:
856 case InfoType::IT_function:
860 case InfoType::IT_default:
861 return llvm::createStringError(llvm::inconvertibleErrorCode(),
862 "unexpected info type");
866 MainContentNodes, InfoIndex, CDCtx);
869 return llvm::Error::success();
874 case InfoType::IT_default:
876 case InfoType::IT_namespace:
878 case InfoType::IT_record:
880 case InfoType::IT_function:
882 case InfoType::IT_enum:
885 llvm_unreachable(
"Unknown InfoType");
890 std::error_code FileErr;
891 llvm::SmallString<128> FilePath;
893 llvm::sys::path::append(FilePath,
"index_json.js");
894 llvm::raw_fd_ostream
OS(FilePath, FileErr, llvm::sys::fs::OF_None);
896 return llvm::createStringError(llvm::inconvertibleErrorCode(),
897 "error creating index file: " +
901 llvm::json::OStream J(
OS, 2);
902 std::function<void(
Index)> IndexToJSON = [&](
const Index &I) {
904 J.attribute(
"USR", toHex(llvm::toStringRef(I.USR)));
905 J.attribute(
"Name", I.Name);
906 J.attribute(
"RefType",
getRefType(I.RefType));
907 J.attribute(
"Path", I.getRelativeFilePath(
""));
908 J.attributeArray(
"Children", [&] {
909 for (
const Index &
C : I.Children)
914 OS <<
"var JsonIndex = `\n";
915 IndexToJSON(CDCtx.
Idx);
917 return llvm::Error::success();
924 auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN);
926 auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV);
927 LeftSidebarNode->Attributes.emplace_back(
"id",
"sidebar-left");
928 LeftSidebarNode->Attributes.emplace_back(
"path",
"");
929 LeftSidebarNode->Attributes.emplace_back(
930 "class",
"col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left");
931 LeftSidebarNode->Attributes.emplace_back(
"style",
"flex: 0 100%;");
933 MainNode->Children.emplace_back(std::move(LeftSidebarNode));
939 std::error_code FileErr, OK;
940 llvm::SmallString<128> IndexPath;
942 llvm::sys::path::append(IndexPath,
"index.html");
943 llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_None);
945 return llvm::createStringError(llvm::inconvertibleErrorCode(),
946 "error creating main index: " +
952 std::vector<std::unique_ptr<TagNode>> HeadNodes =
959 F.Children.emplace_back(std::move(HeaderNode));
960 F.Children.emplace_back(std::move(MainNode));
961 F.Children.emplace_back(std::move(FooterNode));
965 return llvm::Error::success();
969 llvm::SmallString<128> PathWrite;
971 llvm::sys::path::append(PathWrite, llvm::sys::path::filename(FilePath));
972 llvm::SmallString<128> PathRead;
973 llvm::sys::path::native(FilePath, PathRead);
975 std::error_code FileErr = llvm::sys::fs::copy_file(PathRead, PathWrite);
977 return llvm::createStringError(llvm::inconvertibleErrorCode(),
978 "error creating file " +
979 llvm::sys::path::filename(FilePath) +
980 ": " + FileErr.message() +
"\n");
982 return llvm::Error::success();
1003 return llvm::Error::success();
1006 static GeneratorRegistry::Add<HTMLGenerator>
HTML(HTMLGenerator::Format,
1007 "Generator for HTML output.");