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);
166 writer.writeStartElement(
"description");
169 writer.writeAttribute(
"line", QString::number(node->doc().location().lineNo()));
170 writer.writeAttribute(
"column", QString::number(node->doc().location().columnNo()));
174 generateRelations(writer, node);
177 writer.writeStartElement(
"generatedlist");
178 writer.writeAttribute(
"contents",
"classesbymodule");
179 auto *cnn =
static_cast<CollectionNode *>(node);
181 if (cnn->hasNamespaces()) {
182 writer.writeStartElement(
"section");
183 writer.writeStartElement(
"heading");
184 writer.writeAttribute(
"level",
"1");
185 writer.writeCharacters(
"Namespaces");
186 writer.writeEndElement();
188 generateAnnotatedList(writer, node, namespaces);
189 writer.writeEndElement();
191 if (cnn->hasClasses()) {
192 writer.writeStartElement(
"section");
193 writer.writeStartElement(
"heading");
194 writer.writeAttribute(
"level",
"1");
195 writer.writeCharacters(
"Classes");
196 writer.writeEndElement();
198 generateAnnotatedList(writer, node, classes);
199 writer.writeEndElement();
201 writer.writeEndElement();
204 m_inLink = m_inSectionHeading = m_hasQuotingInformation =
false;
210 QList<Text> alsoList = node
->doc().alsoList();
211 supplementAlsoList(node, alsoList);
213 if (!alsoList.isEmpty()) {
214 writer.writeStartElement(
"see-also");
215 for (
const auto &item : alsoList) {
216 const auto *atom = item.firstAtom();
218 atom = addAtomElements(writer, atom, node, marker_);
220 writer.writeEndElement();
226 m_supplement =
false;
228 auto *cn =
static_cast<CollectionNode *>(node);
229 if (!cn->noAutoList())
230 generateAnnotatedList(writer, node, cn->members());
233 writer.writeEndElement();
243 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
254 m_qdb->mergeCollections(
static_cast<CollectionNode *>(node));
263 auto *aggregate =
static_cast<Aggregate *>(node);
264 for (
auto c : aggregate->childNodes()) {
265 if ((c->isAggregate() || c->isTextPageNode() || c->isCollectionNode())
267 generateDocumentation(c);
275 bool keepQuoting =
false;
282 const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group);
284 generateAnnotatedList(writer, relative, cn
->members());
287 const Node *node{
nullptr};
290 if (!m_inLink && !m_inSectionHeading) {
291 link = getAutoLink(atom, relative, &node, Genus::API);
299 startLink(writer, atom, node, link);
301 writer.writeCharacters(atom->string());
304 writer.writeEndElement();
314 writer.writeStartElement(
"brief");
317 writer.writeCharacters(
"This property");
320 writer.writeCharacters(
"This variable");
333 str[0] = str[0].toLower();
334 if (str.endsWith(
'.'))
337 const QList<QStringView> words = QStringView{str}.split(
' ');
338 if (!words.isEmpty()) {
339 QStringView first(words.at(0));
340 if (!(first == u"contains" || first == u"specifies" || first == u"describes"
341 || first == u"defines" || first == u"holds" || first == u"determines"))
342 writer.writeCharacters(
" holds ");
344 writer.writeCharacters(
" ");
351 writer.writeCharacters(
".");
353 writer.writeEndElement();
357 writer.writeStartElement(
"teletype");
359 writer.writeAttribute(
"type",
"normal");
361 writer.writeAttribute(
"type",
"highlighted");
363 writer.writeCharacters(plainCode(atom->string()));
364 writer.writeEndElement();
368 if (!m_hasQuotingInformation)
369 writer.writeTextElement(
370 "code", trimmedTrailing(plainCode(atom->string()), QString(), QString()));
376 writer.writeTextElement(
"badcode",
377 trimmedTrailing(plainCode(atom->string()), QString(), QString()));
382 if (quoteCommand ==
"dots") {
383 writer.writeAttribute(
"indent", atom->string());
384 writer.writeCharacters(
"...");
386 writer.writeCharacters(atom->string());
388 writer.writeEndElement();
395 quoteCommand = atom->string();
396 writer.writeStartElement(quoteCommand);
408 QString link = linkForExampleFile(atom->string());
410 startLink(writer, atom, relative, link);
416 QString link = atom->string();
418 startLink(writer, atom,
nullptr,
"images/used-in-examples/" + link);
423 writer.writeStartElement(
"footnote");
427 writer.writeEndElement();
431 writer.writeEndElement();
434 writer.writeStartElement(
"raw");
435 writer.writeAttribute(
"format", atom->string());
439 writer.writeStartElement(
"bold");
441 writer.writeStartElement(
"italic");
443 writer.writeStartElement(
"underline");
445 writer.writeStartElement(
"subscript");
447 writer.writeStartElement(
"superscript");
449 writer.writeStartElement(
"teletype");
451 writer.writeStartElement(
"argument");
453 writer.writeStartElement(
"index");
458 writer.writeEndElement();
460 writer.writeEndElement();
462 writer.writeEndElement();
464 writer.writeEndElement();
466 writer.writeEndElement();
468 writer.writeEndElement();
470 writer.writeEndElement();
472 writer.writeEndElement();
474 writer.writeCharacters(QChar(0x2122));
477 writer.writeEndElement();
483 writer.writeStartElement(
"generatedlist");
484 writer.writeAttribute(
"contents", atom->string());
485 writer.writeEndElement();
496 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
497 if (!maybe_resolved_file) {
499 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
502 QString file_name{QFileInfo{file.get_path()}.fileName()};
506 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
508 writer.writeStartElement(atom->typeString().toLower());
509 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
511 writer.writeAttribute(
"href", imgPath);
512 writer.writeEndElement();
514 setImageFileName(relative, imgPath);
522 writer.writeStartElement(
"para");
523 writer.writeTextElement(
"bold",
"Important:");
524 writer.writeCharacters(
" ");
528 writer.writeStartElement(
"legalese");
532 writer.writeEndElement();
538 const Node *node =
nullptr;
539 QString link = getLink(atom, relative, &node);
541 startLink(writer, atom, node, link);
546 writer.writeStartElement(
"list");
549 writer.writeAttribute(
"type",
"bullet");
551 writer.writeAttribute(
"type",
"definition");
554 writer.writeAttribute(
"type",
"enum");
556 writer.writeAttribute(
"type",
"definition");
558 writer.writeAttribute(
"type",
"ordered");
560 writer.writeAttribute(
"start",
"A");
562 writer.writeAttribute(
"start",
"a");
564 writer.writeAttribute(
"start",
"I");
566 writer.writeAttribute(
"start",
"i");
568 writer.writeAttribute(
"start", atom
->next()->string());
570 writer.writeAttribute(
"start",
"1");
577 writer.writeStartElement(
"definition");
579 writer.writeTextElement(
580 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
584 writer.writeEndElement();
588 writer.writeStartElement(
"item");
592 writer.writeEndElement();
596 writer.writeEndElement();
600 writer.writeStartElement(
"para");
601 writer.writeTextElement(
"bold",
"Note:");
602 writer.writeCharacters(
" ");
609 writer.writeEndElement();
617 writer.writeStartElement(
"para");
622 writer.writeEndElement();
626 writer.writeStartElement(
"quote");
630 writer.writeEndElement();
634 writer.writeCharacters(atom->string());
638 writer.writeStartElement(
"section");
639 writer.writeAttribute(
"id",
644 writer.writeEndElement();
648 writer.writeStartElement(
"heading");
649 int unit = atom->string().toInt();
650 writer.writeAttribute(
"level", QString::number(unit));
651 m_inSectionHeading =
true;
655 writer.writeEndElement();
656 m_inSectionHeading =
false;
665 writer.writeStartElement(atom->string());
671 writer.writeAttribute(
"identifier", atom->string());
672 writer.writeEndElement();
679 const QString &location = atom->string();
680 writer.writeAttribute(
"location", location);
681 auto maybe_resolved_file{file_resolver.resolve(location)};
683 if (maybe_resolved_file)
684 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
687 QString details =
std::transform_reduce(
688 file_resolver.get_search_directories().cbegin(),
689 file_resolver.get_search_directories().cend(),
690 u"Searched directories:"_s,
692 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
695 relative
->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
701 writer.writeCharacters(atom->string());
704 writer.writeStartElement(
"table");
705 if (atom->string().contains(
"%"))
706 writer.writeAttribute(
"width", atom->string());
710 writer.writeEndElement();
714 writer.writeStartElement(
"header");
718 writer.writeEndElement();
722 writer.writeStartElement(
"row");
726 writer.writeEndElement();
730 writer.writeStartElement(
"item");
731 QStringList spans = atom->string().split(
",");
732 if (spans.size() == 2) {
733 if (spans.at(0) !=
"1")
734 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
735 if (spans.at(1) !=
"1")
736 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
740 writer.writeEndElement();
745 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
750 writer.writeStartElement(
"target");
751 writer.writeAttribute(
"name", TextUtils::asAsciiPrintable(atom->string()));
752 writer.writeEndElement();
756 writer.writeStartElement(
"para");
757 writer.writeTextElement(
"bold",
"Warning:");
758 writer.writeCharacters(
" ");
763 writer.writeCharacters(atom->typeString());
769 m_hasQuotingInformation = keepQuoting;
776 QString fullName = link;
778 fullName = node->fullName();
779 if (!fullName.isEmpty() && !link.isEmpty()) {
780 writer.writeStartElement(
"link");
781 if (atom && !atom->string().isEmpty())
782 writer.writeAttribute(
"raw", atom->string());
784 writer.writeAttribute(
"raw", fullName);
785 writer.writeAttribute(
"href", link);
786 writer.writeAttribute(
"type", targetType(node));
790 writer.writeAttribute(
"enum", fullName);
793 const auto *en =
static_cast<
const ExampleNode *>(node);
794 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
795 if (!fileTitle.isEmpty()) {
796 writer.writeAttribute(
"page", fileTitle);
802 writer.writeAttribute(
"page", fullName);
805 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
806 if (!propertyNode->getters().empty())
807 writer.writeAttribute(
"getter", propertyNode->getters().at(0)->fullName());
820 writer.writeEndElement();
827 if (node && !node->links().empty()) {
828 std::pair<QString, QString> anchorPair;
829 const Node *linkNode;
831 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
833 linkNode = m_qdb->findNodeForTarget(it.value().first, node);
838 if (linkNode == node)
839 anchorPair = it.value();
841 anchorPair = anchorForNode(linkNode);
843 writer.writeStartElement(
"relation");
844 writer.writeAttribute(
"href", anchorPair.first);
845 writer.writeAttribute(
"type", targetType(linkNode));
848 case Node::StartLink:
849 writer.writeAttribute(
"meta",
"start");
852 writer.writeAttribute(
"meta",
"next");
854 case Node::PreviousLink:
855 writer.writeAttribute(
"meta",
"previous");
857 case Node::ContentsLink:
858 writer.writeAttribute(
"meta",
"contents");
861 writer.writeAttribute(
"meta",
"");
863 writer.writeAttribute(
"description", anchorPair.second);
864 writer.writeEndElement();
872 generateAnnotatedList(writer, relative, nodeMap.values());
878 writer.writeStartElement(
"table");
879 writer.writeAttribute(
"width",
"100%");
881 for (
const auto *node : nodeList) {
882 writer.writeStartElement(
"row");
883 writer.writeStartElement(
"item");
884 writer.writeStartElement(
"para");
885 const QString link = linkForNode(node, relative);
886 startLink(writer, node->doc().body().firstAtom(), node, link);
888 writer.writeEndElement();
889 writer.writeEndElement();
891 writer.writeStartElement(
"item");
892 writer.writeStartElement(
"para");
893 writer.writeCharacters(node->doc().briefText().toString());
894 writer.writeEndElement();
895 writer.writeEndElement();
896 writer.writeEndElement();
898 writer.writeEndElement();
903 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_