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