Skip to content

Commit 7a10ea4

Browse files
committed
issue #11579 HTML-tables in markdown files with empty lines between the tags not properly rendered
1 parent 18b0d05 commit 7a10ea4

File tree

4 files changed

+91
-14
lines changed

4 files changed

+91
-14
lines changed

doc/htmlcmds.dox

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ of a HTML tag are passed on to the HTML output only
3939
<tr><td valign="top">\startendhtmltag{CENTER}</td><td valign="top">Starts and ends a section of centered text.</td></tr>
4040
<tr><td valign="top">\startendhtmltag{CAPTION}</td><td valign="top">Starts and ends a caption. Use within a table only.</td></tr>
4141
<tr><td valign="top">\startendhtmltag{CITE}</td><td valign="top">Starts and ends a section of text displayed in a font specific for citations.</td></tr>
42-
<tr><td valign="top">\startendhtmltag{CODE}</td><td valign="top">Starts and ends a piece of text displayed in a typewriter font.</td></tr>
42+
<tr><td valign="top">\startendhtmltag{CODE}</td><td valign="top">Starts and ends a piece of text displayed in a typewriter font.
4343
Note that only for C# code, this command is equivalent to
4444
\ref cmdcode "\\code" (see \ref xmltag_code "\<code\>").</td></tr>
4545
<tr><td valign="top">\startendhtmltag{DD}</td><td valign="top">Starts and ends an item description.</td></tr>
@@ -53,7 +53,7 @@ of a HTML tag are passed on to the HTML output only
5353
<tr><td valign="top">\startalign\anchor htmltag_HR \addindex "\<HR\>"\endalign<tt>\<HR\></tt></td><td valign="top">Writes a horizontal ruler.</td></tr>
5454
<tr><td valign="top">\startendhtmltag{H1}</td><td valign="top">Starts and ends an unnumbered section.</td></tr>
5555
<tr><td valign="top">\startendhtmltag{H2}</td><td valign="top">Starts and ends an unnumbered subsection.</td></tr>
56-
<tr><td valign="top">\startendhtmltag{H3}</td><td valign="top">Starts and ends an unnumbered subsubsection.</td></tr></td></tr>
56+
<tr><td valign="top">\startendhtmltag{H3}</td><td valign="top">Starts and ends an unnumbered subsubsection.</td></tr>
5757
<tr><td valign="top">\startendhtmltag{H4}</td><td valign="top">Starts and ends an unnumbered subsubsection.</td></tr>
5858
<tr><td valign="top">\startendhtmltag{H5}</td><td valign="top">Starts and ends an unnumbered subsubsection.</td></tr>
5959
<tr><td valign="top">\startendhtmltag{H6}</td><td valign="top">Starts and ends an unnumbered subsubsection.</td></tr>

