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();
485 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
486 if (!maybe_resolved_file) {
488 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
491 QString file_name{QFileInfo{file.get_path()}.fileName()};
494 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
496 writer.writeStartElement(
"image");
498 writer.writeAttribute(
"href",
"images/" + file_name);
499 writer.writeEndElement();
501 setImageFileName(relative,
"images/" + file_name);
507 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
508 if (!maybe_resolved_file) {
510 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
513 QString file_name{QFileInfo{file.get_path()}.fileName()};
516 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
518 writer.writeStartElement(
"inlineimage");
520 writer.writeAttribute(
"href",
"images/" + file_name);
521 writer.writeEndElement();
523 setImageFileName(relative,
"images/" + file_name);
531 writer.writeStartElement(
"para");
532 writer.writeTextElement(
"bold",
"Important:");
533 writer.writeCharacters(
" ");
537 writer.writeStartElement(
"legalese");
541 writer.writeEndElement();
547 const Node *node =
nullptr;
548 QString link = getLink(atom, relative, &node);
550 startLink(writer, atom, node, link);
555 writer.writeStartElement(
"list");
558 writer.writeAttribute(
"type",
"bullet");
560 writer.writeAttribute(
"type",
"definition");
563 writer.writeAttribute(
"type",
"enum");
565 writer.writeAttribute(
"type",
"definition");
567 writer.writeAttribute(
"type",
"ordered");
569 writer.writeAttribute(
"start",
"A");
571 writer.writeAttribute(
"start",
"a");
573 writer.writeAttribute(
"start",
"I");
575 writer.writeAttribute(
"start",
"i");
577 writer.writeAttribute(
"start",
"1");
584 writer.writeStartElement(
"definition");
586 writer.writeTextElement(
587 "term", plainCode(marker->markedUpEnumValue(atom
->next()->string(), relative)));
591 writer.writeEndElement();
595 writer.writeStartElement(
"item");
599 writer.writeEndElement();
603 writer.writeEndElement();
607 writer.writeStartElement(
"para");
608 writer.writeTextElement(
"bold",
"Note:");
609 writer.writeCharacters(
" ");
616 writer.writeEndElement();
624 writer.writeStartElement(
"para");
629 writer.writeEndElement();
633 writer.writeStartElement(
"quote");
637 writer.writeEndElement();
641 writer.writeCharacters(atom->string());
645 writer.writeStartElement(
"section");
646 writer.writeAttribute(
"id",
651 writer.writeEndElement();
655 writer.writeStartElement(
"heading");
656 int unit = atom->string().toInt();
657 writer.writeAttribute(
"level", QString::number(unit));
662 writer.writeEndElement();
672 writer.writeStartElement(atom->string());
678 writer.writeAttribute(
"identifier", atom->string());
679 writer.writeEndElement();
686 const QString &location = atom->string();
687 writer.writeAttribute(
"location", location);
690 if (maybe_resolved_file)
691 writer.writeAttribute(
"path", (*maybe_resolved_file).get_path());
694 QString details = std::transform_reduce(
695 file_resolver.get_search_directories().cbegin(),
696 file_resolver.get_search_directories().cend(),
697 u"Searched directories:"_s,
699 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
702 relative->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
708 writer.writeCharacters(atom->string());
711 writer.writeStartElement(
"table");
712 if (atom->string().contains(
"%"))
713 writer.writeAttribute(
"width", atom->string());
717 writer.writeEndElement();
721 writer.writeStartElement(
"header");
725 writer.writeEndElement();
729 writer.writeStartElement(
"row");
733 writer.writeEndElement();
737 writer.writeStartElement(
"item");
738 QStringList spans = atom->string().split(
",");
739 if (spans.size() == 2) {
740 if (spans.at(0) !=
"1")
741 writer.writeAttribute(
"colspan", spans.at(0).trimmed());
742 if (spans.at(1) !=
"1")
743 writer.writeAttribute(
"rowspan", spans.at(1).trimmed());
747 writer.writeEndElement();
752 if (
const auto *endtoc = atom->find(Atom::TableOfContentsRight))
757 writer.writeStartElement(
"target");
758 writer.writeAttribute(
"name", Utilities::asAsciiPrintable(atom->string()));
759 writer.writeEndElement();
763 writer.writeStartElement(
"para");
764 writer.writeTextElement(
"bold",
"Warning:");
765 writer.writeCharacters(
" ");
770 writer.writeCharacters(atom->typeString());
776 m_hasQuotingInformation = keepQuoting;
783 QString fullName = link;
785 fullName = node->fullName();
786 if (!fullName.isEmpty() && !link.isEmpty()) {
787 writer.writeStartElement(
"link");
788 if (atom && !atom->string().isEmpty())
789 writer.writeAttribute(
"raw", atom->string());
791 writer.writeAttribute(
"raw", fullName);
792 writer.writeAttribute(
"href", link);
793 writer.writeAttribute(
"type", targetType(node));
797 writer.writeAttribute(
"enum", fullName);
800 const auto *en =
static_cast<
const ExampleNode *>(node);
801 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
802 if (!fileTitle.isEmpty()) {
803 writer.writeAttribute(
"page", fileTitle);
809 writer.writeAttribute(
"page", fullName);
812 const auto *propertyNode =
static_cast<
const PropertyNode *>(node);
814 writer.writeAttribute(
"getter", propertyNode
->getters().at(0)->fullName());
827 writer.writeEndElement();
834 if (node && !node->links().empty()) {
835 std::pair<QString, QString> anchorPair;
836 const Node *linkNode;
838 for (
auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
840 linkNode =
m_qdb->findNodeForTarget(it.value().first, node);
845 if (linkNode == node)
846 anchorPair = it.value();
848 anchorPair = anchorForNode(linkNode);
850 writer.writeStartElement(
"relation");
851 writer.writeAttribute(
"href", anchorPair.first);
852 writer.writeAttribute(
"type", targetType(linkNode));
855 case Node::StartLink:
856 writer.writeAttribute(
"meta",
"start");
859 writer.writeAttribute(
"meta",
"next");
861 case Node::PreviousLink:
862 writer.writeAttribute(
"meta",
"previous");
864 case Node::ContentsLink:
865 writer.writeAttribute(
"meta",
"contents");
868 writer.writeAttribute(
"meta",
"");
870 writer.writeAttribute(
"description", anchorPair.second);
871 writer.writeEndElement();
879 generateAnnotatedList(writer, relative, nodeMap.values());
885 writer.writeStartElement(
"table");
886 writer.writeAttribute(
"width",
"100%");
888 for (
const auto *node : nodeList) {
889 writer.writeStartElement(
"row");
890 writer.writeStartElement(
"item");
891 writer.writeStartElement(
"para");
892 const QString link = linkForNode(node, relative);
893 startLink(writer, node->doc().body().firstAtom(), node, link);
895 writer.writeEndElement();
896 writer.writeEndElement();
898 writer.writeStartElement(
"item");
899 writer.writeStartElement(
"para");
900 writer.writeCharacters(node->doc().briefText().toString());
901 writer.writeEndElement();
902 writer.writeEndElement();
903 writer.writeEndElement();
905 writer.writeEndElement();
910 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
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_