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#include "md5.h"
43
44static const int NUM_HTML_LIST_TYPES = 4;
45static const char g_types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};
46enum class contexts_t
47{
48 NONE, // 0
49 STARTLI, // 1
50 STARTDD, // 2
51 ENDLI, // 3
52 ENDDD, // 4
53 STARTTD, // 5
54 ENDTD, // 6
55 INTERLI, // 7
56 INTERDD, // 8
58};
59
60static constexpr const char *contexts(contexts_t type)
61{
62 switch (type)
63 {
64 case contexts_t::NONE: return nullptr;
65 case contexts_t::STARTLI: return "startli";
66 case contexts_t::STARTDD: return "startdd";
67 case contexts_t::ENDLI: return "endli";
68 case contexts_t::ENDDD: return "enddd";
69 case contexts_t::STARTTD: return "starttd";
70 case contexts_t::ENDTD: return "endtd";
71 case contexts_t::INTERLI: return "interli";
72 case contexts_t::INTERDD: return "interdd";
73 case contexts_t::INTERTD: return "intertd";
74 default: return nullptr;
75 }
76}
77static const char *hex="0123456789ABCDEF";
78
80{
81 static int cnt = 0;
82 QCString result="a";
83 QCString cntStr;
84 result += cntStr.setNum(cnt);
85 result += "_";
86 cnt++;
87 const char *str = word.data();
88 unsigned char c = 0;
89 if (str)
90 {
91 while ((c = *str++))
92 {
93 if ((c >= 'a' && c <= 'z') || // ALPHA
94 (c >= 'A' && c <= 'Z') || // ALPHA
95 (c >= '0' && c <= '9') || // DIGIT
96 c == '-' ||
97 c == '.'
98 )
99 {
100 result += c;
101 }
102 else
103 {
104 char enc[4];
105 enc[0] = '_';
106 enc[1] = hex[(c & 0xf0) >> 4];
107 enc[2] = hex[c & 0xf];
108 enc[3] = 0;
109 result += enc;
110 }
111 }
112 }
113 return result;
114}
115
116
117
119{
120 //printf("mustBeOutsideParagraph(%s)=",docNodeName(n));
123 /* <table> */ DocHtmlTable,
124 /* <h?> */ DocSection, DocHtmlHeader,
125 /* \internal */ DocInternal,
126 /* <div> */ DocInclude, DocSecRefList,
127 /* <hr> */ DocHorRuler,
128 /* <blockquote> */ DocHtmlBlockQuote,
129 /* \parblock */ DocParBlock,
130 /* \dotfile */ DocDotFile,
131 /* \mscfile */ DocMscFile,
132 /* \diafile */ DocDiaFile,
133 /* \plantumlfile */ DocPlantUmlFile,
134 /* <details> */ DocHtmlDetails,
135 /* <summary> */ DocHtmlSummary,
136 DocIncOperator >(n))
137 {
138 return TRUE;
139 }
140 const DocVerbatim *dv = std::get_if<DocVerbatim>(&n);
141 if (dv)
142 {
143 DocVerbatim::Type t = dv->type();
145 return t!=DocVerbatim::HtmlOnly || dv->isBlock();
146 }
147 const DocStyleChange *sc = std::get_if<DocStyleChange>(&n);
148 if (sc)
149 {
150 return sc->style()==DocStyleChange::Preformatted ||
151 sc->style()==DocStyleChange::Div ||
153 }
154 const DocFormula *df = std::get_if<DocFormula>(&n);
155 if (df)
156 {
157 return !df->isInline();
158 }
159 const DocImage *di = std::get_if<DocImage>(&n);
160 if (di)
161 {
162 return !di->isInlineImage();
163 }
164 return FALSE;
165}
166
168{
169 switch (s.type())
170 {
176 return FALSE;
177 default:
178 return TRUE;
179 }
180}
181
182static bool isDocIncludeVisible(const DocInclude &s)
183{
184 switch (s.type())
185 {
192 return FALSE;
193 default:
194 return TRUE;
195 }
196}
197
199{
200 switch (s.type())
201 {
203 return FALSE;
204 default:
205 return TRUE;
206 }
207}
208
209static bool isInvisibleNode(const DocNodeVariant &node)
210{
211 //printf("isInvisibleNode(%s)\n",docNodeName(node));
212 // skip over white space
213 const DocWhiteSpace *ws = std::get_if<DocWhiteSpace>(&node);
214 if (ws) return true;
215 // skip over image nodes that are not for HTML output
216 const DocImage *di = std::get_if<DocImage>(&node);
217 if (di) return di->type()!=DocImage::Html;
218 // skip over verbatim nodes that are not visible in the HTML output
219 const DocVerbatim *dv = std::get_if<DocVerbatim>(&node);
220 if (dv) return !isDocVerbatimVisible(*dv);
221 // skip over include nodes that are not visible in the HTML output
222 const DocInclude *dinc = std::get_if<DocInclude>(&node);
223 if (dinc) return !isDocIncludeVisible(*dinc);
224 const DocIncOperator *dio = std::get_if<DocIncOperator>(&node);
225 // skip over include operator nodes that are not visible in the HTML output
226 if (dio) return !isDocIncOperatorVisible(*dio);
227 return false;
228}
229
230//-------------------------------------------------------------------------
231
233 const Definition *ctx,const QCString &fn)
234 : m_t(t), m_ci(ci), m_ctx(ctx), m_fileName(fn)
235{
236 if (ctx) m_langExt=ctx->getDefFileExtension();
237}
238
239template<class T>
241{
242 if (n.hasCaption())
243 {
244 t << "<div class=\"caption\">\n";
245 for (const auto &child : n.children())
246 {
247 std::visit(*this, child);
248 }
249 t << "</div>\n";
250 }
251}
252
253 //--------------------------------------
254 // visitor functions for leaf nodes
255 //--------------------------------------
256
258{
259 if (m_hide) return;
260 filter(w.word());
261}
262
264{
265 if (m_hide) return;
266 //printf("linked word: %s\n",qPrint(w.word()));
267 startLink(w.ref(),w.file(),w.relPath(),w.anchor(),w.tooltip());
268 filter(w.word());
269 endLink();
270}
271
273{
274 if (m_hide) return;
275 if (m_insidePre)
276 {
277 m_t << w.chars();
278 }
279 else
280 {
281 m_t << " ";
282 }
283}
284
286{
287 if (m_hide) return;
288 if (m_insideTitle &&
289 (s.symbol()==HtmlEntityMapper::Sym_Quot || s.symbol()==HtmlEntityMapper::Sym_quot)) // escape "'s inside title="..."
290 {
291 m_t << "&quot;";
292 }
293 else
294 {
295 const char *res = HtmlEntityMapper::instance().html(s.symbol());
296 if (res)
297 {
298 m_t << res;
299 }
300 else
301 {
302 err("HTML: non supported HTML-entity found: {}\n",
304 }
305 }
306}
307
309{
310 if (m_hide) return;
311 const char *res = EmojiEntityMapper::instance().unicode(s.index());
312 if (res)
313 {
314 m_t << "<span class=\"emoji\">" << res << "</span>";
315 }
316 else
317 {
318 m_t << s.name();
319 }
320}
321
323{
324 if (!Config_getBool(OBFUSCATE_EMAILS))
325 {
326 m_t << "<a href=\"mailto:" << url << "\">";
327 }
328 else
329 {
330 m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'";
331 if (!url.isEmpty())
332 {
333 const char *p = url.data();
334 uint32_t size=3;
335 while (*p)
336 {
337 m_t << "+'";
338 for (uint32_t j=0;j<size && *p;j++)
339 {
340 p = writeUTF8Char(m_t,p);
341 }
342 m_t << "'";
343 if (size==3) size=2; else size=3;
344 }
345 }
346 m_t << "; return false;\">";
347 }
348}
349
351{
352 if (m_hide) return;
353 if (u.isEmail()) // mail address
354 {
355 QCString url = u.url();
356 // obfuscate the mail address link
358 if (!Config_getBool(OBFUSCATE_EMAILS))
359 {
360 m_t << url;
361 }
362 else
363 {
364 const char *p = url.data();
365 // also obfuscate the address as shown on the web page
366 uint32_t size=5;
367 while (*p)
368 {
369 for (uint32_t j=0;j<size && *p;j++)
370 {
371 p = writeUTF8Char(m_t,p);
372 }
373 if (*p) m_t << "<span class=\"obfuscator\">.nosp@m.</span>";
374 if (size==5) size=4; else size=5;
375 }
376 }
377 m_t << "</a>";
378 }
379 else // web address
380 {
381 m_t << "<a href=\"";
382 filter(u.url());
383 m_t << "\">";
384 filter(u.url());
385 m_t << "</a>";
386 }
387}
388
390{
391 if (m_hide) return;
392 m_t << "<br "<< br.attribs().toString() << " />\n";
393}
394
396{
397 if (m_hide) return;
399 m_t << "<hr "<< hr.attribs().toString() << " />\n";
401}
402
404{
405 if (m_hide) return;
406 switch (s.style())
407 {
409 if (s.enable()) m_t << "<b" << s.attribs().toString() << ">"; else m_t << "</b>";
410 break;
412 if (s.enable()) m_t << "<s" << s.attribs().toString() << ">"; else m_t << "</s>";
413 break;
415 if (s.enable()) m_t << "<strike" << s.attribs().toString() << ">"; else m_t << "</strike>";
416 break;
418 if (s.enable()) m_t << "<del" << s.attribs().toString() << ">"; else m_t << "</del>";
419 break;
421 if (s.enable()) m_t << "<u" << s.attribs().toString() << ">"; else m_t << "</u>";
422 break;
424 if (s.enable()) m_t << "<ins" << s.attribs().toString() << ">"; else m_t << "</ins>";
425 break;
427 if (s.enable())
428 {
429 auto attribs = s.attribs();
430 if (s.tagName()=="a")
431 {
432 attribs.mergeAttribute("class","arg");
433 }
434 m_t << "<em" << attribs.toString() << ">";
435 }
436 else
437 {
438 m_t << "</em>";
439 }
440 break;
442 if (s.enable()) m_t << "<kbd" << s.attribs().toString() << ">"; else m_t << "</kbd>";
443 break;
445 if (s.enable())
446 {
447 m_t << "<span class=\"tt\"" << s.attribs().toString() << ">";
448 m_insidePre=true;
449 }
450 else
451 {
452 m_t << "</span>";
453 m_insidePre=false;
454 }
455 break;
457 if (s.enable())
458 {
459 auto attribs = s.attribs();
460 if (s.tagName()=="p")
461 {
462 attribs.mergeAttribute("class","param");
463 }
464 m_t << "<code" << attribs.toString() << ">";
465 m_insidePre=true;
466 }
467 else
468 {
469 m_insidePre=false;
470 m_t << "</code>";
471 }
472 break;
474 if (s.enable()) m_t << "<sub" << s.attribs().toString() << ">"; else m_t << "</sub>";
475 break;
477 if (s.enable()) m_t << "<sup" << s.attribs().toString() << ">"; else m_t << "</sup>";
478 break;
480 if (s.enable())
481 {
483 m_t << "<center" << s.attribs().toString() << ">";
484 }
485 else
486 {
487 m_t << "</center>";
489 }
490 break;
492 if (s.enable()) m_t << "<small" << s.attribs().toString() << ">"; else m_t << "</small>";
493 break;
495 if (s.enable()) m_t << "<cite" << s.attribs().toString() << ">"; else m_t << "</cite>";
496 break;
498 if (s.enable())
499 {
501 m_t << "<pre" << s.attribs().toString() << ">";
503 }
504 else
505 {
507 m_t << "</pre>";
509 }
510 break;
512 if (s.enable())
513 {
515 m_t << "<div" << s.attribs().toString() << ">";
516 }
517 else
518 {
519 m_t << "</div>";
521 }
522 break;
524 if (s.enable()) m_t << "<span" << s.attribs().toString() << ">"; else m_t << "</span>";
525 break;
526 }
527}
528
529///--------------------------------------------------------------------------------------
530
532{
533 if (m_hide) return;
534 QCString lang = m_langExt;
535 if (!s.language().isEmpty()) // explicit language setting
536 {
537 lang = s.language();
538 }
539 SrcLangExt langExt = getLanguageFromCodeLang(lang);
540 switch(s.type())
541 {
544 m_ci.startCodeFragment("DoxyCode");
546 s.context(),
547 s.text(),
548 langExt,
549 Config_getBool(STRIP_CODE_COMMENTS),
551 .setExample(s.isExample(), s.exampleFile())
552 .setInlineFragment(true)
554 );
555 m_ci.endCodeFragment("DoxyCode");
557 break;
560 m_t << "<pre class=\"fragment\">";
561 filter(s.text());
562 m_t << "</pre>";
564 break;
566 filter(s.text(), true);
567 break;
569 m_t << "<code class=\"JavaDocCode\">";
570 filter(s.text(), true);
571 m_t << "</code>";
572 break;
574 {
575 if (s.isBlock()) forceEndParagraph(s);
576 m_t << s.text();
577 if (s.isBlock()) forceStartParagraph(s);
578 }
579 break;
585 /* nothing */
586 break;
587
588 case DocVerbatim::Dot:
589 {
591
592 bool exists = false;
593 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_", // baseName
594 ".dot", // extension
595 s.text(), // contents
596 exists);
597 if (!fileName.isEmpty())
598 {
599 m_t << "<div class=\"dotgraph\">\n";
600 writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
601 visitCaption(m_t, s);
602 m_t << "</div>\n";
603 }
604
606 }
607 break;
608 case DocVerbatim::Msc:
609 {
611
612 bool exists = false;
613 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_", // baseName
614 ".msc", // extension
615 "msc {"+s.text()+"}", // contents
616 exists);
617 if (!fileName.isEmpty())
618 {
619 m_t << "<div class=\"mscgraph\">\n";
620 writeMscFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),!exists);
621 visitCaption(m_t, s);
622 m_t << "</div>\n";
623 }
624
626 }
627 break;
629 {
631 QCString htmlOutput = Config_getString(HTML_OUTPUT);
633 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
634 if (imgExt=="svg")
635 {
637 }
638 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
639 htmlOutput,s.exampleFile(),
640 s.text(),format,s.engine(),s.srcFile(),s.srcLine(),true);
641 for (const auto &baseName: baseNameVector)
642 {
643 m_t << "<div class=\"plantumlgraph\">\n";
644 writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
645 visitCaption(m_t, s);
646 m_t << "</div>\n";
647 }
649 }
650 break;
651 }
652}
653
655{
656 if (m_hide) return;
657 m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << anc.attribs().toString() << "></a>";
658}
659
661{
662 if (m_hide) return;
664 switch(inc.type())
665 {
668 m_ci.startCodeFragment("DoxyCode");
670 inc.context(),
671 inc.text(),
672 langExt,
673 inc.stripCodeComments(),
675 .setExample(inc.isExample(), inc.exampleFile())
676 .setInlineFragment(true)
677 .setShowLineNumbers(false)
679 );
680 m_ci.endCodeFragment("DoxyCode");
682 break;
684 {
686 m_ci.startCodeFragment("DoxyCode");
687 FileInfo cfi( inc.file().str() );
688 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
690 inc.context(),
691 inc.text(),
692 langExt,
693 inc.stripCodeComments(),
695 .setExample(inc.isExample(), inc.exampleFile())
696 .setFileDef(fd.get())
697 .setInlineFragment(true)
699 );
700 m_ci.endCodeFragment("DoxyCode");
702 }
703 break;
711 break;
713 {
714 if (inc.isBlock()) forceEndParagraph(inc);
715 m_t << inc.text();
716 if (inc.isBlock()) forceStartParagraph(inc);
717 }
718 break;
721 m_t << "<pre class=\"fragment\">";
722 filter(inc.text());
723 m_t << "</pre>";
725 break;
729 m_ci.startCodeFragment("DoxyCode");
731 inc.file(),
732 inc.blockId(),
733 inc.context(),
735 inc.trimLeft(),
737 );
738 m_ci.endCodeFragment("DoxyCode");
740 break;
741 }
742}
743
745{
746 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
747 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
748 if (op.isFirst())
749 {
751 if (!m_hide) m_ci.startCodeFragment("DoxyCode");
753 m_hide=TRUE;
754 }
756 if (locLangExt.isEmpty()) locLangExt = m_langExt;
757 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
758 if (op.type()!=DocIncOperator::Skip)
759 {
760 m_hide = popHidden();
761 if (!m_hide)
762 {
763 std::unique_ptr<FileDef> fd;
764 if (!op.includeFileName().isEmpty())
765 {
766 FileInfo cfi( op.includeFileName().str() );
767 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
768 }
769 getCodeParser(locLangExt).parseCode(
770 m_ci,
771 op.context(),
772 op.text(),
773 langExt,
776 .setExample(op.isExample(), op.exampleFile())
777 .setFileDef(fd.get())
778 .setStartLine(op.line())
781 );
782 }
784 m_hide=TRUE;
785 }
786 if (op.isLast())
787 {
788 m_hide = popHidden();
789 if (!m_hide) m_ci.endCodeFragment("DoxyCode");
791 }
792 else
793 {
794 if (!m_hide) m_t << "\n";
795 }
796}
797
799{
800 if (m_hide) return;
801 bool bDisplay = !f.isInline();
802 if (bDisplay)
803 {
805 m_t << "<p class=\"formulaDsp\">\n";
806 }
807
808 if (Config_getBool(USE_MATHJAX))
809 {
810 QCString text = f.text();
811 bool closeInline = FALSE;
812 if (!bDisplay && !text.isEmpty() && text.at(0)=='$' &&
813 text.at(text.length()-1)=='$')
814 {
815 closeInline=TRUE;
816 text = text.mid(1,text.length()-2);
817 m_t << "\\(";
818 }
819 else if (!bDisplay && !text.isEmpty())
820 {
821 closeInline=TRUE;
822 m_t << "\\(";
823 }
824 m_t << convertToHtml(text);
825 if (closeInline)
826 {
827 m_t << "\\)";
828 }
829 }
830 else
831 {
832 const Formula *formula = FormulaManager::instance().findFormula(f.id());
833
834 enum class ImageType { Light, Dark };
835 enum class Visibility { Always, Dark, Light, AutoDark, AutoLight };
836 auto writeFormula = [&](ImageType imgType,Visibility visibility) -> QCString {
837 // see https://chipcullen.com/how-to-have-dark-mode-image-that-works-with-user-choice for the design idea
838 TextStream t;
839 QCString extension = Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? ".svg":".png" ;
840 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
841 {
842 t << "<picture>";
843 t << "<source srcset=\"" << f.relPath() << f.name();
844 if (visibility==Visibility::AutoDark)
845 {
846 t << extension;
847 t << "\" media=\"(prefers-color-scheme: light)\"";
848 }
849 else // AutoLight
850 {
851 t << "_dark";
852 t << extension;
853 t << "\" media=\"(prefers-color-scheme: dark)\"";
854 }
855 t << "/>";
856 }
857 t << "<img class=\"formula";
858 t << (bDisplay ? "Dsp" : "Inl");
859 if (visibility==Visibility::Light) t << " light-mode-visible";
860 else if (visibility==Visibility::Dark) t << " dark-mode-visible";
861 t << "\" alt=\"" << filterQuotedCdataAttr(f.text()) << "\"" << " src=\"" << f.relPath() << f.name();
862 if (imgType==ImageType::Dark) t << "_dark";
863 t << extension;
864 if (formula && formula->width()!=-1)
865 {
866 t << "\" width=\"";
867 t << formula->width();
868 }
869 if (formula && formula->height()!=-1)
870 {
871 t << "\" height=\"";
872 t << formula->height();
873 }
874 t << "\"/>";
875 if (visibility==Visibility::AutoDark || visibility==Visibility::AutoLight)
876 {
877 t << "</picture>";
878 }
879 return t.str();
880 };
881
882 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
883 switch(colorStyle)
884 {
885 case HTML_COLORSTYLE_t::LIGHT:
886 m_t << writeFormula(ImageType::Light,Visibility::Always);
887 break;
888 case HTML_COLORSTYLE_t::DARK:
889 m_t << writeFormula(ImageType::Dark, Visibility::Always);
890 break;
891 case HTML_COLORSTYLE_t::AUTO_LIGHT:
892 m_t << writeFormula(ImageType::Light, Visibility::AutoLight);
893 break;
894 case HTML_COLORSTYLE_t::AUTO_DARK:
895 m_t << writeFormula(ImageType::Dark, Visibility::AutoDark);
896 break;
897 case HTML_COLORSTYLE_t::TOGGLE:
898 // write the image twice and use javascript (darkmode_toggle.js) to show only one of them
899 m_t << writeFormula(ImageType::Light,Visibility::Light);
900 m_t << writeFormula(ImageType::Dark, Visibility::Dark);
901 break;
902 }
903 }
904 if (bDisplay)
905 {
906 m_t << "\n</p>\n";
908 }
909}
910
912{
914 if (e.member())
915 {
916 anchor.prepend(e.member()->anchor()+"_");
917 }
918 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
919 //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
920 // qPrint(e.entry()),
921 // e.scope() ? qPrint(e.scope()->name()) : "<null>",
922 // e.member() ? qPrint(e.member()->name()) : "<null>"
923 // );
924 Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
925}
926
928{
929 m_t << "</dd>\n";
930 m_t << "<dd>\n";
931}
932
934{
935 if (m_hide) return;
936 auto opt = cite.option();
937 if (!cite.file().isEmpty())
938 {
939 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
940 filter(cite.getText());
941 if (!opt.noCite()) endLink();
942 }
943 else
944 {
945 m_t << "<b>";
946 if (!opt.noPar()) filter("[");
947 filter(cite.target());
948 if (!opt.noPar()) filter("]");
949 m_t << "</b>";
950 }
951}
952
953
954//--------------------------------------
955// visitor functions for compound nodes
956//--------------------------------------
957
958
960{
961 //printf("DocAutoList::visitPre\n");
962 if (m_hide) return;
964 if (l.isEnumList())
965 {
966 //
967 // Do list type based on depth:
968 // 1.
969 // a.
970 // i.
971 // A.
972 // 1. (repeat)...
973 //
974 m_t << "<ol type=\"" << g_types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
975 }
976 else
977 {
978 if (l.isCheckedList())
979 {
980 m_t << "<ul class=\"check\">";
981 }
982 else
983 {
984 m_t << "<ul>";
985 }
986 }
987 if (!l.isPreformatted()) m_t << "\n";
988 visitChildren(l);
989 if (l.isEnumList())
990 {
991 m_t << "</ol>";
992 }
993 else
994 {
995 m_t << "</ul>";
996 }
997 if (!l.isPreformatted()) m_t << "\n";
999}
1000
1002{
1003 if (m_hide) return;
1004 switch (li.itemNumber())
1005 {
1006 case DocAutoList::Unchecked: // unchecked
1007 m_t << "<li class=\"unchecked\">";
1008 break;
1009 case DocAutoList::Checked_x: // checked with x
1010 case DocAutoList::Checked_X: // checked with X
1011 m_t << "<li class=\"checked\">";
1012 break;
1013 default:
1014 m_t << "<li>";
1015 break;
1016 }
1017 visitChildren(li);
1018 m_t << "</li>";
1019 if (!li.isPreformatted()) m_t << "\n";
1020}
1021
1022template<class Node>
1023static bool holds_value(const Node *val,const DocNodeVariant &v)
1024{
1025 bool b = std::visit([&](auto &&x) {
1026 //printf("holds_value val=%s (%p) v=%s (%p)\n",
1027 // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
1028 return val==static_cast<const DocNode*>(&x);
1029 }, v);
1030 return b;
1031}
1032
1033template<class T>
1034bool isFirstChildNode(const T *parent, const DocPara &node)
1035{
1036 return !parent->children().empty() && holds_value(&node,parent->children().front());
1037}
1038
1039template<class T>
1040bool isLastChildNode(const T *parent, const DocPara &node)
1041{
1042 return !parent->children().empty() && holds_value(&node,parent->children().back());
1043}
1044
1046{
1047 const DocNodeList &nodes = parent.children();
1048 auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
1049 if (it==std::end(nodes)) return FALSE;
1050 size_t count = parent.children().size();
1051 auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=nullptr; };
1052 if (count>1 && it==std::begin(nodes)) // it points to first node
1053 {
1054 return isSeparator(std::next(it));
1055 }
1056 else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
1057 {
1058 return isSeparator(std::prev(it));
1059 }
1060 else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
1061 {
1062 return isSeparator(std::prev(it)) && isSeparator(std::next(it));
1063 }
1064 return false;
1065}
1066
1067static contexts_t getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
1068{
1070 isFirst=FALSE;
1071 isLast=FALSE;
1072 if (p.parent())
1073 {
1074 const auto parBlock = std::get_if<DocParBlock>(p.parent());
1075 if (parBlock)
1076 {
1077 // hierarchy: node N -> para -> parblock -> para
1078 // adapt return value to kind of N
1079 const DocNodeVariant *p3 = nullptr;
1080 if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
1081 {
1082 p3 = ::parent(::parent(p.parent()));
1083 }
1084 isFirst=isFirstChildNode(parBlock,p);
1085 isLast =isLastChildNode (parBlock,p);
1086 bool isLI = p3!=nullptr && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
1088 bool isTD = p3!=nullptr && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
1090 if (isFirst)
1091 {
1092 if (isLI) t=contexts_t::STARTLI; else if (isDD) t=contexts_t::STARTDD; else if (isTD) t=contexts_t::STARTTD;
1093 }
1094 if (isLast)
1095 {
1096 if (isLI) t=contexts_t::ENDLI; else if (isDD) t=contexts_t::ENDDD; else if (isTD) t=contexts_t::ENDTD;
1097 }
1098 if (!isFirst && !isLast)
1099 {
1100 if (isLI) t=contexts_t::INTERLI; else if (isDD) t=contexts_t::INTERDD; else if (isTD) t=contexts_t::INTERTD;
1101 }
1102 return t;
1103 }
1104 const auto docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
1105 if (docAutoListItem)
1106 {
1107 isFirst=isFirstChildNode(docAutoListItem,p);
1108 isLast =isLastChildNode (docAutoListItem,p);
1109 t=contexts_t::STARTLI; // not used
1110 return t;
1111 }
1112 const auto docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
1113 if (docSimpleListItem)
1114 {
1115 isFirst=TRUE;
1116 isLast =TRUE;
1117 t=contexts_t::STARTLI; // not used
1118 return t;
1119 }
1120 const auto docParamList = std::get_if<DocParamList>(p.parent());
1121 if (docParamList)
1122 {
1123 isFirst=TRUE;
1124 isLast =TRUE;
1125 t=contexts_t::STARTLI; // not used
1126 return t;
1127 }
1128 const auto docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
1129 if (docHtmlListItem)
1130 {
1131 isFirst=isFirstChildNode(docHtmlListItem,p);
1132 isLast =isLastChildNode (docHtmlListItem,p);
1133 if (isFirst) t=contexts_t::STARTLI;
1134 if (isLast) t=contexts_t::ENDLI;
1135 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1136 return t;
1137 }
1138 const auto docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
1139 if (docSecRefItem)
1140 {
1141 isFirst=isFirstChildNode(docSecRefItem,p);
1142 isLast =isLastChildNode (docSecRefItem,p);
1143 if (isFirst) t=contexts_t::STARTLI;
1144 if (isLast) t=contexts_t::ENDLI;
1145 if (!isFirst && !isLast) t = contexts_t::INTERLI;
1146 return t;
1147 }
1148 const auto docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
1149 if (docHtmlDescData)
1150 {
1151 isFirst=isFirstChildNode(docHtmlDescData,p);
1152 isLast =isLastChildNode (docHtmlDescData,p);
1153 if (isFirst) t=contexts_t::STARTDD;
1154 if (isLast) t=contexts_t::ENDDD;
1155 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1156 return t;
1157 }
1158 const auto docXRefItem = std::get_if<DocXRefItem>(p.parent());
1159 if (docXRefItem)
1160 {
1161 isFirst=isFirstChildNode(docXRefItem,p);
1162 isLast =isLastChildNode (docXRefItem,p);
1163 if (isFirst) t=contexts_t::STARTDD;
1164 if (isLast) t=contexts_t::ENDDD;
1165 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1166 return t;
1167 }
1168 const auto docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
1169 if (docSimpleSect)
1170 {
1171 isFirst=isFirstChildNode(docSimpleSect,p);
1172 isLast =isLastChildNode (docSimpleSect,p);
1173 if (isFirst) t=contexts_t::STARTDD;
1174 if (isLast) t=contexts_t::ENDDD;
1175 if (isSeparatedParagraph(*docSimpleSect,p))
1176 // if the paragraph is enclosed with separators it will
1177 // be included in <dd>..</dd> so avoid addition paragraph
1178 // markers
1179 {
1180 isFirst=isLast=TRUE;
1181 }
1182 if (!isFirst && !isLast) t = contexts_t::INTERDD;
1183 return t;
1184 }
1185 const auto docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
1186 if (docHtmlCell)
1187 {
1188 isFirst=isFirstChildNode(docHtmlCell,p);
1189 isLast =isLastChildNode (docHtmlCell,p);
1190 if (isFirst) t=contexts_t::STARTTD;
1191 if (isLast) t=contexts_t::ENDTD;
1192 if (!isFirst && !isLast) t = contexts_t::INTERTD;
1193 return t;
1194 }
1195 }
1196 return t;
1197}
1198
1199static bool determineIfNeedsTag(const DocPara &p)
1200{
1201 bool needsTag = FALSE;
1202 if (p.parent())
1203 {
1217 >(*p.parent()))
1218 {
1219 needsTag = TRUE;
1220 }
1221 else if (std::get_if<DocRoot>(p.parent()))
1222 {
1223 needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
1224 }
1225 }
1226 return needsTag;
1227}
1228
1230{
1231 if (m_hide) return;
1232
1233 //printf("> DocPara\n");
1234 //dumpDocNodeList(p.children());
1235
1236 bool needsTag = determineIfNeedsTag(p);
1237 //printf(" needsTag=%d\n",needsTag);
1238 bool needsTagBefore = needsTag;
1239 bool needsTagAfter = needsTag;
1240
1241 // if the first element of a paragraph is something that should be outside of
1242 // the paragraph (<ul>,<dl>,<table>,..) then that will already started the
1243 // paragraph and we don't need to do it here
1244 if (!p.children().empty())
1245 {
1246 auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
1247 [](const auto &node) { return !isInvisibleNode(node); });
1248 if (it!=std::end(p.children()))
1249 {
1250 const DocNodeVariant &n = *it;
1252 {
1253 needsTagBefore = FALSE;
1254 }
1255 }
1256 }
1257
1258 // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
1259 // this allows us to mark the tag with a special class so we can
1260 // fix the otherwise ugly spacing.
1261 bool isFirst = false;
1262 bool isLast = false;
1263 contexts_t t = getParagraphContext(p,isFirst,isLast);
1264 //printf("startPara first=%d last=%d\n",isFirst,isLast);
1265 if (isFirst && isLast) needsTagBefore=FALSE;
1266
1267 //printf(" needsTagBefore=%d\n",needsTagBefore);
1268 // write the paragraph tag (if needed)
1269 if (needsTagBefore)
1270 {
1271 if (contexts(t))
1272 m_t << "<p class=\"" << contexts(t) << "\"" << p.attribs().toString() << ">";
1273 else
1274 m_t << "<p" << p.attribs().toString() << ">";
1275 }
1276
1277 visitChildren(p);
1278
1279 // if the last element of a paragraph is something that should be outside of
1280 // the paragraph (<ul>,<dl>,<table>) then that will already have ended the
1281 // paragraph and we don't need to do it here
1282 if (!p.children().empty())
1283 {
1284 auto it = std::prev(std::end(p.children()));
1285 for (;;)
1286 {
1287 const DocNodeVariant &n = *it;
1288 if (!isInvisibleNode(n))
1289 {
1291 {
1292 needsTagAfter = FALSE;
1293 }
1294 // stop searching if we found a node that is visible
1295 break;
1296 }
1297 if (it==std::begin(p.children()))
1298 {
1299 // stop searching if we are at the beginning of the list
1300 break;
1301 }
1302 else
1303 {
1304 --it;
1305 }
1306 }
1307 }
1308
1309 //printf("endPara first=%d last=%d\n",isFirst,isLast);
1310 if (isFirst && isLast) needsTagAfter=FALSE;
1311
1312 //printf(" needsTagAfter=%d\n",needsTagAfter);
1313 if (needsTagAfter) m_t << "</p>\n";
1314 //printf("< DocPara\n");
1315}
1316
1318{
1319 //printf("> DocRoot\n");
1320 //dumpDocNodeList(r.children());
1321 visitChildren(r);
1322 //printf("< DocRoot\n");
1323}
1324
1326{
1327 if (m_hide) return;
1329 m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
1330 switch(s.type())
1331 {
1332 case DocSimpleSect::See:
1333 m_t << theTranslator->trSeeAlso(); break;
1335 m_t << theTranslator->trReturns(); break;
1337 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
1339 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
1341 m_t << theTranslator->trVersion(); break;
1343 m_t << theTranslator->trSince(); break;
1345 m_t << theTranslator->trDate(); break;
1347 m_t << theTranslator->trNote(); break;
1349 m_t << theTranslator->trWarning(); break;
1350 case DocSimpleSect::Pre:
1351 m_t << theTranslator->trPrecondition(); break;
1353 m_t << theTranslator->trPostcondition(); break;
1355 m_t << theTranslator->trCopyright(); break;
1357 m_t << theTranslator->trInvariant(); break;
1359 m_t << theTranslator->trRemarks(); break;
1361 m_t << theTranslator->trAttention(); break;
1363 m_t << theTranslator->trImportant(); break;
1364 case DocSimpleSect::User: break;
1365 case DocSimpleSect::Rcs: break;
1366 case DocSimpleSect::Unknown: break;
1367 }
1368
1369 if (s.title())
1370 {
1371 std::visit(*this,*s.title());
1372 }
1373 m_t << "</dt><dd>";
1374 visitChildren(s);
1375 m_t << "</dd></dl>\n";
1377}
1378
1380{
1381 if (m_hide) return;
1382 visitChildren(t);
1383}
1384
1386{
1387 if (m_hide) return;
1389 m_t << "<ul>";
1390 if (!sl.isPreformatted()) m_t << "\n";
1391 visitChildren(sl);
1392 m_t << "</ul>";
1393 if (!sl.isPreformatted()) m_t << "\n";
1395}
1396
1398{
1399 if (m_hide) return;
1400 m_t << "<li>";
1401 if (li.paragraph())
1402 {
1403 visit(*this,*li.paragraph());
1404 }
1405 m_t << "</li>";
1406 if (!li.isPreformatted()) m_t << "\n";
1407}
1408
1410{
1411 if (m_hide) return;
1413 m_t << "<h" << s.level() << " class=\"doxsection\">";
1414 m_t << "<a class=\"anchor\" id=\"" << s.anchor();
1415 m_t << "\"></a>\n";
1416 if (s.title())
1417 {
1418 std::visit(*this,*s.title());
1419 }
1420 m_t << "</h" << s.level() << ">\n";
1421 visitChildren(s);
1423}
1424
1426{
1427 if (m_hide) return;
1429 if (s.type()==DocHtmlList::Ordered)
1430 {
1431 m_t << "<ol" << s.attribs().toString();
1432 }
1433 else
1434 {
1435 m_t << "<ul" << s.attribs().toString();
1436 }
1437 m_t << ">\n";
1438 visitChildren(s);
1439 if (s.type()==DocHtmlList::Ordered)
1440 {
1441 m_t << "</ol>";
1442 }
1443 else
1444 {
1445 m_t << "</ul>";
1446 }
1447 if (!s.isPreformatted()) m_t << "\n";
1449}
1450
1452{
1453 if (m_hide) return;
1454 m_t << "<li" << i.attribs().toString() << ">";
1455 if (!i.isPreformatted()) m_t << "\n";
1456 visitChildren(i);
1457 m_t << "</li>\n";
1458}
1459
1461{
1462 if (m_hide) return;
1464 m_t << "<dl" << dl.attribs().toString() << ">\n";
1465 visitChildren(dl);
1466 m_t << "</dl>\n";
1468}
1469
1471{
1472 if (m_hide) return;
1473 m_t << "<dt" << dt.attribs().toString() << ">";
1474 visitChildren(dt);
1475 m_t << "</dt>\n";
1476}
1477
1479{
1480 if (m_hide) return;
1481 m_t << "<dd" << dd.attribs().toString() << ">";
1482 visitChildren(dd);
1483 m_t << "</dd>\n";
1484}
1485
1487{
1488 if (m_hide) return;
1489
1491
1492 if (t.caption())
1493 {
1494 QCString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
1495 if (!anc.isEmpty())
1496 {
1497 m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
1498 }
1499 }
1500
1501 QCString attrs = t.attribs().toString();
1502 if (attrs.isEmpty())
1503 {
1504 m_t << "<table class=\"doxtable\">\n";
1505 }
1506 else
1507 {
1508 m_t << "<table" << t.attribs().toString() << ">\n";
1509 }
1510 if (t.caption())
1511 {
1512 std::visit(*this,*t.caption());
1513 }
1514 visitChildren(t);
1515 m_t << "</table>\n";
1517}
1518
1520{
1521 if (m_hide) return;
1522 m_t << "<tr" << tr.attribs().toString() << ">\n";
1523 visitChildren(tr);
1524 m_t << "</tr>\n";
1525}
1526
1528{
1529 if (m_hide) return;
1530 if (c.isHeading())
1531 {
1532 m_t << "<th" << c.attribs().toString() << ">";
1533 }
1534 else
1535 {
1536 m_t << "<td" << c.attribs().toString() << ">";
1537 }
1538 visitChildren(c);
1539 if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
1540}
1541
1543{
1544 if (m_hide) return;
1545 m_t << "<caption" << c.attribs().toString() << ">";
1546 visitChildren(c);
1547 m_t << "</caption>\n";
1548}
1549
1551{
1552 if (m_hide) return;
1553 visitChildren(i);
1554}
1555
1557{
1558 if (m_hide) return;
1559 if (href.url().startsWith("mailto:"))
1560 {
1562 }
1563 else
1564 {
1565 QCString url = correctURL(href.url(),href.relPath());
1566 m_t << "<a href=\"" << convertToHtml(url) << "\""
1567 << href.attribs().toString() << ">";
1568 }
1569 visitChildren(href);
1570 m_t << "</a>";
1571}
1572
1574{
1575 if (m_hide) return;
1576 m_t << "<summary " << s.attribs().toString() << ">\n";
1577 visitChildren(s);
1578 m_t << "</summary>\n";
1579}
1580
1582{
1583 if (m_hide) return;
1585 m_t << "<details " << d.attribs().toString() << ">\n";
1586 auto summary = d.summary();
1587 if (summary)
1588 {
1589 std::visit(*this,*summary);
1590 }
1591 visitChildren(d);
1592 m_t << "</details>\n";
1594}
1595
1597{
1598 if (m_hide) return;
1599 forceEndParagraph(header);
1600 m_t << "<h" << header.level() << header.attribs().toString() << ">";
1601 visitChildren(header);
1602 m_t << "</h" << header.level() << ">\n";
1603 forceStartParagraph(header);
1604}
1605
1607{
1608 if (img.type()==DocImage::Html)
1609 {
1610 bool inlineImage = img.isInlineImage();
1611 bool typeSVG = img.isSVG();
1612 QCString url = img.url();
1613
1614 if (!inlineImage)
1615 {
1616 forceEndParagraph(img);
1617 }
1618 if (m_hide) return;
1619 QCString baseName=stripPath(img.name());
1620 if (!inlineImage) m_t << "<div class=\"image\">\n";
1621 QCString sizeAttribs;
1622 if (!img.width().isEmpty())
1623 {
1624 sizeAttribs+=" width=\""+img.width()+"\"";
1625 }
1626 if (!img.height().isEmpty()) // link to local file
1627 {
1628 sizeAttribs+=" height=\""+img.height()+"\"";
1629 }
1630 // 16 cases: url.isEmpty() | typeSVG | inlineImage | img.hasCaption()
1631
1632 HtmlAttribList attribs = img.attribs();
1633 if (typeSVG)
1634 {
1635 attribs.mergeAttribute("style","pointer-events: none;");
1636 }
1637 QCString alt;
1638 QCString attrs = attribs.toString(&alt);
1639 QCString src;
1640 if (url.isEmpty())
1641 {
1642 src = img.relPath()+img.name();
1643 }
1644 else
1645 {
1646 src = correctURL(url,img.relPath());
1647 }
1648 if (typeSVG && !inlineImage && !src.startsWith("http://") && !src.startsWith("https://"))
1649 {
1650 m_t << "<object type=\"image/svg+xml\" data=\"" << convertToHtml(src)
1651 << "\"" << sizeAttribs << attrs;
1652 if (inlineImage)
1653 {
1654 // skip closing tag
1655 }
1656 else
1657 {
1658 m_t << ">" << alt << "</object>\n";
1659 }
1660 }
1661 else
1662 {
1663 m_t << "<img src=\"" << convertToHtml(src) << "\" alt=\"" << alt << "\"" << sizeAttribs << attrs;
1664 if (inlineImage)
1665 {
1666 m_t << " class=\"inline\"";
1667 }
1668 else
1669 {
1670 m_t << "/>\n";
1671 }
1672 }
1673 if (img.hasCaption())
1674 {
1675 if (inlineImage)
1676 {
1677 m_t << " title=\"";
1678 m_insideTitle=true;
1679 }
1680 else
1681 {
1682 m_t << "<div class=\"caption\">\n";
1683 }
1684 }
1685 else if (inlineImage)
1686 {
1687 m_t << "/>";
1688 }
1689
1690 visitChildren(img);
1691
1692 if (img.hasCaption())
1693 {
1694 if (inlineImage)
1695 {
1696 m_t << "\"/>";
1697 m_insideTitle=false;
1698 }
1699 else // end <div class="caption">
1700 {
1701 m_t << "</div>";
1702 }
1703 }
1704 if (!inlineImage) // end <div class="image">
1705 {
1706 m_t << "</div>\n";
1708 }
1709 }
1710 else // other format -> skip
1711 {
1712 }
1713}
1714
1716{
1717 if (m_hide) return;
1719 bool exists = false;
1720 std::string inBuf;
1721 if (readInputFile(df.file(),inBuf))
1722 {
1723 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1724 ".dot", // extension
1725 inBuf, // contents
1726 exists);
1727 if (!fileName.isEmpty())
1728 {
1729 m_t << "<div class=\"dotgraph\">\n";
1730 writeDotFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1731 if (df.hasCaption())
1732 {
1733 m_t << "<div class=\"caption\">\n";
1734 }
1735 visitChildren(df);
1736 if (df.hasCaption())
1737 {
1738 m_t << "</div>\n";
1739 }
1740 m_t << "</div>\n";
1741 }
1742 }
1744}
1745
1747{
1748 if (m_hide) return;
1750 bool exists = false;
1751 std::string inBuf;
1752 if (readInputFile(df.file(),inBuf))
1753 {
1754 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1755 ".msc", // extension
1756 inBuf, // contents
1757 exists);
1758 if (!fileName.isEmpty())
1759 {
1760 m_t << "<div class=\"mscgraph\">\n";
1761 writeMscFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1762 if (df.hasCaption())
1763 {
1764 m_t << "<div class=\"caption\">\n";
1765 }
1766 visitChildren(df);
1767 if (df.hasCaption())
1768 {
1769 m_t << "</div>\n";
1770 }
1771 m_t << "</div>\n";
1772 }
1773 }
1775}
1776
1778{
1779 if (m_hide) return;
1781 bool exists = false;
1782 std::string inBuf;
1783 if (readInputFile(df.file(),inBuf))
1784 {
1785 auto fileName = writeFileContents(Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1786 ".dia", // extension
1787 inBuf, // contents
1788 exists);
1789 if (!fileName.isEmpty())
1790 {
1791 m_t << "<div class=\"diagraph\">\n";
1792 writeDiaFile(fileName,df.relPath(),df.context(),df.srcFile(),df.srcLine(),!exists);
1793 if (df.hasCaption())
1794 {
1795 m_t << "<div class=\"caption\">\n";
1796 }
1797 visitChildren(df);
1798 if (df.hasCaption())
1799 {
1800 m_t << "</div>\n";
1801 }
1802 m_t << "</div>\n";
1803 }
1804 }
1806}
1807
1809{
1810 if (m_hide) return;
1811 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
1813 QCString htmlOutput = Config_getString(HTML_OUTPUT);
1814 QCString imgExt = getDotImageExtension();
1815 PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
1816 if (imgExt=="svg")
1817 {
1819 }
1820 std::string inBuf;
1821 readInputFile(df.file(),inBuf);
1822 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(htmlOutput,QCString(),
1823 inBuf,format,QCString(),df.srcFile(),df.srcLine(),false);
1824 for (const auto &bName: baseNameVector)
1825 {
1826 QCString baseName=makeBaseName(bName,".pu");
1827 m_t << "<div class=\"plantumlgraph\">\n";
1828 writePlantUMLFile(baseName,df.relPath(),QCString(),df.srcFile(),df.srcLine());
1829 if (df.hasCaption())
1830 {
1831 m_t << "<div class=\"caption\">\n";
1832 }
1833 visitChildren(df);
1834 if (df.hasCaption())
1835 {
1836 m_t << "</div>\n";
1837 }
1838 m_t << "</div>\n";
1839 }
1841}
1842
1844{
1845 if (m_hide) return;
1846 startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
1847 visitChildren(lnk);
1848 endLink();
1849}
1850
1852{
1853 if (m_hide) return;
1854 if (!ref.file().isEmpty())
1855 {
1856 // when ref.isSubPage()==TRUE we use ref.file() for HTML and
1857 // ref.anchor() for LaTeX/RTF
1858 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor(), ref.targetTitle());
1859 }
1860 if (!ref.hasLinkText()) filter(ref.targetTitle());
1861 visitChildren(ref);
1862 if (!ref.file().isEmpty()) endLink();
1863 //m_t << " ";
1864}
1865
1867{
1868 if (m_hide) return;
1869 if (!ref.file().isEmpty())
1870 {
1871 m_t << "<li>";
1872 startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
1873 }
1874 visitChildren(ref);
1875 if (!ref.file().isEmpty())
1876 {
1877 endLink();
1878 m_t << "</li>\n";
1879 }
1880}
1881
1883{
1884 if (m_hide) return;
1886 m_t << "<div>\n";
1887 m_t << "<ul class=\"multicol\">\n";
1888 visitChildren(s);
1889 m_t << "</ul>\n";
1890 m_t << "</div>\n";
1892}
1893
1895{
1896 if (m_hide) return;
1898 QCString className;
1899 QCString heading;
1900 switch(s.type())
1901 {
1903 heading=theTranslator->trParameters();
1904 className="params";
1905 break;
1907 heading=theTranslator->trReturnValues();
1908 className="retval";
1909 break;
1911 heading=theTranslator->trExceptions();
1912 className="exception";
1913 break;
1915 heading=theTranslator->trTemplateParameters();
1916 className="tparams";
1917 break;
1918 default:
1919 ASSERT(0);
1920 }
1921 m_t << "<dl class=\"" << className << "\"><dt>";
1922 m_t << heading;
1923 m_t << "</dt><dd>\n";
1924 m_t << " <table class=\"" << className << "\">\n";
1925 visitChildren(s);
1926 m_t << " </table>\n";
1927 m_t << " </dd>\n";
1928 m_t << "</dl>\n";
1930}
1931
1933{
1934 if (m_hide) return;
1935 m_t << "&#160;" << s.chars() << "&#160;";
1936}
1937
1939{
1940 //printf("DocParamList::visitPre\n");
1941 if (m_hide) return;
1942 m_t << " <tr>";
1943 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
1944 if (sect && sect->hasInOutSpecifier())
1945 {
1946 m_t << "<td class=\"paramdir\">";
1948 {
1949 m_t << "[";
1950 if (pl.direction()==DocParamSect::In)
1951 {
1952 m_t << "in";
1953 }
1954 else if (pl.direction()==DocParamSect::Out)
1955 {
1956 m_t << "out";
1957 }
1958 else if (pl.direction()==DocParamSect::InOut)
1959 {
1960 m_t << "in,out";
1961 }
1962 m_t << "]";
1963 }
1964 m_t << "</td>";
1965 }
1966 if (sect && sect->hasTypeSpecifier())
1967 {
1968 m_t << "<td class=\"paramtype\">";
1969 for (const auto &type : pl.paramTypes())
1970 {
1971 std::visit(*this,type);
1972 }
1973 m_t << "</td>";
1974 }
1975 m_t << "<td class=\"paramname\">";
1976 bool first=TRUE;
1977 for (const auto &param : pl.parameters())
1978 {
1979 if (!first) m_t << ","; else first=FALSE;
1980 std::visit(*this,param);
1981 }
1982 m_t << "</td><td>";
1983 for (const auto &par : pl.paragraphs())
1984 {
1985 std::visit(*this,par);
1986 }
1987 m_t << "</td></tr>\n";
1988}
1989
1991{
1992 if (m_hide) return;
1993 if (x.title().isEmpty()) return;
1994
1996 bool anonymousEnum = x.file()=="@";
1997 if (!anonymousEnum)
1998 {
1999 QCString fn = x.file();
2001 m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
2002 << x.relPath() << fn
2003 << "#" << x.anchor() << "\">";
2004 }
2005 else
2006 {
2007 m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
2008 }
2009 filter(x.title());
2010 if (!anonymousEnum) m_t << "</a>";
2011 m_t << "</b></dt><dd>";
2012 visitChildren(x);
2013 if (x.title().isEmpty()) return;
2014 m_t << "</dd></dl>\n";
2016}
2017
2019{
2020 if (m_hide) return;
2021 startLink(QCString(),ref.file(),ref.relPath(),ref.anchor());
2022 visitChildren(ref);
2023 endLink();
2024 m_t << " ";
2025}
2026
2028{
2029 visitChildren(t);
2030}
2031
2033{
2034 if (m_hide) return;
2036 m_t << "<blockquote class=\"doxtable\"" << b.attribs().toString() << ">\n";
2037 visitChildren(b);
2038 m_t << "</blockquote>\n";
2040}
2041
2043{
2044 if (m_hide) return;
2045 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2046 {
2049 m_t << "<p>";
2050 m_t << theTranslator->trFlowchart();
2051 m_t << " ";
2052 m_t << "<a href=\"";
2053 m_t << fname;
2054 m_t << ".svg\">";
2056 m_t << "</a>";
2057 if (vf.hasCaption())
2058 {
2059 m_t << "<br />";
2060 }
2061 }
2062 visitChildren(vf);
2063 if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
2064 {
2065 m_t << "</p>";
2067 }
2068}
2069
2071{
2072 if (m_hide) return;
2073 visitChildren(pb);
2074}
2075
2076void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
2077{
2078 if (str.isEmpty()) return;
2079 const char *p=str.data();
2080 while (*p)
2081 {
2082 char c=*p++;
2083 switch(c)
2084 {
2085 case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
2086 case '<': m_t << "&lt;"; break;
2087 case '>': m_t << "&gt;"; break;
2088 case '&': m_t << "&amp;"; break;
2089 case '\\':
2090 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2091 m_t << "\\&zwj;" << *p++;
2092 else
2093 m_t << c;
2094 break;
2095 default:
2096 {
2097 uint8_t uc = static_cast<uint8_t>(c);
2098 if (uc<32 && !isspace(c)) // non-printable control characters
2099 {
2100 m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
2101 }
2102 else
2103 {
2104 m_t << c;
2105 }
2106 }
2107 break;
2108 }
2109 }
2110}
2111
2112/// Escape basic entities to produce a valid CDATA attribute value,
2113/// assume that the outer quoting will be using the double quote &quot;
2115{
2116 if (str.isEmpty()) return str;
2117 QCString result;
2118 result.reserve(str.length()+8);
2119 const char *p=str.data();
2120 while (*p)
2121 {
2122 char c=*p++;
2123 switch(c)
2124 {
2125 case '&': result+="&amp;"; break;
2126 case '"': result+="&quot;"; break;
2127 case '<': result+="&lt;"; break;
2128 case '>': result+="&gt;"; break;
2129 case '\\':
2130 if ((*p == '(') || (*p == ')') || (*p == '[') || (*p == ']'))
2131 {
2132 result+="\\&zwj;";
2133 result+=*p++;
2134 }
2135 else
2136 {
2137 result+=c;
2138 }
2139 break;
2140 default:
2141 {
2142 uint8_t uc = static_cast<uint8_t>(c);
2143 if (uc<32 && !isspace(c)) // non-printable control characters
2144 {
2145 result+="&#x24";
2146 result+=hex[uc>>4];
2147 result+=hex[uc&0xF];
2148 result+=";";
2149 }
2150 else
2151 {
2152 result+=c;
2153 }
2154 }
2155 break;
2156 }
2157 }
2158 return result;
2159}
2160
2161void HtmlDocVisitor::startLink(const QCString &ref,const QCString &file,
2162 const QCString &relPath,const QCString &anchor,
2163 const QCString &tooltip)
2164{
2165 //printf("HtmlDocVisitor: file=%s anchor=%s\n",qPrint(file),qPrint(anchor));
2166 if (!ref.isEmpty()) // link to entity imported via tag file
2167 {
2168 m_t << "<a class=\"elRef\" ";
2170 }
2171 else // local link
2172 {
2173 m_t << "<a class=\"el\" ";
2174 }
2175 m_t << "href=\"";
2176 QCString fn = file;
2178 m_t << createHtmlUrl(relPath,ref,true,
2179 m_fileName == Config_getString(HTML_OUTPUT)+"/"+fn,
2180 fn,
2181 anchor);
2182 m_t << "\"";
2183 if (!tooltip.isEmpty()) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
2184 m_t << ">";
2185}
2186
2188{
2189 m_t << "</a>";
2190}
2191
2192void HtmlDocVisitor::writeDotFile(const QCString &fileName,const QCString &relPath,
2193 const QCString &context,const QCString &srcFile,int srcLine,bool newFile)
2194{
2195 QCString baseName=makeBaseName(fileName,".dot");
2196 baseName.prepend("dot_");
2197 QCString outDir = Config_getString(HTML_OUTPUT);
2198 if (newFile) writeDotGraphFromFile(fileName,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2199 writeDotImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,-1,srcFile,srcLine,newFile);
2200}
2201
2202void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,
2203 const QCString &context,const QCString &srcFile,int srcLine, bool newFile)
2204{
2205 QCString baseName=makeBaseName(fileName,".msc");
2206 baseName.prepend("msc_");
2207 QCString outDir = Config_getString(HTML_OUTPUT);
2208 QCString imgExt = getDotImageExtension();
2209 MscOutputFormat mscFormat = imgExt=="svg" ? MscOutputFormat::SVG : MscOutputFormat::BITMAP;
2210 if (newFile) writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
2211 writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
2212}
2213
2214void HtmlDocVisitor::writeDiaFile(const QCString &fileName, const QCString &relPath,
2215 const QCString &,const QCString &srcFile,int srcLine, bool newFile)
2216{
2217 QCString baseName=makeBaseName(fileName,".dia");
2218 baseName.prepend("dia_");
2219 QCString outDir = Config_getString(HTML_OUTPUT);
2220 if (newFile) writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine);
2221
2222 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2223}
2224
2225void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString &relPath,
2226 const QCString &,const QCString &/* srcFile */,int /* srcLine */)
2227{
2228 QCString baseName=makeBaseName(fileName,".pu");
2229 QCString outDir = Config_getString(HTML_OUTPUT);
2230 QCString imgExt = getDotImageExtension();
2231 if (imgExt=="svg")
2232 {
2234 //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />\n";
2235 //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
2236 //m_t << "</iframe>\n";
2237 m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>\n";
2238 }
2239 else
2240 {
2242 m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />\n";
2243 }
2244}
2245
2246/** Returns TRUE if the child nodes in paragraph \a para until \a nodeIndex
2247 contain a style change node that is still active and that style change is one that
2248 must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
2249 See also bug746162.
2250 */
2253{
2254 //printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
2255 int styleMask=0;
2256 bool styleOutsideParagraph=FALSE;
2257 while (!styleOutsideParagraph)
2258 {
2259 const DocNodeVariant *n = &(*it);
2260 const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
2261 if (sc)
2262 {
2263 if (!sc->enable()) // remember styles that has been closed already
2264 {
2265 styleMask|=static_cast<int>(sc->style());
2266 }
2267 bool paraStyle = sc->style()==DocStyleChange::Center ||
2268 sc->style()==DocStyleChange::Div ||
2270 //printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
2271 if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
2272 paraStyle
2273 )
2274 {
2275 styleOutsideParagraph=TRUE;
2276 }
2277 }
2278 if (it!=std::begin(para->children()))
2279 {
2280 --it;
2281 }
2282 else
2283 {
2284 break;
2285 }
2286 }
2287 return styleOutsideParagraph;
2288}
2289
2290/** Used for items found inside a paragraph, which due to XHTML restrictions
2291 * have to be outside of the paragraph. This method will forcefully end
2292 * the current paragraph and forceStartParagraph() will restart it.
2293 */
2294template<class Node>
2296{
2297 const DocPara *para=std::get_if<DocPara>(n.parent());
2298 if (para)
2299 {
2300 const DocNodeList &children = para->children();
2301
2302 //printf("forceEndParagraph\n");
2303 //dumpDocNodeList(children);
2304
2305 auto it = std::find_if(std::begin(children),std::end(children),
2306 [&n](const auto &np) { return holds_value(&n,np); });
2307 if (it==std::end(children)) return;
2308 if (it==std::begin(children)) return; // first node in paragraph
2309 it = std::prev(it);
2310 bool found=false;
2311 while (!found)
2312 {
2313 found = !isInvisibleNode(*it);
2314 if (found) break;
2315 if (it!=std::begin(children))
2316 {
2317 --it;
2318 }
2319 else
2320 {
2321 break;
2322 }
2323 }
2324 if (!found) return; // first visible node in paragraph
2325 const DocNodeVariant &v = *it;
2326 if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
2327 bool styleOutsideParagraph=false;
2328 if (it!=std::begin(children))
2329 {
2330 it = std::prev(it);
2331 styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2332 }
2333 bool isFirst = false;
2334 bool isLast = false;
2335 getParagraphContext(*para,isFirst,isLast);
2336 //printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
2337 if (isFirst && isLast) return;
2338 if (styleOutsideParagraph) return;
2339
2340 //printf("adding </p>\n");
2341 m_t << "</p>";
2342 }
2343}
2344
2345/** Used for items found inside a paragraph, which due to XHTML restrictions
2346 * have to be outside of the paragraph. This method will forcefully start
2347 * the paragraph, that was previously ended by forceEndParagraph().
2348 */
2349template<class Node>
2351{
2352 //printf("> forceStartParagraph(%s)\n",docNodeName(n));
2353 const DocPara *para=nullptr;
2354 if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
2355 {
2356 const DocNodeList &children = para->children();
2357
2358 auto it = std::find_if(std::begin(children),
2359 std::end(children),
2360 [&n](const auto &np)
2361 { return holds_value(&n,np); });
2362 if (it==std::end(children)) return;
2363 bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
2364 //printf("it=%s (%p) styleOutsideParagraph=%d\n",
2365 // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
2366 if (styleOutsideParagraph) return;
2367 it = std::next(it);
2368 while (it!=std::end(children) && isInvisibleNode(*it))
2369 {
2370 ++it;
2371 }
2372 if (it!=std::end(children))
2373 {
2374 const DocNodeVariant &v = *it;
2375 if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
2376 }
2377 else
2378 {
2379 return; // only whitespace at the end!
2380 }
2381
2382 bool needsTag = true;
2383 bool isFirst = false;
2384 bool isLast = false;
2385 getParagraphContext(*para,isFirst,isLast);
2386 if (isFirst && isLast) needsTag = false;
2387 //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
2388
2389 if (needsTag) m_t << "<p>";
2390 }
2391}
2392
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:77
virtual QCString anchor() const =0
virtual QCString getDefFileExtension() const =0
virtual const QCString & name() const =0
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:972
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:1289
const HtmlAttribList & attribs() const
Definition docnode.h:1294
Node representing a HTML table caption.
Definition docnode.h:1226
const HtmlAttribList & attribs() const
Definition docnode.h:1229
Node representing a HTML table cell.
Definition docnode.h:1191
bool isHeading() const
Definition docnode.h:1198
const HtmlAttribList & attribs() const
Definition docnode.h:1203
Node representing a HTML description data.
Definition docnode.h:1179
const HtmlAttribList & attribs() const
Definition docnode.h:1182
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:1163
const HtmlAttribList & attribs() const
Definition docnode.h:1168
Node representing a HTML table row.
Definition docnode.h:1244
const HtmlAttribList & attribs() const
Definition docnode.h:1250
Node Html summary.
Definition docnode.h:844
const HtmlAttribList & attribs() const
Definition docnode.h:848
Node representing a HTML table.
Definition docnode.h:1267
const DocNodeVariant * caption() const
Definition docnode.cpp:2202
const HtmlAttribList & attribs() const
Definition docnode.h:1273
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:1320
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:1112
Node representing a parameter list.
Definition docnode.h:1123
const DocNodeList & parameters() const
Definition docnode.h:1127
const DocNodeList & paramTypes() const
Definition docnode.h:1128
DocParamSect::Direction direction() const
Definition docnode.h:1131
const DocNodeList & paragraphs() const
Definition docnode.h:1129
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:1311
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:1151
const DocNodeVariant * paragraph() const
Definition docnode.h:1155
Node representing a simple section.
Definition docnode.h:1017
QCString typeString() const
Definition docnode.cpp:3212
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:1302
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 writeMscFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine, bool newFile=true)
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 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 writeDotFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine, bool newFile=true)
void visitChildren(const T &t)
void filter(const QCString &str, const bool retainNewline=false)
void forceEndParagraph(const DocNode &n)
void writeDiaFile(const QCString &fileName, const QCString &relPath, const QCString &context, const QCString &srcFile, int srcLine, bool newFile=true)
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
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
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
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
constexpr bool holds_one_of_alternatives(const DocNodeVariant &v)
returns true iff v holds one of types passed as template parameters
Definition docnode.h:1364
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:1328
void writeDotGraphFromFile(const QCString &inFile, const QCString &outDir, const QCString &outFile, GraphOutputFormat format, const QCString &srcFile, int srcLine)
Definition dot.cpp:230
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, bool newFile)
Definition dot.cpp:284
std::unique_ptr< FileDef > createFileDef(const QCString &p, const QCString &n, const QCString &ref, const QCString &dn)
Definition filedef.cpp:269
static bool isInvisibleNode(const DocNodeVariant &node)
static bool determineIfNeedsTag(const DocPara &p)
static const char g_types[][NUM_HTML_LIST_TYPES]
static constexpr const char * contexts(contexts_t type)
contexts_t
bool isFirstChildNode(const T *parent, const DocPara &node)
static const int NUM_HTML_LIST_TYPES
static QCString convertIndexWordToAnchor(const QCString &word)
static contexts_t getParagraphContext(const DocPara &p, bool &isFirst, bool &isLast)
static bool mustBeOutsideParagraph(const DocNodeVariant &n)
static bool isDocVerbatimVisible(const DocVerbatim &s)
static bool insideStyleChangeThatIsOutsideParagraph(const DocPara *para, DocNodeList::const_iterator it)
Returns TRUE if the child nodes in paragraph para until nodeIndex contain a style change node that is...
static bool holds_value(const Node *val, const DocNodeVariant &v)
static bool isDocIncOperatorVisible(const DocIncOperator &s)
bool isSeparatedParagraph(const DocSimpleSect &parent, const DocPara &par)
bool isLastChildNode(const T *parent, const DocPara &node)
static bool isDocIncludeVisible(const DocInclude &s)
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
Portable versions of functions that are platform dependent.
#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
QCString writeFileContents(const QCString &baseName, const QCString &extension, const QCString &content, bool &exists)
Thread-safe function to write a string to a file.
Definition util.cpp:6959
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5191
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:3944
QCString correctURL(const QCString &url, const QCString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:5925
QCString stripPath(const QCString &s)
Definition util.cpp:4929
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:5530
SrcLangExt getLanguageFromCodeLang(QCString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:5209
QCString getDotImageExtension()
Definition util.cpp:6289
QCString makeBaseName(const QCString &name, const QCString &ext)
Definition util.cpp:4945
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:5857
QCString externalLinkTarget(const bool parent)
Definition util.cpp:5705
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5233
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:4902
QCString createHtmlUrl(const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
Definition util.cpp:5716
A bunch of utility functions.