20#include <QtCore/qxmlstream.h>
24using namespace Qt::StringLiterals;
32 m_indexWriteState = {};
56
57
58
59
62 if (m_supplement && currentWriter)
70 QXmlStreamWriter writer(&data);
71 writer.setAutoFormatting(
true);
72 beginSubPage(aggregate, Generator::fileName(aggregate,
"webxml"));
73 writer.writeStartDocument();
74 writer.writeStartElement(
"WebXML");
75 writer.writeStartElement(
"document");
79 writer.writeEndElement();
80 writer.writeEndElement();
81 writer.writeEndDocument();
90 currentWriter.emplace(&data);
91 currentWriter->setAutoFormatting(
true);
92 beginSubPage(pn, Generator::fileName(pn,
"webxml"));
93 currentWriter->writeStartDocument();
94 currentWriter->writeStartElement(
"WebXML");
95 currentWriter->writeStartElement(
"document");
99 currentWriter->writeEndElement();
100 currentWriter->writeEndElement();
101 currentWriter->writeEndDocument();
112 QXmlStreamWriter writer(&data);
113 writer.setAutoFormatting(
true);
114 beginSubPage(en, linkForExampleFile(resolved_file.get_query(),
"webxml"));
115 writer.writeStartDocument();
116 writer.writeStartElement(
"WebXML");
117 writer.writeStartElement(
"document");
118 writer.writeStartElement(
"page");
119 writer.writeAttribute(
"name", resolved_file.get_query());
120 writer.writeAttribute(
"href", linkForExampleFile(resolved_file.get_query()));
121 const QString title = exampleFileTitle(
static_cast<
const ExampleNode *>(en), resolved_file.get_query());
122 writer.writeAttribute(
"title", title);
123 writer.writeAttribute(
"fulltitle", title);
124 writer.writeAttribute(
"subtitle", resolved_file.get_query());
125 writer.writeStartElement(
"description");
128 writer.writeAttribute(
"path", resolved_file.get_path());
129 writer.writeAttribute(
"line",
"0");
130 writer.writeAttribute(
"column",
"0");
135 QString code = quoter.quoteTo(en
->location(), QString(), QString());
136 writer.writeTextElement(
"code", trimmedTrailing(code, QString(), QString()));
138 writer.writeEndElement();
139 writer.writeEndElement();
140 writer.writeEndElement();
141 writer.writeEndElement();
142 writer.writeEndDocument();
151 const Config &config = Config::instance();
153 context.documentLocation = [
this](
const Node *target) {
154 return fullDocumentLocation(target);
160 if (qdocIndexFiles) {
161 qdocIndexFiles->generateIndexSections(writer, node, context, m_indexWriteState,
this);
167 std::ignore = qdocIndexFiles->generateIndexSection(writer, node, context,
168 m_indexWriteState,
this);
182 writer.writeStartElement(
"description");
184 writer.writeAttribute(
"path", effectiveDoc
.location().filePath());
185 writer.writeAttribute(
"line", QString::number(effectiveDoc.location().lineNo()));
186 writer.writeAttribute(
"column", QString::number(effectiveDoc.location().columnNo()));
190 generateRelations(writer, node);
193 writer.writeStartElement(
"generatedlist");
194 writer.writeAttribute(
"contents",
"classesbymodule");
195 auto *cnn =
static_cast<CollectionNode *>(node);
197 if (cnn->hasNamespaces()) {
198 writer.writeStartElement(
"section");
199 writer.writeStartElement(
"heading");
200 writer.writeAttribute(
"level",
"1");
201 writer.writeCharacters(
"Namespaces");
202 writer.writeEndElement();
204 generateAnnotatedList(writer, node, namespaces);
205 writer.writeEndElement();
207 if (cnn->hasClasses()) {
208 writer.writeStartElement(
"section");
209 writer.writeStartElement(
"heading");
210 writer.writeAttribute(
"level",
"1");
211 writer.writeCharacters(
"Classes");
212 writer.writeEndElement();
214 generateAnnotatedList(writer, node, classes);
215 writer.writeEndElement();
217 writer.writeEndElement();
220 m_inLink = m_inSectionHeading = m_hasQuotingInformation =
false;
226 QList<Text> alsoList = effectiveDoc.alsoList();
227 supplementAlsoList(node, alsoList);
229 if (!alsoList.isEmpty()) {
230 writer.writeStartElement(
"see-also");
231 for (
const auto &item : alsoList) {
232 const auto *atom = item.firstAtom();
234 atom = addAtomElements(writer, atom, node, marker_);
236 writer.writeEndElement();
242 m_supplement =
false;
244 auto *cn =
static_cast<CollectionNode *>(node);
245 if (!cn->noAutoList())
246 generateAnnotatedList(writer, node, cn->members());
249 writer.writeEndElement();
259 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
270 m_qdb->mergeCollections(
static_cast<CollectionNode *>(node));
279 auto *aggregate =
static_cast<Aggregate *>(node);
280 for (
auto c : aggregate->childNodes()) {
281 if ((c->isAggregate() || c->isTextPageNode() || c->isCollectionNode())
283 generateDocumentation(c);
291 bool keepQuoting =
false;
298 const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group);
300 generateAnnotatedList(writer, relative, cn
->members());
303 const Node *node{
nullptr};
306 if (!m_inLink && !m_inSectionHeading) {
307 link = getAutoLink(atom, relative, &node, Genus::API);
315 startLink(writer, atom, node, link);
317 writer.writeCharacters(atom->string());
320 writer.writeEndElement();
330 writer.writeStartElement(
"brief");
333 writer.writeCharacters(
"This property");
336 writer.writeCharacters(
"This variable");
349 str[0] = str[0].toLower();
350 if (str.endsWith(
'.'))
353 const QList<QStringView> words = QStringView{str}.split(
' ');
354 if (!words.isEmpty()) {
355 QStringView first(words.at(0));
356 if (!(first == u"contains" || first == u"specifies" || first == u"describes"
357 || first == u"defines" || first == u"holds" || first == u"determines"))
358 writer.writeCharacters(
" holds ");
360 writer.writeCharacters(
" ");
367 writer.writeCharacters(
".");
369 writer.writeEndElement();
373 writer.writeStartElement(
"teletype");
375 writer.writeAttribute(
"type",
"normal");
377 writer.writeAttribute(
"type",
"highlighted");
379 writer.writeCharacters(plainCode(atom->string()));
380 writer.writeEndElement();
384 if (!m_hasQuotingInformation)
385 writer.writeTextElement(
386 "code", trimmedTrailing(plainCode(atom->string()), QString(), QString()));
392 writer.writeTextElement(
"badcode",
393 trimmedTrailing(plainCode(atom->string()), QString(), QString()));
398 if (quoteCommand ==
"dots") {
399 writer.writeAttribute(
"indent", atom->string());
400 writer.writeCharacters(
"...");
402 writer.writeCharacters(atom->string());
404 writer.writeEndElement();
411 quoteCommand = atom->string();
412 writer.writeStartElement(quoteCommand);
424 QString link = linkForExampleFile(atom->string());
426 startLink(writer, atom, relative, link);
432 QString link = atom->string();
434 startLink(writer, atom,
nullptr,
"images/used-in-examples/" + link);
439 writer.writeStartElement(
"footnote");
443 writer.writeEndElement();
447 writer.writeEndElement();
450 writer.writeStartElement(
"raw");
451 writer.writeAttribute(
"format", atom->string());
455 writer.writeStartElement(
"bold");
457 writer.writeStartElement(
"italic");
459 writer.writeStartElement(
"underline");
461 writer.writeStartElement(
"subscript");
463 writer.writeStartElement(
"superscript");
465 writer.writeStartElement(
"teletype");
467 writer.writeStartElement(
"argument");
469 writer.writeStartElement(
"index");
474 writer.writeEndElement();
476 writer.writeEndElement();
478 writer.writeEndElement();
480 writer.writeEndElement();
482 writer.writeEndElement();
484 writer.writeEndElement();
486 writer.writeEndElement();
488 writer.writeEndElement();
490 writer.writeCharacters(QChar(0x2122));
493 writer.writeEndElement();
499 writer.writeStartElement(
"generatedlist");
500 writer.writeAttribute(
"contents", atom->string());
501 writer.writeEndElement();
512 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
513 if (!maybe_resolved_file) {
515 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
518 QString file_name{QFileInfo{file.get_path()}.fileName()};
522 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
524 writer.writeStartElement(atom->typeString().toLower());
525 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
527 writer.writeAttribute(
"href", imgPath);
528 writer.writeEndElement();
530 setImageFileName(relative, imgPath);
538 writer.writeStartElement(
"para");
539 writer.writeTextElement(
"bold",
"Important:");
540 writer.writeCharacters(
" ");
544 writer.writeStartElement(
"legalese");
548 writer.writeEndElement();
554 const Node *node =
nullptr;
555 QString link = getLink(atom, relative, &node);
557 startLink(writer, atom, node, link);
562 writer.writeStartElement(
"list");
565 writer.writeAttribute(
"type",
"bullet");
567 writer.writeAttribute(
"type",
"definition");
570 writer.writeAttribute(
"type",
"enum");
572 writer.writeAttribute(
"type",
"definition");
574 writer.writeAttribute(
"type",
"ordered");
576 writer.writeAttribute(
"start",
"A");
578 writer.writeAttribute(
"start",
"a");
580 writer.writeAttribute(
"start",
"I");
582 writer.writeAttribute(
"start",
"i");
584 writer.writeAttribute(
"start", atom
->next()->string());
586 writer.writeAttribute(
"start",
"1");
593 writer.writeStartElement(
"definition");
595 writer.writeTextElement(
596 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
600 writer.writeEndElement();
604 writer.writeStartElement(
"item");
608 writer.writeEndElement();
612 writer.writeEndElement();
616 writer.writeStartElement(
"para");
617 writer.writeTextElement(
"bold",
"Note:");
618 writer.writeCharacters(
" ");
625 writer.writeEndElement();
633 writer.writeStartElement(
"para");
638 writer.writeEndElement();
642 writer.writeStartElement(
"quote");
646 writer.writeEndElement();
650 writer.writeCharacters(atom->string());
654 writer.writeStartElement(
"section");
655 writer.writeAttribute(
"id",
660 writer.writeEndElement();
664 writer.writeStartElement(
"heading");
665 int unit = atom->string().toInt();
666 writer.writeAttribute(
"level", QString::number(unit));
667 m_inSectionHeading =
true;
671 writer.writeEndElement();
672 m_inSectionHeading =
false;
681 writer.writeStartElement(atom->string());
687 writer.writeAttribute(
"identifier", atom->string());
688 writer.writeEndElement();
695 const QString &location = atom->string();
696 writer.writeAttribute(
"location", location);
697 auto maybe_resolved_file{file_resolver.resolve(location)};
699 if (maybe_resolved_file)
700 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
703 QString details =
std::transform_reduce(
704 file_resolver.get_search_directories().cbegin(),
705 file_resolver.get_search_directories().cend(),
706 u"Searched directories:"_s,
708 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
711 relative
->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
717 writer.writeCharacters(atom->string());
720 writer.writeStartElement(
"table");
721 if (atom->string().contains(
"%"))
722 writer.writeAttribute(
"width", atom->string());
726 writer.writeEndElement();
730 writer.writeStartElement(
"header");
734 writer.writeEndElement();
738 writer.writeStartElement(
"row");
742 writer.writeEndElement();
746 writer.writeStartElement(
"item");
747 QStringList spans = atom->string().split(
",");
748 if (spans.size() == 2) {
749 if (spans.at(0) !=
"1")
750 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
751 if (spans.at(1) !=
"1")
752 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
756 writer.writeEndElement();
761 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
766 writer.writeStartElement(
"target");
767 writer.writeAttribute(
"name", TextUtils::asAsciiPrintable(atom->string()));
768 writer.writeEndElement();
772 writer.writeStartElement(
"para");
773 writer.writeTextElement(
"bold",
"Warning:");
774 writer.writeCharacters(
" ");
779 writer.writeCharacters(atom->typeString());
785 m_hasQuotingInformation = keepQuoting;
792 QString fullName = link;
794 fullName = node->fullName();
795 if (!fullName.isEmpty() && !link.isEmpty()) {
796 writer.writeStartElement(
"link");
797 if (atom && !atom->string().isEmpty())
798 writer.writeAttribute(
"raw", atom->string());
800 writer.writeAttribute(
"raw", fullName);
801 writer.writeAttribute(
"href", link);
802 writer.writeAttribute(
"type", targetType(node));
806 writer.writeAttribute(
"enum", fullName);
809 const auto *en =
static_cast<
const ExampleNode *>(node);
810 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
811 if (!fileTitle.isEmpty()) {
812 writer.writeAttribute(
"page", fileTitle);
818 writer.writeAttribute(
"page", fullName);
821 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
822 if (!propertyNode->getters().empty())
823 writer.writeAttribute(
"getter", propertyNode->getters().at(0)->fullName());
836 writer.writeEndElement();
843 if (node && !node->links().empty()) {
844 std::pair<QString, QString> anchorPair;
845 const Node *linkNode;
847 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
849 linkNode = m_qdb->findNodeForTarget(it.value().first, node);
854 if (linkNode == node)
855 anchorPair = it.value();
857 anchorPair = anchorForNode(linkNode);
859 writer.writeStartElement(
"relation");
860 writer.writeAttribute(
"href", anchorPair.first);
861 writer.writeAttribute(
"type", targetType(linkNode));
864 case Node::StartLink:
865 writer.writeAttribute(
"meta",
"start");
868 writer.writeAttribute(
"meta",
"next");
870 case Node::PreviousLink:
871 writer.writeAttribute(
"meta",
"previous");
873 case Node::ContentsLink:
874 writer.writeAttribute(
"meta",
"contents");
877 writer.writeAttribute(
"meta",
"");
879 writer.writeAttribute(
"description", anchorPair.second);
880 writer.writeEndElement();
888 generateAnnotatedList(writer, relative, nodeMap.values());
894 writer.writeStartElement(
"table");
895 writer.writeAttribute(
"width",
"100%");
897 for (
const auto *node : nodeList) {
898 writer.writeStartElement(
"row");
899 writer.writeStartElement(
"item");
900 writer.writeStartElement(
"para");
901 const QString link = linkForNode(node, relative);
902 startLink(writer, node->doc().body().firstAtom(), node, link);
904 writer.writeEndElement();
905 writer.writeEndElement();
907 writer.writeStartElement(
"item");
908 writer.writeStartElement(
"para");
909 writer.writeCharacters(node->doc().briefText().toString());
910 writer.writeEndElement();
911 writer.writeEndElement();
912 writer.writeEndElement();
914 writer.writeEndElement();
919 return Generator::fileBase(node);
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#define ATOM_FORMATTING_NOTRANSLATE
#define ATOM_LIST_LOWERROMAN
#define ATOM_FORMATTING_SUBSCRIPT
#define ATOM_FORMATTING_BOLD
#define ATOM_FORMATTING_TRADEMARK
#define ATOM_FORMATTING_ITALIC
#define ATOM_LIST_UPPERROMAN
#define ATOM_FORMATTING_SUPERSCRIPT
#define ATOM_FORMATTING_INDEX
#define ATOM_FORMATTING_PARAMETER
The Atom class is the fundamental unit for representing documents internally.
AtomType type() const
Return the type of this atom.
const Atom * next() const
Return the next atom in the atom list.
A class for holding the members of a collection of doc pages.
const NodeList & members() const
The Config class contains the configuration variables for controlling how qdoc produces documentation...
InclusionPolicy createInclusionPolicy() const
const Location & location() const
Returns the starting location of a qdoc comment.
static void quoteFromFile(const Location &location, Quoter "er, ResolvedFile resolved_file, CodeMarker *marker=nullptr)
const Text & body() const
Encapsulate the logic that QDoc uses to find files whose path is provided by the user and that are re...
static bool appendTrademark(const Atom *atom)
Returns true if a trademark symbol should be appended to the output as determined by atom.
void endSubPage()
Flush the text stream associated with the subpage, and then pop it off the text stream stack and dele...
void generateRequiredLinks(const Node *node, CodeMarker *marker)
Generates either a link to the project folder for example node, or a list of links files/images if 'u...
HtmlGenerator(FileResolver &file_resolver)
void initializeGenerator() override
Initializes the HTML output generator's data structures from the configuration (Config) singleton.
void terminateGenerator() override
Gracefully terminates the HTML output generator.
static bool isIncluded(const InclusionPolicy &policy, const NodeContext &context)
A PageNode is a Node that generates a documentation page.
This class imports QDoc index files and serializes index sections for module indexes and WebXML outpu...
static Text sectionHeading(const Atom *sectionBegin)
const Atom * firstAtom() const
QString fileBase(const Node *node) const override
QString format() const override
Returns the format identifier for this producer (e.g., "HTML", "DocBook", "template").
virtual const Atom * addAtomElements(QXmlStreamWriter &writer, const Atom *atom, const Node *relative, CodeMarker *marker)
void terminateGenerator() override
Gracefully terminates the HTML output generator.
void generateDocumentation(Node *node) override
Recursive writing of HTML files from the root node.
void append(QXmlStreamWriter &writer, Node *node) override
virtual void generateIndexSections(QXmlStreamWriter &writer, Node *node)
void generatePageNode(PageNode *pn, CodeMarker *marker) override
Generate the HTML page for an entity that doesn't map to any underlying parsable C++ or QML element.
WebXMLGenerator(FileResolver &file_resolver)
QString fileExtension() const override
Returns "html" for this subclass of Generator.
void initializeGenerator() override
Initializes the HTML output generator's data structures from the configuration (Config) singleton.
void generateExampleFilePage(const PageNode *en, ResolvedFile file, CodeMarker *marker=nullptr) override
Generate an html file with the contents of a C++ or QML source file.
void generateCppReferencePage(Aggregate *aggregate, CodeMarker *marker) override
Generate a reference page for the C++ class, namespace, or header file documented in node using the c...
qsizetype generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker) override
Most of the output is generated by QDocIndexFiles and the append() callback.
#define CONFIG_LOCATIONINFO
Combined button and popup list for selecting options.
QMap< QString, Node * > NodeMap
ExampleEntries exampleEntries
The Node class is the base class for all the nodes in QDoc's parse tree.
bool isExternalPage() const
Returns true if the node type is ExternalPage.
const Doc & doc() const
Returns a reference to the node's Doc data member.
bool isGroup() const
Returns true if the node type is Group.
SharedCommentNode * sharedCommentNode()
bool isNamespace() const
Returns true if the node type is Namespace.
bool isHeader() const
Returns true if the node type is HeaderFile.
NodeType nodeType() const override
Returns this node's type.
bool isEnumType() const
Returns true if the node type is Enum.
virtual bool isTextPageNode() const
Returns true if the node is a PageNode but not an Aggregate.
Aggregate * parent() const
Returns the node's parent pointer, that is, the aggregate under which the node is documented.
bool isVariable() const
Returns true if the node type is Variable.
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
const Location & location() const
If this node's definition location is empty, this function returns this node's declaration location.
virtual bool wasSeen() const
Returns the seen flag data member of this node if it is a NamespaceNode or a CollectionNode.
bool isProperty() const
Returns true if the node type is Property.
NodeContext createContext() const
bool isModule() const
Returns true if the node type is Module.
bool isSharingComment() const
This function returns true if the node is sharing a comment with other nodes.
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
virtual bool isCollectionNode() const
Returns true if this is an instance of CollectionNode.
bool isExample() const
Returns true if the node type is Example.
bool isIndexNode() const
Returns true if this node was created from something in an index file.
Represents a file that is reachable by QDoc based on its current configuration.
static CodeMarker * marker_