redcarpet 1.3.3 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of redcarpet might be problematic. Click here for more details.
- data/ext/markdown.c +304 -32
- data/ext/markdown.h +35 -37
- data/ext/redcarpet.c +31 -18
- data/ext/xhtml.c +148 -75
- data/ext/xhtml.h +13 -13
- data/lib/redcarpet.rb +10 -1
- data/redcarpet.gemspec +2 -2
- data/test/redcarpet_test.rb +27 -0
- metadata +5 -5
data/ext/markdown.h
CHANGED
@@ -36,56 +36,50 @@ enum mkd_autolink {
|
|
36
36
|
MKDA_IMPLICIT_EMAIL /* e-mail link without mailto: */
|
37
37
|
};
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
struct mkd_renderopt {
|
44
|
-
void *opaque;
|
45
|
-
unsigned int flags;
|
46
|
-
};
|
47
|
-
|
48
|
-
struct mkd_parseropt {
|
49
|
-
unsigned int flags;
|
50
|
-
int recursion_depth;
|
39
|
+
enum mkd_extensions {
|
40
|
+
MKDEXT_LAX_EMPHASIS = (1 << 0),
|
41
|
+
MKDEXT_TABLES = (1 << 1),
|
42
|
+
MKDEXT_FENCED_CODE = (1 << 2),
|
51
43
|
};
|
52
44
|
|
53
45
|
/* mkd_renderer • functions for rendering parsed data */
|
54
46
|
struct mkd_renderer {
|
55
47
|
/* block level callbacks - NULL skips the block */
|
56
|
-
void (*blockcode)(struct buf *ob, struct buf *text,
|
57
|
-
void (*blockquote)(struct buf *ob, struct buf *text,
|
58
|
-
void (*blockhtml)(struct buf *ob, struct buf *text,
|
59
|
-
void (*header)(struct buf *ob, struct buf *text, int level,
|
60
|
-
void (*hrule)(struct buf *ob,
|
61
|
-
void (*list)(struct buf *ob, struct buf *text, int flags,
|
62
|
-
void (*listitem)(struct buf *ob, struct buf *text, int flags,
|
63
|
-
void (*paragraph)(struct buf *ob, struct buf *text,
|
48
|
+
void (*blockcode)(struct buf *ob, struct buf *text, void *opaque);
|
49
|
+
void (*blockquote)(struct buf *ob, struct buf *text, void *opaque);
|
50
|
+
void (*blockhtml)(struct buf *ob, struct buf *text, void *opaque);
|
51
|
+
void (*header)(struct buf *ob, struct buf *text, int level, void *opaque);
|
52
|
+
void (*hrule)(struct buf *ob, void *opaque);
|
53
|
+
void (*list)(struct buf *ob, struct buf *text, int flags, void *opaque);
|
54
|
+
void (*listitem)(struct buf *ob, struct buf *text, int flags, void *opaque);
|
55
|
+
void (*paragraph)(struct buf *ob, struct buf *text, void *opaque);
|
56
|
+
void (*table)(struct buf *ob, struct buf *header, struct buf *body, void *opaque);
|
57
|
+
void (*table_row)(struct buf *ob, struct buf *text, void *opaque);
|
58
|
+
void (*table_cell)(struct buf *ob, struct buf *text, int flags, void *opaque);
|
59
|
+
|
64
60
|
|
65
61
|
/* span level callbacks - NULL or return 0 prints the span verbatim */
|
66
|
-
int (*autolink)(struct buf *ob, struct buf *link, enum mkd_autolink type,
|
67
|
-
int (*codespan)(struct buf *ob, struct buf *text,
|
68
|
-
int (*double_emphasis)(struct buf *ob, struct buf *text, char c,
|
69
|
-
int (*emphasis)(struct buf *ob, struct buf *text, char c,
|
70
|
-
int (*image)(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt,
|
71
|
-
int (*linebreak)(struct buf *ob,
|
72
|
-
int (*link)(struct buf *ob, struct buf *link, struct buf *title, struct buf *content,
|
73
|
-
int (*raw_html_tag)(struct buf *ob, struct buf *tag,
|
74
|
-
int (*triple_emphasis)(struct buf *ob, struct buf *text, char c,
|
62
|
+
int (*autolink)(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque);
|
63
|
+
int (*codespan)(struct buf *ob, struct buf *text, void *opaque);
|
64
|
+
int (*double_emphasis)(struct buf *ob, struct buf *text, char c, void *opaque);
|
65
|
+
int (*emphasis)(struct buf *ob, struct buf *text, char c,void *opaque);
|
66
|
+
int (*image)(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque);
|
67
|
+
int (*linebreak)(struct buf *ob, void *opaque);
|
68
|
+
int (*link)(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque);
|
69
|
+
int (*raw_html_tag)(struct buf *ob, struct buf *tag, void *opaque);
|
70
|
+
int (*triple_emphasis)(struct buf *ob, struct buf *text, char c, void *opaque);
|
75
71
|
|
76
72
|
/* low level callbacks - NULL copies input directly into the output */
|
77
|
-
void (*entity)(struct buf *ob, struct buf *entity,
|
78
|
-
void (*normal_text)(struct buf *ob, struct buf *text,
|
73
|
+
void (*entity)(struct buf *ob, struct buf *entity, void *opaque);
|
74
|
+
void (*normal_text)(struct buf *ob, struct buf *text, void *opaque);
|
79
75
|
|
80
76
|
/* header and footer */
|
81
|
-
void (*doc_header)(struct buf *ob,
|
82
|
-
void (*doc_footer)(struct buf *ob,
|
77
|
+
void (*doc_header)(struct buf *ob, void *opaque);
|
78
|
+
void (*doc_footer)(struct buf *ob, void *opaque);
|
83
79
|
|
84
80
|
/* renderer data */
|
85
81
|
const char *emph_chars; /* chars that trigger emphasis rendering */
|
86
|
-
|
87
|
-
struct mkd_renderopt render_options;
|
88
|
-
struct mkd_parseropt parser_options;
|
82
|
+
void *opaque;
|
89
83
|
};
|
90
84
|
|
91
85
|
/*********
|
@@ -96,13 +90,17 @@ struct mkd_renderer {
|
|
96
90
|
#define MKD_LIST_ORDERED 1
|
97
91
|
#define MKD_LI_BLOCK 2 /* <li> containing block data */
|
98
92
|
|
93
|
+
#define MKD_TABLE_ALIGN_L (1 << 0)
|
94
|
+
#define MKD_TABLE_ALIGN_R (1 << 1)
|
95
|
+
#define MKD_TABLE_ALIGN_CENTER (MKD_TABLE_ALIGN_L | MKD_TABLE_ALIGN_R)
|
96
|
+
|
99
97
|
/**********************
|
100
98
|
* EXPORTED FUNCTIONS *
|
101
99
|
**********************/
|
102
100
|
|
103
101
|
/* markdown • parses the input buffer and renders it into the output buffer */
|
104
102
|
void
|
105
|
-
markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndr);
|
103
|
+
markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndr, unsigned int extensions);
|
106
104
|
|
107
105
|
#endif
|
108
106
|
|
data/ext/redcarpet.c
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
#include "markdown.h"
|
5
5
|
#include "xhtml.h"
|
6
6
|
|
7
|
-
#define REDCARPET_RECURSION_LIMIT 16
|
8
|
-
|
9
7
|
typedef enum
|
10
8
|
{
|
11
9
|
REDCARPET_RENDER_XHTML,
|
@@ -14,41 +12,46 @@ typedef enum
|
|
14
12
|
|
15
13
|
static VALUE rb_cRedcarpet;
|
16
14
|
|
17
|
-
static void
|
15
|
+
static void rb_redcarpet__get_flags(VALUE ruby_obj,
|
16
|
+
unsigned int *enabled_extensions_p,
|
17
|
+
unsigned int *render_flags_p)
|
18
18
|
{
|
19
|
-
unsigned int render_flags =
|
20
|
-
unsigned int
|
19
|
+
unsigned int render_flags = XHTML_EXPAND_TABS;
|
20
|
+
unsigned int extensions = 0;
|
21
21
|
|
22
22
|
/* smart */
|
23
23
|
if (rb_funcall(ruby_obj, rb_intern("smart"), 0) == Qtrue)
|
24
|
-
render_flags |=
|
24
|
+
render_flags |= XHTML_SMARTYPANTS;
|
25
25
|
|
26
26
|
/* filter_html */
|
27
27
|
if (rb_funcall(ruby_obj, rb_intern("filter_html"), 0) == Qtrue)
|
28
|
-
render_flags |=
|
28
|
+
render_flags |= XHTML_SKIP_HTML;
|
29
29
|
|
30
30
|
/* no_image */
|
31
31
|
if (rb_funcall(ruby_obj, rb_intern("no_image"), 0) == Qtrue)
|
32
|
-
render_flags |=
|
32
|
+
render_flags |= XHTML_SKIP_IMAGES;
|
33
33
|
|
34
34
|
/* no_links */
|
35
35
|
if (rb_funcall(ruby_obj, rb_intern("no_links"), 0) == Qtrue)
|
36
|
-
render_flags |=
|
36
|
+
render_flags |= XHTML_SKIP_LINKS;
|
37
37
|
|
38
38
|
/* filter_style */
|
39
39
|
if (rb_funcall(ruby_obj, rb_intern("filter_styles"), 0) == Qtrue)
|
40
|
-
render_flags |=
|
40
|
+
render_flags |= XHTML_SKIP_STYLE;
|
41
41
|
|
42
42
|
/* autolink */
|
43
43
|
if (rb_funcall(ruby_obj, rb_intern("autolink"), 0) == Qtrue)
|
44
|
-
render_flags |=
|
44
|
+
render_flags |= XHTML_AUTOLINK;
|
45
45
|
|
46
46
|
/* safelink */
|
47
47
|
if (rb_funcall(ruby_obj, rb_intern("safelink"), 0) == Qtrue)
|
48
|
-
render_flags |=
|
48
|
+
render_flags |= XHTML_SAFELINK;
|
49
49
|
|
50
50
|
if (rb_funcall(ruby_obj, rb_intern("generate_toc"), 0) == Qtrue)
|
51
|
-
render_flags |=
|
51
|
+
render_flags |= XHTML_TOC;
|
52
|
+
|
53
|
+
if (rb_funcall(ruby_obj, rb_intern("no_strikethrough"), 0) == Qtrue)
|
54
|
+
render_flags |= XHTML_SKIP_STRIKETHROUGH;
|
52
55
|
|
53
56
|
/* parser - strict
|
54
57
|
* This is fucking stupid; what the 'strict' flag actually
|
@@ -56,9 +59,16 @@ static void rb_redcarpet__setup_xhtml(struct mkd_renderer *rnd, VALUE ruby_obj)
|
|
56
59
|
* named flag internally, even if outside we have retarded
|
57
60
|
* naming because of compat. issues .*/
|
58
61
|
if (rb_funcall(ruby_obj, rb_intern("strict"), 0) == Qtrue)
|
59
|
-
|
62
|
+
extensions |= MKDEXT_LAX_EMPHASIS;
|
63
|
+
|
64
|
+
if (rb_funcall(ruby_obj, rb_intern("no_tables"), 0) != Qtrue)
|
65
|
+
extensions |= MKDEXT_TABLES;
|
60
66
|
|
61
|
-
|
67
|
+
if (rb_funcall(ruby_obj, rb_intern("no_fencedcode"), 0) != Qtrue)
|
68
|
+
extensions |= MKDEXT_FENCED_CODE;
|
69
|
+
|
70
|
+
*enabled_extensions_p = extensions;
|
71
|
+
*render_flags_p = render_flags;
|
62
72
|
}
|
63
73
|
|
64
74
|
static VALUE rb_redcarpet__render(VALUE self, RendererType render_type)
|
@@ -68,6 +78,7 @@ static VALUE rb_redcarpet__render(VALUE self, RendererType render_type)
|
|
68
78
|
|
69
79
|
struct buf input_buf, *output_buf;
|
70
80
|
struct mkd_renderer renderer;
|
81
|
+
unsigned int enabled_extensions, render_flags;
|
71
82
|
|
72
83
|
Check_Type(text, T_STRING);
|
73
84
|
|
@@ -78,20 +89,22 @@ static VALUE rb_redcarpet__render(VALUE self, RendererType render_type)
|
|
78
89
|
output_buf = bufnew(128);
|
79
90
|
bufgrow(output_buf, RSTRING_LEN(text) * 1.2f);
|
80
91
|
|
92
|
+
rb_redcarpet__get_flags(self, &enabled_extensions, &render_flags);
|
93
|
+
|
81
94
|
switch (render_type) {
|
82
95
|
case REDCARPET_RENDER_XHTML:
|
83
|
-
|
96
|
+
init_xhtml_renderer(&renderer, render_flags);
|
84
97
|
break;
|
85
98
|
|
86
99
|
case REDCARPET_RENDER_TOC:
|
87
|
-
init_toc_renderer(&renderer
|
100
|
+
init_toc_renderer(&renderer);
|
88
101
|
break;
|
89
102
|
|
90
103
|
default:
|
91
104
|
return Qnil;
|
92
105
|
}
|
93
106
|
|
94
|
-
markdown(output_buf, &input_buf, &renderer);
|
107
|
+
markdown(output_buf, &input_buf, &renderer, enabled_extensions);
|
95
108
|
|
96
109
|
result = rb_str_new(output_buf->data, output_buf->size);
|
97
110
|
bufrelease(output_buf);
|
data/ext/xhtml.c
CHANGED
@@ -22,9 +22,13 @@
|
|
22
22
|
#include <stdlib.h>
|
23
23
|
#include <stdio.h>
|
24
24
|
|
25
|
-
struct
|
26
|
-
|
27
|
-
|
25
|
+
struct xhtml_renderopt {
|
26
|
+
struct {
|
27
|
+
int header_count;
|
28
|
+
int current_level;
|
29
|
+
} toc_data;
|
30
|
+
|
31
|
+
unsigned int flags;
|
28
32
|
};
|
29
33
|
|
30
34
|
static int
|
@@ -114,12 +118,14 @@ rndr_autolink2(struct buf *ob, const char *link, size_t link_size, enum mkd_auto
|
|
114
118
|
}
|
115
119
|
|
116
120
|
static int
|
117
|
-
rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type,
|
121
|
+
rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque)
|
118
122
|
{
|
123
|
+
struct xhtml_renderopt *options = opaque;
|
124
|
+
|
119
125
|
if (!link || !link->size)
|
120
126
|
return 0;
|
121
127
|
|
122
|
-
if ((options->flags &
|
128
|
+
if ((options->flags & XHTML_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
|
123
129
|
return 0;
|
124
130
|
|
125
131
|
rndr_autolink2(ob, link->data, link->size, type);
|
@@ -127,7 +133,7 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, struct m
|
|
127
133
|
}
|
128
134
|
|
129
135
|
static void
|
130
|
-
rndr_blockcode(struct buf *ob, struct buf *text,
|
136
|
+
rndr_blockcode(struct buf *ob, struct buf *text, void *opaque)
|
131
137
|
{
|
132
138
|
if (ob->size) bufputc(ob, '\n');
|
133
139
|
BUFPUTSL(ob, "<pre><code>");
|
@@ -136,7 +142,7 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
|
|
136
142
|
}
|
137
143
|
|
138
144
|
static void
|
139
|
-
rndr_blockquote(struct buf *ob, struct buf *text,
|
145
|
+
rndr_blockquote(struct buf *ob, struct buf *text, void *opaque)
|
140
146
|
{
|
141
147
|
BUFPUTSL(ob, "<blockquote>\n");
|
142
148
|
if (text) bufput(ob, text->data, text->size);
|
@@ -144,7 +150,7 @@ rndr_blockquote(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
|
|
144
150
|
}
|
145
151
|
|
146
152
|
static int
|
147
|
-
rndr_codespan(struct buf *ob, struct buf *text,
|
153
|
+
rndr_codespan(struct buf *ob, struct buf *text, void *opaque)
|
148
154
|
{
|
149
155
|
BUFPUTSL(ob, "<code>");
|
150
156
|
if (text) lus_attr_escape(ob, text->data, text->size);
|
@@ -153,19 +159,33 @@ rndr_codespan(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
|
|
153
159
|
}
|
154
160
|
|
155
161
|
static int
|
156
|
-
rndr_double_emphasis(struct buf *ob, struct buf *text, char c,
|
162
|
+
rndr_double_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
|
157
163
|
{
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
164
|
+
struct xhtml_renderopt *options = opaque;
|
165
|
+
|
166
|
+
if (!text || !text->size)
|
167
|
+
return 0;
|
168
|
+
|
169
|
+
if (c == '~') {
|
170
|
+
if (options->flags & XHTML_SKIP_STRIKETHROUGH)
|
171
|
+
return 0;
|
172
|
+
|
173
|
+
BUFPUTSL(ob, "<span style=\"text-decoration:line-through;\">");
|
174
|
+
bufput(ob, text->data, text->size);
|
175
|
+
BUFPUTSL(ob, "</span>");
|
176
|
+
} else {
|
177
|
+
BUFPUTSL(ob, "<strong>");
|
178
|
+
bufput(ob, text->data, text->size);
|
179
|
+
BUFPUTSL(ob, "</strong>");
|
180
|
+
}
|
181
|
+
|
162
182
|
return 1;
|
163
183
|
}
|
164
184
|
|
165
185
|
static int
|
166
|
-
rndr_emphasis(struct buf *ob, struct buf *text, char c,
|
186
|
+
rndr_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
|
167
187
|
{
|
168
|
-
if (!text || !text->size) return 0;
|
188
|
+
if (!text || !text->size || c == '~') return 0;
|
169
189
|
BUFPUTSL(ob, "<em>");
|
170
190
|
if (text) bufput(ob, text->data, text->size);
|
171
191
|
BUFPUTSL(ob, "</em>");
|
@@ -173,14 +193,15 @@ rndr_emphasis(struct buf *ob, struct buf *text, char c, struct mkd_renderopt *op
|
|
173
193
|
}
|
174
194
|
|
175
195
|
static void
|
176
|
-
rndr_header(struct buf *ob, struct buf *text, int level,
|
196
|
+
rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)
|
177
197
|
{
|
198
|
+
struct xhtml_renderopt *options = opaque;
|
199
|
+
|
178
200
|
if (ob->size)
|
179
201
|
bufputc(ob, '\n');
|
180
202
|
|
181
|
-
if (options->flags &
|
182
|
-
|
183
|
-
bufprintf(ob, "<a name=\"toc_%d\"></a>", data->header_count++);
|
203
|
+
if (options->flags & XHTML_TOC) {
|
204
|
+
bufprintf(ob, "<a name=\"toc_%d\"></a>", options->toc_data.header_count++);
|
184
205
|
}
|
185
206
|
|
186
207
|
bufprintf(ob, "<h%d>", level);
|
@@ -189,9 +210,11 @@ rndr_header(struct buf *ob, struct buf *text, int level, struct mkd_renderopt *o
|
|
189
210
|
}
|
190
211
|
|
191
212
|
static int
|
192
|
-
rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content,
|
213
|
+
rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque)
|
193
214
|
{
|
194
|
-
|
215
|
+
struct xhtml_renderopt *options = opaque;
|
216
|
+
|
217
|
+
if ((options->flags & XHTML_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
|
195
218
|
return 0;
|
196
219
|
|
197
220
|
BUFPUTSL(ob, "<a href=\"");
|
@@ -206,7 +229,7 @@ rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *conte
|
|
206
229
|
}
|
207
230
|
|
208
231
|
static void
|
209
|
-
rndr_list(struct buf *ob, struct buf *text, int flags,
|
232
|
+
rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)
|
210
233
|
{
|
211
234
|
if (ob->size) bufputc(ob, '\n');
|
212
235
|
bufput(ob, flags & MKD_LIST_ORDERED ? "<ol>\n" : "<ul>\n", 5);
|
@@ -215,7 +238,7 @@ rndr_list(struct buf *ob, struct buf *text, int flags, struct mkd_renderopt *opt
|
|
215
238
|
}
|
216
239
|
|
217
240
|
static void
|
218
|
-
rndr_listitem(struct buf *ob, struct buf *text, int flags,
|
241
|
+
rndr_listitem(struct buf *ob, struct buf *text, int flags, void *opaque)
|
219
242
|
{
|
220
243
|
BUFPUTSL(ob, "<li>");
|
221
244
|
if (text) {
|
@@ -226,7 +249,7 @@ rndr_listitem(struct buf *ob, struct buf *text, int flags, struct mkd_renderopt
|
|
226
249
|
}
|
227
250
|
|
228
251
|
static void
|
229
|
-
rndr_paragraph(struct buf *ob, struct buf *text,
|
252
|
+
rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
|
230
253
|
{
|
231
254
|
size_t i = 0;
|
232
255
|
|
@@ -245,7 +268,7 @@ rndr_paragraph(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
|
|
245
268
|
}
|
246
269
|
|
247
270
|
static void
|
248
|
-
rndr_raw_block(struct buf *ob, struct buf *text,
|
271
|
+
rndr_raw_block(struct buf *ob, struct buf *text, void *opaque)
|
249
272
|
{
|
250
273
|
size_t org, sz;
|
251
274
|
if (!text) return;
|
@@ -260,7 +283,7 @@ rndr_raw_block(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
|
|
260
283
|
}
|
261
284
|
|
262
285
|
static int
|
263
|
-
rndr_triple_emphasis(struct buf *ob, struct buf *text, char c,
|
286
|
+
rndr_triple_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
|
264
287
|
{
|
265
288
|
if (!text || !text->size) return 0;
|
266
289
|
BUFPUTSL(ob, "<strong><em>");
|
@@ -275,14 +298,14 @@ rndr_triple_emphasis(struct buf *ob, struct buf *text, char c, struct mkd_render
|
|
275
298
|
**********************/
|
276
299
|
|
277
300
|
static void
|
278
|
-
rndr_hrule(struct buf *ob,
|
301
|
+
rndr_hrule(struct buf *ob, void *opaque)
|
279
302
|
{
|
280
303
|
if (ob->size) bufputc(ob, '\n');
|
281
304
|
BUFPUTSL(ob, "<hr />\n");
|
282
305
|
}
|
283
306
|
|
284
307
|
static int
|
285
|
-
rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt,
|
308
|
+
rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque)
|
286
309
|
{
|
287
310
|
if (!link || !link->size) return 0;
|
288
311
|
BUFPUTSL(ob, "<img src=\"");
|
@@ -298,27 +321,28 @@ rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt,
|
|
298
321
|
}
|
299
322
|
|
300
323
|
static int
|
301
|
-
rndr_linebreak(struct buf *ob,
|
324
|
+
rndr_linebreak(struct buf *ob, void *opaque)
|
302
325
|
{
|
303
326
|
BUFPUTSL(ob, "<br />\n");
|
304
327
|
return 1;
|
305
328
|
}
|
306
329
|
|
307
330
|
static int
|
308
|
-
rndr_raw_html(struct buf *ob, struct buf *text,
|
331
|
+
rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)
|
309
332
|
{
|
333
|
+
struct xhtml_renderopt *options = opaque;
|
310
334
|
int escape_html = 0;
|
311
335
|
|
312
|
-
if (options->flags &
|
336
|
+
if (options->flags & XHTML_SKIP_HTML)
|
313
337
|
escape_html = 1;
|
314
338
|
|
315
|
-
else if ((options->flags &
|
339
|
+
else if ((options->flags & XHTML_SKIP_STYLE) != 0 && is_html_tag(text, "<style>"))
|
316
340
|
escape_html = 1;
|
317
341
|
|
318
|
-
else if ((options->flags &
|
342
|
+
else if ((options->flags & XHTML_SKIP_LINKS) != 0 && is_html_tag(text, "<a>"))
|
319
343
|
escape_html = 1;
|
320
344
|
|
321
|
-
else if ((options->flags &
|
345
|
+
else if ((options->flags & XHTML_SKIP_IMAGES) != 0 && is_html_tag(text, "<img>"))
|
322
346
|
escape_html = 1;
|
323
347
|
|
324
348
|
|
@@ -330,6 +354,55 @@ rndr_raw_html(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
|
|
330
354
|
return 1;
|
331
355
|
}
|
332
356
|
|
357
|
+
static void
|
358
|
+
rndr_table(struct buf *ob, struct buf *header, struct buf *body, void *opaque)
|
359
|
+
{
|
360
|
+
if (ob->size) bufputc(ob, '\n');
|
361
|
+
BUFPUTSL(ob, "<table><thead>\n");
|
362
|
+
if (header)
|
363
|
+
bufput(ob, header->data, header->size);
|
364
|
+
BUFPUTSL(ob, "\n</thead><tbody>\n");
|
365
|
+
if (body)
|
366
|
+
bufput(ob, body->data, body->size);
|
367
|
+
BUFPUTSL(ob, "\n</tbody></table>");
|
368
|
+
}
|
369
|
+
|
370
|
+
static void
|
371
|
+
rndr_tablerow(struct buf *ob, struct buf *text, void *opaque)
|
372
|
+
{
|
373
|
+
if (ob->size) bufputc(ob, '\n');
|
374
|
+
BUFPUTSL(ob, "<tr>\n");
|
375
|
+
if (text)
|
376
|
+
bufput(ob, text->data, text->size);
|
377
|
+
BUFPUTSL(ob, "\n</tr>");
|
378
|
+
}
|
379
|
+
|
380
|
+
static void
|
381
|
+
rndr_tablecell(struct buf *ob, struct buf *text, int align, void *opaque)
|
382
|
+
{
|
383
|
+
if (ob->size) bufputc(ob, '\n');
|
384
|
+
switch (align) {
|
385
|
+
case MKD_TABLE_ALIGN_L:
|
386
|
+
BUFPUTSL(ob, "<td align=\"left\">");
|
387
|
+
break;
|
388
|
+
|
389
|
+
case MKD_TABLE_ALIGN_R:
|
390
|
+
BUFPUTSL(ob, "<td align=\"right\">");
|
391
|
+
break;
|
392
|
+
|
393
|
+
case MKD_TABLE_ALIGN_CENTER:
|
394
|
+
BUFPUTSL(ob, "<td align=\"center\">");
|
395
|
+
break;
|
396
|
+
|
397
|
+
default:
|
398
|
+
BUFPUTSL(ob, "<td>");
|
399
|
+
break;
|
400
|
+
}
|
401
|
+
|
402
|
+
if (text)
|
403
|
+
bufput(ob, text->data, text->size);
|
404
|
+
BUFPUTSL(ob, "</td>");
|
405
|
+
}
|
333
406
|
|
334
407
|
static struct {
|
335
408
|
char c0;
|
@@ -418,13 +491,14 @@ smartypants_quotes(struct buf *ob, struct buf *text, size_t i, int is_open)
|
|
418
491
|
}
|
419
492
|
|
420
493
|
static void
|
421
|
-
rndr_normal_text(struct buf *ob, struct buf *text,
|
494
|
+
rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)
|
422
495
|
{
|
423
496
|
size_t i;
|
424
497
|
int open_single = 0, open_double = 0, open_tag = 0;
|
498
|
+
struct xhtml_renderopt *options = opaque;
|
425
499
|
|
426
|
-
int autolink = (options->flags &
|
427
|
-
int smartypants = (options->flags &
|
500
|
+
int autolink = (options->flags & XHTML_AUTOLINK);
|
501
|
+
int smartypants = (options->flags & XHTML_SMARTYPANTS);
|
428
502
|
|
429
503
|
if (!text)
|
430
504
|
return;
|
@@ -563,46 +637,46 @@ rndr_normal_text(struct buf *ob, struct buf *text, struct mkd_renderopt *options
|
|
563
637
|
}
|
564
638
|
|
565
639
|
static void
|
566
|
-
toc_header(struct buf *ob, struct buf *text, int level,
|
640
|
+
toc_header(struct buf *ob, struct buf *text, int level, void *opaque)
|
567
641
|
{
|
568
|
-
struct
|
642
|
+
struct xhtml_renderopt *options = opaque;
|
569
643
|
|
570
|
-
if (level >
|
644
|
+
if (level > options->toc_data.current_level) {
|
571
645
|
if (level > 1)
|
572
646
|
BUFPUTSL(ob, "<li>");
|
573
647
|
BUFPUTSL(ob, "<ul>\n");
|
574
648
|
}
|
575
649
|
|
576
|
-
if (level <
|
650
|
+
if (level < options->toc_data.current_level) {
|
577
651
|
BUFPUTSL(ob, "</ul>");
|
578
|
-
if (
|
652
|
+
if (options->toc_data.current_level > 1)
|
579
653
|
BUFPUTSL(ob, "</li>\n");
|
580
654
|
}
|
581
655
|
|
582
|
-
|
656
|
+
options->toc_data.current_level = level;
|
583
657
|
|
584
|
-
bufprintf(ob, "<li><a href=\"#toc_%d\">",
|
658
|
+
bufprintf(ob, "<li><a href=\"#toc_%d\">", options->toc_data.header_count++);
|
585
659
|
if (text)
|
586
660
|
bufput(ob, text->data, text->size);
|
587
661
|
BUFPUTSL(ob, "</a></li>\n");
|
588
662
|
}
|
589
663
|
|
590
664
|
static void
|
591
|
-
toc_finalize(struct buf *ob,
|
665
|
+
toc_finalize(struct buf *ob, void *opaque)
|
592
666
|
{
|
593
|
-
struct
|
667
|
+
struct xhtml_renderopt *options = opaque;
|
594
668
|
|
595
|
-
while (
|
669
|
+
while (options->toc_data.current_level > 1) {
|
596
670
|
BUFPUTSL(ob, "</ul></li>\n");
|
597
|
-
|
671
|
+
options->toc_data.current_level--;
|
598
672
|
}
|
599
673
|
|
600
|
-
if (
|
674
|
+
if (options->toc_data.current_level)
|
601
675
|
BUFPUTSL(ob, "</ul>\n");
|
602
676
|
}
|
603
677
|
|
604
678
|
void
|
605
|
-
init_toc_renderer(struct mkd_renderer *renderer
|
679
|
+
init_toc_renderer(struct mkd_renderer *renderer)
|
606
680
|
{
|
607
681
|
static const struct mkd_renderer toc_render = {
|
608
682
|
NULL,
|
@@ -613,6 +687,9 @@ init_toc_renderer(struct mkd_renderer *renderer, int recursion_depth)
|
|
613
687
|
NULL,
|
614
688
|
NULL,
|
615
689
|
NULL,
|
690
|
+
NULL,
|
691
|
+
NULL,
|
692
|
+
NULL,
|
616
693
|
|
617
694
|
rndr_autolink,
|
618
695
|
rndr_codespan,
|
@@ -630,23 +707,20 @@ init_toc_renderer(struct mkd_renderer *renderer, int recursion_depth)
|
|
630
707
|
NULL,
|
631
708
|
toc_finalize,
|
632
709
|
|
633
|
-
|
634
|
-
|
635
|
-
{ 0, 0 },
|
636
|
-
{ 0, 0 },
|
710
|
+
"*-~",
|
711
|
+
NULL
|
637
712
|
};
|
638
713
|
|
639
|
-
|
714
|
+
struct xhtml_renderopt *options;
|
715
|
+
options = calloc(1, sizeof(struct xhtml_renderopt));
|
716
|
+
options->flags = XHTML_TOC;
|
640
717
|
|
641
|
-
renderer
|
642
|
-
renderer->
|
643
|
-
renderer->render_options.opaque = calloc(1, sizeof(struct toc_data));
|
718
|
+
memcpy(renderer, &toc_render, sizeof(struct mkd_renderer));
|
719
|
+
renderer->opaque = options;
|
644
720
|
}
|
645
721
|
|
646
722
|
void
|
647
|
-
init_xhtml_renderer(struct mkd_renderer *renderer,
|
648
|
-
unsigned int render_flags,
|
649
|
-
unsigned int parser_flags, int recursion_depth)
|
723
|
+
init_xhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags)
|
650
724
|
{
|
651
725
|
static const struct mkd_renderer renderer_default = {
|
652
726
|
rndr_blockcode,
|
@@ -657,6 +731,9 @@ init_xhtml_renderer(struct mkd_renderer *renderer,
|
|
657
731
|
rndr_list,
|
658
732
|
rndr_listitem,
|
659
733
|
rndr_paragraph,
|
734
|
+
rndr_table,
|
735
|
+
rndr_tablerow,
|
736
|
+
rndr_tablecell,
|
660
737
|
|
661
738
|
rndr_autolink,
|
662
739
|
rndr_codespan,
|
@@ -674,33 +751,29 @@ init_xhtml_renderer(struct mkd_renderer *renderer,
|
|
674
751
|
NULL,
|
675
752
|
NULL,
|
676
753
|
|
677
|
-
"*_",
|
678
|
-
|
679
|
-
{ 0, 0 },
|
680
|
-
{ 0, 0 },
|
754
|
+
"*_~",
|
755
|
+
NULL
|
681
756
|
};
|
682
757
|
|
758
|
+
struct xhtml_renderopt *options;
|
759
|
+
options = calloc(1, sizeof(struct xhtml_renderopt));
|
760
|
+
options->flags = render_flags;
|
761
|
+
|
683
762
|
memcpy(renderer, &renderer_default, sizeof(struct mkd_renderer));
|
763
|
+
renderer->opaque = options;
|
684
764
|
|
685
|
-
if (render_flags &
|
765
|
+
if (render_flags & XHTML_SKIP_IMAGES)
|
686
766
|
renderer->image = NULL;
|
687
767
|
|
688
|
-
if (render_flags &
|
768
|
+
if (render_flags & XHTML_SKIP_LINKS) {
|
689
769
|
renderer->link = NULL;
|
690
770
|
renderer->autolink = NULL;
|
691
771
|
}
|
692
|
-
|
693
|
-
renderer->parser_options.recursion_depth = recursion_depth;
|
694
|
-
renderer->parser_options.flags = parser_flags;
|
695
|
-
|
696
|
-
renderer->render_options.flags = render_flags;
|
697
|
-
if (render_flags & RENDER_TOC)
|
698
|
-
renderer->render_options.opaque = calloc(1, sizeof(struct toc_data));
|
699
772
|
}
|
700
773
|
|
701
774
|
void
|
702
775
|
free_renderer(struct mkd_renderer *renderer)
|
703
776
|
{
|
704
|
-
free(renderer->
|
777
|
+
free(renderer->opaque);
|
705
778
|
}
|
706
779
|
|