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 "reflist.h"
42#include "util.h"
43#include "vhdldocgen.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 DString result="a";
84 DString 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();
146 if (t == DocVerbatim::JavaDocCode || t == DocVerbatim::JavaDocLiteral) return false;
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 DString &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",
305 HtmlEntityMapper::instance().html(s.symbol(),true));
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=\"mailto:";
333 if (!url.empty())
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 << "\">";
349 }
350}
351
353{
354 if (m_hide) return;
355 if (u.isEmail()) // mail address
356 {
357 DString 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 auto attribs = s.attribs();
450 attribs.mergeAttribute("class","tt", true);
451 m_t << "<span" << attribs.toString() << ">";
452 m_insidePre=true;
453 }
454 else
455 {
456 m_t << "</span>";
457 m_insidePre=false;
458 }
459 break;
461 if (s.enable())
462 {
463 auto attribs = s.attribs();
464 if (s.tagName()=="p")
465 {
466 attribs.mergeAttribute("class","param");
467 }
468 m_t << "<code" << attribs.toString() << ">";
469 m_insidePre=true;
470 }
471 else
472 {
473 m_insidePre=false;
474 m_t << "</code>";
475 }
476 break;
478 if (s.enable()) m_t << "<sub" << s.attribs().toString() << ">"; else m_t << "</sub>";
479 break;
481 if (s.enable()) m_t << "<sup" << s.attribs().toString() << ">"; else m_t << "</sup>";
482 break;
484 if (s.enable())
485 {
487 m_t << "<center" << s.attribs().toString() << ">";
488 }
489 else
490 {
491 m_t << "</center>";
493 }
494 break;
496 if (s.enable()) m_t << "<small" << s.attribs().toString() << ">"; else m_t << "</small>";
497 break;
499 if (s.enable()) m_t << "<cite" << s.attribs().toString() << ">"; else m_t << "</cite>";
500 break;
502 if (s.enable())
503 {
505 m_t << "<pre" << s.attribs().toString() << ">";
506 m_insidePre=true;
507 }
508 else
509 {
510 m_insidePre=false;
511 m_t << "</pre>";
513 }
514 break;
516 if (s.enable())
517 {
519 m_t << "<div" << s.attribs().toString() << ">";
520 }
521 else
522 {
523 m_t << "</div>";
525 }
526 break;
528 if (s.enable()) m_t << "<span" << s.attribs().toString() << ">"; else m_t << "</span>";
529 break;
530 }
531}
532
533///--------------------------------------------------------------------------------------
534
536{
537 if (m_hide) return;
538 DString lang = m_langExt;
539 if (!s.language().empty()) // explicit language setting
540 {
541 lang = s.language();
542 }
543 SrcLangExt langExt = getLanguageFromCodeLang(lang);
544 switch(s.type())
545 {
548 m_ci.startCodeFragment("DoxyCode");
550 s.context(),
551 s.text(),
552 langExt,
553 Config_getBool(STRIP_CODE_COMMENTS),
555 .setExample(s.isExample(), s.exampleFile())
556 .setInlineFragment(true)
558 );
559 m_ci.endCodeFragment("DoxyCode");
561 break;
564 m_t << "<pre class=\"fragment\">";
565 filter(s.text());
566 m_t << "</pre>";
568 break;
570 filter(s.text(), true);
571 break;
573 m_t << "<code class=\"JavaDocCode\">";
574 filter(s.text(), true);
575 m_t << "</code>";
576 break;
578 {
579 if (s.isBlock()) forceEndParagraph(s);
580 m_t << s.text();
581 if (s.isBlock()) forceStartParagraph(s);
582 }
583 break;
589 /* nothing */
590 break;
591
592 case DocVerbatim::Dot:
593 {
595
596 bool exists = false;
597 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_", // baseName
598 ".dot", // extension
599 s.text(), // contents
600 exists);
601 if (!fileName.empty())
602 {
603 m_t << "<div class=\"dotgraph\">\n";
604 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
605 visitCaption(m_t, s);
606 m_t << "</div>\n";
607 }
608
610 }
611 break;
612 case DocVerbatim::Msc:
613 {
615
616 bool exists = false;
617 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_", // baseName
618 ".msc", // extension
619 "msc {"+s.text()+"}", // contents
620 exists);
621 if (!fileName.empty())
622 {
623 m_t << "<div class=\"mscgraph\">\n";
624 writeMscFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
625 visitCaption(m_t, s);
626 m_t << "</div>\n";
627 }
628
630 }
631 break;
633 {
635 DString htmlOutput = Config_getString(HTML_OUTPUT);
636 DString imgExt = getDotImageExtension();
637 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
638 if (imgExt=="svg")
639 {
641 }
642 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
643 htmlOutput,s.exampleFile(),
644 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
645 for (const auto &baseName: baseNameVector)
646 {
647 m_t << "<div class=\"plantumlgraph\">\n";
648 writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
649 visitCaption(m_t, s);
650 m_t << "</div>\n";
651 }
653 }
654 break;
656 {
658 if (Config_getEnum(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLI) // CLI mode: pre-generate image via mmdc
659 {
660 auto htmlOutput = Config_getString(HTML_OUTPUT);
661 auto outputFormat = MermaidManager::OutputFormat::HTML;
662 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
664 htmlOutput,s.exampleFile(),
665 s.text(),imageFormat,s.srcFile(),s.srcLine());
666 m_t << "<div class=\"mermaidgraph\">\n";
667 writeMermaidFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
668 visitCaption(m_t, s);
669 m_t << "</div>\n";
670 }
671 else // CLIENT_SIDE or AUTO mode: embed for client-side rendering
672 {
673 m_t << "<div class=\"mermaidgraph\">\n";
674 m_t << "<pre class=\"mermaid\">\n";
675 m_t << convertToHtml(s.text());
676 m_t << "</pre>\n";
677 visitCaption(m_t, s);
678 m_t << "</div>\n";
679 }
681 }
682 break;
683 }
684}
685
687{
688 if (m_hide) return;
689 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
690}
691
693{
694 if (m_hide) return;
696 switch(inc.type())
697 {
700 m_ci.startCodeFragment("DoxyCode");
702 inc.context(),
703 inc.text(),
704 langExt,
705 inc.stripCodeComments(),
707 .setExample(inc.isExample(), inc.exampleFile())
708 .setInlineFragment(true)
709 .setShowLineNumbers(false)
711 );
712 m_ci.endCodeFragment("DoxyCode");
714 break;
716 {
718 m_ci.startCodeFragment("DoxyCode");
719 FileInfo cfi( inc.file().str() );
720 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
722 inc.context(),
723 inc.text(),
724 langExt,
725 inc.stripCodeComments(),
727 .setExample(inc.isExample(), inc.exampleFile())
728 .setFileDef(fd.get())
729 .setInlineFragment(true)
731 );
732 m_ci.endCodeFragment("DoxyCode");
734 }
735 break;
743 break;
745 {
746 if (inc.isBlock()) forceEndParagraph(inc);
747 m_t << inc.text();
748 if (inc.isBlock()) forceStartParagraph(inc);
749 }
750 break;
753 m_t << "<pre class=\"fragment\">";
754 filter(inc.text());
755 m_t << "</pre>";
757 break;
761 m_ci.startCodeFragment("DoxyCode");
763 inc.file(),
764 inc.blockId(),
765 inc.context(),
767 inc.trimLeft(),
769 );
770 m_ci.endCodeFragment("DoxyCode");
772 break;
773 }
774}
775
777{
778 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
779 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
780 if (op.isFirst())
781 {
783 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
785 m_hide=true;
786 }
788 if (locLangExt.empty()) locLangExt = m_langExt;
789 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
790 if (op.type()!=DocIncOperator::Skip)
791 {
792 m_hide = popHidden();
793 if (!m_hide)
794 {
795 std::unique_ptr<FileDef> fd;
796 if (!op.includeFileName().empty())
797 {
798 FileInfo cfi( op.includeFileName().str() );
799 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
800 }
801 getCodeParser(locLangExt).parseCode(
802 m_ci,
803 op.context(),
804 op.text(),
805 langExt,
808 .setExample(op.isExample(), op.exampleFile())
809 .setFileDef(fd.get())
810 .setStartLine(op.line())
813 );
814 }
816 m_hide=true;
817 }
818 if (op.isLast())
819 {
820 m_hide = popHidden();
821 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
823 }
824 else
825 {
826 if (!m_hide) m_t << "\n";
827 }
828}
829
831{
832 if (m_hide) return;
833 bool bDisplay = !f.isInline();
834 if (bDisplay)
835 {
837 m_t << "<p class=\"formulaDsp\">\n";
838 }
839
840 if (Config_getBool(USE_MATHJAX))
841 {
842 DString text = f.text();
843 bool closeInline = false;
844 if (!bDisplay && !text.empty() && text.at(0)=='$' &&
845 text.at(text.length()-1)=='$')
846 {
847 closeInline=true;
848 text = text.mid(1,text.length()-2);
849 m_t << "\\(";
850 }
851 else if (!bDisplay && !text.empty())
852 {
853 closeInline=true;
854 m_t << "\\(";
855 }
856 m_t << convertToHtml(text);
857 if (closeInline)
858 {
859 m_t << "\\)";
860 }
861 }
862 else
863 {
864 const Formula *formula = FormulaManager::instance().findFormula(f.id());
865
866 enum class ImageType { Light, Dark };
867 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
868 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> DString {
869 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
870 TextStream t;
871 DString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
872 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
873 {
874 t << "<picture>";
875 t << "<source srcset=\"" << f.relPath() << f.name();
876 if (visibility==Visibility::AutoDark)
877 {
878 t << extension;
879 t << "\" media=\"(prefers-color-scheme: light)\"";
880 }
881 else // AutoLight
882 {
883 t << "_dark";
884 t << extension;
885 t << "\" media=\"(prefers-color-scheme: dark)\"";
886 }
887 t << "/>";
888 }
889 t << "<img class=\"formula";
890 t << (bDisplay ? "Dsp" : "Inl");
891 if (visibility==Visibility::Light) t << " light-mode-visible";
892 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
893 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
894 if (imgType==ImageType::Dark) t << "_dark";
895 t << extension;
896 if (formula && formula->width()!=-1)
897 {
898 t << "\" width=\"";
899 t << formula->width();
900 }
901 if (formula && formula->height()!=-1)
902 {
903 t << "\" height=\"";
904 t << formula->height();
905 }
906 t << "\"/>";
907 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
908 {
909 t << "</picture>";
910 }
911 return t.str();
912 };
913
914 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
915 switch(colorStyle)
916 {
917 case HTML_COLORSTYLE_t::LIGHT:
918 m_t << writeFormula(ImageType::Light,Visibility::Always);
919 break;
920 case HTML_COLORSTYLE_t::DARK:
921 m_t << writeFormula(ImageType::Dark, Visibility::Always);
922 break;
923 case HTML_COLORSTYLE_t::AUTO_LIGHT:
924 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
925 break;
926 case HTML_COLORSTYLE_t::AUTO_DARK:
927 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
928 break;
929 case HTML_COLORSTYLE_t::TOGGLE:
930 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
931 m_t << writeFormula(ImageType::Light,Visibility::Light);
932 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
933 break;
934 }
935 }
936 if (bDisplay)
937 {
938 m_t << "\n</p>\n";
940 }
941}
942
944{
946 if (e.member())
947 {
948 anchor.prepend(e.member()->anchor()+"_");
949 }
950 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
951 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
952 // qPrint(e.entry()),
953 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
954 // e.member() ? qPrint(e.member()->name()) : "<null>"
955 // );
956 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
957}
958
960{
961 m_t << "</dd>\n";
962 m_t << "<dd>\n";
963}
964
966{
967 if (m_hide) return;
968 auto opt = cite.option();
969 if (!cite.file().empty())
970 {
971 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
972 filter(cite.getText(), false, true);
973 if (!opt.noCite()) endLink();
974 }
975 else
976 {
977 m_t << "<b>";
978 if (!opt.noPar()) filter("[");
979 filter(cite.target());
980 if (!opt.noPar()) filter("]");
981 m_t << "</b>";
982 }
983}
984
985
986//--------------------------------------
987// visitor functions for compound nodes
988//--------------------------------------
989
990
992{
993 //printf("DocAutoList::visitPre\n");
994 if (m_hide) return;
996 if (l.isEnumList())
997 {
998 //
999 // Do list type based on depth:
1000 // 1.
1001 // a.
1002 // i.
1003 // A.
1004 // 1. (repeat)...
1005 //
1006 m_t << "<ol type=\"" << g_types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
1007 }
1008 else
1009 {
1010 if (l.isCheckedList())
1011 {
1012 m_t << "<ul class=\"check\">";
1013 }
1014 else
1015 {
1016 m_t << "<ul>";
1017 }
1018 }
1019 if (!l.isPreformatted()) m_t << "\n";
1020 visitChildren(l);
1021 if (l.isEnumList())
1022 {
1023 m_t << "</ol>";
1024 }
1025 else
1026 {
1027 m_t << "</ul>";
1028 }
1029 if (!l.isPreformatted()) m_t << "\n";
1031}
1032
1034{
1035 if (m_hide) return;
1036 switch (li.itemNumber())
1037 {
1038 case DocAutoList::Unchecked: // unchecked
1039 m_t << "<li class=\"unchecked\">";
1040 break;
1041 case DocAutoList::Checked_x: // checked with x
1042 case DocAutoList::Checked_X: // checked with X
1043 m_t << "<li class=\"checked\">";
1044 break;
1045 default:
1046 m_t << "<li>";
1047 break;
1048 }
1049 visitChildren(li);
1050 m_t << "</li>";
1051 if (!li.isPreformatted()) m_t << "\n";
1052}
1053
1054template<class Node>
1055static bool holds_value(const Node *val,const DocNodeVariant &v)
1056{
1057 bool b = std::visit([&](auto &&x) {
1058 //printf("holds_value val=%s (%p) v=%s (%p)\n",
1059 // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
1060 return val==static_cast<const DocNode*>(&x);
1061 }, v);
1062 return b;
1063}
1064
1065template<class T>
1066bool isFirstChildNode(const T *parent, const DocPara &node)
1067{
1068 return !parent->children().empty() && holds_value(&node,parent->children().front());
1069}
1070
1071template<class T>
1072bool isLastChildNode(const T *parent, const DocPara &node)
1073{
1074 return !parent->children().empty() && holds_value(&node,parent->children().back());
1075}
1076
1078{
1079 const DocNodeList &nodes = parent.children();
1080 auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
1081 if (it==std::end(nodes)) return false;
1082 size_t count = parent.children().size();
1083 auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=nullptr; };
1084 if (count>1 && it==std::begin(nodes)) // it points to first node
1085 {
1086 return isSeparator(std::next(it));
1087 }
1088 else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
1089 {
1090 return isSeparator(std::prev(it));
1091 }
1092 else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
1093 {
1094 return isSeparator(std::prev(it)) && isSeparator(std::next(it));
1095 }
1096 return false;
1097}
1098
1099static contexts_t getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
1100{
1102 isFirst=false;
1103 isLast=false;
1104 if (p.parent())
1105 {
1106 const auto &parBlock = std::get_if<DocParBlock>(p.parent());
1107 if (parBlock)
1108 {
1109 // hierarchy: node N -> para -> parblock -> para
1110 // adapt return value to kind of N
1111 const DocNodeVariant *p3 = nullptr;
1112 if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
1113 {
1114 p3 = ::parent(::parent(p.parent()));
1115 }
1116 isFirst=isFirstChildNode(parBlock,p);
1117 isLast =isLastChildNode (parBlock,p);
1118 bool isLI = p3!=nullptr && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
1120 bool isTD = p3!=nullptr && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
1122 if (isFirst)
1123 {
1124 if (isLI) t=contexts_t::STARTLI; else if (isDD) t=contexts_t::STARTDD; else if (isTD) t=contexts_t::STARTTD;
1125 }
1126 if (isLast)
1127 {
1128 if (isLI) t=contexts_t::ENDLI; else if (isDD) t=contexts_t::ENDDD; else if (isTD) t=contexts_t::ENDTD;
1129 }
1130 if (!isFirst && !isLast)
1131 {
1132 if (isLI) t=contexts_t::INTERLI; else if (isDD) t=contexts_t::INTERDD; else if (isTD) t=contexts_t::INTERTD;
1133 }
1134 return t;
1135 }
1136 const auto &docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
1137 if (docAutoListItem)
1138 {
1139 isFirst=isFirstChildNode(docAutoListItem,p);
1140 isLast =isLastChildNode (docAutoListItem,p);
1141 t=contexts_t::STARTLI; // not used
1142 return t;
1143 }
1144 const auto &docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
1145 if (docSimpleListItem)
1146 {
1147 isFirst=true;
1148 isLast =true;
1149 t=contexts_t::STARTLI; // not used
1150 return t;
1151 }
1152 const auto &docParamList = std::get_if<DocParamList>(p.parent());
1153 if (docParamList)
1154 {
1155 isFirst=true;
1156 isLast =true;
1157 t=contexts_t::STARTLI; // not used
1158 return t;
1159 }
1160 const auto &docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
1161 if (docHtmlListItem)
1162 {
1163 isFirst=isFirstChildNode(docHtmlListItem,p);
1164 isLast =isLastChildNode (docHtmlListItem,p);
1165 if (isFirst) t=contexts_t::STARTLI;
1166 if (isLast) t=contexts_t::ENDLI;
1167 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1168 return t;
1169 }
1170 const auto &docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
1171 if (docSecRefItem)
1172 {
1173 isFirst=isFirstChildNode(docSecRefItem,p);
1174 isLast =isLastChildNode (docSecRefItem,p);
1175 if (isFirst) t=contexts_t::STARTLI;
1176 if (isLast) t=contexts_t::ENDLI;
1177 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1178 return t;
1179 }
1180 const auto &docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
1181 if (docHtmlDescData)
1182 {
1183 isFirst=isFirstChildNode(docHtmlDescData,p);
1184 isLast =isLastChildNode (docHtmlDescData,p);
1185 if (isFirst) t=contexts_t::STARTDD;
1186 if (isLast) t=contexts_t::ENDDD;
1187 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1188 return t;
1189 }
1190 const auto &docXRefItem = std::get_if<DocXRefItem>(p.parent());
1191 if (docXRefItem)
1192 {
1193 isFirst=isFirstChildNode(docXRefItem,p);
1194 isLast =isLastChildNode (docXRefItem,p);
1195 if (isFirst) t=contexts_t::STARTDD;
1196 if (isLast) t=contexts_t::ENDDD;
1197 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1198 return t;
1199 }
1200 const auto &docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
1201 if (docSimpleSect)
1202 {
1203 isFirst=isFirstChildNode(docSimpleSect,p);
1204 isLast =isLastChildNode (docSimpleSect,p);
1205 if (isFirst) t=contexts_t::STARTDD;
1206 if (isLast) t=contexts_t::ENDDD;
1207 if (isSeparatedParagraph(*docSimpleSect,p))
1208 // if the paragraph is enclosed with separators it will
1209 // be included in <dd>..</dd> so avoid addition paragraph
1210 // markers
1211 {
1212 isFirst=isLast=true;
1213 }
1214 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1215 return t;
1216 }
1217 const auto &docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
1218 if (docHtmlCell)
1219 {
1220 isFirst=isFirstChildNode(docHtmlCell,p);
1221 isLast =isLastChildNode (docHtmlCell,p);
1222 if (isFirst) t=contexts_t::STARTTD;
1223 if (isLast) t=contexts_t::ENDTD;
1224 if (!isFirst && !isLast) t = contexts_t::INTERTD;
1225 return t;
1226 }
1227 }
1228 return t;
1229}
1230
1231static bool determineIfNeedsTag(const DocPara &p)
1232{
1233 bool needsTag = false;
1234 if (p.parent())
1235 {
1249 >(*p.parent()))
1250 {
1251 needsTag = true;
1252 }
1253 else if (std::get_if<DocRoot>(p.parent()))
1254 {
1255 needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
1256 }
1257 }
1258 return needsTag;
1259}
1260
1262{
1263 if (m_hide) return;
1264
1265 //printf("> DocPara\n");
1266 //dumpDocNodeList(p.children());
1267
1268 bool needsTag = determineIfNeedsTag(p);
1269 //printf(" needsTag=%d\n",needsTag);
1270 bool needsTagBefore = needsTag;
1271 bool needsTagAfter = needsTag;
1272
1273 // if the first element of a paragraph is something that should be outside of
1274 // the paragraph (<ul>,<dl>,<table>,..) then that will already started the
1275 // paragraph and we don't need to do it here
1276 if (!p.children().empty())
1277 {
1278 auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
1279 [](const auto &node) { return !isInvisibleNode(node); });
1280 if (it!=std::end(p.children()))
1281 {
1282 const DocNodeVariant &n = *it;
1284 {
1285 needsTagBefore = false;
1286 }
1287 }
1288 }
1289
1290 // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
1291 // this allows us to mark the tag with a special class so we can
1292 // fix the otherwise ugly spacing.
1293 bool isFirst = false;
1294 bool isLast = false;
1295 contexts_t t = getParagraphContext(p,isFirst,isLast);
1296 //printf("startPara first=%d last=%d\n",isFirst,isLast);
1297 if (isFirst && isLast) needsTagBefore=false;
1298
1299 //printf(" needsTagBefore=%d\n",needsTagBefore);
1300 // write the paragraph tag (if needed)
1301 if (needsTagBefore)
1302 {
1303 if (contexts(t))
1304 m_t << "<p class=\"" << contexts(t) << "\"" << p.attribs().toString() << ">";
1305 else
1306 m_t << "<p" << p.attribs().toString() << ">";
1307 }
1308
1309 visitChildren(p);
1310
1311 // if the last element of a paragraph is something that should be outside of
1312 // the paragraph (<ul>,<dl>,<table>) then that will already have ended the
1313 // paragraph and we don't need to do it here
1314 if (!p.children().empty())
1315 {
1316 auto it = std::prev(std::end(p.children()));
1317 for (;;)
1318 {
1319 const DocNodeVariant &n = *it;
1320 if (!isInvisibleNode(n))
1321 {
1323 {
1324 needsTagAfter = false;
1325 }
1326 // stop searching if we found a node that is visible
1327 break;
1328 }
1329 if (it==std::begin(p.children()))
1330 {
1331 // stop searching if we are at the beginning of the list
1332 break;
1333 }
1334 else
1335 {
1336 --it;
1337 }
1338 }
1339 }
1340
1341 //printf("endPara first=%d last=%d\n",isFirst,isLast);
1342 if (isFirst && isLast) needsTagAfter=false;
1343
1344 //printf(" needsTagAfter=%d\n",needsTagAfter);
1345 if (needsTagAfter) m_t << "</p>\n";
1346 //printf("< DocPara\n");
1347}
1348
1350{
1351 //printf("> DocRoot\n");
1352 //dumpDocNodeList(r.children());
1353 visitChildren(r);
1354 //printf("< DocRoot\n");
1355}
1356
1358{
1359 if (m_hide) return;
1361 m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
1362 switch(s.type())
1363 {
1364 case DocSimpleSect::See:
1365 m_t << theTranslator->trSeeAlso(); break;
1367 m_t << theTranslator->trReturns(); break;
1369 m_t << theTranslator->trAuthor(true,true); break;
1371 m_t << theTranslator->trAuthor(true,false); break;
1373 m_t << theTranslator->trVersion(); break;
1375 m_t << theTranslator->trSince(); break;
1377 m_t << theTranslator->trDate(); break;
1379 m_t << theTranslator->trNote(); break;
1381 m_t << theTranslator->trWarning(); break;
1382 case DocSimpleSect::Pre:
1383 m_t << theTranslator->trPrecondition(); break;
1385 m_t << theTranslator->trPostcondition(); break;
1387 m_t << theTranslator->trCopyright(); break;
1389 m_t << theTranslator->trInvariant(); break;
1391 m_t << theTranslator->trRemarks(); break;
1393 m_t << theTranslator->trAttention(); break;
1395 m_t << theTranslator->trImportant(); break;
1396 case DocSimpleSect::User: break;
1397 case DocSimpleSect::Rcs: break;
1398 case DocSimpleSect::Unknown: break;
1399 }
1400
1401 if (s.title())
1402 {
1403 std::visit(*this,*s.title());
1404 }
1405 m_t << "</dt><dd>";
1406 visitChildren(s);
1407 m_t << "</dd></dl>\n";
1409}
1410
1412{
1413 if (m_hide) return;
1414 visitChildren(t);
1415}
1416
1418{
1419 if (m_hide) return;
1421 m_t << "<ul>";
1422 if (!sl.isPreformatted()) m_t << "\n";
1423 visitChildren(sl);
1424 m_t << "</ul>";
1425 if (!sl.isPreformatted()) m_t << "\n";
1427}
1428
1430{
1431 if (m_hide) return;
1432 m_t << "<li>";
1433 if (li.paragraph())
1434 {
1435 visit(*this,*li.paragraph());
1436 }
1437 m_t << "</li>";
1438 if (!li.isPreformatted()) m_t << "\n";
1439}
1440
1442{
1443 if (m_hide) return;
1445 m_t << "<h" << s.level() << " class=\"doxsection\">";
1446 m_t << "<a class=\"anchor\" id=\"" << s.anchor();
1447 m_t << "\"></a>\n";
1448 if (s.title())
1449 {
1450 std::visit(*this,*s.title());
1451 }
1452 m_t << "</h" << s.level() << ">\n";
1453 visitChildren(s);
1455}
1456
1458{
1459 if (m_hide) return;
1461 if (s.type()==DocHtmlList::Ordered)
1462 {
1463 m_t << "<ol" << s.attribs().toString();
1464 }
1465 else
1466 {
1467 m_t << "<ul" << s.attribs().toString();
1468 }
1469 m_t << ">\n";
1470 visitChildren(s);
1471 if (s.type()==DocHtmlList::Ordered)
1472 {
1473 m_t << "</ol>";
1474 }
1475 else
1476 {
1477 m_t << "</ul>";
1478 }
1479 if (!s.isPreformatted()) m_t << "\n";
1481}
1482
1484{
1485 if (m_hide) return;
1486 m_t << "<li" << i.attribs().toString() << ">";
1487 if (!i.isPreformatted()) m_t << "\n";
1488 visitChildren(i);
1489 m_t << "</li>\n";
1490}
1491
1493{
1494 if (m_hide) return;
1496 m_t << "<dl" << dl.attribs().toString() << ">\n";
1497 visitChildren(dl);
1498 m_t << "</dl>\n";
1500}
1501
1503{
1504 if (m_hide) return;
1505 m_t << "<dt" << dt.attribs().toString() << ">";
1506 visitChildren(dt);
1507 m_t << "</dt>\n";
1508}
1509
1511{
1512 if (m_hide) return;
1513 m_t << "<dd" << dd.attribs().toString() << ">";
1514 visitChildren(dd);
1515 m_t << "</dd>\n";
1516}
1517
1519{
1520 if (m_hide) return;
1521
1523
1524 if (t.caption())
1525 {
1526 DString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
1527 if (!anc.empty())
1528 {
1529 m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
1530 }
1531 }
1532
1533 DString attrs = t.attribs().toString();
1534 if (attrs.empty())
1535 {
1536 m_t << "<table class=\"doxtable\">\n";
1537 }
1538 else
1539 {
1540 m_t << "<table" << t.attribs().toString() << ">\n";
1541 }
1542 if (t.caption())
1543 {
1544 std::visit(*this,*t.caption());
1545 }
1546 visitChildren(t);
1547 m_t << "</table>\n";
1549}
1550
1552{
1553 if (m_hide) return;
1554 m_t << "<tr" << tr.attribs().toString() << ">\n";
1555 visitChildren(tr);
1556 m_t << "</tr>\n";
1557}
1558
1560{
1561 if (m_hide) return;
1562 if (c.isHeading())
1563 {
1564 m_t << "<th" << c.attribs().toString() << ">";
1565 }
1566 else
1567 {
1568 m_t << "<td" << c.attribs().toString() << ">";
1569 }
1570 visitChildren(c);
1571 if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
1572}
1573
1575{
1576 if (m_hide) return;
1577 m_t << "<caption" << c.attribs().toString() << ">";
1578 visitChildren(c);
1579 m_t << "</caption>\n";
1580}
1581
1583{
1584 if (m_hide) return;
1585 visitChildren(i);
1586}
1587
1589{
1590 if (m_hide) return;
1591 if (href.url().startsWith("mailto:"))
1592 {
1594 }
1595 else
1596 {
1597 DString url = correctURL(href.url(),href.relPath());
1598 m_t << "<a href=\"" << convertToHtml(url) << "\""
1599 << href.attribs().toString() << ">";
1600 }
1601 visitChildren(href);
1602 m_t << "</a>";
1603}
1604
1606{
1607 if (m_hide) return;
1608 m_t << "<summary " << s.attribs().toString() << ">\n";
1609 visitChildren(s);
1610 m_t << "</summary>\n";
1611}
1612
1614{
1615 if (m_hide) return;
1617 m_t << "<details " << d.attribs().toString() << ">\n";
1618 auto summary = d.summary();
1619 if (summary)
1620 {
1621 std::visit(*this,*summary);
1622 }
1623 visitChildren(d);
1624 m_t << "</details>\n";
1626}
1627
1629{
1630 if (m_hide) return;
1631 forceEndParagraph(header);
1632 m_t << "<h" << header.level() << header.attribs().toString() << ">";
1633 visitChildren(header);
1634 m_t << "</h" << header.level() << ">\n";
1635 forceStartParagraph(header);
1636}
1637
1639{
1640 if (img.type()==DocImage::Html)
1641 {
1642 bool inlineImage = img.isInlineImage();
1643 bool typeSVG = img.isSVG();
1644 DString url = img.url();
1645
1646 if (!inlineImage)
1647 {
1648 forceEndParagraph(img);
1649 }
1650 if (m_hide) return;
1651 DString baseName=stripPath(img.name());
1652 if (!inlineImage) m_t << "<div class=\"image\">\n";
1653 DString sizeAttribs;
1654 if (!img.width().empty())
1655 {
1656 sizeAttribs+=" width=\""+img.width()+"\"";
1657 }
1658 if (!img.height().empty()) // link to local file
1659 {
1660 sizeAttribs+=" height=\""+img.height()+"\"";
1661 }
1662 // 16 cases: url.empty() | typeSVG | inlineImage | img.hasCaption()
1663
1664 HtmlAttribList attribs = img.attribs();
1665 if (typeSVG)
1666 {
1667 attribs.mergeAttribute("style","pointer-events: none;");
1668 }
1669 DString alt;
1670 DString attrs = attribs.toString(&alt);
1671 DString src;
1672 if (url.empty())
1673 {
1674 src = img.relPath()+img.name();
1675 }
1676 else
1677 {
1678 src = correctURL(url,img.relPath());
1679 }
1680 if (typeSVG && !inlineImage && !src.startsWith("http://") && !src.startsWith("https://"))
1681 {
1682 m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src)
1683 << "\"" << sizeAttribs << attrs;
1684 if (inlineImage)
1685 {
1686 // skip closing tag
1687 }
1688 else
1689 {
1690 m_t << ">" << alt << "</object>\n";
1691 }
1692 }
1693 else
1694 {
1695 m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs;
1696 if (inlineImage)
1697 {
1698 m_t << " class=\"inline\"";
1699 }
1700 else
1701 {
1702 m_t << "/>\n";
1703 }
1704 }
1705 if (img.hasCaption())
1706 {
1707 if (inlineImage)
1708 {
1709 m_t << " title=\"";
1710 m_insideTitle=true;
1711 }
1712 else
1713 {
1714 m_t << "<div class=\"caption\">\n";
1715 }
1716 }
1717 else if (inlineImage)
1718 {
1719 m_t << "/>";
1720 }
1721
1722 visitChildren(img);
1723
1724 if (img.hasCaption())
1725 {
1726 if (inlineImage)
1727 {
1728 m_t << "\"/>";
1729 m_insideTitle=false;
1730 }
1731 else // end <div class="caption">
1732 {
1733 m_t << "</div>";
1734 }
1735 }
1736 if (!inlineImage) // end <div class="image">
1737 {
1738 m_t << "</div>\n";
1740 }
1741 }
1742 else // other format -> skip
1743 {
1744 }
1745}
1746
1748{
1749 if (m_hide) return;
1751 bool exists = false;
1752 std::string inBuf;
1753 if (readInputFile(df.file(),inBuf))
1754 {
1755 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1756 ".dot", // extension
1757 inBuf, // contents
1758 exists);
1759 if (!fileName.empty())
1760 {
1761 m_t << "<div class=\"dotgraph\">\n";
1762 writeDotFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1763 if (df.hasCaption())
1764 {
1765 m_t << "<div class=\"caption\">\n";
1766 }
1767 visitChildren(df);
1768 if (df.hasCaption())
1769 {
1770 m_t << "</div>\n";
1771 }
1772 m_t << "</div>\n";
1773 }
1774 }
1776}
1777
1779{
1780 if (m_hide) return;
1782 bool exists = false;
1783 std::string inBuf;
1784 if (readInputFile(df.file(),inBuf))
1785 {
1786 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1787 ".msc", // extension
1788 inBuf, // contents
1789 exists);
1790 if (!fileName.empty())
1791 {
1792 m_t << "<div class=\"mscgraph\">\n";
1793 writeMscFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1794 if (df.hasCaption())
1795 {
1796 m_t << "<div class=\"caption\">\n";
1797 }
1798 visitChildren(df);
1799 if (df.hasCaption())
1800 {
1801 m_t << "</div>\n";
1802 }
1803 m_t << "</div>\n";
1804 }
1805 }
1807}
1808
1810{
1811 if (m_hide) return;
1813 bool exists = false;
1814 std::string inBuf;
1815 if (readInputFile(df.file(),inBuf))
1816 {
1817 auto fileName = writeInlineGraph(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1818 ".dia", // extension
1819 inBuf, // contents
1820 exists);
1821 if (!fileName.empty())
1822 {
1823 m_t << "<div class=\"diagraph\">\n";
1824 writeDiaFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1825 if (df.hasCaption())
1826 {
1827 m_t << "<div class=\"caption\">\n";
1828 }
1829 visitChildren(df);
1830 if (df.hasCaption())
1831 {
1832 m_t << "</div>\n";
1833 }
1834 m_t << "</div>\n";
1835 }
1836 }
1838}
1839
1841{
1842 if (m_hide) return;
1843 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1845 DString htmlOutput = Config_getString(HTML_OUTPUT);
1846 DString imgExt = getDotImageExtension();
1847 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
1848 if (imgExt=="svg")
1849 {
1851 }
1852 std::string inBuf;
1853 readInputFile(df.file(),inBuf);
1854 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(htmlOutput,DString(),
1855 inBuf,format,DString(),df.srcFile(),df.srcLine(),false);
1856 for (const auto &bName: baseNameVector)
1857 {
1858 DString baseName=makeBaseName(bName,".pu");
1859 m_t << "<div class=\"plantumlgraph\">\n";
1860 writePlantUMLFile(baseName,df.relPath(),DString(),df.srcFile(),df.srcLine());
1861 if (df.hasCaption())
1862 {
1863 m_t << "<div class=\"caption\">\n";
1864 }
1865 visitChildren(df);
1866 if (df.hasCaption())
1867 {
1868 m_t << "</div>\n";
1869 }
1870 m_t << "</div>\n";
1871 }
1873}
1874
1876{
1877 if (m_hide) return;
1878 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1880 if (Config_getEnum(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLI)
1881 {
1882 std::string inBuf;
1883 readInputFile(df.file(),inBuf);
1884 auto htmlOutput = Config_getString(HTML_OUTPUT);
1885 auto outputFormat = MermaidManager::OutputFormat::HTML;
1886 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
1888 inBuf,imageFormat,df.srcFile(),df.srcLine());
1889 m_t << "<div class=\"mermaidgraph\">\n";
1890 writeMermaidFile(baseName,df.relPath(),DString(),df.srcFile(),df.srcLine());
1891 if (df.hasCaption())
1892 {
1893 m_t << "<div class=\"caption\">\n";
1894 }
1895 visitChildren(df);
1896 if (df.hasCaption())
1897 {
1898 m_t << "</div>\n";
1899 }
1900 m_t << "</div>\n";
1901 }
1902 else // AUTO or CLIENT_SIDE
1903 {
1904 // CLIENT_SIDE or AUTO: embed mermaid source for client-side rendering
1905 std::string inBuf;
1906 readInputFile(df.file(),inBuf);
1907 m_t << "<div class=\"mermaidgraph\">\n";
1908 m_t << "<pre class=\"mermaid\">\n";
1909 m_t << convertToHtml(inBuf);
1910 m_t << "</pre>\n";
1911 if (df.hasCaption())
1912 {
1913 m_t << "<div class=\"caption\">\n";
1914 }
1915 visitChildren(df);
1916 if (df.hasCaption())
1917 {
1918 m_t << "</div>\n";
1919 }
1920 m_t << "</div>\n";
1921 }
1923}
1924
1926{
1927 if (m_hide) return;
1928 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1929 visitChildren(lnk);
1930 endLink();
1931}
1932
1934{
1935 if (m_hide) return;
1936 if (!ref.file().empty())
1937 {
1938 // when ref.isSubPage()==true we use ref.file() for HTML and
1939 // ref.anchor() for LaTeX/RTF
1940 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? DString() : ref.anchor(), ref.targetTitle());
1941 }
1942 if (!ref.hasLinkText()) filter(ref.targetTitle());
1943 visitChildren(ref);
1944 if (!ref.file().empty()) endLink();
1945 //m_t << " ";
1946}
1947
1949{
1950 if (m_hide) return;
1951 if (!ref.file().empty())
1952 {
1953 m_t << "<li>";
1954 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? DString() : ref.anchor());
1955 }
1956 visitChildren(ref);
1957 if (!ref.file().empty())
1958 {
1959 endLink();
1960 m_t << "</li>\n";
1961 }
1962}
1963
1965{
1966 if (m_hide) return;
1968 m_t << "<div>\n";
1969 m_t << "<ul class=\"multicol\">\n";
1970 visitChildren(s);
1971 m_t << "</ul>\n";
1972 m_t << "</div>\n";
1974}
1975
1977{
1978 if (m_hide) return;
1980 DString className;
1981 DString heading;
1982 switch(s.type())
1983 {
1985 heading=theTranslator->trParameters();
1986 className="params";
1987 break;
1989 heading=theTranslator->trReturnValues();
1990 className="retval";
1991 break;
1993 heading=theTranslator->trExceptions();
1994 className="exception";
1995 break;
1998 className="tparams";
1999 break;
2000 default:
2001 ASSERT(0);
2002 }
2003 m_t << "<dl class=\"" << className << "\"><dt>";
2004 m_t << heading;
2005 m_t << "</dt><dd>\n";
2006 m_t << " <table class=\"" << className << "\">\n";
2007 visitChildren(s);
2008 m_t << " </table>\n";
2009 m_t << " </dd>\n";
2010 m_t << "</dl>\n";
2012}
2013
2015{
2016 if (m_hide) return;
2017 m_t << "&#160;" << s.chars() << "&#160;";
2018}
2019
2021{
2022 //printf("DocParamList::visitPre\n");
2023 if (m_hide) return;
2024 m_t << " <tr>";
2025 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
2026 if (sect && sect->hasInOutSpecifier())
2027 {
2028 m_t << "<td class=\"paramdir\">";
2030 {
2031 m_t << "[";
2032 if (pl.direction()==DocParamSect::In)
2033 {
2034 m_t << "in";
2035 }
2036 else if (pl.direction()==DocParamSect::Out)
2037 {
2038 m_t << "out";
2039 }
2040 else if (pl.direction()==DocParamSect::InOut)
2041 {
2042 m_t << "in,out";
2043 }
2044 m_t << "]";
2045 }
2046 m_t << "</td>";
2047 }
2048 if (sect && sect->hasTypeSpecifier())
2049 {
2050 m_t << "<td class=\"paramtype\">";
2051 for (const auto &type : pl.paramTypes())
2052 {
2053 std::visit(*this,type);
2054 }
2055 m_t << "</td>";
2056 }
2057 m_t << "<td class=\"paramname\">";
2058 bool first=true;
2059 for (const auto &param : pl.parameters())
2060 {
2061 if (!first) m_t << ","; else first=false;
2062 std::visit(*this,param);
2063 }
2064 m_t << "</td><td>";
2065 for (const auto &par : pl.paragraphs())
2066 {
2067 std::visit(*this,par);
2068 }
2069 m_t << "</td></tr>\n";
2070}
2071
2073{
2074 if (m_hide) return;
2075 if (x.title().empty()) return;
2076
2078 bool anonymousEnum = x.file()=="@";
2079 DString key = x.key();
2080 key.stripPrefix(doxygenList);
2081 if (!anonymousEnum)
2082 {
2083 DString fn = x.file();
2085 m_t << "<dl class=\"" << key << "\"><dt><b><a class=\"el\" href=\""
2086 << x.relPath() << fn
2087 << "#" << x.anchor() << "\">";
2088 }
2089 else
2090 {
2091 m_t << "<dl class=\"" << key << "\"><dt><b>";
2092 }
2093 filter(x.title());
2094 if (!anonymousEnum) m_t << "</a>";
2095 m_t << "</b></dt><dd>";
2096 visitChildren(x);
2097 if (x.title().empty()) return;
2098 m_t << "</dd></dl>\n";
2100}
2101
2103{
2104 if (m_hide) return;
2105 startLink(DString(),ref.file(),ref.relPath(),ref.anchor());
2106 visitChildren(ref);
2107 endLink();
2108 m_t << " ";
2109}
2110
2112{
2113 visitChildren(t);
2114}
2115
2117{
2118 if (m_hide) return;
2120 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2121 visitChildren(b);
2122 m_t << "</blockquote>\n";
2124}
2125
2127{
2128 if (m_hide) return;
2129 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2130 {
2133 m_t << "<p>";
2135 m_t << " ";
2136 m_t << "<a href=\"";
2137 m_t << fname;
2138 m_t << ".svg\">";
2140 m_t << "</a>";
2141 if (vf.hasCaption())
2142 {
2143 m_t << "<br />";
2144 }
2145 }
2146 visitChildren(vf);
2147 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2148 {
2149 m_t << "</p>";
2151 }
2152}
2153
2155{
2156 if (m_hide) return;
2157 visitChildren(pb);
2158}
2159
2160void HtmlDocVisitor::filter(const DString &str, bool retainNewline, bool citeEntry)
2161{
2162 if (str.empty()) return;
2163 const char *p=str.data();
2164 while (*p)
2165 {
2166 char c=*p++;
2167 switch(c)
2168 {
2169 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2170 case '<': m_t << "&lt;"; break;
2171 case '>': m_t << "&gt;"; break;
2172 case '&': // possibility to have a special symbol
2173 if (!citeEntry) {m_t << "&amp;"; break;}
2175 m_t,
2176 p-1,
2177 [](HtmlEntityMapper::SymType symType) { return HtmlEntityMapper::instance().html(symType); },
2178 "&amp;");
2179 break;
2180 case '\\':
2181 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2182 m_t << "\\&zwj;" << *p++;
2183 else
2184 m_t << c;
2185 break;
2186 default:
2187 {
2188 uint8_t uc = static_cast<uint8_t>(c);
2189 if (uc<32 && !isspace(c)) // non-printable control characters
2190 {
2191 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2192 }
2193 else
2194 {
2195 m_t << c;
2196 }
2197 }
2198 break;
2199 }
2200 }
2201}
2202
2203/// Escape basic entities to produce a valid CDATA attribute value,
2204/// assume that the outer quoting will be using the double quote &quot;
2206{
2207 if (str.empty()) return str;
2208 DString result;
2209 result.reserve(str.length()+8);
2210 const char *p=str.data();
2211 while (*p)
2212 {
2213 char c=*p++;
2214 switch(c)
2215 {
2216 case '&': result+="&amp;"; break;
2217 case '"': result+="&quot;"; break;
2218 case '<': result+="&lt;"; break;
2219 case '>': result+="&gt;"; break;
2220 case '\\':
2221 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2222 {
2223 result+="\\&zwj;";
2224 result+=*p++;
2225 }
2226 else
2227 {
2228 result+=c;
2229 }
2230 break;
2231 default:
2232 {
2233 uint8_t uc = static_cast<uint8_t>(c);
2234 if (uc<32 && !isspace(c)) // non-printable control characters
2235 {
2236 result+="&#x24";
2237 result+=hex[uc>>4];
2238 result+=hex[uc&0xF];
2239 result+=";";
2240 }
2241 else
2242 {
2243 result+=c;
2244 }
2245 }
2246 break;
2247 }
2248 }
2249 return result;
2250}
2251
2252void HtmlDocVisitor::startLink(const DString &ref,const DString &file,
2253 const DString &relPath,const DString &anchor,
2254 const DString &tooltip)
2255{
2256 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2257 if (!ref.empty()) // link to entity imported via tag file
2258 {
2259 m_t << "<a class=\"elRef\" ";
2261 }
2262 else // local link
2263 {
2264 m_t << "<a class=\"el\" ";
2265 }
2266 m_t << "href=\"";
2267 DString fn = file;
2269 m_t << createHtmlUrl(relPath,ref,
2270 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2271 fn,
2272 anchor);
2273 m_t << "\"";
2274 if (!tooltip.empty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2275 m_t << ">";
2276}
2277
2279{
2280 m_t << "</a>";
2281}
2282
2283void HtmlDocVisitor::writeDotFile(const DString &fileName,const DString &relPath,
2284 const DString &context,const DString &srcFile,int srcLine,bool newFile)
2285{
2286 DString baseName=makeBaseName(fileName,".dot");
2287 baseName.prepend("dot_");
2288 DString outDir = Config_getString(HTML_OUTPUT);
2289 if (newFile) writeDotGraphFromFile(fileName,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine,true);
2290 writeDotImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,-1,srcFile,srcLine,newFile);
2291}
2292
2293void HtmlDocVisitor::writeMscFile(const DString &fileName,const DString &relPath,
2294 const DString &context,const DString &srcFile,int srcLine, bool newFile)
2295{
2296 DString baseName=makeBaseName(fileName,".msc");
2297 baseName.prepend("msc_");
2298 DString outDir = Config_getString(HTML_OUTPUT);
2299 DString imgExt = getDotImageExtension();
2300 MscOutputFormat mscFormat = imgExt=="svg" ? MscOutputFormat::SVG : MscOutputFormat::BITMAP;
2301 if (newFile) writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine,true);
2302 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2303}
2304
2305void HtmlDocVisitor::writeDiaFile(const DString &fileName, const DString &relPath,
2306 const DString &,const DString &srcFile,int srcLine, bool newFile)
2307{
2308 DString baseName=makeBaseName(fileName,".dia");
2309 baseName.prepend("dia_");
2310 DString outDir = Config_getString(HTML_OUTPUT);
2311 if (newFile) writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine,true);
2312
2313 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2314}
2315
2316void HtmlDocVisitor::writePlantUMLFile(const DString &fileName, const DString &relPath,
2317 const DString &,const DString &/* srcFile */,int /* srcLine */)
2318{
2319 DString baseName=makeBaseName(fileName,".pu");
2320 DString outDir = Config_getString(HTML_OUTPUT);
2321 DString imgExt = getDotImageExtension();
2322 if (imgExt=="svg")
2323 {
2325 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2326 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2327 //m_t << "</iframe>\n";
2328 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2329 }
2330 else
2331 {
2333 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2334 }
2335}
2336
2337void HtmlDocVisitor::writeMermaidFile(const DString &fileName, const DString &relPath,
2338 const DString &,const DString &/* srcFile */,int /* srcLine */)
2339{
2340 auto baseName = makeBaseName(fileName,".mmd");
2341 auto outDir = Config_getString(HTML_OUTPUT);
2342 auto outputFormat = MermaidManager::OutputFormat::HTML;
2343 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
2344 auto imgExt = MermaidManager::imageExtension(imageFormat);
2345 MermaidManager::instance().generateMermaidOutput(fileName,outDir,imageFormat,true);
2346 if (imageFormat == MermaidManager::ImageFormat::SVG)
2347 {
2348 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << "." << imgExt << "\"></object>\n";
2349 }
2350 else
2351 {
2352 m_t << "<img src=\"" << relPath << baseName << "." << imgExt << "\" />\n";
2353 }
2354}
2355
2356/** Returns true if the child nodes in paragraph \a para until \a nodeIndex
2357 contain a style change node that is still active and that style change is one that
2358 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2359 See also bug746162.
2360 */
2363{
2364 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2365 int styleMask=0;
2366 bool styleOutsideParagraph=false;
2367 while (!styleOutsideParagraph)
2368 {
2369 const DocNodeVariant *n = &(*it);
2370 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2371 if (sc)
2372 {
2373 if (!sc->enable()) // remember styles that has been closed already
2374 {
2375 styleMask|=static_cast<int>(sc->style());
2376 }
2377 bool paraStyle = sc->style()==DocStyleChange::Center ||
2378 sc->style()==DocStyleChange::Div ||
2380 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2381 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2382 paraStyle
2383 )
2384 {
2385 styleOutsideParagraph=true;
2386 }
2387 }
2388 if (it!=std::begin(para->children()))
2389 {
2390 --it;
2391 }
2392 else
2393 {
2394 break;
2395 }
2396 }
2397 return styleOutsideParagraph;
2398}
2399
2400/** Used for items found inside a paragraph, which due to XHTML restrictions
2401 * have to be outside of the paragraph. This method will forcefully end
2402 * the current paragraph and forceStartParagraph() will restart it.
2403 */
2404template<class Node>
2406{
2407 const DocPara *para=std::get_if<DocPara>(n.parent());
2408 if (para)
2409 {
2410 const DocNodeList &children = para->children();
2411
2412 //printf("forceEndParagraph\n");
2413 //dumpDocNodeList(children);
2414
2415 auto it = std::find_if(std::begin(children),std::end(children),
2416 [&n](const auto &np) { return holds_value(&n,np); });
2417 if (it==std::end(children)) return;
2418 if (it==std::begin(children)) return; // first node in paragraph
2419 it = std::prev(it);
2420 bool found=false;
2421 while (!found)
2422 {
2423 found = !isInvisibleNode(*it);
2424 if (found) break;
2425 if (it!=std::begin(children))
2426 {
2427 --it;
2428 }
2429 else
2430 {
2431 break;
2432 }
2433 }
2434 if (!found) return; // first visible node in paragraph
2435 const DocNodeVariant &v = *it;
2436 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2437 bool styleOutsideParagraph=false;
2438 if (it!=std::begin(children))
2439 {
2440 it = std::prev(it);
2441 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2442 }
2443 bool isFirst = false;
2444 bool isLast = false;
2445 getParagraphContext(*para,isFirst,isLast);
2446 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2447 if (isFirst && isLast) return;
2448 if (styleOutsideParagraph) return;
2449
2450 //printf("adding </p>\n");
2451 m_t << "</p>";
2452 }
2453}
2454
2455/** Used for items found inside a paragraph, which due to XHTML restrictions
2456 * have to be outside of the paragraph. This method will forcefully start
2457 * the paragraph, that was previously ended by forceEndParagraph().
2458 */
2459template<class Node>
2461{
2462 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2463 const DocPara *para=nullptr;
2464 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2465 {
2466 const DocNodeList &children = para->children();
2467
2468 auto it = std::find_if(std::begin(children),
2469 std::end(children),
2470 [&n](const auto &np)
2471 { return holds_value(&n,np); });
2472 if (it==std::end(children)) return;
2473 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2474 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2475 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2476 if (styleOutsideParagraph) return;
2477 it = std::next(it);
2478 while (it!=std::end(children) && isInvisibleNode(*it))
2479 {
2480 ++it;
2481 }
2482 if (it!=std::end(children))
2483 {
2484 const DocNodeVariant &v = *it;
2485 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2486 }
2487 else
2488 {
2489 return; // only whitespace at the end!
2490 }
2491
2492 bool needsTag = true;
2493 bool isFirst = false;
2494 bool isLast = false;
2495 getParagraphContext(*para,isFirst,isLast);
2496 if (isFirst && isLast) needsTag = false;
2497 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2498
2499 if (needsTag) m_t << "<p>";
2500 }
2501}
2502
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
bool stripPrefix(const DString &prefix)
Definition dstring.h:290
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:988
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:2344
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:1377
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:3354
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, bool prepend=false)
Definition htmlattrib.h:33
DString toString(DString *pAltValue=nullptr) const
Definition htmlattrib.h:54
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:269
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:5374
DString externalLinkTarget(const bool parent)
Definition util.cpp:4492
DString correctURL(const DString &url, const DString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:4660
DString getFileNameExtension(const DString &fn)
Definition util.cpp:4211
DString convertToHtml(const DString &s, bool keepEntities)
Definition util.cpp:3292
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:4375
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4169
void addHtmlExtensionIfMissing(DString &fName)
Definition util.cpp:3932
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:4620
DString createHtmlUrl(const DString &relPath, const DString &ref, bool isLocalFile, const DString &targetFileName, const DString &anchor)
Definition util.cpp:4503
DString getDotImageExtension()
Definition util.cpp:4965
DString makeBaseName(const DString &name, const DString &ext)
Definition util.cpp:3975
DString stripPath(const DString &s)
Definition util.cpp:3961
SrcLangExt getLanguageFromCodeLang(DString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:4187
A bunch of utility functions.