redcarpet 1.3.3 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of redcarpet might be problematic. Click here for more details.

data/ext/markdown.c CHANGED
@@ -56,6 +56,8 @@ struct render {
56
56
  struct array refs;
57
57
  char_trigger active_char[256];
58
58
  struct parray work;
59
+ unsigned int ext_flags;
60
+ size_t max_nesting;
59
61
  };
60
62
 
61
63
  /* html_tag • structure for quick HTML tag search (inspired from discount) */
@@ -238,7 +240,7 @@ parse_inline(struct buf *ob, struct render *rndr, char *data, size_t size)
238
240
  char_trigger action = 0;
239
241
  struct buf work = { 0, 0, 0, 0, 0 };
240
242
 
241
- if (rndr->work.size > rndr->make.parser_options.recursion_depth)
243
+ if (rndr->work.size > rndr->max_nesting)
242
244
  return;
243
245
 
244
246
  while (i < size) {
@@ -249,7 +251,7 @@ parse_inline(struct buf *ob, struct render *rndr, char *data, size_t size)
249
251
  if (rndr->make.normal_text) {
250
252
  work.data = data + i;
251
253
  work.size = end - i;
252
- rndr->make.normal_text(ob, &work, &rndr->make.render_options);
254
+ rndr->make.normal_text(ob, &work, rndr->make.opaque);
253
255
  }
254
256
  else
255
257
  bufput(ob, data + i, end - i);
@@ -346,7 +348,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
346
348
 
347
349
  if (data[i] == c && !isspace(data[i - 1])) {
348
350
 
349
- if ((rndr->make.parser_options.flags & MKD_LAX_EMPHASIS) == 0) {
351
+ if ((rndr->ext_flags & MKDEXT_LAX_EMPHASIS) == 0) {
350
352
  if (!(i + 1 == size || isspace(data[i + 1]) || ispunct(data[i + 1])))
351
353
  continue;
352
354
  }
@@ -360,7 +362,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
360
362
  }
361
363
 
362
364
  parse_inline(work, rndr, data, i);
363
- r = rndr->make.emphasis(ob, work, c, &rndr->make.render_options);
365
+ r = rndr->make.emphasis(ob, work, c, rndr->make.opaque);
364
366
  rndr->work.size -= 1;
365
367
  return r ? i + 1 : 0;
366
368
  }
@@ -395,7 +397,7 @@ parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c
395
397
  }
396
398
 
397
399
  parse_inline(work, rndr, data, i);
398
- r = rndr->make.double_emphasis(ob, work, c, &rndr->make.render_options);
400
+ r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque);
399
401
  rndr->work.size -= 1;
400
402
  return r ? i + 2 : 0;
401
403
  }
@@ -433,7 +435,7 @@ parse_emph3(struct buf *ob, struct render *rndr, char *data, size_t size, char c
433
435
  }
434
436
 
435
437
  parse_inline(work, rndr, data, i);
436
- r = rndr->make.triple_emphasis(ob, work, c, &rndr->make.render_options);
438
+ r = rndr->make.triple_emphasis(ob, work, c, rndr->make.opaque);
437
439
  rndr->work.size -= 1;
438
440
  return r ? i + 3 : 0;
439
441
 
@@ -497,7 +499,7 @@ char_linebreak(struct buf *ob, struct render *rndr, char *data, size_t offset, s
497
499
  while (ob->size && ob->data[ob->size - 1] == ' ')
498
500
  ob->size--;
499
501
 
500
- return rndr->make.linebreak(ob, &rndr->make.render_options) ? 1 : 0;
502
+ return rndr->make.linebreak(ob, rndr->make.opaque) ? 1 : 0;
501
503
  }
502
504
 
503
505
 
