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 "mermaid.h"
37#include "formula.h"
38#include "fileinfo.h"
39#include "indexlist.h"
40#include "portable.h"
41#include "codefragment.h"
42#include "cite.h"
43#include "md5.h"
44
45static const int NUM_HTML_LIST_TYPES = 4;
46static const char g_types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};
47enum class contexts_t
48{
49 NONE, // 0
50 STARTLI, // 1
51 STARTDD, // 2
52 ENDLI, // 3
53 ENDDD, // 4
54 STARTTD, // 5
55 ENDTD, // 6
56 INTERLI, // 7
57 INTERDD, // 8
59};
60
61static constexpr const char *contexts(contexts_t type)
62{
63 switch (type)
64 {
65 case contexts_t::NONE: return nullptr;
66 case contexts_t::STARTLI: return "startli";
67 case contexts_t::STARTDD: return "startdd";
68 case contexts_t::ENDLI: return "endli";
69 case contexts_t::ENDDD: return "enddd";
70 case contexts_t::STARTTD: return "starttd";
71 case contexts_t::ENDTD: return "endtd";
72 case contexts_t::INTERLI: return "interli";
73 case contexts_t::INTERDD: return "interdd";
74 case contexts_t::INTERTD: return "intertd";
75 default: return nullptr;
76 }
77}
78static const char *hex="0123456789ABCDEF";
79
81{
82 static int cnt = 0;
83 QCString result="a";
84 QCString cntStr;
85 result += cntStr.setNum(cnt);
86 result += "_";
87 cnt++;
88 const char *str = word.data();
89 unsigned char c = 0;
90 if (str)
91 {
92 while ((c = *str++))
93 {
94 if ((c >= 'a' && c <= 'z') || // ALPHA
95 (c >= 'A' && c <= 'Z') || // ALPHA
96 (c >= '0' && c <= '9') || // DIGIT
97 c == '-' ||
98 c == '.'
99 )
100 {
101 result += c;
102 }
103 else
104 {
105 char enc[4];
106 enc[0] = '_';
107 enc[1] = hex[(c & 0xf0) >> 4];
108 enc[2] = hex[c & 0xf];
109 enc[3] = 0;
110 result += enc;
111 }
112 }
113 }
114 return result;
115}
116
117
118
120{
121 //printf("mustBeOutsideParagraph(%s)=",docNodeName(n));
124 /* <table> */ DocHtmlTable,
125 /* <h?> */ DocSection, DocHtmlHeader,
126 /* \internal */ DocInternal,
127 /* <div> */ DocInclude, DocSecRefList,
128 /* <hr> */ DocHorRuler,
129 /* <blockquote> */ DocHtmlBlockQuote,
130 /* \parblock */ DocParBlock,
131 /* \dotfile */ DocDotFile,
132 /* \mscfile */ DocMscFile,
133 /* \diafile */ DocDiaFile,
134 /* \plantumlfile */ DocPlantUmlFile,
135 /* \mermaidfile */ DocMermaidFile,
136 /* <details> */ DocHtmlDetails,
137 /* <summary> */ DocHtmlSummary,
138 DocIncOperator >(n))
139 {
140 return TRUE;
141 }
142 const DocVerbatim *dv = std::get_if<DocVerbatim>(&n);
143 if (dv)
144 {
145 DocVerbatim::Type t = dv->type();
147 return t!=DocVerbatim::HtmlOnly || dv->isBlock();
148 }
149 const DocStyleChange *sc = std::get_if<DocStyleChange>(&n);
150 if (sc)
151 {
152 return sc->style()==DocStyleChange::Preformatted ||
153 sc->style()==DocStyleChange::Div ||
155 }
156 const DocFormula *df = std::get_if<DocFormula>(&n);
157 if (df)
158 {
159 return !df->isInline();
160 }
161 const DocImage *di = std::get_if<DocImage>(&n);
162 if (di)
163 {
164 return !di->isInlineImage();
165 }
166 return FALSE;
167}
168
170{
171 switch (s.type())
172 {
178 return FALSE;
179 default:
180 return TRUE;
181 }
182}
183
184static bool isDocIncludeVisible(const DocInclude &s)
185{
186 switch (s.type())
187 {
194 return FALSE;
195 default:
196 return TRUE;
197 }
198}
199
201{
202 switch (s.type())
203 {
205 return FALSE;
206 default:
207 return TRUE;
208 }
209}
210
211static bool isInvisibleNode(const DocNodeVariant &node)
212{
213 //printf("isInvisibleNode(%s)\n",docNodeName(node));
214 // skip over white space
215 const DocWhiteSpace *ws = std::get_if<DocWhiteSpace>(&node);
216 if (ws) return true;
217 // skip over image nodes that are not for HTML output
218 const DocImage *di = std::get_if<DocImage>(&node);
219 if (di) return di->type()!=DocImage::Html;
220 // skip over verbatim nodes that are not visible in the HTML output
221 const DocVerbatim *dv = std::get_if<DocVerbatim>(&node);
222 if (dv) return !isDocVerbatimVisible(*dv);
223 // skip over include nodes that are not visible in the HTML output
224 const DocInclude *dinc = std::get_if<DocInclude>(&node);
225 if (dinc) return !isDocIncludeVisible(*dinc);
226 const DocIncOperator *dio = std::get_if<DocIncOperator>(&node);
227 // skip over include operator nodes that are not visible in the HTML output
228 if (dio) return !isDocIncOperatorVisible(*dio);
229 return false;
230}
231
232//-------------------------------------------------------------------------
233
235 const Definition *ctx,const QCString &fn)
236 : m_t(t), m_ci(ci), m_ctx(ctx), m_fileName(fn)
237{
238 if (ctx) m_langExt=ctx->getDefFileExtension();
239}
240
241template<class T>
243{
244 if (n.hasCaption())
245 {
246 t << "<div class=\"caption\">\n";
247 for (const auto &child : n.children())
248 {
249 std::visit(*this, child);
250 }
251 t << "</div>\n";
252 }
253}
254
255 //--------------------------------------
256 // visitor functions for leaf nodes
257 //--------------------------------------
258
260{
261 if (m_hide) return;
262 filter(w.word());
263}
264
266{
267 if (m_hide) return;
268 //printf("linked word: %s\n",qPrint(w.word()));
269 startLink(w.ref(),w.file(),w.relPath(),w.anchor(),w.tooltip());
270 filter(w.word());
271 endLink();
272}
273
275{
276 if (m_hide) return;
277 if (m_insidePre)
278 {
279 m_t << w.chars();
280 }
281 else
282 {
283 m_t << " ";
284 }
285}
286
288{
289 if (m_hide) return;
290 if (m_insideTitle &&
291 (s.symbol()==HtmlEntityMapper::Sym_Quot || s.symbol()==HtmlEntityMapper::Sym_quot)) // escape "'s inside title="..."
292 {
293 m_t << "&quot;";
294 }
295 else
296 {
297 const char *res = HtmlEntityMapper::instance().html(s.symbol());
298 if (res)
299 {
300 m_t << res;
301 }
302 else
303 {
304 err("HTML: non supported HTML-entity found: {}\n",
306 }
307 }
308}
309
311{
312 if (m_hide) return;
313 const char *res = EmojiEntityMapper::instance().unicode(s.index());
314 if (res)
315 {
316 m_t << "<span class=\"emoji\">" << res << "</span>";
317 }
318 else
319 {
320 m_t << s.name();
321 }
322}
323
325{
326 if (!Config_getBool(OBFUSCATE_EMAILS))
327 {
328 m_t << "<a href=\"mailto:" << url << "\">";
329 }
330 else
331 {
332 m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'";
333 if (!url.isEmpty())
334 {
335 const char *p = url.data();
336 uint32_t size=3;
337 while (*p)
338 {
339 m_t << "+'";
340 for (uint32_t j=0;j<size && *p;j++)
341 {
342 p = writeUTF8Char(m_t,p);
343 }
344 m_t << "'";
345 if (size==3) size=2; else size=3;
346 }
347 }
348 m_t << "; return false;\">";
349 }
350}
351
353{
354 if (m_hide) return;
355 if (u.isEmail()) // mail address
356 {
357 QCString url = u.url();
358 // obfuscate the mail address link
360 if (!Config_getBool(OBFUSCATE_EMAILS))
361 {
362 m_t << url;
363 }
364 else
365 {
366 const char *p = url.data();
367 // also obfuscate the address as shown on the web page
368 uint32_t size=5;
369 while (*p)
370 {
371 for (uint32_t j=0;j<size && *p;j++)
372 {
373 p = writeUTF8Char(m_t,p);
374 }
375 if (*p) m_t << "<span class=\"obfuscator\">.nosp@m.</span>";
376 if (size==5) size=4; else size=5;
377 }
378 }
379 m_t << "</a>";
380 }
381 else // web address
382 {
383 m_t << "<a href=\"";
384 filter(u.url());
385 m_t << "\">";
386 filter(u.url());
387 m_t << "</a>";
388 }
389}
390
392{
393 if (m_hide) return;
394 m_t << "<br "<< br.attribs().toString() << " />\n";
395}
396
398{
399 if (m_hide) return;
401 m_t << "<hr "<< hr.attribs().toString() << " />\n";
403}
404
406{
407 if (m_hide) return;
408 switch (s.style())
409 {
411 if (s.enable()) m_t << "<b" << s.attribs().toString() << ">"; else m_t << "</b>";
412 break;
414 if (s.enable()) m_t << "<s" << s.attribs().toString() << ">"; else m_t << "</s>";
415 break;
417 if (s.enable()) m_t << "<strike" << s.attribs().toString() << ">"; else m_t << "</strike>";
418 break;
420 if (s.enable()) m_t << "<del" << s.attribs().toString() << ">"; else m_t << "</del>";
421 break;
423 if (s.enable()) m_t << "<u" << s.attribs().toString() << ">"; else m_t << "</u>";
424 break;
426 if (s.enable()) m_t << "<ins" << s.attribs().toString() << ">"; else m_t << "</ins>";
427 break;
429 if (s.enable())
430 {
431 auto attribs = s.attribs();
432 if (s.tagName()=="a")
433 {
434 attribs.mergeAttribute("class","arg");
435 }
436 m_t << "<em" << attribs.toString() << ">";
437 }
438 else
439 {
440 m_t << "</em>";
441 }
442 break;
444 if (s.enable()) m_t << "<kbd" << s.attribs().toString() << ">"; else m_t << "</kbd>";
445 break;
447 if (s.enable())
448 {
449 m_t << "<span class=\"tt\"" << s.attribs().toString() << ">";
450 m_insidePre=true;
451 }
452 else
453 {
454 m_t << "</span>";
455 m_insidePre=false;
456 }
457 break;
459 if (s.enable())
460 {
461 auto attribs = s.attribs();
462 if (s.tagName()=="p")
463 {
464 attribs.mergeAttribute("class","param");
465 }
466 m_t << "<code" << attribs.toString() << ">";
467 m_insidePre=true;
468 }
469 else
470 {
471 m_insidePre=false;
472 m_t << "</code>";
473 }
474 break;
476 if (s.enable()) m_t << "<sub" << s.attribs().toString() << ">"; else m_t << "</sub>";
477 break;
479 if (s.enable()) m_t << "<sup" << s.attribs().toString() << ">"; else m_t << "</sup>";
480 break;
482 if (s.enable())
483 {
485 m_t << "<center" << s.attribs().toString() << ">";
486 }
487 else
488 {
489 m_t << "</center>";
491 }
492 break;
494 if (s.enable()) m_t << "<small" << s.attribs().toString() << ">"; else m_t << "</small>";
495 break;
497 if (s.enable()) m_t << "<cite" << s.attribs().toString() << ">"; else m_t << "</cite>";
498 break;
500 if (s.enable())
501 {
503 m_t << "<pre" << s.attribs().toString() << ">";
505 }
506 else
507 {
509 m_t << "</pre>";
511 }
512 break;
514 if (s.enable())
515 {
517 m_t << "<div" << s.attribs().toString() << ">";
518 }
519 else
520 {
521 m_t << "</div>";
523 }
524 break;
526 if (s.enable()) m_t << "<span" << s.attribs().toString() << ">"; else m_t << "</span>";
527 break;
528 }
529}
530
531///--------------------------------------------------------------------------------------
532
534{
535 if (m_hide) return;
536 QCString lang = m_langExt;
537 if (!s.language().isEmpty()) // explicit language setting
538 {
539 lang = s.language();
540 }
541 SrcLangExt langExt = getLanguageFromCodeLang(lang);
542 switch(s.type())
543 {
546 m_ci.startCodeFragment("DoxyCode");
548 s.context(),
549 s.text(),
550 langExt,
551 Config_getBool(STRIP_CODE_COMMENTS),
553 .setExample(s.isExample(), s.exampleFile())
554 .setInlineFragment(true)
556 );
557 m_ci.endCodeFragment("DoxyCode");
559 break;
562 m_t << "<pre class=\"fragment\">";
563 filter(s.text());
564 m_t << "</pre>";
566 break;
568 filter(s.text(), true);
569 break;
571 m_t << "<code class=\"JavaDocCode\">";
572 filter(s.text(), true);
573 m_t << "</code>";
574 break;
576 {
577 if (s.isBlock()) forceEndParagraph(s);
578 m_t << s.text();
579 if (s.isBlock()) forceStartParagraph(s);
580 }
581 break;
587 /* nothing */
588 break;
589
590 case DocVerbatim::Dot:
591 {
593
594 bool exists = false;
595 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_", // baseName
596 ".dot", // extension
597 s.text(), // contents
598 exists);
599 if (!fileName.isEmpty())
600 {
601 m_t << "<div class=\"dotgraph\">\n";
602 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
603 visitCaption(m_t, s);
604 m_t << "</div>\n";
605 }
606
608 }
609 break;
610 case DocVerbatim::Msc:
611 {
613
614 bool exists = false;
615 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_", // baseName
616 ".msc", // extension
617 "msc {"+s.text()+"}", // contents
618 exists);
619 if (!fileName.isEmpty())
620 {
621 m_t << "<div class=\"mscgraph\">\n";
622 writeMscFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
623 visitCaption(m_t, s);
624 m_t << "</div>\n";
625 }
626
628 }
629 break;
631 {
633 QCString htmlOutput = Config_getString(HTML_OUTPUT);
635 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
636 if (imgExt=="svg")
637 {
639 }
640 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
641 htmlOutput,s.exampleFile(),
642 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
643 for (const auto &baseName: baseNameVector)
644 {
645 m_t << "<div class=\"plantumlgraph\">\n";
646 writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
647 visitCaption(m_t, s);
648 m_t << "</div>\n";
649 }
651 }
652 break;
654 {
656 if (Config_getEnum(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLI) // CLI mode: pre-generate image via mmdc
657 {
658 QCString htmlOutput = Config_getString(HTML_OUTPUT);
661 if (imgExt=="svg")
662 {
664 }
666 htmlOutput,s.exampleFile(),
667 s.text(),format,s.srcFile(),s.srcLine());
668 m_t << "<div class=\"mermaidgraph\">\n";
669 writeMermaidFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
670 visitCaption(m_t, s);
671 m_t << "</div>\n";
672 }
673 else // CLIENT_SIDE or AUTO mode: embed for client-side rendering
674 {
675 m_t << "<div class=\"mermaidgraph\">\n";
676 m_t << "<pre class=\"mermaid\">\n";
677 m_t << convertToHtml(s.text());
678 m_t << "</pre>\n";
679 visitCaption(m_t, s);
680 m_t << "</div>\n";
681 }
683 }
684 break;
685 }
686}
687
689{
690 if (m_hide) return;
691 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
692}
693
695{
696 if (m_hide) return;
698 switch(inc.type())
699 {
702 m_ci.startCodeFragment("DoxyCode");
704 inc.context(),
705 inc.text(),
706 langExt,
707 inc.stripCodeComments(),
709 .setExample(inc.isExample(), inc.exampleFile())
710 .setInlineFragment(true)
711 .setShowLineNumbers(false)
713 );
714 m_ci.endCodeFragment("DoxyCode");
716 break;
718 {
720 m_ci.startCodeFragment("DoxyCode");
721 FileInfo cfi( inc.file().str() );
722 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
724 inc.context(),
725 inc.text(),
726 langExt,
727 inc.stripCodeComments(),
729 .setExample(inc.isExample(), inc.exampleFile())
730 .setFileDef(fd.get())
731 .setInlineFragment(true)
733 );
734 m_ci.endCodeFragment("DoxyCode");
736 }
737 break;
745 break;
747 {
748 if (inc.isBlock()) forceEndParagraph(inc);
749 m_t << inc.text();
750 if (inc.isBlock()) forceStartParagraph(inc);
751 }
752 break;
755 m_t << "<pre class=\"fragment\">";
756 filter(inc.text());
757 m_t << "</pre>";
759 break;
763 m_ci.startCodeFragment("DoxyCode");
765 inc.file(),
766 inc.blockId(),
767 inc.context(),
769 inc.trimLeft(),
771 );
772 m_ci.endCodeFragment("DoxyCode");
774 break;
775 }
776}
777
779{
780 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
781 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
782 if (op.isFirst())
783 {
785 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
787 m_hide=TRUE;
788 }
790 if (locLangExt.isEmpty()) locLangExt = m_langExt;
791 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
792 if (op.type()!=DocIncOperator::Skip)
793 {
794 m_hide = popHidden();
795 if (!m_hide)
796 {
797 std::unique_ptr<FileDef> fd;
798 if (!op.includeFileName().isEmpty())
799 {
800 FileInfo cfi( op.includeFileName().str() );
801 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
802 }
803 getCodeParser(locLangExt).parseCode(
804 m_ci,
805 op.context(),
806 op.text(),
807 langExt,
810 .setExample(op.isExample(), op.exampleFile())
811 .setFileDef(fd.get())
812 .setStartLine(op.line())
815 );
816 }
818 m_hide=TRUE;
819 }
820 if (op.isLast())
821 {
822 m_hide = popHidden();
823 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
825 }
826 else
827 {
828 if (!m_hide) m_t << "\n";
829 }
830}
831
833{
834 if (m_hide) return;
835 bool bDisplay = !f.isInline();
836 if (bDisplay)
837 {
839 m_t << "<p class=\"formulaDsp\">\n";
840 }
841
842 if (Config_getBool(USE_MATHJAX))
843 {
844 QCString text = f.text();
845 bool closeInline = FALSE;
846 if (!bDisplay && !text.isEmpty() && text.at(0)=='$' &&
847 text.at(text.length()-1)=='$')
848 {
849 closeInline=TRUE;
850 text = text.mid(1,text.length()-2);
851 m_t << "\\(";
852 }
853 else if (!bDisplay && !text.isEmpty())
854 {
855 closeInline=TRUE;
856 m_t << "\\(";
857 }
858 m_t << convertToHtml(text);
859 if (closeInline)
860 {
861 m_t << "\\)";
862 }
863 }
864 else
865 {
866 const Formula *formula = FormulaManager::instance().findFormula(f.id());
867
868 enum class ImageType { Light, Dark };
869 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
870 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> QCString {
871 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
872 TextStream t;
873 QCString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
874 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
875 {
876 t << "<picture>";
877 t << "<source srcset=\"" << f.relPath() << f.name();
878 if (visibility==Visibility::AutoDark)
879 {
880 t << extension;
881 t << "\" media=\"(prefers-color-scheme: light)\"";
882 }
883 else // AutoLight
884 {
885 t << "_dark";
886 t << extension;
887 t << "\" media=\"(prefers-color-scheme: dark)\"";
888 }
889 t << "/>";
890 }
891 t << "<img class=\"formula";
892 t << (bDisplay ? "Dsp" : "Inl");
893 if (visibility==Visibility::Light) t << " light-mode-visible";
894 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
895 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
896 if (imgType==ImageType::Dark) t << "_dark";
897 t << extension;
898 if (formula && formula->width()!=-1)
899 {
900 t << "\" width=\"";
901 t << formula->width();
902 }
903 if (formula && formula->height()!=-1)
904 {
905 t << "\" height=\"";
906 t << formula->height();
907 }
908 t << "\"/>";
909 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
910 {
911 t << "</picture>";
912 }
913 return t.str();
914 };
915
916 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
917 switch(colorStyle)
918 {
919 case HTML_COLORSTYLE_t::LIGHT:
920 m_t << writeFormula(ImageType::Light,Visibility::Always);
921 break;
922 case HTML_COLORSTYLE_t::DARK:
923 m_t << writeFormula(ImageType::Dark, Visibility::Always);
924 break;
925 case HTML_COLORSTYLE_t::AUTO_LIGHT:
926 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
927 break;
928 case HTML_COLORSTYLE_t::AUTO_DARK:
929 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
930 break;
931 case HTML_COLORSTYLE_t::TOGGLE:
932 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
933 m_t << writeFormula(ImageType::Light,Visibility::Light);
934 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
935 break;
936 }
937 }
938 if (bDisplay)
939 {
940 m_t << "\n</p>\n";
942 }
943}
944
946{
948 if (e.member())
949 {
950 anchor.prepend(e.member()->anchor()+"_");
951 }
952 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
953 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
954 // qPrint(e.entry()),
955 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
956 // e.member() ? qPrint(e.member()->name()) : "<null>"
957 // );
958 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
959}
960
962{
963 m_t << "</dd>\n";
964 m_t << "<dd>\n";
965}
966
968{
969 if (m_hide) return;
970 auto opt = cite.option();
971 if (!cite.file().isEmpty())
972 {
973 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
974 filter(cite.getText());
975 if (!opt.noCite()) endLink();
976 }
977 else
978 {
979 m_t << "<b>";
980 if (!opt.noPar()) filter("[");
981 filter(cite.target());
982 if (!opt.noPar()) filter("]");
983 m_t << "</b>";
984 }
985}
986
987
988//--------------------------------------
989// visitor functions for compound nodes
990//--------------------------------------
991
992
994{
995 //printf("DocAutoList::visitPre\n");
996 if (m_hide) return;
998 if (l.isEnumList())
999 {
1000 //
1001 // Do list type based on depth:
1002 // 1.
1003 // a.
1004 // i.
1005 // A.
1006 // 1. (repeat)...
1007 //
1008 m_t << "<ol type=\"" << g_types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
1009 }
1010 else
1011 {
1012 if (l.isCheckedList())
1013 {
1014 m_t << "<ul class=\"check\">";
1015 }
1016 else
1017 {
1018 m_t << "<ul>";
1019 }
1020 }
1021 if (!l.isPreformatted()) m_t << "\n";
1022 visitChildren(l);
1023 if (l.isEnumList())
1024 {
1025 m_t << "</ol>";
1026 }
1027 else
1028 {
1029 m_t << "</ul>";
1030 }
1031 if (!l.isPreformatted()) m_t << "\n";
1033}
1034
1036{
1037 if (m_hide) return;
1038 switch (li.itemNumber())
1039 {
1040 case DocAutoList::Unchecked: // unchecked
1041 m_t << "<li class=\"unchecked\">";
1042 break;
1043 case DocAutoList::Checked_x: // checked with x
1044 case DocAutoList::Checked_X: // checked with X
1045 m_t << "<li class=\"checked\">";
1046 break;
1047 default:
1048 m_t << "<li>";
1049 break;
1050 }
1051 visitChildren(li);
1052 m_t << "</li>";
1053 if (!li.isPreformatted()) m_t << "\n";
1054}
1055
1056template<class Node>
1057static bool holds_value(const Node *val,const DocNodeVariant &v)
1058{
1059 bool b = std::visit([&](auto &&x) {
1060 //printf("holds_value val=%s (%p) v=%s (%p)\n",
1061 // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
1062 return val==static_cast<const DocNode*>(&x);
1063 }, v);
1064 return b;
1065}
1066
1067template<class T>
1068bool isFirstChildNode(const T *parent, const DocPara &node)
1069{
1070 return !parent->children().empty() && holds_value(&node,parent->children().front());
1071}
1072
1073template<class T>
1074bool isLastChildNode(const T *parent, const DocPara &node)
1075{
1076 return !parent->children().empty() && holds_value(&node,parent->children().back());
1077}
1078
1080{
1081 const DocNodeList &nodes = parent.children();
1082 auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
1083 if (it==std::end(nodes)) return FALSE;
1084 size_t count = parent.children().size();
1085 auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=nullptr; };
1086 if (count>1 && it==std::begin(nodes)) // it points to first node
1087 {
1088 return isSeparator(std::next(it));
1089 }
1090 else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
1091 {
1092 return isSeparator(std::prev(it));
1093 }
1094 else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
1095 {
1096 return isSeparator(std::prev(it)) && isSeparator(std::next(it));
1097 }
1098 return false;
1099}
1100
1101static contexts_t getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
1102{
1104 isFirst=FALSE;
1105 isLast=FALSE;
1106 if (p.parent())
1107 {
1108 const auto parBlock = std::get_if<DocParBlock>(p.parent());
1109 if (parBlock)
1110 {
1111 // hierarchy: node N -> para -> parblock -> para
1112 // adapt return value to kind of N
1113 const DocNodeVariant *p3 = nullptr;
1114 if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
1115 {
1116 p3 = ::parent(::parent(p.parent()));
1117 }
1118 isFirst=isFirstChildNode(parBlock,p);
1119 isLast =isLastChildNode (parBlock,p);
1120 bool isLI = p3!=nullptr && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
1122 bool isTD = p3!=nullptr && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
1124 if (isFirst)
1125 {
1126 if (isLI) t=contexts_t::STARTLI; else if (isDD) t=contexts_t::STARTDD; else if (isTD) t=contexts_t::STARTTD;
1127 }
1128 if (isLast)
1129 {
1130 if (isLI) t=contexts_t::ENDLI; else if (isDD) t=contexts_t::ENDDD; else if (isTD) t=contexts_t::ENDTD;
1131 }
1132 if (!isFirst && !isLast)
1133 {
1134 if (isLI) t=contexts_t::INTERLI; else if (isDD) t=contexts_t::INTERDD; else if (isTD) t=contexts_t::INTERTD;
1135 }
1136 return t;
1137 }
1138 const auto docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
1139 if (docAutoListItem)
1140 {
1141 isFirst=isFirstChildNode(docAutoListItem,p);
1142 isLast =isLastChildNode (docAutoListItem,p);
1143 t=contexts_t::STARTLI; // not used
1144 return t;
1145 }
1146 const auto docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
1147 if (docSimpleListItem)
1148 {
1149 isFirst=TRUE;
1150 isLast =TRUE;
1151 t=contexts_t::STARTLI; // not used
1152 return t;
1153 }
1154 const auto docParamList = std::get_if<DocParamList>(p.parent());
1155 if (docParamList)
1156 {
1157 isFirst=TRUE;
1158 isLast =TRUE;
1159 t=contexts_t::STARTLI; // not used
1160 return t;
1161 }
1162 const auto docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
1163 if (docHtmlListItem)
1164 {
1165 isFirst=isFirstChildNode(docHtmlListItem,p);
1166 isLast =isLastChildNode (docHtmlListItem,p);
1167 if (isFirst) t=contexts_t::STARTLI;
1168 if (isLast) t=contexts_t::ENDLI;
1169 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1170 return t;
1171 }
1172 const auto docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
1173 if (docSecRefItem)
1174 {
1175 isFirst=isFirstChildNode(docSecRefItem,p);
1176 isLast =isLastChildNode (docSecRefItem,p);
1177 if (isFirst) t=contexts_t::STARTLI;
1178 if (isLast) t=contexts_t::ENDLI;
1179 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1180 return t;
1181 }
1182 const auto docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
1183 if (docHtmlDescData)
1184 {
1185 isFirst=isFirstChildNode(docHtmlDescData,p);
1186 isLast =isLastChildNode (docHtmlDescData,p);
1187 if (isFirst) t=contexts_t::STARTDD;
1188 if (isLast) t=contexts_t::ENDDD;
1189 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1190 return t;
1191 }
1192 const auto docXRefItem = std::get_if<DocXRefItem>(p.parent());
1193 if (docXRefItem)
1194 {
1195 isFirst=isFirstChildNode(docXRefItem,p);
1196 isLast =isLastChildNode (docXRefItem,p);
1197 if (isFirst) t=contexts_t::STARTDD;
1198 if (isLast) t=contexts_t::ENDDD;
1199 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1200 return t;
1201 }
1202 const auto docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
1203 if (docSimpleSect)
1204 {
1205 isFirst=isFirstChildNode(docSimpleSect,p);
1206 isLast =isLastChildNode (docSimpleSect,p);
1207 if (isFirst) t=contexts_t::STARTDD;
1208 if (isLast) t=contexts_t::ENDDD;
1209 if (isSeparatedParagraph(*docSimpleSect,p))
1210 // if the paragraph is enclosed with separators it will
1211 // be included in <dd>..</dd> so avoid addition paragraph
1212 // markers
1213 {
1214 isFirst=isLast=TRUE;
1215 }
1216 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1217 return t;
1218 }
1219 const auto docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
1220 if (docHtmlCell)
1221 {
1222 isFirst=isFirstChildNode(docHtmlCell,p);
1223 isLast =isLastChildNode (docHtmlCell,p);
1224 if (isFirst) t=contexts_t::STARTTD;
1225 if (isLast) t=contexts_t::ENDTD;
1226 if (!isFirst && !isLast) t = contexts_t::INTERTD;
1227 return t;
1228 }
1229 }
1230 return t;
1231}
1232
1233static bool determineIfNeedsTag(const DocPara &p)
1234{
1235 bool needsTag = FALSE;
1236 if (p.parent())
1237 {
1251 >(*p.parent()))
1252 {
1253 needsTag = TRUE;
1254 }
1255 else if (std::get_if<DocRoot>(p.parent()))
1256 {
1257 needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
1258 }
1259 }
1260 return needsTag;
1261}
1262
1264{
1265 if (m_hide) return;
1266
1267 //printf("> DocPara\n");
1268 //dumpDocNodeList(p.children());
1269
1270 bool needsTag = determineIfNeedsTag(p);
1271 //printf(" needsTag=%d\n",needsTag);
1272 bool needsTagBefore = needsTag;
1273 bool needsTagAfter = needsTag;
1274
1275 // if the first element of a paragraph is something that should be outside of
1276 // the paragraph (<ul>,<dl>,<table>,..) then that will already started the
1277 // paragraph and we don't need to do it here
1278 if (!p.children().empty())
1279 {
1280 auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
1281 [](const auto &node) { return !isInvisibleNode(node); });
1282 if (it!=std::end(p.children()))
1283 {
1284 const DocNodeVariant &n = *it;
1286 {
1287 needsTagBefore = FALSE;
1288 }
1289 }
1290 }
1291
1292 // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
1293 // this allows us to mark the tag with a special class so we can
1294 // fix the otherwise ugly spacing.
1295 bool isFirst = false;
1296 bool isLast = false;
1297 contexts_t t = getParagraphContext(p,isFirst,isLast);
1298 //printf("startPara first=%d last=%d\n",isFirst,isLast);
1299 if (isFirst && isLast) needsTagBefore=FALSE;
1300
1301 //printf(" needsTagBefore=%d\n",needsTagBefore);
1302 // write the paragraph tag (if needed)
1303 if (needsTagBefore)
1304 {
1305 if (contexts(t))
1306 m_t << "<p class=\"" << contexts(t) << "\"" << p.attribs().toString() << ">";
1307 else
1308 m_t << "<p" << p.attribs().toString() << ">";
1309 }
1310
1311 visitChildren(p);
1312
1313 // if the last element of a paragraph is something that should be outside of
1314 // the paragraph (<ul>,<dl>,<table>) then that will already have ended the
1315 // paragraph and we don't need to do it here
1316 if (!p.children().empty())
1317 {
1318 auto it = std::prev(std::end(p.children()));
1319 for (;;)
1320 {
1321 const DocNodeVariant &n = *it;
1322 if (!isInvisibleNode(n))
1323 {
1325 {
1326 needsTagAfter = FALSE;
1327 }
1328 // stop searching if we found a node that is visible
1329 break;
1330 }
1331 if (it==std::begin(p.children()))
1332 {
1333 // stop searching if we are at the beginning of the list
1334 break;
1335 }
1336 else
1337 {
1338 --it;
1339 }
1340 }
1341 }
1342
1343 //printf("endPara first=%d last=%d\n",isFirst,isLast);
1344 if (isFirst && isLast) needsTagAfter=FALSE;
1345
1346 //printf(" needsTagAfter=%d\n",needsTagAfter);
1347 if (needsTagAfter) m_t << "</p>\n";
1348 //printf("< DocPara\n");
1349}
1350
1352{
1353 //printf("> DocRoot\n");
1354 //dumpDocNodeList(r.children());
1355 visitChildren(r);
1356 //printf("< DocRoot\n");
1357}
1358
1360{
1361 if (m_hide) return;
1363 m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
1364 switch(s.type())
1365 {
1366 case DocSimpleSect::See:
1367 m_t << theTranslator->trSeeAlso(); break;
1369 m_t << theTranslator->trReturns(); break;
1371 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
1373 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
1375 m_t << theTranslator->trVersion(); break;
1377 m_t << theTranslator->trSince(); break;
1379 m_t << theTranslator->trDate(); break;
1381 m_t << theTranslator->trNote(); break;
1383 m_t << theTranslator->trWarning(); break;
1384 case DocSimpleSect::Pre:
1385 m_t << theTranslator->trPrecondition(); break;
1387 m_t << theTranslator->trPostcondition(); break;
1389 m_t << theTranslator->trCopyright(); break;
1391 m_t << theTranslator->trInvariant(); break;
1393 m_t << theTranslator->trRemarks(); break;
1395 m_t << theTranslator->trAttention(); break;
1397 m_t << theTranslator->trImportant(); break;
1398 case DocSimpleSect::User: break;
1399 case DocSimpleSect::Rcs: break;
1400 case DocSimpleSect::Unknown: break;
1401 }
1402
1403 if (s.title())
1404 {
1405 std::visit(*this,*s.title());
1406 }
1407 m_t << "</dt><dd>";
1408 visitChildren(s);
1409 m_t << "</dd></dl>\n";
1411}
1412
1414{
1415 if (m_hide) return;
1416 visitChildren(t);
1417}
1418
1420{
1421 if (m_hide) return;
1423 m_t << "<ul>";
1424 if (!sl.isPreformatted()) m_t << "\n";
1425 visitChildren(sl);
1426 m_t << "</ul>";
1427 if (!sl.isPreformatted()) m_t << "\n";
1429}
1430
1432{
1433 if (m_hide) return;
1434 m_t << "<li>";
1435 if (li.paragraph())
1436 {
1437 visit(*this,*li.paragraph());
1438 }
1439 m_t << "</li>";
1440 if (!li.isPreformatted()) m_t << "\n";
1441}
1442
1444{
1445 if (m_hide) return;
1447 m_t << "<h" << s.level() << " class=\"doxsection\">";
1448 m_t << "<a class=\"anchor\" id=\"" << s.anchor();
1449 m_t << "\"></a>\n";
1450 if (s.title())
1451 {
1452 std::visit(*this,*s.title());
1453 }
1454 m_t << "</h" << s.level() << ">\n";
1455 visitChildren(s);
1457}
1458
1460{
1461 if (m_hide) return;
1463 if (s.type()==DocHtmlList::Ordered)
1464 {
1465 m_t << "<ol" << s.attribs().toString();
1466 }
1467 else
1468 {
1469 m_t << "<ul" << s.attribs().toString();
1470 }
1471 m_t << ">\n";
1472 visitChildren(s);
1473 if (s.type()==DocHtmlList::Ordered)
1474 {
1475 m_t << "</ol>";
1476 }
1477 else
1478 {
1479 m_t << "</ul>";
1480 }
1481 if (!s.isPreformatted()) m_t << "\n";
1483}
1484
1486{
1487 if (m_hide) return;
1488 m_t << "<li" << i.attribs().toString() << ">";
1489 if (!i.isPreformatted()) m_t << "\n";
1490 visitChildren(i);
1491 m_t << "</li>\n";
1492}
1493
1495{
1496 if (m_hide) return;
1498 m_t << "<dl" << dl.attribs().toString() << ">\n";
1499 visitChildren(dl);
1500 m_t << "</dl>\n";
1502}
1503
1505{
1506 if (m_hide) return;
1507 m_t << "<dt" << dt.attribs().toString() << ">";
1508 visitChildren(dt);
1509 m_t << "</dt>\n";
1510}
1511
1513{
1514 if (m_hide) return;
1515 m_t << "<dd" << dd.attribs().toString() << ">";
1516 visitChildren(dd);
1517 m_t << "</dd>\n";
1518}
1519
1521{
1522 if (m_hide) return;
1523
1525
1526 if (t.caption())
1527 {
1528 QCString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
1529 if (!anc.isEmpty())
1530 {
1531 m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
1532 }
1533 }
1534
1535 QCString attrs = t.attribs().toString();
1536 if (attrs.isEmpty())
1537 {
1538 m_t << "<table class=\"doxtable\">\n";
1539 }
1540 else
1541 {
1542 m_t << "<table" << t.attribs().toString() << ">\n";
1543 }
1544 if (t.caption())
1545 {
1546 std::visit(*this,*t.caption());
1547 }
1548 visitChildren(t);
1549 m_t << "</table>\n";
1551}
1552
1554{
1555 if (m_hide) return;
1556 m_t << "<tr" << tr.attribs().toString() << ">\n";
1557 visitChildren(tr);
1558 m_t << "</tr>\n";
1559}
1560
1562{
1563 if (m_hide) return;
1564 if (c.isHeading())
1565 {
1566 m_t << "<th" << c.attribs().toString() << ">";
1567 }
1568 else
1569 {
1570 m_t << "<td" << c.attribs().toString() << ">";
1571 }
1572 visitChildren(c);
1573 if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
1574}
1575
1577{
1578 if (m_hide) return;
1579 m_t << "<caption" << c.attribs().toString() << ">";
1580 visitChildren(c);
1581 m_t << "</caption>\n";
1582}
1583
1585{
1586 if (m_hide) return;
1587 visitChildren(i);
1588}
1589
1591{
1592 if (m_hide) return;
1593 if (href.url().startsWith("mailto:"))
1594 {
1596 }
1597 else
1598 {
1599 QCString url = correctURL(href.url(),href.relPath());
1600 m_t << "<a href=\"" << convertToHtml(url) << "\""
1601 << href.attribs().toString() << ">";
1602 }
1603 visitChildren(href);
1604 m_t << "</a>";
1605}
1606
1608{
1609 if (m_hide) return;
1610 m_t << "<summary " << s.attribs().toString() << ">\n";
1611 visitChildren(s);
1612 m_t << "</summary>\n";
1613}
1614
1616{
1617 if (m_hide) return;
1619 m_t << "<details " << d.attribs().toString() << ">\n";
1620 auto summary = d.summary();
1621 if (summary)
1622 {
1623 std::visit(*this,*summary);
1624 }
1625 visitChildren(d);
1626 m_t << "</details>\n";
1628}
1629
1631{
1632 if (m_hide) return;
1633 forceEndParagraph(header);
1634 m_t << "<h" << header.level() << header.attribs().toString() << ">";
1635 visitChildren(header);
1636 m_t << "</h" << header.level() << ">\n";
1637 forceStartParagraph(header);
1638}
1639
1641{
1642 if (img.type()==DocImage::Html)
1643 {
1644 bool inlineImage = img.isInlineImage();
1645 bool typeSVG = img.isSVG();
1646 QCString url = img.url();
1647
1648 if (!inlineImage)
1649 {
1650 forceEndParagraph(img);
1651 }
1652 if (m_hide) return;
1653 QCString baseName=stripPath(img.name());
1654 if (!inlineImage) m_t << "<div class=\"image\">\n";
1655 QCString sizeAttribs;
1656 if (!img.width().isEmpty())
1657 {
1658 sizeAttribs+=" width=\""+img.width()+"\"";
1659 }
1660 if (!img.height().isEmpty()) // link to local file
1661 {
1662 sizeAttribs+=" height=\""+img.height()+"\"";
1663 }
1664 // 16 cases: url.isEmpty() | typeSVG | inlineImage | img.hasCaption()
1665
1666 HtmlAttribList attribs = img.attribs();
1667 if (typeSVG)
1668 {
1669 attribs.mergeAttribute("style","pointer-events: none;");
1670 }
1671 QCString alt;
1672 QCString attrs = attribs.toString(&alt);
1673 QCString src;
1674 if (url.isEmpty())
1675 {
1676 src = img.relPath()+img.name();
1677 }
1678 else
1679 {
1680 src = correctURL(url,img.relPath());
1681 }
1682 if (typeSVG && !inlineImage && !src.startsWith("http://") && !src.startsWith("https://"))
1683 {
1684 m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src)
1685 << "\"" << sizeAttribs << attrs;
1686 if (inlineImage)
1687 {
1688 // skip closing tag
1689 }
1690 else
1691 {
1692 m_t << ">" << alt << "</object>\n";
1693 }
1694 }
1695 else
1696 {
1697 m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs;
1698 if (inlineImage)
1699 {
1700 m_t << " class=\"inline\"";
1701 }
1702 else
1703 {
1704 m_t << "/>\n";
1705 }
1706 }
1707 if (img.hasCaption())
1708 {
1709 if (inlineImage)
1710 {
1711 m_t << " title=\"";
1712 m_insideTitle=true;
1713 }
1714 else
1715 {
1716 m_t << "<div class=\"caption\">\n";
1717 }
1718 }
1719 else if (inlineImage)
1720 {
1721 m_t << "/>";
1722 }
1723
1724 visitChildren(img);
1725
1726 if (img.hasCaption())
1727 {
1728 if (inlineImage)
1729 {
1730 m_t << "\"/>";
1731 m_insideTitle=false;
1732 }
1733 else // end <div class="caption">
1734 {
1735 m_t << "</div>";
1736 }
1737 }
1738 if (!inlineImage) // end <div class="image">
1739 {
1740 m_t << "</div>\n";
1742 }
1743 }
1744 else // other format -> skip
1745 {
1746 }
1747}
1748
1750{
1751 if (m_hide) return;
1753 bool exists = false;
1754 std::string inBuf;
1755 if (readInputFile(df.file(),inBuf))
1756 {
1757 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1758 ".dot", // extension
1759 inBuf, // contents
1760 exists);
1761 if (!fileName.isEmpty())
1762 {
1763 m_t << "<div class=\"dotgraph\">\n";
1764 writeDotFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1765 if (df.hasCaption())
1766 {
1767 m_t << "<div class=\"caption\">\n";
1768 }
1769 visitChildren(df);
1770 if (df.hasCaption())
1771 {
1772 m_t << "</div>\n";
1773 }
1774 m_t << "</div>\n";
1775 }
1776 }
1778}
1779
1781{
1782 if (m_hide) return;
1784 bool exists = false;
1785 std::string inBuf;
1786 if (readInputFile(df.file(),inBuf))
1787 {
1788 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1789 ".msc", // extension
1790 inBuf, // contents
1791 exists);
1792 if (!fileName.isEmpty())
1793 {
1794 m_t << "<div class=\"mscgraph\">\n";
1795 writeMscFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1796 if (df.hasCaption())
1797 {
1798 m_t << "<div class=\"caption\">\n";
1799 }
1800 visitChildren(df);
1801 if (df.hasCaption())
1802 {
1803 m_t << "</div>\n";
1804 }
1805 m_t << "</div>\n";
1806 }
1807 }
1809}
1810
1812{
1813 if (m_hide) return;
1815 bool exists = false;
1816 std::string inBuf;
1817 if (readInputFile(df.file(),inBuf))
1818 {
1819 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1820 ".dia", // extension
1821 inBuf, // contents
1822 exists);
1823 if (!fileName.isEmpty())
1824 {
1825 m_t << "<div class=\"diagraph\">\n";
1826 writeDiaFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1827 if (df.hasCaption())
1828 {
1829 m_t << "<div class=\"caption\">\n";
1830 }
1831 visitChildren(df);
1832 if (df.hasCaption())
1833 {
1834 m_t << "</div>\n";
1835 }
1836 m_t << "</div>\n";
1837 }
1838 }
1840}
1841
1843{
1844 if (m_hide) return;
1845 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1847 QCString htmlOutput = Config_getString(HTML_OUTPUT);
1848 QCString imgExt = getDotImageExtension();
1849 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
1850 if (imgExt=="svg")
1851 {
1853 }
1854 std::string inBuf;
1855 readInputFile(df.file(),inBuf);
1856 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(htmlOutput,QCString(),
1857 inBuf,format,QCString(),df.srcFile(),df.srcLine(),false);
1858 for (const auto &bName: baseNameVector)
1859 {
1860 QCString baseName=makeBaseName(bName,".pu");
1861 m_t << "<div class=\"plantumlgraph\">\n";
1862 writePlantUMLFile(baseName,df.relPath(),QCString(),df.srcFile(),df.srcLine());
1863 if (df.hasCaption())
1864 {
1865 m_t << "<div class=\"caption\">\n";
1866 }
1867 visitChildren(df);
1868 if (df.hasCaption())
1869 {
1870 m_t << "</div>\n";
1871 }
1872 m_t << "</div>\n";
1873 }
1875}
1876
1878{
1879 if (m_hide) return;
1880 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1882 if (Config_getEnum(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLI)
1883 {
1884 QCString htmlOutput = Config_getString(HTML_OUTPUT);
1885 QCString imgExt = getDotImageExtension();
1887 if (imgExt=="svg")
1888 {
1890 }
1891 std::string inBuf;
1892 readInputFile(df.file(),inBuf);
1894 inBuf,format,df.srcFile(),df.srcLine());
1895 m_t << "<div class=\"mermaidgraph\">\n";
1896 writeMermaidFile(baseName,df.relPath(),QCString(),df.srcFile(),df.srcLine());
1897 if (df.hasCaption())
1898 {
1899 m_t << "<div class=\"caption\">\n";
1900 }
1901 visitChildren(df);
1902 if (df.hasCaption())
1903 {
1904 m_t << "</div>\n";
1905 }
1906 m_t << "</div>\n";
1907 }
1908 else // AUTO or CLIENT_SIDE
1909 {
1910 // CLIENT_SIDE or AUTO: embed mermaid source for client-side rendering
1911 std::string inBuf;
1912 readInputFile(df.file(),inBuf);
1913 m_t << "<div class=\"mermaidgraph\">\n";
1914 m_t << "<pre class=\"mermaid\">\n";
1915 m_t << convertToHtml(inBuf);
1916 m_t << "</pre>\n";
1917 if (df.hasCaption())
1918 {
1919 m_t << "<div class=\"caption\">\n";
1920 }
1921 visitChildren(df);
1922 if (df.hasCaption())
1923 {
1924 m_t << "</div>\n";
1925 }
1926 m_t << "</div>\n";
1927 }
1929}
1930
1932{
1933 if (m_hide) return;
1934 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1935 visitChildren(lnk);
1936 endLink();
1937}
1938
1940{
1941 if (m_hide) return;
1942 if (!ref.file().isEmpty())
1943 {
1944 // when ref.isSubPage()==TRUE we use ref.file() for HTML and
1945 // ref.anchor() for LaTeX/RTF
1946 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor(), ref.targetTitle());
1947 }
1948 if (!ref.hasLinkText()) filter(ref.targetTitle());
1949 visitChildren(ref);
1950 if (!ref.file().isEmpty()) endLink();
1951 //m_t << " ";
1952}
1953
1955{
1956 if (m_hide) return;
1957 if (!ref.file().isEmpty())
1958 {
1959 m_t << "<li>";
1960 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1961 }
1962 visitChildren(ref);
1963 if (!ref.file().isEmpty())
1964 {
1965 endLink();
1966 m_t << "</li>\n";
1967 }
1968}
1969
1971{
1972 if (m_hide) return;
1974 m_t << "<div>\n";
1975 m_t << "<ul class=\"multicol\">\n";
1976 visitChildren(s);
1977 m_t << "</ul>\n";
1978 m_t << "</div>\n";
1980}
1981
1983{
1984 if (m_hide) return;
1986 QCString className;
1987 QCString heading;
1988 switch(s.type())
1989 {
1991 heading=theTranslator->trParameters();
1992 className="params";
1993 break;
1995 heading=theTranslator->trReturnValues();
1996 className="retval";
1997 break;
1999 heading=theTranslator->trExceptions();
2000 className="exception";
2001 break;
2003 heading=theTranslator->trTemplateParameters();
2004 className="tparams";
2005 break;
2006 default:
2007 ASSERT(0);
2008 }
2009 m_t << "<dl class=\"" << className << "\"><dt>";
2010 m_t << heading;
2011 m_t << "</dt><dd>\n";
2012 m_t << " <table class=\"" << className << "\">\n";
2013 visitChildren(s);
2014 m_t << " </table>\n";
2015 m_t << " </dd>\n";
2016 m_t << "</dl>\n";
2018}
2019
2021{
2022 if (m_hide) return;
2023 m_t << "&#160;" << s.chars() << "&#160;";
2024}
2025
2027{
2028 //printf("DocParamList::visitPre\n");
2029 if (m_hide) return;
2030 m_t << " <tr>";
2031 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
2032 if (sect && sect->hasInOutSpecifier())
2033 {
2034 m_t << "<td class=\"paramdir\">";
2036 {
2037 m_t << "[";
2038 if (pl.direction()==DocParamSect::In)
2039 {
2040 m_t << "in";
2041 }
2042 else if (pl.direction()==DocParamSect::Out)
2043 {
2044 m_t << "out";
2045 }
2046 else if (pl.direction()==DocParamSect::InOut)
2047 {
2048 m_t << "in,out";
2049 }
2050 m_t << "]";
2051 }
2052 m_t << "</td>";
2053 }
2054 if (sect && sect->hasTypeSpecifier())
2055 {
2056 m_t << "<td class=\"paramtype\">";
2057 for (const auto &type : pl.paramTypes())
2058 {
2059 std::visit(*this,type);
2060 }
2061 m_t << "</td>";
2062 }
2063 m_t << "<td class=\"paramname\">";
2064 bool first=TRUE;
2065 for (const auto &param : pl.parameters())
2066 {
2067 if (!first) m_t << ","; else first=FALSE;
2068 std::visit(*this,param);
2069 }
2070 m_t << "</td><td>";
2071 for (const auto &par : pl.paragraphs())
2072 {
2073 std::visit(*this,par);
2074 }
2075 m_t << "</td></tr>\n";
2076}
2077
2079{
2080 if (m_hide) return;
2081 if (x.title().isEmpty()) return;
2082
2084 bool anonymousEnum = x.file()=="@";
2085 if (!anonymousEnum)
2086 {
2087 QCString fn = x.file();
2089 m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
2090 << x.relPath() << fn
2091 << "#" << x.anchor() << "\">";
2092 }
2093 else
2094 {
2095 m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
2096 }
2097 filter(x.title());
2098 if (!anonymousEnum) m_t << "</a>";
2099 m_t << "</b></dt><dd>";
2100 visitChildren(x);
2101 if (x.title().isEmpty()) return;
2102 m_t << "</dd></dl>\n";
2104}
2105
2107{
2108 if (m_hide) return;
2109 startLink(QCString(),ref.file(),ref.relPath(),ref.anchor());
2110 visitChildren(ref);
2111 endLink();
2112 m_t << " ";
2113}
2114
2116{
2117 visitChildren(t);
2118}
2119
2121{
2122 if (m_hide) return;
2124 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2125 visitChildren(b);
2126 m_t << "</blockquote>\n";
2128}
2129
2131{
2132 if (m_hide) return;
2133 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2134 {
2137 m_t << "<p>";
2138 m_t << theTranslator->trFlowchart();
2139 m_t << " ";
2140 m_t << "<a href=\"";
2141 m_t << fname;
2142 m_t << ".svg\">";
2144 m_t << "</a>";
2145 if (vf.hasCaption())
2146 {
2147 m_t << "<br />";
2148 }
2149 }
2150 visitChildren(vf);
2151 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2152 {
2153 m_t << "</p>";
2155 }
2156}
2157
2159{
2160 if (m_hide) return;
2161 visitChildren(pb);
2162}
2163
2164void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
2165{
2166 if (str.isEmpty()) return;
2167 const char *p=str.data();
2168 while (*p)
2169 {
2170 char c=*p++;
2171 switch(c)
2172 {
2173 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2174 case '<': m_t << "&lt;"; break;
2175 case '>': m_t << "&gt;"; break;
2176 case '&': m_t << "&amp;"; break;
2177 case '\\':
2178 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2179 m_t << "\\&zwj;" << *p++;
2180 else
2181 m_t << c;
2182 break;
2183 default:
2184 {
2185 uint8_t uc = static_cast<uint8_t>(c);
2186 if (uc<32 && !isspace(c)) // non-printable control characters
2187 {
2188 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2189 }
2190 else
2191 {
2192 m_t << c;
2193 }
2194 }
2195 break;
2196 }
2197 }
2198}
2199
2200/// Escape basic entities to produce a valid CDATA attribute value,
2201/// assume that the outer quoting will be using the double quote &quot;
2203{
2204 if (str.isEmpty()) return str;
2205 QCString result;
2206 result.reserve(str.length()+8);
2207 const char *p=str.data();
2208 while (*p)
2209 {
2210 char c=*p++;
2211 switch(c)
2212 {
2213 case '&': result+="&amp;"; break;
2214 case '"': result+="&quot;"; break;
2215 case '<': result+="&lt;"; break;
2216 case '>': result+="&gt;"; break;
2217 case '\\':
2218 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2219 {
2220 result+="\\&zwj;";
2221 result+=*p++;
2222 }
2223 else
2224 {
2225 result+=c;
2226 }
2227 break;
2228 default:
2229 {
2230 uint8_t uc = static_cast<uint8_t>(c);
2231 if (uc<32 && !isspace(c)) // non-printable control characters
2232 {
2233 result+="&#x24";
2234 result+=hex[uc>>4];
2235 result+=hex[uc&0xF];
2236 result+=";";
2237 }
2238 else
2239 {
2240 result+=c;
2241 }
2242 }
2243 break;
2244 }
2245 }
2246 return result;
2247}
2248
2249void HtmlDocVisitor::startLink(const QCString &ref,const QCString &file,
2250 const QCString &relPath,const QCString &anchor,
2251 const QCString &tooltip)
2252{
2253 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2254 if (!ref.isEmpty()) // link to entity imported via tag file
2255 {
2256 m_t << "<a class=\"elRef\" ";
2258 }
2259 else // local link
2260 {
2261 m_t << "<a class=\"el\" ";
2262 }
2263 m_t << "href=\"";
2264 QCString fn = file;
2266 m_t << createHtmlUrl(relPath,ref,true,
2267 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2268 fn,
2269 anchor);
2270 m_t << "\"";
2271 if (!tooltip.isEmpty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2272 m_t << ">";
2273}
2274
2276{
2277 m_t << "</a>";
2278}
2279
2280void HtmlDocVisitor::writeDotFile(const QCString &fileName,const QCString &relPath,
2281 const QCString &context,const QCString &srcFile,int srcLine,bool newFile)
2282{
2283 QCString baseName=makeBaseName(fileName,".dot");
2284 baseName.prepend("dot_");
2285 QCString outDir = Config_getString(HTML_OUTPUT);
2286 if (newFile) writeDotGraphFromFile(fileName,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2287 writeDotImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,-1,srcFile,srcLine,newFile);
2288}
2289
2290void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,
2291 const QCString &context,const QCString &srcFile,int srcLine, bool newFile)
2292{
2293 QCString baseName=makeBaseName(fileName,".msc");
2294 baseName.prepend("msc_");
2295 QCString outDir = Config_getString(HTML_OUTPUT);
2296 QCString imgExt = getDotImageExtension();
2297 MscOutputFormat mscFormat = imgExt=="svg" ? MscOutputFormat::SVG : MscOutputFormat::BITMAP;
2298 if (newFile) writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
2299 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2300}
2301
2302void HtmlDocVisitor::writeDiaFile(const QCString &fileName, const QCString &relPath,
2303 const QCString &,const QCString &srcFile,int srcLine, bool newFile)
2304{
2305 QCString baseName=makeBaseName(fileName,".dia");
2306 baseName.prepend("dia_");
2307 QCString outDir = Config_getString(HTML_OUTPUT);
2308 if (newFile) writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine);
2309
2310 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2311}
2312
2313void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString &relPath,
2314 const QCString &,const QCString &/* srcFile */,int /* srcLine */)
2315{
2316 QCString baseName=makeBaseName(fileName,".pu");
2317 QCString outDir = Config_getString(HTML_OUTPUT);
2318 QCString imgExt = getDotImageExtension();
2319 if (imgExt=="svg")
2320 {
2322 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2323 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2324 //m_t << "</iframe>\n";
2325 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2326 }
2327 else
2328 {
2330 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2331 }
2332}
2333
2334void HtmlDocVisitor::writeMermaidFile(const QCString &fileName, const QCString &relPath,
2335 const QCString &,const QCString &/* srcFile */,int /* srcLine */)
2336{
2337 QCString baseName=makeBaseName(fileName,".mmd");
2338 QCString outDir = Config_getString(HTML_OUTPUT);
2339 QCString imgExt = getDotImageExtension();
2340 if (imgExt=="svg")
2341 {
2343 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2344 }
2345 else
2346 {
2348 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2349 }
2350}
2351
2352/** Returns TRUE if the child nodes in paragraph \a para until \a nodeIndex
2353 contain a style change node that is still active and that style change is one that
2354 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2355 See also bug746162.
2356 */
2359{
2360 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2361 int styleMask=0;
2362 bool styleOutsideParagraph=FALSE;
2363 while (!styleOutsideParagraph)
2364 {
2365 const DocNodeVariant *n = &(*it);
2366 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2367 if (sc)
2368 {
2369 if (!sc->enable()) // remember styles that has been closed already
2370 {
2371 styleMask|=static_cast<int>(sc->style());
2372 }
2373 bool paraStyle = sc->style()==DocStyleChange::Center ||
2374 sc->style()==DocStyleChange::Div ||
2376 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2377 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2378 paraStyle
2379 )
2380 {
2381 styleOutsideParagraph=TRUE;
2382 }
2383 }
2384 if (it!=std::begin(para->children()))
2385 {
2386 --it;
2387 }
2388 else
2389 {
2390 break;
2391 }
2392 }
2393 return styleOutsideParagraph;
2394}
2395
2396/** Used for items found inside a paragraph, which due to XHTML restrictions
2397 * have to be outside of the paragraph. This method will forcefully end
2398 * the current paragraph and forceStartParagraph() will restart it.
2399 */
2400template<class Node>
2402{
2403 const DocPara *para=std::get_if<DocPara>(n.parent());
2404 if (para)
2405 {
2406 const DocNodeList &children = para->children();
2407
2408 //printf("forceEndParagraph\n");
2409 //dumpDocNodeList(children);
2410
2411 auto it = std::find_if(std::begin(children),std::end(children),
2412 [&n](const auto &np) { return holds_value(&n,np); });
2413 if (it==std::end(children)) return;
2414 if (it==std::begin(children)) return; // first node in paragraph
2415 it = std::prev(it);
2416 bool found=false;
2417 while (!found)
2418 {
2419 found = !isInvisibleNode(*it);
2420 if (found) break;
2421 if (it!=std::begin(children))
2422 {
2423 --it;
2424 }
2425 else
2426 {
2427 break;
2428 }
2429 }
2430 if (!found) return; // first visible node in paragraph
2431 const DocNodeVariant &v = *it;
2432 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2433 bool styleOutsideParagraph=false;
2434 if (it!=std::begin(children))
2435 {
2436 it = std::prev(it);
2437 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2438 }
2439 bool isFirst = false;
2440 bool isLast = false;
2441 getParagraphContext(*para,isFirst,isLast);
2442 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2443 if (isFirst && isLast) return;
2444 if (styleOutsideParagraph) return;
2445
2446 //printf("adding </p>\n");
2447 m_t << "</p>";
2448 }
2449}
2450
2451/** Used for items found inside a paragraph, which due to XHTML restrictions
2452 * have to be outside of the paragraph. This method will forcefully start
2453 * the paragraph, that was previously ended by forceEndParagraph().
2454 */
2455template<class Node>
2457{
2458 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2459 const DocPara *para=nullptr;
2460 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2461 {
2462 const DocNodeList &children = para->children();
2463
2464 auto it = std::find_if(std::begin(children),
2465 std::end(children),
2466 [&n](const auto &np)
2467 { return holds_value(&n,np); });
2468 if (it==std::end(children)) return;
2469 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2470 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2471 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2472 if (styleOutsideParagraph) return;
2473 it = std::next(it);
2474 while (it!=std::end(children) && isInvisibleNode(*it))
2475 {
2476 ++it;
2477 }
2478 if (it!=std::end(children))
2479 {
2480 const DocNodeVariant &v = *it;
2481 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2482 }
2483 else
2484 {
2485 return; // only whitespace at the end!
2486 }
2487
2488 bool needsTag = true;
2489 bool isFirst = false;
2490 bool isLast = false;
2491 getParagraphContext(*para,isFirst,isLast);
2492 if (isFirst && isLast) needsTag = false;
2493 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2494
2495 if (needsTag) m_t << "<p>";
2496 }
2497}
2498
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, const CodeParserOptions &options)=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:77
virtual QCString anchor() const =0
virtual QCString getDefFileExtension() const =0
virtual const QCString & name() const =0
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:974
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:832
QCString url() const
Definition docnode.h:839
QCString relPath() const
Definition docnode.h:841
const HtmlAttribList & attribs() const
Definition docnode.h:842
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:1297
const HtmlAttribList & attribs() const
Definition docnode.h:1302
Node representing a HTML table caption.
Definition docnode.h:1234
const HtmlAttribList & attribs() const
Definition docnode.h:1237
Node representing a HTML table cell.
Definition docnode.h:1199
bool isHeading() const
Definition docnode.h:1206
const HtmlAttribList & attribs() const
Definition docnode.h:1211
Node representing a HTML description data.
Definition docnode.h:1187
const HtmlAttribList & attribs() const
Definition docnode.h:1190
Node representing a Html description list.
Definition docnode.h:910
const HtmlAttribList & attribs() const
Definition docnode.h:914
Node representing a Html description item.
Definition docnode.h:897
const HtmlAttribList & attribs() const
Definition docnode.h:901
Node Html details.
Definition docnode.h:866
const HtmlAttribList & attribs() const
Definition docnode.h:870
const DocNodeVariant * summary() const
Definition docnode.h:873
Node Html heading.
Definition docnode.h:882
const HtmlAttribList & attribs() const
Definition docnode.h:887
int level() const
Definition docnode.h:886
Node representing a Html list.
Definition docnode.h:1009
const HtmlAttribList & attribs() const
Definition docnode.h:1015
Type type() const
Definition docnode.h:1014
Node representing a HTML list item.
Definition docnode.h:1171
const HtmlAttribList & attribs() const
Definition docnode.h:1176
Node representing a HTML table row.
Definition docnode.h:1252
const HtmlAttribList & attribs() const
Definition docnode.h:1258
Node Html summary.
Definition docnode.h:853
const HtmlAttribList & attribs() const
Definition docnode.h:857
Node representing a HTML table.
Definition docnode.h:1275
const DocNodeVariant * caption() const
Definition docnode.cpp:2250
const HtmlAttribList & attribs() const
Definition docnode.h:1281
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:1362
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:978
Node representing an internal reference to some item.
Definition docnode.h:816
QCString file() const
Definition docnode.h:820
QCString relPath() const
Definition docnode.h:821
QCString anchor() const
Definition docnode.h:822
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 mermaid file.
Definition docnode.h:749
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:988
Node representing a paragraph in the documentation tree.
Definition docnode.h:1089
const HtmlAttribList & attribs() const
Definition docnode.h:1120
Node representing a parameter list.
Definition docnode.h:1131
const DocNodeList & parameters() const
Definition docnode.h:1135
const DocNodeList & paramTypes() const
Definition docnode.h:1136
DocParamSect::Direction direction() const
Definition docnode.h:1139
const DocNodeList & paragraphs() const
Definition docnode.h:1137
Node representing a parameter section.
Definition docnode.h:1062
bool hasInOutSpecifier() const
Definition docnode.h:1078
bool hasTypeSpecifier() const
Definition docnode.h:1079
Type type() const
Definition docnode.h:1077
Node representing a uml file.
Definition docnode.h:740
Node representing a reference to some item.
Definition docnode.h:787
QCString anchor() const
Definition docnode.h:794
QCString relPath() const
Definition docnode.h:792
QCString targetTitle() const
Definition docnode.h:795
bool isSubPage() const
Definition docnode.h:801
QCString file() const
Definition docnode.h:791
QCString ref() const
Definition docnode.h:793
bool hasLinkText() const
Definition docnode.h:797
Root node of documentation tree.
Definition docnode.h:1319
Node representing a reference to a section.
Definition docnode.h:944
QCString relPath() const
Definition docnode.h:950
QCString file() const
Definition docnode.h:948
QCString anchor() const
Definition docnode.h:949
QCString ref() const
Definition docnode.h:951
bool isSubPage() const
Definition docnode.h:953
Node representing a list of section references.
Definition docnode.h:968
Node representing a normal section.
Definition docnode.h:923
int level() const
Definition docnode.h:927
QCString anchor() const
Definition docnode.h:929
const DocNodeVariant * title() const
Definition docnode.h:928
Node representing a separator.
Definition docnode.h:365
QCString chars() const
Definition docnode.h:369
Node representing a simple list.
Definition docnode.h:999
Node representing a simple list item.
Definition docnode.h:1159
const DocNodeVariant * paragraph() const
Definition docnode.h:1163
Node representing a simple section.
Definition docnode.h:1026
QCString typeString() const
Definition docnode.cpp:3260
Type type() const
Definition docnode.h:1035
const DocNodeVariant * title() const
Definition docnode.h:1042
Node representing a separator between two simple sections of the same type.
Definition docnode.h:1053
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:1310
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:758
bool hasCaption() const
Definition docnode.h:762
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:132
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:704
static FormulaManager & instance()
Definition formula.cpp:53
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 writeMscFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine, bool newFile=true)
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 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 writeDotFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine, bool newFile=true)
void visitChildren(const T &t)
void writeMermaidFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
void filter(const QCString &str, const bool retainNewline=false)
void forceEndParagraph(const DocNode &n)
void writeDiaFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine, bool newFile=true)
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.
OutputFormat
Mermaid output image formats.
Definition mermaid.h:44
QCString writeMermaidSource(const QCString &outDirArg, const QCString &fileName, const QCString &content, OutputFormat format, const QCString &srcFile, int srcLine)
Write a Mermaid source file and register it for CLI rendering.
Definition mermaid.cpp:54
void generateMermaidOutput(const QCString &baseName, const QCString &outDir, OutputFormat format)
Register a generated Mermaid image with the index.
Definition mermaid.cpp:101
static MermaidManager & instance()
Definition mermaid.cpp:33
Class representing a list of different code generators.
Definition outputlist.h:165
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
QCString & prepend(const char *s)
Definition qcstring.h:422
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
bool startsWith(const char *s) const
Definition qcstring.h:507
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
const std::string & str() const
Definition qcstring.h:552
QCString & setNum(short n)
Definition qcstring.h:459
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
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:172
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:216
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
constexpr bool holds_one_of_alternatives(const DocNodeVariant &v)
returns true iff v holds one of types passed as template parameters
Definition docnode.h:1372
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, DocMermaidFile > DocNodeVariant
Definition docnode.h:67
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:1336
void writeDotGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, GraphOutputFormat format, const QCString &srcFile, int srcLine)
Definition dot.cpp:230
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, bool newFile)
Definition dot.cpp:284
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 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 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
Portable versions of functions that are platform dependent.
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
Options to configure the code parser.
Definition parserintf.h:78
CodeParserOptions & setSearchCtx(const Definition *d)
Definition parserintf.h:116
CodeParserOptions & setStartLine(int lineNr)
Definition parserintf.h:101
CodeParserOptions & setInlineFragment(bool enable)
Definition parserintf.h:107
CodeParserOptions & setShowLineNumbers(bool enable)
Definition parserintf.h:113
CodeParserOptions & setFileDef(const FileDef *fd)
Definition parserintf.h:98
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
QCString writeFileContents(const QCString &baseName, const QCString &extension, const QCString &content, bool &exists)
Thread-safe function to write a string to a file.
Definition util.cpp:6989
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5221
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:3974
QCString correctURL(const QCString &url, const QCString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:5955
QCString stripPath(const QCString &s)
Definition util.cpp:4959
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:5560
SrcLangExt getLanguageFromCodeLang(QCString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:5239
QCString getDotImageExtension()
Definition util.cpp:6319
QCString makeBaseName(const QCString &name, const QCString &ext)
Definition util.cpp:4975
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:5887
QCString externalLinkTarget(const bool parent)
Definition util.cpp:5735
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5263
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:4932
QCString createHtmlUrl(const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
Definition util.cpp:5746
A bunch of utility functions.