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);
398 QString link = linkForExampleFile(atom->string());
400 startLink(writer, atom, relative, link);
406 QString link = atom->string();
408 startLink(writer, atom,
nullptr,
"images/used-in-examples/" + link);
413 writer.writeStartElement(
"footnote");
417 writer.writeEndElement();
421 writer.writeEndElement();
424 writer.writeStartElement(
"raw");
425 writer.writeAttribute(
"format", atom->string());
429 writer.writeStartElement(
"bold");
431 writer.writeStartElement(
"italic");
433 writer.writeStartElement(
"underline");
435 writer.writeStartElement(
"subscript");
437 writer.writeStartElement(
"superscript");
439 writer.writeStartElement(
"teletype");
441 writer.writeStartElement(
"argument");
443 writer.writeStartElement(
"index");
448 writer.writeEndElement();
450 writer.writeEndElement();
452 writer.writeEndElement();
454 writer.writeEndElement();
456 writer.writeEndElement();
458 writer.writeEndElement();
460 writer.writeEndElement();
462 writer.writeEndElement();
464 writer.writeCharacters(QChar(0x2122));
467 writer.writeEndElement();
473 writer.writeStartElement(
"generatedlist");
474 writer.writeAttribute(
"contents", atom->string());
475 writer.writeEndElement();
486 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
487 if (!maybe_resolved_file) {
489 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
492 QString file_name{QFileInfo{file.get_path()}.fileName()};
496 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
498 writer.writeStartElement(atom->typeString().toLower());
499 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
501 writer.writeAttribute(
"href", imgPath);
502 writer.writeEndElement();
504 setImageFileName(relative, imgPath);
512 writer.writeStartElement(
"para");
513 writer.writeTextElement(
"bold",
"Important:");
514 writer.writeCharacters(
" ");
518 writer.writeStartElement(
"legalese");
522 writer.writeEndElement();
528 const Node *node =
nullptr;
529 QString link = getLink(atom, relative, &node);
531 startLink(writer, atom, node, link);
536 writer.writeStartElement(
"list");
539 writer.writeAttribute(
"type",
"bullet");
541 writer.writeAttribute(
"type",
"definition");
544 writer.writeAttribute(
"type",
"enum");
546 writer.writeAttribute(
"type",
"definition");
548 writer.writeAttribute(
"type",
"ordered");
550 writer.writeAttribute(
"start",
"A");
552 writer.writeAttribute(
"start",
"a");
554 writer.writeAttribute(
"start",
"I");
556 writer.writeAttribute(
"start",
"i");
558 writer.writeAttribute(
"start", atom
->next()->string());
560 writer.writeAttribute(
"start",
"1");
567 writer.writeStartElement(
"definition");
569 writer.writeTextElement(
570 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
574 writer.writeEndElement();
578 writer.writeStartElement(
"item");
582 writer.writeEndElement();
586 writer.writeEndElement();
590 writer.writeStartElement(
"para");
591 writer.writeTextElement(
"bold",
"Note:");
592 writer.writeCharacters(
" ");
599 writer.writeEndElement();
607 writer.writeStartElement(
"para");
612 writer.writeEndElement();
616 writer.writeStartElement(
"quote");
620 writer.writeEndElement();
624 writer.writeCharacters(atom->string());
628 writer.writeStartElement(
"section");
629 writer.writeAttribute(
"id",
634 writer.writeEndElement();
638 writer.writeStartElement(
"heading");
639 int unit = atom->string().toInt();
640 writer.writeAttribute(
"level", QString::number(unit));
641 m_inSectionHeading =
true;
645 writer.writeEndElement();
646 m_inSectionHeading =
false;
655 writer.writeStartElement(atom->string());
661 writer.writeAttribute(
"identifier", atom->string());
662 writer.writeEndElement();
669 const QString &location = atom->string();
670 writer.writeAttribute(
"location", location);
671 auto maybe_resolved_file{file_resolver.resolve(location)};
673 if (maybe_resolved_file)
674 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
677 QString details =
std::transform_reduce(
678 file_resolver.get_search_directories().cbegin(),
679 file_resolver.get_search_directories().cend(),
680 u"Searched directories:"_s,
682 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
685 relative
->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
691 writer.writeCharacters(atom->string());
694 writer.writeStartElement(
"table");
695 if (atom->string().contains(
"%"))
696 writer.writeAttribute(
"width", atom->string());
700 writer.writeEndElement();
704 writer.writeStartElement(
"header");
708 writer.writeEndElement();
712 writer.writeStartElement(
"row");
716 writer.writeEndElement();
720 writer.writeStartElement(
"item");
721 QStringList spans = atom->string().split(
",");
722 if (spans.size() == 2) {
723 if (spans.at(0) !=
"1")
724 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
725 if (spans.at(1) !=
"1")
726 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
730 writer.writeEndElement();
735 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
740 writer.writeStartElement(
"target");
741 writer.writeAttribute(
"name", Utilities::asAsciiPrintable(atom->string()));
742 writer.writeEndElement();
746 writer.writeStartElement(
"para");
747 writer.writeTextElement(
"bold",
"Warning:");
748 writer.writeCharacters(
" ");
753 writer.writeCharacters(atom->typeString());
759 m_hasQuotingInformation = keepQuoting;
766 QString fullName = link;
768 fullName = node->fullName();
769 if (!fullName.isEmpty() && !link.isEmpty()) {
770 writer.writeStartElement(
"link");
771 if (atom && !atom->string().isEmpty())
772 writer.writeAttribute(
"raw", atom->string());
774 writer.writeAttribute(
"raw", fullName);
775 writer.writeAttribute(
"href", link);
776 writer.writeAttribute(
"type", targetType(node));
780 writer.writeAttribute(
"enum", fullName);
783 const auto *en =
static_cast<
const ExampleNode *>(node);
784 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
785 if (!fileTitle.isEmpty()) {
786 writer.writeAttribute(
"page", fileTitle);
792 writer.writeAttribute(
"page", fullName);
795 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
796 if (!propertyNode->getters().empty())
797 writer.writeAttribute(
"getter", propertyNode->getters().at(0)->fullName());
810 writer.writeEndElement();
817 if (node && !node->links().empty()) {
818 std::pair<QString, QString> anchorPair;
819 const Node *linkNode;
821 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
823 linkNode = m_qdb->findNodeForTarget(it.value().first, node);
828 if (linkNode == node)
829 anchorPair = it.value();
831 anchorPair = anchorForNode(linkNode);
833 writer.writeStartElement(
"relation");
834 writer.writeAttribute(
"href", anchorPair.first);
835 writer.writeAttribute(
"type", targetType(linkNode));
838 case Node::StartLink:
839 writer.writeAttribute(
"meta",
"start");
842 writer.writeAttribute(
"meta",
"next");
844 case Node::PreviousLink:
845 writer.writeAttribute(
"meta",
"previous");
847 case Node::ContentsLink:
848 writer.writeAttribute(
"meta",
"contents");
851 writer.writeAttribute(
"meta",
"");
853 writer.writeAttribute(
"description", anchorPair.second);
854 writer.writeEndElement();
862 generateAnnotatedList(writer, relative, nodeMap.values());
868 writer.writeStartElement(
"table");
869 writer.writeAttribute(
"width",
"100%");
871 for (
const auto *node : nodeList) {
872 writer.writeStartElement(
"row");
873 writer.writeStartElement(
"item");
874 writer.writeStartElement(
"para");
875 const QString link = linkForNode(node, relative);
876 startLink(writer, node->doc().body().firstAtom(), node, link);
878 writer.writeEndElement();
879 writer.writeEndElement();
881 writer.writeStartElement(
"item");
882 writer.writeStartElement(
"para");
883 writer.writeCharacters(node->doc().briefText().toString());
884 writer.writeEndElement();
885 writer.writeEndElement();
886 writer.writeEndElement();
888 writer.writeEndElement();
893 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)
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 generateExampleFilePage(const Node *en, ResolvedFile file, CodeMarker *marker=nullptr) override
Generate an html file with the contents of a C++ or QML source file.
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 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_