@@ -533,10 +535,10 @@ char_codespan(struct buf *ob, struct render *rndr, char *data, size_t offset, si
533
535
  /* real code span */
534
536
  if (f_begin < f_end) {
535
537
  struct buf work = { data + f_begin, f_end - f_begin, 0, 0, 0 };
536
- if (!rndr->make.codespan(ob, &work, &rndr->make.render_options))
538
+ if (!rndr->make.codespan(ob, &work, rndr->make.opaque))
537
539
  end = 0;
538
540
  } else {
539
- if (!rndr->make.codespan(ob, 0, &rndr->make.render_options))
541
+ if (!rndr->make.codespan(ob, 0, rndr->make.opaque))
540
542
  end = 0;
541
543
  }
542
544
 
@@ -554,7 +556,7 @@ char_escape(struct buf *ob, struct render *rndr, char *data, size_t offset, size
554
556
  if (rndr->make.normal_text) {
555
557
  work.data = data + 1;
556
558
  work.size = 1;
557
- rndr->make.normal_text(ob, &work, &rndr->make.render_options);
559
+ rndr->make.normal_text(ob, &work, rndr->make.opaque);
558
560
  }
559
561
  else bufputc(ob, data[1]);
560
562
  }
@@ -584,7 +586,7 @@ char_entity(struct buf *ob, struct render *rndr, char *data, size_t offset, size
584
586
  if (rndr->make.entity) {
585
587
  work.data = data;
586
588
  work.size = end;
587
- rndr->make.entity(ob, &work, &rndr->make.render_options);
589
+ rndr->make.entity(ob, &work, rndr->make.opaque);
588
590
  }
589
591
  else bufput(ob, data, end);
590
592
 
@@ -604,10 +606,10 @@ char_langle_tag(struct buf *ob, struct render *rndr, char *data, size_t offset,
604
606
  if (rndr->make.autolink && altype != MKDA_NOT_AUTOLINK) {
605
607
  work.data = data + 1;
606
608
  work.size = end - 2;
607
- ret = rndr->make.autolink(ob, &work, altype, &rndr->make.render_options);
609
+ ret = rndr->make.autolink(ob, &work, altype, rndr->make.opaque);
608
610
  }
609
611
  else if (rndr->make.raw_html_tag)
610
- ret = rndr->make.raw_html_tag(ob, &work, &rndr->make.render_options);
612
+ ret = rndr->make.raw_html_tag(ob, &work, rndr->make.opaque);
611
613
  }
612
614
 
613
615
  if (!ret) return 0;
@@ -847,9 +849,9 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
847
849
  if (ob->size && ob->data[ob->size - 1] == '!')
848
850
  ob->size -= 1;
849
851
 
850
- ret = rndr->make.image(ob, link, title, content, &rndr->make.render_options);
852
+ ret = rndr->make.image(ob, link, title, content, rndr->make.opaque);
851
853
  } else
852
- ret = rndr->make.link(ob, link, title, content, &rndr->make.render_options);
854
+ ret = rndr->make.link(ob, link, title, content, rndr->make.opaque);
853
855
 
854
856
  /* cleanup */
855
857
  cleanup:
@@ -902,6 +904,34 @@ is_hrule(char *data, size_t size)
902
904
  return n >= 3;
903
905
  }
904
906
 
907
+ /* check if a line is a code fence; return its size if it is */
908
+ static size_t
909
+ is_codefence(char *data, size_t size)
910
+ {
911
+ size_t i = 0, n = 0;
912
+ char c;
913
+
914
+ /* skipping initial spaces */
915
+ if (size < 3) return 0;
916
+ if (data[0] == ' ') { i += 1;
917
+ if (data[1] == ' ') { i += 1;
918
+ if (data[2] == ' ') { i += 1; } } }
919
+
920
+ /* looking at the hrule char */
921
+ if (i + 2 >= size || data[i] != '~')
922
+ return 0;
923
+
924
+ /* the whole line must be the char or whitespace */
925
+ while (i < size && data[i] != '\n') {
926
+ if (data[i] == '~') n++;
927
+ else if (data[i] != ' ' && data[i] != '\t')
928
+ return 0;
929
+ i++;
930
+ }
931
+
932
+ return n >= 3 ? i + 1 : 0;
933
+ }
934
+
905
935
  /* is_headerline • returns whether the line is a setext-style hdr underline */
906
936
  static int
907
937
  is_headerline(char *data, size_t size)
@@ -1027,7 +1057,7 @@ parse_blockquote(struct buf *ob, struct render *rndr, char *data, size_t size)
1027
1057
 
1028
1058
  parse_block(out, rndr, work_data, work_size);
1029
1059
  if (rndr->make.blockquote)
1030
- rndr->make.blockquote(ob, out, &rndr->make.render_options);
1060
+ rndr->make.blockquote(ob, out, rndr->make.opaque);
1031
1061
  rndr->work.size -= 1;
1032
1062
  return end;
1033
1063
  }
