redcarpet 1.11.4 → 1.12.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
@@ -26,8 +26,8 @@
26
26
  #include <ctype.h>
27
27
  #include <stdio.h>
28
28
 
29
- #define TEXT_UNIT 64 /* unit for the copy of the input buffer */
30
- #define WORK_UNIT 64 /* block-level working buffer */
29
+ #define BUFFER_BLOCK 0
30
+ #define BUFFER_SPAN 1
31
31
 
32
32
  #define MKD_LI_END 8 /* internal list flag */
33
33
 
@@ -56,7 +56,7 @@ struct render {
56
56
  struct mkd_renderer make;
57
57
  struct array refs;
58
58
  char_trigger active_char[256];
59
- struct parray work;
59
+ struct parray work_bufs[2];
60
60
  unsigned int ext_flags;
61
61
  size_t max_nesting;
62
62
  };
@@ -68,25 +68,27 @@ struct html_tag {
68
68
  };
69
69
 
70
70
  static inline struct buf *
71
- rndr_newbuf(struct render *rndr)
71
+ rndr_newbuf(struct render *rndr, int type)
72
72
  {
73
+ static const size_t buf_size[2] = {256, 64};
73
74
  struct buf *work = NULL;
75
+ struct parray *queue = &rndr->work_bufs[type];
74
76
 
75
- if (rndr->work.size < rndr->work.asize) {
76
- work = rndr->work.item[rndr->work.size++];
77
+ if (queue->size < queue->asize) {
78
+ work = queue->item[queue->size++];
77
79
  work->size = 0;
78
80
  } else {
79
- work = bufnew(WORK_UNIT);
80
- parr_push(&rndr->work, work);
81
+ work = bufnew(buf_size[type]);
82
+ parr_push(queue, work);
81
83
  }
82
84
 
83
85
  return work;
84
86
  }
85
87
 
86
88
  static inline void
87
- rndr_popbuf(struct render *rndr)
89
+ rndr_popbuf(struct render *rndr, int type)
88
90
  {
89
- rndr->work.size--;
91
+ rndr->work_bufs[type].size--;
90
92
  }
91
93
 
92
94
  /********************
@@ -306,7 +308,8 @@ parse_inline(struct buf *ob, struct render *rndr, char *data, size_t size)
306
308
  char_trigger action = 0;
307
309
  struct buf work = { 0, 0, 0, 0, 0 };
308
310
 
309
- if (rndr->work.size > rndr->max_nesting)
311
+ if (rndr->work_bufs[BUFFER_SPAN].size +
312
+ rndr->work_bufs[BUFFER_BLOCK].size > rndr->max_nesting)
310
313
  return;
311
314
 
312
315
  while (i < size) {
@@ -415,15 +418,15 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
415
418
 
416
419
  if (data[i] == c && !isspace(data[i - 1])) {
417
420
 
418
- if (rndr->ext_flags & MKDEXT_STRICT_EMPHASIS) {
421
+ if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
419
422
  if (!(i + 1 == size || isspace(data[i + 1]) || ispunct(data[i + 1])))
420
423
  continue;
421
424
  }
422
425
 
423
- work = rndr_newbuf(rndr);
426
+ work = rndr_newbuf(rndr, BUFFER_SPAN);
424
427
  parse_inline(work, rndr, data, i);
425
428
  r = rndr->make.emphasis(ob, work, rndr->make.opaque);
426
- rndr_popbuf(rndr);
429
+ rndr_popbuf(rndr, BUFFER_SPAN);
427
430
  return r ? i + 1 : 0;
428
431
  }
429
432
  }
@@ -451,10 +454,10 @@ parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c
451
454
  i += len;
452
455
 
453
456
  if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !isspace(data[i - 1])) {
454
- work = rndr_newbuf(rndr);
457
+ work = rndr_newbuf(rndr, BUFFER_SPAN);
455
458
  parse_inline(work, rndr, data, i);
456
459
  r = render_method(ob, work, rndr->make.opaque);
457
- rndr_popbuf(rndr);
460
+ rndr_popbuf(rndr, BUFFER_SPAN);
458
461
  return r ? i + 2 : 0;
459
462
  }
460
463
  i++;
@@ -481,11 +484,11 @@ parse_emph3(struct buf *ob, struct render *rndr, char *data, size_t size, char c
481
484
 
482
485
  if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->make.triple_emphasis) {
483
486
  /* triple symbol found */
484
- struct buf *work = rndr_newbuf(rndr);
487
+ struct buf *work = rndr_newbuf(rndr, BUFFER_SPAN);
485
488
 
486
489
  parse_inline(work, rndr, data, i);
487
490
  r = rndr->make.triple_emphasis(ob, work, rndr->make.opaque);
488
- rndr_popbuf(rndr);
491
+ rndr_popbuf(rndr, BUFFER_SPAN);
489
492
  return r ? i + 3 : 0;
490
493
 
491
494
  } else if (i + 1 < size && data[i + 1] == c) {
@@ -654,12 +657,12 @@ char_langle_tag(struct buf *ob, struct render *rndr, char *data, size_t offset,
654
657
 
655
658
  if (end > 2) {
656
659
  if (rndr->make.autolink && altype != MKDA_NOT_AUTOLINK) {
657
- struct buf *u_link = rndr_newbuf(rndr);
660
+ struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
658
661
  work.data = data + 1;
659
662
  work.size = end - 2;
660
663
  unscape_text(u_link, &work);
661
664
  ret = rndr->make.autolink(ob, u_link, altype, rndr->make.opaque);
662
- rndr_popbuf(rndr);
665
+ rndr_popbuf(rndr, BUFFER_SPAN);
663
666
  }
664
667
  else if (rndr->make.raw_html_tag)
665
668
  ret = rndr->make.raw_html_tag(ob, &work, rndr->make.opaque);
@@ -673,22 +676,52 @@ static size_t
673
676
  char_autolink(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
674
677
  {
675
678
  struct buf work = { data, 0, 0, 0, 0 };
676
-
677
- if (offset > 0 && !isspace(data[-1]))
678
- return 0;
679
+ char cclose = 0;
680
+ size_t link_end;
681
+
682
+ /* TODO:
683
+ * what's the fastest check we can do, previous char
684
+ * or URI prefix? We want to do the fastest one first
685
+ * to break asap
686
+ */
687
+
688
+ if (offset > 0) {
689
+ switch (data[-1]) {
690
+ case '"': cclose = '"'; break;
691
+ case '\'': cclose = '\''; break;
692
+ case '(': cclose = ')'; break;
693
+ case '[': cclose = ']'; break;
694
+ case '{': cclose = '}'; break;
695
+ case ' ': case '\t': case '\n': break;
696
+ default:
697
+ return 0;
698
+ }
699
+ }
679
700
 
680
701
  if (!is_safe_link(data, size))
681
702
  return 0;
682
703
 
683
- while (work.size < size && !isspace(data[work.size]))
684
- work.size++;
704
+ link_end = 0;
705
+ while (link_end < size && !isspace(data[link_end]))
706
+ link_end++;
707
+
708
+ if (cclose != 0) {
709
+ size_t i = link_end;
710
+ while (i > 0 && data[i] != cclose)
711
+ i--;
712
+
713
+ if (i > 0)
714
+ link_end = i;
715
+ }
716
+
717
+ work.size = link_end;
685
718
 
686
719
  if (rndr->make.autolink) {
687
- struct buf *u_link = rndr_newbuf(rndr);
720
+ struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
688
721
  unscape_text(u_link, &work);
689
722
 
690
723
  rndr->make.autolink(ob, u_link, MKDA_NORMAL, rndr->make.opaque);
691
- rndr_popbuf(rndr);
724
+ rndr_popbuf(rndr, BUFFER_SPAN);
692
725
  }
693
726
 
694
727
  return work.size;
@@ -704,7 +737,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
704
737
  struct buf *link = 0;
705
738
  struct buf *title = 0;
706
739
  struct buf *u_link = 0;
707
- size_t org_work_size = rndr->work.size;
740
+ size_t org_work_size = rndr->work_bufs[BUFFER_SPAN].size;
708
741
  int text_has_nl = 0, ret = 0;
709
742
 
710
743
  /* checking whether the correct renderer exists */
@@ -795,12 +828,12 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
795
828
 
796
829
  /* building escaped link and title */
797
830
  if (link_e > link_b) {
798
- link = rndr_newbuf(rndr);
831
+ link = rndr_newbuf(rndr, BUFFER_SPAN);
799
832
  bufput(link, data + link_b, link_e - link_b);
800
833
  }
801
834
 
802
835
  if (title_e > title_b) {
803
- title = rndr_newbuf(rndr);
836
+ title = rndr_newbuf(rndr, BUFFER_SPAN);
804
837
  bufput(title, data + title_b, title_e - title_b);
805
838
  }
806
839
 
@@ -822,7 +855,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
822
855
  /* finding the link_ref */
823
856
  if (link_b == link_e) {
824
857
  if (text_has_nl) {
825
- struct buf *b = rndr_newbuf(rndr);
858
+ struct buf *b = rndr_newbuf(rndr, BUFFER_SPAN);
826
859
  size_t j;
827
860
 
828
861
  for (j = 1; j < txt_e; j++) {
@@ -859,7 +892,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
859
892
 
860
893
  /* crafting the id */
861
894
  if (text_has_nl) {
862
- struct buf *b = rndr_newbuf(rndr);
895
+ struct buf *b = rndr_newbuf(rndr, BUFFER_SPAN);
863
896
  size_t j;
864
897
 
865
898
  for (j = 1; j < txt_e; j++) {
@@ -890,13 +923,13 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
890
923
 
891
924
  /* building content: img alt is escaped, link content is parsed */
892
925
  if (txt_e > 1) {
893
- content = rndr_newbuf(rndr);
926
+ content = rndr_newbuf(rndr, BUFFER_SPAN);
894
927
  if (is_img) bufput(content, data + 1, txt_e - 1);
895
928
  else parse_inline(content, rndr, data + 1, txt_e - 1);
896
929
  }
897
930
 
898
931
  if (link) {
899
- u_link = rndr_newbuf(rndr);
932
+ u_link = rndr_newbuf(rndr, BUFFER_SPAN);
900
933
  unscape_text(u_link, link);
901
934
  }
902
935
 
@@ -912,7 +945,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
912
945
 
913
946
  /* cleanup */
914
947
  cleanup:
915
- rndr->work.size = (int)org_work_size;
948
+ rndr->work_bufs[BUFFER_SPAN].size = (int)org_work_size;
916
949
  return ret ? i : 0;
917
950
  }
918
951
 
@@ -1125,7 +1158,7 @@ parse_blockquote(struct buf *ob, struct render *rndr, char *data, size_t size)
1125
1158
  char *work_data = 0;
1126
1159
  struct buf *out = 0;
1127
1160
 
1128
- out = rndr_newbuf(rndr);
1161
+ out = rndr_newbuf(rndr, BUFFER_BLOCK);
1129
1162
  beg = 0;
1130
1163
  while (beg < size) {
1131
1164
  for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
@@ -1155,7 +1188,7 @@ parse_blockquote(struct buf *ob, struct render *rndr, char *data, size_t size)
1155
1188
  parse_block(out, rndr, work_data, work_size);
1156
1189
  if (rndr->make.blockquote)
1157
1190
  rndr->make.blockquote(ob, out, rndr->make.opaque);
1158
- rndr_popbuf(rndr);
1191
+ rndr_popbuf(rndr, BUFFER_BLOCK);
1159
1192
  return end;
1160
1193
  }
1161
1194
 
@@ -1196,11 +1229,11 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
1196
1229
  work.size--;
1197
1230
 
1198
1231
  if (!level) {
1199
- struct buf *tmp = rndr_newbuf(rndr);
1232
+ struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
1200
1233
  parse_inline(tmp, rndr, work.data, work.size);
1201
1234
  if (rndr->make.paragraph)
1202
1235
  rndr->make.paragraph(ob, tmp, rndr->make.opaque);
1203
- rndr_popbuf(rndr);
1236
+ rndr_popbuf(rndr, BUFFER_BLOCK);
1204
1237
  } else {
1205
1238
  struct buf *header_work;
1206
1239
 
@@ -1217,26 +1250,26 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
1217
1250
  work.size -= 1;
1218
1251
 
1219
1252
  if (work.size > 0) {
1220
- struct buf *tmp = rndr_newbuf(rndr);
1253
+ struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
1221
1254
  parse_inline(tmp, rndr, work.data, work.size);
1222
1255
 
1223
1256
  if (rndr->make.paragraph)
1224
1257
  rndr->make.paragraph(ob, tmp, rndr->make.opaque);
1225
1258
 
1226
- rndr_popbuf(rndr);
1259
+ rndr_popbuf(rndr, BUFFER_BLOCK);
1227
1260
  work.data += beg;
1228
1261
  work.size = i - beg;
1229
1262
  }
1230
1263
  else work.size = i;
1231
1264
  }
1232
1265
 
1233
- header_work = rndr_newbuf(rndr);
1266
+ header_work = rndr_newbuf(rndr, BUFFER_SPAN);
1234
1267
  parse_inline(header_work, rndr, work.data, work.size);
1235
1268
 
1236
1269
  if (rndr->make.header)
1237
1270
  rndr->make.header(ob, header_work, (int)level, rndr->make.opaque);
1238
1271
 
1239
- rndr_popbuf(rndr);
1272
+ rndr_popbuf(rndr, BUFFER_SPAN);
1240
1273
  }
1241
1274
 
1242
1275
  return end;
@@ -1253,7 +1286,7 @@ parse_fencedcode(struct buf *ob, struct render *rndr, char *data, size_t size)
1253
1286
  beg = is_codefence(data, size, &lang);
1254
1287
  if (beg == 0) return 0;
1255
1288
 
1256
- work = rndr_newbuf(rndr);
1289
+ work = rndr_newbuf(rndr, BUFFER_BLOCK);
1257
1290
 
1258
1291
  while (beg < size) {
1259
1292
  size_t fence_end;
@@ -1282,7 +1315,7 @@ parse_fencedcode(struct buf *ob, struct render *rndr, char *data, size_t size)
1282
1315
  if (rndr->make.blockcode)
1283
1316
  rndr->make.blockcode(ob, work, lang.size ? &lang : NULL, rndr->make.opaque);
1284
1317
 
1285
- rndr_popbuf(rndr);
1318
+ rndr_popbuf(rndr, BUFFER_BLOCK);
1286
1319
  return beg;
1287
1320
  }
1288
1321
 
@@ -1292,7 +1325,7 @@ parse_blockcode(struct buf *ob, struct render *rndr, char *data, size_t size)
1292
1325
  size_t beg, end, pre;
1293
1326
  struct buf *work = 0;
1294
1327
 
1295
- work = rndr_newbuf(rndr);
1328
+ work = rndr_newbuf(rndr, BUFFER_BLOCK);
1296
1329
 
1297
1330
  beg = 0;
1298
1331
  while (beg < size) {
@@ -1323,7 +1356,7 @@ parse_blockcode(struct buf *ob, struct render *rndr, char *data, size_t size)
1323
1356
  if (rndr->make.blockcode)
1324
1357
  rndr->make.blockcode(ob, work, NULL, rndr->make.opaque);
1325
1358
 
1326
- rndr_popbuf(rndr);
1359
+ rndr_popbuf(rndr, BUFFER_BLOCK);
1327
1360
  return beg;
1328
1361
  }
1329
1362
 
@@ -1353,8 +1386,8 @@ parse_listitem(struct buf *ob, struct render *rndr, char *data, size_t size, int
1353
1386
  end++;
1354
1387
 
1355
1388
  /* getting working buffers */
1356
- work = rndr_newbuf(rndr);
1357
- inter = rndr_newbuf(rndr);
1389
+ work = rndr_newbuf(rndr, BUFFER_SPAN);
1390
+ inter = rndr_newbuf(rndr, BUFFER_SPAN);
1358
1391
 
1359
1392
  /* putting the first line into the working buffer */
1360
1393
  bufput(work, data + beg, end - beg);
@@ -1438,8 +1471,8 @@ parse_listitem(struct buf *ob, struct render *rndr, char *data, size_t size, int
1438
1471
  if (rndr->make.listitem)
1439
1472
  rndr->make.listitem(ob, inter, *flags, rndr->make.opaque);
1440
1473
 
1441
- rndr_popbuf(rndr);
1442
- rndr_popbuf(rndr);
1474
+ rndr_popbuf(rndr, BUFFER_SPAN);
1475
+ rndr_popbuf(rndr, BUFFER_SPAN);
1443
1476
  return beg;
1444
1477
  }
1445
1478
 
@@ -1451,7 +1484,7 @@ parse_list(struct buf *ob, struct render *rndr, char *data, size_t size, int fla
1451
1484
  struct buf *work = 0;
1452
1485
  size_t i = 0, j;
1453
1486
 
1454
- work = rndr_newbuf(rndr);
1487
+ work = rndr_newbuf(rndr, BUFFER_BLOCK);
1455
1488
 
1456
1489
  while (i < size) {
1457
1490
  j = parse_listitem(work, rndr, data + i, size - i, &flags);
@@ -1463,7 +1496,7 @@ parse_list(struct buf *ob, struct render *rndr, char *data, size_t size, int fla
1463
1496
 
1464
1497
  if (rndr->make.list)
1465
1498
  rndr->make.list(ob, work, flags, rndr->make.opaque);
1466
- rndr_popbuf(rndr);
1499
+ rndr_popbuf(rndr, BUFFER_BLOCK);
1467
1500
  return i;
1468
1501
  }
1469
1502
 
@@ -1493,14 +1526,14 @@ parse_atxheader(struct buf *ob, struct render *rndr, char *data, size_t size)
1493
1526
  end--;
1494
1527
 
1495
1528
  if (end > i) {
1496
- struct buf *work = rndr_newbuf(rndr);
1529
+ struct buf *work = rndr_newbuf(rndr, BUFFER_SPAN);
1497
1530
 
1498
1531
  parse_inline(work, rndr, data + i, end - i);
1499
1532
 
1500
1533
  if (rndr->make.header)
1501
1534
  rndr->make.header(ob, work, (int)level, rndr->make.opaque);
1502
1535
 
1503
- rndr_popbuf(rndr);
1536
+ rndr_popbuf(rndr, BUFFER_SPAN);
1504
1537
  }
1505
1538
 
1506
1539
  return skip;
@@ -1643,7 +1676,7 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
1643
1676
  size_t i = 0, col;
1644
1677
  struct buf *row_work = 0;
1645
1678
 
1646
- row_work = rndr_newbuf(rndr);
1679
+ row_work = rndr_newbuf(rndr, BUFFER_SPAN);
1647
1680
 
1648
1681
  if (i < size && data[i] == '|')
1649
1682
  i++;
@@ -1652,7 +1685,7 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
1652
1685
  size_t cell_start, cell_end;
1653
1686
  struct buf *cell_work;
1654
1687
 
1655
- cell_work = rndr_newbuf(rndr);
1688
+ cell_work = rndr_newbuf(rndr, BUFFER_SPAN);
1656
1689
 
1657
1690
  while (i < size && isspace(data[i]))
1658
1691
  i++;
@@ -1671,7 +1704,7 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
1671
1704
  if (rndr->make.table_cell)
1672
1705
  rndr->make.table_cell(row_work, cell_work, col_data ? col_data[col] : 0, rndr->make.opaque);
1673
1706
 
1674
- rndr_popbuf(rndr);
1707
+ rndr_popbuf(rndr, BUFFER_SPAN);
1675
1708
  i++;
1676
1709
  }
1677
1710
 
@@ -1684,7 +1717,7 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
1684
1717
  if (rndr->make.table_row)
1685
1718
  rndr->make.table_row(ob, row_work, rndr->make.opaque);
1686
1719
 
1687
- rndr_popbuf(rndr);
1720
+ rndr_popbuf(rndr, BUFFER_SPAN);
1688
1721
  }
1689
1722
 
1690
1723
  static size_t
@@ -1757,8 +1790,8 @@ parse_table(struct buf *ob, struct render *rndr, char *data, size_t size)
1757
1790
  size_t columns;
1758
1791
  int *col_data = NULL;
1759
1792
 
1760
- header_work = rndr_newbuf(rndr);
1761
- body_work = rndr_newbuf(rndr);
1793
+ header_work = rndr_newbuf(rndr, BUFFER_SPAN);
1794
+ body_work = rndr_newbuf(rndr, BUFFER_BLOCK);
1762
1795
 
1763
1796
  i = parse_table_header(header_work, rndr, data, size, &columns, &col_data);
1764
1797
  if (i > 0) {
@@ -1787,8 +1820,8 @@ parse_table(struct buf *ob, struct render *rndr, char *data, size_t size)
1787
1820
  }
1788
1821
 
1789
1822
  free(col_data);
1790
- rndr_popbuf(rndr);
1791
- rndr_popbuf(rndr);
1823
+ rndr_popbuf(rndr, BUFFER_SPAN);
1824
+ rndr_popbuf(rndr, BUFFER_BLOCK);
1792
1825
  return i;
1793
1826
  }
1794
1827
 
@@ -1800,7 +1833,8 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
1800
1833
  char *txt_data;
1801
1834
  beg = 0;
1802
1835
 
1803
- if (rndr->work.size > rndr->max_nesting)
1836
+ if (rndr->work_bufs[BUFFER_SPAN].size +
1837
+ rndr->work_bufs[BUFFER_BLOCK].size > rndr->max_nesting)
1804
1838
  return;
1805
1839
 
1806
1840
  while (beg < size) {
@@ -2002,13 +2036,17 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer,
2002
2036
  if (!rndrer)
2003
2037
  return;
2004
2038
 
2005
- text = bufnew(TEXT_UNIT);
2039
+ text = bufnew(64);
2006
2040
  if (!text)
2007
2041
  return;
2008
2042
 
2009
- rndr.make = *rndrer;
2043
+ /* Preallocate enough space for our buffer to avoid expanding while copying */
2044
+ bufgrow(text, ib->size);
2045
+
2046
+ memcpy(&rndr.make, rndrer, sizeof(struct mkd_renderer));
2010
2047
  arr_init(&rndr.refs, sizeof (struct link_ref));
2011
- parr_init(&rndr.work);
2048
+ parr_init(&rndr.work_bufs[BUFFER_BLOCK]);
2049
+ parr_init(&rndr.work_bufs[BUFFER_SPAN]);
2012
2050
 
2013
2051
  for (i = 0; i < 256; i += 1)
2014
2052
  rndr.active_char[i] = 0;
@@ -2076,24 +2114,22 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer,
2076
2114
  if (rndr.refs.size)
2077
2115
  qsort(rndr.refs.base, rndr.refs.size, rndr.refs.unit, cmp_link_ref_sort);
2078
2116
 
2079
- /* adding a final newline if not already present */
2080
- if (!text->size)
2081
- goto cleanup;
2082
-
2083
- if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
2084
- bufputc(text, '\n');
2085
-
2086
2117
  /* second pass: actual rendering */
2087
2118
  if (rndr.make.doc_header)
2088
2119
  rndr.make.doc_header(ob, rndr.make.opaque);
2089
2120
 
2090
- parse_block(ob, &rndr, text->data, text->size);
2121
+ if (text->size) {
2122
+ /* adding a final newline if not already present */
2123
+ if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
2124
+ bufputc(text, '\n');
2125
+
2126
+ parse_block(ob, &rndr, text->data, text->size);
2127
+ }
2091
2128
 
2092
2129
  if (rndr.make.doc_footer)
2093
2130
  rndr.make.doc_footer(ob, rndr.make.opaque);
2094
2131
 
2095
2132
  /* clean-up */
2096
- cleanup:
2097
2133
  bufrelease(text);
2098
2134
  lr = rndr.refs.base;
2099
2135
  for (i = 0; i < (size_t)rndr.refs.size; i += 1) {
@@ -2104,12 +2140,17 @@ cleanup:
2104
2140
 
2105
2141
  arr_free(&rndr.refs);
2106
2142
 
2107
- assert(rndr.work.size == 0);
2143
+ assert(rndr.work_bufs[BUFFER_SPAN].size == 0);
2144
+ assert(rndr.work_bufs[BUFFER_BLOCK].size == 0);
2145
+
2146
+ for (i = 0; i < (size_t)rndr.work_bufs[BUFFER_SPAN].asize; ++i)
2147
+ bufrelease(rndr.work_bufs[BUFFER_SPAN].item[i]);
2108
2148
 
2109
- for (i = 0; i < (size_t)rndr.work.asize; i += 1)
2110
- bufrelease(rndr.work.item[i]);
2149
+ for (i = 0; i < (size_t)rndr.work_bufs[BUFFER_BLOCK].asize; ++i)
2150
+ bufrelease(rndr.work_bufs[BUFFER_BLOCK].item[i]);
2111
2151
 
2112
- parr_free(&rndr.work);
2152
+ parr_free(&rndr.work_bufs[BUFFER_SPAN]);
2153
+ parr_free(&rndr.work_bufs[BUFFER_BLOCK]);
2113
2154
  }
2114
2155
 
2115
2156
  /* vim: set filetype=c: */
data/ext/markdown.h CHANGED
@@ -33,7 +33,7 @@ enum mkd_autolink {
33
33
  };
34
34
 
35
35
  enum mkd_extensions {
36
- MKDEXT_STRICT_EMPHASIS = (1 << 0),
36
+ MKDEXT_NO_INTRA_EMPHASIS = (1 << 0),
37
37
  MKDEXT_TABLES = (1 << 1),
38
38
  MKDEXT_FENCED_CODE = (1 << 2),
39
39
  MKDEXT_AUTOLINK = (1 << 3),
data/ext/redcarpet.c CHANGED
@@ -55,8 +55,8 @@ static void rb_redcarpet__get_flags(VALUE ruby_obj,
55
55
  /**
56
56
  * Markdown extensions -- all disabled by default
57
57
  */
58
- if (rb_funcall(ruby_obj, rb_intern("strict"), 0) == Qtrue)
59
- extensions |= MKDEXT_STRICT_EMPHASIS;
58
+ if (rb_funcall(ruby_obj, rb_intern("no_intraemphasis"), 0) == Qtrue)
59
+ extensions |= MKDEXT_NO_INTRA_EMPHASIS;
60
60
 
61
61
  if (rb_funcall(ruby_obj, rb_intern("tables"), 0) == Qtrue)
62
62
  extensions |= MKDEXT_TABLES;
data/ext/xhtml.c CHANGED
@@ -147,14 +147,24 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
147
147
  if (ob->size) bufputc(ob, '\n');
148
148
 
149
149
  if (lang && lang->size) {
150
- size_t i = 0;
150
+ size_t i, cls;
151
151
  BUFPUTSL(ob, "<pre><code class=\"");
152
152
 
153
- for (i = 0; i < lang->size; ++i) {
154
- if (lang->data[i] == '.' && (i == 0 || isspace(lang->data[i - 1])))
155
- continue;
153
+ for (i = 0, cls = 0; i < lang->size; ++i, ++cls) {
154
+ while (i < lang->size && isspace(lang->data[i]))
155
+ i++;
156
+
157
+ if (i < lang->size) {
158
+ size_t org = i;
159
+ while (i < lang->size && !isspace(lang->data[i]))
160
+ i++;
156
161
 
157
- bufputc(ob, lang->data[i]);
162
+ if (lang->data[org] == '.')
163
+ org++;
164
+
165
+ if (cls) bufputc(ob, ' ');
166
+ attr_escape(ob, lang->data + org, i - org);
167
+ }
158
168
  }
159
169
 
160
170
  BUFPUTSL(ob, "\">");
@@ -194,14 +204,13 @@ rndr_blockcode_github(struct buf *ob, struct buf *text, struct buf *lang, void *
194
204
  size_t i = 0;
195
205
  BUFPUTSL(ob, "<pre lang=\"");
196
206
 
197
- for (; i < lang->size; ++i)
198
- if (isspace(lang->data[i]))
199
- break;
207
+ while (i < lang->size && !isspace(lang->data[i]))
208
+ i++;
200
209
 
201
210
  if (lang->data[0] == '.')
202
- bufput(ob, lang->data + 1, i - 1);
211
+ attr_escape(ob, lang->data + 1, i - 1);
203
212
  else
204
- bufput(ob, lang->data, i);
213
+ attr_escape(ob, lang->data, i);
205
214
 
206
215
  BUFPUTSL(ob, "\"><code>");
207
216
  } else
data/lib/redcarpet.rb CHANGED
@@ -26,7 +26,7 @@
26
26
  # end
27
27
  #
28
28
  class Redcarpet
29
- VERSION = '1.11.4'
29
+ VERSION = '1.12.0'
30
30
 
31
31
  # Original Markdown formatted text.
32
32
  attr_reader :text
@@ -49,9 +49,6 @@ class Redcarpet
49
49
  # Treat newlines in paragraphs as real line breaks, GitHub style
50
50
  attr_accessor :hard_wrap
51
51
 
52
- # Disable relaxed emphasis processing.
53
- attr_accessor :strict
54
-
55
52
  # Generate safer HTML for code blocks (no custom CSS classes)
56
53
  attr_accessor :gh_blockcode
57
54
 
@@ -76,6 +73,9 @@ class Redcarpet
76
73
  # Allow HTML blocks inside of paragraphs without being surrounded by newlines
77
74
  attr_accessor :lax_htmlblock
78
75
 
76
+ # Do not render emphasis_inside_words
77
+ attr_accessor :no_intraemphasis
78
+
79
79
  def initialize(text, *extensions)
80
80
  @text = text
81
81
  extensions.each { |e| send("#{e}=", true) }
@@ -92,12 +92,14 @@ class RedcarpetCompat < Redcarpet
92
92
  attr_accessor :fold_lines
93
93
  attr_accessor :no_tables
94
94
  attr_accessor :fold_lines
95
+ attr_accessor :strict
95
96
 
96
97
  def initialize(text, *extensions)
97
98
  super(text, *extensions)
98
99
  self.tables = !self.no_tables
99
100
  self.strikethrough = true
100
101
  self.lax_htmlblock = true
102
+ self.no_intraemphasis = !self.strict
101
103
  end
102
104
  end
103
105
 
data/redcarpet.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'redcarpet'
3
- s.version = '1.11.4'
3
+ s.version = '1.12.0'
4
4
  s.summary = "Ruby bindings for libupskirt"
5
5
  s.description = 'A fast and safe Markdown to (X)HTML parser'
6
- s.date = '2011-04-28'
6
+ s.date = '2011-04-30'
7
7
  s.email = 'vicent@github.com'
8
8
  s.homepage = 'http://github.com/tanoku/redcarpet'
9
9
  s.has_rdoc = true
@@ -32,7 +32,7 @@ class MarkdownTest < Test::Unit::TestCase
32
32
  end
33
33
 
34
34
  def test_that_inline_markdown_starts_and_ends_correctly
35
- markdown = Markdown.new('_start _ foo_bar bar_baz _ end_ *italic* **bold** <a>_blah_</a>')
35
+ markdown = Markdown.new('_start _ foo_bar bar_baz _ end_ *italic* **bold** <a>_blah_</a>', :no_intraemphasis)
36
36
  assert_respond_to markdown, :to_html
37
37
  html_equal "<p><em>start _ foo_bar bar_baz _ end</em> <em>italic</em> <strong>bold</strong> <a><em>blah</em></a></p>", markdown.to_html.strip
38
38
 
@@ -64,7 +64,7 @@ class RedcarpetTest < Test::Unit::TestCase
64
64
  end
65
65
 
66
66
  def test_that_strict_flag_works
67
- rd = Redcarpet.new("foo_bar_baz", :strict)
67
+ rd = RedcarpetCompat.new("foo_bar_baz", :strict)
68
68
  assert_equal "<p>foo<em>bar</em>baz</p>\n", rd.to_html
69
69
  end
70
70
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redcarpet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 51
4
+ hash: 39
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 11
9
- - 4
10
- version: 1.11.4
8
+ - 12
9
+ - 0
10
+ version: 1.12.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Natacha Port\xC3\xA9"
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-04-28 00:00:00 +03:00
19
+ date: 2011-04-30 00:00:00 +03:00
20
20
  default_executable:
21
21
  dependencies: []
22
22