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),
573 .setExample(s.isExample(), s.exampleFile())
574 .setInlineFragment(true)
576 );
577 m_ci.endCodeFragment("DoxyCode");
579 break;
582 m_t << "<pre class=\"fragment\">";
583 filter(s.text());
584 m_t << "</pre>";
586 break;
588 filter(s.text(), true);
589 break;
591 m_t << "<code class=\"JavaDocCode\">";
592 filter(s.text(), true);
593 m_t << "</code>";
594 break;
596 {
597 if (s.isBlock()) forceEndParagraph(s);
598 m_t << s.text();
599 if (s.isBlock()) forceStartParagraph(s);
600 }
601 break;
607 /* nothing */
608 break;
609
610 case DocVerbatim::Dot:
611 {
612 static int dotindex = 1;
613 QCString fileName(4096, QCString::ExplicitSize);
614
616 fileName.sprintf("%s%d%s",
617 qPrint(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_"),
618 dotindex++,
619 ".dot"
620 );
621 std::ofstream file = Portable::openOutputStream(fileName);
622 if (!file.is_open())
623 {
624 err("Could not open file {} for writing\n",fileName);
625 }
626 else
627 {
628 QCString stext = s.text();
629 file.write( stext.data(), stext.length() );
630 file.close();
631
632 m_t << "<div class=\"dotgraph\">\n";
633 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
634 visitCaption(m_t, s);
635 m_t << "</div>\n";
636
637 if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
638 }
640 }
641 break;
642 case DocVerbatim::Msc:
643 {
645
646 static int mscindex = 1;
647 QCString baseName(4096, QCString::ExplicitSize);
648
649 baseName.sprintf("%s%d",
650 qPrint(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_"),
651 mscindex++
652 );
653 std::ofstream file = Portable::openOutputStream(baseName.str()+".msc");
654 if (!file.is_open())
655 {
656 err("Could not open file {}.msc for writing\n",baseName);
657 }
658 else
659 {
660 QCString text = "msc {";
661 text+=s.text();
662 text+="}";
663
664 file.write( text.data(), text.length() );
665 file.close();
666
667 m_t << "<div class=\"mscgraph\">\n";
668 writeMscFile(baseName+".msc",s.relPath(),s.context(),s.srcFile(),s.srcLine());
669 visitCaption(m_t, s);
670 m_t << "</div>\n";
671
672 if (Config_getBool(DOT_CLEANUP)) Dir().remove(baseName.str()+".msc");
673 }
675 }
676 break;
678 {
680 QCString htmlOutput = Config_getString(HTML_OUTPUT);
682 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
683 if (imgExt=="svg")
684 {
686 }
687 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
688 htmlOutput,s.exampleFile(),
689 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
690 for (const auto &baseName: baseNameVector)
691 {
692 m_t << "<div class=\"plantumlgraph\">\n";
693 writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
694 visitCaption(m_t, s);
695 m_t << "</div>\n";
696 }
698 }
699 break;
700 }
701}
702
704{
705 if (m_hide) return;
706 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
707}
708
710{
711 if (m_hide) return;
713 switch(inc.type())
714 {
717 m_ci.startCodeFragment("DoxyCode");
719 inc.context(),
720 inc.text(),
721 langExt,
722 inc.stripCodeComments(),
724 .setExample(inc.isExample(), inc.exampleFile())
725 .setInlineFragment(true)
726 .setShowLineNumbers(false)
728 );
729 m_ci.endCodeFragment("DoxyCode");
731 break;
733 {
735 m_ci.startCodeFragment("DoxyCode");
736 FileInfo cfi( inc.file().str() );
737 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
739 inc.context(),
740 inc.text(),
741 langExt,
742 inc.stripCodeComments(),
744 .setExample(inc.isExample(), inc.exampleFile())
745 .setFileDef(fd.get())
746 .setInlineFragment(true)
748 );
749 m_ci.endCodeFragment("DoxyCode");
751 }
752 break;
760 break;
762 {
763 if (inc.isBlock()) forceEndParagraph(inc);
764 m_t << inc.text();
765 if (inc.isBlock()) forceStartParagraph(inc);
766 }
767 break;
770 m_t << "<pre class=\"fragment\">";
771 filter(inc.text());
772 m_t << "</pre>";
774 break;
778 m_ci.startCodeFragment("DoxyCode");
780 inc.file(),
781 inc.blockId(),
782 inc.context(),
784 inc.trimLeft(),
786 );
787 m_ci.endCodeFragment("DoxyCode");
789 break;
790 }
791}
792
794{
795 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
796 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
797 if (op.isFirst())
798 {
800 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
802 m_hide=TRUE;
803 }
805 if (locLangExt.isEmpty()) locLangExt = m_langExt;
806 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
807 if (op.type()!=DocIncOperator::Skip)
808 {
809 m_hide = popHidden();
810 if (!m_hide)
811 {
812 std::unique_ptr<FileDef> fd;
813 if (!op.includeFileName().isEmpty())
814 {
815 FileInfo cfi( op.includeFileName().str() );
816 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
817 }
818 getCodeParser(locLangExt).parseCode(
819 m_ci,
820 op.context(),
821 op.text(),
822 langExt,
825 .setExample(op.isExample(), op.exampleFile())
826 .setFileDef(fd.get())
827 .setStartLine(op.line())
830 );
831 }
833 m_hide=TRUE;
834 }
835 if (op.isLast())
836 {
837 m_hide = popHidden();
838 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
840 }
841 else
842 {
843 if (!m_hide) m_t << "\n";
844 }
845}
846
848{
849 if (m_hide) return;
850 bool bDisplay = !f.isInline();
851 if (bDisplay)
852 {
854 m_t << "<p class=\"formulaDsp\">\n";
855 }
856
857 if (Config_getBool(USE_MATHJAX))
858 {
859 QCString text = f.text();
860 bool closeInline = FALSE;
861 if (!bDisplay && !text.isEmpty() && text.at(0)=='$' &&
862 text.at(text.length()-1)=='$')
863 {
864 closeInline=TRUE;
865 text = text.mid(1,text.length()-2);
866 m_t << "\\(";
867 }
868 else if (!bDisplay && !text.isEmpty())
869 {
870 closeInline=TRUE;
871 m_t << "\\(";
872 }
873 m_t << convertToHtml(text);
874 if (closeInline)
875 {
876 m_t << "\\)";
877 }
878 }
879 else
880 {
881 const Formula *formula = FormulaManager::instance().findFormula(f.id());
882
883 enum class ImageType { Light, Dark };
884 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
885 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> QCString {
886 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
887 TextStream t;
888 QCString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
889 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
890 {
891 t << "<picture>";
892 t << "<source srcset=\"" << f.relPath() << f.name();
893 if (visibility==Visibility::AutoDark)
894 {
895 t << extension;
896 t << "\" media=\"(prefers-color-scheme: light)\"";
897 }
898 else // AutoLight
899 {
900 t << "_dark";
901 t << extension;
902 t << "\" media=\"(prefers-color-scheme: dark)\"";
903 }
904 t << "/>";
905 }
906 t << "<img class=\"formula";
907 t << (bDisplay ? "Dsp" : "Inl");
908 if (visibility==Visibility::Light) t << " light-mode-visible";
909 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
910 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
911 if (imgType==ImageType::Dark) t << "_dark";
912 t << extension;
913 if (formula && formula->width()!=-1)
914 {
915 t << "\" width=\"";
916 t << formula->width();
917 }
918 if (formula && formula->height()!=-1)
919 {
920 t << "\" height=\"";
921 t << formula->height();
922 }
923 t << "\"/>";
924 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
925 {
926 t << "</picture>";
927 }
928 return t.str();
929 };
930
931 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
932 switch(colorStyle)
933 {
934 case HTML_COLORSTYLE_t::LIGHT:
935 m_t << writeFormula(ImageType::Light,Visibility::Always);
936 break;
937 case HTML_COLORSTYLE_t::DARK:
938 m_t << writeFormula(ImageType::Dark, Visibility::Always);
939 break;
940 case HTML_COLORSTYLE_t::AUTO_LIGHT:
941 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
942 break;
943 case HTML_COLORSTYLE_t::AUTO_DARK:
944 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
945 break;
946 case HTML_COLORSTYLE_t::TOGGLE:
947 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
948 m_t << writeFormula(ImageType::Light,Visibility::Light);
949 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
950 break;
951 }
952 }
953 if (bDisplay)
954 {
955 m_t << "\n</p>\n";
957 }
958}
959
961{
963 if (e.member())
964 {
965 anchor.prepend(e.member()->anchor()+"_");
966 }
967 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
968 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
969 // qPrint(e.entry()),
970 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
971 // e.member() ? qPrint(e.member()->name()) : "<null>"
972 // );
973 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
974}
975
977{
978 m_t << "</dd>\n";
979 m_t << "<dd>\n";
980}
981
983{
984 if (m_hide) return;
985 auto opt = cite.option();
986 if (!cite.file().isEmpty())
987 {
988 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
989 filter(cite.getText());
990 if (!opt.noCite()) endLink();
991 }
992 else
993 {
994 m_t << "<b>";
995 if (!opt.noPar()) filter("[");
996 filter(cite.target());
997 if (!opt.noPar()) filter("]");
998 m_t << "</b>";
999 }
1000}
1001
1002
1003//--------------------------------------
1004// visitor functions for compound nodes
1005//--------------------------------------
1006
1007
1009{
1010 //printf("DocAutoList::visitPre\n");
1011 if (m_hide) return;
1013 if (l.isEnumList())
1014 {
1015 //
1016 // Do list type based on depth:
1017 // 1.
1018 // a.
1019 // i.
1020 // A.
1021 // 1. (repeat)...
1022 //
1023 m_t << "<ol type=\"" << g_types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
1024 }
1025 else
1026 {
1027 if (l.isCheckedList())
1028 {
1029 m_t << "<ul class=\"check\">";
1030 }
1031 else
1032 {
1033 m_t << "<ul>";
1034 }
1035 }
1036 if (!l.isPreformatted()) m_t << "\n";
1037 visitChildren(l);
1038 if (l.isEnumList())
1039 {
1040 m_t << "</ol>";
1041 }
1042 else
1043 {
1044 m_t << "</ul>";
1045 }
1046 if (!l.isPreformatted()) m_t << "\n";
1048}
1049
1051{
1052 if (m_hide) return;
1053 switch (li.itemNumber())
1054 {
1055 case DocAutoList::Unchecked: // unchecked
1056 m_t << "<li class=\"unchecked\">";
1057 break;
1058 case DocAutoList::Checked_x: // checked with x
1059 case DocAutoList::Checked_X: // checked with X
1060 m_t << "<li class=\"checked\">";
1061 break;
1062 default:
1063 m_t << "<li>";
1064 break;
1065 }
1066 visitChildren(li);
1067 m_t << "</li>";
1068 if (!li.isPreformatted()) m_t << "\n";
1069}
1070
1071template<class Node>
1072static bool holds_value(const Node *val,const DocNodeVariant &v)
1073{
1074 bool b = std::visit([&](auto &&x) {
1075 //printf("holds_value val=%s (%p) v=%s (%p)\n",
1076 // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
1077 return val==static_cast<const DocNode*>(&x);
1078 }, v);
1079 return b;
1080}
1081
1082template<class T>
1083bool isFirstChildNode(const T *parent, const DocPara &node)
1084{
1085 return !parent->children().empty() && holds_value(&node,parent->children().front());
1086}
1087
1088template<class T>
1089bool isLastChildNode(const T *parent, const DocPara &node)
1090{
1091 return !parent->children().empty() && holds_value(&node,parent->children().back());
1092}
1093
1095{
1096 const DocNodeList &nodes = parent.children();
1097 auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
1098 if (it==std::end(nodes)) return FALSE;
1099 size_t count = parent.children().size();
1100 auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=nullptr; };
1101 if (count>1 && it==std::begin(nodes)) // it points to first node
1102 {
1103 return isSeparator(std::next(it));
1104 }
1105 else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
1106 {
1107 return isSeparator(std::prev(it));
1108 }
1109 else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
1110 {
1111 return isSeparator(std::prev(it)) && isSeparator(std::next(it));
1112 }
1113 return false;
1114}
1115
1116static contexts_t getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
1117{
1119 isFirst=FALSE;
1120 isLast=FALSE;
1121 if (p.parent())
1122 {
1123 const auto parBlock = std::get_if<DocParBlock>(p.parent());
1124 if (parBlock)
1125 {
1126 // hierarchy: node N -> para -> parblock -> para
1127 // adapt return value to kind of N
1128 const DocNodeVariant *p3 = nullptr;
1129 if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
1130 {
1131 p3 = ::parent(::parent(p.parent()));
1132 }
1133 isFirst=isFirstChildNode(parBlock,p);
1134 isLast =isLastChildNode (parBlock,p);
1135 bool isLI = p3!=nullptr && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
1137 bool isTD = p3!=nullptr && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
1139 if (isFirst)
1140 {
1141 if (isLI) t=contexts_t::STARTLI; else if (isDD) t=contexts_t::STARTDD; else if (isTD) t=contexts_t::STARTTD;
1142 }
1143 if (isLast)
1144 {
1145 if (isLI) t=contexts_t::ENDLI; else if (isDD) t=contexts_t::ENDDD; else if (isTD) t=contexts_t::ENDTD;
1146 }
1147 if (!isFirst && !isLast)
1148 {
1149 if (isLI) t=contexts_t::INTERLI; else if (isDD) t=contexts_t::INTERDD; else if (isTD) t=contexts_t::INTERTD;
1150 }
1151 return t;
1152 }
1153 const auto docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
1154 if (docAutoListItem)
1155 {
1156 isFirst=isFirstChildNode(docAutoListItem,p);
1157 isLast =isLastChildNode (docAutoListItem,p);
1158 t=contexts_t::STARTLI; // not used
1159 return t;
1160 }
1161 const auto docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
1162 if (docSimpleListItem)
1163 {
1164 isFirst=TRUE;
1165 isLast =TRUE;
1166 t=contexts_t::STARTLI; // not used
1167 return t;
1168 }
1169 const auto docParamList = std::get_if<DocParamList>(p.parent());
1170 if (docParamList)
1171 {
1172 isFirst=TRUE;
1173 isLast =TRUE;
1174 t=contexts_t::STARTLI; // not used
1175 return t;
1176 }
1177 const auto docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
1178 if (docHtmlListItem)
1179 {
1180 isFirst=isFirstChildNode(docHtmlListItem,p);
1181 isLast =isLastChildNode (docHtmlListItem,p);
1182 if (isFirst) t=contexts_t::STARTLI;
1183 if (isLast) t=contexts_t::ENDLI;
1184 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1185 return t;
1186 }
1187 const auto docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
1188 if (docSecRefItem)
1189 {
1190 isFirst=isFirstChildNode(docSecRefItem,p);
1191 isLast =isLastChildNode (docSecRefItem,p);
1192 if (isFirst) t=contexts_t::STARTLI;
1193 if (isLast) t=contexts_t::ENDLI;
1194 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1195 return t;
1196 }
1197 const auto docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
1198 if (docHtmlDescData)
1199 {
1200 isFirst=isFirstChildNode(docHtmlDescData,p);
1201 isLast =isLastChildNode (docHtmlDescData,p);
1202 if (isFirst) t=contexts_t::STARTDD;
1203 if (isLast) t=contexts_t::ENDDD;
1204 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1205 return t;
1206 }
1207 const auto docXRefItem = std::get_if<DocXRefItem>(p.parent());
1208 if (docXRefItem)
1209 {
1210 isFirst=isFirstChildNode(docXRefItem,p);
1211 isLast =isLastChildNode (docXRefItem,p);
1212 if (isFirst) t=contexts_t::STARTDD;
1213 if (isLast) t=contexts_t::ENDDD;
1214 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1215 return t;
1216 }
1217 const auto docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
1218 if (docSimpleSect)
1219 {
1220 isFirst=isFirstChildNode(docSimpleSect,p);
1221 isLast =isLastChildNode (docSimpleSect,p);
1222 if (isFirst) t=contexts_t::STARTDD;
1223 if (isLast) t=contexts_t::ENDDD;
1224 if (isSeparatedParagraph(*docSimpleSect,p))
1225 // if the paragraph is enclosed with separators it will
1226 // be included in <dd>..</dd> so avoid addition paragraph
1227 // markers
1228 {
1229 isFirst=isLast=TRUE;
1230 }
1231 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1232 return t;
1233 }
1234 const auto docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
1235 if (docHtmlCell)
1236 {
1237 isFirst=isFirstChildNode(docHtmlCell,p);
1238 isLast =isLastChildNode (docHtmlCell,p);
1239 if (isFirst) t=contexts_t::STARTTD;
1240 if (isLast) t=contexts_t::ENDTD;
1241 if (!isFirst && !isLast) t = contexts_t::INTERTD;
1242 return t;
1243 }
1244 }
1245 return t;
1246}
1247
1248static bool determineIfNeedsTag(const DocPara &p)
1249{
1250 bool needsTag = FALSE;
1251 if (p.parent())
1252 {
1266 >(*p.parent()))
1267 {
1268 needsTag = TRUE;
1269 }
1270 else if (std::get_if<DocRoot>(p.parent()))
1271 {
1272 needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
1273 }
1274 }
1275 return needsTag;
1276}
1277
1279{
1280 if (m_hide) return;
1281
1282 //printf("> DocPara\n");
1283 //dumpDocNodeList(p.children());
1284
1285 bool needsTag = determineIfNeedsTag(p);
1286 //printf(" needsTag=%d\n",needsTag);
1287 bool needsTagBefore = needsTag;
1288 bool needsTagAfter = needsTag;
1289
1290 // if the first element of a paragraph is something that should be outside of
1291 // the paragraph (<ul>,<dl>,<table>,..) then that will already started the
1292 // paragraph and we don't need to do it here
1293 if (!p.children().empty())
1294 {
1295 auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
1296 [](const auto &node) { return !isInvisibleNode(node); });
1297 if (it!=std::end(p.children()))
1298 {
1299 const DocNodeVariant &n = *it;
1301 {
1302 needsTagBefore = FALSE;
1303 }
1304 }
1305 }
1306
1307 // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
1308 // this allows us to mark the tag with a special class so we can
1309 // fix the otherwise ugly spacing.
1310 bool isFirst = false;
1311 bool isLast = false;
1312 contexts_t t = getParagraphContext(p,isFirst,isLast);
1313 //printf("startPara first=%d last=%d\n",isFirst,isLast);
1314 if (!std::holds_alternative<DocAutoListItem>(*p.parent()) && isFirst && isLast) needsTagBefore=FALSE;
1315
1316 //printf(" needsTagBefore=%d\n",needsTagBefore);
1317 // write the paragraph tag (if needed)
1318 if (needsTagBefore)
1319 {
1320 if (contexts(t))
1321 m_t << "<p class=\"" << contexts(t) << "\"" << p.attribs().toString() << ">";
1322 else
1323 m_t << "<p" << p.attribs().toString() << ">";
1324 }
1325
1326 visitChildren(p);
1327
1328 // if the last element of a paragraph is something that should be outside of
1329 // the paragraph (<ul>,<dl>,<table>) then that will already have ended the
1330 // paragraph and we don't need to do it here
1331 if (!p.children().empty())
1332 {
1333 auto it = std::prev(std::end(p.children()));
1334 for (;;)
1335 {
1336 const DocNodeVariant &n = *it;
1337 if (!isInvisibleNode(n))
1338 {
1340 {
1341 needsTagAfter = FALSE;
1342 }
1343 // stop searching if we found a node that is visible
1344 break;
1345 }
1346 if (it==std::begin(p.children()))
1347 {
1348 // stop searching if we are at the beginning of the list
1349 break;
1350 }
1351 else
1352 {
1353 --it;
1354 }
1355 }
1356 }
1357
1358 //printf("endPara first=%d last=%d\n",isFirst,isLast);
1359 if (!std::holds_alternative<DocAutoListItem>(*p.parent()) && isFirst && isLast) needsTagAfter=FALSE;
1360
1361 //printf(" needsTagAfter=%d\n",needsTagAfter);
1362 if (needsTagAfter) m_t << "</p>\n";
1363 //printf("< DocPara\n");
1364}
1365
1367{
1368 //printf("> DocRoot\n");
1369 //dumpDocNodeList(r.children());
1370 visitChildren(r);
1371 //printf("< DocRoot\n");
1372}
1373
1375{
1376 if (m_hide) return;
1378 m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
1379 switch(s.type())
1380 {
1381 case DocSimpleSect::See:
1382 m_t << theTranslator->trSeeAlso(); break;
1384 m_t << theTranslator->trReturns(); break;
1386 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
1388 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
1390 m_t << theTranslator->trVersion(); break;
1392 m_t << theTranslator->trSince(); break;
1394 m_t << theTranslator->trDate(); break;
1396 m_t << theTranslator->trNote(); break;
1398 m_t << theTranslator->trWarning(); break;
1399 case DocSimpleSect::Pre:
1400 m_t << theTranslator->trPrecondition(); break;
1402 m_t << theTranslator->trPostcondition(); break;
1404 m_t << theTranslator->trCopyright(); break;
1406 m_t << theTranslator->trInvariant(); break;
1408 m_t << theTranslator->trRemarks(); break;
1410 m_t << theTranslator->trAttention(); break;
1412 m_t << theTranslator->trImportant(); break;
1413 case DocSimpleSect::User: break;
1414 case DocSimpleSect::Rcs: break;
1415 case DocSimpleSect::Unknown: break;
1416 }
1417
1418 if (s.title())
1419 {
1420 std::visit(*this,*s.title());
1421 }
1422 m_t << "</dt><dd>";
1423 visitChildren(s);
1424 m_t << "</dd></dl>\n";
1426}
1427
1429{
1430 if (m_hide) return;
1431 visitChildren(t);
1432}
1433
1435{
1436 if (m_hide) return;
1438 m_t << "<ul>";
1439 if (!sl.isPreformatted()) m_t << "\n";
1440 visitChildren(sl);
1441 m_t << "</ul>";
1442 if (!sl.isPreformatted()) m_t << "\n";
1444}
1445
1447{
1448 if (m_hide) return;
1449 m_t << "<li>";
1450 if (li.paragraph())
1451 {
1452 visit(*this,*li.paragraph());
1453 }
1454 m_t << "</li>";
1455 if (!li.isPreformatted()) m_t << "\n";
1456}
1457
1459{
1460 if (m_hide) return;
1462 m_t << "<h" << s.level() << " class=\"doxsection\">";
1463 m_t << "<a class=\"anchor\" id=\"" << s.anchor();
1464 m_t << "\"></a>\n";
1465 if (s.title())
1466 {
1467 std::visit(*this,*s.title());
1468 }
1469 m_t << "</h" << s.level() << ">\n";
1470 visitChildren(s);
1472}
1473
1475{
1476 if (m_hide) return;
1478 if (s.type()==DocHtmlList::Ordered)
1479 {
1480 m_t << "<ol" << s.attribs().toString();
1481 }
1482 else
1483 {
1484 m_t << "<ul" << s.attribs().toString();
1485 }
1486 m_t << ">\n";
1487 visitChildren(s);
1488 if (s.type()==DocHtmlList::Ordered)
1489 {
1490 m_t << "</ol>";
1491 }
1492 else
1493 {
1494 m_t << "</ul>";
1495 }
1496 if (!s.isPreformatted()) m_t << "\n";
1498}
1499
1501{
1502 if (m_hide) return;
1503 m_t << "<li" << i.attribs().toString() << ">";
1504 if (!i.isPreformatted()) m_t << "\n";
1505 visitChildren(i);
1506 m_t << "</li>\n";
1507}
1508
1510{
1511 if (m_hide) return;
1513 m_t << "<dl" << dl.attribs().toString() << ">\n";
1514 visitChildren(dl);
1515 m_t << "</dl>\n";
1517}
1518
1520{
1521 if (m_hide) return;
1522 m_t << "<dt" << dt.attribs().toString() << ">";
1523 visitChildren(dt);
1524 m_t << "</dt>\n";
1525}
1526
1528{
1529 if (m_hide) return;
1530 m_t << "<dd" << dd.attribs().toString() << ">";
1531 visitChildren(dd);
1532 m_t << "</dd>\n";
1533}
1534
1536{
1537 if (m_hide) return;
1538
1540
1541 if (t.caption())
1542 {
1543 QCString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
1544 if (!anc.isEmpty())
1545 {
1546 m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
1547 }
1548 }
1549
1550 QCString attrs = t.attribs().toString();
1551 if (attrs.isEmpty())
1552 {
1553 m_t << "<table class=\"doxtable\">\n";
1554 }
1555 else
1556 {
1557 m_t << "<table" << t.attribs().toString() << ">\n";
1558 }
1559 if (t.caption())
1560 {
1561 std::visit(*this,*t.caption());
1562 }
1563 visitChildren(t);
1564 m_t << "</table>\n";
1566}
1567
1569{
1570 if (m_hide) return;
1571 m_t << "<tr" << tr.attribs().toString() << ">\n";
1572 visitChildren(tr);
1573 m_t << "</tr>\n";
1574}
1575
1577{
1578 if (m_hide) return;
1579 if (c.isHeading())
1580 {
1581 m_t << "<th" << c.attribs().toString() << ">";
1582 }
1583 else
1584 {
1585 m_t << "<td" << c.attribs().toString() << ">";
1586 }
1587 visitChildren(c);
1588 if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
1589}
1590
1592{
1593 if (m_hide) return;
1594 m_t << "<caption" << c.attribs().toString() << ">";
1595 visitChildren(c);
1596 m_t << "</caption>\n";
1597}
1598
1600{
1601 if (m_hide) return;
1602 visitChildren(i);
1603}
1604
1606{
1607 if (m_hide) return;
1608 if (href.url().startsWith("mailto:"))
1609 {
1611 }
1612 else
1613 {
1614 QCString url = correctURL(href.url(),href.relPath());
1615 m_t << "<a href=\"" << convertToHtml(url) << "\""
1616 << href.attribs().toString() << ">";
1617 }
1618 visitChildren(href);
1619 m_t << "</a>";
1620}
1621
1623{
1624 if (m_hide) return;
1625 m_t << "<summary " << s.attribs().toString() << ">\n";
1626 visitChildren(s);
1627 m_t << "</summary>\n";
1628}
1629
1631{
1632 if (m_hide) return;
1634 m_t << "<details " << d.attribs().toString() << ">\n";
1635 auto summary = d.summary();
1636 if (summary)
1637 {
1638 std::visit(*this,*summary);
1639 }
1640 visitChildren(d);
1641 m_t << "</details>\n";
1643}
1644
1646{
1647 if (m_hide) return;
1648 forceEndParagraph(header);
1649 m_t << "<h" << header.level() << header.attribs().toString() << ">";
1650 visitChildren(header);
1651 m_t << "</h" << header.level() << ">\n";
1652 forceStartParagraph(header);
1653}
1654
1656{
1657 if (img.type()==DocImage::Html)
1658 {
1659 bool inlineImage = img.isInlineImage();
1660 bool typeSVG = img.isSVG();
1661 QCString url = img.url();
1662
1663 if (!inlineImage)
1664 {
1665 forceEndParagraph(img);
1666 }
1667 if (m_hide) return;
1668 QCString baseName=makeShortName(img.name());
1669 if (!inlineImage) m_t << "<div class=\"image\">\n";
1670 QCString sizeAttribs;
1671 if (!img.width().isEmpty())
1672 {
1673 sizeAttribs+=" width=\""+img.width()+"\"";
1674 }
1675 if (!img.height().isEmpty()) // link to local file
1676 {
1677 sizeAttribs+=" height=\""+img.height()+"\"";
1678 }
1679 // 16 cases: url.isEmpty() | typeSVG | inlineImage | img.hasCaption()
1680
1681 HtmlAttribList attribs = img.attribs();
1682 if (typeSVG)
1683 {
1684 attribs.mergeAttribute("style","pointer-events: none;");
1685 }
1686 QCString alt;
1687 QCString attrs = attribs.toString(&alt);
1688 QCString src;
1689 if (url.isEmpty())
1690 {
1691 src = img.relPath()+img.name();
1692 }
1693 else
1694 {
1695 src = correctURL(url,img.relPath());
1696 }
1697 if (typeSVG && !inlineImage && !src.startsWith("http://") && !src.startsWith("https://"))
1698 {
1699 m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src)
1700 << "\"" << sizeAttribs << attrs;
1701 if (inlineImage)
1702 {
1703 // skip closing tag
1704 }
1705 else
1706 {
1707 m_t << ">" << alt << "</object>\n";
1708 }
1709 }
1710 else
1711 {
1712 m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs;
1713 if (inlineImage)
1714 {
1715 m_t << " class=\"inline\"";
1716 }
1717 else
1718 {
1719 m_t << "/>\n";
1720 }
1721 }
1722 if (img.hasCaption())
1723 {
1724 if (inlineImage)
1725 {
1726 m_t << " title=\"";
1727 m_insideTitle=true;
1728 }
1729 else
1730 {
1731 m_t << "<div class=\"caption\">\n";
1732 }
1733 }
1734 else if (inlineImage)
1735 {
1736 m_t << "/>";
1737 }
1738
1739 visitChildren(img);
1740
1741 if (img.hasCaption())
1742 {
1743 if (inlineImage)
1744 {
1745 m_t << "\"/>";
1746 m_insideTitle=false;
1747 }
1748 else // end <div class="caption">
1749 {
1750 m_t << "</div>";
1751 }
1752 }
1753 if (!inlineImage) // end <div class="image">
1754 {
1755 m_t << "</div>\n";
1757 }
1758 }
1759 else // other format -> skip
1760 {
1761 }
1762}
1763
1765{
1766 if (m_hide) return;
1767 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1769 m_t << "<div class=\"dotgraph\">\n";
1770 writeDotFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1771 if (df.hasCaption())
1772 {
1773 m_t << "<div class=\"caption\">\n";
1774 }
1775 visitChildren(df);
1776 if (df.hasCaption())
1777 {
1778 m_t << "</div>\n";
1779 }
1780 m_t << "</div>\n";
1782}
1783
1785{
1786 if (m_hide) return;
1787 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1789 m_t << "<div class=\"mscgraph\">\n";
1790 writeMscFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1791 if (df.hasCaption())
1792 {
1793 m_t << "<div class=\"caption\">\n";
1794 }
1795 visitChildren(df);
1796 if (df.hasCaption())
1797 {
1798 m_t << "</div>\n";
1799 }
1800 m_t << "</div>\n";
1802}
1803
1805{
1806 if (m_hide) return;
1807 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1809 m_t << "<div class=\"diagraph\">\n";
1810 writeDiaFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
1811 if (df.hasCaption())
1812 {
1813 m_t << "<div class=\"caption\">\n";
1814 }
1815 visitChildren(df);
1816 if (df.hasCaption())
1817 {
1818 m_t << "</div>\n";
1819 }
1820 m_t << "</div>\n";
1822}
1823
1825{
1826 if (m_hide) return;
1827 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1829 QCString htmlOutput = Config_getString(HTML_OUTPUT);
1830 QCString imgExt = getDotImageExtension();
1831 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
1832 if (imgExt=="svg")
1833 {
1835 }
1836 std::string inBuf;
1837 readInputFile(df.file(),inBuf);
1838 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(htmlOutput,QCString(),
1839 inBuf,format,QCString(),df.srcFile(),df.srcLine(),false);
1840 for (const auto &bName: baseNameVector)
1841 {
1842 QCString baseName=makeBaseName(bName);
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";
1855 }
1857}
1858
1860{
1861 if (m_hide) return;
1862 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1863 visitChildren(lnk);
1864 endLink();
1865}
1866
1868{
1869 if (m_hide) return;
1870 if (!ref.file().isEmpty())
1871 {
1872 // when ref.isSubPage()==TRUE we use ref.file() for HTML and
1873 // ref.anchor() for LaTeX/RTF
1874 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1875 }
1876 if (!ref.hasLinkText()) filter(ref.targetTitle());
1877 visitChildren(ref);
1878 if (!ref.file().isEmpty()) endLink();
1879 //m_t << " ";
1880}
1881
1883{
1884 if (m_hide) return;
1885 if (!ref.file().isEmpty())
1886 {
1887 m_t << "<li>";
1888 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1889 }
1890 visitChildren(ref);
1891 if (!ref.file().isEmpty())
1892 {
1893 endLink();
1894 m_t << "</li>\n";
1895 }
1896}
1897
1899{
1900 if (m_hide) return;
1902 m_t << "<div>\n";
1903 m_t << "<ul class=\"multicol\">\n";
1904 visitChildren(s);
1905 m_t << "</ul>\n";
1906 m_t << "</div>\n";
1908}
1909
1911{
1912 if (m_hide) return;
1914 QCString className;
1915 QCString heading;
1916 switch(s.type())
1917 {
1919 heading=theTranslator->trParameters();
1920 className="params";
1921 break;
1923 heading=theTranslator->trReturnValues();
1924 className="retval";
1925 break;
1927 heading=theTranslator->trExceptions();
1928 className="exception";
1929 break;
1931 heading=theTranslator->trTemplateParameters();
1932 className="tparams";
1933 break;
1934 default:
1935 ASSERT(0);
1936 }
1937 m_t << "<dl class=\"" << className << "\"><dt>";
1938 m_t << heading;
1939 m_t << "</dt><dd>\n";
1940 m_t << " <table class=\"" << className << "\">\n";
1941 visitChildren(s);
1942 m_t << " </table>\n";
1943 m_t << " </dd>\n";
1944 m_t << "</dl>\n";
1946}
1947
1949{
1950 if (m_hide) return;
1951 m_t << "&#160;" << s.chars() << "&#160;";
1952}
1953
1955{
1956 //printf("DocParamList::visitPre\n");
1957 if (m_hide) return;
1958 m_t << " <tr>";
1959 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
1960 if (sect && sect->hasInOutSpecifier())
1961 {
1962 m_t << "<td class=\"paramdir\">";
1964 {
1965 m_t << "[";
1966 if (pl.direction()==DocParamSect::In)
1967 {
1968 m_t << "in";
1969 }
1970 else if (pl.direction()==DocParamSect::Out)
1971 {
1972 m_t << "out";
1973 }
1974 else if (pl.direction()==DocParamSect::InOut)
1975 {
1976 m_t << "in,out";
1977 }
1978 m_t << "]";
1979 }
1980 m_t << "</td>";
1981 }
1982 if (sect && sect->hasTypeSpecifier())
1983 {
1984 m_t << "<td class=\"paramtype\">";
1985 for (const auto &type : pl.paramTypes())
1986 {
1987 std::visit(*this,type);
1988 }
1989 m_t << "</td>";
1990 }
1991 m_t << "<td class=\"paramname\">";
1992 bool first=TRUE;
1993 for (const auto &param : pl.parameters())
1994 {
1995 if (!first) m_t << ","; else first=FALSE;
1996 std::visit(*this,param);
1997 }
1998 m_t << "</td><td>";
1999 for (const auto &par : pl.paragraphs())
2000 {
2001 std::visit(*this,par);
2002 }
2003 m_t << "</td></tr>\n";
2004}
2005
2007{
2008 if (m_hide) return;
2009 if (x.title().isEmpty()) return;
2010
2012 bool anonymousEnum = x.file()=="@";
2013 if (!anonymousEnum)
2014 {
2015 QCString fn = x.file();
2017 m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
2018 << x.relPath() << fn
2019 << "#" << x.anchor() << "\">";
2020 }
2021 else
2022 {
2023 m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
2024 }
2025 filter(x.title());
2026 if (!anonymousEnum) m_t << "</a>";
2027 m_t << "</b></dt><dd>";
2028 visitChildren(x);
2029 if (x.title().isEmpty()) return;
2030 m_t << "</dd></dl>\n";
2032}
2033
2035{
2036 if (m_hide) return;
2037 startLink(QCString(),ref.file(),ref.relPath(),ref.anchor());
2038 visitChildren(ref);
2039 endLink();
2040 m_t << " ";
2041}
2042
2044{
2045 visitChildren(t);
2046}
2047
2049{
2050 if (m_hide) return;
2052 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2053 visitChildren(b);
2054 m_t << "</blockquote>\n";
2056}
2057
2059{
2060 if (m_hide) return;
2061 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2062 {
2065 m_t << "<p>";
2066 m_t << theTranslator->trFlowchart();
2067 m_t << " ";
2068 m_t << "<a href=\"";
2069 m_t << fname;
2070 m_t << ".svg\">";
2072 m_t << "</a>";
2073 if (vf.hasCaption())
2074 {
2075 m_t << "<br />";
2076 }
2077 }
2078 visitChildren(vf);
2079 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2080 {
2081 m_t << "</p>";
2083 }
2084}
2085
2087{
2088 if (m_hide) return;
2089 visitChildren(pb);
2090}
2091
2092void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
2093{
2094 if (str.isEmpty()) return;
2095 const char *p=str.data();
2096 while (*p)
2097 {
2098 char c=*p++;
2099 switch(c)
2100 {
2101 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2102 case '<': m_t << "&lt;"; break;
2103 case '>': m_t << "&gt;"; break;
2104 case '&': m_t << "&amp;"; break;
2105 case '\\':
2106 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2107 m_t << "\\&zwj;" << *p++;
2108 else
2109 m_t << c;
2110 break;
2111 default:
2112 {
2113 uint8_t uc = static_cast<uint8_t>(c);
2114 if (uc<32 && !isspace(c)) // non-printable control characters
2115 {
2116 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2117 }
2118 else
2119 {
2120 m_t << c;
2121 }
2122 }
2123 break;
2124 }
2125 }
2126}
2127
2128/// Escape basic entities to produce a valid CDATA attribute value,
2129/// assume that the outer quoting will be using the double quote &quot;
2131{
2132 if (str.isEmpty()) return str;
2133 QCString result;
2134 result.reserve(str.length()+8);
2135 const char *p=str.data();
2136 while (*p)
2137 {
2138 char c=*p++;
2139 switch(c)
2140 {
2141 case '&': result+="&amp;"; break;
2142 case '"': result+="&quot;"; break;
2143 case '<': result+="&lt;"; break;
2144 case '>': result+="&gt;"; break;
2145 case '\\':
2146 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2147 {
2148 result+="\\&zwj;";
2149 result+=*p++;
2150 }
2151 else
2152 {
2153 result+=c;
2154 }
2155 break;
2156 default:
2157 {
2158 uint8_t uc = static_cast<uint8_t>(c);
2159 if (uc<32 && !isspace(c)) // non-printable control characters
2160 {
2161 result+="&#x24";
2162 result+=hex[uc>>4];
2163 result+=hex[uc&0xF];
2164 result+=";";
2165 }
2166 else
2167 {
2168 result+=c;
2169 }
2170 }
2171 break;
2172 }
2173 }
2174 return result;
2175}
2176
2177void HtmlDocVisitor::startLink(const QCString &ref,const QCString &file,
2178 const QCString &relPath,const QCString &anchor,
2179 const QCString &tooltip)
2180{
2181 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2182 if (!ref.isEmpty()) // link to entity imported via tag file
2183 {
2184 m_t << "<a class=\"elRef\" ";
2186 }
2187 else // local link
2188 {
2189 m_t << "<a class=\"el\" ";
2190 }
2191 m_t << "href=\"";
2192 QCString fn = file;
2194 m_t << createHtmlUrl(relPath,ref,true,
2195 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2196 fn,
2197 anchor);
2198 m_t << "\"";
2199 if (!tooltip.isEmpty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2200 m_t << ">";
2201}
2202
2204{
2205 m_t << "</a>";
2206}
2207
2208void HtmlDocVisitor::writeDotFile(const QCString &fn,const QCString &relPath,
2209 const QCString &context,const QCString &srcFile,int srcLine)
2210{
2211 QCString baseName=makeBaseName(fn);
2212 baseName.prepend("dot_");
2213 QCString outDir = Config_getString(HTML_OUTPUT);
2214 writeDotGraphFromFile(fn,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2215 writeDotImageMapFromFile(m_t,fn,outDir,relPath,baseName,context,-1,srcFile,srcLine);
2216}
2217
2218void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,
2219 const QCString &context,const QCString &srcFile,int srcLine)
2220{
2221 QCString baseName=makeBaseName(fileName);
2222 baseName.prepend("msc_");
2223 QCString outDir = Config_getString(HTML_OUTPUT);
2224 QCString imgExt = getDotImageExtension();
2226 if ("svg" == imgExt)
2227 mscFormat = MscOutputFormat::SVG;
2228 writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
2229 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2230}
2231
2232void HtmlDocVisitor::writeDiaFile(const QCString &fileName, const QCString &relPath,
2233 const QCString &,const QCString &srcFile,int srcLine)
2234{
2235 QCString baseName=makeBaseName(fileName);
2236 baseName.prepend("dia_");
2237 QCString outDir = Config_getString(HTML_OUTPUT);
2238 writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine);
2239
2240 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2241}
2242
2243void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString &relPath,
2244 const QCString &,const QCString &/* srcFile */,int /* srcLine */)
2245{
2246 QCString baseName=makeBaseName(fileName);
2247 QCString outDir = Config_getString(HTML_OUTPUT);
2248 QCString imgExt = getDotImageExtension();
2249 if (imgExt=="svg")
2250 {
2252 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2253 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2254 //m_t << "</iframe>\n";
2255 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2256 }
2257 else
2258 {
2260 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2261 }
2262}
2263
2264/** Returns TRUE if the child nodes in paragraph \a para until \a nodeIndex
2265 contain a style change node that is still active and that style change is one that
2266 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2267 See also bug746162.
2268 */
2271{
2272 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2273 int styleMask=0;
2274 bool styleOutsideParagraph=FALSE;
2275 while (!styleOutsideParagraph)
2276 {
2277 const DocNodeVariant *n = &(*it);
2278 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2279 if (sc)
2280 {
2281 if (!sc->enable()) // remember styles that has been closed already
2282 {
2283 styleMask|=static_cast<int>(sc->style());
2284 }
2285 bool paraStyle = sc->style()==DocStyleChange::Center ||
2286 sc->style()==DocStyleChange::Div ||
2288 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2289 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2290 paraStyle
2291 )
2292 {
2293 styleOutsideParagraph=TRUE;
2294 }
2295 }
2296 if (it!=std::begin(para->children()))
2297 {
2298 --it;
2299 }
2300 else
2301 {
2302 break;
2303 }
2304 }
2305 return styleOutsideParagraph;
2306}
2307
2308/** Used for items found inside a paragraph, which due to XHTML restrictions
2309 * have to be outside of the paragraph. This method will forcefully end
2310 * the current paragraph and forceStartParagraph() will restart it.
2311 */
2312template<class Node>
2314{
2315 const DocPara *para=std::get_if<DocPara>(n.parent());
2316 if (para)
2317 {
2318 const DocNodeList &children = para->children();
2319
2320 //printf("forceEndParagraph\n");
2321 //dumpDocNodeList(children);
2322
2323 auto it = std::find_if(std::begin(children),std::end(children),
2324 [&n](const auto &np) { return holds_value(&n,np); });
2325 if (it==std::end(children)) return;
2326 if (it==std::begin(children)) return; // first node in paragraph
2327 it = std::prev(it);
2328 bool found=false;
2329 while (!found)
2330 {
2331 found = !isInvisibleNode(*it);
2332 if (found) break;
2333 if (it!=std::begin(children))
2334 {
2335 --it;
2336 }
2337 else
2338 {
2339 break;
2340 }
2341 }
2342 if (!found) return; // first visible node in paragraph
2343 const DocNodeVariant &v = *it;
2344 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2345 bool styleOutsideParagraph=false;
2346 if (it!=std::begin(children))
2347 {
2348 it = std::prev(it);
2349 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2350 }
2351 bool isFirst = false;
2352 bool isLast = false;
2353 getParagraphContext(*para,isFirst,isLast);
2354 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2355 if (!std::holds_alternative<DocAutoListItem>(*para->parent()) && isFirst && isLast) return;
2356 if (styleOutsideParagraph) return;
2357
2358 //printf("adding </p>\n");
2359 m_t << "</p>";
2360 }
2361}
2362
2363/** Used for items found inside a paragraph, which due to XHTML restrictions
2364 * have to be outside of the paragraph. This method will forcefully start
2365 * the paragraph, that was previously ended by forceEndParagraph().
2366 */
2367template<class Node>
2369{
2370 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2371 const DocPara *para=nullptr;
2372 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2373 {
2374 const DocNodeList &children = para->children();
2375
2376 auto it = std::find_if(std::begin(children),
2377 std::end(children),
2378 [&n](const auto &np)
2379 { return holds_value(&n,np); });
2380 if (it==std::end(children)) return;
2381 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2382 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2383 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2384 if (styleOutsideParagraph) return;
2385 it = std::next(it);
2386 while (it!=std::end(children) && isInvisibleNode(*it))
2387 {
2388 ++it;
2389 }
2390 if (it!=std::end(children))
2391 {
2392 const DocNodeVariant &v = *it;
2393 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2394 }
2395 else
2396 {
2397 return; // only whitespace at the end!
2398 }
2399
2400 bool needsTag = true;
2401 bool isFirst = false;
2402 bool isLast = false;
2403 getParagraphContext(*para,isFirst,isLast);
2404 if (!std::holds_alternative<DocAutoListItem>(*para->parent()) && isFirst && isLast) needsTag = false;
2405 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2406
2407 if (needsTag) m_t << "<p>";
2408 }
2409}
2410
void parseCodeFragment(OutputCodeList &codeOutList, const QCString &fileName, const QCString &blockId, const QCString &scopeName, bool showLineNumbers, bool trimLeft, bool stripCodeComments)
static CodeFragmentManager & instance()
virtual void parseCode(OutputCodeList &codeOutList, const QCString &scopeName, const QCString &input, SrcLangExt lang, bool stripCodeComments, const CodeParserOptions &options)=0
Parses a source file or fragment with the goal to produce highlighted and cross-referenced output.
The common base class of all entity definitions found in the sources.
Definition definition.h: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)
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
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 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
Options to configure the code parser.
Definition parserintf.h:78
CodeParserOptions & setSearchCtx(const Definition *d)
Definition parserintf.h:116
CodeParserOptions & setStartLine(int lineNr)
Definition parserintf.h:101
CodeParserOptions & setInlineFragment(bool enable)
Definition parserintf.h:107
CodeParserOptions & setShowLineNumbers(bool enable)
Definition parserintf.h:113
CodeParserOptions & setFileDef(const FileDef *fd)
Definition parserintf.h:98
SrcLangExt
Definition types.h:207
const char * writeUTF8Char(TextStream &t, const char *s)
Writes the UTF8 character pointed to by s to stream t and returns a pointer to the next character.
Definition utf8.cpp:197
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5159
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:3917
QCString correctURL(const QCString &url, const QCString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:5889
QCString stripPath(const QCString &s)
Definition util.cpp:4902
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:5498
SrcLangExt getLanguageFromCodeLang(QCString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:5177
QCString getDotImageExtension()
Definition util.cpp:6253
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:5821
QCString externalLinkTarget(const bool parent)
Definition util.cpp:5673
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5201
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:4875
QCString createHtmlUrl(const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
Definition util.cpp:5684
A bunch of utility functions.