diff options
Diffstat (limited to 'src/markdown.cpp')
-rw-r--r-- | src/markdown.cpp | 110 |
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) |