redcarpet 2.0.0b → 2.0.0b3
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/README.markdown +2 -2
- data/ext/redcarpet/html.c +38 -45
- data/ext/redcarpet/html.h +15 -6
- data/ext/redcarpet/markdown.c +95 -80
- data/ext/redcarpet/markdown.h +4 -7
- data/ext/redcarpet/rc_markdown.c +22 -19
- data/ext/redcarpet/rc_render.c +39 -68
- data/ext/redcarpet/redcarpet.h +32 -0
- data/lib/redcarpet.rb +1 -1
- data/lib/redcarpet/render_man.rb +65 -0
- data/redcarpet.gemspec +5 -2
- data/test/redcarpet_test.rb +8 -0
- metadata +37 -45
data/README.markdown
CHANGED
@@ -123,7 +123,7 @@ renderers are actually implemented in C, and hence offer a brilliant
|
|
123
123
|
performance, several degrees of magnitude faster than other Ruby Markdown
|
124
124
|
solutions.
|
125
125
|
|
126
|
-
The `HTML` renderer has an alternate version, `Redcarpet::Render::
|
126
|
+
The `HTML` renderer has an alternate version, `Redcarpet::Render::HTML_TOC`,
|
127
127
|
which will output a table of contents in HTML based on the headers of the
|
128
128
|
Markdown document.
|
129
129
|
|
@@ -180,7 +180,7 @@ The following instance methods may be implemented by the renderer:
|
|
180
180
|
header(text, header_level)
|
181
181
|
hrule()
|
182
182
|
list(contents, list_type)
|
183
|
-
list_item(text)
|
183
|
+
list_item(text, list_type)
|
184
184
|
paragraph(text)
|
185
185
|
table(header, body)
|
186
186
|
table_row(content)
|
data/ext/redcarpet/html.c
CHANGED
@@ -25,17 +25,6 @@
|
|
25
25
|
|
26
26
|
#define USE_XHTML(opt) (opt->flags & HTML_USE_XHTML)
|
27
27
|
|
28
|
-
struct html_renderopt {
|
29
|
-
void *extra;
|
30
|
-
|
31
|
-
struct {
|
32
|
-
int header_count;
|
33
|
-
int current_level;
|
34
|
-
} toc_data;
|
35
|
-
|
36
|
-
unsigned int flags;
|
37
|
-
};
|
38
|
-
|
39
28
|
static inline void
|
40
29
|
put_scaped_char(struct buf *ob, char c)
|
41
30
|
{
|
@@ -122,7 +111,14 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
|
|
122
111
|
if (type == MKDA_EMAIL)
|
123
112
|
BUFPUTSL(ob, "mailto:");
|
124
113
|
bufput(ob, link->data, link->size);
|
125
|
-
|
114
|
+
|
115
|
+
if (options->link_attributes) {
|
116
|
+
bufputc(ob, '\"');
|
117
|
+
options->link_attributes(ob, link, opaque);
|
118
|
+
bufputc(ob, '>');
|
119
|
+
} else {
|
120
|
+
BUFPUTSL(ob, "\">");
|
121
|
+
}
|
126
122
|
|
127
123
|
/*
|
128
124
|
* Pretty printing: if we get an email address as
|
@@ -308,11 +304,23 @@ rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *conte
|
|
308
304
|
return 0;
|
309
305
|
|
310
306
|
BUFPUTSL(ob, "<a href=\"");
|
311
|
-
|
307
|
+
|
308
|
+
if (link && link->size)
|
309
|
+
bufput(ob, link->data, link->size);
|
310
|
+
|
312
311
|
if (title && title->size) {
|
313
312
|
BUFPUTSL(ob, "\" title=\"");
|
314
|
-
sdhtml_escape(ob, title->data, title->size);
|
315
|
-
|
313
|
+
sdhtml_escape(ob, title->data, title->size);
|
314
|
+
}
|
315
|
+
|
316
|
+
if (options->link_attributes) {
|
317
|
+
bufputc(ob, '\"');
|
318
|
+
options->link_attributes(ob, link, opaque);
|
319
|
+
bufputc(ob, '>');
|
320
|
+
} else {
|
321
|
+
BUFPUTSL(ob, "\">");
|
322
|
+
}
|
323
|
+
|
316
324
|
if (content && content->size) bufput(ob, content->data, content->size);
|
317
325
|
BUFPUTSL(ob, "</a>");
|
318
326
|
return 1;
|
@@ -558,9 +566,9 @@ toc_finalize(struct buf *ob, void *opaque)
|
|
558
566
|
}
|
559
567
|
|
560
568
|
void
|
561
|
-
sdhtml_toc_renderer(struct
|
569
|
+
sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options)
|
562
570
|
{
|
563
|
-
static const struct
|
571
|
+
static const struct sd_callbacks cb_default = {
|
564
572
|
NULL,
|
565
573
|
NULL,
|
566
574
|
NULL,
|
@@ -590,23 +598,18 @@ sdhtml_toc_renderer(struct mkd_renderer *renderer, void *extra)
|
|
590
598
|
|
591
599
|
NULL,
|
592
600
|
toc_finalize,
|
593
|
-
|
594
|
-
NULL
|
595
601
|
};
|
596
602
|
|
597
|
-
struct html_renderopt
|
598
|
-
options = calloc(1, sizeof(struct html_renderopt));
|
603
|
+
memset(options, 0x0, sizeof(struct html_renderopt));
|
599
604
|
options->flags = HTML_TOC;
|
600
|
-
options->extra = extra;
|
601
605
|
|
602
|
-
memcpy(
|
603
|
-
renderer->opaque = options;
|
606
|
+
memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
|
604
607
|
}
|
605
608
|
|
606
609
|
void
|
607
|
-
sdhtml_renderer(struct
|
610
|
+
sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, unsigned int render_flags)
|
608
611
|
{
|
609
|
-
static const struct
|
612
|
+
static const struct sd_callbacks cb_default = {
|
610
613
|
rndr_blockcode,
|
611
614
|
rndr_blockquote,
|
612
615
|
rndr_raw_block,
|
@@ -636,36 +639,26 @@ sdhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags, void *
|
|
636
639
|
|
637
640
|
NULL,
|
638
641
|
NULL,
|
639
|
-
|
640
|
-
NULL
|
641
642
|
};
|
642
643
|
|
643
|
-
|
644
|
-
options
|
644
|
+
/* Prepare the options pointer */
|
645
|
+
memset(options, 0x0, sizeof(struct html_renderopt));
|
645
646
|
options->flags = render_flags;
|
646
|
-
options->extra = extra;
|
647
647
|
|
648
|
-
|
649
|
-
|
648
|
+
/* Prepare the callbacks */
|
649
|
+
memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
|
650
650
|
|
651
651
|
if (render_flags & HTML_SKIP_IMAGES)
|
652
|
-
|
652
|
+
callbacks->image = NULL;
|
653
653
|
|
654
654
|
if (render_flags & HTML_SKIP_LINKS) {
|
655
|
-
|
656
|
-
|
655
|
+
callbacks->link = NULL;
|
656
|
+
callbacks->autolink = NULL;
|
657
657
|
}
|
658
658
|
|
659
659
|
if (render_flags & HTML_SKIP_HTML)
|
660
|
-
|
660
|
+
callbacks->blockhtml = NULL;
|
661
661
|
|
662
662
|
if (render_flags & HTML_GITHUB_BLOCKCODE)
|
663
|
-
|
663
|
+
callbacks->blockcode = rndr_blockcode_github;
|
664
664
|
}
|
665
|
-
|
666
|
-
void
|
667
|
-
sdhtml_free_renderer(struct mkd_renderer *renderer)
|
668
|
-
{
|
669
|
-
free(renderer->opaque);
|
670
|
-
}
|
671
|
-
|
data/ext/redcarpet/html.h
CHANGED
@@ -21,6 +21,18 @@
|
|
21
21
|
#include "buffer.h"
|
22
22
|
#include <stdlib.h>
|
23
23
|
|
24
|
+
struct html_renderopt {
|
25
|
+
struct {
|
26
|
+
int header_count;
|
27
|
+
int current_level;
|
28
|
+
} toc_data;
|
29
|
+
|
30
|
+
unsigned int flags;
|
31
|
+
|
32
|
+
/* extra callbacks */
|
33
|
+
void (*link_attributes)(struct buf *ob, struct buf *url, void *self);
|
34
|
+
};
|
35
|
+
|
24
36
|
typedef enum {
|
25
37
|
HTML_SKIP_HTML = (1 << 0),
|
26
38
|
HTML_SKIP_STYLE = (1 << 1),
|
@@ -32,7 +44,7 @@ typedef enum {
|
|
32
44
|
HTML_HARD_WRAP = (1 << 9),
|
33
45
|
HTML_GITHUB_BLOCKCODE = (1 << 10),
|
34
46
|
HTML_USE_XHTML = (1 << 11),
|
35
|
-
}
|
47
|
+
} html_render_mode;
|
36
48
|
|
37
49
|
typedef enum {
|
38
50
|
HTML_TAG_NONE = 0,
|
@@ -47,13 +59,10 @@ int
|
|
47
59
|
sdhtml_tag(const char *tag_data, size_t tag_size, const char *tagname);
|
48
60
|
|
49
61
|
extern void
|
50
|
-
sdhtml_renderer(struct
|
51
|
-
|
52
|
-
extern void
|
53
|
-
sdhtml_toc_renderer(struct mkd_renderer *renderer, void *extra);
|
62
|
+
sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);
|
54
63
|
|
55
64
|
extern void
|
56
|
-
|
65
|
+
sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr);
|
57
66
|
|
58
67
|
extern void
|
59
68
|
sdhtml_smartypants(struct buf *ob, struct buf *text);
|
data/ext/redcarpet/markdown.c
CHANGED
@@ -94,7 +94,9 @@ static char_trigger markdown_char_ptrs[] = {
|
|
94
94
|
|
95
95
|
/* render • structure containing one particular render */
|
96
96
|
struct render {
|
97
|
-
struct
|
97
|
+
struct sd_callbacks cb;
|
98
|
+
void *opaque;
|
99
|
+
|
98
100
|
struct array refs;
|
99
101
|
char active_char[256];
|
100
102
|
struct parray work_bufs[2];
|
@@ -354,10 +356,10 @@ parse_inline(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
354
356
|
end++;
|
355
357
|
}
|
356
358
|
|
357
|
-
if (rndr->
|
359
|
+
if (rndr->cb.normal_text) {
|
358
360
|
work.data = data + i;
|
359
361
|
work.size = end - i;
|
360
|
-
rndr->
|
362
|
+
rndr->cb.normal_text(ob, &work, rndr->opaque);
|
361
363
|
}
|
362
364
|
else
|
363
365
|
bufput(ob, data + i, end - i);
|
@@ -461,7 +463,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
|
|
461
463
|
struct buf *work = 0;
|
462
464
|
int r;
|
463
465
|
|
464
|
-
if (!rndr->
|
466
|
+
if (!rndr->cb.emphasis) return 0;
|
465
467
|
|
466
468
|
/* skipping one symbol if coming from emph3 */
|
467
469
|
if (size > 1 && data[0] == c && data[1] == c) i = 1;
|
@@ -486,7 +488,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
|
|
486
488
|
|
487
489
|
work = rndr_newbuf(rndr, BUFFER_SPAN);
|
488
490
|
parse_inline(work, rndr, data, i);
|
489
|
-
r = rndr->
|
491
|
+
r = rndr->cb.emphasis(ob, work, rndr->opaque);
|
490
492
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
491
493
|
return r ? i + 1 : 0;
|
492
494
|
}
|
@@ -504,7 +506,7 @@ parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c
|
|
504
506
|
struct buf *work = 0;
|
505
507
|
int r;
|
506
508
|
|
507
|
-
render_method = (c == '~') ? rndr->
|
509
|
+
render_method = (c == '~') ? rndr->cb.strikethrough : rndr->cb.double_emphasis;
|
508
510
|
|
509
511
|
if (!render_method)
|
510
512
|
return 0;
|
@@ -517,7 +519,7 @@ parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c
|
|
517
519
|
if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !isspace(data[i - 1])) {
|
518
520
|
work = rndr_newbuf(rndr, BUFFER_SPAN);
|
519
521
|
parse_inline(work, rndr, data, i);
|
520
|
-
r = render_method(ob, work, rndr->
|
522
|
+
r = render_method(ob, work, rndr->opaque);
|
521
523
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
522
524
|
return r ? i + 2 : 0;
|
523
525
|
}
|
@@ -543,12 +545,12 @@ parse_emph3(struct buf *ob, struct render *rndr, char *data, size_t size, char c
|
|
543
545
|
if (data[i] != c || isspace(data[i - 1]))
|
544
546
|
continue;
|
545
547
|
|
546
|
-
if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->
|
548
|
+
if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->cb.triple_emphasis) {
|
547
549
|
/* triple symbol found */
|
548
550
|
struct buf *work = rndr_newbuf(rndr, BUFFER_SPAN);
|
549
551
|
|
550
552
|
parse_inline(work, rndr, data, i);
|
551
|
-
r = rndr->
|
553
|
+
r = rndr->cb.triple_emphasis(ob, work, rndr->opaque);
|
552
554
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
553
555
|
return r ? i + 3 : 0;
|
554
556
|
|
@@ -613,7 +615,7 @@ char_linebreak(struct buf *ob, struct render *rndr, char *data, size_t offset, s
|
|
613
615
|
while (ob->size && ob->data[ob->size - 1] == ' ')
|
614
616
|
ob->size--;
|
615
617
|
|
616
|
-
return rndr->
|
618
|
+
return rndr->cb.linebreak(ob, rndr->opaque) ? 1 : 0;
|
617
619
|
}
|
618
620
|
|
619
621
|
|
@@ -649,10 +651,10 @@ char_codespan(struct buf *ob, struct render *rndr, char *data, size_t offset, si
|
|
649
651
|
/* real code span */
|
650
652
|
if (f_begin < f_end) {
|
651
653
|
struct buf work = { data + f_begin, f_end - f_begin, 0, 0, 0 };
|
652
|
-
if (!rndr->
|
654
|
+
if (!rndr->cb.codespan(ob, &work, rndr->opaque))
|
653
655
|
end = 0;
|
654
656
|
} else {
|
655
|
-
if (!rndr->
|
657
|
+
if (!rndr->cb.codespan(ob, 0, rndr->opaque))
|
656
658
|
end = 0;
|
657
659
|
}
|
658
660
|
|
@@ -671,10 +673,10 @@ char_escape(struct buf *ob, struct render *rndr, char *data, size_t offset, size
|
|
671
673
|
if (strchr(escape_chars, data[1]) == NULL)
|
672
674
|
return 0;
|
673
675
|
|
674
|
-
if (rndr->
|
676
|
+
if (rndr->cb.normal_text) {
|
675
677
|
work.data = data + 1;
|
676
678
|
work.size = 1;
|
677
|
-
rndr->
|
679
|
+
rndr->cb.normal_text(ob, &work, rndr->opaque);
|
678
680
|
}
|
679
681
|
else bufputc(ob, data[1]);
|
680
682
|
}
|
@@ -701,10 +703,10 @@ char_entity(struct buf *ob, struct render *rndr, char *data, size_t offset, size
|
|
701
703
|
else
|
702
704
|
return 0; /* lone '&' */
|
703
705
|
|
704
|
-
if (rndr->
|
706
|
+
if (rndr->cb.entity) {
|
705
707
|
work.data = data;
|
706
708
|
work.size = end;
|
707
|
-
rndr->
|
709
|
+
rndr->cb.entity(ob, &work, rndr->opaque);
|
708
710
|
}
|
709
711
|
else bufput(ob, data, end);
|
710
712
|
|
@@ -721,16 +723,16 @@ char_langle_tag(struct buf *ob, struct render *rndr, char *data, size_t offset,
|
|
721
723
|
int ret = 0;
|
722
724
|
|
723
725
|
if (end > 2) {
|
724
|
-
if (rndr->
|
726
|
+
if (rndr->cb.autolink && altype != MKDA_NOT_AUTOLINK) {
|
725
727
|
struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
|
726
728
|
work.data = data + 1;
|
727
729
|
work.size = end - 2;
|
728
730
|
unscape_text(u_link, &work);
|
729
|
-
ret = rndr->
|
731
|
+
ret = rndr->cb.autolink(ob, u_link, altype, rndr->opaque);
|
730
732
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
731
733
|
}
|
732
|
-
else if (rndr->
|
733
|
-
ret = rndr->
|
734
|
+
else if (rndr->cb.raw_html_tag)
|
735
|
+
ret = rndr->cb.raw_html_tag(ob, &work, rndr->opaque);
|
734
736
|
}
|
735
737
|
|
736
738
|
if (!ret) return 0;
|
@@ -743,7 +745,7 @@ char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset
|
|
743
745
|
struct buf *link, *link_url;
|
744
746
|
size_t link_len, rewind;
|
745
747
|
|
746
|
-
if (!rndr->
|
748
|
+
if (!rndr->cb.link)
|
747
749
|
return 0;
|
748
750
|
|
749
751
|
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
@@ -754,7 +756,7 @@ char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset
|
|
754
756
|
bufput(link_url, link->data, link->size);
|
755
757
|
|
756
758
|
ob->size -= rewind;
|
757
|
-
rndr->
|
759
|
+
rndr->cb.link(ob, link_url, NULL, link, rndr->opaque);
|
758
760
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
759
761
|
}
|
760
762
|
|
@@ -768,14 +770,14 @@ char_autolink_email(struct buf *ob, struct render *rndr, char *data, size_t offs
|
|
768
770
|
struct buf *link;
|
769
771
|
size_t link_len, rewind;
|
770
772
|
|
771
|
-
if (!rndr->
|
773
|
+
if (!rndr->cb.autolink)
|
772
774
|
return 0;
|
773
775
|
|
774
776
|
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
775
777
|
|
776
778
|
if ((link_len = sd_autolink__email(&rewind, link, data, offset, size)) > 0) {
|
777
779
|
ob->size -= rewind;
|
778
|
-
rndr->
|
780
|
+
rndr->cb.autolink(ob, link, MKDA_EMAIL, rndr->opaque);
|
779
781
|
}
|
780
782
|
|
781
783
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
@@ -788,14 +790,14 @@ char_autolink_url(struct buf *ob, struct render *rndr, char *data, size_t offset
|
|
788
790
|
struct buf *link;
|
789
791
|
size_t link_len, rewind;
|
790
792
|
|
791
|
-
if (!rndr->
|
793
|
+
if (!rndr->cb.autolink)
|
792
794
|
return 0;
|
793
795
|
|
794
796
|
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
795
797
|
|
796
798
|
if ((link_len = sd_autolink__url(&rewind, link, data, offset, size)) > 0) {
|
797
799
|
ob->size -= rewind;
|
798
|
-
rndr->
|
800
|
+
rndr->cb.autolink(ob, link, MKDA_NORMAL, rndr->opaque);
|
799
801
|
}
|
800
802
|
|
801
803
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
@@ -816,7 +818,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
|
|
816
818
|
int text_has_nl = 0, ret = 0;
|
817
819
|
|
818
820
|
/* checking whether the correct renderer exists */
|
819
|
-
if ((is_img && !rndr->
|
821
|
+
if ((is_img && !rndr->cb.image) || (!is_img && !rndr->cb.link))
|
820
822
|
goto cleanup;
|
821
823
|
|
822
824
|
/* looking for the matching closing bracket */
|
@@ -1013,9 +1015,9 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
|
|
1013
1015
|
if (ob->size && ob->data[ob->size - 1] == '!')
|
1014
1016
|
ob->size -= 1;
|
1015
1017
|
|
1016
|
-
ret = rndr->
|
1018
|
+
ret = rndr->cb.image(ob, u_link, title, content, rndr->opaque);
|
1017
1019
|
} else {
|
1018
|
-
ret = rndr->
|
1020
|
+
ret = rndr->cb.link(ob, u_link, title, content, rndr->opaque);
|
1019
1021
|
}
|
1020
1022
|
|
1021
1023
|
/* cleanup */
|
@@ -1030,7 +1032,7 @@ char_superscript(struct buf *ob, struct render *rndr, char *data, size_t offset,
|
|
1030
1032
|
size_t sup_start, sup_len;
|
1031
1033
|
struct buf *sup;
|
1032
1034
|
|
1033
|
-
if (!rndr->
|
1035
|
+
if (!rndr->cb.superscript)
|
1034
1036
|
return 0;
|
1035
1037
|
|
1036
1038
|
if (size < 2)
|
@@ -1056,7 +1058,7 @@ char_superscript(struct buf *ob, struct render *rndr, char *data, size_t offset,
|
|
1056
1058
|
|
1057
1059
|
sup = rndr_newbuf(rndr, BUFFER_SPAN);
|
1058
1060
|
parse_inline(sup, rndr, data + sup_start, sup_len - sup_start);
|
1059
|
-
rndr->
|
1061
|
+
rndr->cb.superscript(ob, sup, rndr->opaque);
|
1060
1062
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
1061
1063
|
|
1062
1064
|
return (sup_start == 2) ? sup_len + 1 : sup_len;
|
@@ -1317,8 +1319,8 @@ parse_blockquote(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1317
1319
|
}
|
1318
1320
|
|
1319
1321
|
parse_block(out, rndr, work_data, work_size);
|
1320
|
-
if (rndr->
|
1321
|
-
rndr->
|
1322
|
+
if (rndr->cb.blockquote)
|
1323
|
+
rndr->cb.blockquote(ob, out, rndr->opaque);
|
1322
1324
|
rndr_popbuf(rndr, BUFFER_BLOCK);
|
1323
1325
|
return end;
|
1324
1326
|
}
|
@@ -1341,7 +1343,7 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1341
1343
|
break;
|
1342
1344
|
|
1343
1345
|
if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
|
1344
|
-
if (data[i] == '<' && rndr->
|
1346
|
+
if (data[i] == '<' && rndr->cb.blockhtml && parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
|
1345
1347
|
end = i;
|
1346
1348
|
break;
|
1347
1349
|
}
|
@@ -1362,8 +1364,8 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1362
1364
|
if (!level) {
|
1363
1365
|
struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
|
1364
1366
|
parse_inline(tmp, rndr, work.data, work.size);
|
1365
|
-
if (rndr->
|
1366
|
-
rndr->
|
1367
|
+
if (rndr->cb.paragraph)
|
1368
|
+
rndr->cb.paragraph(ob, tmp, rndr->opaque);
|
1367
1369
|
rndr_popbuf(rndr, BUFFER_BLOCK);
|
1368
1370
|
} else {
|
1369
1371
|
struct buf *header_work;
|
@@ -1384,8 +1386,8 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1384
1386
|
struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
|
1385
1387
|
parse_inline(tmp, rndr, work.data, work.size);
|
1386
1388
|
|
1387
|
-
if (rndr->
|
1388
|
-
rndr->
|
1389
|
+
if (rndr->cb.paragraph)
|
1390
|
+
rndr->cb.paragraph(ob, tmp, rndr->opaque);
|
1389
1391
|
|
1390
1392
|
rndr_popbuf(rndr, BUFFER_BLOCK);
|
1391
1393
|
work.data += beg;
|
@@ -1397,8 +1399,8 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1397
1399
|
header_work = rndr_newbuf(rndr, BUFFER_SPAN);
|
1398
1400
|
parse_inline(header_work, rndr, work.data, work.size);
|
1399
1401
|
|
1400
|
-
if (rndr->
|
1401
|
-
rndr->
|
1402
|
+
if (rndr->cb.header)
|
1403
|
+
rndr->cb.header(ob, header_work, (int)level, rndr->opaque);
|
1402
1404
|
|
1403
1405
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
1404
1406
|
}
|
@@ -1443,8 +1445,8 @@ parse_fencedcode(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1443
1445
|
if (work->size && work->data[work->size - 1] != '\n')
|
1444
1446
|
bufputc(work, '\n');
|
1445
1447
|
|
1446
|
-
if (rndr->
|
1447
|
-
rndr->
|
1448
|
+
if (rndr->cb.blockcode)
|
1449
|
+
rndr->cb.blockcode(ob, work, lang.size ? &lang : NULL, rndr->opaque);
|
1448
1450
|
|
1449
1451
|
rndr_popbuf(rndr, BUFFER_BLOCK);
|
1450
1452
|
return beg;
|
@@ -1484,8 +1486,8 @@ parse_blockcode(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1484
1486
|
|
1485
1487
|
bufputc(work, '\n');
|
1486
1488
|
|
1487
|
-
if (rndr->
|
1488
|
-
rndr->
|
1489
|
+
if (rndr->cb.blockcode)
|
1490
|
+
rndr->cb.blockcode(ob, work, NULL, rndr->opaque);
|
1489
1491
|
|
1490
1492
|
rndr_popbuf(rndr, BUFFER_BLOCK);
|
1491
1493
|
return beg;
|
@@ -1599,8 +1601,8 @@ parse_listitem(struct buf *ob, struct render *rndr, char *data, size_t size, int
|
|
1599
1601
|
}
|
1600
1602
|
|
1601
1603
|
/* render of li itself */
|
1602
|
-
if (rndr->
|
1603
|
-
rndr->
|
1604
|
+
if (rndr->cb.listitem)
|
1605
|
+
rndr->cb.listitem(ob, inter, *flags, rndr->opaque);
|
1604
1606
|
|
1605
1607
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
1606
1608
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
@@ -1625,8 +1627,8 @@ parse_list(struct buf *ob, struct render *rndr, char *data, size_t size, int fla
|
|
1625
1627
|
break;
|
1626
1628
|
}
|
1627
1629
|
|
1628
|
-
if (rndr->
|
1629
|
-
rndr->
|
1630
|
+
if (rndr->cb.list)
|
1631
|
+
rndr->cb.list(ob, work, flags, rndr->opaque);
|
1630
1632
|
rndr_popbuf(rndr, BUFFER_BLOCK);
|
1631
1633
|
return i;
|
1632
1634
|
}
|
@@ -1657,8 +1659,8 @@ parse_atxheader(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1657
1659
|
|
1658
1660
|
parse_inline(work, rndr, data + i, end - i);
|
1659
1661
|
|
1660
|
-
if (rndr->
|
1661
|
-
rndr->
|
1662
|
+
if (rndr->cb.header)
|
1663
|
+
rndr->cb.header(ob, work, (int)level, rndr->opaque);
|
1662
1664
|
|
1663
1665
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
1664
1666
|
}
|
@@ -1732,8 +1734,8 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
|
|
1732
1734
|
|
1733
1735
|
if (j) {
|
1734
1736
|
work.size = i + j;
|
1735
|
-
if (do_render && rndr->
|
1736
|
-
rndr->
|
1737
|
+
if (do_render && rndr->cb.blockhtml)
|
1738
|
+
rndr->cb.blockhtml(ob, &work, rndr->opaque);
|
1737
1739
|
return work.size;
|
1738
1740
|
}
|
1739
1741
|
}
|
@@ -1749,8 +1751,8 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
|
|
1749
1751
|
j = is_empty(data + i, size - i);
|
1750
1752
|
if (j) {
|
1751
1753
|
work.size = i + j;
|
1752
|
-
if (do_render && rndr->
|
1753
|
-
rndr->
|
1754
|
+
if (do_render && rndr->cb.blockhtml)
|
1755
|
+
rndr->cb.blockhtml(ob, &work, rndr->opaque);
|
1754
1756
|
return work.size;
|
1755
1757
|
}
|
1756
1758
|
}
|
@@ -1791,8 +1793,8 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
|
|
1791
1793
|
|
1792
1794
|
/* the end of the block has been found */
|
1793
1795
|
work.size = i;
|
1794
|
-
if (do_render && rndr->
|
1795
|
-
rndr->
|
1796
|
+
if (do_render && rndr->cb.blockhtml)
|
1797
|
+
rndr->cb.blockhtml(ob, &work, rndr->opaque);
|
1796
1798
|
|
1797
1799
|
return i;
|
1798
1800
|
}
|
@@ -1828,8 +1830,8 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
|
|
1828
1830
|
cell_end--;
|
1829
1831
|
|
1830
1832
|
parse_inline(cell_work, rndr, data + cell_start, 1 + cell_end - cell_start);
|
1831
|
-
if (rndr->
|
1832
|
-
rndr->
|
1833
|
+
if (rndr->cb.table_cell)
|
1834
|
+
rndr->cb.table_cell(row_work, cell_work, col_data ? col_data[col] : 0, rndr->opaque);
|
1833
1835
|
|
1834
1836
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
1835
1837
|
i++;
|
@@ -1837,12 +1839,12 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
|
|
1837
1839
|
|
1838
1840
|
for (; col < columns; ++col) {
|
1839
1841
|
struct buf empty_cell = {0, 0, 0, 0, 0};
|
1840
|
-
if (rndr->
|
1841
|
-
rndr->
|
1842
|
+
if (rndr->cb.table_cell)
|
1843
|
+
rndr->cb.table_cell(row_work, &empty_cell, col_data ? col_data[col] : 0, rndr->opaque);
|
1842
1844
|
}
|
1843
1845
|
|
1844
|
-
if (rndr->
|
1845
|
-
rndr->
|
1846
|
+
if (rndr->cb.table_row)
|
1847
|
+
rndr->cb.table_row(ob, row_work, rndr->opaque);
|
1846
1848
|
|
1847
1849
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
1848
1850
|
}
|
@@ -1956,8 +1958,8 @@ parse_table(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1956
1958
|
i++;
|
1957
1959
|
}
|
1958
1960
|
|
1959
|
-
if (rndr->
|
1960
|
-
rndr->
|
1961
|
+
if (rndr->cb.table)
|
1962
|
+
rndr->cb.table(ob, header_work, body_work, rndr->opaque);
|
1961
1963
|
}
|
1962
1964
|
|
1963
1965
|
free(col_data);
|
@@ -1985,7 +1987,7 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1985
1987
|
if (is_atxheader(rndr, txt_data, end))
|
1986
1988
|
beg += parse_atxheader(ob, rndr, txt_data, end);
|
1987
1989
|
|
1988
|
-
else if (data[beg] == '<' && rndr->
|
1990
|
+
else if (data[beg] == '<' && rndr->cb.blockhtml &&
|
1989
1991
|
(i = parse_htmlblock(ob, rndr, txt_data, end, 1)) != 0)
|
1990
1992
|
beg += i;
|
1991
1993
|
|
@@ -1993,8 +1995,8 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
|
|
1993
1995
|
beg += i;
|
1994
1996
|
|
1995
1997
|
else if (is_hrule(txt_data, end)) {
|
1996
|
-
if (rndr->
|
1997
|
-
rndr->
|
1998
|
+
if (rndr->cb.hrule)
|
1999
|
+
rndr->cb.hrule(ob, rndr->opaque);
|
1998
2000
|
|
1999
2001
|
while (beg < size && data[beg] != '\n')
|
2000
2002
|
beg++;
|
@@ -2167,14 +2169,21 @@ static void expand_tabs(struct buf *ob, const char *line, size_t size)
|
|
2167
2169
|
|
2168
2170
|
/* markdown • parses the input buffer and renders it into the output buffer */
|
2169
2171
|
void
|
2170
|
-
sd_markdown(struct buf *ob,
|
2172
|
+
sd_markdown(struct buf *ob,
|
2173
|
+
const struct buf *ib,
|
2174
|
+
unsigned int extensions,
|
2175
|
+
const struct sd_callbacks *callbacks,
|
2176
|
+
void *opaque) {
|
2177
|
+
|
2178
|
+
static const float MARKDOWN_GROW_FACTOR = 1.4f;
|
2179
|
+
|
2171
2180
|
struct link_ref *lr;
|
2172
2181
|
struct buf *text;
|
2173
2182
|
size_t i, beg, end;
|
2174
2183
|
struct render rndr;
|
2175
2184
|
|
2176
2185
|
/* filling the render structure */
|
2177
|
-
if (!
|
2186
|
+
if (!callbacks)
|
2178
2187
|
return;
|
2179
2188
|
|
2180
2189
|
text = bufnew(64);
|
@@ -2184,28 +2193,30 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
|
|
2184
2193
|
/* Preallocate enough space for our buffer to avoid expanding while copying */
|
2185
2194
|
bufgrow(text, ib->size);
|
2186
2195
|
|
2187
|
-
memcpy(&rndr.
|
2196
|
+
memcpy(&rndr.cb, callbacks, sizeof(struct sd_callbacks));
|
2188
2197
|
arr_init(&rndr.refs, sizeof (struct link_ref));
|
2189
2198
|
parr_init(&rndr.work_bufs[BUFFER_BLOCK]);
|
2190
2199
|
parr_init(&rndr.work_bufs[BUFFER_SPAN]);
|
2191
2200
|
|
2192
|
-
for (i = 0; i < 256; i++)
|
2193
|
-
rndr.active_char[i] = 0;
|
2201
|
+
/* for (i = 0; i < 256; i++)
|
2202
|
+
rndr.active_char[i] = 0; */
|
2194
2203
|
|
2195
|
-
|
2204
|
+
memset(rndr.active_char, 0x0, 256);
|
2205
|
+
|
2206
|
+
if (rndr.cb.emphasis || rndr.cb.double_emphasis || rndr.cb.triple_emphasis) {
|
2196
2207
|
rndr.active_char['*'] = MD_CHAR_EMPHASIS;
|
2197
2208
|
rndr.active_char['_'] = MD_CHAR_EMPHASIS;
|
2198
2209
|
if (extensions & MKDEXT_STRIKETHROUGH)
|
2199
2210
|
rndr.active_char['~'] = MD_CHAR_EMPHASIS;
|
2200
2211
|
}
|
2201
2212
|
|
2202
|
-
if (rndr.
|
2213
|
+
if (rndr.cb.codespan)
|
2203
2214
|
rndr.active_char['`'] = MD_CHAR_CODESPAN;
|
2204
2215
|
|
2205
|
-
if (rndr.
|
2216
|
+
if (rndr.cb.linebreak)
|
2206
2217
|
rndr.active_char['\n'] = MD_CHAR_LINEBREAK;
|
2207
2218
|
|
2208
|
-
if (rndr.
|
2219
|
+
if (rndr.cb.image || rndr.cb.link)
|
2209
2220
|
rndr.active_char['['] = MD_CHAR_LINK;
|
2210
2221
|
|
2211
2222
|
rndr.active_char['<'] = MD_CHAR_LANGLE;
|
@@ -2223,6 +2234,7 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
|
|
2223
2234
|
|
2224
2235
|
/* Extension data */
|
2225
2236
|
rndr.ext_flags = extensions;
|
2237
|
+
rndr.opaque = opaque;
|
2226
2238
|
rndr.max_nesting = 16;
|
2227
2239
|
|
2228
2240
|
/* first pass: looking for references, copying everything else */
|
@@ -2253,9 +2265,12 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
|
|
2253
2265
|
if (rndr.refs.size)
|
2254
2266
|
qsort(rndr.refs.base, rndr.refs.size, rndr.refs.unit, cmp_link_ref_sort);
|
2255
2267
|
|
2268
|
+
/* pre-grow the output buffer to minimize allocations */
|
2269
|
+
bufgrow(ob, text->size * MARKDOWN_GROW_FACTOR);
|
2270
|
+
|
2256
2271
|
/* second pass: actual rendering */
|
2257
|
-
if (rndr.
|
2258
|
-
rndr.
|
2272
|
+
if (rndr.cb.doc_header)
|
2273
|
+
rndr.cb.doc_header(ob, rndr.opaque);
|
2259
2274
|
|
2260
2275
|
if (text->size) {
|
2261
2276
|
/* adding a final newline if not already present */
|
@@ -2265,8 +2280,8 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
|
|
2265
2280
|
parse_block(ob, &rndr, text->data, text->size);
|
2266
2281
|
}
|
2267
2282
|
|
2268
|
-
if (rndr.
|
2269
|
-
rndr.
|
2283
|
+
if (rndr.cb.doc_footer)
|
2284
|
+
rndr.cb.doc_footer(ob, rndr.opaque);
|
2270
2285
|
|
2271
2286
|
/* clean-up */
|
2272
2287
|
bufrelease(text);
|
data/ext/redcarpet/markdown.h
CHANGED
@@ -31,7 +31,7 @@
|
|
31
31
|
* TYPE DEFINITIONS *
|
32
32
|
********************/
|
33
33
|
|
34
|
-
/* mkd_autolink
|
34
|
+
/* mkd_autolink - type of autolink */
|
35
35
|
enum mkd_autolink {
|
36
36
|
MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
|
37
37
|
MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */
|
@@ -49,8 +49,8 @@ enum mkd_extensions {
|
|
49
49
|
MKDEXT_SUPERSCRIPT = (1 << 7),
|
50
50
|
};
|
51
51
|
|
52
|
-
/*
|
53
|
-
struct
|
52
|
+
/* sd_callbacks - functions for rendering parsed data */
|
53
|
+
struct sd_callbacks {
|
54
54
|
/* block level callbacks - NULL skips the block */
|
55
55
|
void (*blockcode)(struct buf *ob, struct buf *text, struct buf *lang, void *opaque);
|
56
56
|
void (*blockquote)(struct buf *ob, struct buf *text, void *opaque);
|
@@ -85,9 +85,6 @@ struct mkd_renderer {
|
|
85
85
|
/* header and footer */
|
86
86
|
void (*doc_header)(struct buf *ob, void *opaque);
|
87
87
|
void (*doc_footer)(struct buf *ob, void *opaque);
|
88
|
-
|
89
|
-
/* user data */
|
90
|
-
void *opaque;
|
91
88
|
};
|
92
89
|
|
93
90
|
/*********
|
@@ -108,7 +105,7 @@ struct mkd_renderer {
|
|
108
105
|
|
109
106
|
/* sd_markdown * parses the input buffer and renders it into the output buffer */
|
110
107
|
extern void
|
111
|
-
sd_markdown(struct buf *ob, struct buf *ib, const struct
|
108
|
+
sd_markdown(struct buf *ob, const struct buf *ib, unsigned int extensions, const struct sd_callbacks *rndr, void *opaque);
|
112
109
|
|
113
110
|
/* sd_version * returns the library version as major.minor.rev */
|
114
111
|
extern void
|
data/ext/redcarpet/rc_markdown.c
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2011, Vicent Marti
|
3
|
+
*
|
4
|
+
* Permission to use, copy, modify, and distribute this software for any
|
5
|
+
* purpose with or without fee is hereby granted, provided that the above
|
6
|
+
* copyright notice and this permission notice appear in all copies.
|
7
|
+
*
|
8
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
9
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
10
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
11
|
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
12
|
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
13
|
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
14
|
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
15
|
+
*/
|
16
|
+
#include "redcarpet.h"
|
13
17
|
|
14
18
|
VALUE rb_mRedcarpet;
|
15
19
|
VALUE rb_cMarkdown;
|
@@ -54,7 +58,7 @@ static VALUE rb_redcarpet_md_render_with(VALUE self, VALUE rb_rndr, VALUE text)
|
|
54
58
|
{
|
55
59
|
VALUE result;
|
56
60
|
|
57
|
-
struct
|
61
|
+
struct rb_redcarpet_rndr *rndr;
|
58
62
|
struct buf input_buf, *output_buf;
|
59
63
|
unsigned int enabled_extensions = 0;
|
60
64
|
|
@@ -66,17 +70,18 @@ static VALUE rb_redcarpet_md_render_with(VALUE self, VALUE rb_rndr, VALUE text)
|
|
66
70
|
if (rb_respond_to(rb_rndr, rb_intern("preprocess")))
|
67
71
|
text = rb_funcall(rb_rndr, rb_intern("preprocess"), 1, text);
|
68
72
|
|
73
|
+
Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, rndr);
|
74
|
+
|
75
|
+
/* initialize buffers */
|
69
76
|
memset(&input_buf, 0x0, sizeof(struct buf));
|
70
77
|
input_buf.data = RSTRING_PTR(text);
|
71
78
|
input_buf.size = RSTRING_LEN(text);
|
72
79
|
|
73
80
|
output_buf = bufnew(128);
|
74
|
-
bufgrow(output_buf, RSTRING_LEN(text) * 1.4f);
|
75
|
-
|
76
|
-
Data_Get_Struct(rb_rndr, struct mkd_renderer, renderer);
|
77
81
|
|
82
|
+
/* render the magic */
|
78
83
|
rb_redcarpet_md_flags(self, &enabled_extensions);
|
79
|
-
sd_markdown(output_buf, &input_buf,
|
84
|
+
sd_markdown(output_buf, &input_buf, enabled_extensions, &rndr->callbacks, &rndr->options);
|
80
85
|
result = rb_str_new(output_buf->data, output_buf->size);
|
81
86
|
rb_enc_copy(result, text);
|
82
87
|
|
@@ -93,8 +98,6 @@ static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
|
|
93
98
|
return rb_redcarpet_md_render_with(self, rb_iv_get(self, "@renderer"), text);
|
94
99
|
}
|
95
100
|
|
96
|
-
extern void Init_redcarpet_rndr();
|
97
|
-
|
98
101
|
void Init_redcarpet()
|
99
102
|
{
|
100
103
|
rb_mRedcarpet = rb_define_module("Redcarpet");
|
data/ext/redcarpet/rc_render.c
CHANGED
@@ -14,23 +14,11 @@
|
|
14
14
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
15
15
|
*/
|
16
16
|
|
17
|
-
#
|
18
|
-
|
19
|
-
#include <ruby.h>
|
20
|
-
#include "markdown.h"
|
21
|
-
#include "html.h"
|
22
|
-
|
23
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
24
|
-
#include <ruby/encoding.h>
|
25
|
-
#else
|
26
|
-
#define rb_enc_copy(dst, src)
|
27
|
-
#endif
|
28
|
-
|
29
|
-
#define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
|
17
|
+
#include "redcarpet.h"
|
30
18
|
|
31
19
|
#define SPAN_CALLBACK(method_name, ...) {\
|
32
|
-
struct
|
33
|
-
VALUE ret = rb_funcall(
|
20
|
+
struct redcarpet_renderopt *opt = opaque;\
|
21
|
+
VALUE ret = rb_funcall(opt->self, rb_intern(method_name), __VA_ARGS__);\
|
34
22
|
if (NIL_P(ret)) return 0;\
|
35
23
|
Check_Type(ret, T_STRING);\
|
36
24
|
bufput(ob, RSTRING_PTR(ret), RSTRING_LEN(ret));\
|
@@ -38,8 +26,8 @@
|
|
38
26
|
}
|
39
27
|
|
40
28
|
#define BLOCK_CALLBACK(method_name, ...) {\
|
41
|
-
struct
|
42
|
-
VALUE ret = rb_funcall(
|
29
|
+
struct redcarpet_renderopt *opt = opaque;\
|
30
|
+
VALUE ret = rb_funcall(opt->self, rb_intern(method_name), __VA_ARGS__);\
|
43
31
|
if (NIL_P(ret)) return;\
|
44
32
|
Check_Type(ret, T_STRING);\
|
45
33
|
bufput(ob, RSTRING_PTR(ret), RSTRING_LEN(ret));\
|
@@ -52,10 +40,6 @@ VALUE rb_cRenderHTML;
|
|
52
40
|
VALUE rb_cRenderHTML_TOC;
|
53
41
|
VALUE rb_mSmartyPants;
|
54
42
|
|
55
|
-
struct redcarpet_pload {
|
56
|
-
VALUE self;
|
57
|
-
};
|
58
|
-
|
59
43
|
static inline VALUE
|
60
44
|
buf2str(struct buf *text)
|
61
45
|
{
|
@@ -104,7 +88,8 @@ rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)
|
|
104
88
|
static void
|
105
89
|
rndr_listitem(struct buf *ob, struct buf *text, int flags, void *opaque)
|
106
90
|
{
|
107
|
-
BLOCK_CALLBACK("list_item",
|
91
|
+
BLOCK_CALLBACK("list_item", 2, buf2str(text),
|
92
|
+
(flags & MKD_LIST_ORDERED) ? CSTR2SYM("ordered") : CSTR2SYM("unordered"));
|
108
93
|
}
|
109
94
|
|
110
95
|
static void
|
@@ -251,7 +236,7 @@ rndr_doc_footer(struct buf *ob, void *opaque)
|
|
251
236
|
BLOCK_CALLBACK("doc_footer", 0);
|
252
237
|
}
|
253
238
|
|
254
|
-
static struct
|
239
|
+
static struct sd_callbacks rb_redcarpet_callbacks = {
|
255
240
|
rndr_blockcode,
|
256
241
|
rndr_blockquote,
|
257
242
|
rndr_raw_block,
|
@@ -281,8 +266,6 @@ static struct mkd_renderer rb_redcarpet_rndr = {
|
|
281
266
|
|
282
267
|
rndr_doc_header,
|
283
268
|
rndr_doc_footer,
|
284
|
-
|
285
|
-
NULL
|
286
269
|
};
|
287
270
|
|
288
271
|
static const char *rb_redcarpet_method_names[] = {
|
@@ -319,58 +302,51 @@ static const char *rb_redcarpet_method_names[] = {
|
|
319
302
|
|
320
303
|
static const size_t rb_redcarpet_method_count = sizeof(rb_redcarpet_method_names)/sizeof(char *);
|
321
304
|
|
322
|
-
static void rb_redcarpet_rbase_free(struct mkd_renderer *rndr)
|
323
|
-
{
|
324
|
-
xfree(rndr->opaque);
|
325
|
-
xfree(rndr);
|
326
|
-
}
|
327
|
-
|
328
305
|
static VALUE rb_redcarpet_rbase_alloc(VALUE klass)
|
329
306
|
{
|
330
|
-
struct
|
331
|
-
memset(rndr, 0x0, sizeof(struct
|
332
|
-
return Data_Wrap_Struct(klass, NULL,
|
307
|
+
struct rb_redcarpet_rndr *rndr = ALLOC(struct rb_redcarpet_rndr);
|
308
|
+
memset(rndr, 0x0, sizeof(struct rb_redcarpet_rndr));
|
309
|
+
return Data_Wrap_Struct(klass, NULL, NULL, rndr);
|
333
310
|
}
|
334
311
|
|
335
|
-
static void rb_redcarpet__overload(VALUE self)
|
312
|
+
static void rb_redcarpet__overload(VALUE self, VALUE base_class)
|
336
313
|
{
|
337
|
-
|
338
|
-
|
314
|
+
struct rb_redcarpet_rndr *rndr;
|
315
|
+
|
316
|
+
Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
|
317
|
+
rndr->options.self = self;
|
318
|
+
rndr->options.base_class = base_class;
|
339
319
|
|
340
|
-
|
341
|
-
|
320
|
+
if (rb_obj_class(self) == rb_cRenderBase)
|
321
|
+
rb_raise(rb_eRuntimeError,
|
322
|
+
"The Redcarpet::Render::Base class cannot be instantiated. "
|
323
|
+
"Create an inheriting class instead to implement a custom renderer.");
|
342
324
|
|
343
|
-
|
344
|
-
|
325
|
+
if (rb_obj_class(self) != base_class) {
|
326
|
+
void **source = (void **)&rb_redcarpet_callbacks;
|
327
|
+
void **dest = (void **)&rndr->callbacks;
|
328
|
+
size_t i;
|
345
329
|
|
346
|
-
|
347
|
-
|
348
|
-
|
330
|
+
for (i = 0; i < rb_redcarpet_method_count; ++i) {
|
331
|
+
if (rb_respond_to(self, rb_intern(rb_redcarpet_method_names[i])))
|
332
|
+
dest[i] = source[i];
|
333
|
+
}
|
349
334
|
}
|
350
335
|
}
|
351
336
|
|
352
337
|
static VALUE rb_redcarpet_rbase_init(VALUE self)
|
353
338
|
{
|
354
|
-
|
355
|
-
struct redcarpet_pload *payload;
|
356
|
-
|
357
|
-
Data_Get_Struct(self, struct mkd_renderer, rndr);
|
358
|
-
rb_redcarpet__overload(self);
|
359
|
-
|
360
|
-
payload = ALLOC(struct redcarpet_pload);
|
361
|
-
payload->self = self;
|
362
|
-
|
363
|
-
rndr->opaque = payload;
|
339
|
+
rb_redcarpet__overload(self, rb_cRenderBase);
|
364
340
|
return Qnil;
|
365
341
|
}
|
366
342
|
|
367
343
|
static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
|
368
344
|
{
|
369
|
-
struct
|
345
|
+
struct rb_redcarpet_rndr *rndr;
|
370
346
|
unsigned int render_flags = 0;
|
371
347
|
VALUE hash;
|
372
348
|
|
373
|
-
Data_Get_Struct(self, struct
|
349
|
+
Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
|
374
350
|
|
375
351
|
if (rb_scan_args(argc, argv, "01", &hash) == 1)
|
376
352
|
{
|
@@ -406,23 +382,19 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
|
|
406
382
|
render_flags |= HTML_USE_XHTML;
|
407
383
|
}
|
408
384
|
|
409
|
-
sdhtml_renderer(rndr,
|
410
|
-
|
411
|
-
if (rb_obj_class(self) != rb_cRenderHTML)
|
412
|
-
rb_redcarpet__overload(self);
|
385
|
+
sdhtml_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
|
386
|
+
rb_redcarpet__overload(self, rb_cRenderHTML);
|
413
387
|
|
414
388
|
return Qnil;
|
415
389
|
}
|
416
390
|
|
417
391
|
static VALUE rb_redcarpet_htmltoc_init(VALUE self)
|
418
392
|
{
|
419
|
-
struct
|
420
|
-
Data_Get_Struct(self, struct
|
393
|
+
struct rb_redcarpet_rndr *rndr;
|
394
|
+
Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
|
421
395
|
|
422
|
-
sdhtml_toc_renderer(rndr, (
|
423
|
-
|
424
|
-
if (rb_obj_class(self) != rb_cRenderHTML_TOC)
|
425
|
-
rb_redcarpet__overload(self);
|
396
|
+
sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html);
|
397
|
+
rb_redcarpet__overload(self, rb_cRenderHTML_TOC);
|
426
398
|
|
427
399
|
return Qnil;
|
428
400
|
}
|
@@ -449,7 +421,6 @@ static VALUE rb_redcarpet_smartypants_render(VALUE self, VALUE text)
|
|
449
421
|
return result;
|
450
422
|
}
|
451
423
|
|
452
|
-
|
453
424
|
void Init_redcarpet_rndr()
|
454
425
|
{
|
455
426
|
rb_mRender = rb_define_module_under(rb_mRedcarpet, "Render");
|
@@ -465,5 +436,5 @@ void Init_redcarpet_rndr()
|
|
465
436
|
rb_define_method(rb_cRenderHTML_TOC, "initialize", rb_redcarpet_htmltoc_init, 0);
|
466
437
|
|
467
438
|
rb_mSmartyPants = rb_define_module_under(rb_mRender, "SmartyPants");
|
468
|
-
|
439
|
+
rb_define_method(rb_mSmartyPants, "postprocess", rb_redcarpet_smartypants_render, 1);
|
469
440
|
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#ifndef __REDCARPET_H__
|
2
|
+
#define __REDCARPET_H__
|
3
|
+
|
4
|
+
#define RSTRING_NOT_MODIFIED
|
5
|
+
#include "ruby.h"
|
6
|
+
#include <stdio.h>
|
7
|
+
|
8
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
9
|
+
#include <ruby/encoding.h>
|
10
|
+
#else
|
11
|
+
#define rb_enc_copy(dst, src)
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#include "markdown.h"
|
15
|
+
#include "html.h"
|
16
|
+
|
17
|
+
#define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
|
18
|
+
|
19
|
+
extern void Init_redcarpet_rndr();
|
20
|
+
|
21
|
+
struct redcarpet_renderopt {
|
22
|
+
struct html_renderopt html;
|
23
|
+
VALUE self;
|
24
|
+
VALUE base_class;
|
25
|
+
};
|
26
|
+
|
27
|
+
struct rb_redcarpet_rndr {
|
28
|
+
struct sd_callbacks callbacks;
|
29
|
+
struct redcarpet_renderopt options;
|
30
|
+
};
|
31
|
+
|
32
|
+
#endif
|
data/lib/redcarpet.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Redcarpet
|
2
|
+
module Render
|
3
|
+
class ManPage < Base
|
4
|
+
|
5
|
+
def normal_text(text)
|
6
|
+
text.gsub('-', '\\-').strip
|
7
|
+
end
|
8
|
+
|
9
|
+
def block_code(code, language)
|
10
|
+
"\n.nf\n#{normal_text(code)}\n.fi\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
def codespan(code)
|
14
|
+
block_code(code, nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
def header(title, level)
|
18
|
+
case level
|
19
|
+
when 1
|
20
|
+
"\n.TH #{title}\n"
|
21
|
+
|
22
|
+
when 2
|
23
|
+
"\n.SH #{title}\n"
|
24
|
+
|
25
|
+
when 3
|
26
|
+
"\n.SS #{title}\n"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def double_emphasis(text)
|
31
|
+
"\\fB#{text}\\fP"
|
32
|
+
end
|
33
|
+
|
34
|
+
def emphasis(text)
|
35
|
+
"\\fI#{text}\\fP"
|
36
|
+
end
|
37
|
+
|
38
|
+
def linebreak
|
39
|
+
"\n.LP\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
def paragraph(text)
|
43
|
+
"\n.TP\n#{text}\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
def list(content, list_type)
|
47
|
+
case list_type
|
48
|
+
when :ordered
|
49
|
+
"\n\n.nr step 0 1\n#{content}\n"
|
50
|
+
when :unordered
|
51
|
+
"\n.\n#{content}\n"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def list_item(content, list_type)
|
56
|
+
case list_type
|
57
|
+
when :ordered
|
58
|
+
".IP \\n+[step]\n#{content.strip}\n"
|
59
|
+
when :unordered
|
60
|
+
".IP \\[bu] 2 \n#{content.strip}\n"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/redcarpet.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'redcarpet'
|
3
|
-
s.version = '2.0.
|
3
|
+
s.version = '2.0.0b3'
|
4
4
|
s.summary = "Markdown that smells nice"
|
5
5
|
s.description = 'A fast, safe and extensible Markdown to (X)HTML parser'
|
6
|
-
s.date = '2011-08-
|
6
|
+
s.date = '2011-08-09'
|
7
7
|
s.email = 'vicent@github.com'
|
8
8
|
s.homepage = 'http://github.com/tanoku/redcarpet'
|
9
9
|
s.authors = ["Natacha Porté", "Vicent Martí"]
|
@@ -27,7 +27,9 @@ Gem::Specification.new do |s|
|
|
27
27
|
ext/redcarpet/markdown.h
|
28
28
|
ext/redcarpet/rc_markdown.c
|
29
29
|
ext/redcarpet/rc_render.c
|
30
|
+
ext/redcarpet/redcarpet.h
|
30
31
|
lib/redcarpet.rb
|
32
|
+
lib/redcarpet/render_man.rb
|
31
33
|
redcarpet.gemspec
|
32
34
|
sundown
|
33
35
|
test/redcarpet_test.rb
|
@@ -38,4 +40,5 @@ Gem::Specification.new do |s|
|
|
38
40
|
s.extensions = ["ext/redcarpet/extconf.rb"]
|
39
41
|
s.executables = ["redcarpet"]
|
40
42
|
s.require_paths = ["lib"]
|
43
|
+
s.add_development_dependency "rake-compiler"
|
41
44
|
end
|
data/test/redcarpet_test.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# coding: UTF-8
|
1
2
|
rootdir = File.dirname(File.dirname(__FILE__))
|
2
3
|
$LOAD_PATH.unshift "#{rootdir}/lib"
|
3
4
|
|
4
5
|
require 'test/unit'
|
5
6
|
require 'redcarpet'
|
7
|
+
require 'redcarpet/render_man'
|
6
8
|
require 'nokogiri'
|
7
9
|
|
8
10
|
def html_equal(html_a, html_b)
|
@@ -46,6 +48,12 @@ class SmartyPantsTest < Test::Unit::TestCase
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
51
|
+
class SmartyHTMLTests < SmartyPantsTest
|
52
|
+
def setup
|
53
|
+
@pants = Redcarpet::Markdown.new Redcarpet::Render::SmartyHTML
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
49
57
|
class HTMLRenderTest < Test::Unit::TestCase
|
50
58
|
def setup
|
51
59
|
@markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
|
metadata
CHANGED
@@ -1,35 +1,37 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: redcarpet
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0b3
|
5
5
|
prerelease: 5
|
6
|
-
segments:
|
7
|
-
- 2
|
8
|
-
- 0
|
9
|
-
- 0
|
10
|
-
- b
|
11
|
-
version: 2.0.0b
|
12
6
|
platform: ruby
|
13
|
-
authors:
|
14
|
-
-
|
15
|
-
-
|
7
|
+
authors:
|
8
|
+
- Natacha Porté
|
9
|
+
- Vicent Martí
|
16
10
|
autorequire:
|
17
11
|
bindir: bin
|
18
12
|
cert_chain: []
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
date: 2011-08-09 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake-compiler
|
17
|
+
requirement: &70234078705880 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70234078705880
|
24
26
|
description: A fast, safe and extensible Markdown to (X)HTML parser
|
25
27
|
email: vicent@github.com
|
26
|
-
executables:
|
28
|
+
executables:
|
27
29
|
- redcarpet
|
28
|
-
extensions:
|
30
|
+
extensions:
|
29
31
|
- ext/redcarpet/extconf.rb
|
30
|
-
extra_rdoc_files:
|
32
|
+
extra_rdoc_files:
|
31
33
|
- COPYING
|
32
|
-
files:
|
34
|
+
files:
|
33
35
|
- COPYING
|
34
36
|
- README.markdown
|
35
37
|
- Rakefile
|
@@ -48,44 +50,34 @@ files:
|
|
48
50
|
- ext/redcarpet/markdown.h
|
49
51
|
- ext/redcarpet/rc_markdown.c
|
50
52
|
- ext/redcarpet/rc_render.c
|
53
|
+
- ext/redcarpet/redcarpet.h
|
51
54
|
- lib/redcarpet.rb
|
55
|
+
- lib/redcarpet/render_man.rb
|
52
56
|
- redcarpet.gemspec
|
53
57
|
- test/redcarpet_test.rb
|
54
|
-
has_rdoc: true
|
55
58
|
homepage: http://github.com/tanoku/redcarpet
|
56
59
|
licenses: []
|
57
|
-
|
58
60
|
post_install_message:
|
59
61
|
rdoc_options: []
|
60
|
-
|
61
|
-
require_paths:
|
62
|
+
require_paths:
|
62
63
|
- lib
|
63
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
65
|
none: false
|
65
|
-
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
|
69
|
-
|
70
|
-
- 0
|
71
|
-
version: "0"
|
72
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
71
|
none: false
|
74
|
-
requirements:
|
75
|
-
- -
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
hash: 25
|
78
|
-
segments:
|
79
|
-
- 1
|
80
|
-
- 3
|
81
|
-
- 1
|
72
|
+
requirements:
|
73
|
+
- - ! '>'
|
74
|
+
- !ruby/object:Gem::Version
|
82
75
|
version: 1.3.1
|
83
76
|
requirements: []
|
84
|
-
|
85
77
|
rubyforge_project:
|
86
|
-
rubygems_version: 1.6
|
78
|
+
rubygems_version: 1.8.6
|
87
79
|
signing_key:
|
88
80
|
specification_version: 3
|
89
81
|
summary: Markdown that smells nice
|
90
|
-
test_files:
|
82
|
+
test_files:
|
91
83
|
- test/redcarpet_test.rb
|