Classes | Macros | Typedefs | Enumerations | Functions | Variables
markdown.cpp File Reference
#include <stdio.h>
#include <qglobal.h>
#include <qregexp.h>
#include <qfileinfo.h>
#include <qdict.h>
#include "markdown.h"
#include "growbuf.h"
#include "debug.h"
#include "util.h"
#include "doxygen.h"
#include "commentscan.h"
#include "entry.h"
#include "bufstr.h"
#include "commentcnv.h"
#include "config.h"
#include "section.h"
#include "message.h"

Go to the source code of this file.

Classes

struct  LinkRef
 

Macros

#define isIdChar(i)
 
#define isOpenEmphChar(i)
 
#define ignoreCloseEmphChar(i)
 
#define isLiTag(i)
 

Typedefs

typedef int(* action_t) (GrowBuf &out, const char *data, int offset, int size)
 

Enumerations

enum  Alignment { AlignNone, AlignLeft, AlignCenter, AlignRight }
 

Functions

static QDict< LinkRefg_linkRefs (257)
 
static void processInline (GrowBuf &out, const char *data, int size)
 
static QCString escapeSpecialChars (const QCString &s)
 
static void convertStringFragment (QCString &result, const char *data, int size)
 
static Alignment markersToAlignment (bool leftMarker, bool rightMarker)
 
static QCString isBlockCommand (const char *data, int offset, int size)
 
static int findEmphasisChar (const char *data, int size, char c, int c_size)
 
static int processEmphasis1 (GrowBuf &out, const char *data, int size, char c)
 
static int processEmphasis2 (GrowBuf &out, const char *data, int size, char c)
 
static int processEmphasis3 (GrowBuf &out, const char *data, int size, char c)
 
static int processNmdash (GrowBuf &out, const char *data, int off, int size)
 
static int processQuoted (GrowBuf &out, const char *data, int, int size)
 
static int processHtmlTag (GrowBuf &out, const char *data, int offset, int size)
 
static int processEmphasis (GrowBuf &out, const char *data, int offset, int size)
 
static int processLink (GrowBuf &out, const char *data, int, int size)
 
static int processCodeSpan (GrowBuf &out, const char *data, int, int size)
 
static int processSpecialCommand (GrowBuf &out, const char *data, int offset, int size)
 
static int isHeaderline (const char *data, int size)
 
static bool isBlockQuote (const char *data, int size, int indent)
 
static int isLinkRef (const char *data, int size, QCString &refid, QCString &link, QCString &title)
 
static int isHRuler (const char *data, int size)
 
static QCString extractTitleId (QCString &title)
 
static int isAtxHeader (const char *data, int size, QCString &header, QCString &id)
 
static int isEmptyLine (const char *data, int size)
 
static int computeIndentExcludingListMarkers (const char *data, int size)
 
static bool isFencedCodeBlock (const char *data, int size, int refIndent, QCString &lang, int &start, int &end, int &offset)
 
static bool isCodeBlock (const char *data, int offset, int size, int &indent)
 
int findTableColumns (const char *data, int size, int &start, int &end, int &columns)
 
static bool isTableBlock (const char *data, int size)
 
static int writeTableBlock (GrowBuf &out, const char *data, int size)
 
void writeOneLineHeaderOrRuler (GrowBuf &out, const char *data, int size)
 
static int writeBlockQuote (GrowBuf &out, const char *data, int size)
 
static int writeCodeBlock (GrowBuf &out, const char *data, int size, int refIndent)
 
static void findEndOfLine (GrowBuf &out, const char *data, int size, int &pi, int &i, int &end)
 
static void writeFencedCodeBlock (GrowBuf &out, const char *data, const char *lng, int blockStart, int blockEnd)
 
static QCString processQuotations (const QCString &s, int refIndent)
 
static QCString processBlocks (const QCString &s, int indent)
 
static QCString extractPageTitle (QCString &docs, QCString &id)
 
static QCString detab (const QCString &s, int &refIndent)
 
QCString processMarkdown (const QCString &fileName, const int lineNr, Entry *e, const QCString &input)
 
QCString markdownFileNameToId (const QCString &fileName)
 

Variables

static action_t g_actions [256]
 
static Entryg_current
 
static QCString g_fileName
 
static int g_lineNr
 
const int codeBlockIndent = 4
 

Macro Definition Documentation

#define ignoreCloseEmphChar (   i)
Value:
(data[i]=='(' || data[i]=='{' || data[i]=='[' || data[i]=='<' || \
data[i]=='=' || data[i]=='+' || data[i]=='-' || data[i]=='\\' || \
data[i]=='@')

Definition at line 70 of file markdown.cpp.

#define isIdChar (   i)
Value:
((data[i]>='a' && data[i]<='z') || \
(data[i]>='A' && data[i]<='Z') || \
(data[i]>='0' && data[i]<='9') || \
(((unsigned char)data[i])>=0x80))

Definition at line 56 of file markdown.cpp.

#define isLiTag (   i)
Value:
(data[(i)]=='<' && \
(data[(i)+1]=='l' || data[(i)+1]=='L') && \
(data[(i)+2]=='i' || data[(i)+2]=='I') && \
(data[(i)+3]=='>'))

Definition at line 1301 of file markdown.cpp.

#define isOpenEmphChar (   i)
Value:
(data[i]=='\n' || data[i]==' ' || data[i]=='\'' || data[i]=='<' || \
data[i]=='{' || data[i]=='(' || data[i]=='[' || data[i]==',' || \
data[i]==':' || data[i]==';')

Definition at line 63 of file markdown.cpp.

Typedef Documentation

typedef int(* action_t) (GrowBuf &out, const char *data, int offset, int size)

Definition at line 84 of file markdown.cpp.

Enumeration Type Documentation

enum Alignment
Enumerator
AlignNone 
AlignLeft 
AlignCenter 
AlignRight 

Definition at line 86 of file markdown.cpp.

Function Documentation

static int computeIndentExcludingListMarkers ( const char *  data,
int  size 
)
static

Definition at line 1309 of file markdown.cpp.

1310 {
1311  int i=0;
1312  int indent=0;
1313  bool isDigit=FALSE;
1314  bool isLi=FALSE;
1315  bool listMarkerSkipped=FALSE;
1316  while (i<size &&
1317  (data[i]==' ' || // space
1318  (!listMarkerSkipped && // first list marker
1319  (data[i]=='+' || data[i]=='-' || data[i]=='*' || // unordered list char
1320  (data[i]=='#' && i>0 && data[i-1]=='-') || // -# item
1321  (isDigit=(data[i]>='1' && data[i]<='9')) || // ordered list marker?
1322  (isLi=(i<size-3 && isLiTag(i))) // <li> tag
1323  )
1324  )
1325  )
1326  )
1327  {
1328  if (isDigit) // skip over ordered list marker '10. '
1329  {
1330  int j=i+1;
1331  while (j<size && ((data[j]>='0' && data[j]<='9') || data[j]=='.'))
1332  {
1333  if (data[j]=='.') // should be end of the list marker
1334  {
1335  if (j<size-1 && data[j+1]==' ') // valid list marker
1336  {
1337  listMarkerSkipped=TRUE;
1338  indent+=j+1-i;
1339  i=j+1;
1340  break;
1341  }
1342  else // not a list marker
1343  {
1344  break;
1345  }
1346  }
1347  j++;
1348  }
1349  }
1350  else if (isLi)
1351  {
1352  i+=3; // skip over <li>
1353  indent+=3;
1354  listMarkerSkipped=TRUE;
1355  }
1356  else if (data[i]=='-' && i<size-2 && data[i+1]=='#' && data[i+2]==' ')
1357  { // case "-# "
1358  listMarkerSkipped=TRUE; // only a single list marker is accepted
1359  i++; // skip over #
1360  indent++;
1361  }
1362  else if (data[i]!=' ' && i<size-1 && data[i+1]==' ')
1363  { // case "- " or "+ " or "* "
1364  listMarkerSkipped=TRUE; // only a single list marker is accepted
1365  }
1366  if (data[i]!=' ' && !listMarkerSkipped)
1367  { // end of indent
1368  break;
1369  }
1370  indent++,i++;
1371  }
1372  //printf("{%s}->%d\n",QCString(data).left(size).data(),indent);
1373  return indent;
1374 }
const bool FALSE
Definition: qglobal.h:370
#define isLiTag(i)
Definition: markdown.cpp:1301
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
const bool TRUE
Definition: qglobal.h:371
static void convertStringFragment ( QCString result,
const char *  data,
int  size 
)
static

Definition at line 132 of file markdown.cpp.

133 {
134  if (size<0) size=0;
135  result.resize(size+1);
136  memcpy(result.rawData(),data,size);
137  result.at(size)='\0';
138 }
bool resize(uint newlen)
Definition: qcstring.h:225
char * rawData() const
Definition: qcstring.h:216
char & at(uint i) const
Definition: qcstring.h:326
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static QCString detab ( const QCString s,
int &  refIndent 
)
static

Definition at line 2241 of file markdown.cpp.

2242 {
2243  static int tabSize = Config_getInt("TAB_SIZE");
2244  GrowBuf out;
2245  int size = s.length();
2246  const char *data = s.data();
2247  int i=0;
2248  int col=0;
2249  const int maxIndent=1000000; // value representing infinity
2250  int minIndent=maxIndent;
2251  while (i<size)
2252  {
2253  char c = data[i++];
2254  switch(c)
2255  {
2256  case '\t': // expand tab
2257  {
2258  int stop = tabSize - (col%tabSize);
2259  //printf("expand at %d stop=%d\n",col,stop);
2260  col+=stop;
2261  while (stop--) out.addChar(' ');
2262  }
2263  break;
2264  case '\n': // reset colomn counter
2265  out.addChar(c);
2266  col=0;
2267  break;
2268  case ' ': // increment column counter
2269  out.addChar(c);
2270  col++;
2271  break;
2272  default: // non-whitespace => update minIndent
2273  out.addChar(c);
2274  if (c<0 && i<size) // multibyte sequence
2275  {
2276  out.addChar(data[i++]); // >= 2 bytes
2277  if (((uchar)c&0xE0)==0xE0 && i<size)
2278  {
2279  out.addChar(data[i++]); // 3 bytes
2280  }
2281  if (((uchar)c&0xF0)==0xF0 && i<size)
2282  {
2283  out.addChar(data[i++]); // 4 byres
2284  }
2285  }
2286  if (col<minIndent) minIndent=col;
2287  col++;
2288  }
2289  }
2290  if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
2291  out.addChar(0);
2292  //printf("detab refIndent=%d\n",refIndent);
2293  return out.get();
2294 }
uint length() const
Definition: qcstring.h:195
unsigned char uchar
Definition: nybbler.cc:11
#define Config_getInt(val)
Definition: config.cpp:661
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
void addChar(char c)
Definition: growbuf.h:16
const char * data() const
Definition: qcstring.h:207
const char * get()
Definition: growbuf.h:38
static QCString escapeSpecialChars ( const QCString s)
static

Definition at line 111 of file markdown.cpp.

112 {
113  if (s.isEmpty()) return "";
114  GrowBuf growBuf;
115  const char *p=s;
116  char c;
117  while ((c=*p++))
118  {
119  switch (c)
120  {
121  case '<': growBuf.addStr("\\<"); break;
122  case '>': growBuf.addStr("\\>"); break;
123  case '\\': growBuf.addStr("\\\\"); break;
124  case '@': growBuf.addStr("\\@"); break;
125  default: growBuf.addChar(c); break;
126  }
127  }
128  growBuf.addChar(0);
129  return growBuf.get();
130 }
void addStr(const char *s)
Definition: growbuf.h:19
bool isEmpty() const
Definition: qcstring.h:189
void addChar(char c)
Definition: growbuf.h:16
p
Definition: test.py:223
const char * get()
Definition: growbuf.h:38
static QCString * s
Definition: config.cpp:1042
static QCString extractPageTitle ( QCString docs,
QCString id 
)
static