@@ -1084,7 +1114,7 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
1084
1114
 
1085
1115
  parse_inline(tmp, rndr, work.data, work.size);
1086
1116
  if (rndr->make.paragraph)
1087
- rndr->make.paragraph(ob, tmp, &rndr->make.render_options);
1117
+ rndr->make.paragraph(ob, tmp, rndr->make.opaque);
1088
1118
  rndr->work.size--;
1089
1119
 
1090
1120
  } else {
@@ -1114,7 +1144,7 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
1114
1144
  parse_inline(tmp, rndr, work.data, work.size);
1115
1145
 
1116
1146
  if (rndr->make.paragraph)
1117
- rndr->make.paragraph(ob, tmp, &rndr->make.render_options);
1147
+ rndr->make.paragraph(ob, tmp, rndr->make.opaque);
1118
1148
 
1119
1149
  rndr->work.size -= 1;
1120
1150
  work.data += beg;
@@ -1124,13 +1154,61 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
1124
1154
  }
1125
1155
 
1126
1156
  if (rndr->make.header)
1127
- rndr->make.header(ob, &work, level, &rndr->make.render_options);
1157
+ rndr->make.header(ob, &work, level, rndr->make.opaque);
1128
1158
  }
1129
1159
 
1130
1160
  return end;
1131
1161
  }
1132
1162
 
1133
1163
  /* parse_blockquote • hanldes parsing of a block-level code fragment */
1164
+ static size_t
1165
+ parse_fencedcode(struct buf *ob, struct render *rndr, char *data, size_t size)
1166
+ {
1167
+ size_t beg, end;
1168
+ struct buf *work = 0;
1169
+
1170
+ beg = is_codefence(data, size);
1171
+ if (beg == 0) return 0;
1172
+
1173
+ if (rndr->work.size < rndr->work.asize) {
1174
+ work = rndr->work.item[rndr->work.size ++];
1175
+ work->size = 0;
1176
+ } else {
1177
+ work = bufnew(WORK_UNIT);
1178
+ parr_push(&rndr->work, work);
1179
+ }
1180
+
1181
+ while (beg < size) {
1182
+ size_t fence_end;
1183
+
1184
+ fence_end = is_codefence(data + beg, size - beg);
1185
+ if (fence_end != 0) {
1186
+ beg += fence_end;
1187
+ break;
1188
+ }
1189
+
1190
+ for (end = beg + 1; end < size && data[end - 1] != '\n'; end += 1);
1191
+
1192
+ if (beg < end) {
1193
+ /* verbatim copy to the working buffer,
1194
+ escaping entities */
1195
+ if (is_empty(data + beg, end - beg))
1196
+ bufputc(work, '\n');
1197
+ else bufput(work, data + beg, end - beg);
1198
+ }
1199
+ beg = end;
1200
+ }
1201
+
1202
+ if (work->size && work->data[work->size - 1] != '\n')
1203
+ bufputc(work, '\n');
1204
+
1205
+ if (rndr->make.blockcode)
1206
+ rndr->make.blockcode(ob, work, rndr->make.opaque);
1207
+
1208
+ rndr->work.size -= 1;
1209
+ return beg;
1210
+ }
1211
+
1134
1212
  static size_t
1135
1213
  parse_blockcode(struct buf *ob, struct render *rndr, char *data, size_t size)
1136
1214
  {
@@ -1165,7 +1243,7 @@ parse_blockcode(struct buf *ob, struct render *rndr, char *data, size_t size)
1165
1243
  work->size -= 1;
1166
1244
  bufputc(work, '\n');
1167
1245
  if (rndr->make.blockcode)
1168
- rndr->make.blockcode(ob, work, &rndr->make.render_options);
1246
+ rndr->make.blockcode(ob, work, rndr->make.opaque);
1169
1247
  rndr->work.size -= 1;
1170
1248
  return beg;
1171
1249
  }
