redcarpet 1.17.2 → 2.0.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.
- data/README.markdown +294 -37
- data/Rakefile +13 -15
- data/bin/redcarpet +1 -1
- data/ext/redcarpet/autolink.c +18 -19
- data/ext/redcarpet/autolink.h +7 -4
- data/ext/redcarpet/buffer.c +135 -229
- data/ext/redcarpet/buffer.h +47 -113
- data/ext/redcarpet/houdini.h +29 -0
- data/ext/redcarpet/houdini_href_e.c +108 -0
- data/ext/redcarpet/houdini_html_e.c +84 -0
- data/ext/redcarpet/html.c +181 -237
- data/ext/redcarpet/html.h +28 -14
- data/ext/redcarpet/html_blocks.h +206 -0
- data/ext/redcarpet/html_smartypants.c +99 -49
- data/ext/redcarpet/markdown.c +712 -493
- data/ext/redcarpet/markdown.h +48 -41
- data/ext/redcarpet/rc_markdown.c +137 -0
- data/ext/redcarpet/rc_render.c +434 -0
- data/ext/redcarpet/redcarpet.h +33 -0
- data/ext/redcarpet/stack.c +81 -0
- data/ext/redcarpet/stack.h +21 -0
- data/lib/redcarpet/render_man.rb +65 -0
- data/lib/redcarpet.rb +62 -101
- data/redcarpet.gemspec +18 -13
- data/test/redcarpet_test.rb +209 -122
- metadata +33 -20
- data/ext/redcarpet/array.c +0 -300
- data/ext/redcarpet/array.h +0 -147
- data/ext/redcarpet/redcarpet.c +0 -161
- data/lib/markdown.rb +0 -1
- data/test/benchmark.rb +0 -56
- data/test/benchmark.txt +0 -306
- data/test/markdown_test.rb +0 -186
data/ext/redcarpet/html.c
CHANGED
|
@@ -23,87 +23,48 @@
|
|
|
23
23
|
#include <stdio.h>
|
|
24
24
|
#include <ctype.h>
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
struct {
|
|
28
|
-
int header_count;
|
|
29
|
-
int current_level;
|
|
30
|
-
} toc_data;
|
|
31
|
-
|
|
32
|
-
unsigned int flags;
|
|
33
|
-
const char *close_tag;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
static inline void
|
|
37
|
-
put_scaped_char(struct buf *ob, char c)
|
|
38
|
-
{
|
|
39
|
-
switch (c) {
|
|
40
|
-
case '<': BUFPUTSL(ob, "<"); break;
|
|
41
|
-
case '>': BUFPUTSL(ob, ">"); break;
|
|
42
|
-
case '&': BUFPUTSL(ob, "&"); break;
|
|
43
|
-
case '"': BUFPUTSL(ob, """); break;
|
|
44
|
-
default: bufputc(ob, c); break;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
26
|
+
#include "houdini.h"
|
|
47
27
|
|
|
48
|
-
|
|
49
|
-
void
|
|
50
|
-
upshtml_escape(struct buf *ob, const char *src, size_t size)
|
|
51
|
-
{
|
|
52
|
-
size_t i = 0, org;
|
|
53
|
-
while (i < size) {
|
|
54
|
-
/* copying directly unescaped characters */
|
|
55
|
-
org = i;
|
|
56
|
-
while (i < size && src[i] != '<' && src[i] != '>'
|
|
57
|
-
&& src[i] != '&' && src[i] != '"')
|
|
58
|
-
i += 1;
|
|
59
|
-
if (i > org) bufput(ob, src + org, i - org);
|
|
60
|
-
|
|
61
|
-
/* escaping */
|
|
62
|
-
if (i >= size) break;
|
|
63
|
-
|
|
64
|
-
put_scaped_char(ob, src[i]);
|
|
65
|
-
i++;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
28
|
+
#define USE_XHTML(opt) (opt->flags & HTML_USE_XHTML)
|
|
68
29
|
|
|
69
|
-
|
|
70
|
-
|
|
30
|
+
int
|
|
31
|
+
sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname)
|
|
71
32
|
{
|
|
72
|
-
size_t i
|
|
73
|
-
|
|
74
|
-
if (i < tag->size && tag->data[0] != '<')
|
|
75
|
-
return 0;
|
|
33
|
+
size_t i;
|
|
34
|
+
int closed = 0;
|
|
76
35
|
|
|
77
|
-
|
|
36
|
+
if (tag_size < 3 || tag_data[0] != '<')
|
|
37
|
+
return HTML_TAG_NONE;
|
|
78
38
|
|
|
79
|
-
|
|
80
|
-
i++;
|
|
81
|
-
|
|
82
|
-
if (i < tag->size && tag->data[i] == '/')
|
|
83
|
-
i++;
|
|
39
|
+
i = 1;
|
|
84
40
|
|
|
85
|
-
|
|
41
|
+
if (tag_data[i] == '/') {
|
|
42
|
+
closed = 1;
|
|
86
43
|
i++;
|
|
44
|
+
}
|
|
87
45
|
|
|
88
|
-
for (; i <
|
|
46
|
+
for (; i < tag_size; ++i, ++tagname) {
|
|
89
47
|
if (*tagname == 0)
|
|
90
48
|
break;
|
|
91
49
|
|
|
92
|
-
if (
|
|
93
|
-
return
|
|
50
|
+
if (tag_data[i] != *tagname)
|
|
51
|
+
return HTML_TAG_NONE;
|
|
94
52
|
}
|
|
95
53
|
|
|
96
|
-
if (i ==
|
|
97
|
-
return
|
|
54
|
+
if (i == tag_size)
|
|
55
|
+
return HTML_TAG_NONE;
|
|
98
56
|
|
|
99
|
-
|
|
57
|
+
if (isspace(tag_data[i]) || tag_data[i] == '>')
|
|
58
|
+
return closed ? HTML_TAG_CLOSE : HTML_TAG_OPEN;
|
|
59
|
+
|
|
60
|
+
return HTML_TAG_NONE;
|
|
100
61
|
}
|
|
101
62
|
|
|
102
63
|
/********************
|
|
103
64
|
* GENERIC RENDERER *
|
|
104
65
|
********************/
|
|
105
66
|
static int
|
|
106
|
-
rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque)
|
|
67
|
+
rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque)
|
|
107
68
|
{
|
|
108
69
|
struct html_renderopt *options = opaque;
|
|
109
70
|
|
|
@@ -111,15 +72,22 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
|
|
|
111
72
|
return 0;
|
|
112
73
|
|
|
113
74
|
if ((options->flags & HTML_SAFELINK) != 0 &&
|
|
114
|
-
!
|
|
75
|
+
!sd_autolink_issafe(link->data, link->size) &&
|
|
115
76
|
type != MKDA_EMAIL)
|
|
116
77
|
return 0;
|
|
117
78
|
|
|
118
79
|
BUFPUTSL(ob, "<a href=\"");
|
|
119
80
|
if (type == MKDA_EMAIL)
|
|
120
81
|
BUFPUTSL(ob, "mailto:");
|
|
121
|
-
|
|
122
|
-
|
|
82
|
+
houdini_escape_href(ob, link->data, link->size);
|
|
83
|
+
|
|
84
|
+
if (options->link_attributes) {
|
|
85
|
+
bufputc(ob, '\"');
|
|
86
|
+
options->link_attributes(ob, link, opaque);
|
|
87
|
+
bufputc(ob, '>');
|
|
88
|
+
} else {
|
|
89
|
+
BUFPUTSL(ob, "\">");
|
|
90
|
+
}
|
|
123
91
|
|
|
124
92
|
/*
|
|
125
93
|
* Pretty printing: if we get an email address as
|
|
@@ -127,9 +95,9 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
|
|
|
127
95
|
* want to print the `mailto:` prefix
|
|
128
96
|
*/
|
|
129
97
|
if (bufprefix(link, "mailto:") == 0) {
|
|
130
|
-
|
|
98
|
+
houdini_escape_html(ob, link->data + 7, link->size - 7);
|
|
131
99
|
} else {
|
|
132
|
-
|
|
100
|
+
houdini_escape_html(ob, link->data, link->size);
|
|
133
101
|
}
|
|
134
102
|
|
|
135
103
|
BUFPUTSL(ob, "</a>");
|
|
@@ -138,7 +106,7 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
|
|
|
138
106
|
}
|
|
139
107
|
|
|
140
108
|
static void
|
|
141
|
-
rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
|
|
109
|
+
rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque)
|
|
142
110
|
{
|
|
143
111
|
if (ob->size) bufputc(ob, '\n');
|
|
144
112
|
|
|
@@ -159,7 +127,7 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
|
|
|
159
127
|
org++;
|
|
160
128
|
|
|
161
129
|
if (cls) bufputc(ob, ' ');
|
|
162
|
-
|
|
130
|
+
houdini_escape_html(ob, lang->data + org, i - org);
|
|
163
131
|
}
|
|
164
132
|
}
|
|
165
133
|
|
|
@@ -168,75 +136,31 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
|
|
|
168
136
|
BUFPUTSL(ob, "<pre><code>");
|
|
169
137
|
|
|
170
138
|
if (text)
|
|
171
|
-
|
|
139
|
+
houdini_escape_html(ob, text->data, text->size);
|
|
172
140
|
|
|
173
141
|
BUFPUTSL(ob, "</code></pre>\n");
|
|
174
142
|
}
|
|
175
143
|
|
|
176
|
-
/*
|
|
177
|
-
* GitHub style code block:
|
|
178
|
-
*
|
|
179
|
-
* <pre lang="LANG"><code>
|
|
180
|
-
* ...
|
|
181
|
-
* </pre></code>
|
|
182
|
-
*
|
|
183
|
-
* Unlike other parsers, we store the language identifier in the <pre>,
|
|
184
|
-
* and don't let the user generate custom classes.
|
|
185
|
-
*
|
|
186
|
-
* The language identifier in the <pre> block gets postprocessed and all
|
|
187
|
-
* the code inside gets syntax highlighted with Pygments. This is much safer
|
|
188
|
-
* than letting the user specify a CSS class for highlighting.
|
|
189
|
-
*
|
|
190
|
-
* Note that we only generate HTML for the first specifier.
|
|
191
|
-
* E.g.
|
|
192
|
-
* ~~~~ {.python .numbered} => <pre lang="python"><code>
|
|
193
|
-
*/
|
|
194
144
|
static void
|
|
195
|
-
|
|
145
|
+
rndr_blockquote(struct buf *ob, const struct buf *text, void *opaque)
|
|
196
146
|
{
|
|
197
147
|
if (ob->size) bufputc(ob, '\n');
|
|
198
|
-
|
|
199
|
-
if (lang && lang->size) {
|
|
200
|
-
size_t i = 0;
|
|
201
|
-
BUFPUTSL(ob, "<pre lang=\"");
|
|
202
|
-
|
|
203
|
-
while (i < lang->size && !isspace(lang->data[i]))
|
|
204
|
-
i++;
|
|
205
|
-
|
|
206
|
-
if (lang->data[0] == '.')
|
|
207
|
-
upshtml_escape(ob, lang->data + 1, i - 1);
|
|
208
|
-
else
|
|
209
|
-
upshtml_escape(ob, lang->data, i);
|
|
210
|
-
|
|
211
|
-
BUFPUTSL(ob, "\"><code>");
|
|
212
|
-
} else
|
|
213
|
-
BUFPUTSL(ob, "<pre><code>");
|
|
214
|
-
|
|
215
|
-
if (text)
|
|
216
|
-
upshtml_escape(ob, text->data, text->size);
|
|
217
|
-
|
|
218
|
-
BUFPUTSL(ob, "</code></pre>\n");
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
static void
|
|
222
|
-
rndr_blockquote(struct buf *ob, struct buf *text, void *opaque)
|
|
223
|
-
{
|
|
224
148
|
BUFPUTSL(ob, "<blockquote>\n");
|
|
225
149
|
if (text) bufput(ob, text->data, text->size);
|
|
226
|
-
BUFPUTSL(ob, "</blockquote
|
|
150
|
+
BUFPUTSL(ob, "</blockquote>\n");
|
|
227
151
|
}
|
|
228
152
|
|
|
229
153
|
static int
|
|
230
|
-
rndr_codespan(struct buf *ob, struct buf *text, void *opaque)
|
|
154
|
+
rndr_codespan(struct buf *ob, const struct buf *text, void *opaque)
|
|
231
155
|
{
|
|
232
156
|
BUFPUTSL(ob, "<code>");
|
|
233
|
-
if (text)
|
|
157
|
+
if (text) houdini_escape_html(ob, text->data, text->size);
|
|
234
158
|
BUFPUTSL(ob, "</code>");
|
|
235
159
|
return 1;
|
|
236
160
|
}
|
|
237
161
|
|
|
238
162
|
static int
|
|
239
|
-
rndr_strikethrough(struct buf *ob, struct buf *text, void *opaque)
|
|
163
|
+
rndr_strikethrough(struct buf *ob, const struct buf *text, void *opaque)
|
|
240
164
|
{
|
|
241
165
|
if (!text || !text->size)
|
|
242
166
|
return 0;
|
|
@@ -248,7 +172,7 @@ rndr_strikethrough(struct buf *ob, struct buf *text, void *opaque)
|
|
|
248
172
|
}
|
|
249
173
|
|
|
250
174
|
static int
|
|
251
|
-
rndr_double_emphasis(struct buf *ob, struct buf *text, void *opaque)
|
|
175
|
+
rndr_double_emphasis(struct buf *ob, const struct buf *text, void *opaque)
|
|
252
176
|
{
|
|
253
177
|
if (!text || !text->size)
|
|
254
178
|
return 0;
|
|
@@ -261,7 +185,7 @@ rndr_double_emphasis(struct buf *ob, struct buf *text, void *opaque)
|
|
|
261
185
|
}
|
|
262
186
|
|
|
263
187
|
static int
|
|
264
|
-
rndr_emphasis(struct buf *ob, struct buf *text, void *opaque)
|
|
188
|
+
rndr_emphasis(struct buf *ob, const struct buf *text, void *opaque)
|
|
265
189
|
{
|
|
266
190
|
if (!text || !text->size) return 0;
|
|
267
191
|
BUFPUTSL(ob, "<em>");
|
|
@@ -270,11 +194,19 @@ rndr_emphasis(struct buf *ob, struct buf *text, void *opaque)
|
|
|
270
194
|
return 1;
|
|
271
195
|
}
|
|
272
196
|
|
|
197
|
+
static int
|
|
198
|
+
rndr_linebreak(struct buf *ob, void *opaque)
|
|
199
|
+
{
|
|
200
|
+
struct html_renderopt *options = opaque;
|
|
201
|
+
bufputs(ob, USE_XHTML(options) ? "<br/>\n" : "<br>\n");
|
|
202
|
+
return 1;
|
|
203
|
+
}
|
|
204
|
+
|
|
273
205
|
static void
|
|
274
|
-
rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)
|
|
206
|
+
rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque)
|
|
275
207
|
{
|
|
276
208
|
struct html_renderopt *options = opaque;
|
|
277
|
-
|
|
209
|
+
|
|
278
210
|
if (ob->size)
|
|
279
211
|
bufputc(ob, '\n');
|
|
280
212
|
|
|
@@ -288,26 +220,38 @@ rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)
|
|
|
288
220
|
}
|
|
289
221
|
|
|
290
222
|
static int
|
|
291
|
-
rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque)
|
|
223
|
+
rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque)
|
|
292
224
|
{
|
|
293
225
|
struct html_renderopt *options = opaque;
|
|
294
|
-
|
|
295
|
-
if ((options->flags & HTML_SAFELINK) != 0 && !
|
|
226
|
+
|
|
227
|
+
if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
|
|
296
228
|
return 0;
|
|
297
229
|
|
|
298
230
|
BUFPUTSL(ob, "<a href=\"");
|
|
299
|
-
|
|
231
|
+
|
|
232
|
+
if (link && link->size)
|
|
233
|
+
houdini_escape_href(ob, link->data, link->size);
|
|
234
|
+
|
|
300
235
|
if (title && title->size) {
|
|
301
236
|
BUFPUTSL(ob, "\" title=\"");
|
|
302
|
-
|
|
303
|
-
|
|
237
|
+
houdini_escape_html(ob, title->data, title->size);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (options->link_attributes) {
|
|
241
|
+
bufputc(ob, '\"');
|
|
242
|
+
options->link_attributes(ob, link, opaque);
|
|
243
|
+
bufputc(ob, '>');
|
|
244
|
+
} else {
|
|
245
|
+
BUFPUTSL(ob, "\">");
|
|
246
|
+
}
|
|
247
|
+
|
|
304
248
|
if (content && content->size) bufput(ob, content->data, content->size);
|
|
305
249
|
BUFPUTSL(ob, "</a>");
|
|
306
250
|
return 1;
|
|
307
251
|
}
|
|
308
252
|
|
|
309
253
|
static void
|
|
310
|
-
rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)
|
|
254
|
+
rndr_list(struct buf *ob, const struct buf *text, int flags, void *opaque)
|
|
311
255
|
{
|
|
312
256
|
if (ob->size) bufputc(ob, '\n');
|
|
313
257
|
bufput(ob, flags & MKD_LIST_ORDERED ? "<ol>\n" : "<ul>\n", 5);
|
|
@@ -316,18 +260,21 @@ rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)
|
|
|
316
260
|
}
|
|
317
261
|
|
|
318
262
|
static void
|
|
319
|
-
rndr_listitem(struct buf *ob, struct buf *text, int flags, void *opaque)
|
|
263
|
+
rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque)
|
|
320
264
|
{
|
|
321
265
|
BUFPUTSL(ob, "<li>");
|
|
322
266
|
if (text) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
267
|
+
size_t size = text->size;
|
|
268
|
+
while (size && text->data[size - 1] == '\n')
|
|
269
|
+
size--;
|
|
270
|
+
|
|
271
|
+
bufput(ob, text->data, size);
|
|
272
|
+
}
|
|
326
273
|
BUFPUTSL(ob, "</li>\n");
|
|
327
274
|
}
|
|
328
275
|
|
|
329
276
|
static void
|
|
330
|
-
rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
|
|
277
|
+
rndr_paragraph(struct buf *ob, const struct buf *text, void *opaque)
|
|
331
278
|
{
|
|
332
279
|
struct html_renderopt *options = opaque;
|
|
333
280
|
size_t i = 0;
|
|
@@ -353,11 +300,14 @@ rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
|
|
|
353
300
|
if (i > org)
|
|
354
301
|
bufput(ob, text->data + org, i - org);
|
|
355
302
|
|
|
356
|
-
|
|
303
|
+
/*
|
|
304
|
+
* do not insert a line break if this newline
|
|
305
|
+
* is the last character on the paragraph
|
|
306
|
+
*/
|
|
307
|
+
if (i >= text->size - 1)
|
|
357
308
|
break;
|
|
358
309
|
|
|
359
|
-
|
|
360
|
-
bufputs(ob, options->close_tag);
|
|
310
|
+
rndr_linebreak(ob, opaque);
|
|
361
311
|
i++;
|
|
362
312
|
}
|
|
363
313
|
} else {
|
|
@@ -367,7 +317,7 @@ rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
|
|
|
367
317
|
}
|
|
368
318
|
|
|
369
319
|
static void
|
|
370
|
-
rndr_raw_block(struct buf *ob, struct buf *text, void *opaque)
|
|
320
|
+
rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque)
|
|
371
321
|
{
|
|
372
322
|
size_t org, sz;
|
|
373
323
|
if (!text) return;
|
|
@@ -382,7 +332,7 @@ rndr_raw_block(struct buf *ob, struct buf *text, void *opaque)
|
|
|
382
332
|
}
|
|
383
333
|
|
|
384
334
|
static int
|
|
385
|
-
rndr_triple_emphasis(struct buf *ob, struct buf *text, void *opaque)
|
|
335
|
+
rndr_triple_emphasis(struct buf *ob, const struct buf *text, void *opaque)
|
|
386
336
|
{
|
|
387
337
|
if (!text || !text->size) return 0;
|
|
388
338
|
BUFPUTSL(ob, "<strong><em>");
|
|
@@ -394,55 +344,50 @@ rndr_triple_emphasis(struct buf *ob, struct buf *text, void *opaque)
|
|
|
394
344
|
static void
|
|
395
345
|
rndr_hrule(struct buf *ob, void *opaque)
|
|
396
346
|
{
|
|
397
|
-
struct html_renderopt *options = opaque;
|
|
347
|
+
struct html_renderopt *options = opaque;
|
|
398
348
|
if (ob->size) bufputc(ob, '\n');
|
|
399
|
-
|
|
400
|
-
bufputs(ob, options->close_tag);
|
|
349
|
+
bufputs(ob, USE_XHTML(options) ? "<hr/>\n" : "<hr>\n");
|
|
401
350
|
}
|
|
402
351
|
|
|
403
352
|
static int
|
|
404
|
-
rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque)
|
|
353
|
+
rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque)
|
|
405
354
|
{
|
|
406
|
-
struct html_renderopt *options = opaque;
|
|
355
|
+
struct html_renderopt *options = opaque;
|
|
407
356
|
if (!link || !link->size) return 0;
|
|
357
|
+
|
|
408
358
|
BUFPUTSL(ob, "<img src=\"");
|
|
409
|
-
|
|
359
|
+
houdini_escape_href(ob, link->data, link->size);
|
|
410
360
|
BUFPUTSL(ob, "\" alt=\"");
|
|
361
|
+
|
|
411
362
|
if (alt && alt->size)
|
|
412
|
-
|
|
363
|
+
houdini_escape_html(ob, alt->data, alt->size);
|
|
364
|
+
|
|
413
365
|
if (title && title->size) {
|
|
414
366
|
BUFPUTSL(ob, "\" title=\"");
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
bufputc(ob, '"');
|
|
418
|
-
bufputs(ob, options->close_tag);
|
|
419
|
-
return 1;
|
|
420
|
-
}
|
|
367
|
+
houdini_escape_html(ob, title->data, title->size); }
|
|
421
368
|
|
|
422
|
-
|
|
423
|
-
rndr_linebreak(struct buf *ob, void *opaque)
|
|
424
|
-
{
|
|
425
|
-
struct html_renderopt *options = opaque;
|
|
426
|
-
BUFPUTSL(ob, "<br");
|
|
427
|
-
bufputs(ob, options->close_tag);
|
|
369
|
+
bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
|
|
428
370
|
return 1;
|
|
429
371
|
}
|
|
430
372
|
|
|
431
373
|
static int
|
|
432
|
-
rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)
|
|
374
|
+
rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque)
|
|
433
375
|
{
|
|
434
|
-
struct html_renderopt *options = opaque;
|
|
376
|
+
struct html_renderopt *options = opaque;
|
|
435
377
|
|
|
436
378
|
if ((options->flags & HTML_SKIP_HTML) != 0)
|
|
437
379
|
return 1;
|
|
438
380
|
|
|
439
|
-
if ((options->flags & HTML_SKIP_STYLE) != 0 &&
|
|
381
|
+
if ((options->flags & HTML_SKIP_STYLE) != 0 &&
|
|
382
|
+
sdhtml_is_tag(text->data, text->size, "style"))
|
|
440
383
|
return 1;
|
|
441
384
|
|
|
442
|
-
if ((options->flags & HTML_SKIP_LINKS) != 0 &&
|
|
385
|
+
if ((options->flags & HTML_SKIP_LINKS) != 0 &&
|
|
386
|
+
sdhtml_is_tag(text->data, text->size, "a"))
|
|
443
387
|
return 1;
|
|
444
388
|
|
|
445
|
-
if ((options->flags & HTML_SKIP_IMAGES) != 0 &&
|
|
389
|
+
if ((options->flags & HTML_SKIP_IMAGES) != 0 &&
|
|
390
|
+
sdhtml_is_tag(text->data, text->size, "img"))
|
|
446
391
|
return 1;
|
|
447
392
|
|
|
448
393
|
bufput(ob, text->data, text->size);
|
|
@@ -450,85 +395,105 @@ rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)
|
|
|
450
395
|
}
|
|
451
396
|
|
|
452
397
|
static void
|
|
453
|
-
rndr_table(struct buf *ob, struct buf *header, struct buf *body, void *opaque)
|
|
398
|
+
rndr_table(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque)
|
|
454
399
|
{
|
|
455
400
|
if (ob->size) bufputc(ob, '\n');
|
|
456
401
|
BUFPUTSL(ob, "<table><thead>\n");
|
|
457
402
|
if (header)
|
|
458
403
|
bufput(ob, header->data, header->size);
|
|
459
|
-
BUFPUTSL(ob, "
|
|
404
|
+
BUFPUTSL(ob, "</thead><tbody>\n");
|
|
460
405
|
if (body)
|
|
461
406
|
bufput(ob, body->data, body->size);
|
|
462
|
-
BUFPUTSL(ob, "
|
|
407
|
+
BUFPUTSL(ob, "</tbody></table>\n");
|
|
463
408
|
}
|
|
464
409
|
|
|
465
410
|
static void
|
|
466
|
-
rndr_tablerow(struct buf *ob, struct buf *text, void *opaque)
|
|
411
|
+
rndr_tablerow(struct buf *ob, const struct buf *text, void *opaque)
|
|
467
412
|
{
|
|
468
|
-
if (ob->size) bufputc(ob, '\n');
|
|
469
413
|
BUFPUTSL(ob, "<tr>\n");
|
|
470
414
|
if (text)
|
|
471
415
|
bufput(ob, text->data, text->size);
|
|
472
|
-
BUFPUTSL(ob, "
|
|
416
|
+
BUFPUTSL(ob, "</tr>\n");
|
|
473
417
|
}
|
|
474
418
|
|
|
475
419
|
static void
|
|
476
|
-
rndr_tablecell(struct buf *ob, struct buf *text, int
|
|
420
|
+
rndr_tablecell(struct buf *ob, const struct buf *text, int flags, void *opaque)
|
|
477
421
|
{
|
|
478
|
-
if (
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
BUFPUTSL(ob, "<td
|
|
422
|
+
if (flags & MKD_TABLE_HEADER) {
|
|
423
|
+
BUFPUTSL(ob, "<th");
|
|
424
|
+
} else {
|
|
425
|
+
BUFPUTSL(ob, "<td");
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
switch (flags & MKD_TABLE_ALIGNMASK) {
|
|
429
|
+
case MKD_TABLE_ALIGN_CENTER:
|
|
430
|
+
BUFPUTSL(ob, " align=\"center\">");
|
|
482
431
|
break;
|
|
483
432
|
|
|
484
|
-
case
|
|
485
|
-
BUFPUTSL(ob, "
|
|
433
|
+
case MKD_TABLE_ALIGN_L:
|
|
434
|
+
BUFPUTSL(ob, " align=\"left\">");
|
|
486
435
|
break;
|
|
487
436
|
|
|
488
|
-
case
|
|
489
|
-
BUFPUTSL(ob, "
|
|
437
|
+
case MKD_TABLE_ALIGN_R:
|
|
438
|
+
BUFPUTSL(ob, " align=\"right\">");
|
|
490
439
|
break;
|
|
491
440
|
|
|
492
441
|
default:
|
|
493
|
-
BUFPUTSL(ob, "
|
|
494
|
-
break;
|
|
442
|
+
BUFPUTSL(ob, ">");
|
|
495
443
|
}
|
|
496
444
|
|
|
497
445
|
if (text)
|
|
498
446
|
bufput(ob, text->data, text->size);
|
|
499
|
-
|
|
447
|
+
|
|
448
|
+
if (flags & MKD_TABLE_HEADER) {
|
|
449
|
+
BUFPUTSL(ob, "</th>\n");
|
|
450
|
+
} else {
|
|
451
|
+
BUFPUTSL(ob, "</td>\n");
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
static int
|
|
456
|
+
rndr_superscript(struct buf *ob, const struct buf *text, void *opaque)
|
|
457
|
+
{
|
|
458
|
+
if (!text || !text->size) return 0;
|
|
459
|
+
BUFPUTSL(ob, "<sup>");
|
|
460
|
+
bufput(ob, text->data, text->size);
|
|
461
|
+
BUFPUTSL(ob, "</sup>");
|
|
462
|
+
return 1;
|
|
500
463
|
}
|
|
501
464
|
|
|
502
465
|
static void
|
|
503
|
-
rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)
|
|
466
|
+
rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque)
|
|
504
467
|
{
|
|
505
468
|
if (text)
|
|
506
|
-
|
|
469
|
+
houdini_escape_html(ob, text->data, text->size);
|
|
507
470
|
}
|
|
508
471
|
|
|
509
472
|
static void
|
|
510
|
-
toc_header(struct buf *ob, struct buf *text, int level, void *opaque)
|
|
473
|
+
toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
|
|
511
474
|
{
|
|
512
475
|
struct html_renderopt *options = opaque;
|
|
513
476
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
BUFPUTSL(ob, "<li
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
477
|
+
if (level > options->toc_data.current_level) {
|
|
478
|
+
while (level > options->toc_data.current_level) {
|
|
479
|
+
BUFPUTSL(ob, "<ul>\n<li>\n");
|
|
480
|
+
options->toc_data.current_level++;
|
|
481
|
+
}
|
|
482
|
+
} else if (level < options->toc_data.current_level) {
|
|
483
|
+
BUFPUTSL(ob, "</li>\n");
|
|
484
|
+
while (level < options->toc_data.current_level) {
|
|
485
|
+
BUFPUTSL(ob, "</ul>\n</li>\n");
|
|
486
|
+
options->toc_data.current_level--;
|
|
487
|
+
}
|
|
488
|
+
BUFPUTSL(ob,"<li>\n");
|
|
489
|
+
} else {
|
|
490
|
+
BUFPUTSL(ob,"</li>\n<li>\n");
|
|
526
491
|
}
|
|
527
492
|
|
|
528
|
-
bufprintf(ob, "<
|
|
493
|
+
bufprintf(ob, "<a href=\"#toc_%d\">", options->toc_data.header_count++);
|
|
529
494
|
if (text)
|
|
530
495
|
bufput(ob, text->data, text->size);
|
|
531
|
-
BUFPUTSL(ob, "</a
|
|
496
|
+
BUFPUTSL(ob, "</a>\n");
|
|
532
497
|
}
|
|
533
498
|
|
|
534
499
|
static void
|
|
@@ -536,19 +501,16 @@ toc_finalize(struct buf *ob, void *opaque)
|
|
|
536
501
|
{
|
|
537
502
|
struct html_renderopt *options = opaque;
|
|
538
503
|
|
|
539
|
-
while (options->toc_data.current_level >
|
|
540
|
-
BUFPUTSL(ob, "</
|
|
504
|
+
while (options->toc_data.current_level > 0) {
|
|
505
|
+
BUFPUTSL(ob, "</li>\n</ul>\n");
|
|
541
506
|
options->toc_data.current_level--;
|
|
542
507
|
}
|
|
543
|
-
|
|
544
|
-
if (options->toc_data.current_level)
|
|
545
|
-
BUFPUTSL(ob, "</ul>\n");
|
|
546
508
|
}
|
|
547
509
|
|
|
548
510
|
void
|
|
549
|
-
|
|
511
|
+
sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options)
|
|
550
512
|
{
|
|
551
|
-
static const struct
|
|
513
|
+
static const struct sd_callbacks cb_default = {
|
|
552
514
|
NULL,
|
|
553
515
|
NULL,
|
|
554
516
|
NULL,
|
|
@@ -571,31 +533,25 @@ upshtml_toc_renderer(struct mkd_renderer *renderer)
|
|
|
571
533
|
NULL,
|
|
572
534
|
rndr_triple_emphasis,
|
|
573
535
|
rndr_strikethrough,
|
|
536
|
+
rndr_superscript,
|
|
574
537
|
|
|
575
538
|
NULL,
|
|
576
539
|
NULL,
|
|
577
540
|
|
|
578
541
|
NULL,
|
|
579
542
|
toc_finalize,
|
|
580
|
-
|
|
581
|
-
NULL
|
|
582
543
|
};
|
|
583
544
|
|
|
584
|
-
struct html_renderopt
|
|
585
|
-
options = calloc(1, sizeof(struct html_renderopt));
|
|
545
|
+
memset(options, 0x0, sizeof(struct html_renderopt));
|
|
586
546
|
options->flags = HTML_TOC;
|
|
587
547
|
|
|
588
|
-
memcpy(
|
|
589
|
-
renderer->opaque = options;
|
|
548
|
+
memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
|
|
590
549
|
}
|
|
591
550
|
|
|
592
551
|
void
|
|
593
|
-
|
|
552
|
+
sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, unsigned int render_flags)
|
|
594
553
|
{
|
|
595
|
-
static const
|
|
596
|
-
static const char *html_close = ">\n";
|
|
597
|
-
|
|
598
|
-
static const struct mkd_renderer renderer_default = {
|
|
554
|
+
static const struct sd_callbacks cb_default = {
|
|
599
555
|
rndr_blockcode,
|
|
600
556
|
rndr_blockquote,
|
|
601
557
|
rndr_raw_block,
|
|
@@ -618,42 +574,30 @@ upshtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags)
|
|
|
618
574
|
rndr_raw_html,
|
|
619
575
|
rndr_triple_emphasis,
|
|
620
576
|
rndr_strikethrough,
|
|
577
|
+
rndr_superscript,
|
|
621
578
|
|
|
622
579
|
NULL,
|
|
623
580
|
rndr_normal_text,
|
|
624
581
|
|
|
625
582
|
NULL,
|
|
626
583
|
NULL,
|
|
627
|
-
|
|
628
|
-
NULL
|
|
629
584
|
};
|
|
630
585
|
|
|
631
|
-
|
|
632
|
-
options
|
|
586
|
+
/* Prepare the options pointer */
|
|
587
|
+
memset(options, 0x0, sizeof(struct html_renderopt));
|
|
633
588
|
options->flags = render_flags;
|
|
634
|
-
options->close_tag = (render_flags & HTML_USE_XHTML) ? xhtml_close : html_close;
|
|
635
589
|
|
|
636
|
-
|
|
637
|
-
|
|
590
|
+
/* Prepare the callbacks */
|
|
591
|
+
memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
|
|
638
592
|
|
|
639
593
|
if (render_flags & HTML_SKIP_IMAGES)
|
|
640
|
-
|
|
594
|
+
callbacks->image = NULL;
|
|
641
595
|
|
|
642
596
|
if (render_flags & HTML_SKIP_LINKS) {
|
|
643
|
-
|
|
644
|
-
|
|
597
|
+
callbacks->link = NULL;
|
|
598
|
+
callbacks->autolink = NULL;
|
|
645
599
|
}
|
|
646
600
|
|
|
647
601
|
if (render_flags & HTML_SKIP_HTML)
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
if (render_flags & HTML_GITHUB_BLOCKCODE)
|
|
651
|
-
renderer->blockcode = rndr_blockcode_github;
|
|
602
|
+
callbacks->blockhtml = NULL;
|
|
652
603
|
}
|
|
653
|
-
|
|
654
|
-
void
|
|
655
|
-
upshtml_free_renderer(struct mkd_renderer *renderer)
|
|
656
|
-
{
|
|
657
|
-
free(renderer->opaque);
|
|
658
|
-
}
|
|
659
|
-
|