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 +121 -80
- data/ext/markdown.h +1 -1
- data/ext/redcarpet.c +2 -2
- data/ext/xhtml.c +19 -10
- data/lib/redcarpet.rb +6 -4
- data/redcarpet.gemspec +2 -2
- data/test/markdown_test.rb +1 -1
- data/test/redcarpet_test.rb +1 -1
- metadata +5 -5
data/ext/markdown.c
CHANGED
@@ -26,8 +26,8 @@
|
|
26
26
|
#include <ctype.h>
|
27
27
|
#include <stdio.h>
|
28
28
|
|
29
|
-
#define
|
30
|
-
#define
|
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
|
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 (
|
76
|
-
work =
|
77
|
+
if (queue->size < queue->asize) {
|
78
|
+
work = queue->item[queue->size++];
|
77
79
|
work->size = 0;
|
78
80
|
} else {
|
79
|
-
work = bufnew(
|
80
|
-
parr_push(
|
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->
|
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->
|
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 &
|
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
|
-
|
678
|
-
|
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
|
-
|
684
|
-
|
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->
|
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->
|
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->
|
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(
|
2039
|
+
text = bufnew(64);
|
2006
2040
|
if (!text)
|
2007
2041
|
return;
|
2008
2042
|
|
2009
|
-
|
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.
|
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
|
-
|
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.
|
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.
|
2110
|
-
bufrelease(rndr.
|
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.
|
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
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("
|
59
|
-
extensions |=
|
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
|
150
|
+
size_t i, cls;
|
151
151
|
BUFPUTSL(ob, "<pre><code class=\"");
|
152
152
|
|
153
|
-
for (i = 0; i < lang->size; ++i) {
|
154
|
-
|
155
|
-
|
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
|
-
|
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
|
-
|
198
|
-
|
199
|
-
break;
|
207
|
+
while (i < lang->size && !isspace(lang->data[i]))
|
208
|
+
i++;
|
200
209
|
|
201
210
|
if (lang->data[0] == '.')
|
202
|
-
|
211
|
+
attr_escape(ob, lang->data + 1, i - 1);
|
203
212
|
else
|
204
|
-
|
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.
|
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.
|
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-
|
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
|
data/test/markdown_test.rb
CHANGED
@@ -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
|
|
data/test/redcarpet_test.rb
CHANGED
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:
|
4
|
+
hash: 39
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
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-
|
19
|
+
date: 2011-04-30 00:00:00 +03:00
|
20
20
|
default_executable:
|
21
21
|
dependencies: []
|
22
22
|
|