@@ -1292,7 +1370,7 @@ parse_listitem(struct buf *ob, struct render *rndr, char *data, size_t size, int
1292
1370
 
1293
1371
  /* render of li itself */
1294
1372
  if (rndr->make.listitem)
1295
- rndr->make.listitem(ob, inter, *flags, &rndr->make.render_options);
1373
+ rndr->make.listitem(ob, inter, *flags, rndr->make.opaque);
1296
1374
 
1297
1375
  rndr->work.size -= 2;
1298
1376
  return beg;
@@ -1322,7 +1400,7 @@ parse_list(struct buf *ob, struct render *rndr, char *data, size_t size, int fla
1322
1400
  }
1323
1401
 
1324
1402
  if (rndr->make.list)
1325
- rndr->make.list(ob, work, flags, &rndr->make.render_options);
1403
+ rndr->make.list(ob, work, flags, rndr->make.opaque);
1326
1404
  rndr->work.size -= 1;
1327
1405
  return i;
1328
1406
  }
@@ -1358,7 +1436,7 @@ parse_atxheader(struct buf *ob, struct render *rndr, char *data, size_t size)
1358
1436
  work.size = end - i;
1359
1437
 
1360
1438
  if (rndr->make.header)
1361
- rndr->make.header(ob, &work, (int)level, &rndr->make.render_options);
1439
+ rndr->make.header(ob, &work, (int)level, rndr->make.opaque);
1362
1440
 
1363
1441
  }
1364
1442
 
@@ -1433,7 +1511,7 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
1433
1511
  if (j) {
1434
1512
  work.size = i + j;
1435
1513
  if (do_render && rndr->make.blockhtml)
1436
- rndr->make.blockhtml(ob, &work, &rndr->make.render_options);
1514
+ rndr->make.blockhtml(ob, &work, rndr->make.opaque);
1437
1515
  return work.size;
1438
1516
  }
1439
1517
  }
@@ -1450,7 +1528,7 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
1450
1528
  if (j) {
1451
1529
  work.size = i + j;
1452
1530
  if (do_render && rndr->make.blockhtml)
1453
- rndr->make.blockhtml(ob, &work, &rndr->make.render_options);
1531
+ rndr->make.blockhtml(ob, &work, rndr->make.opaque);
1454
1532
  return work.size;
1455
1533
  }
1456
1534
  }
@@ -1505,11 +1583,192 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
1505
1583
  /* the end of the block has been found */
1506
1584
  work.size = i;
1507
1585
  if (do_render && rndr->make.blockhtml)
1508
- rndr->make.blockhtml(ob, &work, &rndr->make.render_options);
1586
+ rndr->make.blockhtml(ob, &work, rndr->make.opaque);
1509
1587
 
1510
1588
  return i;
1511
1589
  }
1512
1590
 
