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// own header
17#include "htmldocvisitor.h"
18
19// other includes
20#include "codefragment.h"
21#include "config.h"
22#include "dia.h"
23#include "docparser.h"
24#include "dot.h"
25#include "doxygen.h"
26#include "emoji.h"
27#include "filedef.h"
28#include "fileinfo.h"
29#include "formula.h"
30#include "htmlentity.h"
31#include "indexlist.h"
32#include "language.h"
33#include "memberdef.h"
34#include "mermaid.h"
35#include "message.h"
36#include "msc.h"
37#include "outputlist.h"
38#include "parserintf.h"
39#include "plantuml.h"
40#include "portable.h"
41#include "util.h"
42#include "vhdldocgen.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 DString result="a";
83 DString 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 /* \mermaidfile */ DocMermaidFile,
135 /* <details> */ DocHtmlDetails,
136 /* <summary> */ DocHtmlSummary,
137 DocIncOperator >(n))
138 {
139 return true;
140 }
141 const DocVerbatim *dv = std::get_if<DocVerbatim>(&n);
142 if (dv)
143 {
144 DocVerbatim::Type t = dv->type();
145 if (t == DocVerbatim::JavaDocCode || t == DocVerbatim::JavaDocLiteral) return false;
146 return t!=DocVerbatim::HtmlOnly || dv->isBlock();
147 }
148 const DocStyleChange *sc = std::get_if<DocStyleChange>(&n);
149 if (sc)
150 {
151 return sc->style()==DocStyleChange::Preformatted ||
152 sc->style()==DocStyleChange::Div ||
154 }
155 const DocFormula *df = std::get_if<DocFormula>(&n);
156 if (df)
157 {
158 return !df->isInline();
159 }
160 const DocImage *di = std::get_if<DocImage>(&n);
161 if (di)
162 {
163 return !di->isInlineImage();
164 }
165 return false;
166}
167
169{
170 switch (s.type())
171 {
177 return false;
178 default:
179 return true;
180 }
181}
182
183static bool isDocIncludeVisible(const DocInclude &s)
184{
185 switch (s.type())
186 {
193 return false;
194 default:
195 return true;
196 }
197}
198
200{
201 switch (s.type())
202 {
204 return false;
205 default:
206 return true;
207 }
208}
209
210static bool isInvisibleNode(const DocNodeVariant &node)
211{
212 //printf("isInvisibleNode(%s)\n",docNodeName(node));
213 // skip over white space
214 const DocWhiteSpace *ws = std::get_if<DocWhiteSpace>(&node);
215 if (ws) return true;
216 // skip over image nodes that are not for HTML output
217 const DocImage *di = std::get_if<DocImage>(&node);
218 if (di) return di->type()!=DocImage::Html;
219 // skip over verbatim nodes that are not visible in the HTML output
220 const DocVerbatim *dv = std::get_if<DocVerbatim>(&node);
221 if (dv) return !isDocVerbatimVisible(*dv);
222 // skip over include nodes that are not visible in the HTML output
223 const DocInclude *dinc = std::get_if<DocInclude>(&node);
224 if (dinc) return !isDocIncludeVisible(*dinc);
225 const DocIncOperator *dio = std::get_if<DocIncOperator>(&node);
226 // skip over include operator nodes that are not visible in the HTML output
227 if (dio) return !isDocIncOperatorVisible(*dio);
228 return false;
229}
230
231//-------------------------------------------------------------------------
232
234 const Definition *ctx,const DString &fn)
235 : m_t(t), m_ci(ci), m_ctx(ctx), m_fileName(fn)
236{
237 if (ctx) m_langExt=ctx->getDefFileExtension();
238}
239
240template<class T>
242{
243 if (n.hasCaption())
244 {
245 t << "<div class=\"caption\">\n";
246 for (const auto &child : n.children())
247 {
248 std::visit(*this, child);
249 }
250 t << "</div>\n";
251 }
252}
253
254 //--------------------------------------
255 // visitor functions for leaf nodes
256 //--------------------------------------
257
259{
260 if (m_hide) return;
261 filter(w.word());
262}
263
265{
266 if (m_hide) return;
267 //printf("linked word: %s\n",qPrint(w.word()));
268 startLink(w.ref(),w.file(),w.relPath(),w.anchor(),w.tooltip());
269 filter(w.word());
270 endLink();
271}
272
274{
275 if (m_hide) return;
276 if (m_insidePre)
277 {
278 m_t << w.chars();
279 }
280 else
281 {
282 m_t << " ";
283 }
284}
285
287{
288 if (m_hide) return;
289 if (m_insideTitle &&
290 (s.symbol()==HtmlEntityMapper::Sym_Quot || s.symbol()==HtmlEntityMapper::Sym_quot)) // escape "'s inside title="..."
291 {
292 m_t << "&quot;";
293 }
294 else
295 {
296 const char *res = HtmlEntityMapper::instance().html(s.symbol());
297 if (res)
298 {
299 m_t << res;
300 }
301 else
302 {
303 err("HTML: non supported HTML-entity found: {}\n",
304 HtmlEntityMapper::instance().html(s.symbol(),true));
305 }
306 }
307}
308
310{
311 if (m_hide) return;
312 const char *res = EmojiEntityMapper::instance().unicode(s.index());
313 if (res)
314 {
315 m_t << "<span class=\"emoji\">" << res << "</span>";
316 }
317 else
318 {
319 m_t << s.name();
320 }
321}
322
324{
325 if (!Config_getBool(OBFUSCATE_EMAILS))
326 {
327 m_t << "<a href=\"mailto:" << url << "\">";
328 }
329 else
330 {
331 m_t << "<a href=\"mailto:";
332 if (!url.empty())
333 {
334 const char *p = url.data();
335 uint32_t size=3;
336 while (*p)
337 {
338 m_t << "+'";
339 for (uint32_t j=0;j<size && *p;j++)
340 {
341 p = writeUTF8Char(m_t,p);
342 }
343 m_t << "'";
344 if (size==3) size=2; else size=3;
345 }
346 }
347 m_t << "\">";
348 }
349}
350
352{
353 if (m_hide) return;
354 if (u.isEmail()) // mail address
355 {
356 DString url = u.url();
357 // obfuscate the mail address link
359 if (!Config_getBool(OBFUSCATE_EMAILS))
360 {
361 m_t << url;
362 }
363 else
364 {
365 const char *p = url.data();
366 // also obfuscate the address as shown on the web page
367 uint32_t size=5;
368 while (*p)
369 {
370 for (uint32_t j=0;j<size && *p;j++)
371 {
372 p = writeUTF8Char(m_t,p);
373 }
374 if (*p) m_t << "<span class=\"obfuscator\">.nosp@m.</span>";
375 if (size==5) size=4; else size=5;
376 }
377 }
378 m_t << "</a>";
379 }
380 else // web address
381 {
382 m_t << "<a href=\"";
383 filter(u.url());
384 m_t << "\">";
385 filter(u.url());
386 m_t << "</a>";
387 }
388}
389
391{
392 if (m_hide) return;
393 m_t << "<br "<< br.attribs().toString() << " />\n";
394}
395
397{
398 if (m_hide) return;
400 m_t << "<hr "<< hr.attribs().toString() << " />\n";
402}
403
405{
406 if (m_hide) return;
407 switch (s.style())
408 {
410 if (s.enable()) m_t << "<b" << s.attribs().toString() << ">"; else m_t << "</b>";
411 break;
413 if (s.enable()) m_t << "<s" << s.attribs().toString() << ">"; else m_t << "</s>";
414 break;
416 if (s.enable()) m_t << "<strike" << s.attribs().toString() << ">"; else m_t << "</strike>";
417 break;
419 if (s.enable()) m_t << "<del" << s.attribs().toString() << ">"; else m_t << "</del>";
420 break;
422 if (s.enable()) m_t << "<u" << s.attribs().toString() << ">"; else m_t << "</u>";
423 break;
425 if (s.enable()) m_t << "<ins" << s.attribs().toString() << ">"; else m_t << "</ins>";
426 break;
428 if (s.enable())
429 {
430 auto attribs = s.attribs();
431 if (s.tagName()=="a")
432 {
433 attribs.mergeAttribute("class","arg");
434 }
435 m_t << "<em" << attribs.toString() << ">";
436 }
437 else
438 {
439 m_t << "</em>";
440 }
441 break;
443 if (s.enable()) m_t << "<kbd" << s.attribs().toString() << ">"; else m_t << "</kbd>";
444 break;
446 if (s.enable())
447 {
448 m_t << "<span class=\"tt\"" << s.attribs().toString() << ">";
449 m_insidePre=true;
450 }
451 else
452 {
453 m_t << "</span>";
454 m_insidePre=false;
455 }
456 break;
458 if (s.enable())
459 {
460 auto attribs = s.attribs();
461 if (s.tagName()=="p")
462 {
463 attribs.mergeAttribute("class","param");
464 }
465 m_t << "<code" << attribs.toString() << ">";
466 m_insidePre=true;
467 }
468 else
469 {
470 m_insidePre=false;
471 m_t << "</code>";
472 }
473 break;
475 if (s.enable()) m_t << "<sub" << s.attribs().toString() << ">"; else m_t << "</sub>";
476 break;
478 if (s.enable()) m_t << "<sup" << s.attribs().toString() << ">"; else m_t << "</sup>";
479 break;
481 if (s.enable())
482 {
484 m_t << "<center" << s.attribs().toString() << ">";
485 }
486 else
487 {
488 m_t << "</center>";
490 }
491 break;
493 if (s.enable()) m_t << "<small" << s.attribs().toString() << ">"; else m_t << "</small>";
494 break;
496 if (s.enable()) m_t << "<cite" << s.attribs().toString() << ">"; else m_t << "</cite>";
497 break;
499 if (s.enable())
500 {
502 m_t << "<pre" << s.attribs().toString() << ">";
503 m_insidePre=true;
504 }
505 else
506 {
507 m_insidePre=false;
508 m_t << "</pre>";
510 }
511 break;
513 if (s.enable())
514 {
516 m_t << "<div" << s.attribs().toString() << ">";
517 }
518 else
519 {
520 m_t << "</div>";
522 }
523 break;
525 if (s.enable()) m_t << "<span" << s.attribs().toString() << ">"; else m_t << "</span>";
526 break;
527 }
528}
529
530///--------------------------------------------------------------------------------------
531
533{
534 if (m_hide) return;
535 DString lang = m_langExt;
536 if (!s.language().empty()) // explicit language setting
537 {
538 lang = s.language();
539 }
540 SrcLangExt langExt = getLanguageFromCodeLang(lang);
541 switch(s.type())
542 {
545 m_ci.startCodeFragment("DoxyCode");
547 s.context(),
548 s.text(),
549 langExt,
550 Config_getBool(STRIP_CODE_COMMENTS),
552 .setExample(s.isExample(), s.exampleFile())
553 .setInlineFragment(true)
555 );
556 m_ci.endCodeFragment("DoxyCode");
558 break;
561 m_t << "<pre class=\"fragment\">";
562 filter(s.text());
563 m_t << "</pre>";
565 break;
567 filter(s.text(), true);
568 break;
570 m_t << "<code class=\"JavaDocCode\">";
571 filter(s.text(), true);
572 m_t << "</code>";
573 break;
575 {
576 if (s.isBlock()) forceEndParagraph(s);
577 m_t << s.text();
578 if (s.isBlock()) forceStartParagraph(s);
579 }
580 break;
586 /* nothing */
587 break;
588
589 case DocVerbatim::Dot:
590 {
592
593 bool exists = false;
594 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_", // baseName
595 ".dot", // extension
596 s.text(), // contents
597 exists);
598 if (!fileName.empty())
599 {
600 m_t << "<div class=\"dotgraph\">\n";
601 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
602 visitCaption(m_t, s);
603 m_t << "</div>\n";
604 }
605
607 }
608 break;
609 case DocVerbatim::Msc:
610 {
612
613 bool exists = false;
614 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_", // baseName
615 ".msc", // extension
616 "msc {"+s.text()+"}", // contents
617 exists);
618 if (!fileName.empty())
619 {
620 m_t << "<div class=\"mscgraph\">\n";
621 writeMscFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
622 visitCaption(m_t, s);
623 m_t << "</div>\n";
624 }
625
627 }
628 break;
630 {
632 DString htmlOutput = Config_getString(HTML_OUTPUT);
633 DString imgExt = getDotImageExtension();
634 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
635 if (imgExt=="svg")
636 {
638 }
639 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
640 htmlOutput,s.exampleFile(),
641 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
642 for (const auto &baseName: baseNameVector)
643 {
644 m_t << "<div class=\"plantumlgraph\">\n";
645 writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
646 visitCaption(m_t, s);
647 m_t << "</div>\n";
648 }
650 }
651 break;
653 {
655 if (Config_getEnum(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLI) // CLI mode: pre-generate image via mmdc
656 {
657 auto htmlOutput = Config_getString(HTML_OUTPUT);
658 auto outputFormat = MermaidManager::OutputFormat::HTML;
659 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
661 htmlOutput,s.exampleFile(),
662 s.text(),imageFormat,s.srcFile(),s.srcLine());
663 m_t << "<div class=\"mermaidgraph\">\n";
664 writeMermaidFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
665 visitCaption(m_t, s);
666 m_t << "</div>\n";
667 }
668 else // CLIENT_SIDE or AUTO mode: embed for client-side rendering
669 {
670 m_t << "<div class=\"mermaidgraph\">\n";
671 m_t << "<pre class=\"mermaid\">\n";
672 m_t << convertToHtml(s.text());
673 m_t << "</pre>\n";
674 visitCaption(m_t, s);
675 m_t << "</div>\n";
676 }
678 }
679 break;
680 }
681}
682
684{
685 if (m_hide) return;
686 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
687}
688
690{
691 if (m_hide) return;
693 switch(inc.type())
694 {
697 m_ci.startCodeFragment("DoxyCode");
699 inc.context(),
700 inc.text(),
701 langExt,
702 inc.stripCodeComments(),
704 .setExample(inc.isExample(), inc.exampleFile())
705 .setInlineFragment(true)
706 .setShowLineNumbers(false)
708 );
709 m_ci.endCodeFragment("DoxyCode");
711 break;
713 {
715 m_ci.startCodeFragment("DoxyCode");
716 FileInfo cfi( inc.file().str() );
717 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
719 inc.context(),
720 inc.text(),
721 langExt,
722 inc.stripCodeComments(),
724 .setExample(inc.isExample(), inc.exampleFile())
725 .setFileDef(fd.get())
726 .setInlineFragment(true)
728 );
729 m_ci.endCodeFragment("DoxyCode");
731 }
732 break;
740 break;
742 {
743 if (inc.isBlock()) forceEndParagraph(inc);
744 m_t << inc.text();
745 if (inc.isBlock()) forceStartParagraph(inc);
746 }
747 break;
750 m_t << "<pre class=\"fragment\">";
751 filter(inc.text());
752 m_t << "</pre>";
754 break;
758 m_ci.startCodeFragment("DoxyCode");
760 inc.file(),
761 inc.blockId(),
762 inc.context(),
764 inc.trimLeft(),
766 );
767 m_ci.endCodeFragment("DoxyCode");
769 break;
770 }
771}
772
774{
775 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
776 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
777 if (op.isFirst())
778 {
780 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
782 m_hide=true;
783 }
785 if (locLangExt.empty()) locLangExt = m_langExt;
786 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
787 if (op.type()!=DocIncOperator::Skip)
788 {
789 m_hide = popHidden();
790 if (!m_hide)
791 {
792 std::unique_ptr<FileDef> fd;
793 if (!op.includeFileName().empty())
794 {
795 FileInfo cfi( op.includeFileName().str() );
796 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
797 }
798 getCodeParser(locLangExt).parseCode(
799 m_ci,
800 op.context(),
801 op.text(),
802 langExt,
805 .setExample(op.isExample(), op.exampleFile())
806 .setFileDef(fd.get())
807 .setStartLine(op.line())
810 );
811 }
813 m_hide=true;
814 }
815 if (op.isLast())
816 {
817 m_hide = popHidden();
818 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
820 }
821 else
822 {
823 if (!m_hide) m_t << "\n";
824 }
825}
826
828{
829 if (m_hide) return;
830 bool bDisplay = !f.isInline();
831 if (bDisplay)
832 {
834 m_t << "<p class=\"formulaDsp\">\n";
835 }
836
837 if (Config_getBool(USE_MATHJAX))
838 {
839 DString text = f.text();
840 bool closeInline = false;
841 if (!bDisplay && !text.empty() && text.at(0)=='$' &&
842 text.at(text.length()-1)=='$')
843 {
844 closeInline=true;
845 text = text.mid(1,text.length()-2);
846 m_t << "\\(";
847 }
848 else if (!bDisplay && !text.empty())
849 {
850 closeInline=true;
851 m_t << "\\(";
852 }
853 m_t << convertToHtml(text);
854 if (closeInline)
855 {
856 m_t << "\\)";
857 }
858 }
859 else
860 {
861 const Formula *formula = FormulaManager::instance().findFormula(f.id());
862
863 enum class ImageType { Light, Dark };
864 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
865 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> DString {
866 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
867 TextStream t;
868 DString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
869 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
870 {
871 t << "<picture>";
872 t << "<source srcset=\"" << f.relPath() << f.name();
873 if (visibility==Visibility::AutoDark)
874 {
875 t << extension;
876 t << "\" media=\"(prefers-color-scheme: light)\"";
877 }
878 else // AutoLight
879 {
880 t << "_dark";
881 t << extension;
882 t << "\" media=\"(prefers-color-scheme: dark)\"";
883 }
884 t << "/>";
885 }
886 t << "<img class=\"formula";
887 t << (bDisplay ? "Dsp" : "Inl");
888 if (visibility==Visibility::Light) t << " light-mode-visible";
889 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
890 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
891 if (imgType==ImageType::Dark) t << "_dark";
892 t << extension;
893 if (formula && formula->width()!=-1)
894 {
895 t << "\" width=\"";
896 t << formula->width();
897 }
898 if (formula && formula->height()!=-1)
899 {
900 t << "\" height=\"";
901 t << formula->height();
902 }
903 t << "\"/>";
904 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
905 {
906 t << "</picture>";
907 }
908 return t.str();
909 };
910
911 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
912 switch(colorStyle)
913 {
914 case HTML_COLORSTYLE_t::LIGHT:
915 m_t << writeFormula(ImageType::Light,Visibility::Always);
916 break;
917 case HTML_COLORSTYLE_t::DARK:
918 m_t << writeFormula(ImageType::Dark, Visibility::Always);
919 break;
920 case HTML_COLORSTYLE_t::AUTO_LIGHT:
921 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
922 break;
923 case HTML_COLORSTYLE_t::AUTO_DARK:
924 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
925 break;
926 case HTML_COLORSTYLE_t::TOGGLE:
927 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
928 m_t << writeFormula(ImageType::Light,Visibility::Light);
929 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
930 break;
931 }
932 }
933 if (bDisplay)
934 {
935 m_t << "\n</p>\n";
937 }
938}
939
941{
943 if (e.member())
944 {
945 anchor.prepend(e.member()->anchor()+"_");
946 }
947 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
948 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
949 // qPrint(e.entry()),
950 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
951 // e.member() ? qPrint(e.member()->name()) : "<null>"
952 // );
953 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
954}
955
957{
958 m_t << "</dd>\n";
959 m_t << "<dd>\n";
960}
961
963{
964 if (m_hide) return;
965 auto opt = cite.option();
966 if (!cite.file().empty())
967 {
968 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
969 filter(cite.getText(), false, true);
970 if (!opt.noCite()) endLink();
971 }
972 else
973 {
974 m_t << "<b>";
975 if (!opt.noPar()) filter("[");
976 filter(cite.target());
977 if (!opt.noPar()) filter("]");
978 m_t << "</b>";
979 }
980}
981
982
983//--------------------------------------
984// visitor functions for compound nodes
985//--------------------------------------
986
987
989{
990 //printf("DocAutoList::visitPre\n");
991 if (m_hide) return;
993 if (l.isEnumList())
994 {
995 //
996 // Do list type based on depth:
997 // 1.
998 // a.
999 // i.
1000 // A.
1001 // 1. (repeat)...
1002 //
1003 m_t << "<ol type=\"" << g_types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
1004 }
1005 else
1006 {
1007 if (l.isCheckedList())
1008 {
1009 m_t << "<ul class=\"check\">";
1010 }
1011 else
1012 {
1013 m_t << "<ul>";
1014 }
1015 }
1016 if (!l.isPreformatted()) m_t << "\n";
1017 visitChildren(l);
1018 if (l.isEnumList())
1019 {
1020 m_t << "</ol>";
1021 }
1022 else
1023 {
1024 m_t << "</ul>";
1025 }
1026 if (!l.isPreformatted()) m_t << "\n";
1028}
1029
1031{
1032 if (m_hide) return;
1033 switch (li.itemNumber())
1034 {
1035 case DocAutoList::Unchecked: // unchecked
1036 m_t << "<li class=\"unchecked\">";
1037 break;
1038 case DocAutoList::Checked_x: // checked with x
1039 case DocAutoList::Checked_X: // checked with X
1040 m_t << "<li class=\"checked\">";
1041 break;
1042 default:
1043 m_t << "<li>";
1044 break;
1045 }
1046 visitChildren(li);
1047 m_t << "</li>";
1048 if (!li.isPreformatted()) m_t << "\n";
1049}
1050
1051template<class Node>
1052static bool holds_value(const Node *val,const DocNodeVariant &v)
1053{
1054 bool b = std::visit([&](auto &&x) {
1055 //printf("holds_value val=%s (%p) v=%s (%p)\n",
1056 // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
1057 return val==static_cast<const DocNode*>(&x);
1058 }, v);
1059 return b;
1060}
1061
1062template<class T>
1063bool isFirstChildNode(const T *parent, const DocPara &node)
1064{
1065 return !parent->children().empty() && holds_value(&node,parent->children().front());
1066}
1067
1068template<class T>
1069bool isLastChildNode(const T *parent, const DocPara &node)
1070{
1071 return !parent->children().empty() && holds_value(&node,parent->children().back());
1072}
1073
1075{
1076 const DocNodeList &nodes = parent.children();
1077 auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
1078 if (it==std::end(nodes)) return false;
1079 size_t count = parent.children().size();
1080 auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=nullptr; };
1081 if (count>1 && it==std::begin(nodes)) // it points to first node
1082 {
1083 return isSeparator(std::next(it));
1084 }
1085 else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
1086 {
1087 return isSeparator(std::prev(it));
1088 }
1089 else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
1090 {
1091 return isSeparator(std::prev(it)) && isSeparator(std::next(it));
1092 }
1093 return false;
1094}
1095
1096static contexts_t getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
1097{
1099 isFirst=false;
1100 isLast=false;
1101 if (p.parent())
1102 {
1103 const auto &parBlock = std::get_if<DocParBlock>(p.parent());
1104 if (parBlock)
1105 {
1106 // hierarchy: node N -> para -> parblock -> para
1107 // adapt return value to kind of N
1108 const DocNodeVariant *p3 = nullptr;
1109 if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
1110 {
1111 p3 = ::parent(::parent(p.parent()));
1112 }
1113 isFirst=isFirstChildNode(parBlock,p);
1114 isLast =isLastChildNode (parBlock,p);
1115 bool isLI = p3!=nullptr && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
1117 bool isTD = p3!=nullptr && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
1119 if (isFirst)
1120 {
1121 if (isLI) t=contexts_t::STARTLI; else if (isDD) t=contexts_t::STARTDD; else if (isTD) t=contexts_t::STARTTD;
1122 }
1123 if (isLast)
1124 {
1125 if (isLI) t=contexts_t::ENDLI; else if (isDD) t=contexts_t::ENDDD; else if (isTD) t=contexts_t::ENDTD;
1126 }
1127 if (!isFirst && !isLast)
1128 {
1129 if (isLI) t=contexts_t::INTERLI; else if (isDD) t=contexts_t::INTERDD; else if (isTD) t=contexts_t::INTERTD;
1130 }
1131 return t;
1132 }
1133 const auto &docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
1134 if (docAutoListItem)
1135 {
1136 isFirst=isFirstChildNode(docAutoListItem,p);
1137 isLast =isLastChildNode (docAutoListItem,p);
1138 t=contexts_t::STARTLI; // not used
1139 return t;
1140 }
1141 const auto &docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
1142 if (docSimpleListItem)
1143 {
1144 isFirst=true;
1145 isLast =true;
1146 t=contexts_t::STARTLI; // not used
1147 return t;
1148 }
1149 const auto &docParamList = std::get_if<DocParamList>(p.parent());
1150 if (docParamList)
1151 {
1152 isFirst=true;
1153 isLast =true;
1154 t=contexts_t::STARTLI; // not used
1155 return t;
1156 }
1157 const auto &docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
1158 if (docHtmlListItem)
1159 {
1160 isFirst=isFirstChildNode(docHtmlListItem,p);
1161 isLast =isLastChildNode (docHtmlListItem,p);
1162 if (isFirst) t=contexts_t::STARTLI;
1163 if (isLast) t=contexts_t::ENDLI;
1164 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1165 return t;
1166 }
1167 const auto &docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
1168 if (docSecRefItem)
1169 {
1170 isFirst=isFirstChildNode(docSecRefItem,p);
1171 isLast =isLastChildNode (docSecRefItem,p);
1172 if (isFirst) t=contexts_t::STARTLI;
1173 if (isLast) t=contexts_t::ENDLI;
1174 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1175 return t;
1176 }
1177 const auto &docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
1178 if (docHtmlDescData)
1179 {
1180 isFirst=isFirstChildNode(docHtmlDescData,p);
1181 isLast =isLastChildNode (docHtmlDescData,p);
1182 if (isFirst) t=contexts_t::STARTDD;
1183 if (isLast) t=contexts_t::ENDDD;
1184 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1185 return t;
1186 }
1187 const auto &docXRefItem = std::get_if<DocXRefItem>(p.parent());
1188 if (docXRefItem)
1189 {
1190 isFirst=isFirstChildNode(docXRefItem,p);
1191 isLast =isLastChildNode (docXRefItem,p);
1192 if (isFirst) t=contexts_t::STARTDD;
1193 if (isLast) t=contexts_t::ENDDD;
1194 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1195 return t;
1196 }
1197 const auto &docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
1198 if (docSimpleSect)
1199 {
1200 isFirst=isFirstChildNode(docSimpleSect,p);
1201 isLast =isLastChildNode (docSimpleSect,p);
1202 if (isFirst) t=contexts_t::STARTDD;
1203 if (isLast) t=contexts_t::ENDDD;
1204 if (isSeparatedParagraph(*docSimpleSect,p))
1205 // if the paragraph is enclosed with separators it will
1206 // be included in <dd>..</dd> so avoid addition paragraph
1207 // markers
1208 {
1209 isFirst=isLast=true;
1210 }
1211 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1212 return t;
1213 }
1214 const auto &docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
1215 if (docHtmlCell)
1216 {
1217 isFirst=isFirstChildNode(docHtmlCell,p);
1218 isLast =isLastChildNode (docHtmlCell,p);
1219 if (isFirst) t=contexts_t::STARTTD;
1220 if (isLast) t=contexts_t::ENDTD;
1221 if (!isFirst && !isLast) t = contexts_t::INTERTD;
1222 return t;
1223 }
1224 }
1225 return t;
1226}
1227
1228static bool determineIfNeedsTag(const DocPara &p)
1229{
1230 bool needsTag = false;
1231 if (p.parent())
1232 {
1246 >(*p.parent()))
1247 {
1248 needsTag = true;
1249 }
1250 else if (std::get_if<DocRoot>(p.parent()))
1251 {
1252 needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
1253 }
1254 }
1255 return needsTag;
1256}
1257
1259{
1260 if (m_hide) return;
1261
1262 //printf("> DocPara\n");
1263 //dumpDocNodeList(p.children());
1264
1265 bool needsTag = determineIfNeedsTag(p);
1266 //printf(" needsTag=%d\n",needsTag);
1267 bool needsTagBefore = needsTag;
1268 bool needsTagAfter = needsTag;
1269
1270 // if the first element of a paragraph is something that should be outside of
1271 // the paragraph (<ul>,<dl>,<table>,..) then that will already started the
1272 // paragraph and we don't need to do it here
1273 if (!p.children().empty())
1274 {
1275 auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
1276 [](const auto &node) { return !isInvisibleNode(node); });
1277 if (it!=std::end(p.children()))
1278 {
1279 const DocNodeVariant &n = *it;
1281 {
1282 needsTagBefore = false;
1283 }
1284 }
1285 }
1286
1287 // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
1288 // this allows us to mark the tag with a special class so we can
1289 // fix the otherwise ugly spacing.
1290 bool isFirst = false;
1291 bool isLast = false;
1292 contexts_t t = getParagraphContext(p,isFirst,isLast);
1293 //printf("startPara first=%d last=%d\n",isFirst,isLast);
1294 if (isFirst && isLast) needsTagBefore=false;
1295
1296 //printf(" needsTagBefore=%d\n",needsTagBefore);
1297 // write the paragraph tag (if needed)
1298 if (needsTagBefore)
1299 {
1300 if (contexts(t))
1301 m_t << "<p class=\"" << contexts(t) << "\"" << p.attribs().toString() << ">";
1302 else
1303 m_t << "<p" << p.attribs().toString() << ">";
1304 }
1305
1306 visitChildren(p);
1307
1308 // if the last element of a paragraph is something that should be outside of
1309 // the paragraph (<ul>,<dl>,<table>) then that will already have ended the
1310 // paragraph and we don't need to do it here
1311 if (!p.children().empty())
1312 {
1313 auto it = std::prev(std::end(p.children()));
1314 for (;;)
1315 {
1316 const DocNodeVariant &n = *it;
1317 if (!isInvisibleNode(n))
1318 {
1320 {
1321 needsTagAfter = false;
1322 }
1323 // stop searching if we found a node that is visible
1324 break;
1325 }
1326 if (it==std::begin(p.children()))
1327 {
1328 // stop searching if we are at the beginning of the list
1329 break;
1330 }
1331 else
1332 {
1333 --it;
1334 }
1335 }
1336 }
1337
1338 //printf("endPara first=%d last=%d\n",isFirst,isLast);
1339 if (isFirst && isLast) needsTagAfter=false;
1340
1341 //printf(" needsTagAfter=%d\n",needsTagAfter);
1342 if (needsTagAfter) m_t << "</p>\n";
1343 //printf("< DocPara\n");
1344}
1345
1347{
1348 //printf("> DocRoot\n");
1349 //dumpDocNodeList(r.children());
1350 visitChildren(r);
1351 //printf("< DocRoot\n");
1352}
1353
1355{
1356 if (m_hide) return;
1358 m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
1359 switch(s.type())
1360 {
1361 case DocSimpleSect::See:
1362 m_t << theTranslator->trSeeAlso(); break;
1364 m_t << theTranslator->trReturns(); break;
1366 m_t << theTranslator->trAuthor(true,true); break;
1368 m_t << theTranslator->trAuthor(true,false); break;
1370 m_t << theTranslator->trVersion(); break;
1372 m_t << theTranslator->trSince(); break;
1374 m_t << theTranslator->trDate(); break;
1376 m_t << theTranslator->trNote(); break;
1378 m_t << theTranslator->trWarning(); break;
1379 case DocSimpleSect::Pre:
1380 m_t << theTranslator->trPrecondition(); break;
1382 m_t << theTranslator->trPostcondition(); break;
1384 m_t << theTranslator->trCopyright(); break;
1386 m_t << theTranslator->trInvariant(); break;
1388 m_t << theTranslator->trRemarks(); break;
1390 m_t << theTranslator->trAttention(); break;
1392 m_t << theTranslator->trImportant(); break;
1393 case DocSimpleSect::User: break;
1394 case DocSimpleSect::Rcs: break;
1395 case DocSimpleSect::Unknown: break;
1396 }
1397
1398 if (s.title())
1399 {
1400 std::visit(*this,*s.title());
1401 }
1402 m_t << "</dt><dd>";
1403 visitChildren(s);
1404 m_t << "</dd></dl>\n";
1406}
1407
1409{
1410 if (m_hide) return;
1411 visitChildren(t);
1412}
1413
1415{
1416 if (m_hide) return;
1418 m_t << "<ul>";
1419 if (!sl.isPreformatted()) m_t << "\n";
1420 visitChildren(sl);
1421 m_t << "</ul>";
1422 if (!sl.isPreformatted()) m_t << "\n";
1424}
1425
1427{
1428 if (m_hide) return;
1429 m_t << "<li>";
1430 if (li.paragraph())
1431 {
1432 visit(*this,*li.paragraph());
1433 }
1434 m_t << "</li>";
1435 if (!li.isPreformatted()) m_t << "\n";
1436}
1437
1439{
1440 if (m_hide) return;
1442 m_t << "<h" << s.level() << " class=\"doxsection\">";
1443 m_t << "<a class=\"anchor\" id=\"" << s.anchor();
1444 m_t << "\"></a>\n";
1445 if (s.title())
1446 {
1447 std::visit(*this,*s.title());
1448 }
1449 m_t << "</h" << s.level() << ">\n";
1450 visitChildren(s);
1452}
1453
1455{
1456 if (m_hide) return;
1458 if (s.type()==DocHtmlList::Ordered)
1459 {
1460 m_t << "<ol" << s.attribs().toString();
1461 }
1462 else
1463 {
1464 m_t << "<ul" << s.attribs().toString();
1465 }
1466 m_t << ">\n";
1467 visitChildren(s);
1468 if (s.type()==DocHtmlList::Ordered)
1469 {
1470 m_t << "</ol>";
1471 }
1472 else
1473 {
1474 m_t << "</ul>";
1475 }
1476 if (!s.isPreformatted()) m_t << "\n";
1478}
1479
1481{
1482 if (m_hide) return;
1483 m_t << "<li" << i.attribs().toString() << ">";
1484 if (!i.isPreformatted()) m_t << "\n";
1485 visitChildren(i);
1486 m_t << "</li>\n";
1487}
1488
1490{
1491 if (m_hide) return;
1493 m_t << "<dl" << dl.attribs().toString() << ">\n";
1494 visitChildren(dl);
1495 m_t << "</dl>\n";
1497}
1498
1500{
1501 if (m_hide) return;
1502 m_t << "<dt" << dt.attribs().toString() << ">";
1503 visitChildren(dt);
1504 m_t << "</dt>\n";
1505}
1506
1508{
1509 if (m_hide) return;
1510 m_t << "<dd" << dd.attribs().toString() << ">";
1511 visitChildren(dd);
1512 m_t << "</dd>\n";
1513}
1514
1516{
1517 if (m_hide) return;
1518
1520
1521 if (t.caption())
1522 {
1523 DString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
1524 if (!anc.empty())
1525 {
1526 m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
1527 }
1528 }
1529
1530 DString attrs = t.attribs().toString();
1531 if (attrs.empty())
1532 {
1533 m_t << "<table class=\"doxtable\">\n";
1534 }
1535 else
1536 {
1537 m_t << "<table" << t.attribs().toString() << ">\n";
1538 }
1539 if (t.caption())
1540 {
1541 std::visit(*this,*t.caption());
1542 }
1543 visitChildren(t);
1544 m_t << "</table>\n";
1546}
1547
1549{
1550 if (m_hide) return;
1551 m_t << "<tr" << tr.attribs().toString() << ">\n";
1552 visitChildren(tr);
1553 m_t << "</tr>\n";
1554}
1555
1557{
1558 if (m_hide) return;
1559 if (c.isHeading())
1560 {
1561 m_t << "<th" << c.attribs().toString() << ">";
1562 }
1563 else
1564 {
1565 m_t << "<td" << c.attribs().toString() << ">";
1566 }
1567 visitChildren(c);
1568 if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
1569}
1570
1572{
1573 if (m_hide) return;
1574 m_t << "<caption" << c.attribs().toString() << ">";
1575 visitChildren(c);
1576 m_t << "</caption>\n";
1577}
1578
1580{
1581 if (m_hide) return;
1582 visitChildren(i);
1583}
1584
1586{
1587 if (m_hide) return;
1588 if (href.url().startsWith("mailto:"))
1589 {
1591 }
1592 else
1593 {
1594 DString url = correctURL(href.url(),href.relPath());
1595 m_t << "<a href=\"" << convertToHtml(url) << "\""
1596 << href.attribs().toString() << ">";
1597 }
1598 visitChildren(href);
1599 m_t << "</a>";
1600}
1601
1603{
1604 if (m_hide) return;
1605 m_t << "<summary " << s.attribs().toString() << ">\n";
1606 visitChildren(s);
1607 m_t << "</summary>\n";
1608}
1609
1611{
1612 if (m_hide) return;
1614 m_t << "<details " << d.attribs().toString() << ">\n";
1615 auto summary = d.summary();
1616 if (summary)
1617 {
1618 std::visit(*this,*summary);
1619 }
1620 visitChildren(d);
1621 m_t << "</details>\n";
1623}
1624
1626{
1627 if (m_hide) return;
1628 forceEndParagraph(header);
1629 m_t << "<h" << header.level() << header.attribs().toString() << ">";
1630 visitChildren(header);
1631 m_t << "</h" << header.level() << ">\n";
1632 forceStartParagraph(header);
1633}
1634
1636{
1637 if (img.type()==DocImage::Html)
1638 {
1639 bool inlineImage = img.isInlineImage();
1640 bool typeSVG = img.isSVG();
1641 DString url = img.url();
1642
1643 if (!inlineImage)
1644 {
1645 forceEndParagraph(img);
1646 }
1647 if (m_hide) return;
1648 DString baseName=stripPath(img.name());
1649 if (!inlineImage) m_t << "<div class=\"image\">\n";
1650 DString sizeAttribs;
1651 if (!img.width().empty())
1652 {
1653 sizeAttribs+=" width=\""+img.width()+"\"";
1654 }
1655 if (!img.height().empty()) // link to local file
1656 {
1657 sizeAttribs+=" height=\""+img.height()+"\"";
1658 }
1659 // 16 cases: url.empty() | typeSVG | inlineImage | img.hasCaption()
1660
1661 HtmlAttribList attribs = img.attribs();
1662 if (typeSVG)
1663 {
1664 attribs.mergeAttribute("style","pointer-events: none;");
1665 }
1666 DString alt;
1667 DString attrs = attribs.toString(&alt);
1668 DString src;
1669 if (url.empty())
1670 {
1671 src = img.relPath()+img.name();
1672 }
1673 else
1674 {
1675 src = correctURL(url,img.relPath());
1676 }
1677 if (typeSVG && !inlineImage && !src.startsWith("http://") && !src.startsWith("https://"))
1678 {
1679 m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src)
1680 << "\"" << sizeAttribs << attrs;
1681 if (inlineImage)
1682 {
1683 // skip closing tag
1684 }
1685 else
1686 {
1687 m_t << ">" << alt << "</object>\n";
1688 }
1689 }
1690 else
1691 {
1692 m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs;
1693 if (inlineImage)
1694 {
1695 m_t << " class=\"inline\"";
1696 }
1697 else
1698 {
1699 m_t << "/>\n";
1700 }
1701 }
1702 if (img.hasCaption())
1703 {
1704 if (inlineImage)
1705 {
1706 m_t << " title=\"";
1707 m_insideTitle=true;
1708 }
1709 else
1710 {
1711 m_t << "<div class=\"caption\">\n";
1712 }
1713 }
1714 else if (inlineImage)
1715 {
1716 m_t << "/>";
1717 }
1718
1719 visitChildren(img);
1720
1721 if (img.hasCaption())
1722 {
1723 if (inlineImage)
1724 {
1725 m_t << "\"/>";
1726 m_insideTitle=false;
1727 }
1728 else // end <div class="caption">
1729 {
1730 m_t << "</div>";
1731 }
1732 }
1733 if (!inlineImage) // end <div class="image">
1734 {
1735 m_t << "</div>\n";
1737 }
1738 }
1739 else // other format -> skip
1740 {
1741 }
1742}
1743
1745{
1746 if (m_hide) return;
1748 bool exists = false;
1749 std::string inBuf;
1750 if (readInputFile(df.file(),inBuf))
1751 {
1752 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1753 ".dot", // extension
1754 inBuf, // contents
1755 exists);
1756 if (!fileName.empty())
1757 {
1758 m_t << "<div class=\"dotgraph\">\n";
1759 writeDotFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1760 if (df.hasCaption())
1761 {
1762 m_t << "<div class=\"caption\">\n";
1763 }
1764 visitChildren(df);
1765 if (df.hasCaption())
1766 {
1767 m_t << "</div>\n";
1768 }
1769 m_t << "</div>\n";
1770 }
1771 }
1773}
1774
1776{
1777 if (m_hide) return;
1779 bool exists = false;
1780 std::string inBuf;
1781 if (readInputFile(df.file(),inBuf))
1782 {
1783 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1784 ".msc", // extension
1785 inBuf, // contents
1786 exists);
1787 if (!fileName.empty())
1788 {
1789 m_t << "<div class=\"mscgraph\">\n";
1790 writeMscFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1791 if (df.hasCaption())
1792 {
1793 m_t << "<div class=\"caption\">\n";
1794 }
1795 visitChildren(df);
1796 if (df.hasCaption())
1797 {
1798 m_t << "</div>\n";
1799 }
1800 m_t << "</div>\n";
1801 }
1802 }
1804}
1805
1807{
1808 if (m_hide) return;
1810 bool exists = false;
1811 std::string inBuf;
1812 if (readInputFile(df.file(),inBuf))
1813 {
1814 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1815 ".dia", // extension
1816 inBuf, // contents
1817 exists);
1818 if (!fileName.empty())
1819 {
1820 m_t << "<div class=\"diagraph\">\n";
1821 writeDiaFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1822 if (df.hasCaption())
1823 {
1824 m_t << "<div class=\"caption\">\n";
1825 }
1826 visitChildren(df);
1827 if (df.hasCaption())
1828 {
1829 m_t << "</div>\n";
1830 }
1831 m_t << "</div>\n";
1832 }
1833 }
1835}
1836
1838{
1839 if (m_hide) return;
1840 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1842 DString htmlOutput = Config_getString(HTML_OUTPUT);
1843 DString imgExt = getDotImageExtension();
1844 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
1845 if (imgExt=="svg")
1846 {
1848 }
1849 std::string inBuf;
1850 readInputFile(df.file(),inBuf);
1851 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(htmlOutput,DString(),
1852 inBuf,format,DString(),df.srcFile(),df.srcLine(),false);
1853 for (const auto &bName: baseNameVector)
1854 {
1855 DString baseName=makeBaseName(bName,".pu");
1856 m_t << "<div class=\"plantumlgraph\">\n";
1857 writePlantUMLFile(baseName,df.relPath(),DString(),df.srcFile(),df.srcLine());
1858 if (df.hasCaption())
1859 {
1860 m_t << "<div class=\"caption\">\n";
1861 }
1862 visitChildren(df);
1863 if (df.hasCaption())
1864 {
1865 m_t << "</div>\n";
1866 }
1867 m_t << "</div>\n";
1868 }
1870}
1871
1873{
1874 if (m_hide) return;
1875 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1877 if (Config_getEnum(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLI)
1878 {
1879 std::string inBuf;
1880 readInputFile(df.file(),inBuf);
1881 auto htmlOutput = Config_getString(HTML_OUTPUT);
1882 auto outputFormat = MermaidManager::OutputFormat::HTML;
1883 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
1885 inBuf,imageFormat,df.srcFile(),df.srcLine());
1886 m_t << "<div class=\"mermaidgraph\">\n";
1887 writeMermaidFile(baseName,df.relPath(),DString(),df.srcFile(),df.srcLine());
1888 if (df.hasCaption())
1889 {
1890 m_t << "<div class=\"caption\">\n";
1891 }
1892 visitChildren(df);
1893 if (df.hasCaption())
1894 {
1895 m_t << "</div>\n";
1896 }
1897 m_t << "</div>\n";
1898 }
1899 else // AUTO or CLIENT_SIDE
1900 {
1901 // CLIENT_SIDE or AUTO: embed mermaid source for client-side rendering
1902 std::string inBuf;
1903 readInputFile(df.file(),inBuf);
1904 m_t << "<div class=\"mermaidgraph\">\n";
1905 m_t << "<pre class=\"mermaid\">\n";
1906 m_t << convertToHtml(inBuf);
1907 m_t << "</pre>\n";
1908 if (df.hasCaption())
1909 {
1910 m_t << "<div class=\"caption\">\n";
1911 }
1912 visitChildren(df);
1913 if (df.hasCaption())
1914 {
1915 m_t << "</div>\n";
1916 }
1917 m_t << "</div>\n";
1918 }
1920}
1921
1923{
1924 if (m_hide) return;
1925 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1926 visitChildren(lnk);
1927 endLink();
1928}
1929
1931{
1932 if (m_hide) return;
1933 if (!ref.file().empty())
1934 {
1935 // when ref.isSubPage()==true we use ref.file() for HTML and
1936 // ref.anchor() for LaTeX/RTF
1937 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? DString() : ref.anchor(), ref.targetTitle());
1938 }
1939 if (!ref.hasLinkText()) filter(ref.targetTitle());
1940 visitChildren(ref);
1941 if (!ref.file().empty()) endLink();
1942 //m_t << " ";
1943}
1944
1946{
1947 if (m_hide) return;
1948 if (!ref.file().empty())
1949 {
1950 m_t << "<li>";
1951 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? DString() : ref.anchor());
1952 }
1953 visitChildren(ref);
1954 if (!ref.file().empty())
1955 {
1956 endLink();
1957 m_t << "</li>\n";
1958 }
1959}
1960
1962{
1963 if (m_hide) return;
1965 m_t << "<div>\n";
1966 m_t << "<ul class=\"multicol\">\n";
1967 visitChildren(s);
1968 m_t << "</ul>\n";
1969 m_t << "</div>\n";
1971}
1972
1974{
1975 if (m_hide) return;
1977 DString className;
1978 DString heading;
1979 switch(s.type())
1980 {
1982 heading=theTranslator->trParameters();
1983 className="params";
1984 break;
1986 heading=theTranslator->trReturnValues();
1987 className="retval";
1988 break;
1990 heading=theTranslator->trExceptions();
1991 className="exception";
1992 break;
1995 className="tparams";
1996 break;
1997 default:
1998 ASSERT(0);
1999 }
2000 m_t << "<dl class=\"" << className << "\"><dt>";
2001 m_t << heading;
2002 m_t << "</dt><dd>\n";
2003 m_t << " <table class=\"" << className << "\">\n";
2004 visitChildren(s);
2005 m_t << " </table>\n";
2006 m_t << " </dd>\n";
2007 m_t << "</dl>\n";
2009}
2010
2012{
2013 if (m_hide) return;
2014 m_t << "&#160;" << s.chars() << "&#160;";
2015}
2016
2018{
2019 //printf("DocParamList::visitPre\n");
2020 if (m_hide) return;
2021 m_t << " <tr>";
2022 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
2023 if (sect && sect->hasInOutSpecifier())
2024 {
2025 m_t << "<td class=\"paramdir\">";
2027 {
2028 m_t << "[";
2029 if (pl.direction()==DocParamSect::In)
2030 {
2031 m_t << "in";
2032 }
2033 else if (pl.direction()==DocParamSect::Out)
2034 {
2035 m_t << "out";
2036 }
2037 else if (pl.direction()==DocParamSect::InOut)
2038 {
2039 m_t << "in,out";
2040 }
2041 m_t << "]";
2042 }
2043 m_t << "</td>";
2044 }
2045 if (sect && sect->hasTypeSpecifier())
2046 {
2047 m_t << "<td class=\"paramtype\">";
2048 for (const auto &type : pl.paramTypes())
2049 {
2050 std::visit(*this,type);
2051 }
2052 m_t << "</td>";
2053 }
2054 m_t << "<td class=\"paramname\">";
2055 bool first=true;
2056 for (const auto &param : pl.parameters())
2057 {
2058 if (!first) m_t << ","; else first=false;
2059 std::visit(*this,param);
2060 }
2061 m_t << "</td><td>";
2062 for (const auto &par : pl.paragraphs())
2063 {
2064 std::visit(*this,par);
2065 }
2066 m_t << "</td></tr>\n";
2067}
2068
2070{
2071 if (m_hide) return;
2072 if (x.title().empty()) return;
2073
2075 bool anonymousEnum = x.file()=="@";
2076 if (!anonymousEnum)
2077 {
2078 DString fn = x.file();
2080 m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
2081 << x.relPath() << fn
2082 << "#" << x.anchor() << "\">";
2083 }
2084 else
2085 {
2086 m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
2087 }
2088 filter(x.title());
2089 if (!anonymousEnum) m_t << "</a>";
2090 m_t << "</b></dt><dd>";
2091 visitChildren(x);
2092 if (x.title().empty()) return;
2093 m_t << "</dd></dl>\n";
2095}
2096
2098{
2099 if (m_hide) return;
2100 startLink(DString(),ref.file(),ref.relPath(),ref.anchor());
2101 visitChildren(ref);
2102 endLink();
2103 m_t << " ";
2104}
2105
2107{
2108 visitChildren(t);
2109}
2110
2112{
2113 if (m_hide) return;
2115 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2116 visitChildren(b);
2117 m_t << "</blockquote>\n";
2119}
2120
2122{
2123 if (m_hide) return;
2124 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2125 {
2128 m_t << "<p>";
2130 m_t << " ";
2131 m_t << "<a href=\"";
2132 m_t << fname;
2133 m_t << ".svg\">";
2135 m_t << "</a>";
2136 if (vf.hasCaption())
2137 {
2138 m_t << "<br />";
2139 }
2140 }
2141 visitChildren(vf);
2142 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2143 {
2144 m_t << "</p>";
2146 }
2147}
2148
2150{
2151 if (m_hide) return;
2152 visitChildren(pb);
2153}
2154
2155void HtmlDocVisitor::filter(const DString &str, bool retainNewline, bool citeEntry)
2156{
2157 if (str.empty()) return;
2158 const char *p=str.data();
2159 while (*p)
2160 {
2161 char c=*p++;
2162 switch(c)
2163 {
2164 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2165 case '<': m_t << "&lt;"; break;
2166 case '>': m_t << "&gt;"; break;
2167 case '&': // possibility to have a special symbol
2168 if (!citeEntry) {m_t << "&amp;"; break;}
2170 m_t,
2171 p-1,
2172 [](HtmlEntityMapper::SymType symType) { return HtmlEntityMapper::instance().html(symType); },
2173 "&amp;");
2174 break;
2175 case '\\':
2176 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2177 m_t << "\\&zwj;" << *p++;
2178 else
2179 m_t << c;
2180 break;
2181 default:
2182 {
2183 uint8_t uc = static_cast<uint8_t>(c);
2184 if (uc<32 && !isspace(c)) // non-printable control characters
2185 {
2186 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2187 }
2188 else
2189 {
2190 m_t << c;
2191 }
2192 }
2193 break;
2194 }
2195 }
2196}
2197
2198/// Escape basic entities to produce a valid CDATA attribute value,
2199/// assume that the outer quoting will be using the double quote &quot;
2201{
2202 if (str.empty()) return str;
2203 DString result;
2204 result.reserve(str.length()+8);
2205 const char *p=str.data();
2206 while (*p)
2207 {
2208 char c=*p++;
2209 switch(c)
2210 {
2211 case '&': result+="&amp;"; break;
2212 case '"': result+="&quot;"; break;
2213 case '<': result+="&lt;"; break;
2214 case '>': result+="&gt;"; break;
2215 case '\\':
2216 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2217 {
2218 result+="\\&zwj;";
2219 result+=*p++;
2220 }
2221 else
2222 {
2223 result+=c;
2224 }
2225 break;
2226 default:
2227 {
2228 uint8_t uc = static_cast<uint8_t>(c);
2229 if (uc<32 && !isspace(c)) // non-printable control characters
2230 {
2231 result+="&#x24";
2232 result+=hex[uc>>4];
2233 result+=hex[uc&0xF];
2234 result+=";";
2235 }
2236 else
2237 {
2238 result+=c;
2239 }
2240 }
2241 break;
2242 }
2243 }
2244 return result;
2245}
2246
2247void HtmlDocVisitor::startLink(const DString &ref,const DString &file,
2248 const DString &relPath,const DString &anchor,
2249 const DString &tooltip)
2250{
2251 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2252 if (!ref.empty()) // link to entity imported via tag file
2253 {
2254 m_t << "<a class=\"elRef\" ";
2256 }
2257 else // local link
2258 {
2259 m_t << "<a class=\"el\" ";
2260 }
2261 m_t << "href=\"";
2262 DString fn = file;
2264 m_t << createHtmlUrl(relPath,ref,
2265 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2266 fn,
2267 anchor);
2268 m_t << "\"";
2269 if (!tooltip.empty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2270 m_t << ">";
2271}
2272
2274{
2275 m_t << "</a>";
2276}
2277
2278void HtmlDocVisitor::writeDotFile(const DString &fileName,const DString &relPath,
2279 const DString &context,const DString &srcFile,int srcLine,bool newFile)
2280{
2281 DString baseName=makeBaseName(fileName,".dot");
2282 baseName.prepend("dot_");
2283 DString outDir = Config_getString(HTML_OUTPUT);
2284 if (newFile) writeDotGraphFromFile(fileName,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine,true);
2285 writeDotImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,-1,srcFile,srcLine,newFile);
2286}
2287
2288void HtmlDocVisitor::writeMscFile(const DString &fileName,const DString &relPath,
2289 const DString &context,const DString &srcFile,int srcLine, bool newFile)
2290{
2291 DString baseName=makeBaseName(fileName,".msc");
2292 baseName.prepend("msc_");
2293 DString outDir = Config_getString(HTML_OUTPUT);
2294 DString imgExt = getDotImageExtension();
2295 MscOutputFormat mscFormat = imgExt=="svg" ? MscOutputFormat::SVG : MscOutputFormat::BITMAP;
2296 if (newFile) writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine,true);
2297 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2298}
2299
2300void HtmlDocVisitor::writeDiaFile(const DString &fileName, const DString &relPath,
2301 const DString &,const DString &srcFile,int srcLine, bool newFile)
2302{
2303 DString baseName=makeBaseName(fileName,".dia");
2304 baseName.prepend("dia_");
2305 DString outDir = Config_getString(HTML_OUTPUT);
2306 if (newFile) writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine,true);
2307
2308 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2309}
2310
2311void HtmlDocVisitor::writePlantUMLFile(const DString &fileName, const DString &relPath,
2312 const DString &,const DString &/* srcFile */,int /* srcLine */)
2313{
2314 DString baseName=makeBaseName(fileName,".pu");
2315 DString outDir = Config_getString(HTML_OUTPUT);
2316 DString imgExt = getDotImageExtension();
2317 if (imgExt=="svg")
2318 {
2320 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2321 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2322 //m_t << "</iframe>\n";
2323 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2324 }
2325 else
2326 {
2328 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2329 }
2330}
2331
2332void HtmlDocVisitor::writeMermaidFile(const DString &fileName, const DString &relPath,
2333 const DString &,const DString &/* srcFile */,int /* srcLine */)
2334{
2335 auto baseName = makeBaseName(fileName,".mmd");
2336 auto outDir = Config_getString(HTML_OUTPUT);
2337 auto outputFormat = MermaidManager::OutputFormat::HTML;
2338 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
2339 auto imgExt = MermaidManager::imageExtension(imageFormat);
2340 MermaidManager::instance().generateMermaidOutput(fileName,outDir,imageFormat,true);
2341 if (imageFormat == MermaidManager::ImageFormat::SVG)
2342 {
2343 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << "." << imgExt << "\"></object>\n";
2344 }
2345 else
2346 {
2347 m_t << "<img src=\"" << relPath << baseName << "." << imgExt << "\" />\n";
2348 }
2349}
2350
2351/** Returns true if the child nodes in paragraph \a para until \a nodeIndex
2352 contain a style change node that is still active and that style change is one that
2353 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2354 See also bug746162.
2355 */
2358{
2359 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2360 int styleMask=0;
2361 bool styleOutsideParagraph=false;
2362 while (!styleOutsideParagraph)
2363 {
2364 const DocNodeVariant *n = &(*it);
2365 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2366 if (sc)
2367 {
2368 if (!sc->enable()) // remember styles that has been closed already
2369 {
2370 styleMask|=static_cast<int>(sc->style());
2371 }
2372 bool paraStyle = sc->style()==DocStyleChange::Center ||
2373 sc->style()==DocStyleChange::Div ||
2375 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2376 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2377 paraStyle
2378 )
2379 {
2380 styleOutsideParagraph=true;
2381 }
2382 }
2383 if (it!=std::begin(para->children()))
2384 {
2385 --it;
2386 }
2387 else
2388 {
2389 break;
2390 }
2391 }
2392 return styleOutsideParagraph;
2393}
2394
2395/** Used for items found inside a paragraph, which due to XHTML restrictions
2396 * have to be outside of the paragraph. This method will forcefully end
2397 * the current paragraph and forceStartParagraph() will restart it.
2398 */
2399template<class Node>
2401{
2402 const DocPara *para=std::get_if<DocPara>(n.parent());
2403 if (para)
2404 {
2405 const DocNodeList &children = para->children();
2406
2407 //printf("forceEndParagraph\n");
2408 //dumpDocNodeList(children);
2409
2410 auto it = std::find_if(std::begin(children),std::end(children),
2411 [&n](const auto &np) { return holds_value(&n,np); });
2412 if (it==std::end(children)) return;
2413 if (it==std::begin(children)) return; // first node in paragraph
2414 it = std::prev(it);
2415 bool found=false;
2416 while (!found)
2417 {
2418 found = !isInvisibleNode(*it);
2419 if (found) break;
2420 if (it!=std::begin(children))
2421 {
2422 --it;
2423 }
2424 else
2425 {
2426 break;
2427 }
2428 }
2429 if (!found) return; // first visible node in paragraph
2430 const DocNodeVariant &v = *it;
2431 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2432 bool styleOutsideParagraph=false;
2433 if (it!=std::begin(children))
2434 {
2435 it = std::prev(it);
2436 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2437 }
2438 bool isFirst = false;
2439 bool isLast = false;
2440 getParagraphContext(*para,isFirst,isLast);
2441 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2442 if (isFirst && isLast) return;
2443 if (styleOutsideParagraph) return;
2444
2445 //printf("adding </p>\n");
2446 m_t << "</p>";
2447 }
2448}
2449
2450/** Used for items found inside a paragraph, which due to XHTML restrictions
2451 * have to be outside of the paragraph. This method will forcefully start
2452 * the paragraph, that was previously ended by forceEndParagraph().
2453 */
2454template<class Node>
2456{
2457 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2458 const DocPara *para=nullptr;
2459 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2460 {
2461 const DocNodeList &children = para->children();
2462
2463 auto it = std::find_if(std::begin(children),
2464 std::end(children),
2465 [&n](const auto &np)
2466 { return holds_value(&n,np); });
2467 if (it==std::end(children)) return;
2468 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2469 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2470 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2471 if (styleOutsideParagraph) return;
2472 it = std::next(it);
2473 while (it!=std::end(children) && isInvisibleNode(*it))
2474 {
2475 ++it;
2476 }
2477 if (it!=std::end(children))
2478 {
2479 const DocNodeVariant &v = *it;
2480 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2481 }
2482 else
2483 {
2484 return; // only whitespace at the end!
2485 }
2486
2487 bool needsTag = true;
2488 bool isFirst = false;
2489 bool isLast = false;
2490 getParagraphContext(*para,isFirst,isLast);
2491 if (isFirst && isLast) needsTag = false;
2492 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2493
2494 if (needsTag) m_t << "<p>";
2495 }
2496}
2497
static CodeFragmentManager & instance()
void parseCodeFragment(OutputCodeList &codeOutList, const DString &fileName, const DString &blockId, const DString &scopeName, bool showLineNumbers, bool trimLeft, bool stripCodeComments)
virtual void parseCode(OutputCodeList &codeOutList, const DString &scopeName, const DString &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.
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
DString & setNum(short n)
Definition dstring.h:552
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
DString & prepend(const char *s)
Definition dstring.h:515
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition dstring.h:217
const std::string & str() const
Definition dstring.h:645
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
bool startsWith(const char *s) const
Definition dstring.h:600
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
The common base class of all entity definitions found in the sources.
Definition definition.h:77
virtual DString getDefFileExtension() const =0
virtual const DString & name() const =0
virtual DString anchor() const =0
Node representing an anchor.
Definition docnode.h:229
const HtmlAttribList & attribs() const
Definition docnode.h:235
DString 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
DString ref() const
Definition docnode.h:250
DString getText() const
Definition docnode.cpp:979
DString anchor() const
Definition docnode.h:251
DString relPath() const
Definition docnode.h:249
CiteInfoOption option() const
Definition docnode.h:253
DString target() const
Definition docnode.h:252
DString file() const
Definition docnode.h:248
DocNodeList & children()
Definition docnode.h:143
Node representing a dia file.
Definition docnode.h:731
DString file() const
Definition docnode.h:685
DString srcFile() const
Definition docnode.h:691
DString relPath() const
Definition docnode.h:686
DString context() const
Definition docnode.h:690
int srcLine() const
Definition docnode.h:692
bool hasCaption() const
Definition docnode.h:687
Node representing a dot file.
Definition docnode.h:713
Node representing an emoji.
Definition docnode.h:341
int index() const
Definition docnode.h:345
DString name() const
Definition docnode.h:344
Node representing an item of a cross-referenced list.
Definition docnode.h:529
DString text() const
Definition docnode.h:533
DString relPath() const
Definition docnode.h:534
bool isInline() const
Definition docnode.h:536
int id() const
Definition docnode.h:535
DString name() const
Definition docnode.h:532
Node representing a Hypertext reference.
Definition docnode.h:832
DString relPath() const
Definition docnode.h:841
const HtmlAttribList & attribs() const
Definition docnode.h:842
DString url() const
Definition docnode.h:839
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:1296
const HtmlAttribList & attribs() const
Definition docnode.h:1301
Node representing a HTML table caption.
Definition docnode.h:1233
const HtmlAttribList & attribs() const
Definition docnode.h:1236
Node representing a HTML table cell.
Definition docnode.h:1198
bool isHeading() const
Definition docnode.h:1205
const HtmlAttribList & attribs() const
Definition docnode.h:1210
Node representing a HTML description data.
Definition docnode.h:1186
const HtmlAttribList & attribs() const
Definition docnode.h:1189
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:1170
const HtmlAttribList & attribs() const
Definition docnode.h:1175
Node representing a HTML table row.
Definition docnode.h:1251
const HtmlAttribList & attribs() const
Definition docnode.h:1257
Node Html summary.
Definition docnode.h:853
const HtmlAttribList & attribs() const
Definition docnode.h:857
Node representing a HTML table.
Definition docnode.h:1274
const DocNodeVariant * caption() const
Definition docnode.cpp:2255
const HtmlAttribList & attribs() const
Definition docnode.h:1280
Node representing an image.
Definition docnode.h:642
const HtmlAttribList & attribs() const
Definition docnode.h:656
DString relPath() const
Definition docnode.h:652
Type type() const
Definition docnode.h:647
DString width() const
Definition docnode.h:650
DString name() const
Definition docnode.h:648
DString url() const
Definition docnode.h:653
bool isInlineImage() const
Definition docnode.h:654
bool isSVG() const
Definition docnode.cpp:1367
bool hasCaption() const
Definition docnode.h:649
DString height() const
Definition docnode.h:651
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
DString text() const
Definition docnode.h:499
DString context() const
Definition docnode.h:501
DString exampleFile() const
Definition docnode.h:508
DString includeFileName() const
Definition docnode.h:509
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
bool isBlock() const
Definition docnode.h:458
bool stripCodeComments() const
Definition docnode.h:455
DString blockId() const
Definition docnode.h:454
@ 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
DString context() const
Definition docnode.h:453
Type type() const
Definition docnode.h:451
DString exampleFile() const
Definition docnode.h:457
DString text() const
Definition docnode.h:452
DString file() const
Definition docnode.h:449
DString extension() const
Definition docnode.h:450
bool trimLeft() const
Definition docnode.h:459
bool isExample() const
Definition docnode.h:456
Node representing an entry in the index.
Definition docnode.h:552
DString 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
DString anchor() const
Definition docnode.h:822
DString file() const
Definition docnode.h:820
DString relPath() const
Definition docnode.h:821
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
DString word() const
Definition docnode.h:170
DString anchor() const
Definition docnode.h:174
DString ref() const
Definition docnode.h:173
DString tooltip() const
Definition docnode.h:175
DString file() const
Definition docnode.h:171
DString relPath() const
Definition docnode.h:172
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:81
bool isPreformatted() const
Definition docnode.h:104
DocNodeVariant * parent()
Definition docnode.h:89
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:1119
Node representing a parameter list.
Definition docnode.h:1130
const DocNodeList & parameters() const
Definition docnode.h:1134
const DocNodeList & paramTypes() const
Definition docnode.h:1135
DocParamSect::Direction direction() const
Definition docnode.h:1138
const DocNodeList & paragraphs() const
Definition docnode.h:1136
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
DString ref() const
Definition docnode.h:793
DString relPath() const
Definition docnode.h:792
DString file() const
Definition docnode.h:791
bool isSubPage() const
Definition docnode.h:801
DString anchor() const
Definition docnode.h:794
bool hasLinkText() const
Definition docnode.h:797
DString targetTitle() const
Definition docnode.h:795
Root node of documentation tree.
Definition docnode.h:1318
Node representing a reference to a section.
Definition docnode.h:944
DString anchor() const
Definition docnode.h:949
DString ref() const
Definition docnode.h:951
DString relPath() const
Definition docnode.h:950
DString file() const
Definition docnode.h:948
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
DString anchor() const
Definition docnode.h:929
const DocNodeVariant * title() const
Definition docnode.h:928
Node representing a separator.
Definition docnode.h:365
DString chars() const
Definition docnode.h:369
Node representing a simple list.
Definition docnode.h:999
Node representing a simple list item.
Definition docnode.h:1158
const DocNodeVariant * paragraph() const
Definition docnode.h:1162
Node representing a simple section.
Definition docnode.h:1026
DString typeString() const
Definition docnode.cpp:3265
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
Style style() const
Definition docnode.h:307
DString tagName() const
Definition docnode.h:312
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:1309
Node representing a simple section title.
Definition docnode.h:608
Node representing a URL (or email address).
Definition docnode.h:188
DString url() const
Definition docnode.h:192
bool isEmail() const
Definition docnode.h:193
Node representing a verbatim, unparsed text fragment.
Definition docnode.h:376
DString text() const
Definition docnode.h:383
int srcLine() const
Definition docnode.h:398
DString language() const
Definition docnode.h:388
bool isBlock() const
Definition docnode.h:389
bool isExample() const
Definition docnode.h:385
Type type() const
Definition docnode.h:382
DString exampleFile() const
Definition docnode.h:386
DString srcFile() const
Definition docnode.h:397
DString context() const
Definition docnode.h:384
DString engine() const
Definition docnode.h:393
DString 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
void pushHidden(bool hide)
CodeParserInterface & getCodeParser(const DString &langExt)
bool popHidden()
Node representing some amount of white space.
Definition docnode.h:354
DString chars() const
Definition docnode.h:358
Node representing a word.
Definition docnode.h:153
DString word() const
Definition docnode.h:156
Node representing an item of a cross-referenced list.
Definition docnode.h:621
DString anchor() const
Definition docnode.h:625
DString key() const
Definition docnode.h:628
DString file() const
Definition docnode.h:624
DString title() const
Definition docnode.h:626
DString relPath() const
Definition docnode.h:627
static IndexList * indexList
Definition doxygen.h:125
const char * unicode(int index) const
Access routine to the unicode sequence for the Emoji entity.
Definition emoji.cpp:2019
static EmojiEntityMapper & instance()
Returns the one and only instance of the Emoji entity mapper.
Definition emoji.cpp:1981
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
std::string fileName() const
Definition fileinfo.cpp:122
std::string dirPath(bool absPath=true) const
Definition fileinfo.cpp:141
static DString 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
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:31
void mergeAttribute(const DString &optName, const DString &optValue)
Definition htmlattrib.h:33
DString toString(DString *pAltValue=nullptr) const
Definition htmlattrib.h:47
void filter(const DString &str, bool retainNewline=false, bool citeEntry=false)
void startLink(const DString &ref, const DString &file, const DString &relPath, const DString &anchor, const DString &tooltip="")
TextStream & m_t
DString filterQuotedCdataAttr(const DString &str)
Escape basic entities to produce a valid CDATA attribute value, assume that the outer quoting will be...
HtmlDocVisitor(TextStream &t, OutputCodeList &ci, const Definition *ctx, const DString &fn=DString())
void forceStartParagraph(const DocNode &n)
void operator()(const DocWord &)
void visitCaption(TextStream &t, const T &n)
OutputCodeList & m_ci
void writeObfuscatedMailAddress(const DString &url)
void writeDotFile(const DString &fileName, const DString &relPath, const DString &context, const DString &srcFile, int srcLine, bool newFile=true)
void writeDiaFile(const DString &fileName, const DString &relPath, const DString &context, const DString &srcFile, int srcLine, bool newFile=true)
void visitChildren(const T &t)
void writeMscFile(const DString &fileName, const DString &relPath, const DString &context, const DString &srcFile, int srcLine, bool newFile=true)
void writePlantUMLFile(const DString &fileName, const DString &relPath, const DString &context, const DString &srcFile, int srcLine)
void forceEndParagraph(const DocNode &n)
void writeMermaidFile(const DString &fileName, const DString &relPath, const DString &context, const DString &srcFile, int srcLine)
const Definition * m_ctx
const char * writeHtmlEntity(T &result, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)
Definition htmlentity.h:127
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.
void addIndexItem(const Definition *context, const MemberDef *md, const DString &sectionAnchor=DString(), const DString &title=DString())
Definition indexlist.h:118
static MermaidManager & instance()
Definition mermaid.cpp:38
static DString imageExtension(ImageFormat imageFormat)
Definition mermaid.cpp:48
static ImageFormat convertToImageFormat(OutputFormat outputFormat)
Definition mermaid.cpp:59
void generateMermaidOutput(const DString &baseName, const DString &outDir, ImageFormat format, bool toIndex)
Register a generated Mermaid image with the index.
Definition mermaid.cpp:121
DString writeMermaidSource(const DString &outDirArg, const DString &fileName, const DString &content, ImageFormat format, const DString &srcFile, int srcLine)
Write a Mermaid source file and register it for CLI rendering.
Definition mermaid.cpp:75
Class representing a list of different code generators.
Definition outputlist.h:162
void startCodeFragment(const DString &style)
Definition outputlist.h:276
void endCodeFragment(const DString &style)
Definition outputlist.h:279
void generatePlantUMLOutput(const DString &baseName, const DString &outDir, OutputFormat format, bool toIndex)
Convert a PlantUML file to an image.
Definition plantuml.cpp:207
OutputFormat
Plant UML output image formats.
Definition plantuml.h:43
StringVector writePlantUMLSource(const DString &outDirArg, const DString &fileName, const DString &content, OutputFormat format, const DString &engine, const DString &srcFile, int srcLine, bool inlineCode)
Write a PlantUML compatible file.
Definition plantuml.cpp:37
static PlantumlManager & instance()
Definition plantuml.cpp:236
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:232
virtual DString trExceptions()=0
virtual DString trReturns()=0
virtual DString trParameters()=0
virtual DString trCopyright()=0
virtual DString trWarning()=0
virtual DString trSince()=0
virtual DString trNote()=0
virtual DString trAuthor(bool first_capital, bool singular)=0
virtual DString trReturnValues()=0
virtual DString trVersion()=0
virtual DString trTemplateParameters()=0
virtual DString trImportant()=0
virtual DString trPrecondition()=0
virtual DString trFlowchart()=0
virtual DString trAttention()=0
virtual DString trInvariant()=0
virtual DString trRemarks()=0
virtual DString trDate()=0
virtual DString trSeeAlso()=0
virtual DString trPostcondition()=0
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 DString &inFile, const DString &outDir, const DString &outFile, DiaOutputFormat format, const DString &srcFile, int srcLine, bool toIndex)
Definition dia.cpp:29
constexpr bool holds_one_of_alternatives(const DocNodeVariant &v)
returns true iff v holds one of types passed as template parameters
Definition docnode.h:1371
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:66
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:1335
void writeDotGraphFromFile(const DString &inFile, const DString &outDir, const DString &outFile, GraphOutputFormat format, const DString &srcFile, int srcLine, bool toIndex)
Definition dot.cpp:196
void writeDotImageMapFromFile(TextStream &t, const DString &inFile, const DString &outDir, const DString &relPath, const DString &baseName, const DString &context, int graphId, const DString &srcFile, int srcLine, bool newFile)
Definition dot.cpp:249
std::unique_ptr< FileDef > createFileDef(const DString &p, const DString &n, const DString &ref, const DString &dn)
Definition filedef.cpp:267
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 contexts_t getParagraphContext(const DocPara &p, bool &isFirst, bool &isLast)
static DString convertIndexWordToAnchor(const DString &word)
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)
static const char * hex
Translator * theTranslator
Definition language.cpp:76
#define err(fmt,...)
Definition message.h:127
#define ASSERT(x)
Definition message.h:142
void writeMscGraphFromFile(const DString &inFile, const DString &outDir, const DString &outFile, MscOutputFormat format, const DString &srcFile, int srcLine, bool toIndex)
Definition msc.cpp:160
void writeMscImageMapFromFile(TextStream &t, const DString &inFile, const DString &outDir, const DString &relPath, const DString &baseName, const DString &context, MscOutputFormat format, const DString &srcFile, int srcLine)
Definition msc.cpp:239
MscOutputFormat
Definition msc.h:22
Portable versions of functions that are platform dependent.
Options to configure the code parser.
Definition parserintf.h:77
CodeParserOptions & setSearchCtx(const Definition *d)
Definition parserintf.h:115
CodeParserOptions & setStartLine(int lineNr)
Definition parserintf.h:100
CodeParserOptions & setInlineFragment(bool enable)
Definition parserintf.h:106
CodeParserOptions & setShowLineNumbers(bool enable)
Definition parserintf.h:112
CodeParserOptions & setFileDef(const FileDef *fd)
Definition parserintf.h:97
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:201
DString writeInlineGraph(const DString &baseName, const DString &extension, const DString &content, bool &exists)
Definition util.cpp:5358
DString externalLinkTarget(const bool parent)
Definition util.cpp:4491
DString correctURL(const DString &url, const DString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:4659
DString getFileNameExtension(const DString &fn)
Definition util.cpp:4210
DString convertToHtml(const DString &s, bool keepEntities)
Definition util.cpp:3291
bool readInputFile(const DString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:4374
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4168
void addHtmlExtensionIfMissing(DString &fName)
Definition util.cpp:3931
bool copyFile(const DString &src, const DString &dest)
Copies the contents of file with name src to the newly created file with name dest.
Definition util.cpp:4619
DString createHtmlUrl(const DString &relPath, const DString &ref, bool isLocalFile, const DString &targetFileName, const DString &anchor)
Definition util.cpp:4502
DString getDotImageExtension()
Definition util.cpp:4964
DString makeBaseName(const DString &name, const DString &ext)
Definition util.cpp:3974
DString stripPath(const DString &s)
Definition util.cpp:3960
SrcLangExt getLanguageFromCodeLang(DString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:4186
A bunch of utility functions.