18#include <QtCore/qxmlstream.h>
22using namespace Qt::StringLiterals;
53
54
55
56
59 if (m_supplement && currentWriter)
67 QXmlStreamWriter writer(&data);
68 writer.setAutoFormatting(
true);
69 beginSubPage(aggregate, Generator::fileName(aggregate,
"webxml"));
70 writer.writeStartDocument();
71 writer.writeStartElement(
"WebXML");
72 writer.writeStartElement(
"document");
76 writer.writeEndElement();
77 writer.writeEndElement();
78 writer.writeEndDocument();
87 currentWriter.emplace(&data);
88 currentWriter->setAutoFormatting(
true);
89 beginSubPage(pn, Generator::fileName(pn,
"webxml"));
90 currentWriter->writeStartDocument();
91 currentWriter->writeStartElement(
"WebXML");
92 currentWriter->writeStartElement(
"document");
96 currentWriter->writeEndElement();
97 currentWriter->writeEndElement();
98 currentWriter->writeEndDocument();
109 QXmlStreamWriter writer(&data);
110 writer.setAutoFormatting(
true);
111 beginSubPage(en, linkForExampleFile(resolved_file.get_query(),
"webxml"));
112 writer.writeStartDocument();
113 writer.writeStartElement(
"WebXML");
114 writer.writeStartElement(
"document");
115 writer.writeStartElement(
"page");
116 writer.writeAttribute(
"name", resolved_file.get_query());
117 writer.writeAttribute(
"href", linkForExampleFile(resolved_file.get_query()));
118 const QString title = exampleFileTitle(
static_cast<
const ExampleNode *>(en), resolved_file.get_query());
119 writer.writeAttribute(
"title", title);
120 writer.writeAttribute(
"fulltitle", title);
121 writer.writeAttribute(
"subtitle", resolved_file.get_query());
122 writer.writeStartElement(
"description");
125 writer.writeAttribute(
"path", resolved_file.get_path());
126 writer.writeAttribute(
"line",
"0");
127 writer.writeAttribute(
"column",
"0");
132 QString code = quoter.quoteTo(en
->location(), QString(), QString());
133 writer.writeTextElement(
"code", trimmedTrailing(code, QString(), QString()));
135 writer.writeEndElement();
136 writer.writeEndElement();
137 writer.writeEndElement();
138 writer.writeEndElement();
139 writer.writeEndDocument();
149 if (qdocIndexFiles) {
150 qdocIndexFiles->generateIndexSections(writer, node,
this,
this);
153 std::ignore = qdocIndexFiles->generateIndexSection(writer, node,
this,
this);
162 writer.writeStartElement(
"description");
165 writer.writeAttribute(
"line", QString::number(node->doc().location().lineNo()));
166 writer.writeAttribute(
"column", QString::number(node->doc().location().columnNo()));
170 generateRelations(writer, node);
173 writer.writeStartElement(
"generatedlist");
174 writer.writeAttribute(
"contents",
"classesbymodule");
175 auto *cnn =
static_cast<CollectionNode *>(node);
177 if (cnn->hasNamespaces()) {
178 writer.writeStartElement(
"section");
179 writer.writeStartElement(
"heading");
180 writer.writeAttribute(
"level",
"1");
181 writer.writeCharacters(
"Namespaces");
182 writer.writeEndElement();
184 generateAnnotatedList(writer, node, namespaces);
185 writer.writeEndElement();
187 if (cnn->hasClasses()) {
188 writer.writeStartElement(
"section");
189 writer.writeStartElement(
"heading");
190 writer.writeAttribute(
"level",
"1");
191 writer.writeCharacters(
"Classes");
192 writer.writeEndElement();
194 generateAnnotatedList(writer, node, classes);
195 writer.writeEndElement();
197 writer.writeEndElement();
200 m_inLink = m_inSectionHeading = m_hasQuotingInformation =
false;
206 QList<Text> alsoList = node
->doc().alsoList();
207 supplementAlsoList(node, alsoList);
209 if (!alsoList.isEmpty()) {
210 writer.writeStartElement(
"see-also");
211 for (
const auto &item : alsoList) {
212 const auto *atom = item.firstAtom();
214 atom = addAtomElements(writer, atom, node, marker_);
216 writer.writeEndElement();
222 m_supplement =
false;
224 auto *cn =
static_cast<CollectionNode *>(node);
225 if (!cn->noAutoList())
226 generateAnnotatedList(writer, node, cn->members());
229 writer.writeEndElement();
239 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
250 m_qdb->mergeCollections(
static_cast<CollectionNode *>(node));
259 auto *aggregate =
static_cast<Aggregate *>(node);
260 for (
auto c : aggregate->childNodes()) {
261 if ((c->isAggregate() || c->isTextPageNode() || c->isCollectionNode())
263 generateDocumentation(c);
271 bool keepQuoting =
false;
278 const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group);
280 generateAnnotatedList(writer, relative, cn
->members());
283 const Node *node{
nullptr};
286 if (!m_inLink && !m_inSectionHeading) {
287 link = getAutoLink(atom, relative, &node, Genus::API);
295 startLink(writer, atom, node, link);
297 writer.writeCharacters(atom->string());
300 writer.writeEndElement();
310 writer.writeStartElement(
"brief");
313 writer.writeCharacters(
"This property");
316 writer.writeCharacters(
"This variable");
329 str[0] = str[0].toLower();
330 if (str.endsWith(
'.'))
333 const QList<QStringView> words = QStringView{str}.split(
' ');
334 if (!words.isEmpty()) {
335 QStringView first(words.at(0));
336 if (!(first == u"contains" || first == u"specifies" || first == u"describes"
337 || first == u"defines" || first == u"holds" || first == u"determines"))
338 writer.writeCharacters(
" holds ");
340 writer.writeCharacters(
" ");
347 writer.writeCharacters(
".");
349 writer.writeEndElement();
353 writer.writeStartElement(
"teletype");
355 writer.writeAttribute(
"type",
"normal");
357 writer.writeAttribute(
"type",
"highlighted");
359 writer.writeCharacters(plainCode(atom->string()));
360 writer.writeEndElement();
364 if (!m_hasQuotingInformation)
365 writer.writeTextElement(
366 "code", trimmedTrailing(plainCode(atom->string()), QString(), QString()));
372 writer.writeTextElement(
"badcode",
373 trimmedTrailing(plainCode(atom->string()), QString(), QString()));
378 if (quoteCommand ==
"dots") {
379 writer.writeAttribute(
"indent", atom->string());
380 writer.writeCharacters(
"...");
382 writer.writeCharacters(atom->string());
384 writer.writeEndElement();
391 quoteCommand = atom->string();
392 writer.writeStartElement(quoteCommand);
404 QString link = linkForExampleFile(atom->string());
406 startLink(writer, atom, relative, link);
412 QString link = atom->string();
414 startLink(writer, atom,
nullptr,
"images/used-in-examples/" + link);
419 writer.writeStartElement(
"footnote");
423 writer.writeEndElement();
427 writer.writeEndElement();
430 writer.writeStartElement(
"raw");
431 writer.writeAttribute(
"format", atom->string());
435 writer.writeStartElement(
"bold");
437 writer.writeStartElement(
"italic");
439 writer.writeStartElement(
"underline");
441 writer.writeStartElement(
"subscript");
443 writer.writeStartElement(
"superscript");
445 writer.writeStartElement(
"teletype");
447 writer.writeStartElement(
"argument");
449 writer.writeStartElement(
"index");
454 writer.writeEndElement();
456 writer.writeEndElement();
458 writer.writeEndElement();
460 writer.writeEndElement();
462 writer.writeEndElement();
464 writer.writeEndElement();
466 writer.writeEndElement();
468 writer.writeEndElement();
470 writer.writeCharacters(QChar(0x2122));
473 writer.writeEndElement();
479 writer.writeStartElement(
"generatedlist");
480 writer.writeAttribute(
"contents", atom->string());
481 writer.writeEndElement();
492 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
493 if (!maybe_resolved_file) {
495 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
498 QString file_name{QFileInfo{file.get_path()}.fileName()};
502 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
504 writer.writeStartElement(atom->typeString().toLower());
505 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
507 writer.writeAttribute(
"href", imgPath);
508 writer.writeEndElement();
510 setImageFileName(relative, imgPath);
518 writer.writeStartElement(
"para");
519 writer.writeTextElement(
"bold",
"Important:");
520 writer.writeCharacters(
" ");
524 writer.writeStartElement(
"legalese");
528 writer.writeEndElement();
534 const Node *node =
nullptr;
535 QString link = getLink(atom, relative, &node);
537 startLink(writer, atom, node, link);
542 writer.writeStartElement(
"list");
545 writer.writeAttribute(
"type",
"bullet");
547 writer.writeAttribute(
"type",
"definition");
550 writer.writeAttribute(
"type",
"enum");
552 writer.writeAttribute(
"type",
"definition");
554 writer.writeAttribute(
"type",
"ordered");
556 writer.writeAttribute(
"start",
"A");
558 writer.writeAttribute(
"start",
"a");
560 writer.writeAttribute(
"start",
"I");
562 writer.writeAttribute(
"start",
"i");
564 writer.writeAttribute(
"start", atom
->next()->string());
566 writer.writeAttribute(
"start",
"1");
573 writer.writeStartElement(
"definition");
575 writer.writeTextElement(
576 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
580 writer.writeEndElement();
584 writer.writeStartElement(
"item");
588 writer.writeEndElement();
592 writer.writeEndElement();
596 writer.writeStartElement(
"para");
597 writer.writeTextElement(
"bold",
"Note:");
598 writer.writeCharacters(
" ");
605 writer.writeEndElement();
613 writer.writeStartElement(
"para");
618 writer.writeEndElement();
622 writer.writeStartElement(
"quote");
626 writer.writeEndElement();
630 writer.writeCharacters(atom->string());
634 writer.writeStartElement(
"section");
635 writer.writeAttribute(
"id",
640 writer.writeEndElement();
644 writer.writeStartElement(
"heading");
645 int unit = atom->string().toInt();
646 writer.writeAttribute(
"level", QString::number(unit));
647 m_inSectionHeading =
true;
651 writer.writeEndElement();
652 m_inSectionHeading =
false;
661 writer.writeStartElement(atom->string());
667 writer.writeAttribute(
"identifier", atom->string());
668 writer.writeEndElement();
675 const QString &location = atom->string();
676 writer.writeAttribute(
"location", location);
677 auto maybe_resolved_file{file_resolver.resolve(location)};
679 if (maybe_resolved_file)
680 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
683 QString details =
std::transform_reduce(
684 file_resolver.get_search_directories().cbegin(),
685 file_resolver.get_search_directories().cend(),
686 u"Searched directories:"_s,
688 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
691 relative
->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
697 writer.writeCharacters(atom->string());
700 writer.writeStartElement(
"table");
701 if (atom->string().contains(
"%"))
702 writer.writeAttribute(
"width", atom->string());
706 writer.writeEndElement();
710 writer.writeStartElement(
"header");
714 writer.writeEndElement();
718 writer.writeStartElement(
"row");
722 writer.writeEndElement();
726 writer.writeStartElement(
"item");
727 QStringList spans = atom->string().split(
",");
728 if (spans.size() == 2) {
729 if (spans.at(0) !=
"1")
730 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
731 if (spans.at(1) !=
"1")
732 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
736 writer.writeEndElement();
741 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
746 writer.writeStartElement(
"target");
747 writer.writeAttribute(
"name", Utilities::asAsciiPrintable(atom->string()));
748 writer.writeEndElement();
752 writer.writeStartElement(
"para");
753 writer.writeTextElement(
"bold",
"Warning:");
754 writer.writeCharacters(
" ");
759 writer.writeCharacters(atom->typeString());
765 m_hasQuotingInformation = keepQuoting;
772 QString fullName = link;
774 fullName = node->fullName();
775 if (!fullName.isEmpty() && !link.isEmpty()) {
776 writer.writeStartElement(
"link");
777 if (atom && !atom->string().isEmpty())
778 writer.writeAttribute(
"raw", atom->string());
780 writer.writeAttribute(
"raw", fullName);
781 writer.writeAttribute(
"href", link);
782 writer.writeAttribute(
"type", targetType(node));
786 writer.writeAttribute(
"enum", fullName);
789 const auto *en =
static_cast<
const ExampleNode *>(node);
790 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
791 if (!fileTitle.isEmpty()) {
792 writer.writeAttribute(
"page", fileTitle);
798 writer.writeAttribute(
"page", fullName);
801 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
802 if (!propertyNode->getters().empty())
803 writer.writeAttribute(
"getter", propertyNode->getters().at(0)->fullName());
816 writer.writeEndElement();
823 if (node && !node->links().empty()) {
824 std::pair<QString, QString> anchorPair;
825 const Node *linkNode;
827 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
829 linkNode = m_qdb->findNodeForTarget(it.value().first, node);
834 if (linkNode == node)
835 anchorPair = it.value();
837 anchorPair = anchorForNode(linkNode);
839 writer.writeStartElement(
"relation");
840 writer.writeAttribute(
"href", anchorPair.first);
841 writer.writeAttribute(
"type", targetType(linkNode));
844 case Node::StartLink:
845 writer.writeAttribute(
"meta",
"start");
848 writer.writeAttribute(
"meta",
"next");
850 case Node::PreviousLink:
851 writer.writeAttribute(
"meta",
"previous");
853 case Node::ContentsLink:
854 writer.writeAttribute(
"meta",
"contents");
857 writer.writeAttribute(
"meta",
"");
859 writer.writeAttribute(
"description", anchorPair.second);
860 writer.writeEndElement();
868 generateAnnotatedList(writer, relative, nodeMap.values());
874 writer.writeStartElement(
"table");
875 writer.writeAttribute(
"width",
"100%");
877 for (
const auto *node : nodeList) {
878 writer.writeStartElement(
"row");
879 writer.writeStartElement(
"item");
880 writer.writeStartElement(
"para");
881 const QString link = linkForNode(node, relative);
882 startLink(writer, node->doc().body().firstAtom(), node, link);
884 writer.writeEndElement();
885 writer.writeEndElement();
887 writer.writeStartElement(
"item");
888 writer.writeStartElement(
"para");
889 writer.writeCharacters(node->doc().briefText().toString());
890 writer.writeEndElement();
891 writer.writeEndElement();
892 writer.writeEndElement();
894 writer.writeEndElement();
899 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.
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.
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_