src/docnode.cpp

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,53 @@ Token DocHtmlRow::parse()
19911991
isFirst=FALSE;
19921992
retval=cell->parse();
19931993
isHeading = retval.is(TokenRetval::RetVal_TableHCell);
1994+
//printf("DocHtmlRow:retval=%s\n",retval.to_string());
1995+
if (retval.is(TokenRetval::RetVal_EndTableCell))
1996+
{
1997+
// get next token
1998+
retval=parser()->tokenizer.lex();
1999+
// skip whitespace after </td> or </th>
2000+
while (retval.is_any_of(TokenRetval::TK_WHITESPACE,TokenRetval::TK_NEWPARA)) retval=parser()->tokenizer.lex();
2001+
//printf("DocHtmlRow:retval= next=%s name=%s endTag=%d\n",retval.to_string(),qPrint(parser()->context.token->name),parser()->context.token->endTag);
2002+
HtmlTagType tagId=Mappers::htmlTagMapper->map(parser()->context.token->name);
2003+
if (tok.is(TokenRetval::TK_HTMLTAG))
2004+
{
2005+
if ((tagId==HtmlTagType::HTML_TD || tagId==HtmlTagType::HTML_TH) &&
2006+
!parser()->context.token->endTag) // found new <td> or <td> tag
2007+
{
2008+
retval = Token::make_RetVal_TableCell();
2009+
isHeading = tagId==HtmlTagType::HTML_TH;
2010+
}
2011+
else if (tagId==HtmlTagType::HTML_TR)
2012+
{
2013+
if (parser()->context.token->endTag) // found </tr> tag
2014+
{
2015+
retval = Token::make_RetVal_EndTableRow();
2016+
}
2017+
else // found <tr> tag
2018+
{
2019+
retval = Token::make_RetVal_TableRow();
2020+
}
2021+
}
2022+
else if (tagId==HtmlTagType::HTML_TABLE && parser()->context.token->endTag) // found </table>
2023+
{
2024+
retval = Token::make_RetVal_EndTable();
2025+
}
2026+
else // found some other tag
2027+
{
2028+
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"expected <td>, <th> or <tr> tag but "
2029+
"found <{}> instead!",parser()->context.token->name);
2030+
parser()->tokenizer.pushBackHtmlTag(parser()->context.token->name);
2031+
goto endrow;
2032+
}
2033+
}
2034+
else // token other than html token
2035+
{
2036+
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"expected <td>, <th> or <tr> tag but found {} token instead!",
2037+
tok.to_string());
2038+
goto endrow;
2039+
}
2040+
}
19942041
}
19952042
while (retval.is_any_of(TokenRetval::RetVal_TableCell,TokenRetval::RetVal_TableHCell));
19962043
cell->markLast(TRUE);
@@ -2150,6 +2197,31 @@ Token DocHtmlTable::parse()
21502197
{
21512198
children().append<DocHtmlRow>(parser(),thisVariant(),parser()->context.token->attribs);
21522199
retval = children().get_last<DocHtmlRow>()->parse();
2200+
//printf("DocHtmlTable::retval=%s\n",retval.to_string());
2201+
if (retval.is(TokenRetval::RetVal_EndTableRow))
2202+
{
2203+
// get next token
2204+
retval=parser()->tokenizer.lex();
2205+
// skip whitespace after </td> or </th>
2206+
while (retval.is_any_of(TokenRetval::TK_WHITESPACE,TokenRetval::TK_NEWPARA)) retval=parser()->tokenizer.lex();
2207+
//printf("DocHtmlTable::retval= next=%s name=%s endTag=%d\n",retval.to_string(),qPrint(parser()->context.token->name),parser()->context.token->endTag);
2208+
HtmlTagType tagId=Mappers::htmlTagMapper->map(parser()->context.token->name);
2209+
if (tagId==HtmlTagType::HTML_TR && !parser()->context.token->endTag)
2210+
{
2211+
retval = Token::make_RetVal_TableRow();
2212+
}
2213+
else if (tagId==HtmlTagType::HTML_TABLE && parser()->context.token->endTag)
2214+
{
2215+
retval = Token::make_RetVal_EndTable();
2216+
}
2217+
else // found some other tag
2218+
{
2219+
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"expected <tr> or </table> tag but "
2220+
"found token {} instead!",retval.to_string());
2221+
retval=Token::make_RetVal_OK();
2222+
break;
2223+
}
2224+
}
21532225
}
21542226

21552227
computeTableGrid();
@@ -5431,13 +5503,13 @@ Token DocPara::handleHtmlEndTag(const QCString &tagName)
54315503
retval = Token::make_RetVal_EndTable();
54325504
break;
54335505
case HtmlTagType::HTML_TR:
5434-
// ignore </tr> tag
5506+
retval = Token::make_RetVal_EndTableRow();
54355507
break;
54365508
case HtmlTagType::HTML_TD:
5437-
// ignore </td> tag
5509+
retval = Token::make_RetVal_EndTableCell();
54385510
break;
54395511
case HtmlTagType::HTML_TH:
5440-
// ignore </th> tag
5512+
retval = Token::make_RetVal_EndTableCell();
54415513
break;
54425514
case HtmlTagType::HTML_THEAD:
54435515
case HtmlTagType::HTML_TBODY:

