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 "portable.h"
40#include "codefragment.h"
41#include "cite.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 m_t << "<span class=\"tt\"" << s.attribs().toString() << ">";
470 m_insidePre=true;
471 }
472 else
473 {
474 m_t << "</span>";
475 m_insidePre=false;
476 }
477 break;
479 if (s.enable())
480 {
481 auto attribs = s.attribs();
482 if (s.tagName()=="p")
483 {
484 attribs.mergeAttribute("class","param");
485 }
486 m_t << "<code" << attribs.toString() << ">";
487 m_insidePre=true;
488 }
489 else
490 {
491 m_insidePre=false;
492 m_t << "</code>";
493 }
494 break;
496 if (s.enable()) m_t << "<sub" << s.attribs().toString() << ">"; else m_t << "</sub>";
497 break;
499 if (s.enable()) m_t << "<sup" << s.attribs().toString() << ">"; else m_t << "</sup>";
500 break;
502 if (s.enable())
503 {
505 m_t << "<center" << s.attribs().toString() << ">";
506 }
507 else
508 {
509 m_t << "</center>";
511 }
512 break;
514 if (s.enable()) m_t << "<small" << s.attribs().toString() << ">"; else m_t << "</small>";
515 break;
517 if (s.enable()) m_t << "<cite" << s.attribs().toString() << ">"; else m_t << "</cite>";
518 break;
520 if (s.enable())
521 {
523 m_t << "<pre" << s.attribs().toString() << ">";
525 }
526 else
527 {
529 m_t << "</pre>";
531 }
532 break;
534 if (s.enable())
535 {
537 m_t << "<div" << s.attribs().toString() << ">";
538 }
539 else
540 {
541 m_t << "</div>";
543 }
544 break;
546 if (s.enable()) m_t << "<span" << s.attribs().toString() << ">"; else m_t << "</span>";
547 break;
548 }
549}
550
551///--------------------------------------------------------------------------------------
552
554{
555 if (m_hide) return;
556 QCString lang = m_langExt;
557 if (!s.language().isEmpty()) // explicit language setting
558 {
559 lang = s.language();
560 }
561 SrcLangExt langExt = getLanguageFromCodeLang(lang);
562 switch(s.type())
563 {
566 m_ci.startCodeFragment("DoxyCode");
568 s.context(),
569 s.text(),
570 langExt,
571 Config_getBool(STRIP_CODE_COMMENTS),
572 s.isExample(),
573 s.exampleFile(),
574 nullptr, // fileDef
575 -1, // startLine
576 -1, // endLine
577 true, // inlineFragment
578 nullptr, // memberDef
579 true, // show line numbers
580 m_ctx // search context
581 );
582 m_ci.endCodeFragment("DoxyCode");
584 break;
587 m_t << "<pre class=\"fragment\">";
588 filter(s.text());
589 m_t << "</pre>";
591 break;
593 filter(s.text(), true);
594 break;
596 m_t << "<code class=\"JavaDocCode\">";
597 filter(s.text(), true);
598 m_t << "</code>";
599 break;
601 {
602 if (s.isBlock()) forceEndParagraph(s);
603 m_t << s.text();
604 if (s.isBlock()) forceStartParagraph(s);
605 }
606 break;
612 /* nothing */
613 break;
614
615 case DocVerbatim::Dot:
616 {
617 static int dotindex = 1;
618 QCString fileName(4096, QCString::ExplicitSize);
619
621 fileName.sprintf("%s%d%s",
622 qPrint(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_"),
623 dotindex++,
624 ".dot"
625 );
626 std::ofstream file = Portable::openOutputStream(fileName);
627 if (!file.is_open())
628 {
629 err("Could not open file {} for writing\n",fileName);
630 }
631 else
632 {
633 QCString stext = s.text();
634 file.write( stext.data(), stext.length() );
635 file.close();
636
637 m_t << "<div class=\"dotgraph\">\n";
638 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
639 visitCaption(m_t, s);
640 m_t << "</div>\n";
641
642 if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
643 }
645 }
646 break;
647 case DocVerbatim::Msc:
648 {
650
651 static int mscindex = 1;
652 QCString baseName(4096, QCString::ExplicitSize);
653
654 baseName.sprintf("%s%d",
655 qPrint(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_"),
656 mscindex++
657 );
658 std::ofstream file = Portable::openOutputStream(baseName.str()+".msc");
659 if (!file.is_open())
660 {
661 err("Could not open file {}.msc for writing\n",baseName);
662 }
663 else
664 {
665 QCString text = "msc {";
666 text+=s.text();
667 text+="}";
668
669 file.write( text.data(), text.length() );
670 file.close();
671
672 m_t << "<div class=\"mscgraph\">\n";
673 writeMscFile(baseName+".msc",s.relPath(),s.context(),s.srcFile(),s.srcLine());
674 visitCaption(m_t, s);
675 m_t << "</div>\n";
676
677 if (Config_getBool(DOT_CLEANUP)) Dir().remove(baseName.str()+".msc");
678 }
680 }
681 break;
683 {
685 QCString htmlOutput = Config_getString(HTML_OUTPUT);
687 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
688 if (imgExt=="svg")
689 {
691 }
692 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
693 htmlOutput,s.exampleFile(),
694 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
695 for (const auto &baseName: baseNameVector)
696 {
697 m_t << "<div class=\"plantumlgraph\">\n";
698 writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
699 visitCaption(m_t, s);
700 m_t << "</div>\n";
701 }
703 }
704 break;
705 }
706}
707
709{
710 if (m_hide) return;
711 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
712}
713
715{
716 if (m_hide) return;
718 switch(inc.type())
719 {
722 m_ci.startCodeFragment("DoxyCode");
724 inc.context(),
725 inc.text(),
726 langExt,
727 inc.stripCodeComments(),
728 inc.isExample(),
729 inc.exampleFile(),
730 nullptr, // fileDef
731 -1, // startLine
732 -1, // endLine
733 TRUE, // inlineFragment
734 nullptr, // memberDef
735 FALSE, // show line numbers
736 m_ctx // search context
737 );
738 m_ci.endCodeFragment("DoxyCode");
740 break;
742 {
744 m_ci.startCodeFragment("DoxyCode");
745 FileInfo cfi( inc.file().str() );
746 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
748 inc.context(),
749 inc.text(),
750 langExt,
751 inc.stripCodeComments(),
752 inc.isExample(),
753 inc.exampleFile(),
754 fd.get(), // fileDef,
755 -1, // start line
756 -1, // end line
757 true, // inline fragment
758 nullptr, // memberDef
759 true, // show line numbers
760 m_ctx // search context
761 );
762 m_ci.endCodeFragment("DoxyCode");
764 }
765 break;
773 break;
775 {
776 if (inc.isBlock()) forceEndParagraph(inc);
777 m_t << inc.text();
778 if (inc.isBlock()) forceStartParagraph(inc);
779 }
780 break;
783 m_t << "<pre class=\"fragment\">";
784 filter(inc.text());
785 m_t << "</pre>";
787 break;
791 m_ci.startCodeFragment("DoxyCode");
793 inc.file(),
794 inc.blockId(),
795 inc.context(),
797 inc.trimLeft(),
799 );
800 m_ci.endCodeFragment("DoxyCode");
802 break;
803 }
804}
805
807{
808 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
809 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
810 if (op.isFirst())
811 {
813 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
815 m_hide=TRUE;
816 }
818 if (locLangExt.isEmpty()) locLangExt = m_langExt;
819 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
820 if (op.type()!=DocIncOperator::Skip)
821 {
822 m_hide = popHidden();
823 if (!m_hide)
824 {
825 std::unique_ptr<FileDef> fd;
826 if (!op.includeFileName().isEmpty())
827 {
828 FileInfo cfi( op.includeFileName().str() );
829 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
830 }
831 getCodeParser(locLangExt).parseCode(
832 m_ci,
833 op.context(),
834 op.text(),
835 langExt,
837 op.isExample(),
838 op.exampleFile(),
839 fd.get(), // fileDef
840 op.line(), // startLine
841 -1, // endLine
842 true, // inline fragment
843 nullptr, // memberDef
844 op.showLineNo(), // show line numbers
845 m_ctx // search context
846 );
847 }
849 m_hide=TRUE;
850 }
851 if (op.isLast())
852 {
853 m_hide = popHidden();
854 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
856 }
857 else
858 {
859 if (!m_hide) m_t << "\n";
860 }
861}
862
864{
865 if (m_hide) return;
866 bool bDisplay = !f.isInline();
867 if (bDisplay)
868 {
870 m_t << "<p class=\"formulaDsp\">\n";
871 }
872
873 if (Config_getBool(USE_MATHJAX))
874 {
875 QCString text = f.text();
876 bool closeInline = FALSE;
877 if (!bDisplay && !text.isEmpty() && text.at(0)=='$' &&
878 text.at(text.length()-1)=='$')
879 {
880 closeInline=TRUE;
881 text = text.mid(1,text.length()-2);
882 m_t << "\\(";
883 }
884 else if (!bDisplay && !text.isEmpty())
885 {
886 closeInline=TRUE;
887 m_t << "\\(";
888 }
889 m_t << convertToHtml(text);
890 if (closeInline)
891 {
892 m_t << "\\)";
893 }
894 }
895 else
896 {
897 const Formula *formula = FormulaManager::instance().findFormula(f.id());
898
899 enum class ImageType { Light, Dark };
900 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
901 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> QCString {
902 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
903 TextStream t;
904 QCString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
905 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
906 {
907 t << "<picture>";
908 t << "<source srcset=\"" << f.relPath() << f.name();
909 if (visibility==Visibility::AutoDark)
910 {
911 t << extension;
912 t << "\" media=\"(prefers-color-scheme: light)\"";
913 }
914 else // AutoLight
915 {
916 t << "_dark";
917 t << extension;
918 t << "\" media=\"(prefers-color-scheme: dark)\"";
919 }
920 t << "/>";
921 }
922 t << "<img class=\"formula";
923 t << (bDisplay ? "Dsp" : "Inl");
924 if (visibility==Visibility::Light) t << " light-mode-visible";
925 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
926 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
927 if (imgType==ImageType::Dark) t << "_dark";
928 t << extension;
929 if (formula && formula->width()!=-1)
930 {
931 t << "\" width=\"";
932 t << formula->width();
933 }
934 if (formula && formula->height()!=-1)
935 {
936 t << "\" height=\"";
937 t << formula->height();
938 }
939 t << "\"/>";
940 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
941 {
942 t << "</picture>";
943 }
944 return t.str();
945 };
946
947 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
948 switch(colorStyle)
949 {
950 case HTML_COLORSTYLE_t::LIGHT:
951 m_t << writeFormula(ImageType::Light,Visibility::Always);
952 break;
953 case HTML_COLORSTYLE_t::DARK:
954 m_t << writeFormula(ImageType::Dark, Visibility::Always);
955 break;
956 case HTML_COLORSTYLE_t::AUTO_LIGHT:
957 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
958 break;
959 case HTML_COLORSTYLE_t::AUTO_DARK:
960 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
961 break;
962 case HTML_COLORSTYLE_t::TOGGLE:
963 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
964 m_t << writeFormula(ImageType::Light,Visibility::Light);
965 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
966 break;
967 }
968 }
969 if (bDisplay)
970 {
971 m_t << "\n</p>\n";
973 }
974}
975
977{
979 if (e.member())
980 {
981 anchor.prepend(e.member()->anchor()+"_");
982 }
983 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
984 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
985 // qPrint(e.entry()),
986 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
987 // e.member() ? qPrint(e.member()->name()) : "<null>"
988 // );
989 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
990}
991
993{
994 m_t << "</dd>\n";
995 m_t << "<dd>\n";
996}
997
999{
1000 if (m_hide) return;
1001 auto opt = cite.option();
1002 if (!cite.file().isEmpty())
1003 {
1004 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
1005 filter(cite.getText());
1006 if (!opt.noCite()) endLink();
1007 }
1008 else
1009 {
1010 m_t << "<b>";
1011 if (!opt.noPar()) filter("[");
1012 filter(cite.target());
1013 if (!opt.noPar()) filter("]");
1014 m_t << "</b>";
1015 }
1016}
1017
1018
1019//--------------------------------------
1020// visitor functions for compound nodes
1021//--------------------------------------
1022
1023
1025{
1026 //printf("DocAutoList::visitPre\n");
1027 if (m_hide) return;
1029 if (l.isEnumList())
1030 {
1031 //
1032 // Do list type based on depth:
1033 // 1.
1034 // a.
1035 // i.
1036 // A.
1037 // 1. (repeat)...
1038 //
1039 m_t << "<ol type=\"" << g_types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
1040 }
1041 else
1042 {
1043 if (l.isCheckedList())
1044 {
1045 m_t << "<ul class=\"check\">";
1046 }
1047 else
1048 {
1049 m_t << "<ul>";
1050 }
1051 }
1052 if (!l.isPreformatted()) m_t << "\n";
1053 visitChildren(l);
1054 if (l.isEnumList())
1055 {
1056 m_t << "</ol>";
1057 }
1058 else
1059 {
1060 m_t << "</ul>";
1061 }
1062 if (!l.isPreformatted()) m_t << "\n";
1064}
1065
1067{
1068 if (m_hide) return;
1069 switch (li.itemNumber())
1070 {
1071 case DocAutoList::Unchecked: // unchecked
1072 m_t << "<li class=\"unchecked\">";
1073 break;
1074 case DocAutoList::Checked_x: // checked with x
1075 case DocAutoList::Checked_X: // checked with X
1076 m_t << "<li class=\"checked\">";
1077 break;
1078 default:
1079 m_t << "<li>";
1080 break;
1081 }
1082 visitChildren(li);
1083 m_t << "</li>";
1084 if (!li.isPreformatted()) m_t << "\n";
1085}
1086
1087template<class Node>
1088static bool holds_value(const Node *val,const DocNodeVariant &v)
1089{
1090 bool b = std::visit([&](auto &&x) {
1091 //printf("holds_value val=%s (%p) v=%s (%p)\n",
1092 // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
1093 return val==static_cast<const DocNode*>(&x);
1094 }, v);
1095 return b;
1096}
1097
1098template<class T>
1099bool isFirstChildNode(const T *parent, const DocPara &node)
1100{
1101 return !parent->children().empty() && holds_value(&node,parent->children().front());
1102}
1103
1104template<class T>
1105bool isLastChildNode(const T *parent, const DocPara &node)
1106{
1107 return !parent->children().empty() && holds_value(&node,parent->children().back());
1108}
1109
1111{
1112 const DocNodeList &nodes = parent.children();
1113 auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
1114 if (it==std::end(nodes)) return FALSE;
1115 size_t count = parent.children().size();
1116 auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=nullptr; };
1117 if (count>1 && it==std::begin(nodes)) // it points to first node
1118 {
1119 return isSeparator(std::next(it));
1120 }
1121 else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
1122 {
1123 return isSeparator(std::prev(it));
1124 }
1125 else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
1126 {
1127 return isSeparator(std::prev(it)) && isSeparator(std::next(it));
1128 }
1129 return false;
1130}
1131
1132static contexts_t getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
1133{
1135 isFirst=FALSE;
1136 isLast=FALSE;
1137 if (p.parent())
1138 {
1139 const auto parBlock = std::get_if<DocParBlock>(p.parent());
1140 if (parBlock)
1141 {
1142 // hierarchy: node N -> para -> parblock -> para
1143 // adapt return value to kind of N
1144 const DocNodeVariant *p3 = nullptr;
1145 if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
1146 {
1147 p3 = ::parent(::parent(p.parent()));
1148 }
1149 isFirst=isFirstChildNode(parBlock,p);
1150 isLast =isLastChildNode (parBlock,p);
1151 bool isLI = p3!=nullptr && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
1153 bool isTD = p3!=nullptr && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
1155 if (isFirst)
1156 {
1157 if (isLI) t=contexts_t::STARTLI; else if (isDD) t=contexts_t::STARTDD; else if (isTD) t=contexts_t::STARTTD;
1158 }
1159 if (isLast)
1160 {
1161 if (isLI) t=contexts_t::ENDLI; else if (isDD) t=contexts_t::ENDDD; else if (isTD) t=contexts_t::ENDTD;
1162 }
1163 if (!isFirst && !isLast)
1164 {
1165 if (isLI) t=contexts_t::INTERLI; else if (isDD) t=contexts_t::INTERDD; else if (isTD) t=contexts_t::INTERTD;
1166 }
1167 return t;
1168 }
1169 const auto docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
1170 if (docAutoListItem)
1171 {
1172 isFirst=isFirstChildNode(docAutoListItem,p);
1173 isLast =isLastChildNode (docAutoListItem,p);
1174 t=contexts_t::STARTLI; // not used
1175 return t;
1176 }
1177 const auto docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
1178 if (docSimpleListItem)
1179 {
1180 isFirst=TRUE;
1181 isLast =TRUE;
1182 t=contexts_t::STARTLI; // not used
1183 return t;
1184 }
1185 const auto docParamList = std::get_if<DocParamList>(p.parent());
1186 if (docParamList)
1187 {
1188 isFirst=TRUE;
1189 isLast =TRUE;
1190 t=contexts_t::STARTLI; // not used
1191 return t;
1192 }
1193 const auto docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
1194 if (docHtmlListItem)
1195 {
1196 isFirst=isFirstChildNode(docHtmlListItem,p);
1197 isLast =isLastChildNode (docHtmlListItem,p);
1198 if (isFirst) t=contexts_t::STARTLI;
1199 if (isLast) t=contexts_t::ENDLI;
1200 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1201 return t;
1202 }
1203 const auto docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
1204 if (docSecRefItem)
1205 {
1206 isFirst=isFirstChildNode(docSecRefItem,p);
1207 isLast =isLastChildNode (docSecRefItem,p);
1208 if (isFirst) t=contexts_t::STARTLI;
1209 if (isLast) t=contexts_t::ENDLI;
1210 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1211 return t;
1212 }
1213 const auto docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
1214 if (docHtmlDescData)
1215 {
1216 isFirst=isFirstChildNode(docHtmlDescData,p);
1217 isLast =isLastChildNode (docHtmlDescData,p);
1218 if (isFirst) t=contexts_t::STARTDD;
1219 if (isLast) t=contexts_t::ENDDD;
1220 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1221 return t;
1222 }
1223 const auto docXRefItem = std::get_if<DocXRefItem>(p.parent());
1224 if (docXRefItem)
1225 {
1226 isFirst=isFirstChildNode(docXRefItem,p);
1227 isLast =isLastChildNode (docXRefItem,p);
1228 if (isFirst) t=contexts_t::STARTDD;
1229 if (isLast) t=contexts_t::ENDDD;
1230 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1231 return t;
1232 }
1233 const auto docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
1234 if (docSimpleSect)
1235 {
1236 isFirst=isFirstChildNode(docSimpleSect,p);
1237 isLast =isLastChildNode (docSimpleSect,p);
1238 if (isFirst) t=contexts_t::STARTDD;
1239 if (isLast) t=contexts_t::ENDDD;
1240 if (isSeparatedParagraph(*docSimpleSect,p))
1241 // if the paragraph is enclosed with separators it will
1242 // be included in <dd>..</dd> so avoid addition paragraph
1243 // markers
1244 {
1245 isFirst=isLast=TRUE;
1246 }
1247 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1248 return t;
1249 }
1250 const auto docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
1251 if (docHtmlCell)
1252 {
1253 isFirst=isFirstChildNode(docHtmlCell,p);
1254 isLast =isLastChildNode (docHtmlCell,p);
1255 if (isFirst) t=contexts_t::STARTTD;
1256 if (isLast) t=contexts_t::ENDTD;
1257 if (!isFirst && !isLast) t = contexts_t::INTERTD;
1258 return t;
1259 }
1260 }
1261 return t;
1262}
1263
1264static bool determineIfNeedsTag(const DocPara &p)
1265{
1266 bool needsTag = FALSE;
1267 if (p.parent())
1268 {
1282 >(*p.parent()))
1283 {
1284 needsTag = TRUE;
1285 }
1286 else if (std::get_if<DocRoot>(p.parent()))
1287 {
1288 needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
1289 }
1290 }
1291 return needsTag;
1292}
1293
1295{
1296 if (m_hide) return;
1297
1298 //printf("> DocPara\n");
1299 //dumpDocNodeList(p.children());
1300
1301 bool needsTag = determineIfNeedsTag(p);
1302 //printf(" needsTag=%d\n",needsTag);
1303 bool needsTagBefore = needsTag;
1304 bool needsTagAfter = needsTag;
1305
1306 // if the first element of a paragraph is something that should be outside of
1307 // the paragraph (<ul>,<dl>,<table>,..) then that will already started the
1308 // paragraph and we don't need to do it here
1309 if (!p.children().empty())
1310 {
1311 auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
1312 [](const auto &node) { return !isInvisibleNode(node); });
1313 if (it!=std::end(p.children()))
1314 {
1315 const DocNodeVariant &n = *it;
1317 {
1318 needsTagBefore = FALSE;
1319 }
1320 }
1321 }
1322
1323 // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
1324 // this allows us to mark the tag with a special class so we can
1325 // fix the otherwise ugly spacing.
1326 bool isFirst = false;
1327 bool isLast = false;
1328 contexts_t t = getParagraphContext(p,isFirst,isLast);
1329 //printf("startPara first=%d last=%d\n",isFirst,isLast);
1330 if (!std::holds_alternative<DocAutoListItem>(*p.parent()) && isFirst && isLast) needsTagBefore=FALSE;
1331
1332 //printf(" needsTagBefore=%d\n",needsTagBefore);
1333 // write the paragraph tag (if needed)
1334 if (needsTagBefore)
1335 {
1336 if (contexts(t))
1337 m_t << "<p class=\"" << contexts(t) << "\"" << p.attribs().toString() << ">";
1338 else
1339 m_t << "<p" << p.attribs().toString() << ">";
1340 }
1341
1342 visitChildren(p);
1343
1344 // if the last element of a paragraph is something that should be outside of
1345 // the paragraph (<ul>,<dl>,<table>) then that will already have ended the
1346 // paragraph and we don't need to do it here
1347 if (!p.children().empty())
1348 {
1349 auto it = std::prev(std::end(p.children()));
1350 for (;;)
1351 {
1352 const DocNodeVariant &n = *it;
1353 if (!isInvisibleNode(n))
1354 {
1356 {
1357 needsTagAfter = FALSE;
1358 }
1359 // stop searching if we found a node that is visible
1360 break;
1361 }
1362 if (it==std::begin(p.children()))
1363 {
1364 // stop searching if we are at the beginning of the list
1365 break;
1366 }
1367 else
1368 {
1369 --it;
1370 }
1371 }
1372 }
1373
1374 //printf("endPara first=%d last=%d\n",isFirst,isLast);
1375 if (!std::holds_alternative<DocAutoListItem>(*p.parent()) && isFirst && isLast) needsTagAfter=FALSE;
1376
1377 //printf(" needsTagAfter=%d\n",needsTagAfter);
1378 if (needsTagAfter) m_t << "</p>\n";
1379 //printf("< DocPara\n");
1380}
1381
1383{
1384 //printf("> DocRoot\n");
1385 //dumpDocNodeList(r.children());
1386 visitChildren(r);
1387 //printf("< DocRoot\n");
1388}
1389
1391{
1392 if (m_hide) return;
1394 m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
1395 switch(s.type())
1396 {
1397 case DocSimpleSect::See:
1398 m_t << theTranslator->trSeeAlso(); break;
1400 m_t << theTranslator->trReturns(); break;
1402 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
1404 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
1406 m_t << theTranslator->trVersion(); break;
1408 m_t << theTranslator->trSince(); break;
1410 m_t << theTranslator->trDate(); break;
1412 m_t << theTranslator->trNote(); break;
1414 m_t << theTranslator->trWarning(); break;
1415 case DocSimpleSect::Pre:
1416 m_t << theTranslator->trPrecondition(); break;
1418 m_t << theTranslator->trPostcondition(); break;
1420 m_t << theTranslator->trCopyright(); break;
1422 m_t << theTranslator->trInvariant(); break;
1424 m_t << theTranslator->trRemarks(); break;
1426 m_t << theTranslator->trAttention(); break;
1428 m_t << theTranslator->trImportant(); break;
1429 case DocSimpleSect::User: break;
1430 case DocSimpleSect::Rcs: break;
1431 case DocSimpleSect::Unknown: break;
1432 }
1433
1434 if (s.title())
1435 {
1436 std::visit(*this,*s.title());
1437 }
1438 m_t << "</dt><dd>";
1439 visitChildren(s);
1440 m_t << "</dd></dl>\n";
1442}
1443
1445{
1446 if (m_hide) return;
1447 visitChildren(t);
1448}
1449
1451{
1452 if (m_hide) return;
1454 m_t << "<ul>";
1455 if (!sl.isPreformatted()) m_t << "\n";
1456 visitChildren(sl);
1457 m_t << "</ul>";
1458 if (!sl.isPreformatted()) m_t << "\n";
1460}
1461
1463{
1464 if (m_hide) return;
1465 m_t << "<li>";
1466 if (li.paragraph())
1467 {
1468 visit(*this,*li.paragraph());
1469 }
1470 m_t << "</li>";
1471 if (!li.isPreformatted()) m_t << "\n";
1472}
1473
1475{
1476 if (m_hide) return;
1478 m_t << "<h" << s.level() << " class=\"doxsection\">";
1479 m_t << "<a class=\"anchor\" id=\"" << s.anchor();
1480 m_t << "\"></a>\n";
1481 if (s.title())
1482 {
1483 std::visit(*this,*s.title());
1484 }
1485 m_t << "</h" << s.level() << ">\n";
1486 visitChildren(s);
1488}
1489
1491{
1492 if (m_hide) return;
1494 if (s.type()==DocHtmlList::Ordered)
1495 {
1496 m_t << "<ol" << s.attribs().toString();
1497 }
1498 else
1499 {
1500 m_t << "<ul" << s.attribs().toString();
1501 }
1502 m_t << ">\n";
1503 visitChildren(s);
1504 if (s.type()==DocHtmlList::Ordered)
1505 {
1506 m_t << "</ol>";
1507 }
1508 else
1509 {
1510 m_t << "</ul>";
1511 }
1512 if (!s.isPreformatted()) m_t << "\n";
1514}
1515
1517{
1518 if (m_hide) return;
1519 m_t << "<li" << i.attribs().toString() << ">";
1520 if (!i.isPreformatted()) m_t << "\n";
1521 visitChildren(i);
1522 m_t << "</li>\n";
1523}
1524
1526{
1527 if (m_hide) return;
1529 m_t << "<dl" << dl.attribs().toString() << ">\n";
1530 visitChildren(dl);
1531 m_t << "</dl>\n";
1533}
1534
1536{
1537 if (m_hide) return;
1538 m_t << "<dt" << dt.attribs().toString() << ">";
1539 visitChildren(dt);
1540 m_t << "</dt>\n";
1541}
1542
1544{
1545 if (m_hide) return;
1546 m_t << "<dd" << dd.attribs().toString() << ">";
1547 visitChildren(dd);
1548 m_t << "</dd>\n";
1549}
1550
1552{
1553 if (m_hide) return;
1554
1556
1557 if (t.caption())
1558 {
1559 QCString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
1560 if (!anc.isEmpty())
1561 {
1562 m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
1563 }
1564 }
1565
1566 QCString attrs = t.attribs().toString();
1567 if (attrs.isEmpty())
1568 {
1569 m_t << "<table class=\"doxtable\">\n";
1570 }
1571 else
1572 {
1573 m_t << "<table" << t.attribs().toString() << ">\n";
1574 }
1575 if (t.caption())
1576 {
1577 std::visit(*this,*t.caption());
1578 }
1579 visitChildren(t);
1580 m_t << "</table>\n";
1582}
1583
1585{
1586 if (m_hide) return;
1587 m_t << "<tr" << tr.attribs().toString() << ">\n";
1588 visitChildren(tr);
1589 m_t << "</tr>\n";
1590}
1591
1593{
1594 if (m_hide) return;
1595 if (c.isHeading())
1596 {
1597 m_t << "<th" << c.attribs().toString() << ">";
1598 }
1599 else
1600 {
1601 m_t << "<td" << c.attribs().toString() << ">";
1602 }
1603 visitChildren(c);
1604 if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
1605}
1606
1608{
1609 if (m_hide) return;
1610 m_t << "<caption" << c.attribs().toString() << ">";
1611 visitChildren(c);
1612 m_t << "</caption>\n";
1613}
1614
1616{
1617 if (m_hide) return;
1618 visitChildren(i);
1619}
1620
1622{
1623 if (m_hide) return;
1624 if (href.url().startsWith("mailto:"))
1625 {
1627 }
1628 else
1629 {
1630 QCString url = correctURL(href.url(),href.relPath());
1631 m_t << "<a href=\"" << convertToHtml(url) << "\""
1632 << href.attribs().toString() << ">";
1633 }
1634 visitChildren(href);
1635 m_t << "</a>";
1636}
1637
1639{
1640 if (m_hide) return;
1641 m_t << "<summary " << s.attribs().toString() << ">\n";
1642 visitChildren(s);
1643 m_t << "</summary>\n";
1644}
1645
1647{
1648 if (m_hide) return;
1650 m_t << "<details " << d.attribs().toString() << ">\n";
1651 auto summary = d.summary();
1652 if (summary)
1653 {
1654 std::visit(*this,*summary);
1655 }
1656 visitChildren(d);
1657 m_t << "</details>\n";
1659}
1660
1662{
1663 if (m_hide) return;
1664 forceEndParagraph(header);
1665 m_t << "<h" << header.level() << header.attribs().toString() << ">";
1666 visitChildren(header);
1667 m_t << "</h" << header.level() << ">\n";
1668 forceStartParagraph(header);
1669}
1670
1672{
1673 if (img.type()==DocImage::Html)
1674 {
1675 bool inlineImage = img.isInlineImage();
1676 bool typeSVG = img.isSVG();
1677 QCString url = img.url();
1678
1679 if (!inlineImage)
1680 {
1681 forceEndParagraph(img);
1682 }
1683 if (m_hide) return;
1684 QCString baseName=makeShortName(img.name());
1685 if (!inlineImage) m_t << "<div class=\"image\">\n";
1686 QCString sizeAttribs;
1687 if (!img.width().isEmpty())
1688 {
1689 sizeAttribs+=" width=\""+img.width()+"\"";
1690 }
1691 if (!img.height().isEmpty()) // link to local file
1692 {
1693 sizeAttribs+=" height=\""+img.height()+"\"";
1694 }
1695 // 16 cases: url.isEmpty() | typeSVG | inlineImage | img.hasCaption()
1696
1697 HtmlAttribList attribs = img.attribs();
1698 if (typeSVG)
1699 {
1700 attribs.mergeAttribute("style","pointer-events: none;");
1701 }
1702 QCString alt;
1703 QCString attrs = attribs.toString(&alt);
1704 QCString src;
1705 if (url.isEmpty())
1706 {
1707 src = img.relPath()+img.name();
1708 }
1709 else
1710 {
1711 src = correctURL(url,img.relPath());
1712 }
1713 if (typeSVG && !inlineImage && !src.startsWith("http://") && !src.startsWith("https://"))
1714 {
1715 m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src)
1716 << "\"" << sizeAttribs << attrs;
1717 if (inlineImage)
1718 {
1719 // skip closing tag
1720 }
1721 else
1722 {
1723 m_t << ">" << alt << "</object>\n";
1724 }
1725 }
1726 else
1727 {
1728 m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs;
1729 if (inlineImage)
1730 {
1731 m_t << " class=\"inline\"";
1732 }
1733 else
1734 {
1735 m_t << "/>\n";
1736 }
1737 }
1738 if (img.hasCaption())
1739 {
1740 if (inlineImage)
1741 {
1742 m_t << " title=\"";
1743 m_insideTitle=true;
1744 }
1745 else
1746 {
1747 m_t << "<div class=\"caption\">\n";
1748 }
1749 }
1750 else if (inlineImage)
1751 {
1752 m_t << "/>";
1753 }
1754
1755 visitChildren(img);
1756
1757 if (img.hasCaption())
1758 {
1759 if (inlineImage)
1760 {
1761 m_t << "\"/>";
1762 m_insideTitle=false;
1763 }
1764 else // end <div class="caption">
1765 {
1766 m_t << "</div>";
1767 }
1768 }
1769 if (!inlineImage) // end <div class="image">
1770 {
1771 m_t << "</div>\n";
1773 }
1774 }
1775 else // other format -> skip
1776 {
1777 }
1778}
1779
1781{
1782 if (m_hide) return;
1783 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1785 m_t << "<div class=\"dotgraph\">\n";
1786 writeDotFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1787 if (df.hasCaption())
1788 {
1789 m_t << "<div class=\"caption\">\n";
1790 }
1791 visitChildren(df);
1792 if (df.hasCaption())
1793 {
1794 m_t << "</div>\n";
1795 }
1796 m_t << "</div>\n";
1798}
1799
1801{
1802 if (m_hide) return;
1803 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1805 m_t << "<div class=\"mscgraph\">\n";
1806 writeMscFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1807 if (df.hasCaption())
1808 {
1809 m_t << "<div class=\"caption\">\n";
1810 }
1811 visitChildren(df);
1812 if (df.hasCaption())
1813 {
1814 m_t << "</div>\n";
1815 }
1816 m_t << "</div>\n";
1818}
1819
1821{
1822 if (m_hide) return;
1823 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1825 m_t << "<div class=\"diagraph\">\n";
1826 writeDiaFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1827 if (df.hasCaption())
1828 {
1829 m_t << "<div class=\"caption\">\n";
1830 }
1831 visitChildren(df);
1832 if (df.hasCaption())
1833 {
1834 m_t << "</div>\n";
1835 }
1836 m_t << "</div>\n";
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 QCString htmlOutput = Config_getString(HTML_OUTPUT);
1846 QCString 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,QCString(),
1855 inBuf,format,QCString(),df.srcFile(),df.srcLine(),false);
1856 for (const auto &bName: baseNameVector)
1857 {
1858 QCString baseName=makeBaseName(bName);
1859 m_t << "<div class=\"plantumlgraph\">\n";
1860 writePlantUMLFile(baseName,df.relPath(),QCString(),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 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1879 visitChildren(lnk);
1880 endLink();
1881}
1882
1884{
1885 if (m_hide) return;
1886 if (!ref.file().isEmpty())
1887 {
1888 // when ref.isSubPage()==TRUE we use ref.file() for HTML and
1889 // ref.anchor() for LaTeX/RTF
1890 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1891 }
1892 if (!ref.hasLinkText()) filter(ref.targetTitle());
1893 visitChildren(ref);
1894 if (!ref.file().isEmpty()) endLink();
1895 //m_t << " ";
1896}
1897
1899{
1900 if (m_hide) return;
1901 if (!ref.file().isEmpty())
1902 {
1903 m_t << "<li>";
1904 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1905 }
1906 visitChildren(ref);
1907 if (!ref.file().isEmpty())
1908 {
1909 endLink();
1910 m_t << "</li>\n";
1911 }
1912}
1913
1915{
1916 if (m_hide) return;
1918 m_t << "<div>\n";
1919 m_t << "<ul class=\"multicol\">\n";
1920 visitChildren(s);
1921 m_t << "</ul>\n";
1922 m_t << "</div>\n";
1924}
1925
1927{
1928 if (m_hide) return;
1930 QCString className;
1931 QCString heading;
1932 switch(s.type())
1933 {
1935 heading=theTranslator->trParameters();
1936 className="params";
1937 break;
1939 heading=theTranslator->trReturnValues();
1940 className="retval";
1941 break;
1943 heading=theTranslator->trExceptions();
1944 className="exception";
1945 break;
1947 heading=theTranslator->trTemplateParameters();
1948 className="tparams";
1949 break;
1950 default:
1951 ASSERT(0);
1952 }
1953 m_t << "<dl class=\"" << className << "\"><dt>";
1954 m_t << heading;
1955 m_t << "</dt><dd>\n";
1956 m_t << " <table class=\"" << className << "\">\n";
1957 visitChildren(s);
1958 m_t << " </table>\n";
1959 m_t << " </dd>\n";
1960 m_t << "</dl>\n";
1962}
1963
1965{
1966 if (m_hide) return;
1967 m_t << "&#160;" << s.chars() << "&#160;";
1968}
1969
1971{
1972 //printf("DocParamList::visitPre\n");
1973 if (m_hide) return;
1974 m_t << " <tr>";
1975 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
1976 if (sect && sect->hasInOutSpecifier())
1977 {
1978 m_t << "<td class=\"paramdir\">";
1980 {
1981 m_t << "[";
1982 if (pl.direction()==DocParamSect::In)
1983 {
1984 m_t << "in";
1985 }
1986 else if (pl.direction()==DocParamSect::Out)
1987 {
1988 m_t << "out";
1989 }
1990 else if (pl.direction()==DocParamSect::InOut)
1991 {
1992 m_t << "in,out";
1993 }
1994 m_t << "]";
1995 }
1996 m_t << "</td>";
1997 }
1998 if (sect && sect->hasTypeSpecifier())
1999 {
2000 m_t << "<td class=\"paramtype\">";
2001 for (const auto &type : pl.paramTypes())
2002 {
2003 std::visit(*this,type);
2004 }
2005 m_t << "</td>";
2006 }
2007 m_t << "<td class=\"paramname\">";
2008 bool first=TRUE;
2009 for (const auto &param : pl.parameters())
2010 {
2011 if (!first) m_t << ","; else first=FALSE;
2012 std::visit(*this,param);
2013 }
2014 m_t << "</td><td>";
2015 for (const auto &par : pl.paragraphs())
2016 {
2017 std::visit(*this,par);
2018 }
2019 m_t << "</td></tr>\n";
2020}
2021
2023{
2024 if (m_hide) return;
2025 if (x.title().isEmpty()) return;
2026
2028 bool anonymousEnum = x.file()=="@";
2029 if (!anonymousEnum)
2030 {
2031 QCString fn = x.file();
2033 m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
2034 << x.relPath() << fn
2035 << "#" << x.anchor() << "\">";
2036 }
2037 else
2038 {
2039 m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
2040 }
2041 filter(x.title());
2042 if (!anonymousEnum) m_t << "</a>";
2043 m_t << "</b></dt><dd>";
2044 visitChildren(x);
2045 if (x.title().isEmpty()) return;
2046 m_t << "</dd></dl>\n";
2048}
2049
2051{
2052 if (m_hide) return;
2053 startLink(QCString(),ref.file(),ref.relPath(),ref.anchor());
2054 visitChildren(ref);
2055 endLink();
2056 m_t << " ";
2057}
2058
2060{
2061 visitChildren(t);
2062}
2063
2065{
2066 if (m_hide) return;
2068 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2069 visitChildren(b);
2070 m_t << "</blockquote>\n";
2072}
2073
2075{
2076 if (m_hide) return;
2077 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2078 {
2081 m_t << "<p>";
2082 m_t << theTranslator->trFlowchart();
2083 m_t << " ";
2084 m_t << "<a href=\"";
2085 m_t << fname;
2086 m_t << ".svg\">";
2088 m_t << "</a>";
2089 if (vf.hasCaption())
2090 {
2091 m_t << "<br />";
2092 }
2093 }
2094 visitChildren(vf);
2095 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2096 {
2097 m_t << "</p>";
2099 }
2100}
2101
2103{
2104 if (m_hide) return;
2105 visitChildren(pb);
2106}
2107
2108void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
2109{
2110 if (str.isEmpty()) return;
2111 const char *p=str.data();
2112 while (*p)
2113 {
2114 char c=*p++;
2115 switch(c)
2116 {
2117 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2118 case '<': m_t << "&lt;"; break;
2119 case '>': m_t << "&gt;"; break;
2120 case '&': m_t << "&amp;"; break;
2121 case '\\':
2122 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2123 m_t << "\\&zwj;" << *p++;
2124 else
2125 m_t << c;
2126 break;
2127 default:
2128 {
2129 uint8_t uc = static_cast<uint8_t>(c);
2130 if (uc<32 && !isspace(c)) // non-printable control characters
2131 {
2132 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2133 }
2134 else
2135 {
2136 m_t << c;
2137 }
2138 }
2139 break;
2140 }
2141 }
2142}
2143
2144/// Escape basic entities to produce a valid CDATA attribute value,
2145/// assume that the outer quoting will be using the double quote &quot;
2147{
2148 if (str.isEmpty()) return str;
2149 QCString result;
2150 result.reserve(str.length()+8);
2151 const char *p=str.data();
2152 while (*p)
2153 {
2154 char c=*p++;
2155 switch(c)
2156 {
2157 case '&': result+="&amp;"; break;
2158 case '"': result+="&quot;"; break;
2159 case '<': result+="&lt;"; break;
2160 case '>': result+="&gt;"; break;
2161 case '\\':
2162 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2163 {
2164 result+="\\&zwj;";
2165 result+=*p++;
2166 }
2167 else
2168 {
2169 result+=c;
2170 }
2171 break;
2172 default:
2173 {
2174 uint8_t uc = static_cast<uint8_t>(c);
2175 if (uc<32 && !isspace(c)) // non-printable control characters
2176 {
2177 result+="&#x24";
2178 result+=hex[uc>>4];
2179 result+=hex[uc&0xF];
2180 result+=";";
2181 }
2182 else
2183 {
2184 result+=c;
2185 }
2186 }
2187 break;
2188 }
2189 }
2190 return result;
2191}
2192
2193void HtmlDocVisitor::startLink(const QCString &ref,const QCString &file,
2194 const QCString &relPath,const QCString &anchor,
2195 const QCString &tooltip)
2196{
2197 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2198 if (!ref.isEmpty()) // link to entity imported via tag file
2199 {
2200 m_t << "<a class=\"elRef\" ";
2202 }
2203 else // local link
2204 {
2205 m_t << "<a class=\"el\" ";
2206 }
2207 m_t << "href=\"";
2208 QCString fn = file;
2210 m_t << createHtmlUrl(relPath,ref,true,
2211 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2212 fn,
2213 anchor);
2214 m_t << "\"";
2215 if (!tooltip.isEmpty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2216 m_t << ">";
2217}
2218
2220{
2221 m_t << "</a>";
2222}
2223
2224void HtmlDocVisitor::writeDotFile(const QCString &fn,const QCString &relPath,
2225 const QCString &context,const QCString &srcFile,int srcLine)
2226{
2227 QCString baseName=makeBaseName(fn);
2228 baseName.prepend("dot_");
2229 QCString outDir = Config_getString(HTML_OUTPUT);
2230 writeDotGraphFromFile(fn,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2231 writeDotImageMapFromFile(m_t,fn,outDir,relPath,baseName,context,-1,srcFile,srcLine);
2232}
2233
2234void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,
2235 const QCString &context,const QCString &srcFile,int srcLine)
2236{
2237 QCString baseName=makeBaseName(fileName);
2238 baseName.prepend("msc_");
2239 QCString outDir = Config_getString(HTML_OUTPUT);
2240 QCString imgExt = getDotImageExtension();
2242 if ("svg" == imgExt)
2243 mscFormat = MscOutputFormat::SVG;
2244 writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
2245 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2246}
2247
2248void HtmlDocVisitor::writeDiaFile(const QCString &fileName, const QCString &relPath,
2249 const QCString &,const QCString &srcFile,int srcLine)
2250{
2251 QCString baseName=makeBaseName(fileName);
2252 baseName.prepend("dia_");
2253 QCString outDir = Config_getString(HTML_OUTPUT);
2254 writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine);
2255
2256 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2257}
2258
2259void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString &relPath,
2260 const QCString &,const QCString &/* srcFile */,int /* srcLine */)
2261{
2262 QCString baseName=makeBaseName(fileName);
2263 QCString outDir = Config_getString(HTML_OUTPUT);
2264 QCString imgExt = getDotImageExtension();
2265 if (imgExt=="svg")
2266 {
2268 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2269 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2270 //m_t << "</iframe>\n";
2271 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2272 }
2273 else
2274 {
2276 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2277 }
2278}
2279
2280/** Returns TRUE if the child nodes in paragraph \a para until \a nodeIndex
2281 contain a style change node that is still active and that style change is one that
2282 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2283 See also bug746162.
2284 */
2287{
2288 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2289 int styleMask=0;
2290 bool styleOutsideParagraph=FALSE;
2291 while (!styleOutsideParagraph)
2292 {
2293 const DocNodeVariant *n = &(*it);
2294 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2295 if (sc)
2296 {
2297 if (!sc->enable()) // remember styles that has been closed already
2298 {
2299 styleMask|=static_cast<int>(sc->style());
2300 }
2301 bool paraStyle = sc->style()==DocStyleChange::Center ||
2302 sc->style()==DocStyleChange::Div ||
2304 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2305 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2306 paraStyle
2307 )
2308 {
2309 styleOutsideParagraph=TRUE;
2310 }
2311 }
2312 if (it!=std::begin(para->children()))
2313 {
2314 --it;
2315 }
2316 else
2317 {
2318 break;
2319 }
2320 }
2321 return styleOutsideParagraph;
2322}
2323
2324/** Used for items found inside a paragraph, which due to XHTML restrictions
2325 * have to be outside of the paragraph. This method will forcefully end
2326 * the current paragraph and forceStartParagraph() will restart it.
2327 */
2328template<class Node>
2330{
2331 const DocPara *para=std::get_if<DocPara>(n.parent());
2332 if (para)
2333 {
2334 const DocNodeList &children = para->children();
2335
2336 //printf("forceEndParagraph\n");
2337 //dumpDocNodeList(children);
2338
2339 auto it = std::find_if(std::begin(children),std::end(children),
2340 [&n](const auto &np) { return holds_value(&n,np); });
2341 if (it==std::end(children)) return;
2342 if (it==std::begin(children)) return; // first node in paragraph
2343 it = std::prev(it);
2344 bool found=false;
2345 while (!found)
2346 {
2347 found = !isInvisibleNode(*it);
2348 if (found) break;
2349 if (it!=std::begin(children))
2350 {
2351 --it;
2352 }
2353 else
2354 {
2355 break;
2356 }
2357 }
2358 if (!found) return; // first visible node in paragraph
2359 const DocNodeVariant &v = *it;
2360 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2361 bool styleOutsideParagraph=false;
2362 if (it!=std::begin(children))
2363 {
2364 it = std::prev(it);
2365 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2366 }
2367 bool isFirst = false;
2368 bool isLast = false;
2369 getParagraphContext(*para,isFirst,isLast);
2370 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2371 if (!std::holds_alternative<DocAutoListItem>(*para->parent()) && isFirst && isLast) return;
2372 if (styleOutsideParagraph) return;
2373
2374 //printf("adding </p>\n");
2375 m_t << "</p>";
2376 }
2377}
2378
2379/** Used for items found inside a paragraph, which due to XHTML restrictions
2380 * have to be outside of the paragraph. This method will forcefully start
2381 * the paragraph, that was previously ended by forceEndParagraph().
2382 */
2383template<class Node>
2385{
2386 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2387 const DocPara *para=nullptr;
2388 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2389 {
2390 const DocNodeList &children = para->children();
2391
2392 auto it = std::find_if(std::begin(children),
2393 std::end(children),
2394 [&n](const auto &np)
2395 { return holds_value(&n,np); });
2396 if (it==std::end(children)) return;
2397 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2398 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2399 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2400 if (styleOutsideParagraph) return;
2401 it = std::next(it);
2402 while (it!=std::end(children) && isInvisibleNode(*it))
2403 {
2404 ++it;
2405 }
2406 if (it!=std::end(children))
2407 {
2408 const DocNodeVariant &v = *it;
2409 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2410 }
2411 else
2412 {
2413 return; // only whitespace at the end!
2414 }
2415
2416 bool needsTag = true;
2417 bool isFirst = false;
2418 bool isLast = false;
2419 getParagraphContext(*para,isFirst,isLast);
2420 if (!std::holds_alternative<DocAutoListItem>(*para->parent()) && isFirst && isLast) needsTag = false;
2421 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2422
2423 if (needsTag) m_t << "<p>";
2424 }
2425}
2426
void parseCodeFragment(OutputCodeList &codeOutList, const QCString &fileName, const QCString &blockId, const QCString &scopeName, bool showLineNumbers, bool trimLeft, bool stripCodeComments)
static CodeFragmentManager & instance()
virtual void parseCode(OutputCodeList &codeOutList, const QCString &scopeName, const QCString &input, SrcLangExt lang, bool stripCodeComments, bool isExampleBlock, const QCString &exampleName=QCString(), const FileDef *fileDef=nullptr, int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, const MemberDef *memberDef=nullptr, bool showLineNumbers=TRUE, const Definition *searchCtx=nullptr, bool collectXRefs=TRUE)=0
Parses a source file or fragment with the goal to produce highlighted and cross-referenced output.
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual QCString anchor() const =0
virtual QCString getDefFileExtension() const =0
virtual const QCString & name() const =0
Class representing a directory in the file system.
Definition dir.h:75
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:314
Node representing an anchor.
Definition docnode.h:229
const HtmlAttribList & attribs() const
Definition docnode.h:235
QCString anchor() const
Definition docnode.h:232
Node representing an auto List.
Definition docnode.h:571
bool isCheckedList() const
Definition docnode.h:582
bool isEnumList() const
Definition docnode.h:580
int depth() const
Definition docnode.h:583
Node representing an item of a auto list.
Definition docnode.h:595
int itemNumber() const
Definition docnode.h:598
Node representing a citation of some bibliographic reference.
Definition docnode.h:245
QCString getText() const
Definition docnode.cpp:959
QCString relPath() const
Definition docnode.h:249
CiteInfoOption option() const
Definition docnode.h:253
QCString target() const
Definition docnode.h:252
QCString anchor() const
Definition docnode.h:251
QCString ref() const
Definition docnode.h:250
QCString file() const
Definition docnode.h:248
DocNodeList & children()
Definition docnode.h:143
Node representing a dia file.
Definition docnode.h:731
QCString relPath() const
Definition docnode.h:686
QCString srcFile() const
Definition docnode.h:691
QCString file() const
Definition docnode.h:685
int srcLine() const
Definition docnode.h:692
bool hasCaption() const
Definition docnode.h:687
QCString context() const
Definition docnode.h:690
Node representing a dot file.
Definition docnode.h:713
Node representing an emoji.
Definition docnode.h:341
int index() const
Definition docnode.h:345
QCString name() const
Definition docnode.h:344
Node representing an item of a cross-referenced list.
Definition docnode.h:529
QCString text() const
Definition docnode.h:533
QCString name() const
Definition docnode.h:532
bool isInline() const
Definition docnode.h:536
int id() const
Definition docnode.h:535
QCString relPath() const
Definition docnode.h:534
Node representing a Hypertext reference.
Definition docnode.h:823
QCString url() const
Definition docnode.h:830
QCString relPath() const
Definition docnode.h:832
const HtmlAttribList & attribs() const
Definition docnode.h:833
Node representing a horizontal ruler.
Definition docnode.h:216
const HtmlAttribList & attribs() const
Definition docnode.h:221
Node representing an HTML blockquote.
Definition docnode.h:1291
const HtmlAttribList & attribs() const
Definition docnode.h:1296
Node representing a HTML table caption.
Definition docnode.h:1228
const HtmlAttribList & attribs() const
Definition docnode.h:1231
Node representing a HTML table cell.
Definition docnode.h:1193
bool isHeading() const
Definition docnode.h:1200
const HtmlAttribList & attribs() const
Definition docnode.h:1205
Node representing a HTML description data.
Definition docnode.h:1181
const HtmlAttribList & attribs() const
Definition docnode.h:1184
Node representing a Html description list.
Definition docnode.h:901
const HtmlAttribList & attribs() const
Definition docnode.h:905
Node representing a Html description item.
Definition docnode.h:888
const HtmlAttribList & attribs() const
Definition docnode.h:892
Node Html details.
Definition docnode.h:857
const HtmlAttribList & attribs() const
Definition docnode.h:861
const DocNodeVariant * summary() const
Definition docnode.h:864
Node Html heading.
Definition docnode.h:873
const HtmlAttribList & attribs() const
Definition docnode.h:878
int level() const
Definition docnode.h:877
Node representing a Html list.
Definition docnode.h:1000
const HtmlAttribList & attribs() const
Definition docnode.h:1006
Type type() const
Definition docnode.h:1005
Node representing a HTML list item.
Definition docnode.h:1165
const HtmlAttribList & attribs() const
Definition docnode.h:1170
Node representing a HTML table row.
Definition docnode.h:1246
const HtmlAttribList & attribs() const
Definition docnode.h:1252
Node Html summary.
Definition docnode.h:844
const HtmlAttribList & attribs() const
Definition docnode.h:848
Node representing a HTML table.
Definition docnode.h:1269
const DocNodeVariant * caption() const
Definition docnode.cpp:2189
const HtmlAttribList & attribs() const
Definition docnode.h:1275
Node representing an image.
Definition docnode.h:642
const HtmlAttribList & attribs() const
Definition docnode.h:656
QCString relPath() const
Definition docnode.h:652
QCString name() const
Definition docnode.h:648
QCString url() const
Definition docnode.h:653
QCString height() const
Definition docnode.h:651
Type type() const
Definition docnode.h:647
QCString width() const
Definition docnode.h:650
bool isInlineImage() const
Definition docnode.h:654
bool isSVG() const
Definition docnode.cpp:1307
bool hasCaption() const
Definition docnode.h:649
Node representing a include/dontinclude operator block.
Definition docnode.h:477
bool stripCodeComments() const
Definition docnode.h:506
bool isLast() const
Definition docnode.h:503
QCString includeFileName() const
Definition docnode.h:509
QCString text() const
Definition docnode.h:499
QCString context() const
Definition docnode.h:501
QCString exampleFile() const
Definition docnode.h:508
int line() const
Definition docnode.h:497
Type type() const
Definition docnode.h:485
bool isFirst() const
Definition docnode.h:502
bool showLineNo() const
Definition docnode.h:498
bool isExample() const
Definition docnode.h:507
Node representing an included text block from file.
Definition docnode.h:435
QCString blockId() const
Definition docnode.h:454
QCString extension() const
Definition docnode.h:450
bool isBlock() const
Definition docnode.h:458
bool stripCodeComments() const
Definition docnode.h:455
@ LatexInclude
Definition docnode.h:437
@ SnippetWithLines
Definition docnode.h:438
@ DontIncWithLines
Definition docnode.h:439
@ IncWithLines
Definition docnode.h:438
@ HtmlInclude
Definition docnode.h:437
@ VerbInclude
Definition docnode.h:437
@ DontInclude
Definition docnode.h:437
@ DocbookInclude
Definition docnode.h:439
Type type() const
Definition docnode.h:451
QCString exampleFile() const
Definition docnode.h:457
QCString text() const
Definition docnode.h:452
QCString file() const
Definition docnode.h:449
bool trimLeft() const
Definition docnode.h:459
bool isExample() const
Definition docnode.h:456
QCString context() const
Definition docnode.h:453
Node representing an entry in the index.
Definition docnode.h:552
QCString entry() const
Definition docnode.h:559
const Definition * scope() const
Definition docnode.h:557
const MemberDef * member() const
Definition docnode.h:558
Node representing an internal section of documentation.
Definition docnode.h:969
Node representing an internal reference to some item.
Definition docnode.h:807
QCString file() const
Definition docnode.h:811
QCString relPath() const
Definition docnode.h:812
QCString anchor() const
Definition docnode.h:813
Node representing a line break.
Definition docnode.h:202
const HtmlAttribList & attribs() const
Definition docnode.h:208
Node representing a word that can be linked to something.
Definition docnode.h:165
QCString file() const
Definition docnode.h:171
QCString relPath() const
Definition docnode.h:172
QCString ref() const
Definition docnode.h:173
QCString word() const
Definition docnode.h:170
QCString anchor() const
Definition docnode.h:174
QCString tooltip() const
Definition docnode.h:175
Node representing a msc file.
Definition docnode.h:722
Abstract node interface with type information.
Definition docnode.h:82
bool isPreformatted() const
Definition docnode.h:105
DocNodeVariant * parent()
Definition docnode.h:90
Node representing an block of paragraphs.
Definition docnode.h:979
Node representing a paragraph in the documentation tree.
Definition docnode.h:1080
const HtmlAttribList & attribs() const
Definition docnode.h:1114
Node representing a parameter list.
Definition docnode.h:1125
const DocNodeList & parameters() const
Definition docnode.h:1129
const DocNodeList & paramTypes() const
Definition docnode.h:1130
DocParamSect::Direction direction() const
Definition docnode.h:1133
const DocNodeList & paragraphs() const
Definition docnode.h:1131
Node representing a parameter section.
Definition docnode.h:1053
bool hasInOutSpecifier() const
Definition docnode.h:1069
bool hasTypeSpecifier() const
Definition docnode.h:1070
Type type() const
Definition docnode.h:1068
Node representing a uml file.
Definition docnode.h:740
Node representing a reference to some item.
Definition docnode.h:778
QCString anchor() const
Definition docnode.h:785
QCString relPath() const
Definition docnode.h:783
QCString targetTitle() const
Definition docnode.h:786
bool isSubPage() const
Definition docnode.h:792
QCString file() const
Definition docnode.h:782
QCString ref() const
Definition docnode.h:784
bool hasLinkText() const
Definition docnode.h:788
Root node of documentation tree.
Definition docnode.h:1313
Node representing a reference to a section.
Definition docnode.h:935
QCString relPath() const
Definition docnode.h:941
QCString file() const
Definition docnode.h:939
QCString anchor() const
Definition docnode.h:940
QCString ref() const
Definition docnode.h:942
bool isSubPage() const
Definition docnode.h:944
Node representing a list of section references.
Definition docnode.h:959
Node representing a normal section.
Definition docnode.h:914
int level() const
Definition docnode.h:918
QCString anchor() const
Definition docnode.h:920
const DocNodeVariant * title() const
Definition docnode.h:919
Node representing a separator.
Definition docnode.h:365
QCString chars() const
Definition docnode.h:369
Node representing a simple list.
Definition docnode.h:990
Node representing a simple list item.
Definition docnode.h:1153
const DocNodeVariant * paragraph() const
Definition docnode.h:1157
Node representing a simple section.
Definition docnode.h:1017
QCString typeString() const
Definition docnode.cpp:3192
Type type() const
Definition docnode.h:1026
const DocNodeVariant * title() const
Definition docnode.h:1033
Node representing a separator between two simple sections of the same type.
Definition docnode.h:1044
Node representing a style change.
Definition docnode.h:268
const HtmlAttribList & attribs() const
Definition docnode.h:311
QCString tagName() const
Definition docnode.h:312
Style style() const
Definition docnode.h:307
bool enable() const
Definition docnode.h:309
Node representing a special symbol.
Definition docnode.h:328
HtmlEntityMapper::SymType symbol() const
Definition docnode.h:332
Root node of a text fragment.
Definition docnode.h:1304
Node representing a simple section title.
Definition docnode.h:608
Node representing a URL (or email address).
Definition docnode.h:188
QCString url() const
Definition docnode.h:192
bool isEmail() const
Definition docnode.h:193
Node representing a verbatim, unparsed text fragment.
Definition docnode.h:376
QCString srcFile() const
Definition docnode.h:397
int srcLine() const
Definition docnode.h:398
QCString language() const
Definition docnode.h:388
bool isBlock() const
Definition docnode.h:389
bool isExample() const
Definition docnode.h:385
QCString context() const
Definition docnode.h:384
Type type() const
Definition docnode.h:382
QCString text() const
Definition docnode.h:383
QCString exampleFile() const
Definition docnode.h:386
QCString engine() const
Definition docnode.h:393
QCString relPath() const
Definition docnode.h:387
@ JavaDocLiteral
Definition docnode.h:378
Node representing a VHDL flow chart.
Definition docnode.h:749
bool hasCaption() const
Definition docnode.h:753
CodeParserInterface & getCodeParser(const QCString &langExt)
void pushHidden(bool hide)
bool popHidden()
Node representing some amount of white space.
Definition docnode.h:354
QCString chars() const
Definition docnode.h:358
Node representing a word.
Definition docnode.h:153
QCString word() const
Definition docnode.h:156
Node representing an item of a cross-referenced list.
Definition docnode.h:621
QCString anchor() const
Definition docnode.h:625
QCString key() const
Definition docnode.h:628
QCString relPath() const
Definition docnode.h:627
QCString file() const
Definition docnode.h:624
QCString title() const
Definition docnode.h:626
static IndexList * indexList
Definition doxygen.h:133
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
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:165
OutputFormat
Plant UML output image formats.
Definition plantuml.h:44
StringVector writePlantUMLSource(const QCString &outDirArg, const QCString &fileName, const QCString &content, OutputFormat format, const QCString &engine, const QCString &srcFile, int srcLine, bool inlineCode)
Write a PlantUML compatible file.
Definition plantuml.cpp:31
static PlantumlManager & instance()
Definition plantuml.cpp:231
void generatePlantUMLOutput(const QCString &baseName, const QCString &outDir, OutputFormat format)
Convert a PlantUML file to an image.
Definition plantuml.cpp:202
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:422
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
bool startsWith(const char *s) const
Definition qcstring.h:507
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
const std::string & str() const
Definition qcstring.h:552
QCString & setNum(short n)
Definition qcstring.h:459
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
@ ExplicitSize
Definition qcstring.h:146
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:96
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
QCString left(size_t len) const
Definition qcstring.h:229
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:216
static const MemberDef * getFlowMember()
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
#define Config_getEnum(name)
Definition config.h:35
void writeDiaGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, DiaOutputFormat format, const QCString &srcFile, int srcLine)
Definition dia.cpp:26
static constexpr auto hex
static QCString makeBaseName(const QCString &name)
static QCString makeShortName(const QCString &baseName)
std::variant< DocWord, DocLinkedWord, DocURL, DocLineBreak, DocHorRuler, DocAnchor, DocCite, DocStyleChange, DocSymbol, DocEmoji, DocWhiteSpace, DocSeparator, DocVerbatim, DocInclude, DocIncOperator, DocFormula, DocIndexEntry, DocAutoList, DocAutoListItem, DocTitle, DocXRefItem, DocImage, DocDotFile, DocMscFile, DocDiaFile, DocVhdlFlow, DocLink, DocRef, DocInternalRef, DocHRef, DocHtmlHeader, DocHtmlDescTitle, DocHtmlDescList, DocSection, DocSecRefItem, DocSecRefList, DocInternal, DocParBlock, DocSimpleList, DocHtmlList, DocSimpleSect, DocSimpleSectSep, DocParamSect, DocPara, DocParamList, DocSimpleListItem, DocHtmlListItem, DocHtmlDescData, DocHtmlCell, DocHtmlCaption, DocHtmlRow, DocHtmlTable, DocHtmlBlockQuote, DocText, DocRoot, DocHtmlDetails, DocHtmlSummary, DocPlantUmlFile > DocNodeVariant
Definition docnode.h:67
constexpr bool holds_one_of_alternatives(const DocNodeVariant &v)
returns true iff v holds one of types passed as template parameters
Definition docnode.h:1366
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1330
void writeDotImageMapFromFile(TextStream &t, const QCString &inFile, const QCString &outDir, const QCString &relPath, const QCString &baseName, const QCString &context, int graphId, const QCString &srcFile, int srcLine)
Definition dot.cpp:283
void writeDotGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, GraphOutputFormat format, const QCString &srcFile, int srcLine)
Definition dot.cpp:230
std::unique_ptr< FileDef > createFileDef(const QCString &p, const QCString &n, const QCString &ref, const QCString &dn)
Definition filedef.cpp:268
static bool isInvisibleNode(const DocNodeVariant &node)
static bool determineIfNeedsTag(const DocPara &p)
static const char g_types[][NUM_HTML_LIST_TYPES]
static constexpr const char * contexts(contexts_t type)
contexts_t
bool isFirstChildNode(const T *parent, const DocPara &node)
static const int NUM_HTML_LIST_TYPES
static QCString convertIndexWordToAnchor(const QCString &word)
static contexts_t getParagraphContext(const DocPara &p, bool &isFirst, bool &isLast)
static QCString makeBaseName(const QCString &name)
static bool mustBeOutsideParagraph(const DocNodeVariant &n)
static bool isDocVerbatimVisible(const DocVerbatim &s)
static bool insideStyleChangeThatIsOutsideParagraph(const DocPara *para, DocNodeList::const_iterator it)
Returns TRUE if the child nodes in paragraph para until nodeIndex contain a style change node that is...
static bool holds_value(const Node *val, const DocNodeVariant &v)
static bool isDocIncOperatorVisible(const DocIncOperator &s)
bool isSeparatedParagraph(const DocSimpleSect &parent, const DocPara &par)
bool isLastChildNode(const T *parent, const DocPara &node)
static QCString makeShortName(const QCString &name)
static bool isDocIncludeVisible(const DocInclude &s)
Translator * theTranslator
Definition language.cpp:71
#define err(fmt,...)
Definition message.h:127
void writeMscImageMapFromFile(TextStream &t, const QCString &inFile, const QCString &outDir, const QCString &relPath, const QCString &baseName, const QCString &context, MscOutputFormat format, const QCString &srcFile, int srcLine)
Definition msc.cpp:233
void writeMscGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, MscOutputFormat format, const QCString &srcFile, int srcLine)
Definition msc.cpp:157
MscOutputFormat
Definition msc.h:22
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:649
Portable versions of functions that are platform dependent.
const char * qPrint(const char *s)
Definition qcstring.h:687
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
SrcLangExt
Definition types.h:207
const char * writeUTF8Char(TextStream &t, const char *s)
Writes the UTF8 character pointed to by s to stream t and returns a pointer to the next character.
Definition utf8.cpp:197
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5147
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:3905
QCString correctURL(const QCString &url, const QCString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:5877
QCString stripPath(const QCString &s)
Definition util.cpp:4890
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:5486
SrcLangExt getLanguageFromCodeLang(QCString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:5165
QCString getDotImageExtension()
Definition util.cpp:6239
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:5809
QCString externalLinkTarget(const bool parent)
Definition util.cpp:5661
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5189
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:4863
QCString createHtmlUrl(const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
Definition util.cpp:5672
A bunch of utility functions.