Definition at line 2198 of file markdown.cpp.

2199 {
2200  int ln=0;
2201  // first first non-empty line
2202  QCString title;
2203  const char *data = docs.data();
2204  int i=0;
2205  int size=docs.size();
2206  while (i<size && (data[i]==' ' || data[i]=='\n'))
2207  {
2208  if (data[i]=='\n') ln++;
2209  i++;
2210  }
2211  if (i>=size) return "";
2212  int end1=i+1;
2213  while (end1<size && data[end1-1]!='\n') end1++;
2214  //printf("i=%d end1=%d size=%d line='%s'\n",i,end1,size,docs.mid(i,end1-i).data());
2215  // first line from i..end1
2216  if (end1<size)
2217  {
2218  ln++;
2219  // second line form end1..end2
2220  int end2=end1+1;
2221  while (end2<size && data[end2-1]!='\n') end2++;
2222  if (isHeaderline(data+end1,size-end1))
2223  {
2224  convertStringFragment(title,data+i,end1-i-1);
2225  QCString lns;
2226  lns.fill('\n',ln);
2227  docs=lns+docs.mid(end2);
2228  id = extractTitleId(title);
2229  //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
2230  return title;
2231  }
2232  }
2233  if (i<end1 && isAtxHeader(data+i,end1-i,title,id)>0)
2234  {
2235  docs=docs.mid(end1);
2236  }
2237  //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
2238  return title;
2239 }
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
static int isAtxHeader(const char *data, int size, QCString &header, QCString &id)
Definition: markdown.cpp:1252
uint size() const
Definition: qcstring.h:201
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int isHeaderline(const char *data, int size)
Definition: markdown.cpp:1069
static QCString extractTitleId(QCString &title)
Definition: markdown.cpp:1234
const char * data() const
Definition: qcstring.h:207
QCString mid(uint index, uint len=0xffffffff) const
Definition: qcstring.cpp:246
bool fill(char c, int len=-1)
Definition: qcstring.h:243
static QCString extractTitleId ( QCString title)
static

Definition at line 1234 of file markdown.cpp.

1235 {
1236  //static QRegExp r1("^[a-z_A-Z][a-z_A-Z0-9\\-]*:");
1237  static QRegExp r2("\\{#[a-z_A-Z][a-z_A-Z0-9\\-]*\\}");
1238  int l=0;
1239  int i = r2.match(title,0,&l);
1240  if (i!=-1 && title.mid(i+l).stripWhiteSpace().isEmpty()) // found {#id} style id
1241  {
1242  QCString id = title.mid(i+2,l-3);
1243  title = title.left(i);
1244  //printf("found id='%s' title='%s'\n",id.data(),title.data());
1245  return id;
1246  }
1247  //printf("no id found in title '%s'\n",title.data());
1248  return "";
1249 }
QCString stripWhiteSpace() const
Definition: qcstring.cpp:295
bool isEmpty() const
Definition: qcstring.h:189
The QRegExp class provides pattern matching using regular expressions or wildcards.
Definition: qregexp.h:46
QCString left(uint len) const
Definition: qcstring.cpp:213
static QStrList * l
Definition: config.cpp:1044
QCString mid(uint index, uint len=0xffffffff) const
Definition: qcstring.cpp:246
static int findEmphasisChar ( const char *  data,
int  size,
char  c,
int  c_size 
)
static

looks for the next emph char, skipping other constructs, and stopping when either it is found, or we are at the end of a paragraph.

Definition at line 237 of file markdown.cpp.

238 {
239  int i = 1;
240 
241  while (i<size)
242  {
243  while (i<size && data[i]!=c && data[i]!='`' &&
244  data[i]!='\\' && data[i]!='@' &&
245  data[i]!='\n') i++;
246  //printf("findEmphasisChar: data=[%s] i=%d c=%c\n",data,i,data[i]);
247 
248  // not counting escaped chars or characters that are unlikely
249  // to appear as the end of the emphasis char
250  if (i>0 && ignoreCloseEmphChar(i-1))
251  {
252  i++;
253  continue;
254  }
255  else
256  {
257  // get length of emphasis token
258  int len = 0;
259  while (i+len<size && data[i+len]==c)
260  {
261  len++;
262  }
263 
264  if (len>0)
265  {
266  if (len!=c_size || (i<size-len && isIdChar(i+len))) // to prevent touching some_underscore_identifier
267  {
268  i=i+len;
269  continue;
270  }
271  return i; // found it
272  }
273  }
274 
275  // skipping a code span
276  if (data[i]=='`')
277  {
278  int snb=0;
279  while (i<size && data[i]=='`') snb++,i++;
280 
281  // find same pattern to end the span
282  int enb=0;
283  while (i<size && enb<snb)
284  {
285  if (data[i]=='`') enb++;
286  if (snb==1 && data[i]=='\'') break; // ` ended by '
287  i++;
288  }
289  }
290  else if (data[i]=='@' || data[i]=='\\')
291  { // skip over blocks that should not be processed
292  QCString endBlockName = isBlockCommand(data+i,i,size-i);
293  if (!endBlockName.isEmpty())
294  {
295  i++;
296  int l = endBlockName.length();
297  while (i<size-l)
298  {
299  if ((data[i]=='\\' || data[i]=='@') && // command
300  data[i-1]!='\\' && data[i-1]!='@') // not escaped
301  {
302  if (qstrncmp(&data[i+1],endBlockName,l)==0)
303  {
304  break;
305  }
306  }
307  i++;
308  }
309  }
310  else if (i<size-1 && isIdChar(i+1)) // @cmd, stop processing, see bug 690385
311  {
312  return 0;
313  }
314  else
315  {
316  i++;
317  }
318  }
319  else if (data[i]=='\n') // end * or _ at paragraph boundary
320  {
321  i++;
322  while (i<size && data[i]==' ') i++;
323  if (i>=size || data[i]=='\n') return 0; // empty line -> paragraph
324  }
325  else // should not get here!
326  {
327  i++;
328  }
329 
330  }
331  return 0;
332 }
Q_EXPORT int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qcstring.h:101
#define ignoreCloseEmphChar(i)
Definition: markdown.cpp:70
bool isEmpty() const
Definition: qcstring.h:189
uint length() const
Definition: qcstring.h:195
static QStrList * l
Definition: config.cpp:1044
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static QCString isBlockCommand(const char *data, int offset, int size)
Definition: markdown.cpp:183
#define isIdChar(i)
Definition: markdown.cpp:56
static void findEndOfLine ( GrowBuf out,
const char *  data,
int  size,
int &  pi,
int &  i,
int &  end 
)
static

Definition at line 1875 of file markdown.cpp.

