summaryrefslogtreecommitdiffstats
path: root/src/markdown.cpp
diff options
context:
space:
mode:
authorjohnk <johnk@arlut.utexas.edu>2016-10-05 19:38:51 (GMT)
committerjohnk <johnk@arlut.utexas.edu>2016-10-05 19:38:51 (GMT)
commit7f35695022d3baa8fc8c8d1b9a9f3368a0963871 (patch)
treebae5059d7772434969a76e22cd23115f027b7051 /src/markdown.cpp
parent8074d26746e58056b8aa1444439368b038f1dcd7 (diff)
downloadDoxygen-7f35695022d3baa8fc8c8d1b9a9f3368a0963871.zip
Doxygen-7f35695022d3baa8fc8c8d1b9a9f3368a0963871.tar.gz
Doxygen-7f35695022d3baa8fc8c8d1b9a9f3368a0963871.tar.bz2
Add support for more CSS formatting and column/row spanning in markdown tables
Diffstat (limited to 'src/markdown.cpp')
-rw-r--r--src/markdown.cpp181
1 files changed, 173 insertions, 8 deletions
diff --git a/src/markdown.cpp b/src/markdown.cpp
index d63e149..919fc6e 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -36,6 +36,8 @@
#include <qregexp.h>
#include <qfileinfo.h>
#include <qdict.h>
+#include <qvector.h>
+//#define USE_ORIGINAL_TABLES
#include "markdown.h"
#include "growbuf.h"
@@ -81,6 +83,13 @@ struct LinkRef
QCString title;
};
+struct TableCell
+{
+ TableCell() : colSpan(false) {}
+ QCString cellText;
+ bool colSpan;
+};
+
typedef int (*action_t)(GrowBuf &out,const char *data,int offset,int size);
enum Alignment { AlignNone, AlignLeft, AlignCenter, AlignRight };
@@ -1578,14 +1587,6 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size)
i = findTableColumns(data,size,start,end,columns);
- out.addStr("<table>");
-
- // write table header, in range [start..end]
- out.addStr("<tr>");
-
- int headerStart = start;
- int headerEnd = end;
-
// read cell alignments
int ret = findTableColumns(data+i,size-i,start,end,cc);
k=0;
@@ -1626,6 +1627,15 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size)
// proceed to next line
i+=ret;
+#ifdef USE_ORIGINAL_TABLES
+ out.addStr("<table>");
+
+ // write table header, in range [start..end]
+ out.addStr("<tr>");
+
+ int headerStart = start;
+ int headerEnd = end;
+
int m=headerStart;
for (k=0;k<columns;k++)
{
@@ -1689,6 +1699,161 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size)
}
out.addStr("</table> ");
+#else
+ // Store the table cell information by row then column. This
+ // allows us to handle row spanning.
+ QVector<QVector<TableCell> > tableContents;
+ tableContents.setAutoDelete(TRUE);
+
+ int headerStart = start;
+ int headerEnd = end;
+
+ int m=headerStart;
+ QVector<TableCell> *headerContents = new QVector<TableCell>(columns);
+ headerContents->setAutoDelete(TRUE);
+ for (k=0;k<columns;k++)
+ {
+ headerContents->insert(k, new TableCell);
+ while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\')))
+ {
+ headerContents->at(k)->cellText += data[m++];
+ }
+ m++;
+ // do the column span test before stripping white space
+ // || is spanning columns, | | is not
+ headerContents->at(k)->colSpan = headerContents->at(k)->cellText.isEmpty();
+ headerContents->at(k)->cellText = headerContents->at(k)->cellText.stripWhiteSpace();
+ }
+ // qvector doesn't have an append like std::vector, so we gotta do
+ // extra work
+ tableContents.resize(1);
+ tableContents.insert(0, headerContents);
+
+ // write table cells
+ int rowNum = 1;
+ while (i<size)
+ {
+ int ret = findTableColumns(data+i,size-i,start,end,cc);
+ if (cc!=columns) break; // end of table
+
+ j=start+i;
+ k=0;
+ QVector<TableCell> *rowContents = new QVector<TableCell>(columns);
+ rowContents->setAutoDelete(TRUE);
+ rowContents->insert(k, new TableCell);
+ while (j<=end+i)
+ {
+ if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\')))
+ {
+ // do the column span test before stripping white space
+ // || is spanning columns, | | is not
+ rowContents->at(k)->colSpan = rowContents->at(k)->cellText.isEmpty();
+ rowContents->at(k)->cellText = rowContents->at(k)->cellText.stripWhiteSpace();
+ k++;
+ rowContents->insert(k, new TableCell);
+ } // if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\')))
+ else
+ {
+ rowContents->at(k)->cellText += data[j];
+ } // else { if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\'))) }
+ j++;
+ } // while (j<=end+i)
+ // do the column span test before stripping white space
+ // || is spanning columns, | | is not
+ rowContents->at(k)->colSpan = rowContents->at(k)->cellText.isEmpty();
+ rowContents->at(k)->cellText = rowContents->at(k)->cellText.stripWhiteSpace();
+ // qvector doesn't have an append like std::vector, so we gotta do
+ // extra work
+ tableContents.resize(tableContents.size()+1);
+ tableContents.insert(rowNum++, rowContents);
+
+ // proceed to next line
+ i+=ret;
+ }
+
+
+ out.addStr("<table class=\"markdownTable\">\n");
+ QCString cellTag("th"), cellClass("class=\"markdownTableHead");
+ for (unsigned row = 0; row < tableContents.size(); row++)
+ {
+ out.addStr(" <tr class=\"markdownTable");
+ if (row)
+ {
+ out.addStr("Body\"");
+ if (row % 2)
+ {
+ out.addStr(" class=\"markdownTableRowOdd\">\n");
+ }
+ else
+ {
+ out.addStr(" class=\"markdownTableRowEven\">\n");
+ }
+ }
+ else
+ {
+ out.addStr("Head\">\n");
+ }
+ for (int c = 0; c < columns; c++)
+ {
+ // save the cell text for use after column span computation
+ QCString cellText(tableContents[row]->at(c)->cellText);
+
+ // Row span handling. Spanning rows will contain a caret ('^').
+ // If the current cell contains just a caret, this is part of an
+ // earlier row's span and the cell should not be added to the
+ // output.
+ if (tableContents[row]->at(c)->cellText == "^")
+ continue;
+ unsigned rowSpan = 1, spanRow = row+1;
+ while ((spanRow < tableContents.size()) &&
+ (tableContents[spanRow]->at(c)->cellText == "^"))
+ {
+ spanRow++;
+ rowSpan++;
+ }
+
+ out.addStr(" <" + cellTag + " " + cellClass);
+ // use appropriate alignment style
+ switch (columnAlignment[c])
+ {
+ case AlignLeft: out.addStr("Left\""); break;
+ case AlignRight: out.addStr("Right\""); break;
+ case AlignCenter: out.addStr("Center\""); break;
+ case AlignNone: out.addStr("None\""); break;
+ }
+
+ if (rowSpan > 1)
+ {
+ QCString spanStr;
+ spanStr.setNum(rowSpan);
+ out.addStr(" rowspan=\"" + spanStr + "\"");
+ }
+ // Column span handling, assumes that column spans will have
+ // empty strings, which would indicate the sequence "||", used
+ // to signify spanning columns.
+ unsigned colSpan = 1;
+ while ((c < columns-1) &&
+ tableContents[row]->at(c+1)->colSpan)
+ {
+ c++;
+ colSpan++;
+ }
+ if (colSpan > 1)
+ {
+ QCString spanStr;
+ spanStr.setNum(colSpan);
+ out.addStr(" colspan=\"" + spanStr + "\"");
+ }
+ // need at least one space on either side of the cell text in
+ // order for doxygen to do other formatting
+ out.addStr("> " + cellText + " </" + cellTag + ">\n");
+ }
+ cellTag = "td";
+ cellClass = "class=\"markdownTableBody";
+ out.addStr(" </tr>\n");
+ }
+ out.addStr("</table>\n");
+#endif
delete[] columnAlignment;
return i;