浏览该文件的文档.
36 #include <unordered_map>
57 #define ENABLE_TRACING
61 #define IOSTREAM stdout
62 #define DATA_BUFSIZE 20
63 #if defined(_WIN32) && !defined(CYGWIN) && !defined(__MINGW32__)
64 #define PRETTY_FUNC __FUNCSIG__
66 #define PRETTY_FUNC __PRETTY_FUNCTION__
93 else if (c==
'\n') { data_s[j++]=
'\\'; data_s[j++]=
'n'; }
94 else if (c==
'\t') { data_s[j++]=
'\\'; data_s[j++]=
't'; }
95 else if (c==
'\r') { data_s[j++]=
'\\'; data_s[j++]=
'r'; }
96 else if (c==
'\\') { data_s[j++]=
'\\'; data_s[j++]=
'\\'; }
162 #define TRACE(data) Trace trace_(PRETTY_FUNC,data);
163 #define TRACE_MORE(...) trace_.trace(__VA_ARGS__);
164 #define TRACE_RESULT(v) trace_.setResult(v);
166 #define TRACE(data) do {} while(false)
167 #define TRACE_MORE(...) do {} while(false)
168 #define TRACE_RESULT(v) do {} while(false)
174 #define isIdChar(i) \
175 ((data[i]>='a' && data[i]<='z') || \
176 (data[i]>='A' && data[i]<='Z') || \
177 (data[i]>='0' && data[i]<='9') || \
178 (((unsigned char)data[i])>=0x80)) // unicode characters
180 #define extraChar(i) \
181 (data[i]=='-' || data[i]=='+' || data[i]=='!' || \
182 data[i]=='?' || data[i]=='$' || data[i]=='@' || \
183 data[i]=='&' || data[i]=='*' || data[i]=='%')
186 #define isOpenEmphChar(i) \
187 (data[i]=='\n' || data[i]==' ' || data[i]=='\'' || data[i]=='<' || \
188 data[i]=='>' || data[i]=='{' || data[i]=='(' || data[i]=='[' || \
189 data[i]==',' || data[i]==':' || data[i]==';')
193 #define ignoreCloseEmphChar(i) \
194 (data[i]=='(' || data[i]=='{' || data[i]=='[' || (data[i]=='<' && data[i+1]!='/') || \
208 : m_fileName(fileName), m_lineNr(lineNr), m_indentLevel(indentLevel)
210 using namespace std::placeholders;
242 if (data[0] ==
'\n')
return 1;
244 if (data[0] ==
'\\' &&
qstrncmp(data+1,
"ilinebr ",7)==0)
return data[8]==
' ' ? 9 : 8;
254 const char *p=s.
data();
260 case '"':
if (pc!=
'\\') { growBuf.
addChar(
'\\'); } growBuf.
addChar(c);
break;
261 default: growBuf.
addChar(c);
break;
267 return growBuf.
get();
274 bool insideQuote=
FALSE;
276 const char *p=s.
data();
282 case '"':
if (pc!=
'\\') { insideQuote=!insideQuote; } growBuf.
addChar(c);
break;
284 case '>':
if (!insideQuote)
288 if ((p[0] ==
':') && (p[1] ==
':'))
300 case '\\':
if (!insideQuote) { growBuf.
addChar(
'\\'); } growBuf.
addChar(
'\\');
break;
301 case '@':
if (!insideQuote) { growBuf.
addChar(
'\\'); } growBuf.
addChar(
'@');
break;
302 case '#':
if (!insideQuote) { growBuf.
addChar(
'\\'); } growBuf.
addChar(
'#');
break;
303 default: growBuf.
addChar(c);
break;
309 return growBuf.
get();
326 if (leftMarker && rightMarker)
334 else if (rightMarker)
367 bool openBracket = offset>0 && data[-1]==
'{';
368 bool isEscaped = offset>0 && (data[-1]==
'\\' || data[-1]==
'@');
372 while (
end<size && (data[
end]>=
'a' && data[
end]<=
'z'))
end++;
376 if (blockName==
"code" && openBracket)
381 else if (blockName==
"dot" ||
384 blockName==
"verbatim" ||
385 blockName==
"latexonly" ||
386 blockName==
"htmlonly" ||
387 blockName==
"xmlonly" ||
388 blockName==
"rtfonly" ||
389 blockName==
"manonly" ||
390 blockName==
"docbookonly"
397 else if (blockName==
"startuml")
402 else if (blockName==
"f" &&
end<size)
409 else if (data[
end]==
'(')
414 else if (data[
end]==
'[')
419 else if (data[
end]==
'{')
438 while (i<size && data[i]!=c && data[i]!=
'`' &&
439 data[i]!=
'\\' && data[i]!=
'@' &&
440 !(data[i]==
'/' && data[i-1]==
'<') &&
455 while (i+len<size && data[i+len]==c)
462 if (len!=c_size || (i<size-len &&
isIdChar(i+len)))
476 while (i<size && data[i]==
'`') snb++,i++;
480 while (i<size && enb<snb)
482 if (data[i]==
'`') enb++;
483 if (snb==1 && data[i]==
'\'')
break;
487 else if (data[i]==
'@' || data[i]==
'\\')
493 int l = endBlockName.
length();
496 if ((data[i]==
'\\' || data[i]==
'@') &&
497 data[i-1]!=
'\\' && data[i-1]!=
'@')
517 else if (data[i-1]==
'<' && data[i]==
'/')
522 else if (data[i]==
'\n')
525 while (i<size && data[i]==
' ') i++;
526 if (i>=size || data[i]==
'\n') {
TRACE_RESULT(0);
return 0; }
545 if (size>1 && data[0]==c && data[1]==c) { i=1; }
554 if (i+1<size && data[i+1]==c)
559 if (data[i]==c && data[i-1]!=
' ' && data[i-1]!=
'\n')
587 if (i+1<size && data[i]==c && data[i+1]==c && i && data[i-1]!=
' ' &&
624 if (data[i]!=c || data[i-1]==
' ' || data[i-1]==
'\n')
629 if (i+2<size && data[i+1]==c && data[i+2]==c)
637 else if (i+1<size && data[i+1]==c)
679 if (i<size && data[i]==
'-')
683 if (i<size && data[i]==
'-')
687 if (i<size && data[i]==
'-')
691 if (count>=2 && off>=2 &&
qstrncmp(data-2,
"<!",2)==0)
693 if (count==2 && (data[2]==
'>'))
695 if (count==2 && (off<8 ||
qstrncmp(data-8,
"operator",8)!=0))
718 while (i<size && data[i]!=
'"' && nl<2)
720 if (data[i]==
'\n') nl++;
723 if (i<size && data[i]==
'"' && nl<2)
740 if (offset>0 && data[-1]==
'\\') {
TRACE_RESULT(0);
return 0; }
746 while (i<size &&
isIdChar(i)) i++,l++;
749 if (tagName.
lower()==
"pre")
751 bool insideStr=
FALSE;
755 if (!insideStr && c==
'<')
757 if (data[i+1]==
'/' &&
758 tolower(data[i+2])==
'p' && tolower(data[i+3])==
'r' &&
759 tolower(data[i+4])==
'e' && tolower(data[i+5])==
'>')
767 else if (insideStr && c==
'"')
769 if (data[i-1]!=
'\\') insideStr=
FALSE;
782 if (data[i]==
'/' && i<size-1 && data[i+1]==
'>')
789 else if (data[i]==
'>')
796 else if (data[i]==
' ')
799 bool insideAttr=
FALSE;
802 if (!insideAttr && data[i]==
'"')
806 else if (data[i]==
'"' && data[i-1]!=
'\\')
810 else if (!insideAttr && data[i]==
'>')
837 (size>1 && data[0]!=data[1] && !(
isIdChar(1) ||
extraChar(1) || data[1]==
'[')) ||
846 if (size>2 && c!=
'~' && data[1]!=c)
849 if (data[1]==
' ' || data[1]==
'\n' ||
857 if (size>3 && data[1]==c && data[2]!=c)
859 if (data[2]==
' ' || data[2]==
'\n' ||
867 if (size>4 && c!=
'~' && data[1]==c && data[2]==c && data[3]!=c)
869 if (data[3]==
' ' || data[3]==
'\n' ||
890 if (!explicitTitle && !content.
isEmpty())
896 else if ((content.
isEmpty() || explicitTitle) && !title.
isEmpty())
915 int contentStart,contentEnd,linkStart,titleStart,titleEnd;
916 bool isImageLink =
FALSE;
922 if (size<2 || data[1]!=
'[')
939 else if (data[i]==
'[')
943 else if (data[i]==
']')
948 else if (data[i]==
'\n')
957 if (i>=size)
return 0;
965 while (i<size && data[i]==
' ') i++;
966 if (i<size && data[i]==
'\n')
971 while (i<size && data[i]==
' ') i++;
976 bool explicitTitle=
FALSE;
977 if (i<size && data[i]==
'(')
980 while (i<size && data[i]==
' ') i++;
981 bool uriFormat=
false;
982 if (i<size && data[i]==
'<') { i++; uriFormat=
true; }
985 while (i<size && data[i]!=
'\'' && data[i]!=
'"' && braceCount>0)
992 else if (data[i]==
'(')
996 else if (data[i]==
')')
1007 if (i>=size || data[i]==
'\n') {
TRACE_RESULT(0);
return 0; }
1015 if (data[i]==
'\'' || data[i]==
'"')
1021 while (i<size && data[i]!=
')')
1037 while (titleEnd>titleStart && data[titleEnd]==
' ') titleEnd--;
1038 if (data[titleEnd]==c)
1051 else if (i<size && data[i]==
'[')
1057 while (i<size && data[i]!=
']')
1080 link = lr_it->second.link;
1081 title = lr_it->second.title;
1092 else if (i<size && data[i]!=
':' && !content.
isEmpty())
1099 link = lr_it->second.link;
1100 title = lr_it->second.title;
1104 else if (content==
"TOC")
1126 if (toc_level > 0 && toc_level <=5)
1133 else if (isImageLink)
1137 if (link.
find(
"@ref ")!=-1 || link.
find(
"\\ref ")!=-1 ||
1193 if (explicitTitle && !title.
isEmpty())
1203 else if (link.
find(
'/')!=-1 || link.
find(
'.')!=-1 || link.
find(
'#')!=-1)
1208 for (
int ii = 0; ii < nlTotal; ii++)
m_out.
addStr(
"\n");
1237 int end, nb = 0, i, f_begin, f_end;
1240 while (nb<size && data[nb]==
'`')
1248 for (
end=nb;
end<size && i<nb && nl<2;
end++)
1254 else if (data[
end]==
'\n')
1273 if (i < nb && end >= size)
1286 while (f_begin <
end && data[f_begin]==
' ')
1291 while (f_end > nb && data[f_end-1]==
' ')
1299 if (f_begin < f_end)
1333 int l = endBlockName.
length();
1336 if ((data[i]==
'\\' || data[i]==
'@') &&
1337 data[i-1]!=
'\\' && data[i-1]!=
'@')
1350 if (size>1 && data[0]==
'\\')
1353 if (c==
'[' || c==
']' || c==
'*' || c==
'!' || c==
'(' || c==
')' || c==
'`' || c==
'_')
1359 else if (c==
'-' && size>3 && data[2]==
'-' && data[3]==
'-')
1365 else if (c==
'-' && size>2 && data[2]==
'-')
1385 if (
end>=size)
break;
1387 end = action(data+i,i,size-i);
1405 while (i<size && data[i]==
' ') i++;
1410 while (i<size && data[i]==
'=') i++,c++;
1411 while (i<size && data[i]==
' ') i++;
1412 int level = (c>1 && (i>=size || data[i]==
'\n')) ? 1 : 0;
1428 while (i<size && data[i]==
'-') i++,c++;
1429 while (i<size && data[i]==
' ') i++;
1430 return (c>1 && (i>=size || data[i]==
'\n')) ?
m_indentLevel+2 : 0;
1441 while (i<size && data[i]==
' ') i++;
1446 while (i<size && (data[i]==
'>' || data[i]==
' '))
1448 if (data[i]==
'>') level++;
1453 bool res = (level>0 && i<size && ((data[i-1]==
' ') || data[i]==
'\n')) || (level > 1);
1473 while (i<size && data[i]==
' ') i++;
1474 if (i>=size || data[i]!=
'[') {
TRACE_RESULT(0);
return 0; }
1477 while (i<size && data[i]!=
'\n' && data[i]!=
']') i++;
1478 if (i>=size || data[i]!=
']') {
TRACE_RESULT(0);
return 0; }
1483 if (i>=size || data[i]!=
':') {
TRACE_RESULT(0);
return 0; }
1487 while (i<size && data[i]==
' ') i++;
1488 if (i<size && data[i]==
'\n')
1491 while (i<size && data[i]==
' ') i++;
1495 if (i<size && data[i]==
'<') i++;
1497 while (i<size && data[i]!=
' ' && data[i]!=
'\n') i++;
1499 if (i<size && data[i]==
'>') i++;
1503 if (link==
"@ref" || link==
"\\ref")
1506 while (i<size && data[i]!=
'\n' && data[i]!=
'"') i++;
1516 while (i<size && data[i]==
' ') i++;
1517 if (i<size && data[i]==
'\n')
1521 while (i<size && data[i]==
' ') i++;
1531 if (c==
'\'' || c==
'"' || c==
'(')
1538 while (i<size && data[i]!=
'\n') i++;
1543 while (
end>titleStart && data[
end]!=c)
end--;
1550 while (i<size && data[i]==
' ') i++;
1563 if (size>0 && data[size-1]==
'\n') size--;
1564 while (i<size && data[i]==
' ') i++;
1567 if (c!=
'*' && c!=
'-' && c!=
'_')
1578 else if (data[i]!=
' ')
1593 static const reg::Ex r2(R
"({#(\a[\w-]*)}\s*$)");
1595 std::string ti = title.str();
1598 std::string
id =
match[1].str();
1599 title = title.
left((
int)
match.position());
1604 if ((level > 0) && (level <=
Config_getInt(TOC_INCLUDE_HEADINGS)))
1608 id.
sprintf(
"autotoc_md%d",autoId++);
1623 int level = 0, blanks=0;
1626 while (i<size && data[i]==
' ') i++;
1627 if (i>=size || data[i]!=
'#')
1632 while (i<size && level<6 && data[i]==
'#') i++,level++;
1633 while (i<size && data[i]==
' ') i++,blanks++;
1634 if (level==1 && blanks==0)
1642 while (
end<size && data[
end]!=
'\n')
end++;
1643 while (
end>i && (data[
end-1]==
'#' || data[
end-1]==
' '))
end--;
1651 while (i>=0 && (header.
at(i)==
'#' || header.
at(i)==
' ')) i--;
1652 header=header.
left(i+1);
1696 #define isLiTag(i) \
1697 (data[(i)]=='<' && \
1698 (data[(i)+1]=='l' || data[(i)+1]=='L') && \
1699 (data[(i)+2]=='i' || data[(i)+2]=='I') && \
1711 bool listMarkerSkipped=
FALSE;
1714 (!listMarkerSkipped &&
1715 (data[i]==
'+' || data[i]==
'-' || data[i]==
'*' ||
1716 (data[i]==
'#' && i>0 && data[i-1]==
'-') ||
1717 (isDigit=(data[i]>=
'1' && data[i]<=
'9')) ||
1718 (isLi=(i<size-3 &&
isLiTag(i)))
1727 while (j<size && ((data[j]>=
'0' && data[j]<=
'9') || data[j]==
'.'))
1731 if (j<size-1 && data[j+1]==
' ')
1733 listMarkerSkipped=
TRUE;
1750 listMarkerSkipped=
TRUE;
1752 else if (data[i]==
'-' && i<size-2 && data[i+1]==
'#' && data[i+2]==
' ')
1754 listMarkerSkipped=
TRUE;
1758 else if (data[i]!=
' ' && i<size-1 && data[i+1]==
' ')
1760 listMarkerSkipped=
TRUE;
1762 if (data[i]!=
' ' && !listMarkerSkipped)
1776 int normalIndent = 0;
1777 while (normalIndent<size && data[normalIndent]==
' ') normalIndent++;
1779 int result = listIndent>normalIndent ? listIndent : 0;
1796 else if (data[i]==
'\n')
1800 else if (data[i]!=
' ' && data[i]!=
'\t')
1820 while (i<size && data[i]==
' ') indent++,i++;
1821 if (indent>=refIndent+4)
1828 if (i<size && data[i]==
'`') tildaChar=
'`';
1829 while (i<size && data[i]==tildaChar) startTildes++,i++;
1836 if (i<size && data[i]==
'{') i++;
1838 while (i<size && (data[i]!=
'\n' && data[i]!=
'}' && data[i]!=
' ')) i++;
1840 while (i<size && data[i]!=
'\n') i++;
1844 if (data[i]==tildaChar)
1848 while (i<size && data[i]==tildaChar) endTildes++,i++;
1849 while (i<size && data[i]==
' ') i++;
1850 if (i==size || data[i]==
'\n')
1852 if (endTildes==startTildes)
1868 static bool isCodeBlock(
const char *data,
int offset,
int size,
int &indent)
1875 while (i<size && data[i]==
' ') indent0++,i++;
1883 if (indent0>=size || data[indent0]==
'\n')
1900 nl_pos[nl++]=j+nl_size;
1906 if (i==0 && nl==2) nl_pos[nl++]=-offset;
1917 if (!
isEmptyLine(data+nl_pos[1],nl_pos[0]-nl_pos[1]-1))
1964 while (i<size && data[i]==
' ') i++;
1965 if (i<size && data[i]==
'|' && data[i]!=
'\n') i++,n++;
1972 while (i<size && (j =
isNewline(data + i))==0) i++;
1976 while (i>0 && data[i]==
' ') i--;
1977 if (i>0 && data[i-1]!=
'\\' && data[i]==
'|') i--,n++;
1987 if (data[i]==
'|' && (i==0 || data[i-1]!=
'\\')) columns++;
1988 if (columns==1) columns++;
1992 if (n==2 && columns==0)
2010 if (i>=size || cc0<1)
2023 if (data[j]!=
':' && data[j]!=
'-' && data[j]!=
'|' && data[j]!=
' ')
2050 int columns,start,
end,cc;
2054 int headerStart = start;
2055 int headerEnd =
end;
2060 std::vector<int> columnAlignment(columns);
2063 bool startFound=
FALSE;
2069 if (data[j]==
':') { leftMarker=
TRUE; startFound=
TRUE; }
2070 if (data[j]==
'-') startFound=
TRUE;
2073 if (data[j]==
'-') rightMarker=
FALSE;
2074 else if (data[j]==
':') rightMarker=
TRUE;
2075 if (j<=
end+i && (data[j]==
'|' && (j==0 || data[j-1]!=
'\\')))
2099 std::vector<std::vector<TableCell> > tableContents;
2102 std::vector<TableCell> headerContents(columns);
2103 for (k=0;k<columns;k++)
2105 while (m<=headerEnd && (data[m]!=
'|' || (m>0 && data[m-1]==
'\\')))
2107 headerContents[k].cellText += data[m++];
2112 headerContents[k].colSpan = headerContents[k].cellText.isEmpty();
2113 headerContents[k].cellText = headerContents[k].cellText.stripWhiteSpace();
2115 tableContents.push_back(headerContents);
2121 if (cc!=columns)
break;
2125 std::vector<TableCell> rowContents(columns);
2128 if (j<=
end+i && (data[j]==
'|' && (j==0 || data[j-1]!=
'\\')))
2132 rowContents[k].colSpan = rowContents[k].cellText.isEmpty();
2133 rowContents[k].cellText = rowContents[k].cellText.stripWhiteSpace();
2138 rowContents[k].cellText += data[j];
2144 rowContents[k].colSpan = rowContents[k].cellText.isEmpty();
2145 rowContents[k].cellText = rowContents[k].cellText.stripWhiteSpace();
2146 tableContents.push_back(rowContents);
2153 QCString cellTag(
"th"), cellClass(
"class=\"markdownTableHead");
2154 for (
unsigned row = 0; row < tableContents.size(); row++)
2160 m_out.
addStr(
"\n<tr class=\"markdownTableRowOdd\">");
2164 m_out.
addStr(
"\n<tr class=\"markdownTableRowEven\">");
2169 m_out.
addStr(
"\n <tr class=\"markdownTableHead\">");
2171 for (
int c = 0; c < columns; c++)
2174 QCString cellText(tableContents[row][c].cellText);
2180 if (tableContents[row][c].cellText ==
"^")
2184 if (tableContents[row][c].colSpan)
2187 while ( cr >= 0 && tableContents[row][cr].colSpan)
2191 if (cr >= 0 && tableContents[row][cr].cellText ==
"^")
continue;
2193 unsigned rowSpan = 1, spanRow = row+1;
2194 while ((spanRow < tableContents.size()) &&
2195 (tableContents[spanRow][c].cellText ==
"^"))
2203 switch (columnAlignment[c])
2220 unsigned colSpan = 1;
2221 while ((c < columns-1) && tableContents[row][c+1].colSpan)
2234 m_out.
addStr(
"> " + cellText +
" \\ilinebr </" + cellTag +
">");
2237 cellClass =
"class=\"markdownTableBody";
2253 while (i<size && data[i]!=
'\n')
2255 if (data[i]!=
' ' && data[i]!=
'\t') j++;
2260 bool res = (j>0 && data[i-1]==
' ' && data[i-2]==
' ');
2279 if (level<5 && !
id.isEmpty())
2312 if (data[size-1] ==
'\n') tmpSize--;
2334 while (
end<=size && data[
end-1]!=
'\n')
end++;
2339 while (j<
end && (data[j]==
' ' || data[j]==
'>'))
2341 if (data[j]==
'>') { level++; indent=j+1; }
2342 else if (j>0 && data[j-1]==
'>') indent=j+1;
2345 if (j>0 && data[j-1]==
'>' &&
2346 !(j==size || data[j]==
'\n'))
2352 if (!level && data[j-1]!=
'\n') level=curLevel;
2355 for (l=curLevel;l<level-1;l++)
2361 else if (level<curLevel)
2363 for (l=level;l<curLevel;l++)
2369 if (level==0)
break;
2376 for (l=0;l<curLevel;l++)
2396 while (
end<=size && data[
end-1]!=
'\n')
end++;
2399 while (j<
end && data[j]==
' ') j++,indent++;
2409 while (emptyLines>0)
2425 while (emptyLines>0)
2439 int &pi,
int&i,
int &
end)
2451 if ((data[
end-1]==
'\\' || data[
end-1]==
'@') &&
2452 (
end<=1 || (data[
end-2]!=
'\\' && data[
end-2]!=
'@'))
2459 int l = endBlockName.
length();
2460 for (;
end<size-l-1;
end++)
2462 if ((data[
end]==
'\\' || data[
end]==
'@') &&
2463 data[
end-1]!=
'\\' && data[
end-1]!=
'@'
2477 else if (nb==0 && data[
end-1]==
'<' &&
end<size-6 &&
2478 (
end<=1 || (data[
end-2]!=
'\\' && data[
end-2]!=
'@'))
2481 if (tolower(data[
end])==
'p' && tolower(data[
end+1])==
'r' &&
2482 tolower(data[
end+2])==
'e' && (data[
end+3]==
'>' || data[
end+3]==
' '))
2493 else if (nb==0 && data[
end-1]==
'`')
2495 while (
end<=size && data[
end-1]==
'`')
end++,nb++;
2497 else if (nb>0 && data[
end-1]==
'`')
2500 while (
end<=size && data[
end-1]==
'`')
end++,enb++;
2513 int blockStart,
int blockEnd)
2517 if (!lang.
isEmpty() && lang.
at(0)==
'.') lang=lang.
mid(1);
2518 while (*data==
' ' || *data==
'\t')
2537 const char *data = s.
data();
2539 int i=0,
end=0,pi=-1;
2540 int blockStart,blockEnd,blockOffset;
2541 bool newBlock =
false;
2542 bool insideList =
false;
2543 int currentIndent = refIndent;
2544 int listIndent = refIndent;
2552 while (lineIndent<
end && data[i+lineIndent]==
' ') lineIndent++;
2558 if (insideList && lineIndent<currentIndent)
2561 currentIndent = refIndent;
2569 if (listIndent<currentIndent+4)
2573 currentIndent = listIndent;
2580 currentIndent = listIndent;
2591 if (
isFencedCodeBlock(data+pi,size-pi,currentIndent,lang,blockStart,blockEnd,blockOffset))
2615 if (pi!=-1 && pi<size)
2638 const char *data = s.
data();
2640 int i=0,
end=0,pi=-1,ref,level;
2642 int blockIndent = indent;
2647 while (
end<=size && data[
end-1]!=
'\n')
2649 if (data[
end-1]==
' ') sp++;
2653 #if 0 // commented m_out, since starting with a comment block is probably a usage error
2666 int currentIndent = indent;
2667 int listIndent = indent;
2668 bool insideList =
false;
2669 bool newBlock =
false;
2677 while (lineIndent<
end && data[i+lineIndent]==
' ') lineIndent++;
2683 if (insideList && lineIndent<currentIndent)
2686 currentIndent = indent;
2687 blockIndent = indent;
2695 if (listIndent<currentIndent+4)
2699 currentIndent = listIndent;
2700 blockIndent = listIndent;
2707 currentIndent = listIndent;
2708 blockIndent = listIndent;
2722 int blockStart,blockEnd,blockOffset;
2724 blockIndent = currentIndent;
2727 if (data[i]==
'@' || data[i]==
'\\') endBlockName =
isBlockCommand(data+i,i,size-i);
2731 if (
isLinkRef(data+pi,i-pi,
id,link,title))
2741 int l = endBlockName.
length();
2744 if ((data[i]==
'\\' || data[i]==
'@') &&
2745 data[i-1]!=
'\\' && data[i-1]!=
'@')
2763 while (pi<size && data[pi]==
' ') pi++;
2772 m_out.
addStr(level==1?
"@section ":
"@subsection ");
2794 else if ((ref=
isLinkRef(data+pi,size-pi,
id,link,title)))
2803 else if (
isFencedCodeBlock(data+pi,size-pi,currentIndent,lang,blockStart,blockEnd,blockOffset))
2837 if (pi!=-1 && pi<size)
2839 if (
isLinkRef(data+pi,size-pi,
id,link,title))
2860 const char *data = docs.
data();
2863 int size=docs.
size();
2864 while (i<size && (data[i]==
' ' || data[i]==
'\n'))
2869 (data[i]==
'\\' || data[i]==
'@') &&
2870 (
qstrncmp(&data[i+1],
"page ",5)==0 ||
qstrncmp(&data[i+1],
"mainpage",8)==0)
2888 int size=docs.
size();
2890 const char *data = docs_org.
data();
2892 while (i<size && (data[i]==
' ' || data[i]==
'\n'))
2894 if (data[i]==
'\n') prepend++;
2899 while (end1<size && data[end1-1]!=
'\n') end1++;
2906 while (end2<size && data[end2-1]!=
'\n') end2++;
2910 docs+=
"\n\n"+docs_org.
mid(end2);
2920 docs+=docs_org.
mid(end1);
2939 const char *data = s.
data();
2942 const int maxIndent=1000000;
2943 int minIndent=maxIndent;
2946 signed char c = (
signed char)data[i++];
2951 int stop = tabSize - (col%tabSize);
2978 for (
int j=0;j<bytes-1 && c;j++)
2990 if (col<minIndent) minIndent=col;
2994 if (minIndent!=maxIndent) refIndent=minIndent;
else refIndent=0;
3004 if (input.
isEmpty())
return input;
3009 if (s.
at(s.
length()-1)!=
'\n') s +=
"\n";
3010 s =
detab(s,refIndent);
3036 const char *p = result.
data();
3039 while (*p==
' ') p++;
3040 while (*p==
'\n') {startNewlines++;p++;};
3043 if (p>result.
data())
3046 result = result.
mid(
static_cast<int>(p-result.
data()));
3059 if (i!=-1) baseFn = baseFn.
left(i);
3065 if (!
isId(c)) *p=
'_';
3090 const char *fileBuf,
3091 const std::shared_ptr<Entry> &root,
3094 std::shared_ptr<Entry> current = std::make_shared<Entry>();
3097 current->fileName = fileName;
3098 current->docFile = fileName;
3099 current->docLine = 1;
3105 if (
id.startsWith(
"autotoc_md"))
id =
"";
3106 int indentLevel=title.
isEmpty() ? 0 : -1;
3111 bool wasEmpty =
id.isEmpty();
3115 if (!mdfileAsMainPage.
isEmpty() &&
3116 (fn==mdfileAsMainPage ||
3121 docs.
prepend(
"@anchor " +
id +
"\\ilinebr ");
3122 docs.
prepend(
"@mainpage "+title+
"\\ilinebr ");
3124 else if (
id==
"mainpage" ||
id==
"index")
3126 if (title.
isEmpty()) title = titleFn;
3127 docs.
prepend(
"@anchor " +
id +
"\\ilinebr ");
3128 docs.
prepend(
"@mainpage "+title+
"\\ilinebr ");
3132 if (title.
isEmpty()) {title = titleFn;prepend=0;}
3134 docs.
prepend(
"@page "+
id+
" "+title+
"\\ilinebr ");
3136 for (
int i = 0; i < prepend; i++) docs.
prepend(
"\n");
3140 p->commentScanner.enterFile(fileName,lineNr);
3142 bool needsEntry =
FALSE;
3145 while (
p->commentScanner.parseCommentBlock(
3161 QCString docFile = current->docFile;
3162 root->moveToSubEntryAndRefresh(current);
3164 current->docFile = docFile;
3165 current->docLine = lineNr;
3170 root->moveToSubEntryAndKeep(current);
3172 p->commentScanner.leaveFile(fileName,lineNr);
static int computeIndentExcludingListMarkers(const char *data, int size)
void writeOneLineHeaderOrRuler(const char *data, int size)
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
QCString markdownFileNameToId(const QCString &fileName)
processes string s and converts markdown into doxygen/html commands.
static int isLinkRef(const char *data, int size, QCString &refid, QCString &link, QCString &title)
returns end of the link ref if this is indeed a link reference.
char * rawData()
Returns a writable pointer to the data.
Protection
Protection level of members
QCString stripExtensionGeneral(const QCString &fName, const QCString &ext)
int isAtxHeader(const char *data, int size, QCString &header, QCString &id, bool allowAdjustLevel)
QCString process(const QCString &input, int &startNewlines, bool fromParseInput=false)
static FileNameLinkedMap * imageNameLinkedMap
int isHeaderline(const char *data, int size, bool allowAdjustLevel)
returns whether the line is a setext-style hdr underline
int writeTableBlock(const char *data, int size)
uint length() const
Returns the length of the string, not counting the 0-terminator.
int processHtmlTagWrite(const char *data, int offset, int size, bool doWrite)
Process a HTML tag.
int processEmphasis1(const char *data, int size, char c)
process single emphasis
int findRev(char c, int index=-1, bool cs=TRUE) const
bool isEmpty() const
Returns TRUE iff the string is empty
bool match(const std::string &str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
std::unique_ptr< Private > p
void findEndOfLine(const char *data, int size, int &pi, int &i, int &end)
QCString processBlocks(const QCString &s, int indent)
uint size() const
Returns the length of the string, not counting the 0-terminator.
SrcLangExt
Language as given by extension
#define eol
The end of line string for this machine.
QCString extractPageTitle(QCString &docs, QCString &id, int &prepend)
std::function< int(const char *, int, int)> Action_t
virtual ~MarkdownOutlineParser()
static int isListMarker(const char *data, int size)
char & at(size_t i)
Returns a reference to the character at index i.
QCString isBlockCommand(const char *data, int offset, int size)
void addStr(const QCString &s)
int find(char c, int index=0, bool cs=TRUE) const
bool isURL(const QCString &url)
Checks whether the given url starts with a supported protocol
int qstrncmp(const char *str1, const char *str2, size_t len)
static bool hasLineBreak(const char *data, int size)
static bool isFlagSet(DebugMask mask)
Class representing a string buffer optimised for growing.
DirIterator end(const DirIterator &) noexcept
int processEmphasis(const char *data, int offset, int size)
void setIndentLevel(int level)
const char * strnstr(const char *haystack, const char *needle, size_t haystack_len)
static bool isExplicitPage(const QCString &docs)
returns TRUE if input string docs starts with @page or @mainpage command
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
#define Config_getInt(name)
static QCString escapeDoubleQuotes(const QCString &s)
QCString left(size_t len) const
std::unordered_map< std::string, LinkRef > m_linkRefs
int processNmdash(const char *data, int off, int size)
Process ndash and mdashes
const int codeBlockIndent
static ParserManager * parserManager
Trace(const QCString &func, const QCString &data)
std::unique_ptr< OutlineParserInterface > getOutlineParser(const QCString &extension)
Gets the interface to the parser associated with a given extension.
QCString processQuotations(const QCString &s, int refIndent)
static void print(DebugMask mask, int prio, const char *fmt,...)
int processCodeSpan(const char *data, int, int size)
'‘’ parsing a code span (assuming codespan != 0)
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
static QCString escapeSpecialChars(const QCString &s)
void writeFencedCodeBlock(const char *data, const char *lng, int blockStart, int blockEnd)
void parsePrototype(const QCString &text)
Callback function called by the comment block scanner.
static Alignment markersToAlignment(bool leftMarker, bool rightMarker)
helper function to convert presence of left and/or right alignment markers to a alignment value
int isNewline(const char *data)
int findTableColumns(const char *data, int size, int &start, int &end, int &columns)
Finds the location of the table's contains in the string data.
int processSpecialCommand(const char *data, int offset, int size)
static bool isFencedCodeBlock(const char *data, int size, int refIndent, QCString &lang, int &start, int &end, int &offset)
QCString detab(const QCString &s, int &refIndent)
void processInline(const char *data, int size)
Markdown(const QCString &fileName, int lineNr, int indentLevel=0)
int writeBlockQuote(const char *data, int size)
static bool isEmptyLine(const char *data, int size)
int findEmphasisChar(const char *data, int size, char c, int c_size)
looks for the next emph char, skipping other constructs, and stopping when either it is found,...
Object representing the matching results.
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
void setResult(const char *s)
void parseInput(const QCString &fileName, const char *fileBuf, const std::shared_ptr< Entry > &root, ClangTUParser *clangParser)
Parses a single input file with the goal to build an Entry tree.
static bool isEndOfList(const char *data, int size)
int writeCodeBlock(const char *data, int size, int refIndent)
int processQuoted(const char *data, int, int size)
Process quoted section "...", can contain one embedded newline
int processEmphasis2(const char *data, int size, char c)
process double emphasis
QCString externalLinkTarget(const bool parent)
QCString & setNum(short n)
Various UTF8 related helper functions.
uint8_t getUTF8CharNumBytes(char c)
Returns the number of bytes making up a single UTF8 character given the first byte in the sequence.
Markdown::Action_t m_actions[256]
const uchar g_utf8_nbsp[3]
int isUTF8NonBreakableSpace(const char *input)
Check if the first character pointed at by input is a non-breakable whitespace character.
bool isBlockQuote(const char *data, int size, int indent)
returns TRUE if this line starts a block quote
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
void addStrEscapeUtf8Nbsp(const char *s, int len)
Class representing a regular expression.
Helper class to process markdown formatted text
#define isOpenEmphChar(i)
Minimal replacement for QFileInfo.
std::string absFilePath() const
const char * qPrint(const char *s)
static bool isTableBlock(const char *data, int size)
Returns TRUE iff data points to the start of a table block
#define Config_getString(name)
static QCString extractTitleId(QCString &title, int level)
QCString getFileNameExtension(const QCString &fn)
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string
Clang parser object for a single translation unit, which consists of a source file and the directly o...
A model of a file symbol.
static bool isHRuler(const char *data, int size)
CommentScanner commentScanner
int processLink(const char *data, int, int size)
static QCString stripFromPath(const QCString &path, const StringVector &l)
bool isAbsolutePath(const QCString &fileName)
std::string fileName() const
void writeMarkdownImage(const char *fmt, bool explicitTitle, const QCString &title, const QCString &content, const QCString &link, const FileDef *fd)
Portable versions of functions that are platform dependent.
bool search(const std::string &str, Match &match, const Ex &re, size_t pos)
Search in a given string str starting at position pos for a match against regular expression re.
A bunch of utility functions.
static void convertStringFragment(QCString &result, const char *data, int size)
#define ignoreCloseEmphChar(i)
static bool isCodeBlock(const char *data, int offset, int size, int &indent)
QCString & prepend(const char *s)
bool resize(size_t newlen)
Resizes the string to hold newlen characters (this value should also count the 0-terminator).
void setResult(const QCString &s)
QCString & sprintf(const char *format,...)
int processHtmlTag(const char *data, int offset, int size)
int processEmphasis3(const char *data, int size, char c)
Parsing triple emphasis.
Trace(const QCString &func)
This is an alternative implementation of QCString.
void trace(const char *fmt,...)