markly 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/markly +94 -0
- data/ext/markly/arena.c +103 -0
- data/ext/markly/autolink.c +425 -0
- data/ext/markly/autolink.h +8 -0
- data/ext/markly/blocks.c +1585 -0
- data/ext/markly/buffer.c +278 -0
- data/ext/markly/buffer.h +116 -0
- data/ext/markly/case_fold_switch.inc +4327 -0
- data/ext/markly/chunk.h +135 -0
- data/ext/markly/cmark-gfm-core-extensions.h +54 -0
- data/ext/markly/cmark-gfm-extension_api.h +736 -0
- data/ext/markly/cmark-gfm-extensions_export.h +42 -0
- data/ext/markly/cmark-gfm.h +817 -0
- data/ext/markly/cmark-gfm_export.h +42 -0
- data/ext/markly/cmark-gfm_version.h +7 -0
- data/ext/markly/cmark.c +55 -0
- data/ext/markly/cmark_ctype.c +44 -0
- data/ext/markly/cmark_ctype.h +33 -0
- data/ext/markly/commonmark.c +519 -0
- data/ext/markly/config.h +76 -0
- data/ext/markly/core-extensions.c +27 -0
- data/ext/markly/entities.inc +2138 -0
- data/ext/markly/ext_scanners.c +1159 -0
- data/ext/markly/ext_scanners.h +24 -0
- data/ext/markly/extconf.rb +7 -0
- data/ext/markly/footnotes.c +40 -0
- data/ext/markly/footnotes.h +25 -0
- data/ext/markly/houdini.h +57 -0
- data/ext/markly/houdini_href_e.c +100 -0
- data/ext/markly/houdini_html_e.c +66 -0
- data/ext/markly/houdini_html_u.c +149 -0
- data/ext/markly/html.c +465 -0
- data/ext/markly/html.h +27 -0
- data/ext/markly/inlines.c +1633 -0
- data/ext/markly/inlines.h +29 -0
- data/ext/markly/iterator.c +159 -0
- data/ext/markly/iterator.h +26 -0
- data/ext/markly/latex.c +466 -0
- data/ext/markly/linked_list.c +37 -0
- data/ext/markly/man.c +278 -0
- data/ext/markly/map.c +122 -0
- data/ext/markly/map.h +41 -0
- data/ext/markly/markly.c +1226 -0
- data/ext/markly/markly.h +16 -0
- data/ext/markly/node.c +979 -0
- data/ext/markly/node.h +118 -0
- data/ext/markly/parser.h +58 -0
- data/ext/markly/plaintext.c +235 -0
- data/ext/markly/plugin.c +36 -0
- data/ext/markly/plugin.h +34 -0
- data/ext/markly/references.c +42 -0
- data/ext/markly/references.h +26 -0
- data/ext/markly/registry.c +63 -0
- data/ext/markly/registry.h +24 -0
- data/ext/markly/render.c +205 -0
- data/ext/markly/render.h +62 -0
- data/ext/markly/scanners.c +20382 -0
- data/ext/markly/scanners.h +62 -0
- data/ext/markly/scanners.re +326 -0
- data/ext/markly/strikethrough.c +167 -0
- data/ext/markly/strikethrough.h +9 -0
- data/ext/markly/syntax_extension.c +149 -0
- data/ext/markly/syntax_extension.h +34 -0
- data/ext/markly/table.c +803 -0
- data/ext/markly/table.h +12 -0
- data/ext/markly/tagfilter.c +60 -0
- data/ext/markly/tagfilter.h +8 -0
- data/ext/markly/tasklist.c +156 -0
- data/ext/markly/tasklist.h +8 -0
- data/ext/markly/utf8.c +317 -0
- data/ext/markly/utf8.h +35 -0
- data/ext/markly/xml.c +181 -0
- data/lib/markly.rb +43 -0
- data/lib/markly/flags.rb +37 -0
- data/lib/markly/markly.so +0 -0
- data/lib/markly/node.rb +70 -0
- data/lib/markly/node/inspect.rb +59 -0
- data/lib/markly/renderer.rb +133 -0
- data/lib/markly/renderer/html_renderer.rb +252 -0
- data/lib/markly/version.rb +5 -0
- metadata +211 -0
data/ext/markly/node.h
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#ifndef CMARK_NODE_H
|
2
|
+
#define CMARK_NODE_H
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#include <stdio.h>
|
9
|
+
#include <stdint.h>
|
10
|
+
|
11
|
+
#include "cmark-gfm.h"
|
12
|
+
#include "cmark-gfm-extension_api.h"
|
13
|
+
#include "buffer.h"
|
14
|
+
#include "chunk.h"
|
15
|
+
|
16
|
+
typedef struct {
|
17
|
+
cmark_list_type list_type;
|
18
|
+
int marker_offset;
|
19
|
+
int padding;
|
20
|
+
int start;
|
21
|
+
cmark_delim_type delimiter;
|
22
|
+
unsigned char bullet_char;
|
23
|
+
bool tight;
|
24
|
+
bool checked; // For task list extension
|
25
|
+
} cmark_list;
|
26
|
+
|
27
|
+
typedef struct {
|
28
|
+
cmark_chunk info;
|
29
|
+
cmark_chunk literal;
|
30
|
+
uint8_t fence_length;
|
31
|
+
uint8_t fence_offset;
|
32
|
+
unsigned char fence_char;
|
33
|
+
int8_t fenced;
|
34
|
+
} cmark_code;
|
35
|
+
|
36
|
+
typedef struct {
|
37
|
+
int level;
|
38
|
+
bool setext;
|
39
|
+
} cmark_heading;
|
40
|
+
|
41
|
+
typedef struct {
|
42
|
+
cmark_chunk url;
|
43
|
+
cmark_chunk title;
|
44
|
+
} cmark_link;
|
45
|
+
|
46
|
+
typedef struct {
|
47
|
+
cmark_chunk on_enter;
|
48
|
+
cmark_chunk on_exit;
|
49
|
+
} cmark_custom;
|
50
|
+
|
51
|
+
enum cmark_node__internal_flags {
|
52
|
+
CMARK_NODE__OPEN = (1 << 0),
|
53
|
+
CMARK_NODE__LAST_LINE_BLANK = (1 << 1),
|
54
|
+
CMARK_NODE__LAST_LINE_CHECKED = (1 << 2),
|
55
|
+
};
|
56
|
+
|
57
|
+
struct cmark_node {
|
58
|
+
cmark_strbuf content;
|
59
|
+
|
60
|
+
struct cmark_node *next;
|
61
|
+
struct cmark_node *prev;
|
62
|
+
struct cmark_node *parent;
|
63
|
+
struct cmark_node *first_child;
|
64
|
+
struct cmark_node *last_child;
|
65
|
+
|
66
|
+
void *user_data;
|
67
|
+
cmark_free_func user_data_free_func;
|
68
|
+
|
69
|
+
int start_line;
|
70
|
+
int start_column;
|
71
|
+
int end_line;
|
72
|
+
int end_column;
|
73
|
+
int internal_offset;
|
74
|
+
uint16_t type;
|
75
|
+
uint16_t flags;
|
76
|
+
|
77
|
+
cmark_syntax_extension *extension;
|
78
|
+
|
79
|
+
union {
|
80
|
+
cmark_chunk literal;
|
81
|
+
cmark_list list;
|
82
|
+
cmark_code code;
|
83
|
+
cmark_heading heading;
|
84
|
+
cmark_link link;
|
85
|
+
cmark_custom custom;
|
86
|
+
int html_block_type;
|
87
|
+
void *opaque;
|
88
|
+
} as;
|
89
|
+
};
|
90
|
+
|
91
|
+
static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) {
|
92
|
+
return node->content.mem;
|
93
|
+
}
|
94
|
+
CMARK_GFM_EXPORT int cmark_node_check(cmark_node *node, FILE *out);
|
95
|
+
|
96
|
+
static CMARK_INLINE bool CMARK_NODE_TYPE_BLOCK_P(cmark_node_type node_type) {
|
97
|
+
return (node_type & CMARK_NODE_TYPE_MASK) == CMARK_NODE_TYPE_BLOCK;
|
98
|
+
}
|
99
|
+
|
100
|
+
static CMARK_INLINE bool CMARK_NODE_BLOCK_P(cmark_node *node) {
|
101
|
+
return node != NULL && CMARK_NODE_TYPE_BLOCK_P((cmark_node_type) node->type);
|
102
|
+
}
|
103
|
+
|
104
|
+
static CMARK_INLINE bool CMARK_NODE_TYPE_INLINE_P(cmark_node_type node_type) {
|
105
|
+
return (node_type & CMARK_NODE_TYPE_MASK) == CMARK_NODE_TYPE_INLINE;
|
106
|
+
}
|
107
|
+
|
108
|
+
static CMARK_INLINE bool CMARK_NODE_INLINE_P(cmark_node *node) {
|
109
|
+
return node != NULL && CMARK_NODE_TYPE_INLINE_P((cmark_node_type) node->type);
|
110
|
+
}
|
111
|
+
|
112
|
+
CMARK_GFM_EXPORT bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type);
|
113
|
+
|
114
|
+
#ifdef __cplusplus
|
115
|
+
}
|
116
|
+
#endif
|
117
|
+
|
118
|
+
#endif
|
data/ext/markly/parser.h
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#ifndef CMARK_PARSER_H
|
2
|
+
#define CMARK_PARSER_H
|
3
|
+
|
4
|
+
#include <stdio.h>
|
5
|
+
#include "references.h"
|
6
|
+
#include "node.h"
|
7
|
+
#include "buffer.h"
|
8
|
+
|
9
|
+
#ifdef __cplusplus
|
10
|
+
extern "C" {
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#define MAX_LINK_LABEL_LENGTH 1000
|
14
|
+
|
15
|
+
struct cmark_parser {
|
16
|
+
struct cmark_mem *mem;
|
17
|
+
/* A hashtable of urls in the current document for cross-references */
|
18
|
+
struct cmark_map *refmap;
|
19
|
+
/* The root node of the parser, always a CMARK_NODE_DOCUMENT */
|
20
|
+
struct cmark_node *root;
|
21
|
+
/* The last open block after a line is fully processed */
|
22
|
+
struct cmark_node *current;
|
23
|
+
/* See the documentation for cmark_parser_get_line_number() in cmark.h */
|
24
|
+
int line_number;
|
25
|
+
/* See the documentation for cmark_parser_get_offset() in cmark.h */
|
26
|
+
bufsize_t offset;
|
27
|
+
/* See the documentation for cmark_parser_get_column() in cmark.h */
|
28
|
+
bufsize_t column;
|
29
|
+
/* See the documentation for cmark_parser_get_first_nonspace() in cmark.h */
|
30
|
+
bufsize_t first_nonspace;
|
31
|
+
/* See the documentation for cmark_parser_get_first_nonspace_column() in cmark.h */
|
32
|
+
bufsize_t first_nonspace_column;
|
33
|
+
bufsize_t thematic_break_kill_pos;
|
34
|
+
/* See the documentation for cmark_parser_get_indent() in cmark.h */
|
35
|
+
int indent;
|
36
|
+
/* See the documentation for cmark_parser_is_blank() in cmark.h */
|
37
|
+
bool blank;
|
38
|
+
/* See the documentation for cmark_parser_has_partially_consumed_tab() in cmark.h */
|
39
|
+
bool partially_consumed_tab;
|
40
|
+
/* Contains the currently processed line */
|
41
|
+
cmark_strbuf curline;
|
42
|
+
/* See the documentation for cmark_parser_get_last_line_length() in cmark.h */
|
43
|
+
bufsize_t last_line_length;
|
44
|
+
/* FIXME: not sure about the difference with curline */
|
45
|
+
cmark_strbuf linebuf;
|
46
|
+
/* Options set by the user, see the Options section in cmark.h */
|
47
|
+
int options;
|
48
|
+
bool last_buffer_ended_with_cr;
|
49
|
+
cmark_llist *syntax_extensions;
|
50
|
+
cmark_llist *inline_syntax_extensions;
|
51
|
+
cmark_ispunct_func backslash_ispunct;
|
52
|
+
};
|
53
|
+
|
54
|
+
#ifdef __cplusplus
|
55
|
+
}
|
56
|
+
#endif
|
57
|
+
|
58
|
+
#endif
|
@@ -0,0 +1,235 @@
|
|
1
|
+
#include "node.h"
|
2
|
+
#include "syntax_extension.h"
|
3
|
+
#include "render.h"
|
4
|
+
|
5
|
+
#define OUT(s, wrap, escaping) renderer->out(renderer, node, s, wrap, escaping)
|
6
|
+
#define LIT(s) renderer->out(renderer, node, s, false, LITERAL)
|
7
|
+
#define CR() renderer->cr(renderer)
|
8
|
+
#define BLANKLINE() renderer->blankline(renderer)
|
9
|
+
#define LISTMARKER_SIZE 20
|
10
|
+
|
11
|
+
// Functions to convert cmark_nodes to plain text strings.
|
12
|
+
|
13
|
+
static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_node *node,
|
14
|
+
cmark_escaping escape,
|
15
|
+
int32_t c, unsigned char nextc) {
|
16
|
+
cmark_render_code_point(renderer, c);
|
17
|
+
}
|
18
|
+
|
19
|
+
// if node is a block node, returns node.
|
20
|
+
// otherwise returns first block-level node that is an ancestor of node.
|
21
|
+
// if there is no block-level ancestor, returns NULL.
|
22
|
+
static cmark_node *get_containing_block(cmark_node *node) {
|
23
|
+
while (node) {
|
24
|
+
if (CMARK_NODE_BLOCK_P(node)) {
|
25
|
+
return node;
|
26
|
+
} else {
|
27
|
+
node = node->parent;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
return NULL;
|
31
|
+
}
|
32
|
+
|
33
|
+
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
34
|
+
cmark_event_type ev_type, int options) {
|
35
|
+
cmark_node *tmp;
|
36
|
+
int list_number;
|
37
|
+
cmark_delim_type list_delim;
|
38
|
+
int i;
|
39
|
+
bool entering = (ev_type == CMARK_EVENT_ENTER);
|
40
|
+
char listmarker[LISTMARKER_SIZE];
|
41
|
+
bool first_in_list_item;
|
42
|
+
bufsize_t marker_width;
|
43
|
+
bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options) &&
|
44
|
+
!(CMARK_OPT_HARDBREAKS & options);
|
45
|
+
|
46
|
+
// Don't adjust tight list status til we've started the list.
|
47
|
+
// Otherwise we loose the blank line between a paragraph and
|
48
|
+
// a following list.
|
49
|
+
if (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) {
|
50
|
+
tmp = get_containing_block(node);
|
51
|
+
renderer->in_tight_list_item =
|
52
|
+
tmp && // tmp might be NULL if there is no containing block
|
53
|
+
((tmp->type == CMARK_NODE_ITEM &&
|
54
|
+
cmark_node_get_list_tight(tmp->parent)) ||
|
55
|
+
(tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
|
56
|
+
cmark_node_get_list_tight(tmp->parent->parent)));
|
57
|
+
}
|
58
|
+
|
59
|
+
if (node->extension && node->extension->plaintext_render_func) {
|
60
|
+
node->extension->plaintext_render_func(node->extension, renderer, node, ev_type, options);
|
61
|
+
return 1;
|
62
|
+
}
|
63
|
+
|
64
|
+
switch (node->type) {
|
65
|
+
case CMARK_NODE_DOCUMENT:
|
66
|
+
break;
|
67
|
+
|
68
|
+
case CMARK_NODE_BLOCK_QUOTE:
|
69
|
+
break;
|
70
|
+
|
71
|
+
case CMARK_NODE_LIST:
|
72
|
+
if (!entering && node->next && (node->next->type == CMARK_NODE_CODE_BLOCK ||
|
73
|
+
node->next->type == CMARK_NODE_LIST)) {
|
74
|
+
CR();
|
75
|
+
}
|
76
|
+
break;
|
77
|
+
|
78
|
+
case CMARK_NODE_ITEM:
|
79
|
+
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
|
80
|
+
marker_width = 4;
|
81
|
+
} else {
|
82
|
+
list_number = cmark_node_get_list_start(node->parent);
|
83
|
+
list_delim = cmark_node_get_list_delim(node->parent);
|
84
|
+
tmp = node;
|
85
|
+
while (tmp->prev) {
|
86
|
+
tmp = tmp->prev;
|
87
|
+
list_number += 1;
|
88
|
+
}
|
89
|
+
// we ensure a width of at least 4 so
|
90
|
+
// we get nice transition from single digits
|
91
|
+
// to double
|
92
|
+
snprintf(listmarker, LISTMARKER_SIZE, "%d%s%s", list_number,
|
93
|
+
list_delim == CMARK_PAREN_DELIM ? ")" : ".",
|
94
|
+
list_number < 10 ? " " : " ");
|
95
|
+
marker_width = (bufsize_t)strlen(listmarker);
|
96
|
+
}
|
97
|
+
if (entering) {
|
98
|
+
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
|
99
|
+
LIT(" - ");
|
100
|
+
renderer->begin_content = true;
|
101
|
+
} else {
|
102
|
+
LIT(listmarker);
|
103
|
+
renderer->begin_content = true;
|
104
|
+
}
|
105
|
+
for (i = marker_width; i--;) {
|
106
|
+
cmark_strbuf_putc(renderer->prefix, ' ');
|
107
|
+
}
|
108
|
+
} else {
|
109
|
+
cmark_strbuf_truncate(renderer->prefix,
|
110
|
+
renderer->prefix->size - marker_width);
|
111
|
+
CR();
|
112
|
+
}
|
113
|
+
break;
|
114
|
+
|
115
|
+
case CMARK_NODE_HEADING:
|
116
|
+
if (entering) {
|
117
|
+
renderer->begin_content = true;
|
118
|
+
renderer->no_linebreaks = true;
|
119
|
+
} else {
|
120
|
+
renderer->no_linebreaks = false;
|
121
|
+
BLANKLINE();
|
122
|
+
}
|
123
|
+
break;
|
124
|
+
|
125
|
+
case CMARK_NODE_CODE_BLOCK:
|
126
|
+
first_in_list_item = node->prev == NULL && node->parent &&
|
127
|
+
node->parent->type == CMARK_NODE_ITEM;
|
128
|
+
|
129
|
+
if (!first_in_list_item) {
|
130
|
+
BLANKLINE();
|
131
|
+
}
|
132
|
+
OUT(cmark_node_get_literal(node), false, LITERAL);
|
133
|
+
BLANKLINE();
|
134
|
+
break;
|
135
|
+
|
136
|
+
case CMARK_NODE_HTML_BLOCK:
|
137
|
+
break;
|
138
|
+
|
139
|
+
case CMARK_NODE_CUSTOM_BLOCK:
|
140
|
+
break;
|
141
|
+
|
142
|
+
case CMARK_NODE_THEMATIC_BREAK:
|
143
|
+
BLANKLINE();
|
144
|
+
break;
|
145
|
+
|
146
|
+
case CMARK_NODE_PARAGRAPH:
|
147
|
+
if (!entering) {
|
148
|
+
BLANKLINE();
|
149
|
+
}
|
150
|
+
break;
|
151
|
+
|
152
|
+
case CMARK_NODE_TEXT:
|
153
|
+
OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
|
154
|
+
break;
|
155
|
+
|
156
|
+
case CMARK_NODE_LINEBREAK:
|
157
|
+
CR();
|
158
|
+
break;
|
159
|
+
|
160
|
+
case CMARK_NODE_SOFTBREAK:
|
161
|
+
if (CMARK_OPT_HARDBREAKS & options) {
|
162
|
+
CR();
|
163
|
+
} else if (!renderer->no_linebreaks && renderer->width == 0 &&
|
164
|
+
!(CMARK_OPT_HARDBREAKS & options) &&
|
165
|
+
!(CMARK_OPT_NOBREAKS & options)) {
|
166
|
+
CR();
|
167
|
+
} else {
|
168
|
+
OUT(" ", allow_wrap, LITERAL);
|
169
|
+
}
|
170
|
+
break;
|
171
|
+
|
172
|
+
case CMARK_NODE_CODE:
|
173
|
+
OUT(cmark_node_get_literal(node), allow_wrap, LITERAL);
|
174
|
+
break;
|
175
|
+
|
176
|
+
case CMARK_NODE_HTML_INLINE:
|
177
|
+
break;
|
178
|
+
|
179
|
+
case CMARK_NODE_CUSTOM_INLINE:
|
180
|
+
break;
|
181
|
+
|
182
|
+
case CMARK_NODE_STRONG:
|
183
|
+
break;
|
184
|
+
|
185
|
+
case CMARK_NODE_EMPH:
|
186
|
+
break;
|
187
|
+
|
188
|
+
case CMARK_NODE_LINK:
|
189
|
+
break;
|
190
|
+
|
191
|
+
case CMARK_NODE_IMAGE:
|
192
|
+
break;
|
193
|
+
|
194
|
+
case CMARK_NODE_FOOTNOTE_REFERENCE:
|
195
|
+
if (entering) {
|
196
|
+
LIT("[^");
|
197
|
+
OUT(cmark_chunk_to_cstr(renderer->mem, &node->as.literal), false, LITERAL);
|
198
|
+
LIT("]");
|
199
|
+
}
|
200
|
+
break;
|
201
|
+
|
202
|
+
case CMARK_NODE_FOOTNOTE_DEFINITION:
|
203
|
+
if (entering) {
|
204
|
+
renderer->footnote_ix += 1;
|
205
|
+
LIT("[^");
|
206
|
+
char n[32];
|
207
|
+
snprintf(n, sizeof(n), "%d", renderer->footnote_ix);
|
208
|
+
OUT(n, false, LITERAL);
|
209
|
+
LIT("]: ");
|
210
|
+
|
211
|
+
cmark_strbuf_puts(renderer->prefix, " ");
|
212
|
+
} else {
|
213
|
+
cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4);
|
214
|
+
}
|
215
|
+
break;
|
216
|
+
default:
|
217
|
+
assert(false);
|
218
|
+
break;
|
219
|
+
}
|
220
|
+
|
221
|
+
return 1;
|
222
|
+
}
|
223
|
+
|
224
|
+
char *cmark_render_plaintext(cmark_node *root, int options, int width) {
|
225
|
+
return cmark_render_plaintext_with_mem(root, options, width, cmark_node_mem(root));
|
226
|
+
}
|
227
|
+
|
228
|
+
char *cmark_render_plaintext_with_mem(cmark_node *root, int options, int width, cmark_mem *mem) {
|
229
|
+
if (options & CMARK_OPT_HARDBREAKS) {
|
230
|
+
// disable breaking on width, since it has
|
231
|
+
// a different meaning with OPT_HARDBREAKS
|
232
|
+
width = 0;
|
233
|
+
}
|
234
|
+
return cmark_render(mem, root, options, width, outc, S_render_node);
|
235
|
+
}
|
data/ext/markly/plugin.c
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
|
3
|
+
#include "plugin.h"
|
4
|
+
|
5
|
+
extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
|
6
|
+
|
7
|
+
int cmark_plugin_register_syntax_extension(cmark_plugin * plugin,
|
8
|
+
cmark_syntax_extension * extension) {
|
9
|
+
plugin->syntax_extensions = cmark_llist_append(&CMARK_DEFAULT_MEM_ALLOCATOR, plugin->syntax_extensions, extension);
|
10
|
+
return 1;
|
11
|
+
}
|
12
|
+
|
13
|
+
cmark_plugin *
|
14
|
+
cmark_plugin_new(void) {
|
15
|
+
cmark_plugin *res = (cmark_plugin *) CMARK_DEFAULT_MEM_ALLOCATOR.calloc(1, sizeof(cmark_plugin));
|
16
|
+
|
17
|
+
res->syntax_extensions = NULL;
|
18
|
+
|
19
|
+
return res;
|
20
|
+
}
|
21
|
+
|
22
|
+
void
|
23
|
+
cmark_plugin_free(cmark_plugin *plugin) {
|
24
|
+
cmark_llist_free_full(&CMARK_DEFAULT_MEM_ALLOCATOR,
|
25
|
+
plugin->syntax_extensions,
|
26
|
+
(cmark_free_func) cmark_syntax_extension_free);
|
27
|
+
CMARK_DEFAULT_MEM_ALLOCATOR.free(plugin);
|
28
|
+
}
|
29
|
+
|
30
|
+
cmark_llist *
|
31
|
+
cmark_plugin_steal_syntax_extensions(cmark_plugin *plugin) {
|
32
|
+
cmark_llist *res = plugin->syntax_extensions;
|
33
|
+
|
34
|
+
plugin->syntax_extensions = NULL;
|
35
|
+
return res;
|
36
|
+
}
|