src/doctokenizer.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,17 @@
6060
TKSPEC(RetVal_TableCell, 0x1000E) \
6161
TKSPEC(RetVal_TableHCell, 0x1000F) \
6262
TKSPEC(RetVal_EndTable, 0x10010) \
63-
TKSPEC(RetVal_Internal, 0x10011) \
64-
TKSPEC(RetVal_SwitchLang, 0x10012) \
65-
TKSPEC(RetVal_CloseXml, 0x10013) \
66-
TKSPEC(RetVal_EndBlockQuote, 0x10014) \
67-
TKSPEC(RetVal_CopyDoc, 0x10015) \
68-
TKSPEC(RetVal_EndInternal, 0x10016) \
69-
TKSPEC(RetVal_EndParBlock, 0x10017) \
70-
TKSPEC(RetVal_EndHtmlDetails, 0x10018) \
71-
TKSPEC(RetVal_SubSubParagraph, 0x10019)
63+
TKSPEC(RetVal_EndTableCell, 0x10011) \
64+
TKSPEC(RetVal_EndTableRow, 0x10012) \
65+
TKSPEC(RetVal_Internal, 0x10013) \
66+
TKSPEC(RetVal_SwitchLang, 0x10014) \
67+
TKSPEC(RetVal_CloseXml, 0x10015) \
68+
TKSPEC(RetVal_EndBlockQuote, 0x10016) \
69+
TKSPEC(RetVal_CopyDoc, 0x10017) \
70+
TKSPEC(RetVal_EndInternal, 0x10018) \
71+
TKSPEC(RetVal_EndParBlock, 0x10019) \
72+
TKSPEC(RetVal_EndHtmlDetails, 0x1001A) \
73+
TKSPEC(RetVal_SubSubParagraph, 0x1001B)
7274

7375
enum class TokenRetval
7476
{

src/section.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class SectionManager : public LinkedMap<SectionInfo>
137137
//! Returns a non-owning pointer to the newly added section.
138138
SectionInfo *add(const SectionInfo &si)
139139
{
140+
//printf("SectionManager::add(%s,%s,%d,%s)\n",qPrint(si.label()),qPrint(si.fileName()),si.lineNr(),qPrint(si.title()));
140141
return LinkedMap<SectionInfo>::add(si.label(),si.fileName(),
141142
si.lineNr(),si.title(),si.type(),si.level(),si.ref());
142143
}
@@ -146,6 +147,7 @@ class SectionManager : public LinkedMap<SectionInfo>
146147
SectionInfo *add(const QCString &label, const QCString &fileName, int lineNr,
147148
const QCString &title, SectionType type, int level,const QCString &ref=QCString())
148149
{
150+
//printf("SectionManager::add(%s,%s,%d,%s)\n",qPrint(label),qPrint(fileName),lineNr,qPrint(title));
149151
return LinkedMap<SectionInfo>::add(label.data(),fileName,lineNr,title,type,level,ref);
150152
}
151153

@@ -154,6 +156,7 @@ class SectionManager : public LinkedMap<SectionInfo>
154156
SectionInfo *replace(const QCString &label, const QCString &fileName, int lineNr,
155157
const QCString &title, SectionType type, int level,const QCString &ref=QCString())
156158
{
159+
//printf("SectionManager::replace(%s,%s,%d,%s)\n",qPrint(label),qPrint(fileName),lineNr,qPrint(title));
157160
SectionInfo *si = LinkedMap<SectionInfo>::find(label.data());
158161
if (si)
159162
{

0 commit comments

Comments
 (0)