|
| 1 | +// Copyright 2023 Google LLC |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +#include "docfx/doxygen_pages.h" |
| 16 | +#include "docfx/doxygen2markdown.h" |
| 17 | +#include <iostream> |
| 18 | +#include <sstream> |
| 19 | +#include <string_view> |
| 20 | + |
| 21 | +// A "page" appears in the generated XML as: |
| 22 | +// clang-format off |
| 23 | +// <compounddef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="indexpage" kind="page"> |
| 24 | +// clang-format on |
| 25 | +// |
| 26 | +// That is, they are generic `compounddef` nodes -- the same entity used to |
| 27 | +// represent class or function reference docs. The definition is fairly complex |
| 28 | +// (see below). We will ignore things that we do not expect, such as |
| 29 | +// include diagrams, inner classes, etc. |
| 30 | +// |
| 31 | +// clang-format off |
| 32 | +// <xsd:complexType name="DoxygenType"> |
| 33 | +// <xsd:sequence maxOccurs="unbounded"> |
| 34 | +// <xsd:element name="compounddef" type="compounddefType" minOccurs="0" /> |
| 35 | +// </xsd:sequence> |
| 36 | +// <xsd:attribute name="version" type="DoxVersionNumber" use="required" /> |
| 37 | +// <xsd:attribute ref="xml:lang" use="required"/> |
| 38 | +// </xsd:complexType> |
| 39 | +// |
| 40 | +// <xsd:complexType name="compounddefType"> |
| 41 | +// <xsd:sequence> |
| 42 | +// <xsd:element name="compoundname" type="xsd:string"/> |
| 43 | +// <xsd:element name="title" type="xsd:string" minOccurs="0" /> |
| 44 | +// <xsd:element name="basecompoundref" type="compoundRefType" minOccurs="0" maxOccurs="unbounded" /> |
| 45 | +// <xsd:element name="derivedcompoundref" type="compoundRefType" minOccurs="0" maxOccurs="unbounded" /> |
| 46 | +// <xsd:element name="includes" type="incType" minOccurs="0" maxOccurs="unbounded" /> |
| 47 | +// <xsd:element name="includedby" type="incType" minOccurs="0" maxOccurs="unbounded" /> |
| 48 | +// <xsd:element name="incdepgraph" type="graphType" minOccurs="0" /> |
| 49 | +// <xsd:element name="invincdepgraph" type="graphType" minOccurs="0" /> |
| 50 | +// <xsd:element name="innerdir" type="refType" minOccurs="0" maxOccurs="unbounded" /> |
| 51 | +// <xsd:element name="innerfile" type="refType" minOccurs="0" maxOccurs="unbounded" /> |
| 52 | +// <xsd:element name="innerclass" type="refType" minOccurs="0" maxOccurs="unbounded" /> |
| 53 | +// <xsd:element name="innernamespace" type="refType" minOccurs="0" maxOccurs="unbounded" /> |
| 54 | +// <xsd:element name="innerpage" type="refType" minOccurs="0" maxOccurs="unbounded" /> |
| 55 | +// <xsd:element name="innergroup" type="refType" minOccurs="0" maxOccurs="unbounded" /> |
| 56 | +// <xsd:element name="templateparamlist" type="templateparamlistType" minOccurs="0" /> |
| 57 | +// <xsd:element name="sectiondef" type="sectiondefType" minOccurs="0" maxOccurs="unbounded" /> |
| 58 | +// <xsd:element name="tableofcontents" type="tableofcontentsType" minOccurs="0" maxOccurs="1" /> |
| 59 | +// <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" /> |
| 60 | +// <xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" /> |
| 61 | +// <xsd:element name="inheritancegraph" type="graphType" minOccurs="0" /> |
| 62 | +// <xsd:element name="collaborationgraph" type="graphType" minOccurs="0" /> |
| 63 | +// <xsd:element name="programlisting" type="listingType" minOccurs="0" /> |
| 64 | +// <xsd:element name="location" type="locationType" minOccurs="0" /> |
| 65 | +// <xsd:element name="listofallmembers" type="listofallmembersType" minOccurs="0" /> |
| 66 | +// </xsd:sequence> |
| 67 | +// <xsd:attribute name="id" type="xsd:string" /> |
| 68 | +// <xsd:attribute name="kind" type="DoxCompoundKind" /> |
| 69 | +// <xsd:attribute name="language" type="DoxLanguage" use="optional"/> |
| 70 | +// <xsd:attribute name="prot" type="DoxProtectionKind" /> |
| 71 | +// <xsd:attribute name="final" type="DoxBool" use="optional"/> |
| 72 | +// <xsd:attribute name="inline" type="DoxBool" use="optional"/> |
| 73 | +// <xsd:attribute name="sealed" type="DoxBool" use="optional"/> |
| 74 | +// <xsd:attribute name="abstract" type="DoxBool" use="optional"/> |
| 75 | +// </xsd:complexType> |
| 76 | +// clang-format on |
| 77 | +std::string Page2Markdown(pugi::xml_node const& node) { |
| 78 | + if (std::string_view{node.name()} != "compounddef" || |
| 79 | + std::string_view{node.attribute("kind").as_string()} != "page") { |
| 80 | + std::ostringstream os; |
| 81 | + os << "The node is not a page " << __func__ << "(): node="; |
| 82 | + node.print(os, /*indent=*/"", /*flags=*/pugi::format_raw, |
| 83 | + /*encoding=*/pugi::encoding_auto, /*depth=*/1); |
| 84 | + throw std::runtime_error(std::move(os).str()); |
| 85 | + } |
| 86 | + std::ostringstream os; |
| 87 | + MarkdownContext ctx; |
| 88 | + os << "# "; |
| 89 | + AppendTitle(os, ctx, node); |
| 90 | + os << "\n"; |
| 91 | + for (auto const& child : node) { |
| 92 | + auto name = std::string_view(child.name()); |
| 93 | + if (name == "compoundname") continue; // no markdown output |
| 94 | + if (name == "briefdescription") continue; // no markdown output |
| 95 | + if (name == "location") continue; // no markdown output |
| 96 | + if (name == "title") continue; // already handled |
| 97 | + // These are unexpected in a page: basecompoundref, derivedcompoundref, |
| 98 | + // includes, includedby, incdepgraph, invincdepgraph, innerdir, |
| 99 | + // innerfile, innerclass, innernamespace, innerpage, innergroup, |
| 100 | + // templateparamlist, sectiondef, inheritancegraph, collaborationgraph, |
| 101 | + // programlisting, listofallmembers. |
| 102 | + if (AppendIfDetailedDescription(os, ctx, child)) continue; |
| 103 | + UnknownChildType(__func__, child); |
| 104 | + } |
| 105 | + os << "\n"; |
| 106 | + return std::move(os).str(); |
| 107 | +} |
0 commit comments