Doxygen
Loading...
Searching...
No Matches
htmldocvisitor.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include "htmldocvisitor.h"
17#include "docparser.h"
18#include "language.h"
19#include "doxygen.h"
20#include "outputgen.h"
21#include "outputlist.h"
22#include "dot.h"
23#include "message.h"
24#include "config.h"
25#include "htmlgen.h"
26#include "parserintf.h"
27#include "msc.h"
28#include "dia.h"
29#include "util.h"
30#include "vhdldocgen.h"
31#include "filedef.h"
32#include "memberdef.h"
33#include "htmlentity.h"
34#include "emoji.h"
35#include "plantuml.h"
36#include "formula.h"
37#include "fileinfo.h"
38#include "indexlist.h"
39#include "growbuf.h"
40#include "portable.h"
41#include "codefragment.h"
42#include "cite.h"
43
44static const int NUM_HTML_LIST_TYPES = 4;
45static const char g_types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};
46enum class contexts_t
47{
48 NONE, // 0
49 STARTLI, // 1
50 STARTDD, // 2
51 ENDLI, // 3
52 ENDDD, // 4
53 STARTTD, // 5
54 ENDTD, // 6
55 INTERLI, // 7
56 INTERDD, // 8
58};
59
60static constexpr const char *contexts(contexts_t type)
61{
62 switch (type)
63 {
64 case contexts_t::NONE: return nullptr;
65 case contexts_t::STARTLI: return "startli";
66 case contexts_t::STARTDD: return "startdd";
67 case contexts_t::ENDLI: return "endli";
68 case contexts_t::ENDDD: return "enddd";
69 case contexts_t::STARTTD: return "starttd";
70 case contexts_t::ENDTD: return "endtd";
71 case contexts_t::INTERLI: return "interli";
72 case contexts_t::INTERDD: return "interdd";
73 case contexts_t::INTERTD: return "intertd";
74 default: return nullptr;
75 }
76}
77static const char *hex="0123456789ABCDEF";
78
80{
81 static int cnt = 0;
82 QCString result="a";
83 QCString cntStr;
84 result += cntStr.setNum(cnt);
85 result += "_";
86 cnt++;
87 const char *str = word.data();
88 unsigned char c = 0;
89 if (str)
90 {
91 while ((c = *str++))
92 {
93 if ((c >= 'a' && c <= 'z') || // ALPHA
94 (c >= 'A' && c <= 'Z') || // ALPHA
95 (c >= '0' && c <= '9') || // DIGIT
96 c == '-' ||
97 c == '.'
98 )
99 {
100 result += c;
101 }
102 else
103 {
104 char enc[4];
105 enc[0] = '_';
106 enc[1] = hex[(c & 0xf0) >> 4];
107 enc[2] = hex[c & 0xf];
108 enc[3] = 0;
109 result += enc;
110 }
111 }
112 }
113 return result;
114}
115
116
117
119{
120 //printf("mustBeOutsideParagraph(%s)=",docNodeName(n));
123 /* <table> */ DocHtmlTable,
124 /* <h?> */ DocSection, DocHtmlHeader,
125 /* \internal */ DocInternal,
126 /* <div> */ DocInclude, DocSecRefList,
127 /* <hr> */ DocHorRuler,
128 /* <blockquote> */ DocHtmlBlockQuote,
129 /* \parblock */ DocParBlock,
130 /* \dotfile */ DocDotFile,
131 /* \mscfile */ DocMscFile,
132 /* \diafile */ DocDiaFile,
133 /* \plantumlfile */ DocPlantUmlFile,
134 /* <details> */ DocHtmlDetails,
135 /* <summary> */ DocHtmlSummary,
136 DocIncOperator >(n))
137 {
138 return TRUE;
139 }
140 const DocVerbatim *dv = std::get_if<DocVerbatim>(&n);
141 if (dv)
142 {
143 DocVerbatim::Type t = dv->type();
145 return t!=DocVerbatim::HtmlOnly || dv->isBlock();
146 }
147 const DocStyleChange *sc = std::get_if<DocStyleChange>(&n);
148 if (sc)
149 {
150 return sc->style()==DocStyleChange::Preformatted ||
151 sc->style()==DocStyleChange::Div ||
153 }
154 const DocFormula *df = std::get_if<DocFormula>(&n);
155 if (df)
156 {
157 return !df->isInline();
158 }
159 const DocImage *di = std::get_if<DocImage>(&n);
160 if (di)
161 {
162 return !di->isInlineImage();
163 }
164 return FALSE;
165}
166
168{
169 switch (s.type())
170 {
176 return FALSE;
177 default:
178 return TRUE;
179 }
180}
181
182static bool isDocIncludeVisible(const DocInclude &s)
183{
184 switch (s.type())
185 {
192 return FALSE;
193 default:
194 return TRUE;
195 }
196}
197
199{
200 switch (s.type())
201 {
203 return FALSE;
204 default:
205 return TRUE;
206 }
207}
208
209static bool isInvisibleNode(const DocNodeVariant &node)
210{
211 //printf("isInvisibleNode(%s)\n",docNodeName(node));
212 // skip over white space
213 const DocWhiteSpace *ws = std::get_if<DocWhiteSpace>(&node);
214 if (ws) return true;
215 // skip over image nodes that are not for HTML output
216 const DocImage *di = std::get_if<DocImage>(&node);
217 if (di) return di->type()!=DocImage::Html;
218 // skip over verbatim nodes that are not visible in the HTML output
219 const DocVerbatim *dv = std::get_if<DocVerbatim>(&node);
220 if (dv) return !isDocVerbatimVisible(*dv);
221 // skip over include nodes that are not visible in the HTML output
222 const DocInclude *dinc = std::get_if<DocInclude>(&node);
223 if (dinc) return !isDocIncludeVisible(*dinc);
224 const DocIncOperator *dio = std::get_if<DocIncOperator>(&node);
225 // skip over include operator nodes that are not visible in the HTML output
226 if (dio) return !isDocIncOperatorVisible(*dio);
227 return false;
228}
229
230static QCString makeShortName(const QCString &name)
231{
232 QCString shortName = name;
233 int i = shortName.findRev('/');
234 if (i!=-1)
235 {
236 shortName=shortName.mid(i+1);
237 }
238 return shortName;
239}
240
241static QCString makeBaseName(const QCString &name)
242{
243 QCString baseName = makeShortName(name);
244 int i=baseName.find('.');
245 if (i!=-1)
246 {
247 baseName=baseName.left(i);
248 }
249 return baseName;
250}
251
252
253//-------------------------------------------------------------------------
254
256 const Definition *ctx,const QCString &fn)
257 : m_t(t), m_ci(ci), m_ctx(ctx), m_fileName(fn)
258{
259 if (ctx) m_langExt=ctx->getDefFileExtension();
260}
261
262template<class T>
264{
265 if (n.hasCaption())
266 {
267 t << "<div class=\"caption\">\n";
268 for (const auto &child : n.children())
269 {
270 std::visit(*this, child);
271 }
272 t << "</div>\n";
273 }
274}
275
276 //--------------------------------------
277 // visitor functions for leaf nodes
278 //--------------------------------------
279
281{
282 if (m_hide) return;
283 filter(w.word());
284}
285
287{
288 if (m_hide) return;
289 //printf("linked word: %s\n",qPrint(w.word()));
290 startLink(w.ref(),w.file(),w.relPath(),w.anchor(),w.tooltip());
291 filter(w.word());
292 endLink();
293}
294
296{
297 if (m_hide) return;
298 if (m_insidePre)
299 {
300 m_t << w.chars();
301 }
302 else
303 {
304 m_t << " ";
305 }
306}
307
309{
310 if (m_hide) return;
311 if (m_insideTitle &&
312 (s.symbol()==HtmlEntityMapper::Sym_Quot || s.symbol()==HtmlEntityMapper::Sym_quot)) // escape "'s inside title="..."
313 {
314 m_t << "&quot;";
315 }
316 else
317 {
318 const char *res = HtmlEntityMapper::instance().html(s.symbol());
319 if (res)
320 {
321 m_t << res;
322 }
323 else
324 {
325 err("HTML: non supported HTML-entity found: {}\n",
327 }
328 }
329}
330
332{
333 if (m_hide) return;
334 const char *res = EmojiEntityMapper::instance().unicode(s.index());
335 if (res)
336 {
337 m_t << "<span class=\"emoji\">" << res << "</span>";
338 }
339 else
340 {
341 m_t << s.name();
342 }
343}
344
346{
347 if (!Config_getBool(OBFUSCATE_EMAILS))
348 {
349 m_t << "<a href=\"mailto:" << url << "\">";
350 }
351 else
352 {
353 m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'";
354 if (!url.isEmpty())
355 {
356 const char *p = url.data();
357 uint32_t size=3;
358 while (*p)
359 {
360 m_t << "+'";
361 for (uint32_t j=0;j<size && *p;j++)
362 {
363 p = writeUTF8Char(m_t,p);
364 }
365 m_t << "'";
366 if (size==3) size=2; else size=3;
367 }
368 }
369 m_t << "; return false;\">";
370 }
371}
372
374{
375 if (m_hide) return;
376 if (u.isEmail()) // mail address
377 {
378 QCString url = u.url();
379 // obfuscate the mail address link
381 if (!Config_getBool(OBFUSCATE_EMAILS))
382 {
383 m_t << url;
384 }
385 else
386 {
387 const char *p = url.data();
388 // also obfuscate the address as shown on the web page
389 uint32_t size=5;
390 while (*p)
391 {
392 for (uint32_t j=0;j<size && *p;j++)
393 {
394 p = writeUTF8Char(m_t,p);
395 }
396 if (*p) m_t << "<span class=\"obfuscator\">.nosp@m.</span>";
397 if (size==5) size=4; else size=5;
398 }
399 }
400 m_t << "</a>";
401 }
402 else // web address
403 {
404 m_t << "<a href=\"";
405 filter(u.url());
406 m_t << "\">";
407 filter(u.url());
408 m_t << "</a>";
409 }
410}
411
413{
414 if (m_hide) return;
415 m_t << "<br "<< br.attribs().toString() << " />\n";
416}
417
419{
420 if (m_hide) return;
422 m_t << "<hr "<< hr.attribs().toString() << " />\n";
424}
425
427{
428 if (m_hide) return;
429 switch (s.style())
430 {
432 if (s.enable()) m_t << "<b" << s.attribs().toString() << ">"; else m_t << "</b>";
433 break;
435 if (s.enable()) m_t << "<s" << s.attribs().toString() << ">"; else m_t << "</s>";
436 break;
438 if (s.enable()) m_t << "<strike" << s.attribs().toString() << ">"; else m_t << "</strike>";
439 break;
441 if (s.enable()) m_t << "<del" << s.attribs().toString() << ">"; else m_t << "</del>";
442 break;
444 if (s.enable()) m_t << "<u" << s.attribs().toString() << ">"; else m_t << "</u>";
445 break;
447 if (s.enable()) m_t << "<ins" << s.attribs().toString() << ">"; else m_t << "</ins>";
448 break;
450 if (s.enable())
451 {
452 auto attribs = s.attribs();
453 if (s.tagName()=="a")
454 {
455 attribs.mergeAttribute("class","arg");
456 }
457 m_t << "<em" << attribs.toString() << ">";
458 }
459 else
460 {
461 m_t << "</em>";
462 }
463 break;
465 if (s.enable()) m_t << "<kbd" << s.attribs().toString() << ">"; else m_t << "</kbd>";
466 break;
468 if (s.enable())
469 {
470 m_t << "<span class=\"tt\"" << s.attribs().toString() << ">";
471 m_insidePre=true;
472 }
473 else
474 {
475 m_t << "</span>";
476 m_insidePre=false;
477 }
478 break;
480 if (s.enable())
481 {
482 auto attribs = s.attribs();
483 if (s.tagName()=="p")
484 {
485 attribs.mergeAttribute("class","param");
486 }
487 m_t << "<code" << attribs.toString() << ">";
488 m_insidePre=true;
489 }
490 else
491 {
492 m_insidePre=false;
493 m_t << "</code>";
494 }
495 break;
497 if (s.enable()) m_t << "<sub" << s.attribs().toString() << ">"; else m_t << "</sub>";
498 break;
500 if (s.enable()) m_t << "<sup" << s.attribs().toString() << ">"; else m_t << "</sup>";
501 break;
503 if (s.enable())
504 {
506 m_t << "<center" << s.attribs().toString() << ">";
507 }
508 else
509 {
510 m_t << "</center>";
512 }
513 break;
515 if (s.enable()) m_t << "<small" << s.attribs().toString() << ">"; else m_t << "</small>";
516 break;
518 if (s.enable()) m_t << "<cite" << s.attribs().toString() << ">"; else m_t << "</cite>";
519 break;
521 if (s.enable())
522 {
524 m_t << "<pre" << s.attribs().toString() << ">";
526 }
527 else
528 {
530 m_t << "</pre>";
532 }
533 break;
535 if (s.enable())
536 {
538 m_t << "<div" << s.attribs().toString() << ">";
539 }
540 else
541 {
542 m_t << "</div>";
544 }
545 break;
547 if (s.enable()) m_t << "<span" << s.attribs().toString() << ">"; else m_t << "</span>";
548 break;
549 }
550}
551
552///--------------------------------------------------------------------------------------
553
555{
556 if (m_hide) return;
557 QCString lang = m_langExt;
558 if (!s.language().isEmpty()) // explicit language setting
559 {
560 lang = s.language();
561 }
562 SrcLangExt langExt = getLanguageFromCodeLang(lang);
563 switch(s.type())
564 {
567 m_ci.startCodeFragment("DoxyCode");
569 s.context(),
570 s.text(),
571 langExt,
572 Config_getBool(STRIP_CODE_COMMENTS),
573 s.isExample(),
574 s.exampleFile(),
575 nullptr, // fileDef
576 -1, // startLine
577 -1, // endLine
578 true, // inlineFragment
579 nullptr, // memberDef
580 true, // show line numbers
581 m_ctx // search context
582 );
583 m_ci.endCodeFragment("DoxyCode");
585 break;
588 m_t << "<pre class=\"fragment\">";
589 filter(s.text());
590 m_t << "</pre>";
592 break;
594 filter(s.text(), true);
595 break;
597 m_t << "<code class=\"JavaDocCode\">";
598 filter(s.text(), true);
599 m_t << "</code>";
600 break;
602 {
603 if (s.isBlock()) forceEndParagraph(s);
604 m_t << s.text();
605 if (s.isBlock()) forceStartParagraph(s);
606 }
607 break;
613 /* nothing */
614 break;
615
616 case DocVerbatim::Dot:
617 {
618 static int dotindex = 1;
619 QCString fileName(4096, QCString::ExplicitSize);
620
622 fileName.sprintf("%s%d%s",
623 qPrint(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_"),
624 dotindex++,
625 ".dot"
626 );
627 std::ofstream file = Portable::openOutputStream(fileName);
628 if (!file.is_open())
629 {
630 err("Could not open file {} for writing\n",fileName);
631 }
632 else
633 {
634 QCString stext = s.text();
635 file.write( stext.data(), stext.length() );
636 file.close();
637
638 m_t << "<div class=\"dotgraph\">\n";
639 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
640 visitCaption(m_t, s);
641 m_t << "</div>\n";
642
643 if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
644 }
646 }
647 break;
648 case DocVerbatim::Msc:
649 {
651
652 static int mscindex = 1;
653 QCString baseName(4096, QCString::ExplicitSize);
654
655 baseName.sprintf("%s%d",
656 qPrint(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_"),
657 mscindex++
658 );
659 std::ofstream file = Portable::openOutputStream(baseName.str()+".msc");
660 if (!file.is_open())
661 {
662 err("Could not open file {}.msc for writing\n",baseName);
663 }
664 else
665 {
666 QCString text = "msc {";
667 text+=s.text();
668 text+="}";
669
670 file.write( text.data(), text.length() );
671 file.close();
672
673 m_t << "<div class=\"mscgraph\">\n";
674 writeMscFile(baseName+".msc",s.relPath(),s.context(),s.srcFile(),s.srcLine());
675 visitCaption(m_t, s);
676 m_t << "</div>\n";
677
678 if (Config_getBool(DOT_CLEANUP)) Dir().remove(baseName.str()+".msc");
679 }
681 }
682 break;
684 {
686 QCString htmlOutput = Config_getString(HTML_OUTPUT);
688 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
689 if (imgExt=="svg")
690 {
692 }
693 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
694 htmlOutput,s.exampleFile(),
695 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
696 for (const auto &baseName: baseNameVector)
697 {
698 m_t << "<div class=\"plantumlgraph\">\n";
699 writePlantUMLFile(QCString(baseName),s.relPath(),s.context(),s.srcFile(),s.srcLine());
700 visitCaption(m_t, s);
701 m_t << "</div>\n";
702 }
704 }
705 break;
706 }
707}
708
710{
711 if (m_hide) return;
712 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
713}
714
716{
717 if (m_hide) return;
719 switch(inc.type())
720 {
723 m_ci.startCodeFragment("DoxyCode");
725 inc.context(),
726 inc.text(),
727 langExt,
728 inc.stripCodeComments(),
729 inc.isExample(),
730 inc.exampleFile(),
731 nullptr, // fileDef
732 -1, // startLine
733 -1, // endLine
734 TRUE, // inlineFragment
735 nullptr, // memberDef
736 FALSE, // show line numbers
737 m_ctx // search context
738 );
739 m_ci.endCodeFragment("DoxyCode");
741 break;
743 {
745 m_ci.startCodeFragment("DoxyCode");
746 FileInfo cfi( inc.file().str() );
747 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
749 inc.context(),
750 inc.text(),
751 langExt,
752 inc.stripCodeComments(),
753 inc.isExample(),
754 inc.exampleFile(),
755 fd.get(), // fileDef,
756 -1, // start line
757 -1, // end line
758 true, // inline fragment
759 nullptr, // memberDef
760 true, // show line numbers
761 m_ctx // search context
762 );
763 m_ci.endCodeFragment("DoxyCode");
765 }
766 break;
774 break;
776 {
777 if (inc.isBlock()) forceEndParagraph(inc);
778 m_t << inc.text();
779 if (inc.isBlock()) forceStartParagraph(inc);
780 }
781 break;
784 m_t << "<pre class=\"fragment\">";
785 filter(inc.text());
786 m_t << "</pre>";
788 break;
792 m_ci.startCodeFragment("DoxyCode");
794 inc.file(),
795 inc.blockId(),
796 inc.context(),
798 inc.trimLeft(),
800 );
801 m_ci.endCodeFragment("DoxyCode");
803 break;
804 }
805}
806
808{
809 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
810 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
811 if (op.isFirst())
812 {
814 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
816 m_hide=TRUE;
817 }
819 if (locLangExt.isEmpty()) locLangExt = m_langExt;
820 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
821 if (op.type()!=DocIncOperator::Skip)
822 {
823 m_hide = popHidden();
824 if (!m_hide)
825 {
826 std::unique_ptr<FileDef> fd;
827 if (!op.includeFileName().isEmpty())
828 {
829 FileInfo cfi( op.includeFileName().str() );
830 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
831 }
832 getCodeParser(locLangExt).parseCode(
833 m_ci,
834 op.context(),
835 op.text(),
836 langExt,
838 op.isExample(),
839 op.exampleFile(),
840 fd.get(), // fileDef
841 op.line(), // startLine
842 -1, // endLine
843 true, // inline fragment
844 nullptr, // memberDef
845 op.showLineNo(), // show line numbers
846 m_ctx // search context
847 );
848 }
850 m_hide=TRUE;
851 }
852 if (op.isLast())
853 {
854 m_hide = popHidden();
855 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
857 }
858 else
859 {
860 if (!m_hide) m_t << "\n";
861 }
862}
863
865{
866 if (m_hide) return;
867 bool bDisplay = !f.isInline();
868 if (bDisplay)
869 {
871 m_t << "<p class=\"formulaDsp\">\n";
872 }
873
874 if (Config_getBool(USE_MATHJAX))
875 {
876 QCString text = f.text();
877 bool closeInline = FALSE;
878 if (!bDisplay && !text.isEmpty() && text.at(0)=='$' &&
879 text.at(text.length()-1)=='$')
880 {
881 closeInline=TRUE;
882 text = text.mid(1,text.length()-2);
883 m_t << "\\(";
884 }
885 else if (!bDisplay && !text.isEmpty())
886 {
887 closeInline=TRUE;
888 m_t << "\\(";
889 }
890 m_t << convertToHtml(text);
891 if (closeInline)
892 {
893 m_t << "\\)";
894 }
895 }
896 else
897 {
898 const Formula *formula = FormulaManager::instance().findFormula(f.id());
899
900 enum class ImageType { Light, Dark };
901 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
902 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> QCString {
903 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
904 TextStream t;
905 QCString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
906 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
907 {
908 t << "<picture>";
909 t << "<source srcset=\"" << f.relPath() << f.name();
910 if (visibility==Visibility::AutoDark)
911 {
912 t << extension;
913 t << "\" media=\"(prefers-color-scheme: light)\"";
914 }
915 else // AutoLight
916 {
917 t << "_dark";
918 t << extension;
919 t << "\" media=\"(prefers-color-scheme: dark)\"";
920 }
921 t << "/>";
922 }
923 t << "<img class=\"formula";
924 t << (bDisplay ? "Dsp" : "Inl");
925 if (visibility==Visibility::Light) t << " light-mode-visible";
926 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
927 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
928 if (imgType==ImageType::Dark) t << "_dark";
929 t << extension;
930 if (formula && formula->width()!=-1)
931 {
932 t << "\" width=\"";
933 t << formula->width();
934 }
935 if (formula && formula->height()!=-1)
936 {
937 t << "\" height=\"";
938 t << formula->height();
939 }
940 t << "\"/>";
941 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
942 {
943 t << "</picture>";
944 }
945 return QCString(t.str());
946 };
947
948 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
949 switch(colorStyle)
950 {
951 case HTML_COLORSTYLE_t::LIGHT:
952 m_t << writeFormula(ImageType::Light,Visibility::Always);
953 break;
954 case HTML_COLORSTYLE_t::DARK:
955 m_t << writeFormula(ImageType::Dark, Visibility::Always);
956 break;
957 case HTML_COLORSTYLE_t::AUTO_LIGHT:
958 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
959 break;
960 case HTML_COLORSTYLE_t::AUTO_DARK:
961 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
962 break;
963 case HTML_COLORSTYLE_t::TOGGLE:
964 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
965 m_t << writeFormula(ImageType::Light,Visibility::Light);
966 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
967 break;
968 }
969 }
970 if (bDisplay)
971 {
972 m_t << "\n</p>\n";
974 }
975}
976
978{
980 if (e.member())
981 {
982 anchor.prepend(e.member()->anchor()+"_");
983 }
984 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
985 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
986 // qPrint(e.entry()),
987 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
988 // e.member() ? qPrint(e.member()->name()) : "<null>"
989 // );
990 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
991}
992
994{
995 m_t << "</dd>\n";
996 m_t << "<dd>\n";
997}
998
1000{
1001 if (m_hide) return;
1002 auto opt = cite.option();
1003 if (!cite.file().isEmpty())
1004 {
1005 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
1006 filter(cite.getText());
1007 if (!opt.noCite()) endLink();
1008 }
1009 else
1010 {
1011 m_t << "<b>";
1012 if (!opt.noPar()) filter("[");
1013 filter(cite.target());
1014 if (!opt.noPar()) filter("]");
1015 m_t << "</b>";
1016 }
1017}
1018
1019
1020//--------------------------------------
1021// visitor functions for compound nodes
1022//--------------------------------------
1023
1024
1026{
1027 //printf("DocAutoList::visitPre\n");
1028 if (m_hide) return;
1030 if (l.isEnumList())
1031 {
1032 //
1033 // Do list type based on depth:
1034 // 1.
1035 // a.
1036 // i.
1037 // A.
1038 // 1. (repeat)...
1039 //
1040 m_t << "<ol type=\"" << g_types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
1041 }
1042 else
1043 {
1044 if (l.isCheckedList())
1045 {
1046 m_t << "<ul class=\"check\">";
1047 }
1048 else
1049 {
1050 m_t << "<ul>";
1051 }
1052 }
1053 if (!l.isPreformatted()) m_t << "\n";
1054 visitChildren(l);
1055 if (l.isEnumList())
1056 {
1057 m_t << "</ol>";
1058 }
1059 else
1060 {
1061 m_t << "</ul>";
1062 }
1063 if (!l.isPreformatted()) m_t << "\n";
1065}
1066
1068{
1069 if (m_hide) return;
1070 switch (li.itemNumber())
1071 {
1072 case DocAutoList::Unchecked: // unchecked
1073 m_t << "<li class=\"unchecked\">";
1074 break;
1075 case DocAutoList::Checked_x: // checked with x
1076 case DocAutoList::Checked_X: // checked with X
1077 m_t << "<li class=\"checked\">";
1078 break;
1079 default:
1080 m_t << "<li>";
1081 break;
1082 }
1083 visitChildren(li);
1084 m_t << "</li>";
1085 if (!li.isPreformatted()) m_t << "\n";
1086}
1087
1088template<class Node>
1089static bool holds_value(const Node *val,const DocNodeVariant &v)
1090{
1091 bool b = std::visit([&](auto &&x) {
1092 //printf("holds_value val=%s (%p) v=%s (%p)\n",
1093 // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
1094 return val==static_cast<const DocNode*>(&x);
1095 }, v);
1096 return b;
1097}
1098
1099template<class T>
1100bool isFirstChildNode(const T *parent, const DocPara &node)
1101{
1102 return !parent->children().empty() && holds_value(&node,parent->children().front());
1103}
1104
1105template<class T>
1106bool isLastChildNode(const T *parent, const DocPara &node)
1107{
1108 return !parent->children().empty() && holds_value(&node,parent->children().back());
1109}
1110
1112{
1113 const DocNodeList &nodes = parent.children();
1114 auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
1115 if (it==std::end(nodes)) return FALSE;
1116 size_t count = parent.children().size();
1117 auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=nullptr; };
1118 if (count>1 && it==std::begin(nodes)) // it points to first node
1119 {
1120 return isSeparator(std::next(it));
1121 }
1122 else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
1123 {
1124 return isSeparator(std::prev(it));
1125 }
1126 else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
1127 {
1128 return isSeparator(std::prev(it)) && isSeparator(std::next(it));
1129 }
1130 return false;
1131}
1132
1133static contexts_t getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
1134{
1136 isFirst=FALSE;
1137 isLast=FALSE;
1138 if (p.parent())
1139 {
1140 const auto parBlock = std::get_if<DocParBlock>(p.parent());
1141 if (parBlock)
1142 {
1143 // hierarchy: node N -> para -> parblock -> para
1144 // adapt return value to kind of N
1145 const DocNodeVariant *p3 = nullptr;
1146 if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
1147 {
1148 p3 = ::parent(::parent(p.parent()));
1149 }
1150 isFirst=isFirstChildNode(parBlock,p);
1151 isLast =isLastChildNode (parBlock,p);
1152 bool isLI = p3!=nullptr && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
1154 bool isTD = p3!=nullptr && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
1156 if (isFirst)
1157 {
1158 if (isLI) t=contexts_t::STARTLI; else if (isDD) t=contexts_t::STARTDD; else if (isTD) t=contexts_t::STARTTD;
1159 }
1160 if (isLast)
1161 {
1162 if (isLI) t=contexts_t::ENDLI; else if (isDD) t=contexts_t::ENDDD; else if (isTD) t=contexts_t::ENDTD;
1163 }
1164 if (!isFirst && !isLast)
1165 {
1166 if (isLI) t=contexts_t::INTERLI; else if (isDD) t=contexts_t::INTERDD; else if (isTD) t=contexts_t::INTERTD;
1167 }
1168 return t;
1169 }
1170 const auto docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
1171 if (docAutoListItem)
1172 {
1173 isFirst=isFirstChildNode(docAutoListItem,p);
1174 isLast =isLastChildNode (docAutoListItem,p);
1175 t=contexts_t::STARTLI; // not used
1176 return t;
1177 }
1178 const auto docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
1179 if (docSimpleListItem)
1180 {
1181 isFirst=TRUE;
1182 isLast =TRUE;
1183 t=contexts_t::STARTLI; // not used
1184 return t;
1185 }
1186 const auto docParamList = std::get_if<DocParamList>(p.parent());
1187 if (docParamList)
1188 {
1189 isFirst=TRUE;
1190 isLast =TRUE;
1191 t=contexts_t::STARTLI; // not used
1192 return t;
1193 }
1194 const auto docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
1195 if (docHtmlListItem)
1196 {
1197 isFirst=isFirstChildNode(docHtmlListItem,p);
1198 isLast =isLastChildNode (docHtmlListItem,p);
1199 if (isFirst) t=contexts_t::STARTLI;
1200 if (isLast) t=contexts_t::ENDLI;
1201 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1202 return t;
1203 }
1204 const auto docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
1205 if (docSecRefItem)
1206 {
1207 isFirst=isFirstChildNode(docSecRefItem,p);
1208 isLast =isLastChildNode (docSecRefItem,p);
1209 if (isFirst) t=contexts_t::STARTLI;
1210 if (isLast) t=contexts_t::ENDLI;
1211 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1212 return t;
1213 }
1214 const auto docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
1215 if (docHtmlDescData)
1216 {
1217 isFirst=isFirstChildNode(docHtmlDescData,p);
1218 isLast =isLastChildNode (docHtmlDescData,p);
1219 if (isFirst) t=contexts_t::STARTDD;
1220 if (isLast) t=contexts_t::ENDDD;
1221 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1222 return t;
1223 }
1224 const auto docXRefItem = std::get_if<DocXRefItem>(p.parent());
1225 if (docXRefItem)
1226 {
1227 isFirst=isFirstChildNode(docXRefItem,p);
1228 isLast =isLastChildNode (docXRefItem,p);
1229 if (isFirst) t=contexts_t::STARTDD;
1230 if (isLast) t=contexts_t::ENDDD;
1231 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1232 return t;
1233 }
1234 const auto docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
1235 if (docSimpleSect)
1236 {
1237 isFirst=isFirstChildNode(docSimpleSect,p);
1238 isLast =isLastChildNode (docSimpleSect,p);
1239 if (isFirst) t=contexts_t::STARTDD;
1240 if (isLast) t=contexts_t::ENDDD;
1241 if (isSeparatedParagraph(*docSimpleSect,p))
1242 // if the paragraph is enclosed with separators it will
1243 // be included in <dd>..</dd> so avoid addition paragraph
1244 // markers
1245 {
1246 isFirst=isLast=TRUE;
1247 }
1248 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1249 return t;
1250 }
1251 const auto docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
1252 if (docHtmlCell)
1253 {
1254 isFirst=isFirstChildNode(docHtmlCell,p);
1255 isLast =isLastChildNode (docHtmlCell,p);
1256 if (isFirst) t=contexts_t::STARTTD;
1257 if (isLast) t=contexts_t::ENDTD;
1258 if (!isFirst && !isLast) t = contexts_t::INTERTD;
1259 return t;
1260 }
1261 }
1262 return t;
1263}
1264
1265static bool determineIfNeedsTag(const DocPara &p)
1266{
1267 bool needsTag = FALSE;
1268 if (p.parent())
1269 {
1283 >(*p.parent()))
1284 {
1285 needsTag = TRUE;
1286 }
1287 else if (std::get_if<DocRoot>(p.parent()))
1288 {
1289 needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
1290 }
1291 }
1292 return needsTag;
1293}
1294
1296{
1297 if (m_hide) return;
1298
1299 //printf("> DocPara\n");
1300 //dumpDocNodeList(p.children());
1301
1302 bool needsTag = determineIfNeedsTag(p);
1303 //printf(" needsTag=%d\n",needsTag);
1304 bool needsTagBefore = needsTag;
1305 bool needsTagAfter = needsTag;
1306
1307 // if the first element of a paragraph is something that should be outside of
1308 // the paragraph (<ul>,<dl>,<table>,..) then that will already started the
1309 // paragraph and we don't need to do it here
1310 if (!p.children().empty())
1311 {
1312 auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
1313 [](const auto &node) { return !isInvisibleNode(node); });
1314 if (it!=std::end(p.children()))
1315 {
1316 const DocNodeVariant &n = *it;
1318 {
1319 needsTagBefore = FALSE;
1320 }
1321 }
1322 }
1323
1324 // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
1325 // this allows us to mark the tag with a special class so we can
1326 // fix the otherwise ugly spacing.
1327 bool isFirst = false;
1328 bool isLast = false;
1329 contexts_t t = getParagraphContext(p,isFirst,isLast);
1330 //printf("startPara first=%d last=%d\n",isFirst,isLast);
1331 if (isFirst && isLast) needsTagBefore=FALSE;
1332
1333 //printf(" needsTagBefore=%d\n",needsTagBefore);
1334 // write the paragraph tag (if needed)
1335 if (needsTagBefore)
1336 {
1337 if (contexts(t))
1338 m_t << "<p class=\"" << contexts(t) << "\"" << p.attribs().toString() << ">";
1339 else
1340 m_t << "<p" << p.attribs().toString() << ">";
1341 }
1342
1343 visitChildren(p);
1344
1345 // if the last element of a paragraph is something that should be outside of
1346 // the paragraph (<ul>,<dl>,<table>) then that will already have ended the
1347 // paragraph and we don't need to do it here
1348 if (!p.children().empty())
1349 {
1350 auto it = std::prev(std::end(p.children()));
1351 for (;;)
1352 {
1353 const DocNodeVariant &n = *it;
1354 if (!isInvisibleNode(n))
1355 {
1357 {
1358 needsTagAfter = FALSE;
1359 }
1360 // stop searching if we found a node that is visible
1361 break;
1362 }
1363 if (it==std::begin(p.children()))
1364 {
1365 // stop searching if we are at the beginning of the list
1366 break;
1367 }
1368 else
1369 {
1370 --it;
1371 }
1372 }
1373 }
1374
1375 //printf("endPara first=%d last=%d\n",isFirst,isLast);
1376 if (isFirst && isLast) needsTagAfter=FALSE;
1377
1378 //printf(" needsTagAfter=%d\n",needsTagAfter);
1379 if (needsTagAfter) m_t << "</p>\n";
1380 //printf("< DocPara\n");
1381}
1382
1384{
1385 //printf("> DocRoot\n");
1386 //dumpDocNodeList(r.children());
1387 visitChildren(r);
1388 //printf("< DocRoot\n");
1389}
1390
1392{
1393 if (m_hide) return;
1395 m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
1396 switch(s.type())
1397 {
1398 case DocSimpleSect::See:
1399 m_t << theTranslator->trSeeAlso(); break;
1401 m_t << theTranslator->trReturns(); break;
1403 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
1405 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
1407 m_t << theTranslator->trVersion(); break;
1409 m_t << theTranslator->trSince(); break;
1411 m_t << theTranslator->trDate(); break;
1413 m_t << theTranslator->trNote(); break;
1415 m_t << theTranslator->trWarning(); break;
1416 case DocSimpleSect::Pre:
1417 m_t << theTranslator->trPrecondition(); break;
1419 m_t << theTranslator->trPostcondition(); break;
1421 m_t << theTranslator->trCopyright(); break;
1423 m_t << theTranslator->trInvariant(); break;
1425 m_t << theTranslator->trRemarks(); break;
1427 m_t << theTranslator->trAttention(); break;
1429 m_t << theTranslator->trImportant(); break;
1430 case DocSimpleSect::User: break;
1431 case DocSimpleSect::Rcs: break;
1432 case DocSimpleSect::Unknown: break;
1433 }
1434
1435 if (s.title())
1436 {
1437 std::visit(*this,*s.title());
1438 }
1439 m_t << "</dt><dd>";
1440 visitChildren(s);
1441 m_t << "</dd></dl>\n";
1443}
1444
1446{
1447 if (m_hide) return;
1448 visitChildren(t);
1449}
1450
1452{
1453 if (m_hide) return;
1455 m_t << "<ul>";
1456 if (!sl.isPreformatted()) m_t << "\n";
1457 visitChildren(sl);
1458 m_t << "</ul>";
1459 if (!sl.isPreformatted()) m_t << "\n";
1461}
1462
1464{
1465 if (m_hide) return;
1466 m_t << "<li>";
1467 if (li.paragraph())
1468 {
1469 visit(*this,*li.paragraph());
1470 }
1471 m_t << "</li>";
1472 if (!li.isPreformatted()) m_t << "\n";
1473}
1474
1476{
1477 if (m_hide) return;
1479 m_t << "<h" << s.level() << " class=\"doxsection\">";
1480 m_t << "<a class=\"anchor\" id=\"" << s.anchor();
1481 m_t << "\"></a>\n";
1482 if (s.title())
1483 {
1484 std::visit(*this,*s.title());
1485 }
1486 m_t << "</h" << s.level() << ">\n";
1487 visitChildren(s);
1489}
1490
1492{
1493 if (m_hide) return;
1495 if (s.type()==DocHtmlList::Ordered)
1496 {
1497 m_t << "<ol" << s.attribs().toString();
1498 }
1499 else
1500 {
1501 m_t << "<ul" << s.attribs().toString();
1502 }
1503 m_t << ">\n";
1504 visitChildren(s);
1505 if (s.type()==DocHtmlList::Ordered)
1506 {
1507 m_t << "</ol>";
1508 }
1509 else
1510 {
1511 m_t << "</ul>";
1512 }
1513 if (!s.isPreformatted()) m_t << "\n";
1515}
1516
1518{
1519 if (m_hide) return;
1520 m_t << "<li" << i.attribs().toString() << ">";
1521 if (!i.isPreformatted()) m_t << "\n";
1522 visitChildren(i);
1523 m_t << "</li>\n";
1524}
1525
1527{
1528 if (m_hide) return;
1530 m_t << "<dl" << dl.attribs().toString() << ">\n";
1531 visitChildren(dl);
1532 m_t << "</dl>\n";
1534}
1535
1537{
1538 if (m_hide) return;
1539 m_t << "<dt" << dt.attribs().toString() << ">";
1540 visitChildren(dt);
1541 m_t << "</dt>\n";
1542}
1543
1545{
1546 if (m_hide) return;
1547 m_t << "<dd" << dd.attribs().toString() << ">";
1548 visitChildren(dd);
1549 m_t << "</dd>\n";
1550}
1551
1553{
1554 if (m_hide) return;
1555
1557
1558 if (t.caption())
1559 {
1560 QCString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
1561 if (!anc.isEmpty())
1562 {
1563 m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
1564 }
1565 }
1566
1567 QCString attrs = t.attribs().toString();
1568 if (attrs.isEmpty())
1569 {
1570 m_t << "<table class=\"doxtable\">\n";
1571 }
1572 else
1573 {
1574 m_t << "<table" << t.attribs().toString() << ">\n";
1575 }
1576 if (t.caption())
1577 {
1578 std::visit(*this,*t.caption());
1579 }
1580 visitChildren(t);
1581 m_t << "</table>\n";
1583}
1584
1586{
1587 if (m_hide) return;
1588 m_t << "<tr" << tr.attribs().toString() << ">\n";
1589 visitChildren(tr);
1590 m_t << "</tr>\n";
1591}
1592
1594{
1595 if (m_hide) return;
1596 if (c.isHeading())
1597 {
1598 m_t << "<th" << c.attribs().toString() << ">";
1599 }
1600 else
1601 {
1602 m_t << "<td" << c.attribs().toString() << ">";
1603 }
1604 visitChildren(c);
1605 if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
1606}
1607
1609{
1610 if (m_hide) return;
1611 m_t << "<caption" << c.attribs().toString() << ">";
1612 visitChildren(c);
1613 m_t << "</caption>\n";
1614}
1615
1617{
1618 if (m_hide) return;
1619 visitChildren(i);
1620}
1621
1623{
1624 if (m_hide) return;
1625 if (href.url().startsWith("mailto:"))
1626 {
1628 }
1629 else
1630 {
1631 QCString url = correctURL(href.url(),href.relPath());
1632 m_t << "<a href=\"" << convertToHtml(url) << "\""
1633 << href.attribs().toString() << ">";
1634 }
1635 visitChildren(href);
1636 m_t << "</a>";
1637}
1638
1640{
1641 if (m_hide) return;
1642 m_t << "<summary " << s.attribs().toString() << ">\n";
1643 visitChildren(s);
1644 m_t << "</summary>\n";
1645}
1646
1648{
1649 if (m_hide) return;
1651 m_t << "<details " << d.attribs().toString() << ">\n";
1652 auto summary = d.summary();
1653 if (summary)
1654 {
1655 std::visit(*this,*summary);
1656 }
1657 visitChildren(d);
1658 m_t << "</details>\n";
1660}
1661
1663{
1664 if (m_hide) return;
1665 forceEndParagraph(header);
1666 m_t << "<h" << header.level() << header.attribs().toString() << ">";
1667 visitChildren(header);
1668 m_t << "</h" << header.level() << ">\n";
1669 forceStartParagraph(header);
1670}
1671
1673{
1674 if (img.type()==DocImage::Html)
1675 {
1676 bool inlineImage = img.isInlineImage();
1677 bool typeSVG = img.isSVG();
1678 QCString url = img.url();
1679
1680 if (!inlineImage)
1681 {
1682 forceEndParagraph(img);
1683 }
1684 if (m_hide) return;
1685 QCString baseName=makeShortName(img.name());
1686 if (!inlineImage) m_t << "<div class=\"image\">\n";
1687 QCString sizeAttribs;
1688 if (!img.width().isEmpty())
1689 {
1690 sizeAttribs+=" width=\""+img.width()+"\"";
1691 }
1692 if (!img.height().isEmpty()) // link to local file
1693 {
1694 sizeAttribs+=" height=\""+img.height()+"\"";
1695 }
1696 // 16 cases: url.isEmpty() | typeSVG | inlineImage | img.hasCaption()
1697
1698 HtmlAttribList attribs = img.attribs();
1699 if (typeSVG)
1700 {
1701 attribs.mergeAttribute("style","pointer-events: none;");
1702 }
1703 QCString alt;
1704 QCString attrs = attribs.toString(&alt);
1705 QCString src;
1706 if (url.isEmpty())
1707 {
1708 src = img.relPath()+img.name();
1709 }
1710 else
1711 {
1712 src = correctURL(url,img.relPath());
1713 }
1714 if (typeSVG && !inlineImage && !src.startsWith("http://") && !src.startsWith("https://"))
1715 {
1716 m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src)
1717 << "\"" << sizeAttribs << attrs;
1718 if (inlineImage)
1719 {
1720 // skip closing tag
1721 }
1722 else
1723 {
1724 m_t << ">" << alt << "</object>\n";
1725 }
1726 }
1727 else
1728 {
1729 m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs;
1730 if (inlineImage)
1731 {
1732 m_t << " class=\"inline\"";
1733 }
1734 else
1735 {
1736 m_t << "/>\n";
1737 }
1738 }
1739 if (img.hasCaption())
1740 {
1741 if (inlineImage)
1742 {
1743 m_t << " title=\"";
1744 m_insideTitle=true;
1745 }
1746 else
1747 {
1748 m_t << "<div class=\"caption\">\n";
1749 }
1750 }
1751 else if (inlineImage)
1752 {
1753 m_t << "/>";
1754 }
1755
1756 visitChildren(img);
1757
1758 if (img.hasCaption())
1759 {
1760 if (inlineImage)
1761 {
1762 m_t << "\"/>";
1763 m_insideTitle=false;
1764 }
1765 else // end <div class="caption">
1766 {
1767 m_t << "</div>";
1768 }
1769 }
1770 if (!inlineImage) // end <div class="image">
1771 {
1772 m_t << "</div>\n";
1774 }
1775 }
1776 else // other format -> skip
1777 {
1778 }
1779}
1780
1782{
1783 if (m_hide) return;
1784 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1786 m_t << "<div class=\"dotgraph\">\n";
1787 writeDotFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1788 if (df.hasCaption())
1789 {
1790 m_t << "<div class=\"caption\">\n";
1791 }
1792 visitChildren(df);
1793 if (df.hasCaption())
1794 {
1795 m_t << "</div>\n";
1796 }
1797 m_t << "</div>\n";
1799}
1800
1802{
1803 if (m_hide) return;
1804 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1806 m_t << "<div class=\"mscgraph\">\n";
1807 writeMscFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1808 if (df.hasCaption())
1809 {
1810 m_t << "<div class=\"caption\">\n";
1811 }
1812 visitChildren(df);
1813 if (df.hasCaption())
1814 {
1815 m_t << "</div>\n";
1816 }
1817 m_t << "</div>\n";
1819}
1820
1822{
1823 if (m_hide) return;
1824 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1826 m_t << "<div class=\"diagraph\">\n";
1827 writeDiaFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1828 if (df.hasCaption())
1829 {
1830 m_t << "<div class=\"caption\">\n";
1831 }
1832 visitChildren(df);
1833 if (df.hasCaption())
1834 {
1835 m_t << "</div>\n";
1836 }
1837 m_t << "</div>\n";
1839}
1840
1842{
1843 if (m_hide) return;
1844 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1846 QCString htmlOutput = Config_getString(HTML_OUTPUT);
1847 QCString imgExt = getDotImageExtension();
1848 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
1849 if (imgExt=="svg")
1850 {
1852 }
1853 std::string inBuf;
1854 readInputFile(df.file(),inBuf);
1855 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(htmlOutput,QCString(),
1856 inBuf.c_str(),format,QCString(),df.srcFile(),df.srcLine(),false);
1857 for (const auto &bName: baseNameVector)
1858 {
1859 QCString baseName=makeBaseName(QCString(bName));
1860 m_t << "<div class=\"plantumlgraph\">\n";
1861 writePlantUMLFile(baseName,df.relPath(),QCString(),df.srcFile(),df.srcLine());
1862 if (df.hasCaption())
1863 {
1864 m_t << "<div class=\"caption\">\n";
1865 }
1866 visitChildren(df);
1867 if (df.hasCaption())
1868 {
1869 m_t << "</div>\n";
1870 }
1871 m_t << "</div>\n";
1872 }
1874}
1875
1877{
1878 if (m_hide) return;
1879 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1880 visitChildren(lnk);
1881 endLink();
1882}
1883
1885{
1886 if (m_hide) return;
1887 if (!ref.file().isEmpty())
1888 {
1889 // when ref.isSubPage()==TRUE we use ref.file() for HTML and
1890 // ref.anchor() for LaTeX/RTF
1891 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1892 }
1893 if (!ref.hasLinkText()) filter(ref.targetTitle());
1894 visitChildren(ref);
1895 if (!ref.file().isEmpty()) endLink();
1896 //m_t << " ";
1897}
1898
1900{
1901 if (m_hide) return;
1902 if (!ref.file().isEmpty())
1903 {
1904 m_t << "<li>";
1905 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1906 }
1907 visitChildren(ref);
1908 if (!ref.file().isEmpty())
1909 {
1910 endLink();
1911 m_t << "</li>\n";
1912 }
1913}
1914
1916{
1917 if (m_hide) return;
1919 m_t << "<div>\n";
1920 m_t << "<ul class=\"multicol\">\n";
1921 visitChildren(s);
1922 m_t << "</ul>\n";
1923 m_t << "</div>\n";
1925}
1926
1928{
1929 if (m_hide) return;
1931 QCString className;
1932 QCString heading;
1933 switch(s.type())
1934 {
1936 heading=theTranslator->trParameters();
1937 className="params";
1938 break;
1940 heading=theTranslator->trReturnValues();
1941 className="retval";
1942 break;
1944 heading=theTranslator->trExceptions();
1945 className="exception";
1946 break;
1948 heading=theTranslator->trTemplateParameters();
1949 className="tparams";
1950 break;
1951 default:
1952 ASSERT(0);
1953 }
1954 m_t << "<dl class=\"" << className << "\"><dt>";
1955 m_t << heading;
1956 m_t << "</dt><dd>\n";
1957 m_t << " <table class=\"" << className << "\">\n";
1958 visitChildren(s);
1959 m_t << " </table>\n";
1960 m_t << " </dd>\n";
1961 m_t << "</dl>\n";
1963}
1964
1966{
1967 if (m_hide) return;
1968 m_t << "&#160;" << s.chars() << "&#160;";
1969}
1970
1972{
1973 //printf("DocParamList::visitPre\n");
1974 if (m_hide) return;
1975 m_t << " <tr>";
1976 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
1977 if (sect && sect->hasInOutSpecifier())
1978 {
1979 m_t << "<td class=\"paramdir\">";
1981 {
1982 m_t << "[";
1983 if (pl.direction()==DocParamSect::In)
1984 {
1985 m_t << "in";
1986 }
1987 else if (pl.direction()==DocParamSect::Out)
1988 {
1989 m_t << "out";
1990 }
1991 else if (pl.direction()==DocParamSect::InOut)
1992 {
1993 m_t << "in,out";
1994 }
1995 m_t << "]";
1996 }
1997 m_t << "</td>";
1998 }
1999 if (sect && sect->hasTypeSpecifier())
2000 {
2001 m_t << "<td class=\"paramtype\">";
2002 for (const auto &type : pl.paramTypes())
2003 {
2004 std::visit(*this,type);
2005 }
2006 m_t << "</td>";
2007 }
2008 m_t << "<td class=\"paramname\">";
2009 bool first=TRUE;
2010 for (const auto &param : pl.parameters())
2011 {
2012 if (!first) m_t << ","; else first=FALSE;
2013 std::visit(*this,param);
2014 }
2015 m_t << "</td><td>";
2016 for (const auto &par : pl.paragraphs())
2017 {
2018 std::visit(*this,par);
2019 }
2020 m_t << "</td></tr>\n";
2021}
2022
2024{
2025 if (m_hide) return;
2026 if (x.title().isEmpty()) return;
2027
2029 bool anonymousEnum = x.file()=="@";
2030 if (!anonymousEnum)
2031 {
2032 QCString fn = x.file();
2034 m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
2035 << x.relPath() << fn
2036 << "#" << x.anchor() << "\">";
2037 }
2038 else
2039 {
2040 m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
2041 }
2042 filter(x.title());
2043 if (!anonymousEnum) m_t << "</a>";
2044 m_t << "</b></dt><dd>";
2045 visitChildren(x);
2046 if (x.title().isEmpty()) return;
2047 m_t << "</dd></dl>\n";
2049}
2050
2052{
2053 if (m_hide) return;
2054 startLink(QCString(),ref.file(),ref.relPath(),ref.anchor());
2055 visitChildren(ref);
2056 endLink();
2057 m_t << " ";
2058}
2059
2061{
2062 visitChildren(t);
2063}
2064
2066{
2067 if (m_hide) return;
2069 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2070 visitChildren(b);
2071 m_t << "</blockquote>\n";
2073}
2074
2076{
2077 if (m_hide) return;
2078 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2079 {
2082 m_t << "<p>";
2083 m_t << theTranslator->trFlowchart();
2084 m_t << " ";
2085 m_t << "<a href=\"";
2086 m_t << fname;
2087 m_t << ".svg\">";
2089 m_t << "</a>";
2090 if (vf.hasCaption())
2091 {
2092 m_t << "<br />";
2093 }
2094 }
2095 visitChildren(vf);
2096 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2097 {
2098 m_t << "</p>";
2100 }
2101}
2102
2104{
2105 if (m_hide) return;
2106 visitChildren(pb);
2107}
2108
2109void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
2110{
2111 if (str.isEmpty()) return;
2112 const char *p=str.data();
2113 while (*p)
2114 {
2115 char c=*p++;
2116 switch(c)
2117 {
2118 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2119 case '<': m_t << "&lt;"; break;
2120 case '>': m_t << "&gt;"; break;
2121 case '&': m_t << "&amp;"; break;
2122 case '\\': if ((*p == '(') || (*p == ')'))
2123 m_t << "\\&zwj;" << *p++;
2124 else
2125 m_t << c;
2126 break;
2127 default:
2128 {
2129 uint8_t uc = static_cast<uint8_t>(c);
2130 if (uc<32 && !isspace(c)) // non-printable control characters
2131 {
2132 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2133 }
2134 else
2135 {
2136 m_t << c;
2137 }
2138 }
2139 break;
2140 }
2141 }
2142}
2143
2144/// Escape basic entities to produce a valid CDATA attribute value,
2145/// assume that the outer quoting will be using the double quote &quot;
2147{
2148 GrowBuf growBuf;
2149 if (str.isEmpty()) return str;
2150 const char *p=str.data();
2151 while (*p)
2152 {
2153 char c=*p++;
2154 switch(c)
2155 {
2156 case '&': growBuf.addStr("&amp;"); break;
2157 case '"': growBuf.addStr("&quot;"); break;
2158 case '<': growBuf.addStr("&lt;"); break;
2159 case '>': growBuf.addStr("&gt;"); break;
2160 case '\\':
2161 if ((*p == '(') || (*p == ')'))
2162 {
2163 growBuf.addStr("\\&zwj;");
2164 growBuf.addChar(*p++);
2165 }
2166 else
2167 {
2168 growBuf.addChar(c);
2169 }
2170 break;
2171 default:
2172 {
2173 uint8_t uc = static_cast<uint8_t>(c);
2174 if (uc<32 && !isspace(c)) // non-printable control characters
2175 {
2176 growBuf.addStr("&#x24");
2177 growBuf.addChar(hex[uc>>4]);
2178 growBuf.addChar(hex[uc&0xF]);
2179 growBuf.addStr(";");
2180 }
2181 else
2182 {
2183 growBuf.addChar(c);
2184 }
2185 }
2186 break;
2187 }
2188 }
2189 growBuf.addChar(0);
2190 return growBuf.get();
2191}
2192
2193void HtmlDocVisitor::startLink(const QCString &ref,const QCString &file,
2194 const QCString &relPath,const QCString &anchor,
2195 const QCString &tooltip)
2196{
2197 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2198 if (!ref.isEmpty()) // link to entity imported via tag file
2199 {
2200 m_t << "<a class=\"elRef\" ";
2202 }
2203 else // local link
2204 {
2205 m_t << "<a class=\"el\" ";
2206 }
2207 m_t << "href=\"";
2208 QCString fn = file;
2210 m_t << createHtmlUrl(relPath,ref,true,
2211 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2212 fn,
2213 anchor);
2214 m_t << "\"";
2215 if (!tooltip.isEmpty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2216 m_t << ">";
2217}
2218
2220{
2221 m_t << "</a>";
2222}
2223
2224void HtmlDocVisitor::writeDotFile(const QCString &fn,const QCString &relPath,
2225 const QCString &context,const QCString &srcFile,int srcLine)
2226{
2227 QCString baseName=makeBaseName(fn);
2228 baseName.prepend("dot_");
2229 QCString outDir = Config_getString(HTML_OUTPUT);
2230 writeDotGraphFromFile(fn,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2231 writeDotImageMapFromFile(m_t,fn,outDir,relPath,baseName,context,-1,srcFile,srcLine);
2232}
2233
2234void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,
2235 const QCString &context,const QCString &srcFile,int srcLine)
2236{
2237 QCString baseName=makeBaseName(fileName);
2238 baseName.prepend("msc_");
2239 QCString outDir = Config_getString(HTML_OUTPUT);
2240 QCString imgExt = getDotImageExtension();
2242 if ("svg" == imgExt)
2243 mscFormat = MscOutputFormat::SVG;
2244 writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
2245 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2246}
2247
2248void HtmlDocVisitor::writeDiaFile(const QCString &fileName, const QCString &relPath,
2249 const QCString &,const QCString &srcFile,int srcLine)
2250{
2251 QCString baseName=makeBaseName(fileName);
2252 baseName.prepend("dia_");
2253 QCString outDir = Config_getString(HTML_OUTPUT);
2254 writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine);
2255
2256 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2257}
2258
2259void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString &relPath,
2260 const QCString &,const QCString &/* srcFile */,int /* srcLine */)
2261{
2262 QCString baseName=makeBaseName(fileName);
2263 QCString outDir = Config_getString(HTML_OUTPUT);
2264 QCString imgExt = getDotImageExtension();
2265 if (imgExt=="svg")
2266 {
2268 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2269 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2270 //m_t << "</iframe>\n";
2271 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2272 }
2273 else
2274 {
2276 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2277 }
2278}
2279
2280/** Returns TRUE if the child nodes in paragraph \a para until \a nodeIndex
2281 contain a style change node that is still active and that style change is one that
2282 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2283 See also bug746162.
2284 */
2287{
2288 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2289 int styleMask=0;
2290 bool styleOutsideParagraph=FALSE;
2291 while (!styleOutsideParagraph)
2292 {
2293 const DocNodeVariant *n = &(*it);
2294 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2295 if (sc)
2296 {
2297 if (!sc->enable()) // remember styles that has been closed already
2298 {
2299 styleMask|=static_cast<int>(sc->style());
2300 }
2301 bool paraStyle = sc->style()==DocStyleChange::Center ||
2302 sc->style()==DocStyleChange::Div ||
2304 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2305 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2306 paraStyle
2307 )
2308 {
2309 styleOutsideParagraph=TRUE;
2310 }
2311 }
2312 if (it!=std::begin(para->children()))
2313 {
2314 --it;
2315 }
2316 else
2317 {
2318 break;
2319 }
2320 }
2321 return styleOutsideParagraph;
2322}
2323
2324/** Used for items found inside a paragraph, which due to XHTML restrictions
2325 * have to be outside of the paragraph. This method will forcefully end
2326 * the current paragraph and forceStartParagraph() will restart it.
2327 */
2328template<class Node>
2330{
2331 const DocPara *para=std::get_if<DocPara>(n.parent());
2332 if (para)
2333 {
2334 const DocNodeList &children = para->children();
2335
2336 //printf("forceEndParagraph\n");
2337 //dumpDocNodeList(children);
2338
2339 auto it = std::find_if(std::begin(children),std::end(children),
2340 [&n](const auto &np) { return holds_value(&n,np); });
2341 if (it==std::end(children)) return;
2342 if (it==std::begin(children)) return; // first node in paragraph
2343 it = std::prev(it);
2344 bool found=false;
2345 while (!found)
2346 {
2347 found = !isInvisibleNode(*it);
2348 if (found) break;
2349 if (it!=std::begin(children))
2350 {
2351 --it;
2352 }
2353 else
2354 {
2355 break;
2356 }
2357 }
2358 if (!found) return; // first visible node in paragraph
2359 const DocNodeVariant &v = *it;
2360 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2361 bool styleOutsideParagraph=false;
2362 if (it!=std::begin(children))
2363 {
2364 it = std::prev(it);
2365 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2366 }
2367 bool isFirst = false;
2368 bool isLast = false;
2369 getParagraphContext(*para,isFirst,isLast);
2370 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2371 if (isFirst && isLast) return;
2372 if (styleOutsideParagraph) return;
2373
2374 //printf("adding </p>\n");
2375 m_t << "</p>";
2376 }
2377}
2378
2379/** Used for items found inside a paragraph, which due to XHTML restrictions
2380 * have to be outside of the paragraph. This method will forcefully start
2381 * the paragraph, that was previously ended by forceEndParagraph().
2382 */
2383template<class Node>
2385{
2386 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2387 const DocPara *para=nullptr;
2388 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2389 {
2390 const DocNodeList &children = para->children();
2391
2392 auto it = std::find_if(std::begin(children),
2393 std::end(children),
2394 [&n](const auto &np)
2395 { return holds_value(&n,np); });
2396 if (it==std::end(children)) return;
2397 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2398 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2399 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2400 if (styleOutsideParagraph) return;
2401 it = std::next(it);
2402 while (it!=std::end(children) && isInvisibleNode(*it))
2403 {
2404 ++it;
2405 }
2406 if (it!=std::end(children))
2407 {
2408 const DocNodeVariant &v = *it;
2409 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2410 }
2411 else
2412 {
2413 return; // only whitespace at the end!
2414 }
2415
2416 bool needsTag = true;
2417 bool isFirst = false;
2418 bool isLast = false;
2419 getParagraphContext(*para,isFirst,isLast);
2420 if (isFirst && isLast) needsTag = false;
2421 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2422
2423 if (needsTag) m_t << "<p>";
2424 }
2425}
2426
void parseCodeFragment(OutputCodeList &codeOutList, const QCString &fileName, const QCString &blockId, const QCString &scopeName, bool showLineNumbers, bool trimLeft, bool stripCodeComments)
static CodeFragmentManager & instance()
virtual void parseCode(OutputCodeList &codeOutList, const QCString &scopeName, const QCString &input, SrcLangExt lang, bool stripCodeComments, bool isExampleBlock, const QCString &exampleName=QCString(), const FileDef *fileDef=nullptr, int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, const MemberDef *memberDef=nullptr, bool showLineNumbers=TRUE, const Definition *searchCtx=nullptr, bool collectXRefs=TRUE)=0
Parses a source file or fragment with the goal to produce highlighted and cross-referenced output.
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual QCString anchor() const =0
virtual QCString getDefFileExtension() const =0
virtual const QCString & name() const =0
Class representing a directory in the file system.
Definition dir.h:75
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:314
Node representing an anchor.
Definition docnode.h:229
const HtmlAttribList & attribs() const
Definition docnode.h:235
QCString anchor() const
Definition docnode.h:232
Node representing an auto List.
Definition docnode.h:571
bool isCheckedList() const
Definition docnode.h:582
bool isEnumList() const
Definition docnode.h:580
int depth() const
Definition docnode.h:583
Node representing an item of a auto list.
Definition docnode.h:595
int itemNumber() const
Definition docnode.h:598
Node representing a citation of some bibliographic reference.
Definition docnode.h:245
QCString getText() const
Definition docnode.cpp:939
QCString relPath() const
Definition docnode.h:249
CiteInfoOption option() const
Definition docnode.h:253
QCString target() const
Definition docnode.h:252
QCString anchor() const
Definition docnode.h:251
QCString ref() const
Definition docnode.h:250
QCString file() const
Definition docnode.h:248
DocNodeList & children()
Definition docnode.h:143
Node representing a dia file.
Definition docnode.h:731
QCString relPath() const
Definition docnode.h:686
QCString srcFile() const
Definition docnode.h:691
QCString file() const
Definition docnode.h:685
int srcLine() const
Definition docnode.h:692
bool hasCaption() const
Definition docnode.h:687
QCString context() const
Definition docnode.h:690
Node representing a dot file.
Definition docnode.h:713
Node representing an emoji.
Definition docnode.h:341
int index() const
Definition docnode.h:345
QCString name() const
Definition docnode.h:344
Node representing an item of a cross-referenced list.
Definition docnode.h:529
QCString text() const
Definition docnode.h:533
QCString name() const
Definition docnode.h:532
bool isInline() const
Definition docnode.h:536
int id() const
Definition docnode.h:535
QCString relPath() const
Definition docnode.h:534
Node representing a Hypertext reference.
Definition docnode.h:823
QCString url() const
Definition docnode.h:830
QCString relPath() const
Definition docnode.h:832
const HtmlAttribList & attribs() const
Definition docnode.h:833
Node representing a horizontal ruler.
Definition docnode.h:216
const HtmlAttribList & attribs() const
Definition docnode.h:221
Node representing an HTML blockquote.
Definition docnode.h:1291
const HtmlAttribList & attribs() const
Definition docnode.h:1296
Node representing a HTML table caption.
Definition docnode.h:1228
const HtmlAttribList & attribs() const
Definition docnode.h:1231
Node representing a HTML table cell.
Definition docnode.h:1193
bool isHeading() const
Definition docnode.h:1200
const HtmlAttribList & attribs() const
Definition docnode.h:1205
Node representing a HTML description data.
Definition docnode.h:1181
const HtmlAttribList & attribs() const
Definition docnode.h:1184
Node representing a Html description list.
Definition docnode.h:901
const HtmlAttribList & attribs() const
Definition docnode.h:905
Node representing a Html description item.
Definition docnode.h:888
const HtmlAttribList & attribs() const
Definition docnode.h:892
Node Html details.
Definition docnode.h:857
const HtmlAttribList & attribs() const
Definition docnode.h:861
const DocNodeVariant * summary() const
Definition docnode.h:864
Node Html heading.
Definition docnode.h:873
const HtmlAttribList & attribs() const
Definition docnode.h:878
int level() const
Definition docnode.h:877
Node representing a Html list.
Definition docnode.h:1000
const HtmlAttribList & attribs() const
Definition docnode.h:1006
Type type() const
Definition docnode.h:1005
Node representing a HTML list item.
Definition docnode.h:1165
const HtmlAttribList & attribs() const
Definition docnode.h:1170
Node representing a HTML table row.
Definition docnode.h:1246
const HtmlAttribList & attribs() const
Definition docnode.h:1252
Node Html summary.
Definition docnode.h:844
const HtmlAttribList & attribs() const
Definition docnode.h:848
Node representing a HTML table.
Definition docnode.h:1269
const DocNodeVariant * caption() const
Definition docnode.cpp:2141
const HtmlAttribList & attribs() const
Definition docnode.h:1275
Node representing an image.
Definition docnode.h:642
const HtmlAttribList & attribs() const
Definition docnode.h:656
QCString relPath() const
Definition docnode.h:652
QCString name() const
Definition docnode.h:648
QCString url() const
Definition docnode.h:653
QCString height() const
Definition docnode.h:651
Type type() const
Definition docnode.h:647
QCString width() const
Definition docnode.h:650
bool isInlineImage() const
Definition docnode.h:654
bool isSVG() const
Definition docnode.cpp:1287
bool hasCaption() const
Definition docnode.h:649
Node representing a include/dontinclude operator block.
Definition docnode.h:477
bool stripCodeComments() const
Definition docnode.h:506
bool isLast() const
Definition docnode.h:503
QCString includeFileName() const
Definition docnode.h:509
QCString text() const
Definition docnode.h:499
QCString context() const
Definition docnode.h:501
QCString exampleFile() const
Definition docnode.h:508
int line() const
Definition docnode.h:497
Type type() const
Definition docnode.h:485
bool isFirst() const
Definition docnode.h:502
bool showLineNo() const
Definition docnode.h:498
bool isExample() const
Definition docnode.h:507
Node representing an included text block from file.
Definition docnode.h:435
QCString blockId() const
Definition docnode.h:454
QCString extension() const
Definition docnode.h:450
bool isBlock() const
Definition docnode.h:458
bool stripCodeComments() const
Definition docnode.h:455
@ LatexInclude
Definition docnode.h:437
@ SnippetWithLines
Definition docnode.h:438
@ DontIncWithLines
Definition docnode.h:439
@ IncWithLines
Definition docnode.h:438
@ HtmlInclude
Definition docnode.h:437
@ VerbInclude
Definition docnode.h:437
@ DontInclude
Definition docnode.h:437
@ DocbookInclude
Definition docnode.h:439
Type type() const
Definition docnode.h:451
QCString exampleFile() const
Definition docnode.h:457
QCString text() const
Definition docnode.h:452
QCString file() const
Definition docnode.h:449
bool trimLeft() const
Definition docnode.h:459
bool isExample() const
Definition docnode.h:456
QCString context() const
Definition docnode.h:453
Node representing an entry in the index.
Definition docnode.h:552
QCString entry() const
Definition docnode.h:559
const Definition * scope() const
Definition docnode.h:557
const MemberDef * member() const
Definition docnode.h:558
Node representing an internal section of documentation.
Definition docnode.h:969
Node representing an internal reference to some item.
Definition docnode.h:807
QCString file() const
Definition docnode.h:811
QCString relPath() const
Definition docnode.h:812
QCString anchor() const
Definition docnode.h:813
Node representing a line break.
Definition docnode.h:202
const HtmlAttribList & attribs() const
Definition docnode.h:208
Node representing a word that can be linked to something.
Definition docnode.h:165
QCString file() const
Definition docnode.h:171
QCString relPath() const
Definition docnode.h:172
QCString ref() const
Definition docnode.h:173
QCString word() const
Definition docnode.h:170
QCString anchor() const
Definition docnode.h:174
QCString tooltip() const
Definition docnode.h:175
Node representing a msc file.
Definition docnode.h:722
Abstract node interface with type information.
Definition docnode.h:82
bool isPreformatted() const
Definition docnode.h:105
DocNodeVariant * parent()
Definition docnode.h:90
Node representing an block of paragraphs.
Definition docnode.h:979
Node representing a paragraph in the documentation tree.
Definition docnode.h:1080
const HtmlAttribList & attribs() const
Definition docnode.h:1114
Node representing a parameter list.
Definition docnode.h:1125
const DocNodeList & parameters() const
Definition docnode.h:1129
const DocNodeList & paramTypes() const
Definition docnode.h:1130
DocParamSect::Direction direction() const
Definition docnode.h:1133
const DocNodeList & paragraphs() const
Definition docnode.h:1131
Node representing a parameter section.
Definition docnode.h:1053
bool hasInOutSpecifier() const
Definition docnode.h:1069
bool hasTypeSpecifier() const
Definition docnode.h:1070
Type type() const
Definition docnode.h:1068
Node representing a uml file.
Definition docnode.h:740
Node representing a reference to some item.
Definition docnode.h:778
QCString anchor() const
Definition docnode.h:785
QCString relPath() const
Definition docnode.h:783
QCString targetTitle() const
Definition docnode.h:786
bool isSubPage() const
Definition docnode.h:792
QCString file() const
Definition docnode.h:782
QCString ref() const
Definition docnode.h:784
bool hasLinkText() const
Definition docnode.h:788
Root node of documentation tree.
Definition docnode.h:1313
Node representing a reference to a section.
Definition docnode.h:935
QCString relPath() const
Definition docnode.h:941
QCString file() const
Definition docnode.h:939
QCString anchor() const
Definition docnode.h:940
QCString ref() const
Definition docnode.h:942
bool isSubPage() const
Definition docnode.h:944
Node representing a list of section references.
Definition docnode.h:959
Node representing a normal section.
Definition docnode.h:914
int level() const
Definition docnode.h:918
QCString anchor() const
Definition docnode.h:920
const DocNodeVariant * title() const
Definition docnode.h:919
Node representing a separator.
Definition docnode.h:365
QCString chars() const
Definition docnode.h:369
Node representing a simple list.
Definition docnode.h:990
Node representing a simple list item.
Definition docnode.h:1153
const DocNodeVariant * paragraph() const
Definition docnode.h:1157
Node representing a simple section.
Definition docnode.h:1017
QCString typeString() const
Definition docnode.cpp:3129
Type type() const
Definition docnode.h:1026
const DocNodeVariant * title() const
Definition docnode.h:1033
Node representing a separator between two simple sections of the same type.
Definition docnode.h:1044
Node representing a style change.
Definition docnode.h:268
const HtmlAttribList & attribs() const
Definition docnode.h:311
QCString tagName() const
Definition docnode.h:312
Style style() const
Definition docnode.h:307
bool enable() const
Definition docnode.h:309
Node representing a special symbol.
Definition docnode.h:328
HtmlEntityMapper::SymType symbol() const
Definition docnode.h:332
Root node of a text fragment.
Definition docnode.h:1304
Node representing a simple section title.
Definition docnode.h:608
Node representing a URL (or email address)
Definition docnode.h:188
QCString url() const
Definition docnode.h:192
bool isEmail() const
Definition docnode.h:193
Node representing a verbatim, unparsed text fragment.
Definition docnode.h:376
QCString srcFile() const
Definition docnode.h:397
int srcLine() const
Definition docnode.h:398
QCString language() const
Definition docnode.h:388
bool isBlock() const
Definition docnode.h:389
bool isExample() const
Definition docnode.h:385
QCString context() const
Definition docnode.h:384
Type type() const
Definition docnode.h:382
QCString text() const
Definition docnode.h:383
QCString exampleFile() const
Definition docnode.h:386
QCString engine() const
Definition docnode.h:393
QCString relPath() const
Definition docnode.h:387
@ JavaDocLiteral
Definition docnode.h:378
Node representing a VHDL flow chart.
Definition docnode.h:749
bool hasCaption() const
Definition docnode.h:753
CodeParserInterface & getCodeParser(const QCString &langExt)
void pushHidden(bool hide)
bool popHidden()
Node representing some amount of white space.
Definition docnode.h:354
QCString chars() const
Definition docnode.h:358
Node representing a word.
Definition docnode.h:153
QCString word() const
Definition docnode.h:156
Node representing an item of a cross-referenced list.
Definition docnode.h:621
QCString anchor() const
Definition docnode.h:625
QCString key() const
Definition docnode.h:628
QCString relPath() const
Definition docnode.h:627
QCString file() const
Definition docnode.h:624
QCString title() const
Definition docnode.h:626
static IndexList * indexList
Definition doxygen.h:134
const char * unicode(int index) const
Access routine to the unicode sequence for the Emoji entity.
Definition emoji.cpp:2016
static EmojiEntityMapper & instance()
Returns the one and only instance of the Emoji entity mapper.
Definition emoji.cpp:1978
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
std::string fileName() const
Definition fileinfo.cpp:118
std::string dirPath(bool absPath=true) const
Definition fileinfo.cpp:137
static QCString convertNameToFileName()
Class representing a LaTeX formula as found in the documentation.
Definition formula.h:29
int width() const
Definition formula.h:34
int height() const
Definition formula.h:35
const Formula * findFormula(int formulaId) const
Definition formula.cpp:705
static FormulaManager & instance()
Definition formula.cpp:54
Class representing a string buffer optimized for growing.
Definition growbuf.h:28
void addChar(char c)
Definition growbuf.h:69
void addStr(const QCString &s)
Definition growbuf.h:72
char * get()
Definition growbuf.h:114
Iterator< const GrowVector, const DocNodeVariant > const_iterator
Definition growvector.h:80
bool empty() const
checks whether the container is empty
Definition growvector.h:140
Class representing a list of HTML attributes.
Definition htmlattrib.h:33
QCString toString(QCString *pAltValue=nullptr) const
Definition htmlattrib.h:49
void mergeAttribute(const QCString &optName, const QCString &optValue)
Definition htmlattrib.h:35
HtmlDocVisitor(TextStream &t, OutputCodeList &ci, const Definition *ctx, const QCString &fn=QCString())
TextStream & m_t
void writePlantUMLFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
QCString filterQuotedCdataAttr(const QCString &str)
Escape basic entities to produce a valid CDATA attribute value, assume that the outer quoting will be...
void writeDotFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
void forceStartParagraph(const DocNode &n)
void operator()(const DocWord &)
void startLink(const QCString &ref, const QCString &file, const QCString &relPath, const QCString &anchor, const QCString &tooltip="")
void visitCaption(TextStream &t, const T &n)
OutputCodeList & m_ci
void writeDiaFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
void writeMscFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
void visitChildren(const T &t)
void filter(const QCString &str, const bool retainNewline=false)
void forceEndParagraph(const DocNode &n)
const Definition * m_ctx
void writeObfuscatedMailAddress(const QCString &url)
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
const char * html(SymType symb, bool useInPrintf=FALSE) const
Access routine to the html code of the HTML entity.
Class representing a list of different code generators.
Definition outputlist.h:164
OutputFormat
Plant UML output image formats.
Definition plantuml.h:44
StringVector writePlantUMLSource(const QCString &outDirArg, const QCString &fileName, const QCString &content, OutputFormat format, const QCString &engine, const QCString &srcFile, int srcLine, bool inlineCode)
Write a PlantUML compatible file.
Definition plantuml.cpp:31
static PlantumlManager & instance()
Definition plantuml.cpp:231
void generatePlantUMLOutput(const QCString &baseName, const QCString &outDir, OutputFormat format)
Convert a PlantUML file to an image.
Definition plantuml.cpp:202
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:407
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool startsWith(const char *s) const
Definition qcstring.h:492
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
const std::string & str() const
Definition qcstring.h:537
QCString & setNum(short n)
Definition qcstring.h:444
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
@ ExplicitSize
Definition qcstring.h:133
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159
QCString left(size_t len) const
Definition qcstring.h:214
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:229
static const MemberDef * getFlowMember()
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
#define Config_getEnum(name)
Definition config.h:35
void writeDiaGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, DiaOutputFormat format, const QCString &srcFile, int srcLine)
Definition dia.cpp:26
static constexpr auto hex
static QCString makeBaseName(const QCString &name)
static QCString makeShortName(const QCString &baseName)
std::variant< DocWord, DocLinkedWord, DocURL, DocLineBreak, DocHorRuler, DocAnchor, DocCite, DocStyleChange, DocSymbol, DocEmoji, DocWhiteSpace, DocSeparator, DocVerbatim, DocInclude, DocIncOperator, DocFormula, DocIndexEntry, DocAutoList, DocAutoListItem, DocTitle, DocXRefItem, DocImage, DocDotFile, DocMscFile, DocDiaFile, DocVhdlFlow, DocLink, DocRef, DocInternalRef, DocHRef, DocHtmlHeader, DocHtmlDescTitle, DocHtmlDescList, DocSection, DocSecRefItem, DocSecRefList, DocInternal, DocParBlock, DocSimpleList, DocHtmlList, DocSimpleSect, DocSimpleSectSep, DocParamSect, DocPara, DocParamList, DocSimpleListItem, DocHtmlListItem, DocHtmlDescData, DocHtmlCell, DocHtmlCaption, DocHtmlRow, DocHtmlTable, DocHtmlBlockQuote, DocText, DocRoot, DocHtmlDetails, DocHtmlSummary, DocPlantUmlFile > DocNodeVariant
Definition docnode.h:67
constexpr bool holds_one_of_alternatives(const DocNodeVariant &v)
returns true iff v holds one of types passed as template parameters
Definition docnode.h:1366
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1330
void writeDotImageMapFromFile(TextStream &t, const QCString &inFile, const QCString &outDir, const QCString &relPath, const QCString &baseName, const QCString &context, int graphId, const QCString &srcFile, int srcLine)
Definition dot.cpp:283
void writeDotGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, GraphOutputFormat format, const QCString &srcFile, int srcLine)
Definition dot.cpp:230
std::unique_ptr< FileDef > createFileDef(const QCString &p, const QCString &n, const QCString &ref, const QCString &dn)
Definition filedef.cpp:268
static bool isInvisibleNode(const DocNodeVariant &node)
static bool determineIfNeedsTag(const DocPara &p)
static const char g_types[][NUM_HTML_LIST_TYPES]
static constexpr const char * contexts(contexts_t type)
contexts_t
bool isFirstChildNode(const T *parent, const DocPara &node)
static const int NUM_HTML_LIST_TYPES
static QCString convertIndexWordToAnchor(const QCString &word)
static contexts_t getParagraphContext(const DocPara &p, bool &isFirst, bool &isLast)
static QCString makeBaseName(const QCString &name)
static bool mustBeOutsideParagraph(const DocNodeVariant &n)
static bool isDocVerbatimVisible(const DocVerbatim &s)
static bool insideStyleChangeThatIsOutsideParagraph(const DocPara *para, DocNodeList::const_iterator it)
Returns TRUE if the child nodes in paragraph para until nodeIndex contain a style change node that is...
static bool holds_value(const Node *val, const DocNodeVariant &v)
static bool isDocIncOperatorVisible(const DocIncOperator &s)
bool isSeparatedParagraph(const DocSimpleSect &parent, const DocPara &par)
bool isLastChildNode(const T *parent, const DocPara &node)
static QCString makeShortName(const QCString &name)
static bool isDocIncludeVisible(const DocInclude &s)
Translator * theTranslator
Definition language.cpp:71
#define err(fmt,...)
Definition message.h:127
void writeMscImageMapFromFile(TextStream &t, const QCString &inFile, const QCString &outDir, const QCString &relPath, const QCString &baseName, const QCString &context, MscOutputFormat format, const QCString &srcFile, int srcLine)
Definition msc.cpp:233
void writeMscGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, MscOutputFormat format, const QCString &srcFile, int srcLine)
Definition msc.cpp:157
MscOutputFormat
Definition msc.h:22
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:665
Portable versions of functions that are platform dependent.
const char * qPrint(const char *s)
Definition qcstring.h:672
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
SrcLangExt
Definition types.h:207
const char * writeUTF8Char(TextStream &t, const char *s)
Writes the UTF8 character pointed to by s to stream t and returns a pointer to the next character.
Definition utf8.cpp:197
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5718
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:4476
QCString correctURL(const QCString &url, const QCString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:6438
QCString stripPath(const QCString &s)
Definition util.cpp:5461
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:6047
SrcLangExt getLanguageFromCodeLang(QCString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:5736
QCString getDotImageExtension()
Definition util.cpp:6800
bool copyFile(const QCString &src, const QCString &dest)
Copies the contents of file with name src to the newly created file with name dest.
Definition util.cpp:6370
QCString externalLinkTarget(const bool parent)
Definition util.cpp:6222
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5760
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5412
QCString createHtmlUrl(const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
Definition util.cpp:6233
A bunch of utility functions.