1591
+ static void
1592
+ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, size_t columns, int *col_data)
1593
+ {
1594
+ size_t i = 0, col;
1595
+ struct buf *row_work = 0;
1596
+
1597
+ if (rndr->work.size < rndr->work.asize) {
1598
+ row_work = rndr->work.item[rndr->work.size ++];
1599
+ row_work->size = 0;
1600
+ } else {
1601
+ row_work = bufnew(WORK_UNIT);
1602
+ parr_push(&rndr->work, row_work);
1603
+ }
1604
+
1605
+ if (i < size && data[i] == '|')
1606
+ i++;
1607
+
1608
+ for (col = 0; col < columns && i < size; ++col) {
1609
+ size_t cell_start, cell_end;
1610
+ struct buf *cell_work;
1611
+
1612
+ if (rndr->work.size < rndr->work.asize) {
1613
+ cell_work = rndr->work.item[rndr->work.size ++];
1614
+ cell_work->size = 0;
1615
+ } else {
1616
+ cell_work = bufnew(WORK_UNIT);
1617
+ parr_push(&rndr->work, cell_work);
1618
+ }
1619
+
1620
+ while (i < size && isspace(data[i]))
1621
+ i++;
1622
+
1623
+ cell_start = i;
1624
+
1625
+ while (i < size && data[i] != '|')
1626
+ i++;
1627
+
1628
+ cell_end = i - 1;
1629
+
1630
+ while (cell_end > cell_start && isspace(data[cell_end]))
1631
+ cell_end--;
1632
+
1633
+ parse_inline(cell_work, rndr, data + cell_start, 1 + cell_end - cell_start);
1634
+ if (rndr->make.table_cell)
1635
+ rndr->make.table_cell(row_work, cell_work, col_data ? col_data[col] : 0, rndr->make.opaque);
1636
+
1637
+ rndr->work.size -= 1;
1638
+ i++;
1639
+ }
1640
+
1641
+ for (; col < columns; ++col) {
1642
+ struct buf empty_cell = {0, 0, 0, 0, 0};
1643
+ if (rndr->make.table_cell)
1644
+ rndr->make.table_cell(row_work, &empty_cell, col_data ? col_data[col] : 0, rndr->make.opaque);
1645
+ }
1646
+
1647
+ if (rndr->make.table_row)
1648
+ rndr->make.table_row(ob, row_work, rndr->make.opaque);
1649
+
1650
+ rndr->work.size -= 1;
1651
+ }
1652
+
1653
+ static size_t
1654
+ parse_table_header(struct buf *ob, struct render *rndr, char *data, size_t size, size_t *columns, int **column_data)
1655
+ {
1656
+ int pipes;
1657
+ size_t i = 0, col, header_end, under_end;
1658
+
1659
+ pipes = 0;
1660
+ while (i < size && data[i] != '\n')
1661
+ if (data[i++] == '|')
1662
+ pipes++;
1663
+
1664
+ if (i == size || pipes == 0)
1665
+ return 0;
1666
+
1667
+ header_end = i;
1668
+
1669
+ if (data[0] == '|')
1670
+ pipes--;
1671
+
1672
+ if (i > 2 && data[i - 1] == '|')
1673
+ pipes--;
1674
+
1675
+ *columns = pipes + 1;
1676
+ *column_data = calloc(*columns, sizeof(int));
1677
+
1678
+ /* Parse the header underline */
1679
+ i++;
1680
+ if (i < size && data[i] == '|')
1681
+ i++;
1682
+
1683
+ under_end = i;
1684
+ while (under_end < size && data[under_end] != '\n')
1685
+ under_end++;
1686
+
1687
+ for (col = 0; col < *columns && i < under_end; ++col) {
1688
+ size_t cell_start, cell_end;
1689
+
1690
+ if (data[i] == ':') {
1691
+ i++; (*column_data)[col] |= MKD_TABLE_ALIGN_L;
1692
+ }
1693
+
1694
+ while (i < under_end && data[i] == '-')
1695
+ i++;
1696
+
1697
+ if (i < under_end && data[i] == ':') {
1698
+ i++; (*column_data)[col] |= MKD_TABLE_ALIGN_R;
1699
+ }
1700
+
1701
+ if (i < under_end && data[i] != '|')
1702
+ break;
1703
+
1704
+ i++;
1705
+ }
1706
+
1707
+ if (col < *columns)
1708
+ return 0;
1709
+
1710
+ parse_table_row(ob, rndr, data, header_end, *columns, *column_data);
1711
+ return under_end + 1;
1712
+ }
1713
+
1714
+ static size_t
1715
+ parse_table(struct buf *ob, struct render *rndr, char *data, size_t size)
1716
+ {
1717
+ size_t i;
1718
+
1719
+ struct buf *header_work = 0;
1720
+ struct buf *body_work = 0;
1721
+
1722
+ size_t columns;
1723
+ int *col_data = NULL;
1724
+
1725
+ if (rndr->work.size < rndr->work.asize) {
1726
+ header_work = rndr->work.item[rndr->work.size ++];
1727
+ header_work->size = 0;
1728
+ } else {
1729
+ header_work = bufnew(WORK_UNIT);
1730
+ parr_push(&rndr->work, header_work);
1731
+ }
1732
+
1733
+ if (rndr->work.size < rndr->work.asize) {
1734
+ body_work = rndr->work.item[rndr->work.size ++];
1735
+ body_work->size = 0;
1736
+ } else {
1737
+ body_work = bufnew(WORK_UNIT);
1738
+ parr_push(&rndr->work, body_work);
1739
+ }
1740
+
1741
+ i = parse_table_header(header_work, rndr, data, size, &columns, &col_data);
1742
+ if (i > 0) {
1743
+
1744
+ while (i < size) {
1745
+ size_t row_len;
1746
+ size_t row_start;
1747
+ int pipes = 0;
1748
+
1749
+ row_start = i;
1750
+
1751
+ while (i < size && data[i] != '\n')
1752
+ if (data[i++] == '|')
1753
+ pipes++;
1754
+
1755
+ if (pipes == 0 || i == size) {
1756
+ i = row_start;
1757
+ break;
1758
+ }
1759
+
1760
+ parse_table_row(body_work, rndr, data + row_start, i - row_start, columns, col_data);
1761
+ i++;
1762
+ }
1763
+
1764
+ if (rndr->make.table)
1765
+ rndr->make.table(ob, header_work, body_work, rndr->make.opaque);
1766
+ }
1767
+
1768
+ free(col_data);
1769
+ rndr->work.size -= 2;
1770
+ return i;
1771
+ }
1513
1772
 
