20#include <QtCore/qxmlstream.h>
24using namespace Qt::StringLiterals;
55
56
57
58
61 if (m_supplement && currentWriter)
69 QXmlStreamWriter writer(&data);
70 writer.setAutoFormatting(
true);
71 beginSubPage(aggregate, Generator::fileName(aggregate,
"webxml"));
72 writer.writeStartDocument();
73 writer.writeStartElement(
"WebXML");
74 writer.writeStartElement(
"document");
78 writer.writeEndElement();
79 writer.writeEndElement();
80 writer.writeEndDocument();
89 currentWriter.emplace(&data);
90 currentWriter->setAutoFormatting(
true);
91 beginSubPage(pn, Generator::fileName(pn,
"webxml"));
92 currentWriter->writeStartDocument();
93 currentWriter->writeStartElement(
"WebXML");
94 currentWriter->writeStartElement(
"document");
98 currentWriter->writeEndElement();
99 currentWriter->writeEndElement();
100 currentWriter->writeEndDocument();
111 QXmlStreamWriter writer(&data);
112 writer.setAutoFormatting(
true);
113 beginSubPage(en, linkForExampleFile(resolved_file.get_query(),
"webxml"));
114 writer.writeStartDocument();
115 writer.writeStartElement(
"WebXML");
116 writer.writeStartElement(
"document");
117 writer.writeStartElement(
"page");
118 writer.writeAttribute(
"name", resolved_file.get_query());
119 writer.writeAttribute(
"href", linkForExampleFile(resolved_file.get_query()));
120 const QString title = exampleFileTitle(
static_cast<
const ExampleNode *>(en), resolved_file.get_query());
121 writer.writeAttribute(
"title", title);
122 writer.writeAttribute(
"fulltitle", title);
123 writer.writeAttribute(
"subtitle", resolved_file.get_query());
124 writer.writeStartElement(
"description");
127 writer.writeAttribute(
"path", resolved_file.get_path());
128 writer.writeAttribute(
"line",
"0");
129 writer.writeAttribute(
"column",
"0");
134 QString code = quoter.quoteTo(en
->location(), QString(), QString());
135 writer.writeTextElement(
"code", trimmedTrailing(code, QString(), QString()));
137 writer.writeEndElement();
138 writer.writeEndElement();
139 writer.writeEndElement();
140 writer.writeEndElement();
141 writer.writeEndDocument();
151 if (qdocIndexFiles) {
152 qdocIndexFiles->generateIndexSections(writer, node,
this,
this);
158 std::ignore = qdocIndexFiles->generateIndexSection(writer, node,
this,
this);
172 writer.writeStartElement(
"description");
174 writer.writeAttribute(
"path", effectiveDoc
.location().filePath());
175 writer.writeAttribute(
"line", QString::number(effectiveDoc.location().lineNo()));
176 writer.writeAttribute(
"column", QString::number(effectiveDoc.location().columnNo()));
180 generateRelations(writer, node);
183 writer.writeStartElement(
"generatedlist");
184 writer.writeAttribute(
"contents",
"classesbymodule");
185 auto *cnn =
static_cast<CollectionNode *>(node);
187 if (cnn->hasNamespaces()) {
188 writer.writeStartElement(
"section");
189 writer.writeStartElement(
"heading");
190 writer.writeAttribute(
"level",
"1");
191 writer.writeCharacters(
"Namespaces");
192 writer.writeEndElement();
194 generateAnnotatedList(writer, node, namespaces);
195 writer.writeEndElement();
197 if (cnn->hasClasses()) {
198 writer.writeStartElement(
"section");
199 writer.writeStartElement(
"heading");
200 writer.writeAttribute(
"level",
"1");
201 writer.writeCharacters(
"Classes");
202 writer.writeEndElement();
204 generateAnnotatedList(writer, node, classes);
205 writer.writeEndElement();
207 writer.writeEndElement();
210 m_inLink = m_inSectionHeading = m_hasQuotingInformation =
false;
216 QList<Text> alsoList = effectiveDoc.alsoList();
217 supplementAlsoList(node, alsoList);
219 if (!alsoList.isEmpty()) {
220 writer.writeStartElement(
"see-also");
221 for (
const auto &item : alsoList) {
222 const auto *atom = item.firstAtom();
224 atom = addAtomElements(writer, atom, node, marker_);
226 writer.writeEndElement();
232 m_supplement =
false;
234 auto *cn =
static_cast<CollectionNode *>(node);
235 if (!cn->noAutoList())
236 generateAnnotatedList(writer, node, cn->members());
239 writer.writeEndElement();
249 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
260 m_qdb->mergeCollections(
static_cast<CollectionNode *>(node));
269 auto *aggregate =
static_cast<Aggregate *>(node);
270 for (
auto c : aggregate->childNodes()) {
271 if ((c->isAggregate() || c->isTextPageNode() || c->isCollectionNode())
273 generateDocumentation(c);
281 bool keepQuoting =
false;
288 const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group);
290 generateAnnotatedList(writer, relative, cn
->members());
293 const Node *node{
nullptr};
296 if (!m_inLink && !m_inSectionHeading) {
297 link = getAutoLink(atom, relative, &node, Genus::API);
305 startLink(writer, atom, node, link);
307 writer.writeCharacters(atom->string());
310 writer.writeEndElement();
320 writer.writeStartElement(
"brief");
323 writer.writeCharacters(
"This property");
326 writer.writeCharacters(
"This variable");
339 str[0] = str[0].toLower();
340 if (str.endsWith(
'.'))
343 const QList<QStringView> words = QStringView{str}.split(
' ');
344 if (!words.isEmpty()) {
345 QStringView first(words.at(0));
346 if (!(first == u"contains" || first == u"specifies" || first == u"describes"
347 || first == u"defines" || first == u"holds" || first == u"determines"))
348 writer.writeCharacters(
" holds ");
350 writer.writeCharacters(
" ");
357 writer.writeCharacters(
".");
359 writer.writeEndElement();
363 writer.writeStartElement(
"teletype");
365 writer.writeAttribute(
"type",
"normal");
367 writer.writeAttribute(
"type",
"highlighted");
369 writer.writeCharacters(plainCode(atom->string()));
370 writer.writeEndElement();
374 if (!m_hasQuotingInformation)
375 writer.writeTextElement(
376 "code", trimmedTrailing(plainCode(atom->string()), QString(), QString()));
382 writer.writeTextElement(
"badcode",
383 trimmedTrailing(plainCode(atom->string()), QString(), QString()));
388 if (quoteCommand ==
"dots") {
389 writer.writeAttribute(
"indent", atom->string());
390 writer.writeCharacters(
"...");
392 writer.writeCharacters(atom->string());
394 writer.writeEndElement();
401 quoteCommand = atom->string();
402 writer.writeStartElement(quoteCommand);
414 QString link = linkForExampleFile(atom->string());
416 startLink(writer, atom, relative, link);
422 QString link = atom->string();
424 startLink(writer, atom,
nullptr,
"images/used-in-examples/" + link);
429 writer.writeStartElement(
"footnote");
433 writer.writeEndElement();
437 writer.writeEndElement();
440 writer.writeStartElement(
"raw");
441 writer.writeAttribute(
"format", atom->string());
445 writer.writeStartElement(
"bold");
447 writer.writeStartElement(
"italic");
449 writer.writeStartElement(
"underline");
451 writer.writeStartElement(
"subscript");
453 writer.writeStartElement(
"superscript");
455 writer.writeStartElement(
"teletype");
457 writer.writeStartElement(
"argument");
459 writer.writeStartElement(
"index");
464 writer.writeEndElement();
466 writer.writeEndElement();
468 writer.writeEndElement();
470 writer.writeEndElement();
472 writer.writeEndElement();
474 writer.writeEndElement();
476 writer.writeEndElement();
478 writer.writeEndElement();
480 writer.writeCharacters(QChar(0x2122));
483 writer.writeEndElement();
489 writer.writeStartElement(
"generatedlist");
490 writer.writeAttribute(
"contents", atom->string());
491 writer.writeEndElement();
502 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
503 if (!maybe_resolved_file) {
505 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
508 QString file_name{QFileInfo{file.get_path()}.fileName()};
512 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
514 writer.writeStartElement(atom->typeString().toLower());
515 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
517 writer.writeAttribute(
"href", imgPath);
518 writer.writeEndElement();
520 setImageFileName(relative, imgPath);
528 writer.writeStartElement(
"para");
529 writer.writeTextElement(
"bold",
"Important:");
530 writer.writeCharacters(
" ");
534 writer.writeStartElement(
"legalese");
538 writer.writeEndElement();
544 const Node *node =
nullptr;
545 QString link = getLink(atom, relative, &node);
547 startLink(writer, atom, node, link);
552 writer.writeStartElement(
"list");
555 writer.writeAttribute(
"type",
"bullet");
557 writer.writeAttribute(
"type",
"definition");
560 writer.writeAttribute(
"type",
"enum");
562 writer.writeAttribute(
"type",
"definition");
564 writer.writeAttribute(
"type",
"ordered");
566 writer.writeAttribute(
"start",
"A");
568 writer.writeAttribute(
"start",
"a");
570 writer.writeAttribute(
"start",
"I");
572 writer.writeAttribute(
"start",
"i");
574 writer.writeAttribute(
"start", atom
->next()->string());
576 writer.writeAttribute(
"start",
"1");
583 writer.writeStartElement(
"definition");
585 writer.writeTextElement(
586 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
590 writer.writeEndElement();
594 writer.writeStartElement(
"item");
598 writer.writeEndElement();
602 writer.writeEndElement();
606 writer.writeStartElement(
"para");
607 writer.writeTextElement(
"bold",
"Note:");
608 writer.writeCharacters(
" ");
615 writer.writeEndElement();
623 writer.writeStartElement(
"para");
628 writer.writeEndElement();
632 writer.writeStartElement(
"quote");
636 writer.writeEndElement();
640 writer.writeCharacters(atom->string());
644 writer.writeStartElement(
"section");
645 writer.writeAttribute(
"id",
650 writer.writeEndElement();
654 writer.writeStartElement(
"heading");
655 int unit = atom->string().toInt();
656 writer.writeAttribute(
"level", QString::number(unit));
657 m_inSectionHeading =
true;
661 writer.writeEndElement();
662 m_inSectionHeading =
false;
671 writer.writeStartElement(atom->string());
677 writer.writeAttribute(
"identifier", atom->string());
678 writer.writeEndElement();
685 const QString &location = atom->string();
686 writer.writeAttribute(
"location", location);
687 auto maybe_resolved_file{file_resolver.resolve(location)};
689 if (maybe_resolved_file)
690 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
693 QString details =
std::transform_reduce(
694 file_resolver.get_search_directories().cbegin(),
695 file_resolver.get_search_directories().cend(),
696 u"Searched directories:"_s,
698 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
701 relative
->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
707 writer.writeCharacters(atom->string());
710 writer.writeStartElement(
"table");
711 if (atom->string().contains(
"%"))
712 writer.writeAttribute(
"width", atom->string());
716 writer.writeEndElement();
720 writer.writeStartElement(
"header");
724 writer.writeEndElement();
728 writer.writeStartElement(
"row");
732 writer.writeEndElement();
736 writer.writeStartElement(
"item");
737 QStringList spans = atom->string().split(
",");
738 if (spans.size() == 2) {
739 if (spans.at(0) !=
"1")
740 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
741 if (spans.at(1) !=
"1")
742 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
746 writer.writeEndElement();
751 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
756 writer.writeStartElement(
"target");
757 writer.writeAttribute(
"name", TextUtils::asAsciiPrintable(atom->string()));
758 writer.writeEndElement();
762 writer.writeStartElement(
"para");
763 writer.writeTextElement(
"bold",
"Warning:");
764 writer.writeCharacters(
" ");
769 writer.writeCharacters(atom->typeString());
775 m_hasQuotingInformation = keepQuoting;
782 QString fullName = link;
784 fullName = node->fullName();
785 if (!fullName.isEmpty() && !link.isEmpty()) {
786 writer.writeStartElement(
"link");
787 if (atom && !atom->string().isEmpty())
788 writer.writeAttribute(
"raw", atom->string());
790 writer.writeAttribute(
"raw", fullName);
791 writer.writeAttribute(
"href", link);
792 writer.writeAttribute(
"type", targetType(node));
796 writer.writeAttribute(
"enum", fullName);
799 const auto *en =
static_cast<
const ExampleNode *>(node);
800 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
801 if (!fileTitle.isEmpty()) {
802 writer.writeAttribute(
"page", fileTitle);
808 writer.writeAttribute(
"page", fullName);
811 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
812 if (!propertyNode->getters().empty())
813 writer.writeAttribute(
"getter", propertyNode->getters().at(0)->fullName());
826 writer.writeEndElement();
833 if (node && !node->links().empty()) {
834 std::pair<QString, QString> anchorPair;
835 const Node *linkNode;
837 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
839 linkNode = m_qdb->findNodeForTarget(it.value().first, node);
844 if (linkNode == node)
845 anchorPair = it.value();
847 anchorPair = anchorForNode(linkNode);
849 writer.writeStartElement(
"relation");
850 writer.writeAttribute(
"href", anchorPair.first);
851 writer.writeAttribute(
"type", targetType(linkNode));
854 case Node::StartLink:
855 writer.writeAttribute(
"meta",
"start");
858 writer.writeAttribute(
"meta",
"next");
860 case Node::PreviousLink:
861 writer.writeAttribute(
"meta",
"previous");
863 case Node::ContentsLink:
864 writer.writeAttribute(
"meta",
"contents");
867 writer.writeAttribute(
"meta",
"");
869 writer.writeAttribute(
"description", anchorPair.second);
870 writer.writeEndElement();
878 generateAnnotatedList(writer, relative, nodeMap.values());
884 writer.writeStartElement(
"table");
885 writer.writeAttribute(
"width",
"100%");
887 for (
const auto *node : nodeList) {
888 writer.writeStartElement(
"row");
889 writer.writeStartElement(
"item");
890 writer.writeStartElement(
"para");
891 const QString link = linkForNode(node, relative);
892 startLink(writer, node->doc().body().firstAtom(), node, link);
894 writer.writeEndElement();
895 writer.writeEndElement();
897 writer.writeStartElement(
"item");
898 writer.writeStartElement(
"para");
899 writer.writeCharacters(node->doc().briefText().toString());
900 writer.writeEndElement();
901 writer.writeEndElement();
902 writer.writeEndElement();
904 writer.writeEndElement();
909 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
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 handles qdoc index files.
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
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.
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_