summaryrefslogtreecommitdiffstats
path: root/src/markdown.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/markdown.cpp')
-rw-r--r--src/markdown.cpp539
1 files changed, 409 insertions, 130 deletions
diff --git a/src/markdown.cpp b/src/markdown.cpp
index 42b5bee..95cf3c1 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -43,6 +43,14 @@
#include "util.h"
#include "doxygen.h"
#include "commentscan.h"
+#include "entry.h"
+
+//-----------
+
+#define isIdChar(i) \
+ ((data[(i)]>='a' && data[(i)]<='z') || \
+ (data[(i)]>='A' && data[(i)]<='Z') || \
+ (data[(i)]>='0' && data[(i)]<='9')) \
//----------
@@ -62,6 +70,8 @@ enum Alignment { AlignNone, AlignLeft, AlignCenter, AlignRight };
static QDict<LinkRef> g_linkRefs(257);
static action_t g_actions[256];
+static Entry *g_current;
+static QCString g_fileName;
//static QDict<void> g_htmlBlockTags(17);
//----------
@@ -206,11 +216,7 @@ static int findEmphasisChar(const char *data, int size, char c)
if (data[i] == c)
{
- if (i<size-1 && ((data[i+1]>='a' && data[i+1]<='z') ||
- (data[i+1]>='A' && data[i+1]<='Z') ||
- (data[i+1]>='0' && data[i+1]<='9')
- )
- ) // to prevent touching some_underscore_identifier
+ if (i<size-1 && isIdChar(i+1)) // to prevent touching some_underscore_identifier
{
i++;
continue;
@@ -397,11 +403,110 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c)
return 0;
}
-static int processEmphasis(GrowBuf &out,const char *data,int,int size)
+static int processHtmlTag(GrowBuf &out,const char *data,int offset,int size)
{
+ if (offset>0 && data[-1]=='\\') return 0; // escaped <
+
+ // find the end of the html tag
+ int i=1;
+ int l=0;
+ // compute length of the tag name
+ while (i<size && isIdChar(i)) i++,l++;
+ QCString tagName;
+ convertStringFragment(tagName,data+1,i-1);
+ if (tagName.lower()=="pre") // found <pre> tag
+ {
+ bool insideStr=FALSE;
+ while (i<size-6)
+ {
+ char c=data[i];
+ if (!insideStr && c=='<') // potential start of html tag
+ {
+ if (data[i+1]=='/' &&
+ tolower(data[i+2])=='p' && tolower(data[i+3])=='r' &&
+ tolower(data[i+4])=='e' && tolower(data[i+5])=='>')
+ { // found </pre> tag, copy from start to end of tag
+ out.addStr(data,i+6);
+ //printf("found <pre>..</pre> [%d..%d]\n",0,i+6);
+ return i+6;
+ }
+ }
+ else if (insideStr && c=='"')
+ {
+ if (data[i-1]!='\\') insideStr=FALSE;
+ }
+ else if (c=='"')
+ {
+ insideStr=TRUE;
+ }
+ i++;
+ }
+ }
+ else // some other html tag
+ {
+ if (l>0 && i<size)
+ {
+ if (data[i]=='/' && i<size-1 && data[i+1]=='>') // <bla/>
+ {
+ //printf("Found htmlTag={%s}\n",QCString(data).left(i+2).data());
+ out.addStr(data,i+2);
+ return i+2;
+ }
+ else if (data[i]=='>') // <bla>
+ {
+ //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data());
+ out.addStr(data,i+1);
+ return i+1;
+ }
+ else if (data[i]==' ') // <bla attr=...
+ {
+ i++;
+ bool insideAttr=FALSE;
+ while (i<size)
+ {
+ if (!insideAttr && data[i]=='"')
+ {
+ insideAttr=TRUE;
+ }
+ else if (data[i]=='"' && data[i-1]!='\\')
+ {
+ insideAttr=FALSE;
+ }
+ else if (!insideAttr && data[i]=='>') // found end of tag
+ {
+ //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data());
+ out.addStr(data,i+1);
+ return i+1;
+ }
+ i++;
+ }
+ }
+ }
+ }
+ //printf("Not a valid html tag\n");
+ return 0;
+}
+
+static int processEmphasis(GrowBuf &out,const char *data,int offset,int size)
+{
+ if (offset>0 && size>1 && (isIdChar(-1) || data[-1]==data[0]))
+ {
+ if (isIdChar(1) || data[-1]==data[0])
+ {
+ // avoid processing interal * and _ as cmd_id, or 4*10 as emphasis,
+ // also x**2,y*2 should not be processed
+ return 0;
+ }
+ else if (size>2 && data[0]==data[1] && isIdChar(2))
+ {
+ // avoid processing interal ** and __ such as cmd__id__bla,
+ // or 4**10,5**10 as emphasis
+ return 0;
+ }
+ }
char c = data[0];
- size_t ret;
- if (size>2 && data[1]!=c)
+ int ret;
+ if (size>2 && data[1]!=c) // _bla or *bla
{
// whitespace cannot follow an opening emphasis
if (data[1]==' ' || data[1]=='\n' ||
@@ -411,7 +516,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int,int size)
}
return ret+1;
}
- if (size>3 && data[1]==c && data[2]!=c)
+ if (size>3 && data[1]==c && data[2]!=c) // __bla or **bla
{
if (data[2]==' ' || data[2]=='\n' ||
(ret = processEmphasis2(out, data+2, size-2, c)) == 0)
@@ -420,7 +525,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int,int size)
}
return ret+2;
}
- if (size>4 && data[1]==c && data[2]==c && data[3]!=c)
+ if (size>4 && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla
{
if (data[3]==' ' || data[3]=='\n' ||
(ret = processEmphasis3(out, data+3, size-3, c)) == 0)
@@ -478,7 +583,7 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
contentEnd=i;
convertStringFragment(content,data+contentStart,contentEnd-contentStart);
//printf("processLink: content={%s}\n",content.data());
- if (content.isEmpty()) return 0; // no link text
+ if (!isImageLink && content.isEmpty()) return 0; // no link text
i++; // skip over ]
// skip whitespace
@@ -588,7 +693,7 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
}
i++;
}
- else if (i<size && data[i]!=':') // minimal link ref notation [some id]
+ else if (i<size && data[i]!=':' && !content.isEmpty()) // minimal link ref notation [some id]
{
LinkRef *lr = g_linkRefs.find(content.lower());
//printf("processLink: minimal link {%s} lr=%p",content.data(),lr);
@@ -609,28 +714,33 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
{
return 0;
}
- if (isImageLink) // TODO: use @image?
+ static QRegExp re("^[@\\]ref ");
+ if (isImageLink)
{
- out.addStr("<img src=\"");
- out.addStr(link);
- out.addStr("\" alt=\"");
- out.addStr(content);
- out.addStr("\"");
- if (!title.isEmpty())
+ if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1)
+ // assume doxygen symbol link
{
- out.addStr(" title=\"");
- out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
- out.addStr("\"");
+ out.addStr("@image html ");
+ out.addStr(link.mid(5));
+ if (!explicitTitle && !content.isEmpty())
+ {
+ out.addStr(" \"");
+ out.addStr(content);
+ out.addStr("\"");
+ }
+ else if ((content.isEmpty() || explicitTitle) && !title.isEmpty())
+ {
+ out.addStr(" \"");
+ out.addStr(title);
+ out.addStr("\"");
+ }
}
- out.addStr("/>");
- }
- else
- {
- static QRegExp re("^[@\\]ref ");
- if (link.find('/')!=-1) // file/url link
+ else
{
- out.addStr("<a href=\"");
+ out.addStr("<img src=\"");
out.addStr(link);
+ out.addStr("\" alt=\"");
+ out.addStr(content);
out.addStr("\"");
if (!title.isEmpty())
{
@@ -638,11 +748,12 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
out.addStr("\"");
}
- out.addStr(">");
- out.addStr(content.simplifyWhiteSpace());
- out.addStr("</a>");
+ out.addStr("/>");
}
- else if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1)
+ }
+ else
+ {
+ if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1)
// assume doxygen symbol link
{
out.addStr(link);
@@ -657,7 +768,22 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
}
out.addStr("\"");
}
- else // avoid link to F[x](y)
+ else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1)
+ { // file/url link
+ out.addStr("<a href=\"");
+ out.addStr(link);
+ out.addStr("\"");
+ if (!title.isEmpty())
+ {
+ out.addStr(" title=\"");
+ out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
+ out.addStr("\"");
+ }
+ out.addStr(">");
+ out.addStr(content.simplifyWhiteSpace());
+ out.addStr("</a>");
+ }
+ else // avoid link to e.g. F[x](y)
{
//printf("no link for '%s'\n",link.data());
return 0;
@@ -722,17 +848,14 @@ static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int s
i=f_begin;
while (i<f_end-1)
{
- if (data[i]=='\'' && !((data[i+1]>='a' && data[i+1]<='z') ||
- (data[i+1]>='A' && data[i+1]<='Z') ||
- (data[i+1]>='0' && data[i+1]<='9')
- )) // reject `some word' and not `it's cool`
+ if (data[i]=='\'' && !isIdChar(i+1)) // reject `some word' and not `it's cool`
{
return 0;
}
i++;
}
}
- printf("found code span '%s'\n",QCString(data+f_begin).left(f_end-f_begin).data());
+ //printf("found code span '%s'\n",QCString(data+f_begin).left(f_end-f_begin).data());
/* real code span */
if (f_begin < f_end)
@@ -783,28 +906,6 @@ static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int
return 0;
}
-#if 0
-static int processHtmlBlock(GrowBuf &out, const char *data, int offset, int size)
-{
- if (size<2 || data[0]!='<') return 0;
- int i=1;
- while (i<size && ((data[i]>='0' && data[i]<='9') ||
- (data[i]>='A' && data[i]<='Z') ||
- (data[i]>='a' && data[i]<='z'))) i++;
- if (i<=1 || i>=size) return 0;
- QCString tagName;
- convertStringFragment(tagName,data+1,i-1);
- printf("found html tag '%s'\n",tagName.data());
- if (g_htmlBlockTags.find(tagName)!=0)
- {
- printf("found block tag\n");
-
- // search for end of the block...
- }
- return 0;
-}
-#endif
-
static void processInline(GrowBuf &out,const char *data,int size)
{
int i=0, end=0;
@@ -856,7 +957,24 @@ static bool isBlockQuote(const char *data,int size,int indent)
{
int i = 0;
while (i<size && data[i]==' ') i++;
- return i<size && data[i]=='>' && i<indent+codeBlockIndent;
+ if (i<indent+codeBlockIndent) // could be a quotation
+ {
+ // count >'s and skip spaces
+ int level=0;
+ while (i<size && (data[i]=='>' || data[i]==' '))
+ {
+ if (data[i]=='>') level++;
+ i++;
+ }
+ // last characters should be a space or newline,
+ // so a line starting with >= does not match
+ return level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n');
+ }
+ else // too much indentation -> code block
+ {
+ return FALSE;
+ }
+ //return i<size && data[i]=='>' && i<indent+codeBlockIndent;
}
/** returns end of the link ref if this is indeed a link reference. */
@@ -979,7 +1097,7 @@ static int isHRuler(const char *data,int size)
static QCString extractTitleId(QCString &title)
{
- static QRegExp r1("^[a-z_A-Z][a-z_A-Z0-9\\-]*:");
+ //static QRegExp r1("^[a-z_A-Z][a-z_A-Z0-9\\-]*:");
static QRegExp r2("\\{#[a-z_A-Z][a-z_A-Z0-9\\-]*\\}$");
int l=0;
int i = r2.match(title,0,&l);
@@ -990,20 +1108,21 @@ static QCString extractTitleId(QCString &title)
//printf("found id='%s' title='%s'\n",id.data(),title.data());
return id;
}
- i = r1.match(title,0,&l);
- if (i!=-1) // found id: style id
- {
- QCString id = title.mid(i,l-1);
- title = title.left(i)+title.mid(i+l);
- //printf("found id='%s' title='%s'\n",id.data(),title.data());
- return id;
- }
+ //i = r1.match(title,0,&l);
+ //if (i!=-1) // found id: style id
+ //{
+ // QCString id = title.mid(i,l-1);
+ // title = title.left(i)+title.mid(i+l);
+ // //printf("found id='%s' title='%s'\n",id.data(),title.data());
+ // return id;
+ //}
//printf("no id found in title '%s'\n",title.data());
return "";
}
-static int isAtxHeader(const char *data,int size,QCString &header)
+static int isAtxHeader(const char *data,int size,
+ QCString &header,QCString &id)
{
int i = 0, end;
int level = 0;
@@ -1021,6 +1140,13 @@ static int isAtxHeader(const char *data,int size,QCString &header)
// store result
convertStringFragment(header,data+i,end-i);
+ id = extractTitleId(header);
+ if (!id.isEmpty()) // strip #'s between title and id
+ {
+ i=header.length()-1;
+ while (i>=0 && header.at(i)=='#' || header.at(i)==' ') i--;
+ header=header.left(i+1);
+ }
return level;
}
@@ -1037,19 +1163,29 @@ static int isEmptyLine(const char *data,int size)
return TRUE;
}
+#define isLiTag(i) \
+ (data[(i)]=='<' && \
+ (data[(i)+1]=='l' || data[(i)+1]=='L') && \
+ (data[(i)+2]=='i' || data[(i)+2]=='I') && \
+ (data[(i)+3]=='>'))
+
// compute the indent from the start of the input, excluding list markers
-// such as -, *, +, and 1.
+// such as -, -#, *, +, 1., and <li>
static int computeIndentExcludingListMarkers(const char *data,int size)
{
int i=0;
int indent=0;
bool isDigit=FALSE;
+ bool isLi=FALSE;
bool listMarkerSkipped=FALSE;
while (i<size &&
(data[i]==' ' || // space
(!listMarkerSkipped && // first list marker
(data[i]=='+' || data[i]=='-' || data[i]=='*' || // unordered list char
- (isDigit=(data[i]>='1' && data[i]<='9'))) // ordered list marker?
+ (data[i]=='#' && i>0 && data[i-1]=='-') || // -# item
+ (isDigit=(data[i]>='1' && data[i]<='9')) || // ordered list marker?
+ (isLi=(i<size-3 && isLiTag(i))) // <li> tag
+ )
)
)
)
@@ -1076,12 +1212,24 @@ static int computeIndentExcludingListMarkers(const char *data,int size)
j++;
}
}
- else if (data[i]!=' ' && i<size-1 && data[i+1]==' ')
+ else if (isLi)
{
+ i+=3; // skip over <li>
+ indent+=3;
+ listMarkerSkipped=TRUE;
+ }
+ else if (data[i]=='-' && i<size-2 && data[i+1]=='#' && data[i+2]==' ')
+ { // case "-# "
+ listMarkerSkipped=TRUE; // only a single list marker is accepted
+ i++; // skip over #
+ indent++;
+ }
+ else if (data[i]!=' ' && i<size-1 && data[i+1]==' ')
+ { // case "- " or "+ " or "* "
listMarkerSkipped=TRUE; // only a single list marker is accepted
}
if (data[i]!=' ' && !listMarkerSkipped)
- {
+ { // end of indent
break;
}
indent++,i++;
@@ -1090,6 +1238,44 @@ static int computeIndentExcludingListMarkers(const char *data,int size)
return indent;
}
+static bool isFencedCodeBlock(const char *data,int size,int refIndent,
+ QCString &lang,int &start,int &end,int &offset)
+{
+ // TODO: implement me...
+ // rules: at least 3 ~~~, end of the block same amount of ~~~'s, otherwise
+ // return FALSE
+ int i=0;
+ int indent=0;
+ int startTildes=0;
+ while (i<size && data[i]==' ') indent++,i++;
+ if (indent>=refIndent+4) return FALSE; // part of code block
+ while (i<size && data[i]=='~') startTildes++,i++;
+ if (startTildes<3) return FALSE; // not enough tildes
+ if (i<size && data[i]=='{') i++; // skip over optional {
+ int startLang=i;
+ while (i<size && (data[i]!='\n' && data[i]!='}' && data[i]!=' ')) i++;
+ convertStringFragment(lang,data+startLang,i-startLang);
+ while (i<size && data[i]!='\n') i++; // proceed to the end of the line
+ start=i;
+ while (i<size)
+ {
+ if (data[i]=='~')
+ {
+ end=i-1;
+ int endTildes=0;
+ while (i<size && data[i]=='~') endTildes++,i++;
+ while (i<size && data[i]==' ') i++;
+ if (i==size || data[i]=='\n')
+ {
+ offset=i;
+ return endTildes==startTildes;
+ }
+ }
+ i++;
+ }
+ return FALSE;
+}
+
static bool isCodeBlock(const char *data,int offset,int size,int &indent)
{
//printf("<isCodeBlock(offset=%d,size=%d,indent=%d)\n",offset,size,indent);
@@ -1244,16 +1430,9 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size)
// write table header, in range [start..end]
out.addStr("<tr>");
- j=start;
- for (k=0;k<columns;k++)
- {
- out.addStr("<th>");
- while (j<=end && (data[j]!='|' || (j>0 && data[j-1]=='\\')))
- {
- out.addChar(data[j++]);
- }
- j++;
- }
+
+ int headerStart = start;
+ int headerEnd = end;
// read cell alignments
int ret = findTableColumns(data+i,size-i,start,end,cc);
@@ -1295,6 +1474,25 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size)
// proceed to next line
i+=ret;
+ int m=headerStart;
+ for (k=0;k<columns;k++)
+ {
+ out.addStr("<th");
+ switch (columnAlignment[k])
+ {
+ case AlignLeft: out.addStr(" align=left"); break;
+ case AlignRight: out.addStr(" align=right"); break;
+ case AlignCenter: out.addStr(" align=center"); break;
+ case AlignNone: break;
+ }
+ out.addStr(">");
+ while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\')))
+ {
+ out.addChar(data[m++]);
+ }
+ m++;
+ }
+
// write table cells
while (i<size)
{
@@ -1348,17 +1546,44 @@ void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size)
{
int level;
QCString header;
+ QCString id;
if (isHRuler(data,size))
{
out.addStr("<hr>\n");
}
- else if ((level=isAtxHeader(data,size,header)))
+ else if ((level=isAtxHeader(data,size,header,id)))
{
QCString hTag;
- hTag.sprintf("h%d",level);
- out.addStr("<"+hTag+">");
- out.addStr(header);
- out.addStr("</"+hTag+">\n");
+ if (level<5 && !id.isEmpty())
+ {
+ switch(level)
+ {
+ case 1: out.addStr("@section "); break;
+ case 2: out.addStr("@subsection "); break;
+ case 3: out.addStr("@subsubsection "); break;
+ default: out.addStr("@paragraph "); break;
+ }
+ out.addStr(id);
+ out.addStr(" ");
+ out.addStr(header);
+ SectionInfo *si = new SectionInfo(g_fileName,id,header,SectionInfo::Anchor,level);
+ if (g_current)
+ {
+ g_current->anchors->append(si);
+ }
+ Doxygen::sectionDict.append(header,si);
+ }
+ else
+ {
+ if (!id.isEmpty())
+ {
+ out.addStr("\\anchor "+id+"\n");
+ }
+ hTag.sprintf("h%d",level);
+ out.addStr("<"+hTag+">");
+ out.addStr(header);
+ out.addStr("</"+hTag+">\n");
+ }
}
else // nothing interesting -> just output the line
{
@@ -1387,6 +1612,11 @@ static int writeBlockQuote(GrowBuf &out,const char *data,int size)
else if (j>0 && data[j-1]=='>') indent=j+1;
j++;
}
+ if (j>0 && data[j-1]=='>') // disqualify last > if not followed by space
+ {
+ indent--;
+ j--;
+ }
if (level>curLevel) // quote level increased => add start markers
{
for (l=curLevel;l<level;l++)
@@ -1458,11 +1688,12 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size,
int &pi,int&i,int &end)
{
// find end of the line
+ int nb=0;
for (end=i+1; end<size && data[end-1]!='\n'; end++)
{
// while looking for the end of the line we might encounter a block
// that needs to be passed unprocessed.
- if ((data[end-1]=='\\' || data[end-1]=='@') && // command
+ if ((data[end-1]=='\\' || data[end-1]=='@') && // command
(end<=1 || (data[end-2]!='\\' && data[end-2]!='@')) // not escaped
)
{
@@ -1493,6 +1724,36 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size,
}
}
}
+ else if (nb==0 && data[end-1]=='<' && end<size-6 &&
+ (end<=1 || (data[end-2]!='\\' && data[end-2]!='@'))
+ )
+ {
+ if (tolower(data[end])=='p' && tolower(data[end+1])=='r' &&
+ tolower(data[end+2])=='e' && data[end+3]=='>') // <pre> tag
+ {
+ if (pi!=-1) // output previous line if available
+ {
+ out.addStr(data+pi,i-pi);
+ }
+ // output part until <pre>
+ out.addStr(data+i,end-1-i);
+ // output part until </pre>
+ i = end-1 + processHtmlTag(out,data+end-1,end-1,size-end+1);
+ pi=-1;
+ end = i+1;
+ break;
+ }
+ }
+ else if (nb==0 && data[end-1]=='`')
+ {
+ while (end<size && data[end-1]=='`') end++,nb++;
+ }
+ else if (nb>0 && data[end-1]=='`')
+ {
+ int enb=0;
+ while (end<size && data[end-1]=='`') end++,enb++;
+ if (enb==nb) nb=0;
+ }
}
}
@@ -1578,17 +1839,38 @@ static QCString processBlocks(const QCString &s,int indent)
if (pi!=-1)
{
+ int blockStart,blockEnd,blockOffset;
+ QCString lang;
blockIndent = indent;
//printf("isHeaderLine(%s)=%d\n",QCString(data+i).left(size-i).data(),level);
if ((level=isHeaderline(data+i,size-i))>0)
{
//printf("Found header at %d-%d\n",i,end);
while (pi<size && data[pi]==' ') pi++;
- if (i-pi>1)
+ QCString header,id;
+ convertStringFragment(header,data+pi,i-pi-1);
+ id = extractTitleId(header);
+ if (!header.isEmpty())
{
- out.addStr(level==1?"<h1>":"<h2>");
- out.addStr(data+pi,i-pi-1);
- out.addStr(level==1?"</h1>\n":"</h2>\n");
+ if (!id.isEmpty())
+ {
+ out.addStr(level==1?"@section ":"@subsection ");
+ out.addStr(id);
+ out.addStr(" ");
+ out.addStr(header);
+ SectionInfo *si = new SectionInfo(g_fileName,id,header,SectionInfo::Anchor,level);
+ if (g_current)
+ {
+ g_current->anchors->append(si);
+ }
+ Doxygen::sectionDict.append(header,si);
+ }
+ else
+ {
+ out.addStr(level==1?"<h1>":"<h2>");
+ out.addStr(header);
+ out.addStr(level==1?"</h1>\n":"</h2>\n");
+ }
}
else
{
@@ -1608,6 +1890,23 @@ static QCString processBlocks(const QCString &s,int indent)
pi=-1;
end=i+1;
}
+ else if (isFencedCodeBlock(data+pi,size-pi,indent,lang,blockStart,blockEnd,blockOffset))
+ {
+ //printf("Found FencedCodeBlock lang='%s' start=%d end=%d code={%s}\n",
+ // lang.data(),blockStart,blockEnd,QCString(data+pi+blockStart).left(blockEnd-blockStart).data());
+ out.addStr("@code");
+ if (!lang.isEmpty() && lang.at(0)=='.') lang=lang.mid(1);
+ if (!lang.isEmpty())
+ {
+ out.addStr("{"+lang+"}");
+ }
+ out.addStr(data+pi+blockStart,blockEnd-blockStart);
+ out.addStr("\n@endcode");
+ i=pi+blockOffset;
+ pi=-1;
+ end=i+1;
+ continue;
+ }
else if (isCodeBlock(data+i,i,end-i,blockIndent))
//if (isCodeBlock(data+pi,pi,end-pi,blockIndent))
{
@@ -1651,7 +1950,7 @@ static QCString processBlocks(const QCString &s,int indent)
return out.get();
}
-static QCString extractPageTitle(QCString &docs)
+static QCString extractPageTitle(QCString &docs,QCString &id)
{
// first first non-empty line
QCString title;
@@ -1671,16 +1970,19 @@ static QCString extractPageTitle(QCString &docs)
while (end2<size && data[end2-1]!='\n') end2++;
if (isHeaderline(data+end1,size-end1))
{
- convertStringFragment(title,data+i,end1-i);
+ convertStringFragment(title,data+i,end1-i-1);
docs=docs.mid(end2);
+ id = extractTitleId(title);
+ //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
return title;
}
}
- if (i<end1 && isAtxHeader(data+i,end1-i,title)>0)
+ if (i<end1 && isAtxHeader(data+i,end1-i,title,id)>0)
{
docs=docs.mid(end1);
}
- //printf("extractPageTitle(title='%s' docs='%s')\n",title.data(),docs.data());
+ id = extractTitleId(title);
+ //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
return title;
}
@@ -1727,36 +2029,12 @@ static QCString detab(const QCString &s,int &refIndent)
//---------------------------------------------------------------------------
-QCString processMarkdown(const QCString &input)
+QCString processMarkdown(const QCString &fileName,Entry *e,const QCString &input)
{
-#if 0
- static bool g_init = FALSE;
- if (!g_init)
- {
- g_htmlBlockTags.insert("p",(void*)0x8);
- g_htmlBlockTags.insert("dl",(void*)0x8);
- g_htmlBlockTags.insert("h1",(void*)0x8);
- g_htmlBlockTags.insert("h2",(void*)0x8);
- g_htmlBlockTags.insert("h3",(void*)0x8);
- g_htmlBlockTags.insert("h4",(void*)0x8);
- g_htmlBlockTags.insert("h5",(void*)0x8);
- g_htmlBlockTags.insert("h6",(void*)0x8);
- g_htmlBlockTags.insert("ol",(void*)0x8);
- g_htmlBlockTags.insert("ul",(void*)0x8);
- g_htmlBlockTags.insert("div",(void*)0x8);
- g_htmlBlockTags.insert("pre",(void*)0x8);
- g_htmlBlockTags.insert("form",(void*)0x8);
- g_htmlBlockTags.insert("math",(void*)0x8);
- g_htmlBlockTags.insert("table",(void*)0x8);
- g_htmlBlockTags.insert("iframe",(void*)0x8);
- g_htmlBlockTags.insert("script",(void*)0x8);
- g_htmlBlockTags.insert("fieldset",(void*)0x8);
- g_htmlBlockTags.insert("noscript",(void*)0x8);
- g_init=TRUE;
- }
-#endif
g_linkRefs.setAutoDelete(TRUE);
g_linkRefs.clear();
+ g_current = e;
+ g_fileName = fileName;
static GrowBuf out;
if (input.isEmpty()) return input;
out.clear();
@@ -1777,7 +2055,7 @@ QCString processMarkdown(const QCString &input)
g_actions['@']=processSpecialCommand;
g_actions['[']=processLink;
g_actions['!']=processLink;
- //g_actions['<']=processHtmlBlock;
+ g_actions['<']=processHtmlTag;
// finally process the inline markup (links, emphasis and code spans)
processInline(out,s,size);
out.addChar(0);
@@ -1794,10 +2072,11 @@ void MarkdownFileParser::parseInput(const char *fileName,
Entry *current = new Entry;
current->lang = SrcLangExt_Markdown;
QCString docs = fileBuf;
- QCString title=extractPageTitle(docs).stripWhiteSpace();
- QCString id=extractTitleId(title);
+ QCString id;
+ QCString title=extractPageTitle(docs,id).stripWhiteSpace();
QCString baseName = substitute(QFileInfo(fileName).baseName().utf8()," ","_");
if (id.isEmpty()) id = "md_"+baseName;
+ if (title.isEmpty()) title = baseName;
if (id=="mainpage" || id=="index")
{
docs.prepend("@mainpage "+title+"\n");