19#include <QtCore/qxmlstream.h>
23using namespace Qt::StringLiterals;
54
55
56
57
60 if (m_supplement && currentWriter)
68 QXmlStreamWriter writer(&data);
69 writer.setAutoFormatting(
true);
70 beginSubPage(aggregate, Generator::fileName(aggregate,
"webxml"));
71 writer.writeStartDocument();
72 writer.writeStartElement(
"WebXML");
73 writer.writeStartElement(
"document");
77 writer.writeEndElement();
78 writer.writeEndElement();
79 writer.writeEndDocument();
88 currentWriter.emplace(&data);
89 currentWriter->setAutoFormatting(
true);
90 beginSubPage(pn, Generator::fileName(pn,
"webxml"));
91 currentWriter->writeStartDocument();
92 currentWriter->writeStartElement(
"WebXML");
93 currentWriter->writeStartElement(
"document");
97 currentWriter->writeEndElement();
98 currentWriter->writeEndElement();
99 currentWriter->writeEndDocument();
110 QXmlStreamWriter writer(&data);
111 writer.setAutoFormatting(
true);
112 beginSubPage(en, linkForExampleFile(resolved_file.get_query(),
"webxml"));
113 writer.writeStartDocument();
114 writer.writeStartElement(
"WebXML");
115 writer.writeStartElement(
"document");
116 writer.writeStartElement(
"page");
117 writer.writeAttribute(
"name", resolved_file.get_query());
118 writer.writeAttribute(
"href", linkForExampleFile(resolved_file.get_query()));
119 const QString title = exampleFileTitle(
static_cast<
const ExampleNode *>(en), resolved_file.get_query());
120 writer.writeAttribute(
"title", title);
121 writer.writeAttribute(
"fulltitle", title);
122 writer.writeAttribute(
"subtitle", resolved_file.get_query());
123 writer.writeStartElement(
"description");
126 writer.writeAttribute(
"path", resolved_file.get_path());
127 writer.writeAttribute(
"line",
"0");
128 writer.writeAttribute(
"column",
"0");
133 QString code = quoter.quoteTo(en
->location(), QString(), QString());
134 writer.writeTextElement(
"code", trimmedTrailing(code, QString(), QString()));
136 writer.writeEndElement();
137 writer.writeEndElement();
138 writer.writeEndElement();
139 writer.writeEndElement();
140 writer.writeEndDocument();
150 if (qdocIndexFiles) {
151 qdocIndexFiles->generateIndexSections(writer, node,
this,
this);
157 std::ignore = qdocIndexFiles->generateIndexSection(writer, node,
this,
this);
171 writer.writeStartElement(
"description");
173 writer.writeAttribute(
"path", effectiveDoc
.location().filePath());
174 writer.writeAttribute(
"line", QString::number(effectiveDoc.location().lineNo()));
175 writer.writeAttribute(
"column", QString::number(effectiveDoc.location().columnNo()));
179 generateRelations(writer, node);
182 writer.writeStartElement(
"generatedlist");
183 writer.writeAttribute(
"contents",
"classesbymodule");
184 auto *cnn =
static_cast<CollectionNode *>(node);
186 if (cnn->hasNamespaces()) {
187 writer.writeStartElement(
"section");
188 writer.writeStartElement(
"heading");
189 writer.writeAttribute(
"level",
"1");
190 writer.writeCharacters(
"Namespaces");
191 writer.writeEndElement();
193 generateAnnotatedList(writer, node, namespaces);
194 writer.writeEndElement();
196 if (cnn->hasClasses()) {
197 writer.writeStartElement(
"section");
198 writer.writeStartElement(
"heading");
199 writer.writeAttribute(
"level",
"1");
200 writer.writeCharacters(
"Classes");
201 writer.writeEndElement();
203 generateAnnotatedList(writer, node, classes);
204 writer.writeEndElement();
206 writer.writeEndElement();
209 m_inLink = m_inSectionHeading = m_hasQuotingInformation =
false;
215 QList<Text> alsoList = effectiveDoc.alsoList();
216 supplementAlsoList(node, alsoList);
218 if (!alsoList.isEmpty()) {
219 writer.writeStartElement(
"see-also");
220 for (
const auto &item : alsoList) {
221 const auto *atom = item.firstAtom();
223 atom = addAtomElements(writer, atom, node, marker_);
225 writer.writeEndElement();
231 m_supplement =
false;
233 auto *cn =
static_cast<CollectionNode *>(node);
234 if (!cn->noAutoList())
235 generateAnnotatedList(writer, node, cn->members());
238 writer.writeEndElement();
248 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
259 m_qdb->mergeCollections(
static_cast<CollectionNode *>(node));
268 auto *aggregate =
static_cast<Aggregate *>(node);
269 for (
auto c : aggregate->childNodes()) {
270 if ((c->isAggregate() || c->isTextPageNode() || c->isCollectionNode())
272 generateDocumentation(c);
280 bool keepQuoting =
false;
287 const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group);
289 generateAnnotatedList(writer, relative, cn
->members());
292 const Node *node{
nullptr};
295 if (!m_inLink && !m_inSectionHeading) {
296 link = getAutoLink(atom, relative, &node, Genus::API);
304 startLink(writer, atom, node, link);
306 writer.writeCharacters(atom->string());
309 writer.writeEndElement();
319 writer.writeStartElement(
"brief");
322 writer.writeCharacters(
"This property");
325 writer.writeCharacters(
"This variable");
338 str[0] = str[0].toLower();
339 if (str.endsWith(
'.'))
342 const QList<QStringView> words = QStringView{str}.split(
' ');
343 if (!words.isEmpty()) {
344 QStringView first(words.at(0));
345 if (!(first == u"contains" || first == u"specifies" || first == u"describes"
346 || first == u"defines" || first == u"holds" || first == u"determines"))
347 writer.writeCharacters(
" holds ");
349 writer.writeCharacters(
" ");
356 writer.writeCharacters(
".");
358 writer.writeEndElement();
362 writer.writeStartElement(
"teletype");
364 writer.writeAttribute(
"type",
"normal");
366 writer.writeAttribute(
"type",
"highlighted");
368 writer.writeCharacters(plainCode(atom->string()));
369 writer.writeEndElement();
373 if (!m_hasQuotingInformation)
374 writer.writeTextElement(
375 "code", trimmedTrailing(plainCode(atom->string()), QString(), QString()));
381 writer.writeTextElement(
"badcode",
382 trimmedTrailing(plainCode(atom->string()), QString(), QString()));
387 if (quoteCommand ==
"dots") {
388 writer.writeAttribute(
"indent", atom->string());
389 writer.writeCharacters(
"...");
391 writer.writeCharacters(atom->string());
393 writer.writeEndElement();
400 quoteCommand = atom->string();
401 writer.writeStartElement(quoteCommand);
413 QString link = linkForExampleFile(atom->string());
415 startLink(writer, atom, relative, link);
421 QString link = atom->string();
423 startLink(writer, atom,
nullptr,
"images/used-in-examples/" + link);
428 writer.writeStartElement(
"footnote");
432 writer.writeEndElement();
436 writer.writeEndElement();
439 writer.writeStartElement(
"raw");
440 writer.writeAttribute(
"format", atom->string());
444 writer.writeStartElement(
"bold");
446 writer.writeStartElement(
"italic");
448 writer.writeStartElement(
"underline");
450 writer.writeStartElement(
"subscript");
452 writer.writeStartElement(
"superscript");
454 writer.writeStartElement(
"teletype");
456 writer.writeStartElement(
"argument");
458 writer.writeStartElement(
"index");
463 writer.writeEndElement();
465 writer.writeEndElement();
467 writer.writeEndElement();
469 writer.writeEndElement();
471 writer.writeEndElement();
473 writer.writeEndElement();
475 writer.writeEndElement();
477 writer.writeEndElement();
479 writer.writeCharacters(QChar(0x2122));
482 writer.writeEndElement();
488 writer.writeStartElement(
"generatedlist");
489 writer.writeAttribute(
"contents", atom->string());
490 writer.writeEndElement();
501 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
502 if (!maybe_resolved_file) {
504 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
507 QString file_name{QFileInfo{file.get_path()}.fileName()};
511 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
513 writer.writeStartElement(atom->typeString().toLower());
514 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
516 writer.writeAttribute(
"href", imgPath);
517 writer.writeEndElement();
519 setImageFileName(relative, imgPath);
527 writer.writeStartElement(
"para");
528 writer.writeTextElement(
"bold",
"Important:");
529 writer.writeCharacters(
" ");
533 writer.writeStartElement(
"legalese");
537 writer.writeEndElement();
543 const Node *node =
nullptr;
544 QString link = getLink(atom, relative, &node);
546 startLink(writer, atom, node, link);
551 writer.writeStartElement(
"list");
554 writer.writeAttribute(
"type",
"bullet");
556 writer.writeAttribute(
"type",
"definition");
559 writer.writeAttribute(
"type",
"enum");
561 writer.writeAttribute(
"type",
"definition");
563 writer.writeAttribute(
"type",
"ordered");
565 writer.writeAttribute(
"start",
"A");
567 writer.writeAttribute(
"start",
"a");
569 writer.writeAttribute(
"start",
"I");
571 writer.writeAttribute(
"start",
"i");
573 writer.writeAttribute(
"start", atom
->next()->string());
575 writer.writeAttribute(
"start",
"1");
582 writer.writeStartElement(
"definition");
584 writer.writeTextElement(
585 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
589 writer.writeEndElement();
593 writer.writeStartElement(
"item");
597 writer.writeEndElement();
601 writer.writeEndElement();
605 writer.writeStartElement(
"para");
606 writer.writeTextElement(
"bold",
"Note:");
607 writer.writeCharacters(
" ");
614 writer.writeEndElement();
622 writer.writeStartElement(
"para");
627 writer.writeEndElement();
631 writer.writeStartElement(
"quote");
635 writer.writeEndElement();
639 writer.writeCharacters(atom->string());
643 writer.writeStartElement(
"section");
644 writer.writeAttribute(
"id",
649 writer.writeEndElement();
653 writer.writeStartElement(
"heading");
654 int unit = atom->string().toInt();
655 writer.writeAttribute(
"level", QString::number(unit));
656 m_inSectionHeading =
true;
660 writer.writeEndElement();
661 m_inSectionHeading =
false;
670 writer.writeStartElement(atom->string());
676 writer.writeAttribute(
"identifier", atom->string());
677 writer.writeEndElement();
684 const QString &location = atom->string();
685 writer.writeAttribute(
"location", location);
686 auto maybe_resolved_file{file_resolver.resolve(location)};
688 if (maybe_resolved_file)
689 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
692 QString details =
std::transform_reduce(
693 file_resolver.get_search_directories().cbegin(),
694 file_resolver.get_search_directories().cend(),
695 u"Searched directories:"_s,
697 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
700 relative
->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
706 writer.writeCharacters(atom->string());
709 writer.writeStartElement(
"table");
710 if (atom->string().contains(
"%"))
711 writer.writeAttribute(
"width", atom->string());
715 writer.writeEndElement();
719 writer.writeStartElement(
"header");
723 writer.writeEndElement();
727 writer.writeStartElement(
"row");
731 writer.writeEndElement();
735 writer.writeStartElement(
"item");
736 QStringList spans = atom->string().split(
",");
737 if (spans.size() == 2) {
738 if (spans.at(0) !=
"1")
739 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
740 if (spans.at(1) !=
"1")
741 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
745 writer.writeEndElement();
750 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
755 writer.writeStartElement(
"target");
756 writer.writeAttribute(
"name", TextUtils::asAsciiPrintable(atom->string()));
757 writer.writeEndElement();
761 writer.writeStartElement(
"para");
762 writer.writeTextElement(
"bold",
"Warning:");
763 writer.writeCharacters(
" ");
768 writer.writeCharacters(atom->typeString());
774 m_hasQuotingInformation = keepQuoting;
781 QString fullName = link;
783 fullName = node->fullName();
784 if (!fullName.isEmpty() && !link.isEmpty()) {
785 writer.writeStartElement(
"link");
786 if (atom && !atom->string().isEmpty())
787 writer.writeAttribute(
"raw", atom->string());
789 writer.writeAttribute(
"raw", fullName);
790 writer.writeAttribute(
"href", link);
791 writer.writeAttribute(
"type", targetType(node));
795 writer.writeAttribute(
"enum", fullName);
798 const auto *en =
static_cast<
const ExampleNode *>(node);
799 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
800 if (!fileTitle.isEmpty()) {
801 writer.writeAttribute(
"page", fileTitle);
807 writer.writeAttribute(
"page", fullName);
810 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
811 if (!propertyNode->getters().empty())
812 writer.writeAttribute(
"getter", propertyNode->getters().at(0)->fullName());
825 writer.writeEndElement();
832 if (node && !node->links().empty()) {
833 std::pair<QString, QString> anchorPair;
834 const Node *linkNode;
836 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
838 linkNode = m_qdb->findNodeForTarget(it.value().first, node);
843 if (linkNode == node)
844 anchorPair = it.value();
846 anchorPair = anchorForNode(linkNode);
848 writer.writeStartElement(
"relation");
849 writer.writeAttribute(
"href", anchorPair.first);
850 writer.writeAttribute(
"type", targetType(linkNode));
853 case Node::StartLink:
854 writer.writeAttribute(
"meta",
"start");
857 writer.writeAttribute(
"meta",
"next");
859 case Node::PreviousLink:
860 writer.writeAttribute(
"meta",
"previous");
862 case Node::ContentsLink:
863 writer.writeAttribute(
"meta",
"contents");
866 writer.writeAttribute(
"meta",
"");
868 writer.writeAttribute(
"description", anchorPair.second);
869 writer.writeEndElement();
877 generateAnnotatedList(writer, relative, nodeMap.values());
883 writer.writeStartElement(
"table");
884 writer.writeAttribute(
"width",
"100%");
886 for (
const auto *node : nodeList) {
887 writer.writeStartElement(
"row");
888 writer.writeStartElement(
"item");
889 writer.writeStartElement(
"para");
890 const QString link = linkForNode(node, relative);
891 startLink(writer, node->doc().body().firstAtom(), node, link);
893 writer.writeEndElement();
894 writer.writeEndElement();
896 writer.writeStartElement(
"item");
897 writer.writeStartElement(
"para");
898 writer.writeCharacters(node->doc().briefText().toString());
899 writer.writeEndElement();
900 writer.writeEndElement();
901 writer.writeEndElement();
903 writer.writeEndElement();
908 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_