summaryrefslogtreecommitdiffstats
path: root/src/htmldocvisitor.cpp
diff options
context:
space:
mode:
authorCharles.Lee <cheoljoo@gmail.com>2018-12-24 00:58:06 (GMT)
committerCharles.Lee <cheoljoo@gmail.com>2018-12-24 00:58:06 (GMT)
commitb35d4dbc124ec494b451b79a19218a564a98af53 (patch)
tree5ef64eab0723ebf9d7653b463ba3f1c05fb5cfca /src/htmldocvisitor.cpp
parentf73c9301a711baa68ef2a38acb279b421e3ca2b0 (diff)
parentbabfc33370e28963f890a5f05355aa7778700ca6 (diff)
downloadDoxygen-b35d4dbc124ec494b451b79a19218a564a98af53.zip
Doxygen-b35d4dbc124ec494b451b79a19218a564a98af53.tar.gz
Doxygen-b35d4dbc124ec494b451b79a19218a564a98af53.tar.bz2
merge
Diffstat (limited to 'src/htmldocvisitor.cpp')
-rw-r--r--src/htmldocvisitor.cpp281
1 files changed, 211 insertions, 70 deletions
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index 48f3b91..ea37cea 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -34,10 +34,36 @@
#include "filedef.h"
#include "memberdef.h"
#include "htmlentity.h"
+#include "emoji.h"
#include "plantuml.h"
static const int NUM_HTML_LIST_TYPES = 4;
static const char types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};
+enum contexts_t
+{
+ NONE, // 0
+ STARTLI, // 1
+ STARTDD, // 2
+ ENDLI, // 3
+ ENDDD, // 4
+ STARTTD, // 5
+ ENDTD, // 6
+ INTERLI, // 7
+ INTERDD, // 8
+ INTERTD // 9
+};
+static const char *contexts[10] =
+{ "", // 0
+ "startli", // 1
+ "startdd", // 2
+ "endli", // 3
+ "enddd", // 4
+ "starttd", // 5
+ "endtd", // 6
+ "interli", // 7
+ "interdd", // 8
+ "intertd" // 9
+};
static QCString convertIndexWordToAnchor(const QString &word)
{
@@ -108,6 +134,7 @@ static bool mustBeOutsideParagraph(DocNode *n)
case DocNode::Kind_HtmlBlockQuote:
/* \parblock */
case DocNode::Kind_ParBlock:
+ case DocNode::Kind_IncOperator:
return TRUE;
case DocNode::Kind_Verbatim:
{
@@ -126,7 +153,59 @@ static bool mustBeOutsideParagraph(DocNode *n)
return FALSE;
}
-static QString htmlAttribsToString(const HtmlAttribList &attribs, const bool img_tag = FALSE)
+static bool isDocVerbatimVisible(DocVerbatim *s)
+{
+ switch(s->type())
+ {
+ case DocVerbatim::ManOnly:
+ case DocVerbatim::LatexOnly:
+ case DocVerbatim::XmlOnly:
+ case DocVerbatim::RtfOnly:
+ case DocVerbatim::DocbookOnly:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static bool isDocIncludeVisible(DocInclude *s)
+{
+ switch (s->type())
+ {
+ case DocInclude::DontInclude:
+ case DocInclude::LatexInclude:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static bool isDocIncOperatorVisible(DocIncOperator *s)
+{
+ switch (s->type())
+ {
+ case DocIncOperator::Skip:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static bool isInvisibleNode(DocNode *node)
+{
+ return (node->kind()==DocNode::Kind_WhiteSpace)
+ || // skip over image nodes that are not for HTML output
+ (node->kind()==DocNode::Kind_Image && ((DocImage*)node)->type()!=DocImage::Html)
+ || // skip over verbatim nodes that are not visible in the HTML output
+ (node->kind()==DocNode::Kind_Verbatim && !isDocVerbatimVisible((DocVerbatim*)node))
+ || // skip over include nodes that are not visible in the HTML output
+ (node->kind()==DocNode::Kind_Include && !isDocIncludeVisible((DocInclude*)node))
+ || // skip over include operator nodes that are not visible in the HTML output
+ (node->kind()==DocNode::Kind_IncOperator && !isDocIncOperatorVisible((DocIncOperator*)node))
+ ;
+}
+
+static QString htmlAttribsToString(const HtmlAttribList &attribs, bool img_tag = FALSE)
{
QString result;
HtmlAttribListIterator li(attribs);
@@ -209,6 +288,20 @@ void HtmlDocVisitor::visit(DocSymbol *s)
}
}
+void HtmlDocVisitor::visit(DocEmoji *s)
+{
+ if (m_hide) return;
+ const char *res = EmojiEntityMapper::instance()->unicode(s->index());
+ if (res)
+ {
+ m_t << res;
+ }
+ else
+ {
+ m_t << s->name();
+ }
+}
+
void HtmlDocVisitor::writeObfuscatedMailAddress(const QCString &url)
{
m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'";
@@ -363,7 +456,6 @@ static void visitCaption(HtmlDocVisitor *parent, QList<DocNode> children)
for (cli.toFirst();(n=cli.current());++cli) n->accept(parent);
}
-
void HtmlDocVisitor::visit(DocVerbatim *s)
{
if (m_hide) return;
@@ -403,10 +495,12 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
m_t << "</pre>" /*<< PREFRAG_END*/;
forceStartParagraph(s);
break;
- case DocVerbatim::HtmlOnly:
- if (s->isBlock()) forceEndParagraph(s);
- m_t << s->text();
- if (s->isBlock()) forceStartParagraph(s);
+ case DocVerbatim::HtmlOnly:
+ {
+ if (s->isBlock()) forceEndParagraph(s);
+ m_t << s->text();
+ if (s->isBlock()) forceStartParagraph(s);
+ }
break;
case DocVerbatim::ManOnly:
case DocVerbatim::LatexOnly:
@@ -567,8 +661,12 @@ void HtmlDocVisitor::visit(DocInclude *inc)
break;
case DocInclude::DontInclude:
break;
- case DocInclude::HtmlInclude:
- m_t << inc->text();
+ case DocInclude::HtmlInclude:
+ {
+ if (inc->isBlock()) forceEndParagraph(inc);
+ m_t << inc->text();
+ if (inc->isBlock()) forceStartParagraph(inc);
+ }
break;
case DocInclude::LatexInclude:
break;
@@ -641,7 +739,7 @@ void HtmlDocVisitor::visit(DocIncOperator *op)
// op->type(),op->isFirst(),op->isLast(),op->text().data());
if (op->isFirst())
{
- forceStartParagraph(op);
+ forceEndParagraph(op);
if (!m_hide) m_t << PREFRAG_START;
pushEnabled();
m_hide=TRUE;
@@ -896,24 +994,24 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast)
}
isFirst=isFirstChildNode((DocParBlock*)p->parent(),p);
isLast =isLastChildNode ((DocParBlock*)p->parent(),p);
- t=0;
+ t=NONE;
if (isFirst)
{
if (kind==DocNode::Kind_HtmlListItem ||
kind==DocNode::Kind_SecRefItem)
{
- t=1;
+ t=STARTLI;
}
else if (kind==DocNode::Kind_HtmlDescData ||
kind==DocNode::Kind_XRefItem ||
kind==DocNode::Kind_SimpleSect)
{
- t=2;
+ t=STARTDD;
}
else if (kind==DocNode::Kind_HtmlCell ||
kind==DocNode::Kind_ParamList)
{
- t=5;
+ t=STARTTD;
}
}
if (isLast)
@@ -921,18 +1019,37 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast)
if (kind==DocNode::Kind_HtmlListItem ||
kind==DocNode::Kind_SecRefItem)
{
- t=3;
+ t=ENDLI;
+ }
+ else if (kind==DocNode::Kind_HtmlDescData ||
+ kind==DocNode::Kind_XRefItem ||
+ kind==DocNode::Kind_SimpleSect)
+ {
+ t=ENDDD;
+ }
+ else if (kind==DocNode::Kind_HtmlCell ||
+ kind==DocNode::Kind_ParamList)
+ {
+ t=ENDTD;
+ }
+ }
+ if (!isFirst && !isLast)
+ {
+ if (kind==DocNode::Kind_HtmlListItem ||
+ kind==DocNode::Kind_SecRefItem)
+ {
+ t=INTERLI;
}
else if (kind==DocNode::Kind_HtmlDescData ||
kind==DocNode::Kind_XRefItem ||
kind==DocNode::Kind_SimpleSect)
{
- t=4;
+ t=INTERDD;
}
else if (kind==DocNode::Kind_HtmlCell ||
kind==DocNode::Kind_ParamList)
{
- t=6;
+ t=INTERTD;
}
}
break;
@@ -940,47 +1057,51 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast)
case DocNode::Kind_AutoListItem:
isFirst=isFirstChildNode((DocAutoListItem*)p->parent(),p);
isLast =isLastChildNode ((DocAutoListItem*)p->parent(),p);
- t=1; // not used
+ t=STARTLI; // not used
break;
case DocNode::Kind_SimpleListItem:
isFirst=TRUE;
isLast =TRUE;
- t=1; // not used
+ t=STARTLI; // not used
break;
case DocNode::Kind_ParamList:
isFirst=TRUE;
isLast =TRUE;
- t=1; // not used
+ t=STARTLI; // not used
break;
case DocNode::Kind_HtmlListItem:
isFirst=isFirstChildNode((DocHtmlListItem*)p->parent(),p);
isLast =isLastChildNode ((DocHtmlListItem*)p->parent(),p);
- if (isFirst) t=1;
- if (isLast) t=3;
+ if (isFirst) t=STARTLI;
+ if (isLast) t=ENDLI;
+ if (!isFirst && !isLast) t = INTERLI;
break;
case DocNode::Kind_SecRefItem:
isFirst=isFirstChildNode((DocSecRefItem*)p->parent(),p);
isLast =isLastChildNode ((DocSecRefItem*)p->parent(),p);
- if (isFirst) t=1;
- if (isLast) t=3;
+ if (isFirst) t=STARTLI;
+ if (isLast) t=ENDLI;
+ if (!isFirst && !isLast) t = INTERLI;
break;
case DocNode::Kind_HtmlDescData:
isFirst=isFirstChildNode((DocHtmlDescData*)p->parent(),p);
isLast =isLastChildNode ((DocHtmlDescData*)p->parent(),p);
- if (isFirst) t=2;
- if (isLast) t=4;
+ if (isFirst) t=STARTDD;
+ if (isLast) t=ENDDD;
+ if (!isFirst && !isLast) t = INTERDD;
break;
case DocNode::Kind_XRefItem:
isFirst=isFirstChildNode((DocXRefItem*)p->parent(),p);
isLast =isLastChildNode ((DocXRefItem*)p->parent(),p);
- if (isFirst) t=2;
- if (isLast) t=4;
+ if (isFirst) t=STARTDD;
+ if (isLast) t=ENDDD;
+ if (!isFirst && !isLast) t = INTERDD;
break;
case DocNode::Kind_SimpleSect:
isFirst=isFirstChildNode((DocSimpleSect*)p->parent(),p);
isLast =isLastChildNode ((DocSimpleSect*)p->parent(),p);
- if (isFirst) t=2;
- if (isLast) t=4;
+ if (isFirst) t=STARTDD;
+ if (isLast) t=ENDDD;
if (isSeparatedParagraph((DocSimpleSect*)p->parent(),p))
// if the paragraph is enclosed with separators it will
// be included in <dd>..</dd> so avoid addition paragraph
@@ -988,12 +1109,14 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast)
{
isFirst=isLast=TRUE;
}
+ if (!isFirst && !isLast) t = INTERDD;
break;
case DocNode::Kind_HtmlCell:
isFirst=isFirstChildNode((DocHtmlCell*)p->parent(),p);
isLast =isLastChildNode ((DocHtmlCell*)p->parent(),p);
- if (isFirst) t=5;
- if (isLast) t=6;
+ if (isFirst) t=STARTTD;
+ if (isLast) t=ENDTD;
+ if (!isFirst && !isLast) t = INTERTD;
break;
default:
break;
@@ -1045,8 +1168,7 @@ void HtmlDocVisitor::visitPre(DocPara *p)
uint nodeIndex = 0;
if (p && nodeIndex<p->children().count())
{
- while (nodeIndex<p->children().count() &&
- p->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace)
+ while (nodeIndex<p->children().count() && isInvisibleNode(p->children().at(nodeIndex)))
{
nodeIndex++;
}
@@ -1061,19 +1183,10 @@ void HtmlDocVisitor::visitPre(DocPara *p)
}
}
- // check if this paragraph is the first or last child of a <li> or <dd>.
+ // check if this paragraph is the first or last or intermediate child of a <li> or <dd>.
// this allows us to mark the tag with a special class so we can
// fix the otherwise ugly spacing.
int t;
- static const char *contexts[7] =
- { "", // 0
- "startli", // 1
- "startdd", // 2
- "endli", // 3
- "enddd", // 4
- "starttd", // 5
- "endtd" // 6
- };
bool isFirst;
bool isLast;
t = getParagraphContext(p,isFirst,isLast);
@@ -1123,7 +1236,7 @@ void HtmlDocVisitor::visitPost(DocPara *p)
int nodeIndex = p->children().count()-1;
if (nodeIndex>=0)
{
- while (nodeIndex>=0 && p->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace)
+ while (nodeIndex>=0 && isInvisibleNode(p->children().at(nodeIndex)))
{
nodeIndex--;
}
@@ -1494,7 +1607,22 @@ void HtmlDocVisitor::visitPre(DocImage *img)
{
if (img->type()==DocImage::Html)
{
- forceEndParagraph(img);
+ bool inlineImage = img->isInlineImage();
+ bool typeSVG = FALSE;
+
+ QCString url = img->url();
+ if (url.isEmpty())
+ {
+ typeSVG = (img->name().right(4)==".svg");
+ }
+ else
+ {
+ typeSVG = (url.right(4)==".svg");
+ }
+ if (!inlineImage)
+ {
+ forceEndParagraph(img);
+ }
if (m_hide) return;
QString baseName=img->name();
int i;
@@ -1502,20 +1630,19 @@ void HtmlDocVisitor::visitPre(DocImage *img)
{
baseName=baseName.right(baseName.length()-i-1);
}
- m_t << "<div class=\"image\">" << endl;
- QCString url = img->url();
+ if (!inlineImage) m_t << "<div class=\"image\">" << endl;
QCString sizeAttribs;
if (!img->width().isEmpty())
{
sizeAttribs+=" width=\""+img->width()+"\"";
}
- if (!img->height().isEmpty())
+ if (!img->height().isEmpty()) // link to local file
{
sizeAttribs+=" height=\""+img->height()+"\"";
}
if (url.isEmpty())
{
- if (img->name().right(4)==".svg")
+ if (typeSVG)
{
m_t << "<object type=\"image/svg+xml\" data=\"" << img->relPath() << img->name()
<< "\"" << sizeAttribs << htmlAttribsToString(img->attribs()) << ">" << baseName
@@ -1525,27 +1652,39 @@ void HtmlDocVisitor::visitPre(DocImage *img)
{
m_t << "<img src=\"" << img->relPath() << img->name() << "\" alt=\""
<< baseName << "\"" << sizeAttribs << htmlAttribsToString(img->attribs())
- << "/>" << endl;
+ << (inlineImage ? " class=\"inline\"" : "/>\n");
}
}
- else
+ else // link to URL
{
- if (url.right(4)==".svg")
+ if (typeSVG)
{
m_t << "<object type=\"image/svg+xml\" data=\"" << correctURL(url,img->relPath())
- << "\"" << sizeAttribs << htmlAttribsToString(img->attribs()) << "></object>" << endl;
+ << "\"" << sizeAttribs << htmlAttribsToString(img->attribs())
+ << "></object>" << endl;
}
else
{
m_t << "<img src=\"" << correctURL(url,img->relPath()) << "\""
<< sizeAttribs << htmlAttribsToString(img->attribs(), TRUE)
- << "/>" << endl;
+ << (inlineImage ? " class=\"inline\"" : "/>\n");
}
}
if (img->hasCaption())
{
- m_t << "<div class=\"caption\">" << endl;
- m_t << getHtmlDirEmbedingChar(getTextDirByConfig(img));
+ if (inlineImage)
+ {
+ m_t << " title=\"";
+ }
+ else
+ {
+ m_t << "<div class=\"caption\">" << endl;
+ m_t << getHtmlDirEmbedingChar(getTextDirByConfig(img));
+ }
+ }
+ else if (inlineImage)
+ {
+ m_t << "/>" << endl;
}
}
else // other format -> skip
@@ -1555,17 +1694,24 @@ void HtmlDocVisitor::visitPre(DocImage *img)
}
}
-void HtmlDocVisitor::visitPost(DocImage *img)
+void HtmlDocVisitor::visitPost(DocImage *img)
{
if (img->type()==DocImage::Html)
{
if (m_hide) return;
+ bool inlineImage = img->isInlineImage();
if (img->hasCaption())
{
- m_t << "</div>";
+ if (inlineImage)
+ m_t << "\"/>\n ";
+ else
+ m_t << "</div>";
+ }
+ if (!inlineImage)
+ {
+ m_t << "</div>" << endl;
+ forceStartParagraph(img);
}
- m_t << "</div>" << endl;
- forceStartParagraph(img);
}
else // other format
{
@@ -2193,16 +2339,13 @@ void HtmlDocVisitor::forceEndParagraph(DocNode *n)
int nodeIndex = para->children().findRef(n);
nodeIndex--;
if (nodeIndex<0) return; // first node
- while (nodeIndex>=0 &&
- para->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace
- )
+ while (nodeIndex>=0 && isInvisibleNode(para->children().at(nodeIndex)))
{
- nodeIndex--;
+ nodeIndex--;
}
if (nodeIndex>=0)
{
DocNode *n = para->children().at(nodeIndex);
- //printf("n=%p kind=%d outside=%d\n",n,n->kind(),mustBeOutsideParagraph(n));
if (mustBeOutsideParagraph(n)) return;
}
nodeIndex--;
@@ -2234,16 +2377,14 @@ void HtmlDocVisitor::forceStartParagraph(DocNode *n)
if (styleOutsideParagraph) return;
nodeIndex++;
if (nodeIndex==numNodes) return; // last node
- while (nodeIndex<numNodes &&
- para->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace
- )
+ while (nodeIndex<numNodes && isInvisibleNode(para->children().at(nodeIndex)))
{
nodeIndex++;
}
if (nodeIndex<numNodes)
{
DocNode *n = para->children().at(nodeIndex);
- if (mustBeOutsideParagraph(n)) return;
+ if (mustBeOutsideParagraph(n)) return; // next element also outside paragraph
}
else
{
@@ -2254,8 +2395,8 @@ void HtmlDocVisitor::forceStartParagraph(DocNode *n)
bool isFirst;
bool isLast;
getParagraphContext(para,isFirst,isLast);
- //printf("forceStart first=%d last=%d\n",isFirst,isLast);
if (isFirst && isLast) needsTag = FALSE;
+ //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
if (needsTag)
m_t << "<p" << getDirHtmlClassOfNode(getTextDirByConfig(para, nodeIndex)) << ">";