summaryrefslogtreecommitdiffstats
path: root/src/markdown.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/markdown.cpp')
-rw-r--r--src/markdown.cpp110
1 files changed, 73 insertions, 37 deletions
diff --git a/src/markdown.cpp b/src/markdown.cpp
index 00c0723..33a471a 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -59,7 +59,7 @@
#ifdef ENABLE_TRACING
#define IOSTREAM stdout
#define DATA_BUFSIZE 20
-#if defined(_WIN32) && !defined(CYGWIN)
+#if defined(_WIN32) && !defined(CYGWIN) && !defined(__MINGW32__)
#define PRETTY_FUNC __FUNCSIG__
#else
#define PRETTY_FUNC __PRETTY_FUNCTION__
@@ -784,7 +784,11 @@ void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle,
m_out.addStr(title);
m_out.addStr("\"");
}
- m_out.addStr("\n");
+ else
+ {
+ m_out.addStr(" ");// so the line break will not be part of the image name
+ }
+ m_out.addStr("\\ilinebr");
}
int Markdown::processLink(const char *data,int,int size)
@@ -808,6 +812,7 @@ int Markdown::processLink(const char *data,int,int size)
}
contentStart=i;
int level=1;
+ int nlTotal=0;
int nl=0;
// find the matching ]
while (i<size)
@@ -831,6 +836,8 @@ int Markdown::processLink(const char *data,int,int size)
}
i++;
}
+ nlTotal += nl;
+ nl = 0;
if (i>=size) return 0; // premature end of comment -> no link
contentEnd=i;
convertStringFragment(content,data+contentStart,contentEnd-contentStart);
@@ -843,9 +850,12 @@ int Markdown::processLink(const char *data,int,int size)
if (i<size && data[i]=='\n') // one newline allowed here
{
i++;
+ nl++;
// skip more whitespace
while (i<size && data[i]==' ') i++;
}
+ nlTotal += nl;
+ nl = 0;
bool explicitTitle=FALSE;
if (i<size && data[i]=='(') // inline link
@@ -854,7 +864,6 @@ int Markdown::processLink(const char *data,int,int size)
while (i<size && data[i]==' ') i++;
if (i<size && data[i]=='<') i++;
linkStart=i;
- nl=0;
int braceCount=1;
while (i<size && data[i]!='\'' && data[i]!='"' && braceCount>0)
{
@@ -876,6 +885,8 @@ int Markdown::processLink(const char *data,int,int size)
i++;
}
}
+ nlTotal += nl;
+ nl = 0;
if (i>=size || data[i]=='\n') return 0;
convertStringFragment(link,data+linkStart,i-linkStart);
link = link.stripWhiteSpace();
@@ -985,6 +996,8 @@ int Markdown::processLink(const char *data,int,int size)
{
return 0;
}
+ nlTotal += nl;
+ nl = 0;
if (isToc) // special case for [TOC]
{
int toc_level = Config_getInt(TOC_INCLUDE_HEADINGS);
@@ -1037,7 +1050,11 @@ int Markdown::processLink(const char *data,int,int size)
if (!(Portable::isAbsolutePath(link) || isURL(link)))
{
QFileInfo forg(link);
- if (!(forg.exists() && forg.isReadable()))
+ if (forg.exists() && forg.isReadable())
+ {
+ link = forg.absFilePath().data();
+ }
+ else if (!(forg.exists() && forg.isReadable()))
{
QFileInfo fi(m_fileName);
QCString mdFile = m_fileName.left(m_fileName.length()-fi.fileName().length()) + link;
@@ -1066,6 +1083,7 @@ int Markdown::processLink(const char *data,int,int size)
m_out.addStr("<a href=\"");
m_out.addStr(link);
m_out.addStr("\"");
+ for (int ii = 0; ii < nlTotal; ii++) m_out.addStr("\n");
if (!title.isEmpty())
{
m_out.addStr(" title=\"");
@@ -1923,16 +1941,16 @@ int Markdown::writeTableBlock(const char *data,int size)
{
if (row % 2)
{
- m_out.addStr("<tr class=\"markdownTableRowOdd\">");
+ m_out.addStr("\n<tr class=\"markdownTableRowOdd\">");
}
else
{
- m_out.addStr("<tr class=\"markdownTableRowEven\">");
+ m_out.addStr("\n<tr class=\"markdownTableRowEven\">");
}
}
else
{
- m_out.addStr(" <tr class=\"markdownTableHead\">");
+ m_out.addStr("\n <tr class=\"markdownTableHead\">");
}
for (int c = 0; c < columns; c++)
{
@@ -1986,11 +2004,11 @@ int Markdown::writeTableBlock(const char *data,int size)
}
// need at least one space on either side of the cell text in
// order for doxygen to do other formatting
- m_out.addStr("> " + cellText + "\\ilinebr </" + cellTag + ">");
+ m_out.addStr("> " + cellText + " \\ilinebr </" + cellTag + ">");
}
cellTag = "td";
cellClass = "class=\"markdownTableBody";
- m_out.addStr(" </tr>\n");
+ m_out.addStr(" </tr>");
}
m_out.addStr("</table>\n");
@@ -2023,7 +2041,7 @@ void Markdown::writeOneLineHeaderOrRuler(const char *data,int size)
QCString id;
if (isHRuler(data,size))
{
- m_out.addStr("\n<hr>\n");
+ m_out.addStr("<hr>\n");
}
else if ((level=isAtxHeader(data,size,header,id,TRUE)))
{
@@ -2058,13 +2076,17 @@ void Markdown::writeOneLineHeaderOrRuler(const char *data,int size)
m_out.addStr("</"+hTag+">\n");
}
}
- else // nothing interesting -> just output the line
+ else if (size>0) // nothing interesting -> just output the line
{
- m_out.addStr(data,size);
+ int tmpSize = size;
+ if (data[size-1] == '\n') tmpSize--;
+ m_out.addStr(data,tmpSize);
+
if (hasLineBreak(data,size))
{
- m_out.addStr("<br>\n");
+ m_out.addStr("<br>");
}
+ if (tmpSize != size) m_out.addChar('\n');
}
}
@@ -2100,14 +2122,14 @@ int Markdown::writeBlockQuote(const char *data,int size)
{
for (l=curLevel;l<level;l++)
{
- m_out.addStr("<blockquote>\n");
+ m_out.addStr("<blockquote>");
}
}
else if (level<curLevel) // quote level decreased => add end markers
{
for (l=level;l<curLevel;l++)
{
- m_out.addStr("</blockquote>\n");
+ m_out.addStr("</blockquote>");
}
}
curLevel=level;
@@ -2120,7 +2142,7 @@ int Markdown::writeBlockQuote(const char *data,int size)
// end of comment within blockquote => add end markers
for (l=0;l<curLevel;l++)
{
- m_out.addStr("</blockquote>\n");
+ m_out.addStr("</blockquote>");
}
return i;
}
@@ -2130,6 +2152,7 @@ int Markdown::writeCodeBlock(const char *data,int size,int refIndent)
TRACE(data);
int i=0,end;
//printf("writeCodeBlock: data={%s}\n",QCString(data).left(size).data());
+ // no need for \ilinebr here as the prvious like was empty and was skipped
m_out.addStr("@verbatim\n");
int emptyLines=0;
while (i<size)
@@ -2164,7 +2187,7 @@ int Markdown::writeCodeBlock(const char *data,int size,int refIndent)
break;
}
}
- m_out.addStr("@endverbatim\n");
+ m_out.addStr("@endverbatim\\ilinebr ");
while (emptyLines>0) // write skipped empty lines
{
// add empty line
@@ -2263,8 +2286,8 @@ void Markdown::writeFencedCodeBlock(const char *data,const char *lng,
m_out.addStr("{"+lang+"}");
}
addStrEscapeUtf8Nbsp(data+blockStart,blockEnd-blockStart);
- m_out.addStr("\n");
- m_out.addStr("@endcode\n");
+ m_out.addStr(" ");
+ m_out.addStr("@endcode");
}
QCString Markdown::processQuotations(const QCString &s,int refIndent)
@@ -2491,18 +2514,20 @@ static bool isExplicitPage(const QCString &docs)
return FALSE;
}
-QCString Markdown::extractPageTitle(QCString &docs,QCString &id)
+QCString Markdown::extractPageTitle(QCString &docs,QCString &id, int &prepend)
{
TRACE(docs.data());
- int ln=0;
// first first non-empty line
+ prepend = 0;
QCString title;
- const char *data = docs.data();
int i=0;
int size=docs.size();
+ QCString docs_org(docs);
+ const char *data = docs_org.data();
+ docs = "";
while (i<size && (data[i]==' ' || data[i]=='\n'))
{
- if (data[i]=='\n') ln++;
+ if (data[i]=='\n') prepend++;
i++;
}
if (i>=size) return "";
@@ -2512,16 +2537,13 @@ QCString Markdown::extractPageTitle(QCString &docs,QCString &id)
// first line from i..end1
if (end1<size)
{
- ln++;
// second line form end1..end2
int end2=end1+1;
while (end2<size && data[end2-1]!='\n') end2++;
if (isHeaderline(data+end1,size-end1,FALSE))
{
convertStringFragment(title,data+i,end1-i-1);
- QCString lns;
- lns.fill('\n',ln);
- docs=lns+docs.mid(end2);
+ docs+="\n\n"+docs_org.mid(end2);
id = extractTitleId(title, 0);
//printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
return title;
@@ -2529,10 +2551,12 @@ QCString Markdown::extractPageTitle(QCString &docs,QCString &id)
}
if (i<end1 && isAtxHeader(data+i,end1-i,title,id,FALSE)>0)
{
- docs=docs.mid(end1);
+ docs+="\n";
+ docs+=docs_org.mid(end1);
}
else
{
+ docs=docs_org;
id = extractTitleId(title, 0);
}
//printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
@@ -2661,7 +2685,15 @@ QCString markdownFileNameToId(const QCString &fileName)
QCString baseFn = stripFromPath(QFileInfo(fileName).absFilePath().utf8());
int i = baseFn.findRev('.');
if (i!=-1) baseFn = baseFn.left(i);
- QCString baseName = substitute(substitute(substitute(baseFn," ","_"),"/","_"),":","_");
+ QCString baseName = baseFn;
+ char *p = baseName.rawData();
+ char c;
+ while ((c=*p))
+ {
+ if (!isId(c)) *p='_'; // escape characters that do not yield an identifier by underscores
+ p++;
+ }
+ //printf("markdownFileNameToId(%s)=md_%s\n",qPrint(fileName),qPrint(baseName));
return "md_"+baseName;
}
@@ -2686,6 +2718,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName,
ClangTUParser* /*clangParser*/)
{
std::shared_ptr<Entry> current = std::make_shared<Entry>();
+ int prepend = 0; // number of empty lines in front
current->lang = SrcLangExt_Markdown;
current->fileName = fileName;
current->docFile = fileName;
@@ -2693,7 +2726,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName,
QCString docs = fileBuf;
QCString id;
Markdown markdown(fileName,1,0);
- QCString title=markdown.extractPageTitle(docs,id).stripWhiteSpace();
+ QCString title=markdown.extractPageTitle(docs,id,prepend).stripWhiteSpace();
if (id.startsWith("autotoc_md")) id = "";
int indentLevel=title.isEmpty() ? 0 : -1;
markdown.setIndentLevel(indentLevel);
@@ -2710,24 +2743,26 @@ void MarkdownOutlineParser::parseInput(const char *fileName,
QFileInfo(mdfileAsMainPage).absFilePath()) // file reference with path
)
{
- docs.prepend("@anchor " + id + "\n");
- docs.prepend("@mainpage "+title+"\n");
+ docs.prepend("@anchor " + id + "\\ilinebr ");
+ docs.prepend("@mainpage "+title+"\\ilinebr ");
}
else if (id=="mainpage" || id=="index")
{
if (title.isEmpty()) title = titleFn;
- docs.prepend("@anchor " + id + "\n");
- docs.prepend("@mainpage "+title+"\n");
+ docs.prepend("@anchor " + id + "\\ilinebr ");
+ docs.prepend("@mainpage "+title+"\\ilinebr ");
}
else
{
- if (title.isEmpty()) title = titleFn;
- if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\n");
- docs.prepend("@page "+id+" "+title+"\n");
+ if (title.isEmpty()) {title = titleFn;prepend=0;}
+ if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\\ilinebr ");
+ docs.prepend("@page "+id+" "+title+"\\ilinebr ");
}
+ for (int i = 0; i < prepend; i++) docs.prepend("\n");
}
int lineNr=1;
+ p->commentScanner.enterFile(fileName,lineNr);
Protection prot=Public;
bool needsEntry = FALSE;
int position=0;
@@ -2759,6 +2794,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName,
{
root->moveToSubEntryAndKeep(current);
}
+ p->commentScanner.leaveFile(fileName,lineNr);
}
void MarkdownOutlineParser::parsePrototype(const char *text)