1514
1773
  /* parse_block • parsing of one block, returning next char to parse */
1515
1774
  static void
@@ -1519,7 +1778,7 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
1519
1778
  char *txt_data;
1520
1779
  beg = 0;
1521
1780
 
1522
- if (rndr->work.size > rndr->make.parser_options.recursion_depth)
1781
+ if (rndr->work.size > rndr->max_nesting)
1523
1782
  return;
1524
1783
 
1525
1784
  while (beg < size) {
@@ -1529,7 +1788,8 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
1529
1788
  if (data[beg] == '#')
1530
1789
  beg += parse_atxheader(ob, rndr, txt_data, end);
1531
1790
 
1532
- else if (data[beg] == '<' && rndr->make.blockhtml && (i = parse_htmlblock(ob, rndr, txt_data, end, 1)) != 0)
1791
+ else if (data[beg] == '<' && rndr->make.blockhtml &&
1792
+ (i = parse_htmlblock(ob, rndr, txt_data, end, 1)) != 0)
1533
1793
  beg += i;
1534
1794
 
1535
1795
  else if ((i = is_empty(txt_data, end)) != 0)
@@ -1537,7 +1797,7 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
1537
1797
 
1538
1798
  else if (is_hrule(txt_data, end)) {
1539
1799
  if (rndr->make.hrule)
1540
- rndr->make.hrule(ob, &rndr->make.render_options);
1800
+ rndr->make.hrule(ob, rndr->make.opaque);
1541
1801
 
1542
1802
  while (beg < size && data[beg] != '\n')
1543
1803
  beg++;
@@ -1545,6 +1805,14 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
1545
1805
  beg++;
1546
1806
  }
1547
1807
 
1808
+ else if ((rndr->ext_flags & MKDEXT_FENCED_CODE) != 0 &&
1809
+ (i = parse_fencedcode(ob, rndr, txt_data, end)) != 0)
1810
+ beg += i;
1811
+
1812
+ else if ((rndr->ext_flags & MKDEXT_TABLES) != 0 &&
1813
+ (i = parse_table(ob, rndr, txt_data, end)) != 0)
1814
+ beg += i;
1815
+
1548
1816
  else if (prefix_quote(txt_data, end))
1549
1817
  beg += parse_blockquote(ob, rndr, txt_data, end);
1550
1818
 
@@ -1702,7 +1970,7 @@ static void expand_tabs(struct buf *ob, const char *line, size_t size)
1702
1970
 
1703
1971
  /* markdown • parses the input buffer and renders it into the output buffer */
1704
1972
  void
1705
- markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer) {
1973
+ markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, unsigned int extensions) {
1706
1974
  struct link_ref *lr;
1707
1975
  struct buf *text = bufnew(TEXT_UNIT);
1708
1976
  size_t i, beg, end;
@@ -1738,6 +2006,10 @@ markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer) {
1738
2006
  rndr.active_char['\\'] = char_escape;
1739
2007
  rndr.active_char['&'] = char_entity;
1740
2008
 
2009
+ /* Extension data */
2010
+ rndr.ext_flags = extensions;
2011
+ rndr.max_nesting = 16;
2012
+
1741
2013
  /* first pass: looking for references, copying everything else */
1742
2014
  beg = 0;
1743
2015
  while (beg < ib->size) /* iterating over lines */
@@ -1775,12 +2047,12 @@ markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer) {
1775
2047
 
1776
2048
  /* second pass: actual rendering */
1777
2049
  if (rndr.make.doc_header)
1778
- rndr.make.doc_header(ob, &rndr.make.render_options);
2050
+ rndr.make.doc_header(ob, rndr.make.opaque);
1779
2051
 
1780
2052
  parse_block(ob, &rndr, text->data, text->size);
1781
2053
 
1782
2054
  if (rndr.make.doc_footer)
1783
- rndr.make.doc_footer(ob, &rndr.make.render_options);
2055
+ rndr.make.doc_footer(ob, rndr.make.opaque);
1784
2056
 
1785
2057
  /* clean-up */
1786
2058
  bufrelease(text);