redcarpet 1.5.0 → 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/ext/xhtml.c DELETED
@@ -1,779 +0,0 @@
1
- /*
2
- * Copyright (c) 2009, Natacha Porté
3
- * Copyright (c) 2011, Vicent Marti
4
- *
5
- * Permission to use, copy, modify, and distribute this software for any
6
- * purpose with or without fee is hereby granted, provided that the above
7
- * copyright notice and this permission notice appear in all copies.
8
- *
9
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
- */
17
-
18
- #include "markdown.h"
19
- #include "xhtml.h"
20
-
21
- #include <strings.h>
22
- #include <stdlib.h>
23
- #include <stdio.h>
24
-
25
- struct xhtml_renderopt {
26
- struct {
27
- int header_count;
28
- int current_level;
29
- } toc_data;
30
-
31
- unsigned int flags;
32
- };
33
-
34
- static int
35
- is_safe_link(const char *link, size_t link_len)
36
- {
37
- static const size_t valid_uris_count = 4;
38
- static const char *valid_uris[] = {
39
- "http:", "https:", "ftp:", "mailto:"
40
- };
41
-
42
- size_t i;
43
-
44
- for (i = 0; i < valid_uris_count; ++i) {
45
- size_t len = strlen(valid_uris[i]);
46
-
47
- if (link_len > len && memcmp(link, valid_uris[i], len) == 0)
48
- return 1;
49
- }
50
-
51
- return 0;
52
- }
53
-
54
- static inline int
55
- put_scaped_char(struct buf *ob, char c)
56
- {
57
- switch (c) {
58
- case '<': BUFPUTSL(ob, "&lt;"); return 1;
59
- case '>': BUFPUTSL(ob, "&gt;"); return 1;
60
- case '&': BUFPUTSL(ob, "&amp;"); return 1;
61
- case '"': BUFPUTSL(ob, "&quot;"); return 1;
62
- default: return 0;
63
- }
64
- }
65
-
66
- /* lus_attr_escape • copy the buffer entity-escaping '<', '>', '&' and '"' */
67
- static void
68
- lus_attr_escape(struct buf *ob, const char *src, size_t size)
69
- {
70
- size_t i = 0, org;
71
- while (i < size) {
72
- /* copying directly unescaped characters */
73
- org = i;
74
- while (i < size && src[i] != '<' && src[i] != '>'
75
- && src[i] != '&' && src[i] != '"')
76
- i += 1;
77
- if (i > org) bufput(ob, src + org, i - org);
78
-
79
- /* escaping */
80
- if (i >= size) break;
81
-
82
- put_scaped_char(ob, src[i]);
83
- i++;
84
- }
85
- }
86
-
87
- static int
88
- is_html_tag(struct buf *tag, const char *tagname)
89
- {
90
- size_t i;
91
-
92
- for (i = 0; i < tag->size; ++i) {
93
- if (tagname[i] == '>')
94
- break;
95
-
96
- if (tag->data[i] != tagname[i])
97
- return 0;
98
- }
99
-
100
- return (i == tag->size || isspace(tag->data[i]) || tag->data[i] == '>');
101
- }
102
-
103
- /********************
104
- * GENERIC RENDERER *
105
- ********************/
106
-
107
- static void
108
- rndr_autolink2(struct buf *ob, const char *link, size_t link_size, enum mkd_autolink type)
109
- {
110
- BUFPUTSL(ob, "<a href=\"");
111
- if (type == MKDA_IMPLICIT_EMAIL) BUFPUTSL(ob, "mailto:");
112
- lus_attr_escape(ob, link, link_size);
113
- BUFPUTSL(ob, "\">");
114
- if (type == MKDA_EXPLICIT_EMAIL && link_size > 7)
115
- lus_attr_escape(ob, link + 7, link_size - 7);
116
- else lus_attr_escape(ob, link, link_size);
117
- BUFPUTSL(ob, "</a>");
118
- }
119
-
120
- static int
121
- rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque)
122
- {
123
- struct xhtml_renderopt *options = opaque;
124
-
125
- if (!link || !link->size)
126
- return 0;
127
-
128
- if ((options->flags & XHTML_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
129
- return 0;
130
-
131
- rndr_autolink2(ob, link->data, link->size, type);
132
- return 1;
133
- }
134
-
135
- static void
136
- rndr_blockcode(struct buf *ob, struct buf *text, void *opaque)
137
- {
138
- if (ob->size) bufputc(ob, '\n');
139
- BUFPUTSL(ob, "<pre><code>");
140
- if (text) lus_attr_escape(ob, text->data, text->size);
141
- BUFPUTSL(ob, "</code></pre>\n");
142
- }
143
-
144
- static void
145
- rndr_blockquote(struct buf *ob, struct buf *text, void *opaque)
146
- {
147
- BUFPUTSL(ob, "<blockquote>\n");
148
- if (text) bufput(ob, text->data, text->size);
149
- BUFPUTSL(ob, "</blockquote>");
150
- }
151
-
152
- static int
153
- rndr_codespan(struct buf *ob, struct buf *text, void *opaque)
154
- {
155
- BUFPUTSL(ob, "<code>");
156
- if (text) lus_attr_escape(ob, text->data, text->size);
157
- BUFPUTSL(ob, "</code>");
158
- return 1;
159
- }
160
-
161
- static int
162
- rndr_double_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
163
- {
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
-
182
- return 1;
183
- }
184
-
185
- static int
186
- rndr_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
187
- {
188
- if (!text || !text->size || c == '~') return 0;
189
- BUFPUTSL(ob, "<em>");
190
- if (text) bufput(ob, text->data, text->size);
191
- BUFPUTSL(ob, "</em>");
192
- return 1;
193
- }
194
-
195
- static void
196
- rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)
197
- {
198
- struct xhtml_renderopt *options = opaque;
199
-
200
- if (ob->size)
201
- bufputc(ob, '\n');
202
-
203
- if (options->flags & XHTML_TOC) {
204
- bufprintf(ob, "<a name=\"toc_%d\"></a>", options->toc_data.header_count++);
205
- }
206
-
207
- bufprintf(ob, "<h%d>", level);
208
- if (text) bufput(ob, text->data, text->size);
209
- bufprintf(ob, "</h%d>\n", level);
210
- }
211
-
212
- static int
213
- rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque)
214
- {
215
- struct xhtml_renderopt *options = opaque;
216
-
217
- if ((options->flags & XHTML_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
218
- return 0;
219
-
220
- BUFPUTSL(ob, "<a href=\"");
221
- if (link && link->size) lus_attr_escape(ob, link->data, link->size);
222
- if (title && title->size) {
223
- BUFPUTSL(ob, "\" title=\"");
224
- lus_attr_escape(ob, title->data, title->size); }
225
- BUFPUTSL(ob, "\">");
226
- if (content && content->size) bufput(ob, content->data, content->size);
227
- BUFPUTSL(ob, "</a>");
228
- return 1;
229
- }
230
-
231
- static void
232
- rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)
233
- {
234
- if (ob->size) bufputc(ob, '\n');
235
- bufput(ob, flags & MKD_LIST_ORDERED ? "<ol>\n" : "<ul>\n", 5);
236
- if (text) bufput(ob, text->data, text->size);
237
- bufput(ob, flags & MKD_LIST_ORDERED ? "</ol>\n" : "</ul>\n", 6);
238
- }
239
-
240
- static void
241
- rndr_listitem(struct buf *ob, struct buf *text, int flags, void *opaque)
242
- {
243
- BUFPUTSL(ob, "<li>");
244
- if (text) {
245
- while (text->size && text->data[text->size - 1] == '\n')
246
- text->size -= 1;
247
- bufput(ob, text->data, text->size); }
248
- BUFPUTSL(ob, "</li>\n");
249
- }
250
-
251
- static void
252
- rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
253
- {
254
- size_t i = 0;
255
-
256
- if (ob->size) bufputc(ob, '\n');
257
-
258
- if (!text || !text->size)
259
- return;
260
-
261
- while (i < text->size && isspace(text->data[i])) i++;
262
-
263
- if (i < text->size) {
264
- BUFPUTSL(ob, "<p>");
265
- bufput(ob, &text->data[i], text->size - i);
266
- BUFPUTSL(ob, "</p>\n");
267
- }
268
- }
269
-
270
- static void
271
- rndr_raw_block(struct buf *ob, struct buf *text, void *opaque)
272
- {
273
- size_t org, sz;
274
- if (!text) return;
275
- sz = text->size;
276
- while (sz > 0 && text->data[sz - 1] == '\n') sz -= 1;
277
- org = 0;
278
- while (org < sz && text->data[org] == '\n') org += 1;
279
- if (org >= sz) return;
280
- if (ob->size) bufputc(ob, '\n');
281
- bufput(ob, text->data + org, sz - org);
282
- bufputc(ob, '\n');
283
- }
284
-
285
- static int
286
- rndr_triple_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
287
- {
288
- if (!text || !text->size) return 0;
289
- BUFPUTSL(ob, "<strong><em>");
290
- bufput(ob, text->data, text->size);
291
- BUFPUTSL(ob, "</em></strong>");
292
- return 1;
293
- }
294
-
295
-
296
- /**********************
297
- * XHTML 1.0 RENDERER *
298
- **********************/
299
-
300
- static void
301
- rndr_hrule(struct buf *ob, void *opaque)
302
- {
303
- if (ob->size) bufputc(ob, '\n');
304
- BUFPUTSL(ob, "<hr />\n");
305
- }
306
-
307
- static int
308
- rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque)
309
- {
310
- if (!link || !link->size) return 0;
311
- BUFPUTSL(ob, "<img src=\"");
312
- lus_attr_escape(ob, link->data, link->size);
313
- BUFPUTSL(ob, "\" alt=\"");
314
- if (alt && alt->size)
315
- lus_attr_escape(ob, alt->data, alt->size);
316
- if (title && title->size) {
317
- BUFPUTSL(ob, "\" title=\"");
318
- lus_attr_escape(ob, title->data, title->size); }
319
- BUFPUTSL(ob, "\" />");
320
- return 1;
321
- }
322
-
323
- static int
324
- rndr_linebreak(struct buf *ob, void *opaque)
325
- {
326
- BUFPUTSL(ob, "<br />\n");
327
- return 1;
328
- }
329
-
330
- static int
331
- rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)
332
- {
333
- struct xhtml_renderopt *options = opaque;
334
- int escape_html = 0;
335
-
336
- if (options->flags & XHTML_SKIP_HTML)
337
- escape_html = 1;
338
-
339
- else if ((options->flags & XHTML_SKIP_STYLE) != 0 && is_html_tag(text, "<style>"))
340
- escape_html = 1;
341
-
342
- else if ((options->flags & XHTML_SKIP_LINKS) != 0 && is_html_tag(text, "<a>"))
343
- escape_html = 1;
344
-
345
- else if ((options->flags & XHTML_SKIP_IMAGES) != 0 && is_html_tag(text, "<img>"))
346
- escape_html = 1;
347
-
348
-
349
- if (escape_html)
350
- lus_attr_escape(ob, text->data, text->size);
351
- else
352
- bufput(ob, text->data, text->size);
353
-
354
- return 1;
355
- }
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
- }
406
-
407
- static struct {
408
- char c0;
409
- const char *pattern;
410
- const char *entity;
411
- int skip;
412
- } smartypants_subs[] = {
413
- { '\'', "'s>", "&rsquo;", 0 },
414
- { '\'', "'t>", "&rsquo;", 0 },
415
- { '\'', "'re>", "&rsquo;", 0 },
416
- { '\'', "'ll>", "&rsquo;", 0 },
417
- { '\'', "'ve>", "&rsquo;", 0 },
418
- { '\'', "'m>", "&rsquo;", 0 },
419
- { '\'', "'d>", "&rsquo;", 0 },
420
- { '-', "--", "&mdash;", 1 },
421
- { '-', "<->", "&ndash;", 0 },
422
- { '.', "...", "&hellip;", 2 },
423
- { '.', ". . .", "&hellip;", 4 },
424
- { '(', "(c)", "&copy;", 2 },
425
- { '(', "(r)", "&reg;", 2 },
426
- { '(', "(tm)", "&trade;", 3 },
427
- { '3', "<3/4>", "&frac34;", 2 },
428
- { '3', "<3/4ths>", "&frac34;", 2 },
429
- { '1', "<1/2>", "&frac12;", 2 },
430
- { '1', "<1/4>", "&frac14;", 2 },
431
- { '1', "<1/4th>", "&frac14;", 2 },
432
- { '&', "&#0;", 0, 3 },
433
- };
434
-
435
- #define SUBS_COUNT (sizeof(smartypants_subs) / sizeof(smartypants_subs[0]))
436
-
437
- static inline
438
- word_boundary(char c)
439
- {
440
- return isspace(c) || ispunct(c);
441
- }
442
-
443
- static int
444
- smartypants_cmpsub(const struct buf *buf, size_t start, const char *prefix)
445
- {
446
- size_t i;
447
-
448
- if (prefix[0] == '<') {
449
- if (start == 0 || !word_boundary(buf->data[start - 1]))
450
- return 0;
451
-
452
- prefix++;
453
- }
454
-
455
- for (i = start; i < buf->size; ++i) {
456
- char c, p;
457
-
458
- c = tolower(buf->data[i]);
459
- p = *prefix++;
460
-
461
- if (p == 0)
462
- return 1;
463
-
464
- if (p == '>')
465
- return word_boundary(c);
466
-
467
- if (c != p)
468
- return 0;
469
- }
470
-
471
- return (*prefix == '>');
472
- }
473
-
474
- static int
475
- smartypants_quotes(struct buf *ob, struct buf *text, size_t i, int is_open)
476
- {
477
- char ent[8];
478
-
479
- if (is_open && i + 1 < text->size && !word_boundary(text->data[i + 1]))
480
- return 0;
481
-
482
- if (!is_open && i > 0 && !word_boundary(text->data[i - 1]))
483
- return 0;
484
-
485
- snprintf(ent, sizeof(ent), "&%c%cquo;",
486
- is_open ? 'r' : 'l',
487
- text->data[i] == '\'' ? 's' : 'd');
488
-
489
- bufputs(ob, ent);
490
- return 1;
491
- }
492
-
493
- static void
494
- rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)
495
- {
496
- size_t i;
497
- int open_single = 0, open_double = 0, open_tag = 0;
498
- struct xhtml_renderopt *options = opaque;
499
-
500
- int autolink = (options->flags & XHTML_AUTOLINK);
501
- int smartypants = (options->flags & XHTML_SMARTYPANTS);
502
-
503
- if (!text)
504
- return;
505
-
506
- if (!autolink && !smartypants) {
507
- lus_attr_escape(ob, text->data, text->size);
508
- return;
509
- }
510
-
511
- for (i = 0; i < text->size; ++i) {
512
- size_t sub;
513
- char c = text->data[i];
514
-
515
- /*
516
- * Autolinking
517
- */
518
- if (autolink) {
519
- /* Autolinking is not standarized in the Markdown spec.
520
- * We only check for links immediately after a space */
521
- if ((i == 0 || isspace(text->data[i - 1])) &&
522
- is_safe_link(text->data + i, text->size - i)) {
523
- size_t j = i;
524
-
525
- while (j < text->size && !isspace(text->data[j]))
526
- j++;
527
-
528
- rndr_autolink2(ob, &text->data[i], j - i, MKDA_NORMAL);
529
- i = j - 1;
530
- continue;
531
- }
532
- }
533
-
534
- /*
535
- * Smartypants subsitutions
536
- */
537
- if (smartypants) {
538
- for (sub = 0; sub < SUBS_COUNT; ++sub) {
539
- if (c == smartypants_subs[sub].c0 &&
540
- smartypants_cmpsub(text, i, smartypants_subs[sub].pattern)) {
541
-
542
- if (smartypants_subs[sub].entity)
543
- bufputs(ob, smartypants_subs[sub].entity);
544
-
545
- i += smartypants_subs[sub].skip;
546
- break;
547
- }
548
- }
549
-
550
- if (sub < SUBS_COUNT)
551
- continue;
552
-
553
- switch (c) {
554
- case '<':
555
- open_tag = 1;
556
- break;
557
-
558
- case '>':
559
- open_tag = 0;
560
- break;
561
-
562
- #if 0
563
- /*
564
- * FIXME: this is bongos.
565
- *
566
- * The markdown spec defines that code blocks can be delimited
567
- * by more than one backtick, e.g.
568
- *
569
- * ``There is a literal backtick (`) here.``
570
- * <p><code>There is a literal backtick (`) here.</code></p>
571
- *
572
- * Obviously, there's no way to differentiate between the start
573
- * of a code block and the start of a quoted string for smartypants
574
- *
575
- * Look at this piece of Python code:
576
- *
577
- * ``result = ''.join(['this', 'is', 'bongos'])``
578
- *
579
- * This MD expression is clearly ambiguous since it can be parsed as:
580
- *
581
- * <p>&ldquo;result = &rdquo;.join ...</p>
582
- *
583
- * Or also as:
584
- *
585
- * <p><code>result = ''.join(['this', 'is', 'bongos'])</code></p>
586
- *
587
- * Fuck everything about this. This is temporarily disabled, because at GitHub
588
- * it's probably smarter to prioritize code blocks than pretty cutesy punctuation.
589
- *
590
- * The equivalent closing tag for the (``), ('') has also been disabled, because
591
- * it makes no sense to have closing tags without opening tags.
592
- */
593
- case '`':
594
- if (open_tag == 0) {
595
- if (i + 1 < text->size && text->data[i + 1] == '`') {
596
- BUFPUTSL(ob, "&ldquo;"); i++;
597
- continue;
598
- }
599
- }
600
- break;
601
- #endif
602
-
603
- case '\"':
604
- if (open_tag == 0) {
605
- if (smartypants_quotes(ob, text, i, open_double)) {
606
- open_double = !open_double;
607
- continue;
608
- }
609
- }
610
- break;
611
-
612
- case '\'':
613
- if (open_tag == 0) {
614
-
615
- #if 0 /* temporarily disabled, see previous comment */
616
- if (i + 1 < text->size && text->data[i + 1] == '\'') {
617
- BUFPUTSL(ob, "&rdquo;"); i++;
618
- continue;
619
- }
620
- #endif
621
-
622
- if (smartypants_quotes(ob, text, i, open_single)) {
623
- open_single = !open_single;
624
- continue;
625
- }
626
- }
627
- break;
628
- }
629
- }
630
-
631
- /*
632
- * Copy raw character
633
- */
634
- if (!put_scaped_char(ob, c))
635
- bufputc(ob, c);
636
- }
637
- }
638
-
639
- static void
640
- toc_header(struct buf *ob, struct buf *text, int level, void *opaque)
641
- {
642
- struct xhtml_renderopt *options = opaque;
643
-
644
- if (level > options->toc_data.current_level) {
645
- if (level > 1)
646
- BUFPUTSL(ob, "<li>");
647
- BUFPUTSL(ob, "<ul>\n");
648
- }
649
-
650
- if (level < options->toc_data.current_level) {
651
- BUFPUTSL(ob, "</ul>");
652
- if (options->toc_data.current_level > 1)
653
- BUFPUTSL(ob, "</li>\n");
654
- }
655
-
656
- options->toc_data.current_level = level;
657
-
658
- bufprintf(ob, "<li><a href=\"#toc_%d\">", options->toc_data.header_count++);
659
- if (text)
660
- bufput(ob, text->data, text->size);
661
- BUFPUTSL(ob, "</a></li>\n");
662
- }
663
-
664
- static void
665
- toc_finalize(struct buf *ob, void *opaque)
666
- {
667
- struct xhtml_renderopt *options = opaque;
668
-
669
- while (options->toc_data.current_level > 1) {
670
- BUFPUTSL(ob, "</ul></li>\n");
671
- options->toc_data.current_level--;
672
- }
673
-
674
- if (options->toc_data.current_level)
675
- BUFPUTSL(ob, "</ul>\n");
676
- }
677
-
678
- void
679
- init_toc_renderer(struct mkd_renderer *renderer)
680
- {
681
- static const struct mkd_renderer toc_render = {
682
- NULL,
683
- NULL,
684
- NULL,
685
- toc_header,
686
- NULL,
687
- NULL,
688
- NULL,
689
- NULL,
690
- NULL,
691
- NULL,
692
- NULL,
693
-
694
- rndr_autolink,
695
- rndr_codespan,
696
- rndr_double_emphasis,
697
- rndr_emphasis,
698
- rndr_image,
699
- rndr_linebreak,
700
- rndr_link,
701
- rndr_raw_html,
702
- rndr_triple_emphasis,
703
-
704
- NULL,
705
- NULL,
706
-
707
- NULL,
708
- toc_finalize,
709
-
710
- "*-~",
711
- NULL
712
- };
713
-
714
- struct xhtml_renderopt *options;
715
- options = calloc(1, sizeof(struct xhtml_renderopt));
716
- options->flags = XHTML_TOC;
717
-
718
- memcpy(renderer, &toc_render, sizeof(struct mkd_renderer));
719
- renderer->opaque = options;
720
- }
721
-
722
- void
723
- init_xhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags)
724
- {
725
- static const struct mkd_renderer renderer_default = {
726
- rndr_blockcode,
727
- rndr_blockquote,
728
- rndr_raw_block,
729
- rndr_header,
730
- rndr_hrule,
731
- rndr_list,
732
- rndr_listitem,
733
- rndr_paragraph,
734
- rndr_table,
735
- rndr_tablerow,
736
- rndr_tablecell,
737
-
738
- rndr_autolink,
739
- rndr_codespan,
740
- rndr_double_emphasis,
741
- rndr_emphasis,
742
- rndr_image,
743
- rndr_linebreak,
744
- rndr_link,
745
- rndr_raw_html,
746
- rndr_triple_emphasis,
747
-
748
- NULL,
749
- rndr_normal_text,
750
-
751
- NULL,
752
- NULL,
753
-
754
- "*_~",
755
- NULL
756
- };
757
-
758
- struct xhtml_renderopt *options;
759
- options = calloc(1, sizeof(struct xhtml_renderopt));
760
- options->flags = render_flags;
761
-
762
- memcpy(renderer, &renderer_default, sizeof(struct mkd_renderer));
763
- renderer->opaque = options;
764
-
765
- if (render_flags & XHTML_SKIP_IMAGES)
766
- renderer->image = NULL;
767
-
768
- if (render_flags & XHTML_SKIP_LINKS) {
769
- renderer->link = NULL;
770
- renderer->autolink = NULL;
771
- }
772
- }
773
-
774
- void
775
- free_renderer(struct mkd_renderer *renderer)
776
- {
777
- free(renderer->opaque);
778
- }
779
-