1877 {
1878  // find end of the line
1879  int nb=0;
1880  end=i+1;
1881  while (end<=size && data[end-1]!='\n')
1882  {
1883  // while looking for the end of the line we might encounter a block
1884  // that needs to be passed unprocessed.
1885  if ((data[end-1]=='\\' || data[end-1]=='@') && // command
1886  (end<=1 || (data[end-2]!='\\' && data[end-2]!='@')) // not escaped
1887  )
1888  {
1889  QCString endBlockName = isBlockCommand(data+end-1,end-1,size-(end-1));
1890  end++;
1891  if (!endBlockName.isEmpty())
1892  {
1893  int l = endBlockName.length();
1894  for (;end<size-l-1;end++) // search for end of block marker
1895  {
1896  if ((data[end]=='\\' || data[end]=='@') &&
1897  data[end-1]!='\\' && data[end-1]!='@'
1898  )
1899  {
1900  if (qstrncmp(&data[end+1],endBlockName,l)==0)
1901  {
1902  if (pi!=-1) // output previous line if available
1903  {
1904  //printf("feol out={%s}\n",QCString(data+pi).left(i-pi).data());
1905  out.addStr(data+pi,i-pi);
1906  }
1907  // found end marker, skip over this block
1908  //printf("feol.block out={%s}\n",QCString(data+i).left(end+l+1-i).data());
1909  out.addStr(data+i,end+l+1-i);
1910  pi=-1;
1911  i=end+l+1; // continue after block
1912  end=i+1;
1913  break;
1914  }
1915  }
1916  }
1917  }
1918  }
1919  else if (nb==0 && data[end-1]=='<' && end<size-6 &&
1920  (end<=1 || (data[end-2]!='\\' && data[end-2]!='@'))
1921  )
1922  {
1923  if (tolower(data[end])=='p' && tolower(data[end+1])=='r' &&
1924  tolower(data[end+2])=='e' && data[end+3]=='>') // <pre> tag
1925  {
1926  if (pi!=-1) // output previous line if available
1927  {
1928  out.addStr(data+pi,i-pi);
1929  }
1930  // output part until <pre>
1931  out.addStr(data+i,end-1-i);
1932  // output part until </pre>
1933  i = end-1 + processHtmlTag(out,data+end-1,end-1,size-end+1);
1934  pi=-1;
1935  end = i+1;
1936  break;
1937  }
1938  else
1939  {
1940  end++;
1941  }
1942  }
1943  else if (nb==0 && data[end-1]=='`')
1944  {
1945  while (end<=size && data[end-1]=='`') end++,nb++;
1946  }
1947  else if (nb>0 && data[end-1]=='`')
1948  {
1949  int enb=0;
1950  while (end<=size && data[end-1]=='`') end++,enb++;
1951  if (enb==nb) nb=0;
1952  }
1953  else
1954  {
1955  end++;
1956  }
1957  }
1958  //printf("findEndOfLine pi=%d i=%d end=%d {%s}\n",pi,i,end,QCString(data+i).left(end-i).data());
1959 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
Q_EXPORT int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qcstring.h:101
static constexpr double nb
Definition: Units.h:81
void addStr(const char *s)
Definition: growbuf.h:19
bool isEmpty() const
Definition: qcstring.h:189
uint length() const
Definition: qcstring.h:195
static int processHtmlTag(GrowBuf &out, const char *data, int offset, int size)
Definition: markdown.cpp:505
static QStrList * l
Definition: config.cpp:1044
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
float pi
Definition: units.py:11
static QCString isBlockCommand(const char *data, int offset, int size)
Definition: markdown.cpp:183
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. Only one line will be inspected.

Parameters
[in]datapointer to the string buffer.
[in]sizethe size of the buffer.
[out]startoffset of the first character of the table content
[out]endoffset of the last character of the table content
[out]columnsnumber of table columns found
Returns
The offset until the next line in the buffer.

Definition at line 1491 of file markdown.cpp.

1492 {
1493  int i=0,n=0;
1494  int eol;
1495  // find start character of the table line
1496  while (i<size && data[i]==' ') i++;
1497  if (i<size && data[i]=='|' && data[i]!='\n') i++,n++; // leading | does not count
1498  start = i;
1499 
1500  // find end character of the table line
1501  while (i<size && data[i]!='\n') i++;
1502  eol=i+1;
1503  i--;
1504  while (i>0 && data[i]==' ') i--;
1505  if (i>0 && data[i-1]!='\\' && data[i]=='|') i--,n++; // trailing or escaped | does not count
1506  end = i;
1507 
1508  // count columns between start and end
1509  columns=0;
1510  if (end>start)
1511  {
1512  i=start;
1513  while (i<=end) // look for more column markers
1514  {
1515  if (data[i]=='|' && (i==0 || data[i-1]!='\\')) columns++;
1516  if (columns==1) columns++; // first | make a non-table into a two column table
1517  i++;
1518  }
1519  }
1520  if (n==2 && columns==0) // table row has | ... |
1521  {
1522  columns++;
1523  }
1524  //printf("findTableColumns(start=%d,end=%d,columns=%d) eol=%d\n",
1525  // start,end,columns,eol);
1526  return eol;
1527 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
#define eol
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
string columns
Definition: depos.py:13
std::void_t< T > n
static QDict<LinkRef> g_linkRefs ( 257  )
static
static int isAtxHeader ( const char *  data,
int  size,
QCString header,
QCString id 
)
static

Definition at line 1252 of file markdown.cpp.

1254 {
1255  int i = 0, end;
1256  int level = 0, blanks=0;
1257 
1258  // find start of header text and determine heading level
1259  while (i<size && data[i]==' ') i++;
1260  if (i>=size || data[i]!='#')
1261  {
1262  return 0;
1263  }
1264  while (i<size && level<6 && data[i]=='#') i++,level++;
1265  while (i<size && data[i]==' ') i++,blanks++;
1266  if (level==1 && blanks==0)
1267  {
1268  return 0; // special case to prevent #someid seen as a header (see bug 671395)
1269  }
1270 
1271  // find end of header text
1272  end=i;
1273  while (end<size && data[end]!='\n') end++;
1274  while (end>i && (data[end-1]=='#' || data[end-1]==' ')) end--;
1275 
1276  // store result
1277  convertStringFragment(header,data+i,end-i);
1278  id = extractTitleId(header);
1279  if (!id.isEmpty()) // strip #'s between title and id
1280  {
1281  i=header.length()-1;
1282  while (i>=0 && (header.at(i)=='#' || header.at(i)==' ')) i--;
1283  header=header.left(i+1);
1284  }
1285 
1286  return level;
1287 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
uint length() const
Definition: qcstring.h:195
char & at(uint i) const
Definition: qcstring.h:326
QCString left(uint len) const
Definition: qcstring.cpp:213
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static QCString extractTitleId(QCString &title)
Definition: markdown.cpp:1234
static QCString isBlockCommand ( const char *  data,
int  offset,
int  size 
)
static

Definition at line 183 of file markdown.cpp.

184 {
185  bool openBracket = offset>0 && data[-1]=='{';
186  bool isEscaped = offset>0 && (data[-1]=='\\' || data[-1]=='@');
187  if (isEscaped) return QCString();
188 
189  int end=1;
190  while (end<size && (data[end]>='a' && data[end]<='z')) end++;
191  if (end==1) return QCString();
193  convertStringFragment(blockName,data+1,end-1);
194  if (blockName=="code" && openBracket)
195  {
196  return "}";
197  }
198  else if (blockName=="dot" ||
199  blockName=="code" ||
200  blockName=="msc" ||
201  blockName=="verbatim" ||
202  blockName=="latexonly" ||
203  blockName=="htmlonly" ||
204  blockName=="xmlonly" ||
205  blockName=="rtfonly" ||
206  blockName=="manonly" ||
207  blockName=="docbookonly"
208  )
209  {
210  return "end"+blockName;
211  }
212  else if (blockName=="startuml")
213  {
214  return "enduml";
215  }
216  else if (blockName=="f" && end<size)
217  {
218  if (data[end]=='$')
219  {
220  return "f$";
221  }
222  else if (data[end]=='[')
223  {
224  return "f]";
225  }
226  else if (data[end]=='}')
227  {
228  return "f}";
229  }
230  }
231  return QCString();
232 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
static QCString blockName
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static bool isBlockQuote ( const char *  data,
int  size,
int  indent 
)
static

returns TRUE if this line starts a block quote

Definition at line 1092 of file markdown.cpp.

1093 {
1094  int i = 0;
1095  while (i<size && data[i]==' ') i++;
1096  if (i<indent+codeBlockIndent) // could be a quotation
1097  {
1098  // count >'s and skip spaces
1099  int level=0;
1100  while (i<size && (data[i]=='>' || data[i]==' '))
1101  {
1102  if (data[i]=='>') level++;
1103  i++;
1104  }
1105  // last characters should be a space or newline,
1106  // so a line starting with >= does not match
1107  return level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n');
1108  }
1109  else // too much indentation -> code block
1110  {
1111  return FALSE;
1112  }
1113  //return i<size && data[i]=='>' && i<indent+codeBlockIndent;
1114 }
const bool FALSE
Definition: qglobal.h:370
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
const int codeBlockIndent
Definition: markdown.cpp:106
static bool isCodeBlock ( const char *  data,
int  offset,
int  size,
int &  indent 
)
static

Definition at line 1415 of file markdown.cpp.

1416 {
1417  //printf("<isCodeBlock(offset=%d,size=%d,indent=%d)\n",offset,size,indent);
1418  // determine the indent of this line
1419  int i=0;
1420  int indent0=0;
1421  while (i<size && data[i]==' ') indent0++,i++;
1422 
1423  if (indent0<codeBlockIndent)
1424  {
1425  //printf(">isCodeBlock: line is not indented enough %d<4\n",indent0);
1426  return FALSE;
1427  }
1428  if (indent0>=size || data[indent0]=='\n') // empty line does not start a code block
1429  {
1430  //printf("only spaces at the end of a comment block\n");
1431  return FALSE;
1432  }
1433 
1434  i=offset;
1435  int nl=0;
1436  int nl_pos[3];
1437  // search back 3 lines and remember the start of lines -1 and -2
1438  while (i>0 && nl<3)
1439  {
1440  if (data[i-offset-1]=='\n') nl_pos[nl++]=i-offset;
1441  i--;
1442  }
1443 
1444  // if there are only 2 preceding lines, then line -2 starts at -offset
1445  if (i==0 && nl==2) nl_pos[nl++]=-offset;
1446  //printf(" nl=%d\n",nl);
1447 
1448  if (nl==3) // we have at least 2 preceding lines
1449  {
1450  //printf(" positions: nl_pos=[%d,%d,%d] line[-2]='%s' line[-1]='%s'\n",
1451  // nl_pos[0],nl_pos[1],nl_pos[2],
1452  // QCString(data+nl_pos[1]).left(nl_pos[0]-nl_pos[1]-1).data(),
1453  // QCString(data+nl_pos[2]).left(nl_pos[1]-nl_pos[2]-1).data());
1454 
1455  // check that line -1 is empty
1456  if (!isEmptyLine(data+nl_pos[1],nl_pos[0]-nl_pos[1]-1))
1457  {
1458  return FALSE;
1459  }
1460 
1461  // determine the indent of line -2
1462  indent=computeIndentExcludingListMarkers(data+nl_pos[2],nl_pos[1]-nl_pos[2]);
1463 
1464  //printf(">isCodeBlock local_indent %d>=%d+4=%d\n",
1465  // indent0,indent2,indent0>=indent2+4);
1466  // if the difference is >4 spaces -> code block
1467  return indent0>=indent+codeBlockIndent;
1468  }
1469  else // not enough lines to determine the relative indent, use global indent
1470  {
1471  // check that line -1 is empty
1472  if (nl==1 && !isEmptyLine(data-offset,offset-1))
1473  {
1474  return FALSE;
1475  }
1476  //printf(">isCodeBlock global indent %d>=%d+4=%d nl=%d\n",
1477  // indent0,indent,indent0>=indent+4,nl);
1478  return indent0>=indent+codeBlockIndent;
1479  }
1480 }
static int computeIndentExcludingListMarkers(const char *data, int size)
Definition: markdown.cpp:1309
const bool FALSE
Definition: qglobal.h:370
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int isEmptyLine(const char *data, int size)
Definition: markdown.cpp:1289
const int codeBlockIndent
Definition: markdown.cpp:106
std::string indent0()
std::string nl(std::size_t i=1)
static int isEmptyLine ( const char *  data,
int  size 
)
static

Definition at line 1289 of file markdown.cpp.

1290 {
1291  int i=0;
1292  while (i<size)
1293  {
1294  if (data[i]=='\n') return TRUE;
1295  if (data[i]!=' ') return FALSE;
1296  i++;
1297  }
1298  return TRUE;
1299 }
const bool FALSE
Definition: qglobal.h:370
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
const bool TRUE
Definition: qglobal.h:371
static bool isFencedCodeBlock ( const char *  data,
int  size,
int  refIndent,
QCString lang,
int &  start,
int &  end,
int &  offset 
)
static

Definition at line 1376 of file markdown.cpp.

1378 {
1379  // rules: at least 3 ~~~, end of the block same amount of ~~~'s, otherwise
1380  // return FALSE
1381  int i=0;
1382  int indent=0;
1383  int startTildes=0;
1384  while (i<size && data[i]==' ') indent++,i++;
1385  if (indent>=refIndent+4) return FALSE; // part of code block
1386  char tildaChar='~';
1387  if (i<size && data[i]=='`') tildaChar='`';
1388  while (i<size && data[i]==tildaChar) startTildes++,i++;
1389  if (startTildes<3) return FALSE; // not enough tildes
1390  if (i<size && data[i]=='{') i++; // skip over optional {
1391  int startLang=i;
1392  while (i<size && (data[i]!='\n' && data[i]!='}' && data[i]!=' ')) i++;
1393  convertStringFragment(lang,data+startLang,i-startLang);
1394  while (i<size && data[i]!='\n') i++; // proceed to the end of the line
1395  start=i;
1396  while (i<size)
1397  {
1398  if (data[i]==tildaChar)
1399  {
1400  end=i-1;
1401  int endTildes=0;
1402  while (i<size && data[i]==tildaChar) endTildes++,i++;
1403  while (i<size && data[i]==' ') i++;
1404  if (i==size || data[i]=='\n')
1405  {
1406  offset=i;
1407  return endTildes==startTildes;
1408  }
1409  }
1410  i++;
1411  }
1412  return FALSE;
1413 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
const bool FALSE
Definition: qglobal.h:370
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int isHeaderline ( const char *  data,
int  size 
)
static

returns whether the line is a setext-style hdr underline

Definition at line 1069 of file markdown.cpp.

1070 {
1071  int i=0, c=0;
1072  while (i<size && data[i]==' ') i++;
1073 
1074  // test of level 1 header
1075  if (data[i]=='=')
1076  {
1077  while (i<size && data[i]=='=') i++,c++;
1078  while (i<size && data[i]==' ') i++;
1079  return (c>1 && (i>=size || data[i]=='\n')) ? 1 : 0;
1080  }
1081  // test of level 2 header
1082  if (data[i]=='-')
1083  {
1084  while (i<size && data[i]=='-') i++,c++;
1085  while (i<size && data[i]==' ') i++;
1086  return (c>1 && (i>=size || data[i]=='\n')) ? 2 : 0;
1087  }
1088  return 0;
1089 }
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int isHRuler ( const char *  data,
int  size 
)
static

Definition at line 1207 of file markdown.cpp.

1208 {
1209  int i=0;
1210  if (size>0 && data[size-1]=='\n') size--; // ignore newline character
1211  while (i<size && data[i]==' ') i++;
1212  if (i>=size) return 0; // empty line
1213  char c=data[i];
1214  if (c!='*' && c!='-' && c!='_')
1215  {
1216  return 0; // not a hrule character
1217  }
1218  int n=0;
1219  while (i<size)
1220  {
1221  if (data[i]==c)
1222  {
1223  n++; // count rule character
1224  }
1225  else if (data[i]!=' ')
1226  {
1227  return 0; // line contains non hruler characters
1228  }
1229  i++;
1230  }
1231  return n>=3; // at least 3 characters needed for a hruler
1232 }
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
std::void_t< T > n
static int isLinkRef ( const char *  data,
int  size,
QCString refid,
QCString link,
QCString title 
)
static

returns end of the link ref if this is indeed a link reference.

Definition at line 1117 of file markdown.cpp.

1119 {
1120  //printf("isLinkRef data={%s}\n",data);
1121  // format: start with [some text]:
1122  int i = 0;
1123  while (i<size && data[i]==' ') i++;
1124  if (i>=size || data[i]!='[') return 0;
1125  i++;
1126  int refIdStart=i;
1127  while (i<size && data[i]!='\n' && data[i]!=']') i++;
1128  if (i>=size || data[i]!=']') return 0;
1129  convertStringFragment(refid,data+refIdStart,i-refIdStart);
1130  if (refid.isEmpty()) return 0;
1131  //printf(" isLinkRef: found refid='%s'\n",refid.data());
1132  i++;
1133  if (i>=size || data[i]!=':') return 0;
1134  i++;
1135 
1136  // format: whitespace* \n? whitespace* (<url> | url)
1137  while (i<size && data[i]==' ') i++;
1138  if (i<size && data[i]=='\n')
1139  {
1140  i++;
1141  while (i<size && data[i]==' ') i++;
1142  }
1143  if (i>=size) return 0;
1144 
1145  if (i<size && data[i]=='<') i++;
1146  int linkStart=i;
1147  while (i<size && data[i]!=' ' && data[i]!='\n') i++;
1148  int linkEnd=i;
1149  if (i<size && data[i]=='>') i++;
1150  if (linkStart==linkEnd) return 0; // empty link
1151  convertStringFragment(link,data+linkStart,linkEnd-linkStart);
1152  //printf(" isLinkRef: found link='%s'\n",link.data());
1153  if (link=="@ref" || link=="\\ref")
1154  {
1155  int argStart=i;
1156  while (i<size && data[i]!='\n' && data[i]!='"') i++;
1157  QCString refArg;
1158  convertStringFragment(refArg,data+argStart,i-argStart);
1159  link+=refArg;
1160  }
1161 
1162  title.resize(0);
1163 
1164  // format: (whitespace* \n? whitespace* ( 'title' | "title" | (title) ))?
1165  int eol=0;
1166  while (i<size && data[i]==' ') i++;
1167  if (i<size && data[i]=='\n')
1168  {
1169  eol=i;
1170  i++;
1171  while (i<size && data[i]==' ') i++;
1172  }
1173  if (i>=size)
1174  {
1175  //printf("end of isLinkRef while looking for title! i=%d\n",i);
1176  return i; // end of buffer while looking for the optional title
1177  }
1178 
1179  char c = data[i];
1180  if (c=='\'' || c=='"' || c=='(') // optional title present?
1181  {
1182  //printf(" start of title found! char='%c'\n",c);
1183  i++;
1184  if (c=='(') c=')'; // replace c by end character
1185  int titleStart=i;
1186  // search for end of the line
1187  while (i<size && data[i]!='\n') i++;
1188  eol = i;
1189 
1190  // search back to matching character
1191  int end=i-1;
1192  while (end>titleStart && data[end]!=c) end--;
1193  if (end>titleStart)
1194  {
1195  convertStringFragment(title,data+titleStart,end-titleStart);
1196  }
1197  //printf(" title found: '%s'\n",title.data());
1198  }
1199  while (i<size && data[i]==' ') i++;
1200  //printf("end of isLinkRef: i=%d size=%d data[i]='%c' eol=%d\n",
1201  // i,size,data[i],eol);
1202  if (i>=size) return i; // end of buffer while ref id was found
1203  else if (eol) return eol; // end of line while ref id was found
1204  return 0; // invalid link ref
1205 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
bool resize(uint newlen)
Definition: qcstring.h:225
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
bool isEmpty() const
Definition: qcstring.h:189
#define eol
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static bool isTableBlock ( const char *  data,
int  size 
)
static

Returns TRUE iff data points to the start of a table block

Definition at line 1530 of file markdown.cpp.

1531 {
1532  int cc0,start,end;
1533 
1534  // the first line should have at least two columns separated by '|'
1535  int i = findTableColumns(data,size,start,end,cc0);
1536  if (i>=size || cc0<1)
1537  {
1538  //printf("isTableBlock: no |'s in the header\n");
1539  return FALSE;
1540  }
1541 
1542  int cc1;
1543  int ret = findTableColumns(data+i,size-i,start,end,cc1);
1544  int j=i+start;
1545  // separator line should consist of |, - and : and spaces only
1546  while (j<=end+i)
1547  {
1548  if (data[j]!=':' && data[j]!='-' && data[j]!='|' && data[j]!=' ')
1549  {
1550  //printf("isTableBlock: invalid character '%c'\n",data[j]);
1551  return FALSE; // invalid characters in table separator
1552  }
1553  j++;
1554  }
1555  if (cc1!=cc0) // number of columns should be same as previous line
1556  {
1557  return FALSE;
1558  }
1559 
1560  i+=ret; // goto next line
1561  int cc2;
1562  findTableColumns(data+i,size-i,start,end,cc2);
1563 
1564  //printf("isTableBlock: %d\n",cc1==cc2);
1565  return cc1==cc2;
1566 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
const bool FALSE
Definition: qglobal.h:370
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
int findTableColumns(const char *data, int size, int &start, int &end, int &columns)
Definition: markdown.cpp:1491
QCString markdownFileNameToId ( const QCString fileName)

Definition at line 2344 of file markdown.cpp.

2345 {
2346  QCString baseFn = stripFromPath(QFileInfo(fileName).absFilePath().utf8());
2347  int i = baseFn.findRev('.');
2348  if (i!=-1) baseFn = baseFn.left(i);
2349  QCString baseName = substitute(substitute(baseFn," ","_"),"/","_");
2350  return "md_"+baseName;
2351 }
QCString left(uint len) const
Definition: qcstring.cpp:213
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition: qcstring.cpp:95
static QCString stripFromPath(const QCString &path, QStrList &l)
Definition: util.cpp:274
static QCString baseName
Definition: scanner.cpp:10890
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:51
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition: util.cpp:5088
static Alignment markersToAlignment ( bool  leftMarker,
bool  rightMarker 
)
static

helper function to convert presence of left and/or right alignment markers to a alignment value

Definition at line 143 of file markdown.cpp.

144 {
145  //printf("markerToAlignment(%d,%d)\n",leftMarker,rightMarker);
146  if (leftMarker && rightMarker)
147  {
148  return AlignCenter;
149  }
150  else if (leftMarker)
151  {
152  return AlignLeft;
153  }
154  else if (rightMarker)
155  {
156  return AlignRight;
157  }
158  else
159  {
160  return AlignNone;
161  }
162 }
static QCString processBlocks ( const QCString s,
int  indent 
)
static

Definition at line 2034 of file markdown.cpp.

2035 {
2036  GrowBuf out;
2037  const char *data = s.data();
2038  int size = s.length();
2039  int i=0,end=0,pi=-1,ref,level;
2040  QCString id,link,title;
2041  int blockIndent = indent;
2042 
2043  // get indent for the first line
2044  end = i+1;
2045  int sp=0;
2046  while (end<=size && data[end-1]!='\n')
2047  {
2048  if (data[end-1]==' ') sp++;
2049  end++;
2050  }
2051 
2052 #if 0 // commented out, since starting with a comment block is probably a usage error
2053  // see also http://stackoverflow.com/q/20478611/784672
2054 
2055  // special case when the documentation starts with a code block
2056  // since the first line is skipped when looking for a code block later on.
2057  if (end>codeBlockIndent && isCodeBlock(data,0,end,blockIndent))
2058  {
2059  i=writeCodeBlock(out,data,size,blockIndent);
2060  end=i+1;
2061  pi=-1;
2062  }
2063 #endif
2064 
2065  // process each line
2066  while (i<size)
2067  {
2068  findEndOfLine(out,data,size,pi,i,end);
2069  // line is now found at [i..end)
2070 
2071  //printf("findEndOfLine: pi=%d i=%d end=%d\n",pi,i,end);
2072 
2073  if (pi!=-1)
2074  {
2075  int blockStart,blockEnd,blockOffset;
2076  QCString lang;
2077  blockIndent = indent;
2078  //printf("isHeaderLine(%s)=%d\n",QCString(data+i).left(size-i).data(),level);
2079  if ((level=isHeaderline(data+i,size-i))>0)
2080  {
2081  //if (level==1) g_correctSectionLevel=FALSE;
2082  //if (g_correctSectionLevel) level--;
2083  //printf("Found header at %d-%d\n",i,end);
2084  while (pi<size && data[pi]==' ') pi++;
2085  QCString header,id;
2086  convertStringFragment(header,data+pi,i-pi-1);
2087  id = extractTitleId(header);
2088  //printf("header='%s' is='%s'\n",header.data(),id.data());
2089  if (!header.isEmpty())
2090  {
2091  if (!id.isEmpty())
2092  {
2093  out.addStr(level==1?"@section ":"@subsection ");
2094  out.addStr(id);
2095  out.addStr(" ");
2096  out.addStr(header);
2097  out.addStr("\n\n");
2099  if (si)
2100  {
2101  if (si->lineNr != -1)
2102  {
2103  warn(g_fileName,g_lineNr,"multiple use of section label '%s', (first occurrence: %s, line %d)",header.data(),si->fileName.data(),si->lineNr);
2104  }
2105  else
2106  {
2107  warn(g_fileName,g_lineNr,"multiple use of section label '%s', (first occurrence: %s)",header.data(),si->fileName.data());
2108  }
2109  }
2110  else
2111  {
2112  si = new SectionInfo(g_fileName,g_lineNr,id,header,
2113  level==1 ? SectionInfo::Section : SectionInfo::Subsection,level);
2114  if (g_current)
2115  {
2116  g_current->anchors->append(si);
2117  }
2118  Doxygen::sectionDict->append(id,si);
2119  }
2120  }
2121  else
2122  {
2123  out.addStr(level==1?"<h1>":"<h2>");
2124  out.addStr(header);
2125  out.addStr(level==1?"\n</h1>\n":"\n</h2>\n");
2126  }
2127  }
2128  else
2129  {
2130  out.addStr("<hr>\n");
2131  }
2132  pi=-1;
2133  i=end;
2134  end=i+1;
2135  continue;
2136  }
2137  else if ((ref=isLinkRef(data+pi,size-pi,id,link,title)))
2138  {
2139  //printf("found link ref: id='%s' link='%s' title='%s'\n",
2140  // id.data(),link.data(),title.data());
2141  g_linkRefs.insert(id.lower(),new LinkRef(link,title));
2142  i=ref+pi;
2143  pi=-1;
2144  end=i+1;
2145  }
2146  else if (isFencedCodeBlock(data+pi,size-pi,indent,lang,blockStart,blockEnd,blockOffset))
2147  {
2148  //printf("Found FencedCodeBlock lang='%s' start=%d end=%d code={%s}\n",
2149  // lang.data(),blockStart,blockEnd,QCString(data+pi+blockStart).left(blockEnd-blockStart).data());
2150  writeFencedCodeBlock(out,data+pi,lang,blockStart,blockEnd);
2151  i=pi+blockOffset;
2152  pi=-1;
2153  end=i+1;
2154  continue;
2155  }
2156  else if (isCodeBlock(data+i,i,end-i,blockIndent))
2157  {
2158  // skip previous line (it is empty anyway)
2159  i+=writeCodeBlock(out,data+i,size-i,blockIndent);
2160  pi=-1;
2161  end=i+1;
2162  continue;
2163  }
2164  else if (isTableBlock(data+pi,size-pi))
2165  {
2166  i=pi+writeTableBlock(out,data+pi,size-pi);
2167  pi=-1;
2168  end=i+1;
2169  continue;
2170  }
2171  else
2172  {
2173  writeOneLineHeaderOrRuler(out,data+pi,i-pi);
2174  }
2175  }
2176  pi=i;
2177  i=end;
2178  }
2179  //printf("last line %d size=%d\n",i,size);
2180  if (pi!=-1 && pi<size) // deal with the last line
2181  {
2182  if (isLinkRef(data+pi,size-pi,id,link,title))
2183  {
2184  //printf("found link ref: id='%s' link='%s' title='%s'\n",
2185  // id.data(),link.data(),title.data());
2186  g_linkRefs.insert(id.lower(),new LinkRef(link,title));
2187  }
2188  else
2189  {
2190  writeOneLineHeaderOrRuler(out,data+pi,size-pi);
2191  }
2192  }
2193 
2194  out.addChar(0);
2195  return out.get();
2196 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
static bool isTableBlock(const char *data, int size)
Definition: markdown.cpp:1530
void addStr(const char *s)
Definition: growbuf.h:19
bool isEmpty() const
Definition: qcstring.h:189
uint length() const
Definition: qcstring.h:195
void append(const type *d)
Definition: qlist.h:73
static int writeTableBlock(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1568
static void findEndOfLine(GrowBuf &out, const char *data, int size, int &pi, int &i, int &end)
Definition: markdown.cpp:1875
void writeOneLineHeaderOrRuler(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1692
void append(const char *key, const T *d)
Definition: sortdict.h:135
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int isHeaderline(const char *data, int size)
Definition: markdown.cpp:1069
void addChar(char c)
Definition: growbuf.h:16
static int g_lineNr
Definition: markdown.cpp:95
static QCString extractTitleId(QCString &title)
Definition: markdown.cpp:1234
static void writeFencedCodeBlock(GrowBuf &out, const char *data, const char *lng, int blockStart, int blockEnd)
Definition: markdown.cpp:1961
static int writeCodeBlock(GrowBuf &out, const char *data, int size, int refIndent)
Definition: markdown.cpp:1824
QList< SectionInfo > * anchors
list of anchors defined in this entry
Definition: entry.h:281
QCString fileName
Definition: section.h:61
static Entry * g_current
Definition: markdown.cpp:93
static SectionDict * sectionDict
Definition: doxygen.h:117
const char * data() const
Definition: qcstring.h:207
int lineNr
Definition: section.h:62
void warn(const char *file, int line, const char *fmt,...)
Definition: message.cpp:183
static bool isFencedCodeBlock(const char *data, int size, int refIndent, QCString &lang, int &start, int &end, int &offset)
Definition: markdown.cpp:1376
static bool isCodeBlock(const char *data, int offset, int size, int &indent)
Definition: markdown.cpp:1415
const char * get()
Definition: growbuf.h:38
const int codeBlockIndent
Definition: markdown.cpp:106
static QCString g_fileName
Definition: markdown.cpp:94
float pi
Definition: units.py:11
T * find(const char *key)
Definition: sortdict.h:232
static int isLinkRef(const char *data, int size, QCString &refid, QCString &link, QCString &title)
Definition: markdown.cpp:1117
static QDict< LinkRef > g_linkRefs(257)
static int processCodeSpan ( GrowBuf out,
const char *  data,
int  ,
int  size 
)
static

'`' parsing a code span (assuming codespan != 0)

Definition at line 918 of file markdown.cpp.

919 {
920  int end, nb = 0, i, f_begin, f_end;
921 
922  /* counting the number of backticks in the delimiter */
923  while (nb<size && data[nb]=='`')
924  {
925  nb++;
926  }
927 
928  /* finding the next delimiter */
929  i = 0;
930  int nl=0;
931  for (end=nb; end<size && i<nb && nl<2; end++)
932  {
933  if (data[end]=='`')
934  {
935  i++;
936  }
937  else if (data[end]=='\n')
938  {
939  i=0;
940  nl++;
941  }
942  else
943  {
944  i=0;
945  }
946  }
947  if (i < nb && end >= size)
948  {
949  return 0; // no matching delimiter
950  }
951  if (nl==2) // too many newlines inside the span
952  {
953  return 0;
954  }
955 
956  // trimming outside whitespaces
957  f_begin = nb;
958  while (f_begin < end && data[f_begin]==' ')
959  {
960  f_begin++;
961  }
962  f_end = end - nb;
963  while (f_end > nb && data[f_end-1]==' ')
964  {
965  f_end--;
966  }
967 
968  if (nb==1) // check for closing ' followed by space within f_begin..f_end
969  {
970  i=f_begin;
971  while (i<f_end-1)
972  {
973  if (data[i]=='\'' && !isIdChar(i+1)) // reject `some word' and not `it's cool`
974  {
975  return 0;
976  }
977  i++;
978  }
979  }
980  //printf("found code span '%s'\n",QCString(data+f_begin).left(f_end-f_begin).data());
981 
982  /* real code span */
983  if (f_begin < f_end)
984  {
985  QCString codeFragment;
986  convertStringFragment(codeFragment,data+f_begin,f_end-f_begin);
987  out.addStr("<tt>");
988  //out.addStr(convertToHtml(codeFragment,TRUE));
989  out.addStr(escapeSpecialChars(codeFragment));
990  out.addStr("</tt>");
991  }
992  return end;
993 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
static constexpr double nb
Definition: Units.h:81
void addStr(const char *s)
Definition: growbuf.h:19
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static QCString escapeSpecialChars(const QCString &s)
Definition: markdown.cpp:111
std::string nl(std::size_t i=1)
#define isIdChar(i)
Definition: markdown.cpp:56
static int processEmphasis ( GrowBuf out,
const char *  data,
int  offset,
int  size 
)
static

Definition at line 589 of file markdown.cpp.

590 {
591  if ((offset>0 && !isOpenEmphChar(-1)) || // invalid char before * or _
592  (size>1 && data[0]!=data[1] && !(isIdChar(1) || data[1]=='[')) || // invalid char after * or _
593  (size>2 && data[0]==data[1] && !(isIdChar(2) || data[2]=='['))) // invalid char after ** or __
594  {
595  return 0;
596  }
597 
598  char c = data[0];
599  int ret;
600  if (size>2 && data[1]!=c) // _bla or *bla
601  {
602  // whitespace cannot follow an opening emphasis
603  if (data[1]==' ' || data[1]=='\n' ||
604  (ret = processEmphasis1(out, data+1, size-1, c)) == 0)
605  {
606  return 0;
607  }
608  return ret+1;
609  }
610  if (size>3 && data[1]==c && data[2]!=c) // __bla or **bla
611  {
612  if (data[2]==' ' || data[2]=='\n' ||
613  (ret = processEmphasis2(out, data+2, size-2, c)) == 0)
614  {
615  return 0;
616  }
617  return ret+2;
618  }
619  if (size>4 && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla
620  {
621  if (data[3]==' ' || data[3]=='\n' ||
622  (ret = processEmphasis3(out, data+3, size-3, c)) == 0)
623  {
624  return 0;
625  }
626  return ret+3;
627  }
628  return 0;
629 }
static int processEmphasis2(GrowBuf &out, const char *data, int size, char c)
Definition: markdown.cpp:366
static int processEmphasis1(GrowBuf &out, const char *data, int size, char c)
Definition: markdown.cpp:335
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int processEmphasis3(GrowBuf &out, const char *data, int size, char c)
Definition: markdown.cpp:395
#define isOpenEmphChar(i)
Definition: markdown.cpp:63
#define isIdChar(i)
Definition: markdown.cpp:56
static int processEmphasis1 ( GrowBuf out,
const char *  data,
int  size,
char  c 
)
static

process single emphasis

Definition at line 335 of file markdown.cpp.

336 {
337  int i = 0, len;
338 
339  /* skipping one symbol if coming from emph3 */
340  if (size>1 && data[0]==c && data[1]==c) { i=1; }
341 
342  while (i<size)
343  {
344  len = findEmphasisChar(data+i, size-i, c, 1);
345  if (len==0) return 0;
346  i+=len;
347  if (i>=size) return 0;
348 
349  if (i+1<size && data[i+1]==c)
350  {
351  i++;
352  continue;
353  }
354  if (data[i]==c && data[i-1]!=' ' && data[i-1]!='\n')
355  {
356  out.addStr("<em>");
357  processInline(out,data,i);
358  out.addStr("</em>");
359  return i+1;
360  }
361  }
362  return 0;
363 }
void addStr(const char *s)
Definition: growbuf.h:19
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int findEmphasisChar(const char *data, int size, char c, int c_size)
Definition: markdown.cpp:237
static void processInline(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1045
static int processEmphasis2 ( GrowBuf out,
const char *  data,
int  size,
char  c 
)
static

process double emphasis

Definition at line 366 of file markdown.cpp.

367 {
368  int i = 0, len;
369 
370  while (i<size)
371  {
372  len = findEmphasisChar(data+i, size-i, c, 2);
373  if (len==0)
374  {
375  return 0;
376  }
377  i += len;
378  if (i+1<size && data[i]==c && data[i+1]==c && i && data[i-1]!=' ' &&
379  data[i-1]!='\n'
380  )
381  {
382  out.addStr("<strong>");
383  processInline(out,data,i);
384  out.addStr("</strong>");
385  return i + 2;
386  }
387  i++;
388  }
389  return 0;
390 }
void addStr(const char *s)
Definition: growbuf.h:19
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int findEmphasisChar(const char *data, int size, char c, int c_size)
Definition: markdown.cpp:237
static void processInline(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1045
static int processEmphasis3 ( GrowBuf out,
const char *  data,
int  size,
char  c 
)
static

Parsing tripple emphasis. Finds the first closing tag, and delegates to the other emph

Definition at line 395 of file markdown.cpp.

396 {
397  int i = 0, len;
398 
399  while (i<size)
400  {
401  len = findEmphasisChar(data+i, size-i, c, 3);
402  if (len==0)
403  {
404  return 0;
405  }
406  i+=len;
407 
408  /* skip whitespace preceded symbols */
409  if (data[i]!=c || data[i-1]==' ' || data[i-1]=='\n')
410  {
411  continue;
412  }
413 
414  if (i+2<size && data[i+1]==c && data[i+2]==c)
415  {
416  out.addStr("<em><strong>");
417  processInline(out,data,i);
418  out.addStr("</strong></em>");
419  return i+3;
420  }
421  else if (i+1<size && data[i+1]==c)
422  {
423  // double symbol found, handing over to emph1
424  len = processEmphasis1(out, data-2, size+2, c);
425  if (len==0)
426  {
427  return 0;
428  }
429  else
430  {
431  return len - 2;
432  }
433  }
434  else
435  {
436  // single symbol found, handing over to emph2
437  len = processEmphasis2(out, data-1, size+1, c);
438  if (len==0)
439  {
440  return 0;
441  }
442  else
443  {
444  return len - 1;
445  }
446  }
447  }
448  return 0;
449 }
static int processEmphasis2(GrowBuf &out, const char *data, int size, char c)
Definition: markdown.cpp:366
static int processEmphasis1(GrowBuf &out, const char *data, int size, char c)
Definition: markdown.cpp:335
void addStr(const char *s)
Definition: growbuf.h:19
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int findEmphasisChar(const char *data, int size, char c, int c_size)
Definition: markdown.cpp:237
static void processInline(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1045
static int processHtmlTag ( GrowBuf out,
const char *  data,
int  offset,
int  size 
)
static

Process a HTML tag. Note that

..

are treated specially, in the sense that all code inside is written unprocessed

Definition at line 505 of file markdown.cpp.

506 {
507  if (offset>0 && data[-1]=='\\') return 0; // escaped <
508 
509  // find the end of the html tag
510  int i=1;
511  int l=0;
512  // compute length of the tag name
513  while (i<size && isIdChar(i)) i++,l++;
514  QCString tagName;
515  convertStringFragment(tagName,data+1,i-1);
516  if (tagName.lower()=="pre") // found <pre> tag
517  {
518  bool insideStr=FALSE;
519  while (i<size-6)
520  {
521  char c=data[i];
522  if (!insideStr && c=='<') // potential start of html tag
523  {
524  if (data[i+1]=='/' &&
525  tolower(data[i+2])=='p' && tolower(data[i+3])=='r' &&
526  tolower(data[i+4])=='e' && tolower(data[i+5])=='>')
527  { // found </pre> tag, copy from start to end of tag
528  out.addStr(data,i+6);
529  //printf("found <pre>..</pre> [%d..%d]\n",0,i+6);
530  return i+6;
531  }
532  }
533  else if (insideStr && c=='"')
534  {
535  if (data[i-1]!='\\') insideStr=FALSE;
536  }
537  else if (c=='"')
538  {
539  insideStr=TRUE;
540  }
541  i++;
542  }
543  }
544  else // some other html tag
545  {
546  if (l>0 && i<size)
547  {
548  if (data[i]=='/' && i<size-1 && data[i+1]=='>') // <bla/>
549  {
550  //printf("Found htmlTag={%s}\n",QCString(data).left(i+2).data());
551  out.addStr(data,i+2);
552  return i+2;
553  }
554  else if (data[i]=='>') // <bla>
555  {
556  //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data());
557  out.addStr(data,i+1);
558  return i+1;
559  }
560  else if (data[i]==' ') // <bla attr=...
561  {
562  i++;
563  bool insideAttr=FALSE;
564  while (i<size)
565  {
566  if (!insideAttr && data[i]=='"')
567  {
568  insideAttr=TRUE;
569  }
570  else if (data[i]=='"' && data[i-1]!='\\')
571  {
572  insideAttr=FALSE;
573  }
574  else if (!insideAttr && data[i]=='>') // found end of tag
575  {
576  //printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data());
577  out.addStr(data,i+1);
578  return i+1;
579  }
580  i++;
581  }
582  }
583  }
584  }
585  //printf("Not a valid html tag\n");
586  return 0;
587 }
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
void addStr(const char *s)
Definition: growbuf.h:19
const bool FALSE
Definition: qglobal.h:370
static QStrList * l
Definition: config.cpp:1044
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
QCString lower() const
Definition: qcstring.cpp:263
const bool TRUE
Definition: qglobal.h:371
#define isIdChar(i)
Definition: markdown.cpp:56
static void processInline ( GrowBuf out,
const char *  data,
int  size 
)
static

Definition at line 1045 of file markdown.cpp.

1046 {
1047  int i=0, end=0;
1048  action_t action = 0;
1049  while (i<size)
1050  {
1051  while (end<size && ((action=g_actions[(uchar)data[end]])==0)) end++;
1052  out.addStr(data+i,end-i);
1053  if (end>=size) break;
1054  i=end;
1055  end = action(out,data+i,i,size-i);
1056  if (!end)
1057  {
1058  end=i+1;
1059  }
1060  else
1061  {
1062  i+=end;
1063  end=i;
1064  }
1065  }
1066 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void addStr(const char *s)
Definition: growbuf.h:19
static action_t g_actions[256]
Definition: markdown.cpp:92
int(* action_t)(GrowBuf &out, const char *data, int offset, int size)
Definition: markdown.cpp:84
unsigned char uchar
Definition: nybbler.cc:11
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int processLink ( GrowBuf out,
const char *  data,
int  ,
int  size 
)
static

Definition at line 631 of file markdown.cpp.

632 {
633  QCString content;
634  QCString link;
635  QCString title;
636  int contentStart,contentEnd,linkStart,titleStart,titleEnd;
637  bool isImageLink = FALSE;
638  bool isToc = FALSE;
639  int i=1;
640  if (data[0]=='!')
641  {
642  isImageLink = TRUE;
643  if (size<2 || data[1]!='[')
644  {
645  return 0;
646  }
647  i++;
648  }
649  contentStart=i;
650  int level=1;
651  int nl=0;
652  // find the matching ]
653  while (i<size)
654  {
655  if (data[i-1]=='\\') // skip escaped characters
656  {
657  }
658  else if (data[i]=='[')
659  {
660  level++;
661  }
662  else if (data[i]==']')
663  {
664  level--;
665  if (level<=0) break;
666  }
667  else if (data[i]=='\n')
668  {
669  nl++;
670  if (nl>1) return 0; // only allow one newline in the content
671  }
672  i++;
673  }
674  if (i>=size) return 0; // premature end of comment -> no link
675  contentEnd=i;
676  convertStringFragment(content,data+contentStart,contentEnd-contentStart);
677  //printf("processLink: content={%s}\n",content.data());
678  if (!isImageLink && content.isEmpty()) return 0; // no link text
679  i++; // skip over ]
680 
681  // skip whitespace
682  while (i<size && data[i]==' ') i++;
683  if (i<size && data[i]=='\n') // one newline allowed here
684  {
685  i++;
686  // skip more whitespace
687  while (i<size && data[i]==' ') i++;
688  }
689 
690  bool explicitTitle=FALSE;
691  if (i<size && data[i]=='(') // inline link
692  {
693  i++;
694  while (i<size && data[i]==' ') i++;
695  if (i<size && data[i]=='<') i++;
696  linkStart=i;
697  nl=0;
698  int braceCount=1;
699  while (i<size && data[i]!='\'' && data[i]!='"' && braceCount>0)
700  {
701  if (data[i]=='\n') // unexpected EOL
702  {
703  nl++;
704  if (nl>1) return 0;
705  }
706  else if (data[i]=='(')
707  {
708  braceCount++;
709  }
710  else if (data[i]==')')
711  {
712  braceCount--;
713  }
714  if (braceCount>0)
715  {
716  i++;
717  }
718  }
719  if (i>=size || data[i]=='\n') return 0;
720  convertStringFragment(link,data+linkStart,i-linkStart);
721  link = link.stripWhiteSpace();
722  //printf("processLink: link={%s}\n",link.data());
723  if (link.isEmpty()) return 0;
724  if (link.at(link.length()-1)=='>') link=link.left(link.length()-1);
725 
726  // optional title
727  if (data[i]=='\'' || data[i]=='"')
728  {
729  char c = data[i];
730  i++;
731  titleStart=i;
732  nl=0;
733  while (i<size && data[i]!=')')
734  {
735  if (data[i]=='\n')
736  {
737  if (nl>1) return 0;
738  nl++;
739  }
740  i++;
741  }
742  if (i>=size)
743  {
744  return 0;
745  }
746  titleEnd = i-1;
747  // search back for closing marker
748  while (titleEnd>titleStart && data[titleEnd]==' ') titleEnd--;
749  if (data[titleEnd]==c) // found it
750  {
751  convertStringFragment(title,data+titleStart,titleEnd-titleStart);
752  //printf("processLink: title={%s}\n",title.data());
753  }
754  else
755  {
756  return 0;
757  }
758  }
759  i++;
760  }
761  else if (i<size && data[i]=='[') // reference link
762  {
763  i++;
764  linkStart=i;
765  nl=0;
766  // find matching ]
767  while (i<size && data[i]!=']')
768  {
769  if (data[i]=='\n')
770  {
771  nl++;
772  if (nl>1) return 0;
773  }
774  i++;
775  }
776  if (i>=size) return 0;
777  // extract link
778  convertStringFragment(link,data+linkStart,i-linkStart);
779  //printf("processLink: link={%s}\n",link.data());
780  link = link.stripWhiteSpace();
781  if (link.isEmpty()) // shortcut link
782  {
783  link=content;
784  }
785  // lookup reference
786  LinkRef *lr = g_linkRefs.find(link.lower());
787  if (lr) // found it
788  {
789  link = lr->link;
790  title = lr->title;
791  //printf("processLink: ref: link={%s} title={%s}\n",link.data(),title.data());
792  }
793  else // reference not found!
794  {
795  //printf("processLink: ref {%s} do not exist\n",link.lower().data());
796  return 0;
797  }
798  i++;
799  }
800  else if (i<size && data[i]!=':' && !content.isEmpty()) // minimal link ref notation [some id]
801  {
802  LinkRef *lr = g_linkRefs.find(content.lower());
803  //printf("processLink: minimal link {%s} lr=%p",content.data(),lr);
804  if (lr) // found it
805  {
806  link = lr->link;
807  title = lr->title;
808  explicitTitle=TRUE;
809  i=contentEnd;
810  }
811  else if (content=="TOC")
812  {
813  isToc=TRUE;
814  i=contentEnd;
815  }
816  else
817  {
818  return 0;
819  }
820  i++;
821  }
822  else
823  {
824  return 0;
825  }
826  if (isToc) // special case for [TOC]
827  {
829  }
830  else if (isImageLink)
831  {
832  bool ambig;
833  FileDef *fd=0;
834  if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1 ||
835  (fd=findFileDef(Doxygen::imageNameDict,link,ambig)))
836  // assume doxygen symbol link or local image link
837  {
838  out.addStr("@image html ");
839  out.addStr(link.mid(fd ? 0 : 5));
840  if (!explicitTitle && !content.isEmpty())
841  {
842  out.addStr(" \"");
843  out.addStr(content);
844  out.addStr("\"");
845  }
846  else if ((content.isEmpty() || explicitTitle) && !title.isEmpty())
847  {
848  out.addStr(" \"");
849  out.addStr(title);
850  out.addStr("\"");
851  }
852  }
853  else
854  {
855  out.addStr("<img src=\"");
856  out.addStr(link);
857  out.addStr("\" alt=\"");
858  out.addStr(content);
859  out.addStr("\"");
860  if (!title.isEmpty())
861  {
862  out.addStr(" title=\"");
863  out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
864  out.addStr("\"");
865  }
866  out.addStr("/>");
867  }
868  }
869  else
870  {
871  SrcLangExt lang = getLanguageFromFileName(link);
872  int lp=-1;
873  if ((lp=link.find("@ref "))!=-1 || (lp=link.find("\\ref "))!=-1 || lang==SrcLangExt_Markdown)
874  // assume doxygen symbol link
875  {
876  if (lp==-1) // link to markdown page
877  {
878  out.addStr("@ref ");
879  }
880  out.addStr(link);
881  out.addStr(" \"");
882  if (explicitTitle && !title.isEmpty())
883  {
884  out.addStr(title);
885  }
886  else
887  {
888  out.addStr(content);
889  }
890  out.addStr("\"");
891  }
892  else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1)
893  { // file/url link
894  out.addStr("<a href=\"");
895  out.addStr(link);
896  out.addStr("\"");
897  if (!title.isEmpty())
898  {
899  out.addStr(" title=\"");
900  out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
901  out.addStr("\"");
902  }
903  out.addStr(">");
904  content = content.simplifyWhiteSpace();
905  processInline(out,content,content.length());
906  out.addStr("</a>");
907  }
908  else // avoid link to e.g. F[x](y)
909  {
910  //printf("no link for '%s'\n",link.data());
911  return 0;
912  }
913  }
914  return i;
915 }
static void convertStringFragment(QCString &result, const char *data, int size)
Definition: markdown.cpp:132
QCString stripWhiteSpace() const
Definition: qcstring.cpp:295
QCString link
Definition: markdown.cpp:80
bool stat
static ?
Definition: entry.h:245
void addStr(const char *s)
Definition: growbuf.h:19
bool isEmpty() const
Definition: qcstring.h:189
uint length() const
Definition: qcstring.h:195
char & at(uint i) const
Definition: qcstring.h:326
QCString title
Definition: markdown.cpp:81
const bool FALSE
Definition: qglobal.h:370
QCString left(uint len) const
Definition: qcstring.cpp:213
int find(char c, int index=0, bool cs=TRUE) const
Definition: qcstring.cpp:41
SrcLangExt
Definition: types.h:41
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
FileDef * findFileDef(const FileNameDict *fnDict, const char *n, bool &ambig)
Definition: util.cpp:4963
static Entry * g_current
Definition: markdown.cpp:93
static FileNameDict * imageNameDict
Definition: doxygen.h:110
QCString mid(uint index, uint len=0xffffffff) const
Definition: qcstring.cpp:246
SrcLangExt getLanguageFromFileName(const QCString fileName)
Definition: util.cpp:7061
static void processInline(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1045
QCString lower() const
Definition: qcstring.cpp:263
static int braceCount
std::string nl(std::size_t i=1)
const bool TRUE
Definition: qglobal.h:371
QCString simplifyWhiteSpace() const
Definition: qcstring.cpp:323
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition: util.cpp:5088
static QDict< LinkRef > g_linkRefs(257)
QCString processMarkdown ( const QCString fileName,
const int  lineNr,
Entry e,
const QCString s 
)

processes string s and converts markdown into doxygen/html commands.

Definition at line 2298 of file markdown.cpp.

2299 {
2300  static bool init=FALSE;
2301  if (!init)
2302  {
2303  // setup callback table for special characters
2304  g_actions[(unsigned int)'_']=processEmphasis;
2305  g_actions[(unsigned int)'*']=processEmphasis;
2306  g_actions[(unsigned int)'`']=processCodeSpan;
2307  g_actions[(unsigned int)'\\']=processSpecialCommand;
2308  g_actions[(unsigned int)'@']=processSpecialCommand;
2309  g_actions[(unsigned int)'[']=processLink;
2310  g_actions[(unsigned int)'!']=processLink;
2311  g_actions[(unsigned int)'<']=processHtmlTag;
2312  g_actions[(unsigned int)'-']=processNmdash;
2313  g_actions[(unsigned int)'"']=processQuoted;
2314  init=TRUE;
2315  }
2316 
2317  g_linkRefs.setAutoDelete(TRUE);
2318  g_linkRefs.clear();
2319  g_current = e;
2320  g_fileName = fileName;
2321  g_lineNr = lineNr;
2322  static GrowBuf out;
2323  if (input.isEmpty()) return input;
2324  out.clear();
2325  int refIndent;
2326  // for replace tabs by spaces
2327  QCString s = detab(input,refIndent);
2328  //printf("======== DeTab =========\n---- output -----\n%s\n---------\n",s.data());
2329  // then process quotation blocks (as these may contain other blocks)
2330  s = processQuotations(s,refIndent);
2331  //printf("======== Quotations =========\n---- output -----\n%s\n---------\n",s.data());
2332  // then process block items (headers, rules, and code blocks, references)
2333  s = processBlocks(s,refIndent);
2334  //printf("======== Blocks =========\n---- output -----\n%s\n---------\n",s.data());
2335  // finally process the inline markup (links, emphasis and code spans)
2336  processInline(out,s,s.length());
2337  out.addChar(0);
2338  Debug::print(Debug::Markdown,0,"======== Markdown =========\n---- input ------- \n%s\n---- output -----\n%s\n---------\n",qPrint(input),qPrint(out.get()));
2339  return out.get();
2340 }
void clear()
Definition: growbuf.h:15
bool isEmpty() const
Definition: qcstring.h:189
uint length() const
Definition: qcstring.h:195
static int processEmphasis(GrowBuf &out, const char *data, int offset, int size)
Definition: markdown.cpp:589
static action_t g_actions[256]
Definition: markdown.cpp:92
static int processHtmlTag(GrowBuf &out, const char *data, int offset, int size)
Definition: markdown.cpp:505
const bool FALSE
Definition: qglobal.h:370
static QCString processQuotations(const QCString &s, int refIndent)
Definition: markdown.cpp:1976
init
Definition: train.py:42
static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int size)
Definition: markdown.cpp:996
static QCString processBlocks(const QCString &s, int indent)
Definition: markdown.cpp:2034
static int processNmdash(GrowBuf &out, const char *data, int off, int size)
Definition: markdown.cpp:452
void addChar(char c)
Definition: growbuf.h:16
static int g_lineNr
Definition: markdown.cpp:95
const double e
fileName
Definition: dumpTree.py:9
static void print(DebugMask mask, int prio, const char *fmt,...)
Definition: debug.cpp:84
static Entry * g_current
Definition: markdown.cpp:93
static QCString detab(const QCString &s, int &refIndent)
Definition: markdown.cpp:2241
static int processQuoted(GrowBuf &out, const char *data, int, int size)
Definition: markdown.cpp:484
static int processCodeSpan(GrowBuf &out, const char *data, int, int size)
Definition: markdown.cpp:918
const char * get()
Definition: growbuf.h:38
static int processLink(GrowBuf &out, const char *data, int, int size)
Definition: markdown.cpp:631
static QCString g_fileName
Definition: markdown.cpp:94
static void processInline(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1045
static QCString * s
Definition: config.cpp:1042
const char * qPrint(const char *s)
Definition: qcstring.h:797
const bool TRUE
Definition: qglobal.h:371
static QDict< LinkRef > g_linkRefs(257)
static int processNmdash ( GrowBuf out,
const char *  data,
int  off,
int  size 
)
static

Process ndash and mdashes

Definition at line 452 of file markdown.cpp.

453 {
454  // precondition: data[0]=='-'
455  int i=1;
456  int count=1;
457  if (i<size && data[i]=='-') // found --
458  {
459  count++,i++;
460  }
461  if (i<size && data[i]=='-') // found ---
462  {
463  count++,i++;
464  }
465  if (i<size && data[i]=='-') // found ----
466  {
467  count++;
468  }
469  if (count==2 && (off<8 || qstrncmp(data-8,"operator",8)!=0)) // -- => ndash
470  {
471  out.addStr("&ndash;");
472  return 2;
473  }
474  else if (count==3) // --- => ndash
475  {
476  out.addStr("&mdash;");
477  return 3;
478  }
479  // not an ndash or mdash
480  return 0;
481 }
Q_EXPORT int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qcstring.h:101
void addStr(const char *s)
Definition: growbuf.h:19
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static QCString processQuotations ( const QCString s,
int  refIndent 
)
static

Definition at line 1976 of file markdown.cpp.

1977 {
1978  GrowBuf out;
1979  const char *data = s.data();
1980  int size = s.length();
1981  int i=0,end=0,pi=-1;
1982  int blockStart,blockEnd,blockOffset;
1983  QCString lang;
1984  while (i<size)
1985  {
1986  findEndOfLine(out,data,size,pi,i,end);
1987  // line is now found at [i..end)
1988 
1989  if (pi!=-1)
1990  {
1991  if (isFencedCodeBlock(data+pi,size-pi,refIndent,lang,blockStart,blockEnd,blockOffset))
1992  {
1993  writeFencedCodeBlock(out,data+pi,lang,blockStart,blockEnd);
1994  i=pi+blockOffset;
1995  pi=-1;
1996  end=i+1;
1997  continue;
1998  }
1999  else if (isBlockQuote(data+pi,i-pi,refIndent))
2000  {
2001  i = pi+writeBlockQuote(out,data+pi,size-pi);
2002  pi=-1;
2003  end=i+1;
2004  continue;
2005  }
2006  else
2007  {
2008  //printf("quote out={%s}\n",QCString(data+pi).left(i-pi).data());
2009  out.addStr(data+pi,i-pi);
2010  }
2011  }
2012  pi=i;
2013  i=end;
2014  }
2015  if (pi!=-1 && pi<size) // deal with the last line
2016  {
2017  if (isBlockQuote(data+pi,size-pi,refIndent))
2018  {
2019  writeBlockQuote(out,data+pi,size-pi);
2020  }
2021  else
2022  {
2023  out.addStr(data+pi,size-pi);
2024  }
2025  }
2026  out.addChar(0);
2027 
2028  //printf("Process quotations\n---- input ----\n%s\n---- output ----\n%s\n------------\n",
2029  // s.data(),out.get());
2030 
2031  return out.get();
2032 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void addStr(const char *s)
Definition: growbuf.h:19
uint length() const
Definition: qcstring.h:195
static void findEndOfLine(GrowBuf &out, const char *data, int size, int &pi, int &i, int &end)
Definition: markdown.cpp:1875
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
void addChar(char c)
Definition: growbuf.h:16
static int writeBlockQuote(GrowBuf &out, const char *data, int size)
Definition: markdown.cpp:1768
static void writeFencedCodeBlock(GrowBuf &out, const char *data, const char *lng, int blockStart, int blockEnd)
Definition: markdown.cpp:1961
const char * data() const
Definition: qcstring.h:207
static bool isFencedCodeBlock(const char *data, int size, int refIndent, QCString &lang, int &start, int &end, int &offset)
Definition: markdown.cpp:1376
const char * get()
Definition: growbuf.h:38
static bool isBlockQuote(const char *data, int size, int indent)
Definition: markdown.cpp:1092
float pi
Definition: units.py:11
static int processQuoted ( GrowBuf out,
const char *  data,
int  ,
int  size 
)
static

Process quoted section "...", can contain one embedded newline

Definition at line 484 of file markdown.cpp.

485 {
486  int i=1;
487  int nl=0;
488  while (i<size && data[i]!='"' && nl<2)
489  {
490  if (data[i]=='\n') nl++;
491  i++;
492  }
493  if (i<size && data[i]=='"' && nl<2)
494  {
495  out.addStr(data,i+1);
496  return i+1;
497  }
498  // not a quoted section
499  return 0;
500 }
void addStr(const char *s)
Definition: growbuf.h:19
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
std::string nl(std::size_t i=1)
static int processSpecialCommand ( GrowBuf out,
const char *  data,
int  offset,
int  size 
)
static

Definition at line 996 of file markdown.cpp.

997 {
998  int i=1;
999  QCString endBlockName = isBlockCommand(data,offset,size);
1000  if (!endBlockName.isEmpty())
1001  {
1002  int l = endBlockName.length();
1003  while (i<size-l)
1004  {
1005  if ((data[i]=='\\' || data[i]=='@') && // command
1006  data[i-1]!='\\' && data[i-1]!='@') // not escaped
1007  {
1008  if (qstrncmp(&data[i+1],endBlockName,l)==0)
1009  {
1010  //printf("found end at %d\n",i);
1011  out.addStr(data,i+1+l);
1012  return i+1+l;
1013  }
1014  }
1015  i++;
1016  }
1017  }
1018  if (size>1 && data[0]=='\\')
1019  {
1020  char c=data[1];
1021  if (c=='[' || c==']' || c=='*' || /* c=='+' || c=='-' || c=='.' || */
1022  c=='!' || c=='(' || c==')' || c=='`' || c=='_')
1023  {
1024  if (c=='-' && size>3 && data[2]=='-' && data[3]=='-') // \---
1025  {
1026  out.addStr(&data[1],3);
1027  return 4;
1028  }
1029  else if (c=='-' && size>2 && data[2]=='-') // \--
1030  {
1031  out.addStr(&data[1],2);
1032  return 3;
1033  }
1034  else if (c=='-') // \-
1035  {
1036  out.addChar(c);
1037  }
1038  out.addChar(data[1]);
1039  return 2;
1040  }
1041  }
1042  return 0;
1043 }
Q_EXPORT int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qcstring.h:101
void addStr(const char *s)
Definition: growbuf.h:19
bool isEmpty() const
Definition: qcstring.h:189
uint length() const
Definition: qcstring.h:195
static QStrList * l
Definition: config.cpp:1044
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
void addChar(char c)
Definition: growbuf.h:16
static QCString isBlockCommand(const char *data, int offset, int size)
Definition: markdown.cpp:183
static int writeBlockQuote ( GrowBuf out,
const char *  data,
int  size 
)
static

Definition at line 1768 of file markdown.cpp.

1769 {
1770  int l;
1771  int i=0;
1772  int curLevel=0;
1773  int end=0;
1774  while (i<size)
1775  {
1776  // find end of this line
1777  end=i+1;
1778  while (end<=size && data[end-1]!='\n') end++;
1779  int j=i;
1780  int level=0;
1781  int indent=i;
1782  // compute the quoting level
1783  while (j<end && (data[j]==' ' || data[j]=='>'))
1784  {
1785  if (data[j]=='>') { level++; indent=j+1; }
1786  else if (j>0 && data[j-1]=='>') indent=j+1;
1787  j++;
1788  }
1789  if (j>0 && data[j-1]=='>' &&
1790  !(j==size || data[j]=='\n')) // disqualify last > if not followed by space
1791  {
1792  indent--;
1793  j--;
1794  }
1795  if (level>curLevel) // quote level increased => add start markers
1796  {
1797  for (l=curLevel;l<level;l++)
1798  {
1799  out.addStr("<blockquote>\n");
1800  }
1801  }
1802  else if (level<curLevel) // quote level descreased => add end markers
1803  {
1804  for (l=level;l<curLevel;l++)
1805  {
1806  out.addStr("</blockquote>\n");
1807  }
1808  }
1809  curLevel=level;
1810  if (level==0) break; // end of quote block
1811  // copy line without quotation marks
1812  out.addStr(data+indent,end-indent);
1813  // proceed with next line
1814  i=end;
1815  }
1816  // end of comment within blockquote => add end markers
1817  for (l=0;l<curLevel;l++)
1818  {
1819  out.addStr("</blockquote>\n");
1820  }
1821  return i;
1822 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void addStr(const char *s)
Definition: growbuf.h:19
static QStrList * l
Definition: config.cpp:1044
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int writeCodeBlock ( GrowBuf out,
const char *  data,
int  size,
int  refIndent 
)
static

Definition at line 1824 of file markdown.cpp.

1825 {
1826  int i=0,end;
1827  //printf("writeCodeBlock: data={%s}\n",QCString(data).left(size).data());
1828  out.addStr("@verbatim\n");
1829  int emptyLines=0;
1830  while (i<size)
1831  {
1832  // find end of this line
1833  end=i+1;
1834  while (end<=size && data[end-1]!='\n') end++;
1835  int j=i;
1836  int indent=0;
1837  while (j<end && data[j]==' ') j++,indent++;
1838  //printf("j=%d end=%d indent=%d refIndent=%d tabSize=%d data={%s}\n",
1839  // j,end,indent,refIndent,Config_getInt("TAB_SIZE"),QCString(data+i).left(end-i-1).data());
1840  if (j==end-1) // empty line
1841  {
1842  emptyLines++;
1843  i=end;
1844  }
1845  else if (indent>=refIndent+codeBlockIndent) // enough indent to contine the code block
1846  {
1847  while (emptyLines>0) // write skipped empty lines
1848  {
1849  // add empty line
1850  out.addStr("\n");
1851  emptyLines--;
1852  }
1853  // add code line minus the indent
1854  out.addStr(data+i+refIndent+codeBlockIndent,end-i-refIndent-codeBlockIndent);
1855  i=end;
1856  }
1857  else // end of code block
1858  {
1859  break;
1860  }
1861  }
1862  out.addStr("@endverbatim\n");
1863  while (emptyLines>0) // write skipped empty lines
1864  {
1865  // add empty line
1866  out.addStr("\n");
1867  emptyLines--;
1868  }
1869  //printf("i=%d\n",i);
1870  return i;
1871 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void addStr(const char *s)
Definition: growbuf.h:19
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
const int codeBlockIndent
Definition: markdown.cpp:106
static void writeFencedCodeBlock ( GrowBuf out,
const char *  data,
const char *  lng,
int  blockStart,
int  blockEnd 
)
static

Definition at line 1961 of file markdown.cpp.

1963 {
1964  QCString lang = lng;
1965  if (!lang.isEmpty() && lang.at(0)=='.') lang=lang.mid(1);
1966  out.addStr("@code");
1967  if (!lang.isEmpty())
1968  {
1969  out.addStr("{"+lang+"}");
1970  }
1971  out.addStr(data+blockStart,blockEnd-blockStart);
1972  out.addStr("\n");
1973  out.addStr("@endcode");
1974 }
void addStr(const char *s)
Definition: growbuf.h:19
bool isEmpty() const
Definition: qcstring.h:189
char & at(uint i) const
Definition: qcstring.h:326
QCString mid(uint index, uint len=0xffffffff) const
Definition: qcstring.cpp:246
void writeOneLineHeaderOrRuler ( GrowBuf out,
const char *  data,
int  size 
)

Definition at line 1692 of file markdown.cpp.

1693 {
1694  int level;
1695  QCString header;
1696  QCString id;
1697  if (isHRuler(data,size))
1698  {
1699  out.addStr("<hr>\n");
1700  }
1701  else if ((level=isAtxHeader(data,size,header,id)))
1702  {
1703  //if (level==1) g_correctSectionLevel=FALSE;
1704  //if (g_correctSectionLevel) level--;
1705  QCString hTag;
1706  if (level<5 && !id.isEmpty())
1707  {
1709  switch(level)
1710  {
1711  case 1: out.addStr("@section ");
1712  type=SectionInfo::Section;
1713  break;
1714  case 2: out.addStr("@subsection ");
1716  break;
1717  case 3: out.addStr("@subsubsection ");
1719  break;
1720  default: out.addStr("@paragraph ");
1722  break;
1723  }
1724  out.addStr(id);
1725  out.addStr(" ");
1726  out.addStr(header);
1727  out.addStr("\n");
1729  if (si)
1730  {
1731  if (si->lineNr != -1)
1732  {
1733  warn(g_fileName,g_lineNr,"multiple use of section label '%s', (first occurrence: %s, line %d)",header.data(),si->fileName.data(),si->lineNr);
1734  }
1735  else
1736  {
1737  warn(g_fileName,g_lineNr,"multiple use of section label '%s', (first occurrence: %s)",header.data(),si->fileName.data());
1738  }
1739  }
1740  else
1741  {
1742  si = new SectionInfo(g_fileName,g_lineNr,id,header,type,level);
1743  if (g_current)
1744  {
1745  g_current->anchors->append(si);
1746  }
1747  Doxygen::sectionDict->append(id,si);
1748  }
1749  }
1750  else
1751  {
1752  if (!id.isEmpty())
1753  {
1754  out.addStr("\\anchor "+id+"\n");
1755  }
1756  hTag.sprintf("h%d",level);
1757  out.addStr("<"+hTag+">");
1758  out.addStr(header);
1759  out.addStr("</"+hTag+">\n");
1760  }
1761  }
1762  else // nothing interesting -> just output the line
1763  {
1764  out.addStr(data,size);
1765  }
1766 }
static int isAtxHeader(const char *data, int size, QCString &header, QCString &id)
Definition: markdown.cpp:1252
void addStr(const char *s)
Definition: growbuf.h:19
void append(const type *d)
Definition: qlist.h:73
static int isHRuler(const char *data, int size)
Definition: markdown.cpp:1207
void append(const char *key, const T *d)
Definition: sortdict.h:135
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static int g_lineNr
Definition: markdown.cpp:95
QList< SectionInfo > * anchors
list of anchors defined in this entry
Definition: entry.h:281
QCString fileName
Definition: section.h:61
static Entry * g_current
Definition: markdown.cpp:93
static SectionDict * sectionDict
Definition: doxygen.h:117
const char * data() const
Definition: qcstring.h:207
int lineNr
Definition: section.h:62
void warn(const char *file, int line, const char *fmt,...)
Definition: message.cpp:183
QCString & sprintf(const char *format,...)
Definition: qcstring.cpp:27
static QCString g_fileName
Definition: markdown.cpp:94
T * find(const char *key)
Definition: sortdict.h:232
static int writeTableBlock ( GrowBuf out,
const char *  data,
int  size 
)
static

Definition at line 1568 of file markdown.cpp.

1569 {
1570  int i=0,j,k;
1571  int columns,start,end,cc;
1572 
1573  i = findTableColumns(data,size,start,end,columns);
1574 
1575  out.addStr("<table>");
1576 
1577  // write table header, in range [start..end]
1578  out.addStr("<tr>");
1579 
1580  int headerStart = start;
1581  int headerEnd = end;
1582 
1583  // read cell alignments
1584  int ret = findTableColumns(data+i,size-i,start,end,cc);
1585  k=0;
1586  Alignment *columnAlignment = new Alignment[columns];
1587 
1588  bool leftMarker=FALSE,rightMarker=FALSE;
1589  bool startFound=FALSE;
1590  j=start+i;
1591  while (j<=end+i)
1592  {
1593  if (!startFound)
1594  {
1595  if (data[j]==':') { leftMarker=TRUE; startFound=TRUE; }
1596  if (data[j]=='-') startFound=TRUE;
1597  //printf(" data[%d]=%c startFound=%d\n",j,data[j],startFound);
1598  }
1599  if (data[j]=='-') rightMarker=FALSE;
1600  else if (data[j]==':') rightMarker=TRUE;
1601  if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\')))
1602  {
1603  if (k<columns)
1604  {
1605  columnAlignment[k] = markersToAlignment(leftMarker,rightMarker);
1606  //printf("column[%d] alignment=%d\n",k,columnAlignment[k]);
1607  leftMarker=FALSE;
1608  rightMarker=FALSE;
1609  startFound=FALSE;
1610  }
1611  k++;
1612  }
1613  j++;
1614  }
1615  if (k<columns)
1616  {
1617  columnAlignment[k] = markersToAlignment(leftMarker,rightMarker);
1618  //printf("column[%d] alignment=%d\n",k,columnAlignment[k]);
1619  }
1620  // proceed to next line
1621  i+=ret;
1622 
1623  int m=headerStart;
1624  for (k=0;k<columns;k++)
1625  {
1626  out.addStr("<th");
1627  switch (columnAlignment[k])
1628  {
1629  case AlignLeft: out.addStr(" align=\"left\""); break;
1630  case AlignRight: out.addStr(" align=\"right\""); break;
1631  case AlignCenter: out.addStr(" align=\"center\""); break;
1632  case AlignNone: break;
1633  }
1634  out.addStr(">");
1635  while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\')))
1636  {
1637  out.addChar(data[m++]);
1638  }
1639  m++;
1640  }
1641  out.addStr("\n</th>\n");
1642 
1643  // write table cells
1644  while (i<size)
1645  {
1646  int ret = findTableColumns(data+i,size-i,start,end,cc);
1647  //printf("findTableColumns cc=%d\n",cc);
1648  if (cc!=columns) break; // end of table
1649 
1650  out.addStr("<tr>");
1651  j=start+i;
1652  int columnStart=j;
1653  k=0;
1654  while (j<=end+i)
1655  {
1656  if (j==columnStart)
1657  {
1658  out.addStr("<td");
1659  switch (columnAlignment[k])
1660  {
1661  case AlignLeft: out.addStr(" align=\"left\""); break;
1662  case AlignRight: out.addStr(" align=\"right\""); break;
1663  case AlignCenter: out.addStr(" align=\"center\""); break;
1664  case AlignNone: break;
1665  }
1666  out.addStr(">");
1667  }
1668  if (j<=end+i && (data[j]=='|' && (j==0 || data[j-1]!='\\')))
1669  {
1670  columnStart=j+1;
1671  k++;
1672  }
1673  else
1674  {
1675  out.addChar(data[j]);
1676  }
1677  j++;
1678  }
1679  out.addChar('\n');
1680 
1681  // proceed to next line
1682  i+=ret;
1683  }
1684 
1685  out.addStr("</table> ");
1686 
1687  delete[] columnAlignment;
1688  return i;
1689 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void addStr(const char *s)
Definition: growbuf.h:19
const bool FALSE
Definition: qglobal.h:370
static Alignment markersToAlignment(bool leftMarker, bool rightMarker)
Definition: markdown.cpp:143
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
int findTableColumns(const char *data, int size, int &start, int &end, int &columns)
Definition: markdown.cpp:1491
void addChar(char c)
Definition: growbuf.h:16
string columns
Definition: depos.py:13
Alignment
Definition: markdown.cpp:86
const bool TRUE
Definition: qglobal.h:371

Variable Documentation

const int codeBlockIndent = 4

Definition at line 106 of file markdown.cpp.

action_t g_actions[256]
static

Definition at line 92 of file markdown.cpp.

Entry* g_current
static

Definition at line 93 of file markdown.cpp.

QCString g_fileName
static

Definition at line 94 of file markdown.cpp.

int g_lineNr
static

Definition at line 95 of file markdown.cpp.