diff options
author | Charles.Lee <cheoljoo@gmail.com> | 2018-12-24 00:58:06 (GMT) |
---|---|---|
committer | Charles.Lee <cheoljoo@gmail.com> | 2018-12-24 00:58:06 (GMT) |
commit | b35d4dbc124ec494b451b79a19218a564a98af53 (patch) | |
tree | 5ef64eab0723ebf9d7653b463ba3f1c05fb5cfca /src/htmldocvisitor.cpp | |
parent | f73c9301a711baa68ef2a38acb279b421e3ca2b0 (diff) | |
parent | babfc33370e28963f890a5f05355aa7778700ca6 (diff) | |
download | Doxygen-b35d4dbc124ec494b451b79a19218a564a98af53.zip Doxygen-b35d4dbc124ec494b451b79a19218a564a98af53.tar.gz Doxygen-b35d4dbc124ec494b451b79a19218a564a98af53.tar.bz2 |
merge
Diffstat (limited to 'src/htmldocvisitor.cpp')
-rw-r--r-- | src/htmldocvisitor.cpp | 281 |
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)) << ">"; |