16#include <QtCore/qxmlstream.h>
20using namespace Qt::StringLiterals;
51
52
53
54
57 if (m_supplement && currentWriter)
58 addAtomElements(*currentWriter.data(), atom, relative, marker);
65 QXmlStreamWriter writer(&data);
66 writer.setAutoFormatting(
true);
67 beginSubPage(aggregate, Generator::fileName(aggregate,
"webxml"));
68 writer.writeStartDocument();
69 writer.writeStartElement(
"WebXML");
70 writer.writeStartElement(
"document");
74 writer.writeEndElement();
75 writer.writeEndElement();
76 writer.writeEndDocument();
85 currentWriter.reset(
new QXmlStreamWriter(&data));
86 currentWriter->setAutoFormatting(
true);
87 beginSubPage(pn, Generator::fileName(pn,
"webxml"));
88 currentWriter->writeStartDocument();
89 currentWriter->writeStartElement(
"WebXML");
90 currentWriter->writeStartElement(
"document");
92 generateIndexSections(*currentWriter.data(), pn);
94 currentWriter->writeEndElement();
95 currentWriter->writeEndElement();
96 currentWriter->writeEndDocument();
107 QXmlStreamWriter writer(&data);
108 writer.setAutoFormatting(
true);
109 beginSubPage(en, linkForExampleFile(resolved_file.get_query(),
"webxml"));
110 writer.writeStartDocument();
111 writer.writeStartElement(
"WebXML");
112 writer.writeStartElement(
"document");
113 writer.writeStartElement(
"page");
114 writer.writeAttribute(
"name", resolved_file.get_query());
115 writer.writeAttribute(
"href", linkForExampleFile(resolved_file.get_query()));
116 const QString title = exampleFileTitle(
static_cast<
const ExampleNode *>(en), resolved_file.get_query());
117 writer.writeAttribute(
"title", title);
118 writer.writeAttribute(
"fulltitle", title);
119 writer.writeAttribute(
"subtitle", resolved_file.get_query());
120 writer.writeStartElement(
"description");
123 writer.writeAttribute(
"path", resolved_file.get_path());
124 writer.writeAttribute(
"line",
"0");
125 writer.writeAttribute(
"column",
"0");
130 QString code = quoter.quoteTo(en->location(), QString(), QString());
131 writer.writeTextElement(
"code", trimmedTrailing(code, QString(), QString()));
133 writer.writeEndElement();
134 writer.writeEndElement();
135 writer.writeEndElement();
136 writer.writeEndElement();
137 writer.writeEndDocument();
147 if (qdocIndexFiles) {
148 qdocIndexFiles->generateIndexSections(writer, node,
this);
151 qdocIndexFiles->generateIndexSection(writer, node,
this);
160 writer.writeStartElement(
"description");
163 writer.writeAttribute(
"line", QString::number(node->doc().location().lineNo()));
164 writer.writeAttribute(
"column", QString::number(node->doc().location().columnNo()));
168 generateRelations(writer, node);
171 writer.writeStartElement(
"generatedlist");
172 writer.writeAttribute(
"contents",
"classesbymodule");
176 writer.writeStartElement(
"section");
177 writer.writeStartElement(
"heading");
178 writer.writeAttribute(
"level",
"1");
179 writer.writeCharacters(
"Namespaces");
180 writer.writeEndElement();
182 generateAnnotatedList(writer, node, namespaces);
183 writer.writeEndElement();
186 writer.writeStartElement(
"section");
187 writer.writeStartElement(
"heading");
188 writer.writeAttribute(
"level",
"1");
189 writer.writeCharacters(
"Classes");
190 writer.writeEndElement();
192 generateAnnotatedList(writer, node, classes);
193 writer.writeEndElement();
195 writer.writeEndElement();
204 QList<Text> alsoList = node->doc().alsoList();
205 supplementAlsoList(node, alsoList);
207 if (!alsoList.isEmpty()) {
208 writer.writeStartElement(
"see-also");
209 for (
const auto &item : alsoList) {
210 const auto *atom = item.firstAtom();
212 atom = addAtomElements(writer, atom, node, marker_);
214 writer.writeEndElement();
220 m_supplement =
false;
224 generateAnnotatedList(writer, node, cn
->members());
227 writer.writeEndElement();
255 auto *aggregate =
static_cast<
Aggregate *>(node);
256 for (
auto c : aggregate->childNodes()) {
257 if ((c->isAggregate() || c->isTextPageNode() || c->isCollectionNode())
259 generateDocumentation(c);
267 bool keepQuoting =
false;
276 generateAnnotatedList(writer, relative, cn
->members());
279 const Node *node{
nullptr};
283 link = getAutoLink(atom, relative, &node, Node::API);
291 startLink(writer, atom, node, link);
293 writer.writeCharacters(atom->string());
296 writer.writeEndElement();
306 writer.writeStartElement(
"brief");
309 writer.writeCharacters(
"This property");
312 writer.writeCharacters(
"This variable");
325 str[0] = str[0].toLower();
326 if (str.endsWith(
'.'))
329 const QList<QStringView> words = QStringView{str}.split(
' ');
330 if (!words.isEmpty()) {
331 QStringView first(words.at(0));
332 if (!(first == u"contains" || first == u"specifies" || first == u"describes"
333 || first == u"defines" || first == u"holds" || first == u"determines"))
334 writer.writeCharacters(
" holds ");
336 writer.writeCharacters(
" ");
343 writer.writeCharacters(
".");
345 writer.writeEndElement();
349 writer.writeStartElement(
"teletype");
351 writer.writeAttribute(
"type",
"normal");
353 writer.writeAttribute(
"type",
"highlighted");
355 writer.writeCharacters(plainCode(atom->string()));
356 writer.writeEndElement();
360 if (!m_hasQuotingInformation)
361 writer.writeTextElement(
362 "code", trimmedTrailing(plainCode(atom->string()), QString(), QString()));
368 writer.writeTextElement(
"badcode",
369 trimmedTrailing(plainCode(atom->string()), QString(), QString()));
374 if (quoteCommand ==
"dots") {
375 writer.writeAttribute(
"indent", atom->string());
376 writer.writeCharacters(
"...");
378 writer.writeCharacters(atom->string());
380 writer.writeEndElement();
387 quoteCommand = atom->string();
388 writer.writeStartElement(quoteCommand);
394 QString link = linkForExampleFile(atom->string());
396 startLink(writer, atom, relative, link);
402 QString link = atom->string();
404 startLink(writer, atom,
nullptr,
"images/used-in-examples/" + link);
409 writer.writeStartElement(
"footnote");
413 writer.writeEndElement();
417 writer.writeEndElement();
420 writer.writeStartElement(
"raw");
421 writer.writeAttribute(
"format", atom->string());
425 writer.writeStartElement(
"bold");
427 writer.writeStartElement(
"italic");
429 writer.writeStartElement(
"underline");
431 writer.writeStartElement(
"subscript");
433 writer.writeStartElement(
"superscript");
435 writer.writeStartElement(
"teletype");
437 writer.writeStartElement(
"argument");
439 writer.writeStartElement(
"index");
444 writer.writeEndElement();
446 writer.writeEndElement();
448 writer.writeEndElement();
450 writer.writeEndElement();
452 writer.writeEndElement();
454 writer.writeEndElement();
456 writer.writeEndElement();
458 writer.writeEndElement();
460 writer.writeCharacters(QChar(0x2122));
463 writer.writeEndElement();
469 writer.writeStartElement(
"generatedlist");
470 writer.writeAttribute(
"contents", atom->string());
471 writer.writeEndElement();
481 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
482 if (!maybe_resolved_file) {
484 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
487 QString file_name{QFileInfo{file.get_path()}.fileName()};
490 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
492 writer.writeStartElement(
"image");
494 writer.writeAttribute(
"href",
"images/" + file_name);
495 writer.writeEndElement();
497 setImageFileName(relative,
"images/" + file_name);
503 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
504 if (!maybe_resolved_file) {
506 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
509 QString file_name{QFileInfo{file.get_path()}.fileName()};
512 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
514 writer.writeStartElement(
"inlineimage");
516 writer.writeAttribute(
"href",
"images/" + file_name);
517 writer.writeEndElement();
519 setImageFileName(relative,
"images/" + file_name);
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",
"1");
580 writer.writeStartElement(
"definition");
582 writer.writeTextElement(
583 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
587 writer.writeEndElement();
591 writer.writeStartElement(
"item");
595 writer.writeEndElement();
599 writer.writeEndElement();
603 writer.writeStartElement(
"para");
604 writer.writeTextElement(
"bold",
"Note:");
605 writer.writeCharacters(
" ");
612 writer.writeEndElement();
620 writer.writeStartElement(
"para");
625 writer.writeEndElement();
629 writer.writeStartElement(
"quote");
633 writer.writeEndElement();
637 writer.writeCharacters(atom->string());
641 writer.writeStartElement(
"section");
642 writer.writeAttribute(
"id",
647 writer.writeEndElement();
651 writer.writeStartElement(
"heading");
652 int unit = atom->string().toInt();
653 writer.writeAttribute(
"level", QString::number(unit));
658 writer.writeEndElement();
668 writer.writeStartElement(atom->string());
674 writer.writeAttribute(
"identifier", atom->string());
675 writer.writeEndElement();
682 const QString &location = atom->string();
683 writer.writeAttribute(
"location", location);
686 if (maybe_resolved_file)
687 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
690 QString details = std::transform_reduce(
691 file_resolver.get_search_directories().cbegin(),
692 file_resolver.get_search_directories().cend(),
693 u"Searched directories:"_s,
695 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
698 relative->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
704 writer.writeCharacters(atom->string());
707 writer.writeStartElement(
"table");
708 if (atom->string().contains(
"%"))
709 writer.writeAttribute(
"width", atom->string());
713 writer.writeEndElement();
717 writer.writeStartElement(
"header");
721 writer.writeEndElement();
725 writer.writeStartElement(
"row");
729 writer.writeEndElement();
733 writer.writeStartElement(
"item");
734 QStringList spans = atom->string().split(
",");
735 if (spans.size() == 2) {
736 if (spans.at(0) !=
"1")
737 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
738 if (spans.at(1) !=
"1")
739 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
743 writer.writeEndElement();
747 writer.writeStartElement(
"target");
748 writer.writeAttribute(
"name", Utilities::asAsciiPrintable(atom->string()));
749 writer.writeEndElement();
753 writer.writeStartElement(
"para");
754 writer.writeTextElement(
"bold",
"Warning:");
755 writer.writeCharacters(
" ");
760 writer.writeCharacters(atom->typeString());
766 m_hasQuotingInformation = keepQuoting;
773 QString fullName = link;
775 fullName = node->fullName();
776 if (!fullName.isEmpty() && !link.isEmpty()) {
777 writer.writeStartElement(
"link");
778 if (atom && !atom->string().isEmpty())
779 writer.writeAttribute(
"raw", atom->string());
781 writer.writeAttribute(
"raw", fullName);
782 writer.writeAttribute(
"href", link);
783 writer.writeAttribute(
"type", targetType(node));
787 writer.writeAttribute(
"enum", fullName);
790 const auto *en =
static_cast<
const ExampleNode *>(node);
791 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
792 if (!fileTitle.isEmpty()) {
793 writer.writeAttribute(
"page", fileTitle);
799 writer.writeAttribute(
"page", fullName);
802 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
804 writer.writeAttribute(
"getter", propertyNode
->getters().at(0)->fullName());
817 writer.writeEndElement();
824 if (node && !node->links().empty()) {
825 std::pair<QString, QString> anchorPair;
826 const Node *linkNode;
828 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
830 linkNode =
m_qdb->findNodeForTarget(it.value().first, node);
835 if (linkNode == node)
836 anchorPair = it.value();
838 anchorPair = anchorForNode(linkNode);
840 writer.writeStartElement(
"relation");
841 writer.writeAttribute(
"href", anchorPair.first);
842 writer.writeAttribute(
"type", targetType(linkNode));
845 case Node::StartLink:
846 writer.writeAttribute(
"meta",
"start");
849 writer.writeAttribute(
"meta",
"next");
851 case Node::PreviousLink:
852 writer.writeAttribute(
"meta",
"previous");
854 case Node::ContentsLink:
855 writer.writeAttribute(
"meta",
"contents");
858 writer.writeAttribute(
"meta",
"");
860 writer.writeAttribute(
"description", anchorPair.second);
861 writer.writeEndElement();
869 generateAnnotatedList(writer, relative, nodeMap.values());
875 writer.writeStartElement(
"table");
876 writer.writeAttribute(
"width",
"100%");
878 for (
const auto *node : nodeList) {
879 writer.writeStartElement(
"row");
880 writer.writeStartElement(
"item");
881 writer.writeStartElement(
"para");
882 const QString link = linkForNode(node, relative);
883 startLink(writer, node->doc().body().firstAtom(), node, link);
885 writer.writeEndElement();
886 writer.writeEndElement();
888 writer.writeStartElement(
"item");
889 writer.writeStartElement(
"para");
890 writer.writeCharacters(node->doc().briefText().toString());
891 writer.writeEndElement();
892 writer.writeEndElement();
893 writer.writeEndElement();
895 writer.writeEndElement();
900 return Generator::fileBase(node);
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#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
NodeMap getMembers(Node::NodeType type) const
Returns a map containing this collection node's member nodes with a specified node type.
bool hasNamespaces() const override
Returns true if this collection node contains at least one namespace node.
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.
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.
virtual bool isInternal() const
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
bool isHeader() const
Returns true if the node type is HeaderFile.
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...
NodeType nodeType() const
Returns this node's type.
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.
bool isModule() const
Returns true if the node type is Module.
LinkType
An unsigned char value that probably should be moved out of the Node base class.
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.
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
Represents a file that is reachable by QDoc based on its current configuration.
static CodeMarker * marker_