markly 0.6.1 → 0.8.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/conduct.md +133 -0
- data/ext/markly/arena.c +9 -8
- data/ext/markly/autolink.c +217 -134
- data/ext/markly/blocks.c +40 -4
- data/ext/markly/cmark-gfm-core-extensions.h +11 -11
- data/ext/markly/cmark-gfm-extension_api.h +1 -0
- data/ext/markly/cmark-gfm.h +18 -2
- data/ext/markly/cmark-gfm_version.h +2 -2
- data/ext/markly/cmark.c +3 -3
- data/ext/markly/commonmark.c +33 -38
- data/ext/markly/ext_scanners.c +360 -640
- data/ext/markly/extconf.rb +8 -1
- data/ext/markly/footnotes.c +23 -0
- data/ext/markly/footnotes.h +2 -0
- data/ext/markly/html.c +60 -23
- data/ext/markly/inlines.c +216 -61
- data/ext/markly/latex.c +6 -4
- data/ext/markly/man.c +7 -11
- data/ext/markly/map.c +11 -4
- data/ext/markly/map.h +5 -2
- data/ext/markly/markly.c +582 -586
- data/ext/markly/markly.h +1 -1
- data/ext/markly/node.c +76 -10
- data/ext/markly/node.h +49 -1
- data/ext/markly/parser.h +1 -0
- data/ext/markly/plaintext.c +12 -29
- data/ext/markly/references.c +1 -0
- data/ext/markly/render.c +15 -7
- data/ext/markly/scanners.c +13916 -20242
- data/ext/markly/scanners.h +8 -0
- data/ext/markly/scanners.re +47 -8
- data/ext/markly/strikethrough.c +1 -1
- data/ext/markly/table.c +143 -74
- data/ext/markly/xml.c +2 -1
- data/lib/markly/flags.rb +16 -0
- data/lib/markly/node/inspect.rb +59 -53
- data/lib/markly/node.rb +125 -58
- data/lib/markly/renderer/generic.rb +136 -0
- data/lib/markly/renderer/html.rb +301 -0
- data/lib/markly/version.rb +7 -1
- data/lib/markly.rb +38 -32
- data/license.md +39 -0
- data/readme.md +36 -0
- data.tar.gz.sig +0 -0
- metadata +63 -31
- metadata.gz.sig +0 -0
- data/bin/markly +0 -94
- data/lib/markly/markly.so +0 -0
- data/lib/markly/renderer/html_renderer.rb +0 -281
- data/lib/markly/renderer.rb +0 -133
data/ext/markly/markly.h
CHANGED
data/ext/markly/node.c
CHANGED
@@ -5,10 +5,42 @@
|
|
5
5
|
#include "node.h"
|
6
6
|
#include "syntax_extension.h"
|
7
7
|
|
8
|
+
/**
|
9
|
+
* Expensive safety checks are off by default, but can be enabled
|
10
|
+
* by calling cmark_enable_safety_checks().
|
11
|
+
*/
|
12
|
+
static bool enable_safety_checks = false;
|
13
|
+
|
14
|
+
void cmark_enable_safety_checks(bool enable) {
|
15
|
+
enable_safety_checks = enable;
|
16
|
+
}
|
17
|
+
|
8
18
|
static void S_node_unlink(cmark_node *node);
|
9
19
|
|
10
20
|
#define NODE_MEM(node) cmark_node_mem(node)
|
11
21
|
|
22
|
+
void cmark_register_node_flag(cmark_node_internal_flags *flags) {
|
23
|
+
static cmark_node_internal_flags nextflag = CMARK_NODE__REGISTER_FIRST;
|
24
|
+
|
25
|
+
// flags should be a pointer to a global variable and this function
|
26
|
+
// should only be called once to initialize its value.
|
27
|
+
if (*flags) {
|
28
|
+
fprintf(stderr, "flag initialization error in cmark_register_node_flag\n");
|
29
|
+
abort();
|
30
|
+
}
|
31
|
+
|
32
|
+
// Check that we haven't run out of bits.
|
33
|
+
if (nextflag == 0) {
|
34
|
+
fprintf(stderr, "too many flags in cmark_register_node_flag\n");
|
35
|
+
abort();
|
36
|
+
}
|
37
|
+
|
38
|
+
*flags = nextflag;
|
39
|
+
nextflag <<= 1;
|
40
|
+
}
|
41
|
+
|
42
|
+
void cmark_init_standard_node_flags(void) {}
|
43
|
+
|
12
44
|
bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
|
13
45
|
if (child_type == CMARK_NODE_DOCUMENT) {
|
14
46
|
return false;
|
@@ -48,8 +80,6 @@ bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
|
|
48
80
|
}
|
49
81
|
|
50
82
|
static bool S_can_contain(cmark_node *node, cmark_node *child) {
|
51
|
-
cmark_node *cur;
|
52
|
-
|
53
83
|
if (node == NULL || child == NULL) {
|
54
84
|
return false;
|
55
85
|
}
|
@@ -57,14 +87,16 @@ static bool S_can_contain(cmark_node *node, cmark_node *child) {
|
|
57
87
|
return 0;
|
58
88
|
}
|
59
89
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
90
|
+
if (enable_safety_checks) {
|
91
|
+
// Verify that child is not an ancestor of node or equal to node.
|
92
|
+
cmark_node *cur = node;
|
93
|
+
do {
|
94
|
+
if (cur == child) {
|
95
|
+
return false;
|
96
|
+
}
|
97
|
+
cur = cur->parent;
|
98
|
+
} while (cur != NULL);
|
99
|
+
}
|
68
100
|
|
69
101
|
return cmark_node_can_contain_type(node, (cmark_node_type) child->type);
|
70
102
|
}
|
@@ -301,6 +333,14 @@ cmark_node *cmark_node_last_child(cmark_node *node) {
|
|
301
333
|
}
|
302
334
|
}
|
303
335
|
|
336
|
+
cmark_node *cmark_node_parent_footnote_def(cmark_node *node) {
|
337
|
+
if (node == NULL) {
|
338
|
+
return NULL;
|
339
|
+
} else {
|
340
|
+
return node->parent_footnote_def;
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
304
344
|
void *cmark_node_get_user_data(cmark_node *node) {
|
305
345
|
if (node == NULL) {
|
306
346
|
return NULL;
|
@@ -337,6 +377,7 @@ const char *cmark_node_get_literal(cmark_node *node) {
|
|
337
377
|
case CMARK_NODE_HTML_INLINE:
|
338
378
|
case CMARK_NODE_CODE:
|
339
379
|
case CMARK_NODE_FOOTNOTE_REFERENCE:
|
380
|
+
case CMARK_NODE_FOOTNOTE_DEFINITION:
|
340
381
|
return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);
|
341
382
|
|
342
383
|
case CMARK_NODE_CODE_BLOCK:
|
@@ -524,6 +565,31 @@ int cmark_node_set_list_tight(cmark_node *node, int tight) {
|
|
524
565
|
}
|
525
566
|
}
|
526
567
|
|
568
|
+
int cmark_node_get_item_index(cmark_node *node) {
|
569
|
+
if (node == NULL) {
|
570
|
+
return 0;
|
571
|
+
}
|
572
|
+
|
573
|
+
if (node->type == CMARK_NODE_ITEM) {
|
574
|
+
return node->as.list.start;
|
575
|
+
} else {
|
576
|
+
return 0;
|
577
|
+
}
|
578
|
+
}
|
579
|
+
|
580
|
+
int cmark_node_set_item_index(cmark_node *node, int idx) {
|
581
|
+
if (node == NULL || idx < 0) {
|
582
|
+
return 0;
|
583
|
+
}
|
584
|
+
|
585
|
+
if (node->type == CMARK_NODE_ITEM) {
|
586
|
+
node->as.list.start = idx;
|
587
|
+
return 1;
|
588
|
+
} else {
|
589
|
+
return 0;
|
590
|
+
}
|
591
|
+
}
|
592
|
+
|
527
593
|
const char *cmark_node_get_fence_info(cmark_node *node) {
|
528
594
|
if (node == NULL) {
|
529
595
|
return NULL;
|
data/ext/markly/node.h
CHANGED
@@ -52,8 +52,14 @@ enum cmark_node__internal_flags {
|
|
52
52
|
CMARK_NODE__OPEN = (1 << 0),
|
53
53
|
CMARK_NODE__LAST_LINE_BLANK = (1 << 1),
|
54
54
|
CMARK_NODE__LAST_LINE_CHECKED = (1 << 2),
|
55
|
+
|
56
|
+
// Extensions can register custom flags by calling `cmark_register_node_flag`.
|
57
|
+
// This is the starting value for the custom flags.
|
58
|
+
CMARK_NODE__REGISTER_FIRST = (1 << 3),
|
55
59
|
};
|
56
60
|
|
61
|
+
typedef uint16_t cmark_node_internal_flags;
|
62
|
+
|
57
63
|
struct cmark_node {
|
58
64
|
cmark_strbuf content;
|
59
65
|
|
@@ -72,10 +78,25 @@ struct cmark_node {
|
|
72
78
|
int end_column;
|
73
79
|
int internal_offset;
|
74
80
|
uint16_t type;
|
75
|
-
|
81
|
+
cmark_node_internal_flags flags;
|
76
82
|
|
77
83
|
cmark_syntax_extension *extension;
|
78
84
|
|
85
|
+
/**
|
86
|
+
* Used during cmark_render() to cache the most recent non-NULL
|
87
|
+
* extension, if you go up the parent chain like this:
|
88
|
+
*
|
89
|
+
* node->parent->...parent->extension
|
90
|
+
*/
|
91
|
+
cmark_syntax_extension *ancestor_extension;
|
92
|
+
|
93
|
+
union {
|
94
|
+
int ref_ix;
|
95
|
+
int def_count;
|
96
|
+
} footnote;
|
97
|
+
|
98
|
+
cmark_node *parent_footnote_def;
|
99
|
+
|
79
100
|
union {
|
80
101
|
cmark_chunk literal;
|
81
102
|
cmark_list list;
|
@@ -88,6 +109,26 @@ struct cmark_node {
|
|
88
109
|
} as;
|
89
110
|
};
|
90
111
|
|
112
|
+
/**
|
113
|
+
* Syntax extensions can use this function to register a custom node
|
114
|
+
* flag. The flags are stored in the `flags` field of the `cmark_node`
|
115
|
+
* struct. The `flags` parameter should be the address of a global variable
|
116
|
+
* which will store the flag value.
|
117
|
+
*/
|
118
|
+
CMARK_GFM_EXPORT
|
119
|
+
void cmark_register_node_flag(cmark_node_internal_flags *flags);
|
120
|
+
|
121
|
+
/**
|
122
|
+
* DEPRECATED.
|
123
|
+
*
|
124
|
+
* This function was added in cmark-gfm version 0.29.0.gfm.7, and was
|
125
|
+
* required to be called at program start time, which caused
|
126
|
+
* backwards-compatibility issues in applications that use cmark-gfm as a
|
127
|
+
* library. It is now a no-op.
|
128
|
+
*/
|
129
|
+
CMARK_GFM_EXPORT
|
130
|
+
void cmark_init_standard_node_flags(void);
|
131
|
+
|
91
132
|
static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) {
|
92
133
|
return node->content.mem;
|
93
134
|
}
|
@@ -111,6 +152,13 @@ static CMARK_INLINE bool CMARK_NODE_INLINE_P(cmark_node *node) {
|
|
111
152
|
|
112
153
|
CMARK_GFM_EXPORT bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type);
|
113
154
|
|
155
|
+
/**
|
156
|
+
* Enable (or disable) extra safety checks. These extra checks cause
|
157
|
+
* extra performance overhead (in some cases quadratic), so they are only
|
158
|
+
* intended to be used during testing.
|
159
|
+
*/
|
160
|
+
CMARK_GFM_EXPORT void cmark_enable_safety_checks(bool enable);
|
161
|
+
|
114
162
|
#ifdef __cplusplus
|
115
163
|
}
|
116
164
|
#endif
|
data/ext/markly/parser.h
CHANGED
@@ -46,6 +46,7 @@ struct cmark_parser {
|
|
46
46
|
/* Options set by the user, see the Options section in cmark.h */
|
47
47
|
int options;
|
48
48
|
bool last_buffer_ended_with_cr;
|
49
|
+
size_t total_size;
|
49
50
|
cmark_llist *syntax_extensions;
|
50
51
|
cmark_llist *inline_syntax_extensions;
|
51
52
|
cmark_ispunct_func backslash_ispunct;
|
data/ext/markly/plaintext.c
CHANGED
@@ -16,23 +16,8 @@ static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_node *node,
|
|
16
16
|
cmark_render_code_point(renderer, c);
|
17
17
|
}
|
18
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
19
|
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
34
20
|
cmark_event_type ev_type, int options) {
|
35
|
-
cmark_node *tmp;
|
36
21
|
int list_number;
|
37
22
|
cmark_delim_type list_delim;
|
38
23
|
int i;
|
@@ -46,14 +31,17 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
46
31
|
// Don't adjust tight list status til we've started the list.
|
47
32
|
// Otherwise we loose the blank line between a paragraph and
|
48
33
|
// a following list.
|
49
|
-
if (
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
34
|
+
if (entering) {
|
35
|
+
if (node->parent && node->parent->type == CMARK_NODE_ITEM) {
|
36
|
+
renderer->in_tight_list_item = node->parent->parent->as.list.tight;
|
37
|
+
}
|
38
|
+
} else {
|
39
|
+
if (node->type == CMARK_NODE_LIST) {
|
40
|
+
renderer->in_tight_list_item =
|
41
|
+
node->parent &&
|
42
|
+
node->parent->type == CMARK_NODE_ITEM &&
|
43
|
+
node->parent->parent->as.list.tight;
|
44
|
+
}
|
57
45
|
}
|
58
46
|
|
59
47
|
if (node->extension && node->extension->plaintext_render_func) {
|
@@ -79,13 +67,8 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
79
67
|
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
|
80
68
|
marker_width = 4;
|
81
69
|
} else {
|
82
|
-
list_number =
|
70
|
+
list_number = cmark_node_get_item_index(node);
|
83
71
|
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
72
|
// we ensure a width of at least 4 so
|
90
73
|
// we get nice transition from single digits
|
91
74
|
// to double
|
data/ext/markly/references.c
CHANGED
@@ -32,6 +32,7 @@ void cmark_reference_create(cmark_map *map, cmark_chunk *label,
|
|
32
32
|
ref->title = cmark_clean_title(map->mem, title);
|
33
33
|
ref->entry.age = map->size;
|
34
34
|
ref->entry.next = map->refs;
|
35
|
+
ref->entry.size = ref->url.len + ref->title.len;
|
35
36
|
|
36
37
|
map->refs = (cmark_map_entry *)ref;
|
37
38
|
map->size++;
|
data/ext/markly/render.c
CHANGED
@@ -31,13 +31,7 @@ static void S_out(cmark_renderer *renderer, cmark_node *node,
|
|
31
31
|
cmark_chunk remainder = cmark_chunk_literal("");
|
32
32
|
int k = renderer->buffer->size - 1;
|
33
33
|
|
34
|
-
cmark_syntax_extension *ext =
|
35
|
-
cmark_node *n = node;
|
36
|
-
while (n && !ext) {
|
37
|
-
ext = n->extension;
|
38
|
-
if (!ext)
|
39
|
-
n = n->parent;
|
40
|
-
}
|
34
|
+
cmark_syntax_extension *ext = node->ancestor_extension;
|
41
35
|
if (ext && !ext->commonmark_escape_func)
|
42
36
|
ext = NULL;
|
43
37
|
|
@@ -182,6 +176,20 @@ char *cmark_render(cmark_mem *mem, cmark_node *root, int options, int width,
|
|
182
176
|
|
183
177
|
while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
|
184
178
|
cur = cmark_iter_get_node(iter);
|
179
|
+
if (cur->extension) {
|
180
|
+
cur->ancestor_extension = cur->extension;
|
181
|
+
} else if (cur->parent) {
|
182
|
+
cur->ancestor_extension = cur->parent->ancestor_extension;
|
183
|
+
}
|
184
|
+
if (cur->type == CMARK_NODE_ITEM) {
|
185
|
+
// Calculate the list item's index, for the benefit of output formats
|
186
|
+
// like commonmark and plaintext.
|
187
|
+
if (cur->prev) {
|
188
|
+
cmark_node_set_item_index(cur, 1 + cmark_node_get_item_index(cur->prev));
|
189
|
+
} else {
|
190
|
+
cmark_node_set_item_index(cur, cmark_node_get_list_start(cur->parent));
|
191
|
+
}
|
192
|
+
}
|
185
193
|
if (!render_node(&renderer, cur, ev_type, options)) {
|
186
194
|
// a false value causes us to skip processing
|
187
195
|
// the node's contents. this is used for
|