18#include <QtCore/qxmlstream.h>
22using namespace Qt::StringLiterals;
53
54
55
56
59 if (m_supplement && currentWriter)
60 addAtomElements(*currentWriter.data(), atom, relative, marker);
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.reset(
new QXmlStreamWriter(&data));
88 currentWriter->setAutoFormatting(
true);
89 beginSubPage(pn, Generator::fileName(pn,
"webxml"));
90 currentWriter->writeStartDocument();
91 currentWriter->writeStartElement(
"WebXML");
92 currentWriter->writeStartElement(
"document");
94 generateIndexSections(*currentWriter.data(), pn);
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);
153 std::ignore = qdocIndexFiles->generateIndexSection(writer, node,
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");
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();
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();
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;
226 generateAnnotatedList(writer, node, cn
->members());
229 writer.writeEndElement();
239 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
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;
280 generateAnnotatedList(writer, relative, cn
->members());
283 const Node *node{
nullptr};
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()};
495 Config::copyFile(relative->doc().location(), file.get_path(), file_name,
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",
"1");
565 writer.writeStartElement(
"definition");
567 writer.writeTextElement(
568 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
572 writer.writeEndElement();
576 writer.writeStartElement(
"item");
580 writer.writeEndElement();
584 writer.writeEndElement();
588 writer.writeStartElement(
"para");
589 writer.writeTextElement(
"bold",
"Note:");
590 writer.writeCharacters(
" ");
597 writer.writeEndElement();
605 writer.writeStartElement(
"para");
610 writer.writeEndElement();
614 writer.writeStartElement(
"quote");
618 writer.writeEndElement();
622 writer.writeCharacters(atom->string());
626 writer.writeStartElement(
"section");
627 writer.writeAttribute(
"id",
632 writer.writeEndElement();
636 writer.writeStartElement(
"heading");
637 int unit = atom->string().toInt();
638 writer.writeAttribute(
"level", QString::number(unit));
643 writer.writeEndElement();
653 writer.writeStartElement(atom->string());
659 writer.writeAttribute(
"identifier", atom->string());
660 writer.writeEndElement();
667 const QString &location = atom->string();
668 writer.writeAttribute(
"location", location);
671 if (maybe_resolved_file)
672 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
675 QString details = std::transform_reduce(
676 file_resolver.get_search_directories().cbegin(),
677 file_resolver.get_search_directories().cend(),
678 u"Searched directories:"_s,
680 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
683 relative->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
689 writer.writeCharacters(atom->string());
692 writer.writeStartElement(
"table");
693 if (atom->string().contains(
"%"))
694 writer.writeAttribute(
"width", atom->string());
698 writer.writeEndElement();
702 writer.writeStartElement(
"header");
706 writer.writeEndElement();
710 writer.writeStartElement(
"row");
714 writer.writeEndElement();
718 writer.writeStartElement(
"item");
719 QStringList spans = atom->string().split(
",");
720 if (spans.size() == 2) {
721 if (spans.at(0) !=
"1")
722 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
723 if (spans.at(1) !=
"1")
724 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
728 writer.writeEndElement();
733 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
738 writer.writeStartElement(
"target");
739 writer.writeAttribute(
"name", Utilities::asAsciiPrintable(atom->string()));
740 writer.writeEndElement();
744 writer.writeStartElement(
"para");
745 writer.writeTextElement(
"bold",
"Warning:");
746 writer.writeCharacters(
" ");
751 writer.writeCharacters(atom->typeString());
757 m_hasQuotingInformation = keepQuoting;
764 QString fullName = link;
766 fullName = node->fullName();
767 if (!fullName.isEmpty() && !link.isEmpty()) {
768 writer.writeStartElement(
"link");
769 if (atom && !atom->string().isEmpty())
770 writer.writeAttribute(
"raw", atom->string());
772 writer.writeAttribute(
"raw", fullName);
773 writer.writeAttribute(
"href", link);
774 writer.writeAttribute(
"type", targetType(node));
778 writer.writeAttribute(
"enum", fullName);
781 const auto *en =
static_cast<
const ExampleNode *>(node);
782 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
783 if (!fileTitle.isEmpty()) {
784 writer.writeAttribute(
"page", fileTitle);
790 writer.writeAttribute(
"page", fullName);
793 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
795 writer.writeAttribute(
"getter", propertyNode
->getters().at(0)->fullName());
808 writer.writeEndElement();
815 if (node && !node->links().empty()) {
816 std::pair<QString, QString> anchorPair;
817 const Node *linkNode;
819 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
821 linkNode =
m_qdb->findNodeForTarget(it.value().first, node);
826 if (linkNode == node)
827 anchorPair = it.value();
829 anchorPair = anchorForNode(linkNode);
831 writer.writeStartElement(
"relation");
832 writer.writeAttribute(
"href", anchorPair.first);
833 writer.writeAttribute(
"type", targetType(linkNode));
836 case Node::StartLink:
837 writer.writeAttribute(
"meta",
"start");
840 writer.writeAttribute(
"meta",
"next");
842 case Node::PreviousLink:
843 writer.writeAttribute(
"meta",
"previous");
845 case Node::ContentsLink:
846 writer.writeAttribute(
"meta",
"contents");
849 writer.writeAttribute(
"meta",
"");
851 writer.writeAttribute(
"description", anchorPair.second);
852 writer.writeEndElement();
860 generateAnnotatedList(writer, relative, nodeMap.values());
866 writer.writeStartElement(
"table");
867 writer.writeAttribute(
"width",
"100%");
869 for (
const auto *node : nodeList) {
870 writer.writeStartElement(
"row");
871 writer.writeStartElement(
"item");
872 writer.writeStartElement(
"para");
873 const QString link = linkForNode(node, relative);
874 startLink(writer, node->doc().body().firstAtom(), node, link);
876 writer.writeEndElement();
877 writer.writeEndElement();
879 writer.writeStartElement(
"item");
880 writer.writeStartElement(
"para");
881 writer.writeCharacters(node->doc().briefText().toString());
882 writer.writeEndElement();
883 writer.writeEndElement();
884 writer.writeEndElement();
886 writer.writeEndElement();
891 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.
bool hasClasses() const override
Returns true if this collection node contains at least one class node.
const NodeList & members() const
bool hasNamespaces() const override
Returns true if this collection node contains at least one namespace node.
NodeMap getMembers(NodeType type) 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...
FileResolver & file_resolver
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.
bool noAutoList() const
Returns the value of the no auto-list flag.
This class describes one instance of using the Q_PROPERTY macro.
const NodeList & getters() const
void mergeCollections(CollectionNode *c)
Finds all the collection nodes with the same name and type as c and merges their members into the mem...
This class handles qdoc index files.
static Text sectionHeading(const Atom *sectionBegin)
const Atom * firstAtom() const
QString fileBase(const Node *node) const override
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 format() override
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_