Doxygen
Loading...
Searching...
No Matches
htmldocvisitor.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include "htmldocvisitor.h"
17#include "docparser.h"
18#include "language.h"
19#include "doxygen.h"
20#include "outputgen.h"
21#include "outputlist.h"
22#include "dot.h"
23#include "message.h"
24#include "config.h"
25#include "htmlgen.h"
26#include "parserintf.h"
27#include "msc.h"
28#include "dia.h"
29#include "util.h"
30#include "vhdldocgen.h"
31#include "filedef.h"
32#include "memberdef.h"
33#include "htmlentity.h"
34#include "emoji.h"
35#include "plantuml.h"
36#include "formula.h"
37#include "fileinfo.h"
38#include "indexlist.h"
39#include "growbuf.h"
40#include "portable.h"
41#include "codefragment.h"
42
43static const int NUM_HTML_LIST_TYPES = 4;
44static const char 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: %s\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 m_t << u.url() << "\">";
405 filter(u.url());
406 m_t << "</a>";
407 }
408}
409
411{
412 if (m_hide) return;
413 m_t << "<br "<< br.attribs().toString() << " />\n";
414}
415
417{
418 if (m_hide) return;
420 m_t << "<hr "<< hr.attribs().toString() << " />\n";
422}
423
425{
426 if (m_hide) return;
427 switch (s.style())
428 {
430 if (s.enable()) m_t << "<b" << s.attribs().toString() << ">"; else m_t << "</b>";
431 break;
433 if (s.enable()) m_t << "<s" << s.attribs().toString() << ">"; else m_t << "</s>";
434 break;
436 if (s.enable()) m_t << "<strike" << s.attribs().toString() << ">"; else m_t << "</strike>";
437 break;
439 if (s.enable()) m_t << "<del" << s.attribs().toString() << ">"; else m_t << "</del>";
440 break;
442 if (s.enable()) m_t << "<u" << s.attribs().toString() << ">"; else m_t << "</u>";
443 break;
445 if (s.enable()) m_t << "<ins" << s.attribs().toString() << ">"; else m_t << "</ins>";
446 break;
448 if (s.enable())
449 {
450 auto attribs = s.attribs();
451 if (s.tagName()=="a")
452 {
453 attribs.mergeAttribute("class","arg");
454 }
455 m_t << "<em" << attribs.toString() << ">";
456 }
457 else
458 {
459 m_t << "</em>";
460 }
461 break;
463 if (s.enable()) m_t << "<kbd" << s.attribs().toString() << ">"; else m_t << "</kbd>";
464 break;
466 if (s.enable())
467 {
468 auto attribs = s.attribs();
469 if (s.tagName()=="p")
470 {
471 attribs.mergeAttribute("class","param");
472 }
473 m_t << "<code" << attribs.toString() << ">";
474 }
475 else
476 {
477 m_t << "</code>";
478 }
479 break;
481 if (s.enable()) m_t << "<sub" << s.attribs().toString() << ">"; else m_t << "</sub>";
482 break;
484 if (s.enable()) m_t << "<sup" << s.attribs().toString() << ">"; else m_t << "</sup>";
485 break;
487 if (s.enable())
488 {
490 m_t << "<center" << s.attribs().toString() << ">";
491 }
492 else
493 {
494 m_t << "</center>";
496 }
497 break;
499 if (s.enable()) m_t << "<small" << s.attribs().toString() << ">"; else m_t << "</small>";
500 break;
502 if (s.enable()) m_t << "<cite" << s.attribs().toString() << ">"; else m_t << "</cite>";
503 break;
505 if (s.enable())
506 {
508 m_t << "<pre" << s.attribs().toString() << ">";
510 }
511 else
512 {
514 m_t << "</pre>";
516 }
517 break;
519 if (s.enable())
520 {
522 m_t << "<div" << s.attribs().toString() << ">";
523 }
524 else
525 {
526 m_t << "</div>";
528 }
529 break;
531 if (s.enable()) m_t << "<span" << s.attribs().toString() << ">"; else m_t << "</span>";
532 break;
533 }
534}
535
536///--------------------------------------------------------------------------------------
537
539{
540 if (m_hide) return;
541 QCString lang = m_langExt;
542 if (!s.language().isEmpty()) // explicit language setting
543 {
544 lang = s.language();
545 }
546 SrcLangExt langExt = getLanguageFromCodeLang(lang);
547 switch(s.type())
548 {
551 m_ci.startCodeFragment("DoxyCode");
553 s.context(),
554 s.text(),
555 langExt,
556 Config_getBool(STRIP_CODE_COMMENTS),
557 s.isExample(),
558 s.exampleFile(),
559 nullptr, // fileDef
560 -1, // startLine
561 -1, // endLine
562 true, // inlineFragment
563 nullptr, // memberDef
564 true, // show line numbers
565 m_ctx // search context
566 );
567 m_ci.endCodeFragment("DoxyCode");
569 break;
572 m_t << "<pre class=\"fragment\">";
573 filter(s.text());
574 m_t << "</pre>";
576 break;
578 filter(s.text(), true);
579 break;
581 m_t << "<code class=\"JavaDocCode\">";
582 filter(s.text(), true);
583 m_t << "</code>";
584 break;
586 {
587 if (s.isBlock()) forceEndParagraph(s);
588 m_t << s.text();
589 if (s.isBlock()) forceStartParagraph(s);
590 }
591 break;
597 /* nothing */
598 break;
599
600 case DocVerbatim::Dot:
601 {
602 static int dotindex = 1;
603 QCString fileName(4096, QCString::ExplicitSize);
604
606 fileName.sprintf("%s%d%s",
607 qPrint(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_"),
608 dotindex++,
609 ".dot"
610 );
611 std::ofstream file = Portable::openOutputStream(fileName);
612 if (!file.is_open())
613 {
614 err("Could not open file %s for writing\n",qPrint(fileName));
615 }
616 else
617 {
618 QCString stext = s.text();
619 file.write( stext.data(), stext.length() );
620 file.close();
621
622 m_t << "<div class=\"dotgraph\">\n";
623 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
624 visitCaption(m_t, s);
625 m_t << "</div>\n";
626
627 if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
628 }
630 }
631 break;
632 case DocVerbatim::Msc:
633 {
635
636 static int mscindex = 1;
637 QCString baseName(4096, QCString::ExplicitSize);
638
639 baseName.sprintf("%s%d",
640 qPrint(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_"),
641 mscindex++
642 );
643 std::ofstream file = Portable::openOutputStream(baseName.str()+".msc");
644 if (!file.is_open())
645 {
646 err("Could not open file %s.msc for writing\n",qPrint(baseName));
647 }
648 else
649 {
650 QCString text = "msc {";
651 text+=s.text();
652 text+="}";
653
654 file.write( text.data(), text.length() );
655 file.close();
656
657 m_t << "<div class=\"mscgraph\">\n";
658 writeMscFile(baseName+".msc",s.relPath(),s.context(),s.srcFile(),s.srcLine());
659 visitCaption(m_t, s);
660 m_t << "</div>\n";
661
662 if (Config_getBool(DOT_CLEANUP)) Dir().remove(baseName.str()+".msc");
663 }
665 }
666 break;
668 {
670 QCString htmlOutput = Config_getString(HTML_OUTPUT);
672 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
673 if (imgExt=="svg")
674 {
676 }
678 htmlOutput,s.exampleFile(),
679 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
680 m_t << "<div class=\"plantumlgraph\">\n";
681 writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
682 visitCaption(m_t, s);
683 m_t << "</div>\n";
685 }
686 break;
687 }
688}
689
691{
692 if (m_hide) return;
693 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
694}
695
697{
698 if (m_hide) return;
700 switch(inc.type())
701 {
704 m_ci.startCodeFragment("DoxyCode");
706 inc.context(),
707 inc.text(),
708 langExt,
709 inc.stripCodeComments(),
710 inc.isExample(),
711 inc.exampleFile(),
712 nullptr, // fileDef
713 -1, // startLine
714 -1, // endLine
715 TRUE, // inlineFragment
716 nullptr, // memberDef
717 FALSE, // show line numbers
718 m_ctx // search context
719 );
720 m_ci.endCodeFragment("DoxyCode");
722 break;
724 {
726 m_ci.startCodeFragment("DoxyCode");
727 FileInfo cfi( inc.file().str() );
728 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
730 inc.context(),
731 inc.text(),
732 langExt,
733 inc.stripCodeComments(),
734 inc.isExample(),
735 inc.exampleFile(),
736 fd.get(), // fileDef,
737 -1, // start line
738 -1, // end line
739 true, // inline fragment
740 nullptr, // memberDef
741 true, // show line numbers
742 m_ctx // search context
743 );
744 m_ci.endCodeFragment("DoxyCode");
746 }
747 break;
755 break;
757 {
758 if (inc.isBlock()) forceEndParagraph(inc);
759 m_t << inc.text();
760 if (inc.isBlock()) forceStartParagraph(inc);
761 }
762 break;
765 m_t << "<pre class=\"fragment\">";
766 filter(inc.text());
767 m_t << "</pre>";
769 break;
773 m_ci.startCodeFragment("DoxyCode");
775 inc.file(),
776 inc.blockId(),
777 inc.context(),
779 inc.trimLeft(),
781 );
782 m_ci.endCodeFragment("DoxyCode");
784 break;
785 }
786}
787
789{
790 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
791 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
792 if (op.isFirst())
793 {
795 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
797 m_hide=TRUE;
798 }
800 if (locLangExt.isEmpty()) locLangExt = m_langExt;
801 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
802 if (op.type()!=DocIncOperator::Skip)
803 {
804 m_hide = popHidden();
805 if (!m_hide)
806 {
807 std::unique_ptr<FileDef> fd;
808 if (!op.includeFileName().isEmpty())
809 {
810 FileInfo cfi( op.includeFileName().str() );
811 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
812 }
813 getCodeParser(locLangExt).parseCode(
814 m_ci,
815 op.context(),
816 op.text(),
817 langExt,
819 op.isExample(),
820 op.exampleFile(),
821 fd.get(), // fileDef
822 op.line(), // startLine
823 -1, // endLine
824 true, // inline fragment
825 nullptr, // memberDef
826 op.showLineNo(), // show line numbers
827 m_ctx // search context
828 );
829 }
831 m_hide=TRUE;
832 }
833 if (op.isLast())
834 {
835 m_hide = popHidden();
836 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
838 }
839 else
840 {
841 if (!m_hide) m_t << "\n";
842 }
843}
844
846{
847 if (m_hide) return;
848 bool bDisplay = !f.isInline();
849 if (bDisplay)
850 {
852 m_t << "<p class=\"formulaDsp\">\n";
853 }
854
855 if (Config_getBool(USE_MATHJAX))
856 {
857 QCString text = f.text();
858 bool closeInline = FALSE;
859 if (!bDisplay && !text.isEmpty() && text.at(0)=='$' &&
860 text.at(text.length()-1)=='$')
861 {
862 closeInline=TRUE;
863 text = text.mid(1,text.length()-2);
864 m_t << "\\(";
865 }
866 else if (!bDisplay && !text.isEmpty())
867 {
868 closeInline=TRUE;
869 m_t << "\\(";
870 }
871 m_t << convertToHtml(text);
872 if (closeInline)
873 {
874 m_t << "\\)";
875 }
876 }
877 else
878 {
879 const Formula *formula = FormulaManager::instance().findFormula(f.id());
880
881 enum class ImageType { Light, Dark };
882 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
883 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> QCString {
884 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
885 TextStream t;
886 QCString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
887 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
888 {
889 t << "<picture>";
890 t << "<source srcset=\"" << f.relPath() << f.name();
891 if (visibility==Visibility::AutoDark)
892 {
893 t << extension;
894 t << "\" media=\"(prefers-color-scheme: light)\"";
895 }
896 else // AutoLight
897 {
898 t << "_dark";
899 t << extension;
900 t << "\" media=\"(prefers-color-scheme: dark)\"";
901 }
902 t << "/>";
903 }
904 t << "<img class=\"formula";
905 t << (bDisplay ? "Dsp" : "Inl");
906 if (visibility==Visibility::Light) t << " light-mode-visible";
907 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
908 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
909 if (imgType==ImageType::Dark) t << "_dark";
910 t << extension;
911 if (formula && formula->width()!=-1)
912 {
913 t << "\" width=\"";
914 t << formula->width();
915 }
916 if (formula && formula->height()!=-1)
917 {
918 t << "\" height=\"";
919 t << formula->height();
920 }
921 t << "\"/>";
922 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
923 {
924 t << "</picture>";
925 }
926 return QCString(t.str());
927 };
928
929 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
930 switch(colorStyle)
931 {
932 case HTML_COLORSTYLE_t::LIGHT:
933 m_t << writeFormula(ImageType::Light,Visibility::Always);
934 break;
935 case HTML_COLORSTYLE_t::DARK:
936 m_t << writeFormula(ImageType::Dark, Visibility::Always);
937 break;
938 case HTML_COLORSTYLE_t::AUTO_LIGHT:
939 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
940 break;
941 case HTML_COLORSTYLE_t::AUTO_DARK:
942 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
943 break;
944 case HTML_COLORSTYLE_t::TOGGLE:
945 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
946 m_t << writeFormula(ImageType::Light,Visibility::Light);
947 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
948 break;
949 }
950 }
951 if (bDisplay)
952 {
953 m_t << "\n</p>\n";
955 }
956}
957
959{
961 if (e.member())
962 {
963 anchor.prepend(e.member()->anchor()+"_");
964 }
965 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
966 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
967 // qPrint(e.entry()),
968 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
969 // e.member() ? qPrint(e.member()->name()) : "<null>"
970 // );
971 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
972}
973
975{
976 m_t << "</dd>\n";
977 m_t << "<dd>\n";
978}
979
981{
982 if (m_hide) return;
983 if (!cite.file().isEmpty())
984 {
985 startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
986 }
987 else
988 {
989 m_t << "<b>[";
990 }
991 filter(cite.text());
992 if (!cite.file().isEmpty())
993 {
994 endLink();
995 }
996 else
997 {
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=\"" << 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 (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 (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() << ">";
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)
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);
1839 htmlOutput,QCString(),
1840 inBuf.c_str(),format,QCString(),df.srcFile(),df.srcLine(),false);
1841 baseName=makeBaseName(baseName);
1842 m_t << "<div class=\"plantumlgraph\">\n";
1843 writePlantUMLFile(baseName,df.relPath(),QCString(),df.srcFile(),df.srcLine());
1844 if (df.hasCaption())
1845 {
1846 m_t << "<div class=\"caption\">\n";
1847 }
1848 visitChildren(df);
1849 if (df.hasCaption())
1850 {
1851 m_t << "</div>\n";
1852 }
1853 m_t << "</div>\n";
1855}
1856
1858{
1859 if (m_hide) return;
1860 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1861 visitChildren(lnk);
1862 endLink();
1863}
1864
1866{
1867 if (m_hide) return;
1868 if (!ref.file().isEmpty())
1869 {
1870 // when ref.isSubPage()==TRUE we use ref.file() for HTML and
1871 // ref.anchor() for LaTeX/RTF
1872 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1873 }
1874 if (!ref.hasLinkText()) filter(ref.targetTitle());
1875 visitChildren(ref);
1876 if (!ref.file().isEmpty()) endLink();
1877 //m_t << " ";
1878}
1879
1881{
1882 if (m_hide) return;
1883 if (!ref.file().isEmpty())
1884 {
1885 m_t << "<li>";
1886 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1887 }
1888 visitChildren(ref);
1889 if (!ref.file().isEmpty())
1890 {
1891 endLink();
1892 m_t << "</li>\n";
1893 }
1894}
1895
1897{
1898 if (m_hide) return;
1900 m_t << "<div>\n";
1901 m_t << "<ul class=\"multicol\">\n";
1902 visitChildren(s);
1903 m_t << "</ul>\n";
1904 m_t << "</div>\n";
1906}
1907
1909{
1910 if (m_hide) return;
1912 QCString className;
1913 QCString heading;
1914 switch(s.type())
1915 {
1917 heading=theTranslator->trParameters();
1918 className="params";
1919 break;
1921 heading=theTranslator->trReturnValues();
1922 className="retval";
1923 break;
1925 heading=theTranslator->trExceptions();
1926 className="exception";
1927 break;
1929 heading=theTranslator->trTemplateParameters();
1930 className="tparams";
1931 break;
1932 default:
1933 ASSERT(0);
1934 }
1935 m_t << "<dl class=\"" << className << "\"><dt>";
1936 m_t << heading;
1937 m_t << "</dt><dd>\n";
1938 m_t << " <table class=\"" << className << "\">\n";
1939 visitChildren(s);
1940 m_t << " </table>\n";
1941 m_t << " </dd>\n";
1942 m_t << "</dl>\n";
1944}
1945
1947{
1948 if (m_hide) return;
1949 m_t << "&#160;" << s.chars() << "&#160;";
1950}
1951
1953{
1954 //printf("DocParamList::visitPre\n");
1955 if (m_hide) return;
1956 m_t << " <tr>";
1957 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
1958 if (sect && sect->hasInOutSpecifier())
1959 {
1960 m_t << "<td class=\"paramdir\">";
1962 {
1963 m_t << "[";
1964 if (pl.direction()==DocParamSect::In)
1965 {
1966 m_t << "in";
1967 }
1968 else if (pl.direction()==DocParamSect::Out)
1969 {
1970 m_t << "out";
1971 }
1972 else if (pl.direction()==DocParamSect::InOut)
1973 {
1974 m_t << "in,out";
1975 }
1976 m_t << "]";
1977 }
1978 m_t << "</td>";
1979 }
1980 if (sect && sect->hasTypeSpecifier())
1981 {
1982 m_t << "<td class=\"paramtype\">";
1983 for (const auto &type : pl.paramTypes())
1984 {
1985 std::visit(*this,type);
1986 }
1987 m_t << "</td>";
1988 }
1989 m_t << "<td class=\"paramname\">";
1990 bool first=TRUE;
1991 for (const auto &param : pl.parameters())
1992 {
1993 if (!first) m_t << ","; else first=FALSE;
1994 std::visit(*this,param);
1995 }
1996 m_t << "</td><td>";
1997 for (const auto &par : pl.paragraphs())
1998 {
1999 std::visit(*this,par);
2000 }
2001 m_t << "</td></tr>\n";
2002}
2003
2005{
2006 if (m_hide) return;
2007 if (x.title().isEmpty()) return;
2008
2010 bool anonymousEnum = x.file()=="@";
2011 if (!anonymousEnum)
2012 {
2013 QCString fn = x.file();
2015 m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
2016 << x.relPath() << fn
2017 << "#" << x.anchor() << "\">";
2018 }
2019 else
2020 {
2021 m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
2022 }
2023 filter(x.title());
2024 if (!anonymousEnum) m_t << "</a>";
2025 m_t << "</b></dt><dd>";
2026 visitChildren(x);
2027 if (x.title().isEmpty()) return;
2028 m_t << "</dd></dl>\n";
2030}
2031
2033{
2034 if (m_hide) return;
2035 startLink(QCString(),ref.file(),ref.relPath(),ref.anchor());
2036 visitChildren(ref);
2037 endLink();
2038 m_t << " ";
2039}
2040
2042{
2043 visitChildren(t);
2044}
2045
2047{
2048 if (m_hide) return;
2050 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2051 visitChildren(b);
2052 m_t << "</blockquote>\n";
2054}
2055
2057{
2058 if (m_hide) return;
2059 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2060 {
2063 m_t << "<p>";
2064 m_t << theTranslator->trFlowchart();
2065 m_t << " ";
2066 m_t << "<a href=\"";
2067 m_t << fname;
2068 m_t << ".svg\">";
2070 m_t << "</a>";
2071 if (vf.hasCaption())
2072 {
2073 m_t << "<br />";
2074 }
2075 }
2076 visitChildren(vf);
2077 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2078 {
2079 m_t << "</p>";
2081 }
2082}
2083
2085{
2086 if (m_hide) return;
2087 visitChildren(pb);
2088}
2089
2090void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
2091{
2092 if (str.isEmpty()) return;
2093 const char *p=str.data();
2094 while (*p)
2095 {
2096 char c=*p++;
2097 switch(c)
2098 {
2099 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2100 case '<': m_t << "&lt;"; break;
2101 case '>': m_t << "&gt;"; break;
2102 case '&': m_t << "&amp;"; break;
2103 case '\\': if ((*p == '(') || (*p == ')'))
2104 m_t << "\\&zwj;" << *p++;
2105 else
2106 m_t << c;
2107 break;
2108 default:
2109 {
2110 uint8_t uc = static_cast<uint8_t>(c);
2111 if (uc<32 && !isspace(c)) // non-printable control characters
2112 {
2113 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2114 }
2115 else
2116 {
2117 m_t << c;
2118 }
2119 }
2120 break;
2121 }
2122 }
2123}
2124
2125/// Escape basic entities to produce a valid CDATA attribute value,
2126/// assume that the outer quoting will be using the double quote &quot;
2128{
2129 GrowBuf growBuf;
2130 if (str.isEmpty()) return str;
2131 const char *p=str.data();
2132 while (*p)
2133 {
2134 char c=*p++;
2135 switch(c)
2136 {
2137 case '&': growBuf.addStr("&amp;"); break;
2138 case '"': growBuf.addStr("&quot;"); break;
2139 case '<': growBuf.addStr("&lt;"); break;
2140 case '>': growBuf.addStr("&gt;"); break;
2141 case '\\':
2142 if ((*p == '(') || (*p == ')'))
2143 {
2144 growBuf.addStr("\\&zwj;");
2145 growBuf.addChar(*p++);
2146 }
2147 else
2148 {
2149 growBuf.addChar(c);
2150 }
2151 break;
2152 default:
2153 {
2154 uint8_t uc = static_cast<uint8_t>(c);
2155 if (uc<32 && !isspace(c)) // non-printable control characters
2156 {
2157 growBuf.addStr("&#x24");
2158 growBuf.addChar(hex[uc>>4]);
2159 growBuf.addChar(hex[uc&0xF]);
2160 growBuf.addStr(";");
2161 }
2162 else
2163 {
2164 growBuf.addChar(c);
2165 }
2166 }
2167 break;
2168 }
2169 }
2170 growBuf.addChar(0);
2171 return growBuf.get();
2172}
2173
2174void HtmlDocVisitor::startLink(const QCString &ref,const QCString &file,
2175 const QCString &relPath,const QCString &anchor,
2176 const QCString &tooltip)
2177{
2178 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2179 if (!ref.isEmpty()) // link to entity imported via tag file
2180 {
2181 m_t << "<a class=\"elRef\" ";
2183 }
2184 else // local link
2185 {
2186 m_t << "<a class=\"el\" ";
2187 }
2188 m_t << "href=\"";
2189 QCString fn = file;
2191 m_t << createHtmlUrl(relPath,ref,true,
2192 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2193 fn,
2194 anchor);
2195 m_t << "\"";
2196 if (!tooltip.isEmpty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2197 m_t << ">";
2198}
2199
2201{
2202 m_t << "</a>";
2203}
2204
2205void HtmlDocVisitor::writeDotFile(const QCString &fn,const QCString &relPath,
2206 const QCString &context,const QCString &srcFile,int srcLine)
2207{
2208 QCString baseName=makeBaseName(fn);
2209 baseName.prepend("dot_");
2210 QCString outDir = Config_getString(HTML_OUTPUT);
2211 writeDotGraphFromFile(fn,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2212 writeDotImageMapFromFile(m_t,fn,outDir,relPath,baseName,context,-1,srcFile,srcLine);
2213}
2214
2215void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,
2216 const QCString &context,const QCString &srcFile,int srcLine)
2217{
2218 QCString baseName=makeBaseName(fileName);
2219 baseName.prepend("msc_");
2220 QCString outDir = Config_getString(HTML_OUTPUT);
2221 QCString imgExt = getDotImageExtension();
2223 if ("svg" == imgExt)
2224 mscFormat = MscOutputFormat::SVG;
2225 writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
2226 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2227}
2228
2229void HtmlDocVisitor::writeDiaFile(const QCString &fileName, const QCString &relPath,
2230 const QCString &,const QCString &srcFile,int srcLine)
2231{
2232 QCString baseName=makeBaseName(fileName);
2233 baseName.prepend("dia_");
2234 QCString outDir = Config_getString(HTML_OUTPUT);
2235 writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine);
2236
2237 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2238}
2239
2240void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString &relPath,
2241 const QCString &,const QCString &/* srcFile */,int /* srcLine */)
2242{
2243 QCString baseName=makeBaseName(fileName);
2244 QCString outDir = Config_getString(HTML_OUTPUT);
2245 QCString imgExt = getDotImageExtension();
2246 if (imgExt=="svg")
2247 {
2249 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2250 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2251 //m_t << "</iframe>\n";
2252 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2253 }
2254 else
2255 {
2257 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2258 }
2259}
2260
2261/** Returns TRUE if the child nodes in paragraph \a para until \a nodeIndex
2262 contain a style change node that is still active and that style change is one that
2263 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2264 See also bug746162.
2265 */
2268{
2269 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2270 int styleMask=0;
2271 bool styleOutsideParagraph=FALSE;
2272 while (!styleOutsideParagraph)
2273 {
2274 const DocNodeVariant *n = &(*it);
2275 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2276 if (sc)
2277 {
2278 if (!sc->enable()) // remember styles that has been closed already
2279 {
2280 styleMask|=static_cast<int>(sc->style());
2281 }
2282 bool paraStyle = sc->style()==DocStyleChange::Center ||
2283 sc->style()==DocStyleChange::Div ||
2285 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2286 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2287 paraStyle
2288 )
2289 {
2290 styleOutsideParagraph=TRUE;
2291 }
2292 }
2293 if (it!=std::begin(para->children()))
2294 {
2295 --it;
2296 }
2297 else
2298 {
2299 break;
2300 }
2301 }
2302 return styleOutsideParagraph;
2303}
2304
2305/** Used for items found inside a paragraph, which due to XHTML restrictions
2306 * have to be outside of the paragraph. This method will forcefully end
2307 * the current paragraph and forceStartParagraph() will restart it.
2308 */
2309template<class Node>
2311{
2312 const DocPara *para=std::get_if<DocPara>(n.parent());
2313 if (para)
2314 {
2315 const DocNodeList &children = para->children();
2316
2317 //printf("forceEndParagraph\n");
2318 //dumpDocNodeList(children);
2319
2320 auto it = std::find_if(std::begin(children),std::end(children),
2321 [&n](const auto &np) { return holds_value(&n,np); });
2322 if (it==std::end(children)) return;
2323 if (it==std::begin(children)) return; // first node in paragraph
2324 it = std::prev(it);
2325 bool found=false;
2326 while (!found)
2327 {
2328 found = !isInvisibleNode(*it);
2329 if (found) break;
2330 if (it!=std::begin(children))
2331 {
2332 --it;
2333 }
2334 else
2335 {
2336 break;
2337 }
2338 }
2339 if (!found) return; // first visible node in paragraph
2340 const DocNodeVariant &v = *it;
2341 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2342 bool styleOutsideParagraph=false;
2343 if (it!=std::begin(children))
2344 {
2345 it = std::prev(it);
2346 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2347 }
2348 bool isFirst = false;
2349 bool isLast = false;
2350 getParagraphContext(*para,isFirst,isLast);
2351 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2352 if (isFirst && isLast) return;
2353 if (styleOutsideParagraph) return;
2354
2355 //printf("adding </p>\n");
2356 m_t << "</p>";
2357 }
2358}
2359
2360/** Used for items found inside a paragraph, which due to XHTML restrictions
2361 * have to be outside of the paragraph. This method will forcefully start
2362 * the paragraph, that was previously ended by forceEndParagraph().
2363 */
2364template<class Node>
2366{
2367 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2368 const DocPara *para=nullptr;
2369 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2370 {
2371 const DocNodeList &children = para->children();
2372
2373 auto it = std::find_if(std::begin(children),
2374 std::end(children),
2375 [&n](const auto &np)
2376 { return holds_value(&n,np); });
2377 if (it==std::end(children)) return;
2378 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2379 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2380 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2381 if (styleOutsideParagraph) return;
2382 it = std::next(it);
2383 while (it!=std::end(children) && isInvisibleNode(*it))
2384 {
2385 ++it;
2386 }
2387 if (it!=std::end(children))
2388 {
2389 const DocNodeVariant &v = *it;
2390 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2391 }
2392 else
2393 {
2394 return; // only whitespace at the end!
2395 }
2396
2397 bool needsTag = true;
2398 bool isFirst = false;
2399 bool isLast = false;
2400 getParagraphContext(*para,isFirst,isLast);
2401 if (isFirst && isLast) needsTag = false;
2402 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2403
2404 if (needsTag) m_t << "<p>";
2405 }
2406}
2407
void parseCodeFragment(OutputCodeList &codeOutList, const QCString &fileName, const QCString &blockId, const QCString &scopeName, bool showLineNumbers, bool trimLeft, bool stripCodeComments)
static CodeFragmentManager & instance()
virtual void parseCode(OutputCodeList &codeOutList, const QCString &scopeName, const QCString &input, SrcLangExt lang, bool stripCodeComments, bool isExampleBlock, const QCString &exampleName=QCString(), const FileDef *fileDef=nullptr, int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, const MemberDef *memberDef=nullptr, bool showLineNumbers=TRUE, const Definition *searchCtx=nullptr, bool collectXRefs=TRUE)=0
Parses a source file or fragment with the goal to produce highlighted and cross-referenced output.
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual QCString anchor() const =0
virtual QCString getDefFileExtension() const =0
virtual const QCString & name() const =0
Class representing a directory in the file system.
Definition dir.h:75
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:314
Node representing an anchor.
Definition docnode.h:228
const HtmlAttribList & attribs() const
Definition docnode.h:234
QCString anchor() const
Definition docnode.h:231
Node representing an auto List.
Definition docnode.h:566
bool isCheckedList() const
Definition docnode.h:577
bool isEnumList() const
Definition docnode.h:575
int depth() const
Definition docnode.h:578
Node representing an item of a auto list.
Definition docnode.h:590
int itemNumber() const
Definition docnode.h:593
Node representing a citation of some bibliographic reference.
Definition docnode.h:244
QCString text() const
Definition docnode.h:251
QCString relPath() const
Definition docnode.h:248
QCString anchor() const
Definition docnode.h:250
QCString ref() const
Definition docnode.h:249
QCString file() const
Definition docnode.h:247
DocNodeList & children()
Definition docnode.h:142
Node representing a dia file.
Definition docnode.h:725
QCString relPath() const
Definition docnode.h:680
QCString srcFile() const
Definition docnode.h:685
QCString file() const
Definition docnode.h:679
int srcLine() const
Definition docnode.h:686
bool hasCaption() const
Definition docnode.h:681
QCString context() const
Definition docnode.h:684
Node representing a dot file.
Definition docnode.h:707
Node representing an emoji.
Definition docnode.h:336
int index() const
Definition docnode.h:340
QCString name() const
Definition docnode.h:339
Node representing an item of a cross-referenced list.
Definition docnode.h:524
QCString text() const
Definition docnode.h:528
QCString name() const
Definition docnode.h:527
bool isInline() const
Definition docnode.h:531
int id() const
Definition docnode.h:530
QCString relPath() const
Definition docnode.h:529
Node representing a Hypertext reference.
Definition docnode.h:817
QCString url() const
Definition docnode.h:824
QCString relPath() const
Definition docnode.h:826
const HtmlAttribList & attribs() const
Definition docnode.h:827
Node representing a horizontal ruler.
Definition docnode.h:215
const HtmlAttribList & attribs() const
Definition docnode.h:220
Node representing an HTML blockquote.
Definition docnode.h:1285
const HtmlAttribList & attribs() const
Definition docnode.h:1290
Node representing a HTML table caption.
Definition docnode.h:1222
const HtmlAttribList & attribs() const
Definition docnode.h:1225
Node representing a HTML table cell.
Definition docnode.h:1187
bool isHeading() const
Definition docnode.h:1194
const HtmlAttribList & attribs() const
Definition docnode.h:1199
Node representing a HTML description data.
Definition docnode.h:1175
const HtmlAttribList & attribs() const
Definition docnode.h:1178
Node representing a Html description list.
Definition docnode.h:895
const HtmlAttribList & attribs() const
Definition docnode.h:899
Node representing a Html description item.
Definition docnode.h:882
const HtmlAttribList & attribs() const
Definition docnode.h:886
Node Html details.
Definition docnode.h:851
const HtmlAttribList & attribs() const
Definition docnode.h:855
const DocNodeVariant * summary() const
Definition docnode.h:858
Node Html heading.
Definition docnode.h:867
const HtmlAttribList & attribs() const
Definition docnode.h:872
int level() const
Definition docnode.h:871
Node representing a Html list.
Definition docnode.h:994
const HtmlAttribList & attribs() const
Definition docnode.h:1000
Type type() const
Definition docnode.h:999
Node representing a HTML list item.
Definition docnode.h:1159
const HtmlAttribList & attribs() const
Definition docnode.h:1164
Node representing a HTML table row.
Definition docnode.h:1240
const HtmlAttribList & attribs() const
Definition docnode.h:1246
Node Html summary.
Definition docnode.h:838
const HtmlAttribList & attribs() const
Definition docnode.h:842
Node representing a HTML table.
Definition docnode.h:1263
const DocNodeVariant * caption() const
Definition docnode.cpp:2029
const HtmlAttribList & attribs() const
Definition docnode.h:1269
Node representing an image.
Definition docnode.h:636
const HtmlAttribList & attribs() const
Definition docnode.h:650
QCString relPath() const
Definition docnode.h:646
QCString name() const
Definition docnode.h:642
QCString url() const
Definition docnode.h:647
QCString height() const
Definition docnode.h:645
Type type() const
Definition docnode.h:641
QCString width() const
Definition docnode.h:644
bool isInlineImage() const
Definition docnode.h:648
bool isSVG() const
Definition docnode.cpp:1248
bool hasCaption() const
Definition docnode.h:643
Node representing a include/dontinclude operator block.
Definition docnode.h:472
bool stripCodeComments() const
Definition docnode.h:501
bool isLast() const
Definition docnode.h:498
QCString includeFileName() const
Definition docnode.h:504
QCString text() const
Definition docnode.h:494
QCString context() const
Definition docnode.h:496
QCString exampleFile() const
Definition docnode.h:503
int line() const
Definition docnode.h:492
Type type() const
Definition docnode.h:480
bool isFirst() const
Definition docnode.h:497
bool showLineNo() const
Definition docnode.h:493
bool isExample() const
Definition docnode.h:502
Node representing an included text block from file.
Definition docnode.h:430
QCString blockId() const
Definition docnode.h:449
QCString extension() const
Definition docnode.h:445
bool isBlock() const
Definition docnode.h:453
bool stripCodeComments() const
Definition docnode.h:450
@ LatexInclude
Definition docnode.h:432
@ SnippetWithLines
Definition docnode.h:433
@ DontIncWithLines
Definition docnode.h:434
@ IncWithLines
Definition docnode.h:433
@ HtmlInclude
Definition docnode.h:432
@ VerbInclude
Definition docnode.h:432
@ DontInclude
Definition docnode.h:432
@ DocbookInclude
Definition docnode.h:434
Type type() const
Definition docnode.h:446
QCString exampleFile() const
Definition docnode.h:452
QCString text() const
Definition docnode.h:447
QCString file() const
Definition docnode.h:444
bool trimLeft() const
Definition docnode.h:454
bool isExample() const
Definition docnode.h:451
QCString context() const
Definition docnode.h:448
Node representing an entry in the index.
Definition docnode.h:547
QCString entry() const
Definition docnode.h:554
const Definition * scope() const
Definition docnode.h:552
const MemberDef * member() const
Definition docnode.h:553
Node representing an internal section of documentation.
Definition docnode.h:963
Node representing an internal reference to some item.
Definition docnode.h:801
QCString file() const
Definition docnode.h:805
QCString relPath() const
Definition docnode.h:806
QCString anchor() const
Definition docnode.h:807
Node representing a line break.
Definition docnode.h:201
const HtmlAttribList & attribs() const
Definition docnode.h:207
Node representing a word that can be linked to something.
Definition docnode.h:164
QCString file() const
Definition docnode.h:170
QCString relPath() const
Definition docnode.h:171
QCString ref() const
Definition docnode.h:172
QCString word() const
Definition docnode.h:169
QCString anchor() const
Definition docnode.h:173
QCString tooltip() const
Definition docnode.h:174
Node representing a msc file.
Definition docnode.h:716
Abstract node interface with type information.
Definition docnode.h:81
bool isPreformatted() const
Definition docnode.h:104
DocNodeVariant * parent()
Definition docnode.h:89
Node representing an block of paragraphs.
Definition docnode.h:973
Node representing a paragraph in the documentation tree.
Definition docnode.h:1074
const HtmlAttribList & attribs() const
Definition docnode.h:1108
Node representing a parameter list.
Definition docnode.h:1119
const DocNodeList & parameters() const
Definition docnode.h:1123
const DocNodeList & paramTypes() const
Definition docnode.h:1124
DocParamSect::Direction direction() const
Definition docnode.h:1127
const DocNodeList & paragraphs() const
Definition docnode.h:1125
Node representing a parameter section.
Definition docnode.h:1047
bool hasInOutSpecifier() const
Definition docnode.h:1063
bool hasTypeSpecifier() const
Definition docnode.h:1064
Type type() const
Definition docnode.h:1062
Node representing a uml file.
Definition docnode.h:734
Node representing a reference to some item.
Definition docnode.h:772
QCString anchor() const
Definition docnode.h:779
QCString relPath() const
Definition docnode.h:777
QCString targetTitle() const
Definition docnode.h:780
bool isSubPage() const
Definition docnode.h:786
QCString file() const
Definition docnode.h:776
QCString ref() const
Definition docnode.h:778
bool hasLinkText() const
Definition docnode.h:782
Root node of documentation tree.
Definition docnode.h:1307
Node representing a reference to a section.
Definition docnode.h:929
QCString relPath() const
Definition docnode.h:935
QCString file() const
Definition docnode.h:933
QCString anchor() const
Definition docnode.h:934
QCString ref() const
Definition docnode.h:936
bool isSubPage() const
Definition docnode.h:938
Node representing a list of section references.
Definition docnode.h:953
Node representing a normal section.
Definition docnode.h:908
int level() const
Definition docnode.h:912
QCString anchor() const
Definition docnode.h:914
const DocNodeVariant * title() const
Definition docnode.h:913
Node representing a separator.
Definition docnode.h:360
QCString chars() const
Definition docnode.h:364
Node representing a simple list.
Definition docnode.h:984
Node representing a simple list item.
Definition docnode.h:1147
const DocNodeVariant * paragraph() const
Definition docnode.h:1151
Node representing a simple section.
Definition docnode.h:1011
QCString typeString() const
Definition docnode.cpp:3008
Type type() const
Definition docnode.h:1020
const DocNodeVariant * title() const
Definition docnode.h:1027
Node representing a separator between two simple sections of the same type.
Definition docnode.h:1038
Node representing a style change.
Definition docnode.h:264
const HtmlAttribList & attribs() const
Definition docnode.h:306
QCString tagName() const
Definition docnode.h:307
Style style() const
Definition docnode.h:302
bool enable() const
Definition docnode.h:304
Node representing a special symbol.
Definition docnode.h:323
HtmlEntityMapper::SymType symbol() const
Definition docnode.h:327
Root node of a text fragment.
Definition docnode.h:1298
Node representing a simple section title.
Definition docnode.h:603
Node representing a URL (or email address)
Definition docnode.h:187
QCString url() const
Definition docnode.h:191
bool isEmail() const
Definition docnode.h:192
Node representing a verbatim, unparsed text fragment.
Definition docnode.h:371
QCString srcFile() const
Definition docnode.h:392
int srcLine() const
Definition docnode.h:393
QCString language() const
Definition docnode.h:383
bool isBlock() const
Definition docnode.h:384
bool isExample() const
Definition docnode.h:380
QCString context() const
Definition docnode.h:379
Type type() const
Definition docnode.h:377
QCString text() const
Definition docnode.h:378
QCString exampleFile() const
Definition docnode.h:381
QCString engine() const
Definition docnode.h:388
QCString relPath() const
Definition docnode.h:382
@ JavaDocLiteral
Definition docnode.h:373
Node representing a VHDL flow chart.
Definition docnode.h:743
bool hasCaption() const
Definition docnode.h:747
CodeParserInterface & getCodeParser(const QCString &langExt)
void pushHidden(bool hide)
bool popHidden()
Node representing some amount of white space.
Definition docnode.h:349
QCString chars() const
Definition docnode.h:353
Node representing a word.
Definition docnode.h:152
QCString word() const
Definition docnode.h:155
Node representing an item of a cross-referenced list.
Definition docnode.h:615
QCString anchor() const
Definition docnode.h:619
QCString key() const
Definition docnode.h:622
QCString relPath() const
Definition docnode.h:621
QCString file() const
Definition docnode.h:618
QCString title() const
Definition docnode.h:620
static IndexList * indexList
Definition doxygen.h:134
const char * unicode(int index) const
Access routine to the unicode sequence for the Emoji entity.
Definition emoji.cpp:2016
static EmojiEntityMapper & instance()
Returns the one and only instance of the Emoji entity mapper.
Definition emoji.cpp:1978
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
std::string fileName() const
Definition fileinfo.cpp:118
std::string dirPath(bool absPath=true) const
Definition fileinfo.cpp:137
static QCString convertNameToFileName()
Class representing a LaTeX formula as found in the documentation.
Definition formula.h:29
int width() const
Definition formula.h:34
int height() const
Definition formula.h:35
const Formula * findFormula(int formulaId) const
Definition formula.cpp:705
static FormulaManager & instance()
Definition formula.cpp:54
Class representing a string buffer optimized for growing.
Definition growbuf.h:28
void addChar(char c)
Definition growbuf.h:69
void addStr(const QCString &s)
Definition growbuf.h:72
char * get()
Definition growbuf.h:114
Iterator< const GrowVector, const DocNodeVariant > const_iterator
Definition growvector.h:80
bool empty() const
checks whether the container is empty
Definition growvector.h:140
Class representing a list of HTML attributes.
Definition htmlattrib.h:33
QCString toString(QCString *pAltValue=nullptr) const
Definition htmlattrib.h:49
void mergeAttribute(const QCString &optName, const QCString &optValue)
Definition htmlattrib.h:35
HtmlDocVisitor(TextStream &t, OutputCodeList &ci, const Definition *ctx, const QCString &fn=QCString())
TextStream & m_t
void writePlantUMLFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
QCString filterQuotedCdataAttr(const QCString &str)
Escape basic entities to produce a valid CDATA attribute value, assume that the outer quoting will be...
void writeDotFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
void forceStartParagraph(const DocNode &n)
void operator()(const DocWord &)
void startLink(const QCString &ref, const QCString &file, const QCString &relPath, const QCString &anchor, const QCString &tooltip="")
void visitCaption(TextStream &t, const T &n)
OutputCodeList & m_ci
void writeDiaFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
void writeMscFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine)
void visitChildren(const T &t)
void filter(const QCString &str, const bool retainNewline=false)
void forceEndParagraph(const DocNode &n)
const Definition * m_ctx
void writeObfuscatedMailAddress(const QCString &url)
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
const char * html(SymType symb, bool useInPrintf=FALSE) const
Access routine to the html code of the HTML entity.
Class representing a list of different code generators.
Definition outputlist.h:164
QCString writePlantUMLSource(const QCString &outDirArg, const QCString &fileName, const QCString &content, OutputFormat format, const QCString &engine, const QCString &srcFile, int srcLine, bool inlineCode)
Write a PlantUML compatible file.
Definition plantuml.cpp:27
OutputFormat
Plant UML output image formats.
Definition plantuml.h:44
static PlantumlManager & instance()
Definition plantuml.cpp:156
void generatePlantUMLOutput(const QCString &baseName, const QCString &outDir, OutputFormat format)
Convert a PlantUML file to an image.
Definition plantuml.cpp:127
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:407
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool startsWith(const char *s) const
Definition qcstring.h:492
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
const std::string & str() const
Definition qcstring.h:537
QCString & setNum(short n)
Definition qcstring.h:444
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
@ ExplicitSize
Definition qcstring.h:133
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159
QCString left(size_t len) const
Definition qcstring.h:214
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:229
static const MemberDef * getFlowMember()
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
#define Config_getEnum(name)
Definition config.h:35
void writeDiaGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, DiaOutputFormat format, const QCString &srcFile, int srcLine)
Definition dia.cpp:26
static constexpr auto hex
static QCString makeBaseName(const QCString &name)
static QCString makeShortName(const QCString &baseName)
std::variant< DocWord, DocLinkedWord, DocURL, DocLineBreak, DocHorRuler, DocAnchor, DocCite, DocStyleChange, DocSymbol, DocEmoji, DocWhiteSpace, DocSeparator, DocVerbatim, DocInclude, DocIncOperator, DocFormula, DocIndexEntry, DocAutoList, DocAutoListItem, DocTitle, DocXRefItem, DocImage, DocDotFile, DocMscFile, DocDiaFile, DocVhdlFlow, DocLink, DocRef, DocInternalRef, DocHRef, DocHtmlHeader, DocHtmlDescTitle, DocHtmlDescList, DocSection, DocSecRefItem, DocSecRefList, DocInternal, DocParBlock, DocSimpleList, DocHtmlList, DocSimpleSect, DocSimpleSectSep, DocParamSect, DocPara, DocParamList, DocSimpleListItem, DocHtmlListItem, DocHtmlDescData, DocHtmlCell, DocHtmlCaption, DocHtmlRow, DocHtmlTable, DocHtmlBlockQuote, DocText, DocRoot, DocHtmlDetails, DocHtmlSummary, DocPlantUmlFile > DocNodeVariant
Definition docnode.h:66
constexpr bool holds_one_of_alternatives(const DocNodeVariant &v)
returns true iff v holds one of types passed as template parameters
Definition docnode.h:1360
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1324
void writeDotImageMapFromFile(TextStream &t, const QCString &inFile, const QCString &outDir, const QCString &relPath, const QCString &baseName, const QCString &context, int graphId, const QCString &srcFile, int srcLine)
Definition dot.cpp:283
void writeDotGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, GraphOutputFormat format, const QCString &srcFile, int srcLine)
Definition dot.cpp:230
std::unique_ptr< FileDef > createFileDef(const QCString &p, const QCString &n, const QCString &ref, const QCString &dn)
Definition filedef.cpp:267
static bool isInvisibleNode(const DocNodeVariant &node)
static bool determineIfNeedsTag(const DocPara &p)
static const char 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:84
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:156
MscOutputFormat
Definition msc.h:22
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:665
Portable versions of functions that are platform dependent.
const char * qPrint(const char *s)
Definition qcstring.h:672
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
SrcLangExt
Language as given by extension.
Definition types.h:42
const char * writeUTF8Char(TextStream &t, const char *s)
Writes the UTF8 character pointed to by s to stream t and returns a pointer to the next character.
Definition utf8.cpp:197
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5549
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:4317
QCString correctURL(const QCString &url, const QCString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:6258
QCString stripPath(const QCString &s)
Definition util.cpp:5292
std::string_view word
Definition util.cpp:980
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:5841
SrcLangExt getLanguageFromCodeLang(QCString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:5567
bool found
Definition util.cpp:984
QCString getDotImageExtension()
Definition util.cpp:6617
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:6170
QCString externalLinkTarget(const bool parent)
Definition util.cpp:6022
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5591
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5243
QCString createHtmlUrl(const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
Definition util.cpp:6033
A bunch of utility functions.