qiita_marker 0.23.6.2 → 0.23.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/qiita_marker/arena.c +9 -8
- data/ext/qiita_marker/autolink.c +209 -159
- data/ext/qiita_marker/blocks.c +25 -1
- data/ext/qiita_marker/cmark-gfm-core-extensions.h +11 -11
- data/ext/qiita_marker/cmark-gfm-extension_api.h +1 -0
- data/ext/qiita_marker/cmark-gfm.h +18 -2
- data/ext/qiita_marker/cmark-gfm_version.h +2 -2
- data/ext/qiita_marker/cmark.c +3 -3
- data/ext/qiita_marker/commonmark.c +18 -33
- data/ext/qiita_marker/html.c +22 -6
- data/ext/qiita_marker/inlines.c +130 -58
- data/ext/qiita_marker/latex.c +6 -4
- data/ext/qiita_marker/man.c +7 -11
- data/ext/qiita_marker/map.c +11 -4
- data/ext/qiita_marker/map.h +5 -2
- data/ext/qiita_marker/node.c +75 -10
- data/ext/qiita_marker/node.h +42 -1
- data/ext/qiita_marker/parser.h +1 -0
- data/ext/qiita_marker/plaintext.c +12 -29
- data/ext/qiita_marker/qiita_marker.c +1 -0
- data/ext/qiita_marker/references.c +1 -0
- data/ext/qiita_marker/render.c +15 -7
- data/ext/qiita_marker/scanners.c +13917 -10369
- data/ext/qiita_marker/scanners.h +8 -0
- data/ext/qiita_marker/strikethrough.c +1 -1
- data/ext/qiita_marker/table.c +59 -35
- data/ext/qiita_marker/xml.c +2 -1
- data/lib/qiita_marker/config.rb +14 -12
- data/lib/qiita_marker/renderer/html_renderer.rb +15 -4
- data/lib/qiita_marker/renderer.rb +1 -1
- data/lib/qiita_marker/version.rb +1 -1
- data/lib/qiita_marker.rb +26 -24
- data/qiita_marker.gemspec +1 -1
- metadata +4 -4
@@ -111,13 +111,13 @@ typedef struct cmark_mem {
|
|
111
111
|
* realloc and free.
|
112
112
|
*/
|
113
113
|
CMARK_GFM_EXPORT
|
114
|
-
cmark_mem *cmark_get_default_mem_allocator();
|
114
|
+
cmark_mem *cmark_get_default_mem_allocator(void);
|
115
115
|
|
116
116
|
/** An arena allocator; uses system calloc to allocate large
|
117
117
|
* slabs of memory. Memory in these slabs is not reused at all.
|
118
118
|
*/
|
119
119
|
CMARK_GFM_EXPORT
|
120
|
-
cmark_mem *cmark_get_arena_mem_allocator();
|
120
|
+
cmark_mem *cmark_get_arena_mem_allocator(void);
|
121
121
|
|
122
122
|
/** Resets the arena allocator, quickly returning all used memory
|
123
123
|
* to the operating system.
|
@@ -225,6 +225,11 @@ CMARK_GFM_EXPORT cmark_node *cmark_node_first_child(cmark_node *node);
|
|
225
225
|
*/
|
226
226
|
CMARK_GFM_EXPORT cmark_node *cmark_node_last_child(cmark_node *node);
|
227
227
|
|
228
|
+
/** Returns the footnote reference of 'node', or NULL if 'node' doesn't have a
|
229
|
+
* footnote reference.
|
230
|
+
*/
|
231
|
+
CMARK_GFM_EXPORT cmark_node *cmark_node_parent_footnote_def(cmark_node *node);
|
232
|
+
|
228
233
|
/**
|
229
234
|
* ## Iterator
|
230
235
|
*
|
@@ -408,6 +413,17 @@ CMARK_GFM_EXPORT int cmark_node_get_list_tight(cmark_node *node);
|
|
408
413
|
*/
|
409
414
|
CMARK_GFM_EXPORT int cmark_node_set_list_tight(cmark_node *node, int tight);
|
410
415
|
|
416
|
+
/**
|
417
|
+
* Returns item index of 'node'. This is only used when rendering output
|
418
|
+
* formats such as commonmark, which need to output the index. It is not
|
419
|
+
* required for formats such as html or latex.
|
420
|
+
*/
|
421
|
+
CMARK_GFM_EXPORT int cmark_node_get_item_index(cmark_node *node);
|
422
|
+
|
423
|
+
/** Sets item index of 'node'. Returns 1 on success, 0 on failure.
|
424
|
+
*/
|
425
|
+
CMARK_GFM_EXPORT int cmark_node_set_item_index(cmark_node *node, int idx);
|
426
|
+
|
411
427
|
/** Returns the info string from a fenced code block.
|
412
428
|
*/
|
413
429
|
CMARK_GFM_EXPORT const char *cmark_node_get_fence_info(cmark_node *node);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#ifndef CMARK_GFM_VERSION_H
|
2
2
|
#define CMARK_GFM_VERSION_H
|
3
3
|
|
4
|
-
#define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) |
|
5
|
-
#define CMARK_GFM_VERSION_STRING "0.29.0.gfm.
|
4
|
+
#define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 11)
|
5
|
+
#define CMARK_GFM_VERSION_STRING "0.29.0.gfm.11"
|
6
6
|
|
7
7
|
#endif
|
data/ext/qiita_marker/cmark.c
CHANGED
@@ -10,9 +10,9 @@
|
|
10
10
|
cmark_node_type CMARK_NODE_LAST_BLOCK = CMARK_NODE_FOOTNOTE_DEFINITION;
|
11
11
|
cmark_node_type CMARK_NODE_LAST_INLINE = CMARK_NODE_FOOTNOTE_REFERENCE;
|
12
12
|
|
13
|
-
int cmark_version() { return CMARK_GFM_VERSION; }
|
13
|
+
int cmark_version(void) { return CMARK_GFM_VERSION; }
|
14
14
|
|
15
|
-
const char *cmark_version_string() { return CMARK_GFM_VERSION_STRING; }
|
15
|
+
const char *cmark_version_string(void) { return CMARK_GFM_VERSION_STRING; }
|
16
16
|
|
17
17
|
static void *xcalloc(size_t nmem, size_t size) {
|
18
18
|
void *ptr = calloc(nmem, size);
|
@@ -38,7 +38,7 @@ static void xfree(void *ptr) {
|
|
38
38
|
|
39
39
|
cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR = {xcalloc, xrealloc, xfree};
|
40
40
|
|
41
|
-
cmark_mem *cmark_get_default_mem_allocator() {
|
41
|
+
cmark_mem *cmark_get_default_mem_allocator(void) {
|
42
42
|
return &CMARK_DEFAULT_MEM_ALLOCATOR;
|
43
43
|
}
|
44
44
|
|
@@ -153,23 +153,8 @@ static bool is_autolink(cmark_node *node) {
|
|
153
153
|
link_text->as.literal.len) == 0);
|
154
154
|
}
|
155
155
|
|
156
|
-
// if node is a block node, returns node.
|
157
|
-
// otherwise returns first block-level node that is an ancestor of node.
|
158
|
-
// if there is no block-level ancestor, returns NULL.
|
159
|
-
static cmark_node *get_containing_block(cmark_node *node) {
|
160
|
-
while (node) {
|
161
|
-
if (CMARK_NODE_BLOCK_P(node)) {
|
162
|
-
return node;
|
163
|
-
} else {
|
164
|
-
node = node->parent;
|
165
|
-
}
|
166
|
-
}
|
167
|
-
return NULL;
|
168
|
-
}
|
169
|
-
|
170
156
|
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
171
157
|
cmark_event_type ev_type, int options) {
|
172
|
-
cmark_node *tmp;
|
173
158
|
int list_number;
|
174
159
|
cmark_delim_type list_delim;
|
175
160
|
int numticks;
|
@@ -189,14 +174,17 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
189
174
|
// Don't adjust tight list status til we've started the list.
|
190
175
|
// Otherwise we loose the blank line between a paragraph and
|
191
176
|
// a following list.
|
192
|
-
if (
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
177
|
+
if (entering) {
|
178
|
+
if (node->parent && node->parent->type == CMARK_NODE_ITEM) {
|
179
|
+
renderer->in_tight_list_item = node->parent->parent->as.list.tight;
|
180
|
+
}
|
181
|
+
} else {
|
182
|
+
if (node->type == CMARK_NODE_LIST) {
|
183
|
+
renderer->in_tight_list_item =
|
184
|
+
node->parent &&
|
185
|
+
node->parent->type == CMARK_NODE_ITEM &&
|
186
|
+
node->parent->parent->as.list.tight;
|
187
|
+
}
|
200
188
|
}
|
201
189
|
|
202
190
|
if (node->extension && node->extension->commonmark_render_func) {
|
@@ -234,13 +222,8 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
234
222
|
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
|
235
223
|
marker_width = 4;
|
236
224
|
} else {
|
237
|
-
list_number =
|
225
|
+
list_number = cmark_node_get_item_index(node);
|
238
226
|
list_delim = cmark_node_get_list_delim(node->parent);
|
239
|
-
tmp = node;
|
240
|
-
while (tmp->prev) {
|
241
|
-
tmp = tmp->prev;
|
242
|
-
list_number += 1;
|
243
|
-
}
|
244
227
|
// we ensure a width of at least 4 so
|
245
228
|
// we get nice transition from single digits
|
246
229
|
// to double
|
@@ -405,10 +388,12 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
405
388
|
break;
|
406
389
|
|
407
390
|
case CMARK_NODE_STRONG:
|
408
|
-
if (
|
409
|
-
|
410
|
-
|
411
|
-
|
391
|
+
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
|
392
|
+
if (entering) {
|
393
|
+
LIT("**");
|
394
|
+
} else {
|
395
|
+
LIT("**");
|
396
|
+
}
|
412
397
|
}
|
413
398
|
break;
|
414
399
|
|
data/ext/qiita_marker/html.c
CHANGED
@@ -64,10 +64,16 @@ static bool S_put_footnote_backref(cmark_html_renderer *renderer, cmark_strbuf *
|
|
64
64
|
if (renderer->written_footnote_ix >= renderer->footnote_ix)
|
65
65
|
return false;
|
66
66
|
renderer->written_footnote_ix = renderer->footnote_ix;
|
67
|
+
char m[32];
|
68
|
+
snprintf(m, sizeof(m), "%d", renderer->written_footnote_ix);
|
67
69
|
|
68
70
|
cmark_strbuf_puts(html, "<a href=\"#fnref-");
|
69
71
|
houdini_escape_href(html, node->as.literal.data, node->as.literal.len);
|
70
|
-
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref
|
72
|
+
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"");
|
73
|
+
cmark_strbuf_puts(html, m);
|
74
|
+
cmark_strbuf_puts(html, "\" aria-label=\"Back to reference ");
|
75
|
+
cmark_strbuf_puts(html, m);
|
76
|
+
cmark_strbuf_puts(html, "\">↩</a>");
|
71
77
|
|
72
78
|
if (node->footnote.def_count > 1)
|
73
79
|
{
|
@@ -79,7 +85,15 @@ static bool S_put_footnote_backref(cmark_html_renderer *renderer, cmark_strbuf *
|
|
79
85
|
houdini_escape_href(html, node->as.literal.data, node->as.literal.len);
|
80
86
|
cmark_strbuf_puts(html, "-");
|
81
87
|
cmark_strbuf_puts(html, n);
|
82
|
-
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref
|
88
|
+
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"");
|
89
|
+
cmark_strbuf_puts(html, m);
|
90
|
+
cmark_strbuf_puts(html, "-");
|
91
|
+
cmark_strbuf_puts(html, n);
|
92
|
+
cmark_strbuf_puts(html, "\" aria-label=\"Back to reference ");
|
93
|
+
cmark_strbuf_puts(html, m);
|
94
|
+
cmark_strbuf_puts(html, "-");
|
95
|
+
cmark_strbuf_puts(html, n);
|
96
|
+
cmark_strbuf_puts(html, "\">↩<sup class=\"footnote-ref\">");
|
83
97
|
cmark_strbuf_puts(html, n);
|
84
98
|
cmark_strbuf_puts(html, "</sup></a>");
|
85
99
|
}
|
@@ -363,10 +377,12 @@ static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
|
|
363
377
|
break;
|
364
378
|
|
365
379
|
case CMARK_NODE_STRONG:
|
366
|
-
if (
|
367
|
-
|
368
|
-
|
369
|
-
|
380
|
+
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
|
381
|
+
if (entering) {
|
382
|
+
cmark_strbuf_puts(html, "<strong>");
|
383
|
+
} else {
|
384
|
+
cmark_strbuf_puts(html, "</strong>");
|
385
|
+
}
|
370
386
|
}
|
371
387
|
break;
|
372
388
|
|
data/ext/qiita_marker/inlines.c
CHANGED
@@ -37,7 +37,6 @@ static const char *RIGHTSINGLEQUOTE = "\xE2\x80\x99";
|
|
37
37
|
|
38
38
|
typedef struct bracket {
|
39
39
|
struct bracket *previous;
|
40
|
-
struct delimiter *previous_delimiter;
|
41
40
|
cmark_node *inl_text;
|
42
41
|
bufsize_t position;
|
43
42
|
bool image;
|
@@ -47,9 +46,15 @@ typedef struct bracket {
|
|
47
46
|
bool in_bracket_image1;
|
48
47
|
} bracket;
|
49
48
|
|
49
|
+
#define FLAG_SKIP_HTML_CDATA (1u << 0)
|
50
|
+
#define FLAG_SKIP_HTML_DECLARATION (1u << 1)
|
51
|
+
#define FLAG_SKIP_HTML_PI (1u << 2)
|
52
|
+
#define FLAG_SKIP_HTML_COMMENT (1u << 3)
|
53
|
+
|
50
54
|
typedef struct subject{
|
51
55
|
cmark_mem *mem;
|
52
56
|
cmark_chunk input;
|
57
|
+
unsigned flags;
|
53
58
|
int line;
|
54
59
|
bufsize_t pos;
|
55
60
|
int block_offset;
|
@@ -59,6 +64,7 @@ typedef struct subject{
|
|
59
64
|
bracket *last_bracket;
|
60
65
|
bufsize_t backticks[MAXBACKTICKS + 1];
|
61
66
|
bool scanned_for_backticks;
|
67
|
+
bool no_link_openers;
|
62
68
|
} subject;
|
63
69
|
|
64
70
|
// Extensions may populate this.
|
@@ -113,6 +119,24 @@ static cmark_node *make_str_with_entities(subject *subj,
|
|
113
119
|
}
|
114
120
|
}
|
115
121
|
|
122
|
+
// Like cmark_node_append_child but without costly sanity checks.
|
123
|
+
// Assumes that child was newly created.
|
124
|
+
static void append_child(cmark_node *node, cmark_node *child) {
|
125
|
+
cmark_node *old_last_child = node->last_child;
|
126
|
+
|
127
|
+
child->next = NULL;
|
128
|
+
child->prev = old_last_child;
|
129
|
+
child->parent = node;
|
130
|
+
node->last_child = child;
|
131
|
+
|
132
|
+
if (old_last_child) {
|
133
|
+
old_last_child->next = child;
|
134
|
+
} else {
|
135
|
+
// Also set first_child if node previously had no children.
|
136
|
+
node->first_child = child;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
116
140
|
// Duplicate a chunk by creating a copy of the buffer not by reusing the
|
117
141
|
// buffer like cmark_chunk_dup does.
|
118
142
|
static cmark_chunk chunk_clone(cmark_mem *mem, cmark_chunk *src) {
|
@@ -156,7 +180,7 @@ static CMARK_INLINE cmark_node *make_autolink(subject *subj,
|
|
156
180
|
link->start_line = link->end_line = subj->line;
|
157
181
|
link->start_column = start_column + 1;
|
158
182
|
link->end_column = end_column + 1;
|
159
|
-
|
183
|
+
append_child(link, make_str_with_entities(subj, start_column + 1, end_column - 1, &url));
|
160
184
|
return link;
|
161
185
|
}
|
162
186
|
|
@@ -165,6 +189,7 @@ static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset,
|
|
165
189
|
int i;
|
166
190
|
e->mem = mem;
|
167
191
|
e->input = *chunk;
|
192
|
+
e->flags = 0;
|
168
193
|
e->line = line_number;
|
169
194
|
e->pos = 0;
|
170
195
|
e->block_offset = block_offset;
|
@@ -176,6 +201,7 @@ static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset,
|
|
176
201
|
e->backticks[i] = 0;
|
177
202
|
}
|
178
203
|
e->scanned_for_backticks = false;
|
204
|
+
e->no_link_openers = true;
|
179
205
|
}
|
180
206
|
|
181
207
|
static CMARK_INLINE int isbacktick(int c) { return (c == '`'); }
|
@@ -515,6 +541,7 @@ static void push_delimiter(subject *subj, unsigned char c, bool can_open,
|
|
515
541
|
delim->can_open = can_open;
|
516
542
|
delim->can_close = can_close;
|
517
543
|
delim->inl_text = inl_text;
|
544
|
+
delim->position = subj->pos;
|
518
545
|
delim->length = inl_text->as.literal.len;
|
519
546
|
delim->previous = subj->last_delim;
|
520
547
|
delim->next = NULL;
|
@@ -535,7 +562,6 @@ static void push_bracket(subject *subj, bool image, cmark_node *inl_text) {
|
|
535
562
|
b->active = true;
|
536
563
|
b->inl_text = inl_text;
|
537
564
|
b->previous = subj->last_bracket;
|
538
|
-
b->previous_delimiter = subj->last_delim;
|
539
565
|
b->position = subj->pos;
|
540
566
|
b->bracket_after = false;
|
541
567
|
if (image) {
|
@@ -544,6 +570,9 @@ static void push_bracket(subject *subj, bool image, cmark_node *inl_text) {
|
|
544
570
|
b->in_bracket_image0 = true;
|
545
571
|
}
|
546
572
|
subj->last_bracket = b;
|
573
|
+
if (!image) {
|
574
|
+
subj->no_link_openers = false;
|
575
|
+
}
|
547
576
|
}
|
548
577
|
|
549
578
|
// Assumes the subject has a c at the current position.
|
@@ -651,12 +680,13 @@ static cmark_syntax_extension *get_extension_for_special_char(cmark_parser *pars
|
|
651
680
|
return NULL;
|
652
681
|
}
|
653
682
|
|
654
|
-
static void process_emphasis(cmark_parser *parser, subject *subj,
|
655
|
-
delimiter *
|
683
|
+
static void process_emphasis(cmark_parser *parser, subject *subj, bufsize_t stack_bottom) {
|
684
|
+
delimiter *candidate;
|
685
|
+
delimiter *closer = NULL;
|
656
686
|
delimiter *opener;
|
657
687
|
delimiter *old_closer;
|
658
688
|
bool opener_found;
|
659
|
-
|
689
|
+
bufsize_t openers_bottom[3][128];
|
660
690
|
int i;
|
661
691
|
|
662
692
|
// initialize openers_bottom:
|
@@ -669,8 +699,10 @@ static void process_emphasis(cmark_parser *parser, subject *subj, delimiter *sta
|
|
669
699
|
}
|
670
700
|
|
671
701
|
// move back to first relevant delim.
|
672
|
-
|
673
|
-
|
702
|
+
candidate = subj->last_delim;
|
703
|
+
while (candidate != NULL && candidate->position >= stack_bottom) {
|
704
|
+
closer = candidate;
|
705
|
+
candidate = candidate->previous;
|
674
706
|
}
|
675
707
|
|
676
708
|
// now move forward, looking for closers, and handling each
|
@@ -680,8 +712,8 @@ static void process_emphasis(cmark_parser *parser, subject *subj, delimiter *sta
|
|
680
712
|
// Now look backwards for first matching opener:
|
681
713
|
opener = closer->previous;
|
682
714
|
opener_found = false;
|
683
|
-
while (opener != NULL && opener
|
684
|
-
opener
|
715
|
+
while (opener != NULL && opener->position >= stack_bottom &&
|
716
|
+
opener->position >= openers_bottom[closer->length % 3][closer->delim_char]) {
|
685
717
|
if (opener->can_open && opener->delim_char == closer->delim_char) {
|
686
718
|
// interior closer of size 2 can't match opener of size 1
|
687
719
|
// or of size 1 can't match 2
|
@@ -707,27 +739,29 @@ static void process_emphasis(cmark_parser *parser, subject *subj, delimiter *sta
|
|
707
739
|
} else {
|
708
740
|
closer = closer->next;
|
709
741
|
}
|
710
|
-
} else if (closer->delim_char == '\'') {
|
742
|
+
} else if (closer->delim_char == '\'' || closer->delim_char == '"') {
|
711
743
|
cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
|
712
|
-
closer->
|
713
|
-
|
714
|
-
|
715
|
-
|
744
|
+
if (closer->delim_char == '\'') {
|
745
|
+
closer->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE);
|
746
|
+
} else {
|
747
|
+
closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE);
|
716
748
|
}
|
717
749
|
closer = closer->next;
|
718
|
-
} else if (closer->delim_char == '"') {
|
719
|
-
cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
|
720
|
-
closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE);
|
721
750
|
if (opener_found) {
|
722
751
|
cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
|
723
|
-
|
752
|
+
if (old_closer->delim_char == '\'') {
|
753
|
+
opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE);
|
754
|
+
} else {
|
755
|
+
opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE);
|
756
|
+
}
|
757
|
+
remove_delimiter(subj, opener);
|
758
|
+
remove_delimiter(subj, old_closer);
|
724
759
|
}
|
725
|
-
closer = closer->next;
|
726
760
|
}
|
727
761
|
if (!opener_found) {
|
728
762
|
// set lower bound for future searches for openers
|
729
763
|
openers_bottom[old_closer->length % 3][old_closer->delim_char] =
|
730
|
-
old_closer->
|
764
|
+
old_closer->position;
|
731
765
|
if (!old_closer->can_open) {
|
732
766
|
// we can remove a closer that can't be an
|
733
767
|
// opener, once we've seen there's no
|
@@ -740,7 +774,8 @@ static void process_emphasis(cmark_parser *parser, subject *subj, delimiter *sta
|
|
740
774
|
}
|
741
775
|
}
|
742
776
|
// free all delimiters in list until stack_bottom:
|
743
|
-
while (subj->last_delim != NULL &&
|
777
|
+
while (subj->last_delim != NULL &&
|
778
|
+
subj->last_delim->position >= stack_bottom) {
|
744
779
|
remove_delimiter(subj, subj->last_delim);
|
745
780
|
}
|
746
781
|
}
|
@@ -779,7 +814,8 @@ static delimiter *S_insert_emph(subject *subj, delimiter *opener,
|
|
779
814
|
tmp = opener_inl->next;
|
780
815
|
while (tmp && tmp != closer_inl) {
|
781
816
|
tmpnext = tmp->next;
|
782
|
-
|
817
|
+
cmark_node_unlink(tmp);
|
818
|
+
append_child(emph, tmp);
|
783
819
|
tmp = tmpnext;
|
784
820
|
}
|
785
821
|
cmark_node_insert_after(opener_inl, emph);
|
@@ -910,7 +946,63 @@ static cmark_node *handle_pointy_brace(subject *subj, int options) {
|
|
910
946
|
}
|
911
947
|
|
912
948
|
// finally, try to match an html tag
|
913
|
-
|
949
|
+
if (subj->pos + 2 <= subj->input.len) {
|
950
|
+
int c = subj->input.data[subj->pos];
|
951
|
+
if (c == '!' && (subj->flags & FLAG_SKIP_HTML_COMMENT) == 0) {
|
952
|
+
c = subj->input.data[subj->pos+1];
|
953
|
+
if (c == '-' && subj->input.data[subj->pos+2] == '-') {
|
954
|
+
if (subj->input.data[subj->pos+3] == '>') {
|
955
|
+
matchlen = 4;
|
956
|
+
} else if (subj->input.data[subj->pos+3] == '-' &&
|
957
|
+
subj->input.data[subj->pos+4] == '>') {
|
958
|
+
matchlen = 5;
|
959
|
+
} else {
|
960
|
+
matchlen = scan_html_comment(&subj->input, subj->pos + 1);
|
961
|
+
if (matchlen > 0) {
|
962
|
+
matchlen += 1; // prefix "<"
|
963
|
+
} else { // no match through end of input: set a flag so
|
964
|
+
// we don't reparse looking for -->:
|
965
|
+
subj->flags |= FLAG_SKIP_HTML_COMMENT;
|
966
|
+
}
|
967
|
+
}
|
968
|
+
} else if (c == '[') {
|
969
|
+
if ((subj->flags & FLAG_SKIP_HTML_CDATA) == 0) {
|
970
|
+
matchlen = scan_html_cdata(&subj->input, subj->pos + 2);
|
971
|
+
if (matchlen > 0) {
|
972
|
+
// The regex doesn't require the final "]]>". But if we're not at
|
973
|
+
// the end of input, it must come after the match. Otherwise,
|
974
|
+
// disable subsequent scans to avoid quadratic behavior.
|
975
|
+
matchlen += 5; // prefix "![", suffix "]]>"
|
976
|
+
if (subj->pos + matchlen > subj->input.len) {
|
977
|
+
subj->flags |= FLAG_SKIP_HTML_CDATA;
|
978
|
+
matchlen = 0;
|
979
|
+
}
|
980
|
+
}
|
981
|
+
}
|
982
|
+
} else if ((subj->flags & FLAG_SKIP_HTML_DECLARATION) == 0) {
|
983
|
+
matchlen = scan_html_declaration(&subj->input, subj->pos + 1);
|
984
|
+
if (matchlen > 0) {
|
985
|
+
matchlen += 2; // prefix "!", suffix ">"
|
986
|
+
if (subj->pos + matchlen > subj->input.len) {
|
987
|
+
subj->flags |= FLAG_SKIP_HTML_DECLARATION;
|
988
|
+
matchlen = 0;
|
989
|
+
}
|
990
|
+
}
|
991
|
+
}
|
992
|
+
} else if (c == '?') {
|
993
|
+
if ((subj->flags & FLAG_SKIP_HTML_PI) == 0) {
|
994
|
+
// Note that we allow an empty match.
|
995
|
+
matchlen = scan_html_pi(&subj->input, subj->pos + 1);
|
996
|
+
matchlen += 3; // prefix "?", suffix "?>"
|
997
|
+
if (subj->pos + matchlen > subj->input.len) {
|
998
|
+
subj->flags |= FLAG_SKIP_HTML_PI;
|
999
|
+
matchlen = 0;
|
1000
|
+
}
|
1001
|
+
}
|
1002
|
+
} else {
|
1003
|
+
matchlen = scan_html_tag(&subj->input, subj->pos);
|
1004
|
+
}
|
1005
|
+
}
|
914
1006
|
if (matchlen > 0) {
|
915
1007
|
contents = cmark_chunk_dup(&subj->input, subj->pos - 1, matchlen + 1);
|
916
1008
|
subj->pos += matchlen;
|
@@ -1076,16 +1168,16 @@ static cmark_node *handle_close_bracket(cmark_parser *parser, subject *subj) {
|
|
1076
1168
|
return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
|
1077
1169
|
}
|
1078
1170
|
|
1079
|
-
|
1171
|
+
// If we got here, we matched a potential link/image text.
|
1172
|
+
// Now we check to see if it's a link/image.
|
1173
|
+
is_image = opener->image;
|
1174
|
+
|
1175
|
+
if (!is_image && subj->no_link_openers) {
|
1080
1176
|
// take delimiter off stack
|
1081
1177
|
pop_bracket(subj);
|
1082
1178
|
return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
|
1083
1179
|
}
|
1084
1180
|
|
1085
|
-
// If we got here, we matched a potential link/image text.
|
1086
|
-
// Now we check to see if it's a link/image.
|
1087
|
-
is_image = opener->image;
|
1088
|
-
|
1089
1181
|
after_link_text_pos = subj->pos;
|
1090
1182
|
|
1091
1183
|
// First, look for an inline link.
|
@@ -1204,7 +1296,7 @@ noMatch:
|
|
1204
1296
|
// being replacing the opening '[' text node with a `^footnote-ref]` node.
|
1205
1297
|
cmark_node_insert_before(opener->inl_text, fnref);
|
1206
1298
|
|
1207
|
-
process_emphasis(parser, subj, opener->
|
1299
|
+
process_emphasis(parser, subj, opener->position);
|
1208
1300
|
// sometimes, the footnote reference text gets parsed into multiple nodes
|
1209
1301
|
// i.e. '[^example]' parsed into '[', '^exam', 'ple]'.
|
1210
1302
|
// this happens for ex with the autolink extension. when the autolinker
|
@@ -1249,42 +1341,22 @@ match:
|
|
1249
1341
|
tmp = opener->inl_text->next;
|
1250
1342
|
while (tmp) {
|
1251
1343
|
tmpnext = tmp->next;
|
1252
|
-
|
1344
|
+
cmark_node_unlink(tmp);
|
1345
|
+
append_child(inl, tmp);
|
1253
1346
|
tmp = tmpnext;
|
1254
1347
|
}
|
1255
1348
|
|
1256
1349
|
// Free the bracket [:
|
1257
1350
|
cmark_node_free(opener->inl_text);
|
1258
1351
|
|
1259
|
-
process_emphasis(parser, subj, opener->
|
1352
|
+
process_emphasis(parser, subj, opener->position);
|
1260
1353
|
pop_bracket(subj);
|
1261
1354
|
|
1262
|
-
// Now, if we have a link, we also want to deactivate
|
1263
|
-
//
|
1355
|
+
// Now, if we have a link, we also want to deactivate links until
|
1356
|
+
// we get a new opener. (This code can be removed if we decide to allow links
|
1264
1357
|
// inside links.)
|
1265
1358
|
if (!is_image) {
|
1266
|
-
|
1267
|
-
while (opener != NULL) {
|
1268
|
-
if (!opener->image) {
|
1269
|
-
if (!opener->active) {
|
1270
|
-
break;
|
1271
|
-
} else {
|
1272
|
-
opener->active = false;
|
1273
|
-
}
|
1274
|
-
}
|
1275
|
-
opener = opener->previous;
|
1276
|
-
}
|
1277
|
-
bool in_bracket_image1 = false;
|
1278
|
-
if (opener) {
|
1279
|
-
in_bracket_image1 = opener->in_bracket_image1;
|
1280
|
-
}
|
1281
|
-
bracket *opener2 = subj->last_bracket;
|
1282
|
-
while (opener2 != opener) {
|
1283
|
-
if (opener2->image) {
|
1284
|
-
opener2->in_bracket_image1 = in_bracket_image1;
|
1285
|
-
}
|
1286
|
-
opener2 = opener2->previous;
|
1287
|
-
}
|
1359
|
+
subj->no_link_openers = true;
|
1288
1360
|
}
|
1289
1361
|
|
1290
1362
|
return NULL;
|
@@ -1463,7 +1535,7 @@ static int parse_inline(cmark_parser *parser, subject *subj, cmark_node *parent,
|
|
1463
1535
|
new_inl = make_str(subj, startpos, endpos - 1, contents);
|
1464
1536
|
}
|
1465
1537
|
if (new_inl != NULL) {
|
1466
|
-
|
1538
|
+
append_child(parent, new_inl);
|
1467
1539
|
}
|
1468
1540
|
|
1469
1541
|
return 1;
|
@@ -1482,7 +1554,7 @@ void cmark_parse_inlines(cmark_parser *parser,
|
|
1482
1554
|
while (!is_eof(&subj) && parse_inline(parser, &subj, parent, options))
|
1483
1555
|
;
|
1484
1556
|
|
1485
|
-
process_emphasis(parser, &subj,
|
1557
|
+
process_emphasis(parser, &subj, 0);
|
1486
1558
|
// free bracket and delim stack
|
1487
1559
|
while (subj.last_delim) {
|
1488
1560
|
remove_delimiter(&subj, subj.last_delim);
|
data/ext/qiita_marker/latex.c
CHANGED
@@ -385,10 +385,12 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
385
385
|
break;
|
386
386
|
|
387
387
|
case CMARK_NODE_STRONG:
|
388
|
-
if (
|
389
|
-
|
390
|
-
|
391
|
-
|
388
|
+
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
|
389
|
+
if (entering) {
|
390
|
+
LIT("\\textbf{");
|
391
|
+
} else {
|
392
|
+
LIT("}");
|
393
|
+
}
|
392
394
|
}
|
393
395
|
break;
|
394
396
|
|
data/ext/qiita_marker/man.c
CHANGED
@@ -74,7 +74,6 @@ static void S_outc(cmark_renderer *renderer, cmark_node *node,
|
|
74
74
|
|
75
75
|
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
76
76
|
cmark_event_type ev_type, int options) {
|
77
|
-
cmark_node *tmp;
|
78
77
|
int list_number;
|
79
78
|
bool entering = (ev_type == CMARK_EVENT_ENTER);
|
80
79
|
bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
|
@@ -123,12 +122,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
123
122
|
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
|
124
123
|
LIT("\\[bu] 2");
|
125
124
|
} else {
|
126
|
-
list_number =
|
127
|
-
tmp = node;
|
128
|
-
while (tmp->prev) {
|
129
|
-
tmp = tmp->prev;
|
130
|
-
list_number += 1;
|
131
|
-
}
|
125
|
+
list_number = cmark_node_get_item_index(node);
|
132
126
|
char list_number_s[LIST_NUMBER_SIZE];
|
133
127
|
snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number);
|
134
128
|
LIT(list_number_s);
|
@@ -225,10 +219,12 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
225
219
|
break;
|
226
220
|
|
227
221
|
case CMARK_NODE_STRONG:
|
228
|
-
if (
|
229
|
-
|
230
|
-
|
231
|
-
|
222
|
+
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
|
223
|
+
if (entering) {
|
224
|
+
LIT("\\f[B]");
|
225
|
+
} else {
|
226
|
+
LIT("\\f[]");
|
227
|
+
}
|
232
228
|
}
|
233
229
|
break;
|
234
230
|
|
data/ext/qiita_marker/map.c
CHANGED
@@ -51,7 +51,7 @@ refsearch(const void *label, const void *p2) {
|
|
51
51
|
}
|
52
52
|
|
53
53
|
static void sort_map(cmark_map *map) {
|
54
|
-
|
54
|
+
size_t i = 0, last = 0, size = map->size;
|
55
55
|
cmark_map_entry *r = map->refs, **sorted = NULL;
|
56
56
|
|
57
57
|
sorted = (cmark_map_entry **)map->mem->calloc(size, sizeof(cmark_map_entry *));
|
@@ -73,6 +73,7 @@ static void sort_map(cmark_map *map) {
|
|
73
73
|
|
74
74
|
cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label) {
|
75
75
|
cmark_map_entry **ref = NULL;
|
76
|
+
cmark_map_entry *r = NULL;
|
76
77
|
unsigned char *norm;
|
77
78
|
|
78
79
|
if (label->len < 1 || label->len > MAX_LINK_LABEL_LENGTH)
|
@@ -91,10 +92,15 @@ cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label) {
|
|
91
92
|
ref = (cmark_map_entry **)bsearch(norm, map->sorted, map->size, sizeof(cmark_map_entry *), refsearch);
|
92
93
|
map->mem->free(norm);
|
93
94
|
|
94
|
-
if (
|
95
|
-
|
95
|
+
if (ref != NULL) {
|
96
|
+
r = ref[0];
|
97
|
+
/* Check for expansion limit */
|
98
|
+
if (r->size > map->max_ref_size - map->ref_size)
|
99
|
+
return NULL;
|
100
|
+
map->ref_size += r->size;
|
101
|
+
}
|
96
102
|
|
97
|
-
return
|
103
|
+
return r;
|
98
104
|
}
|
99
105
|
|
100
106
|
void cmark_map_free(cmark_map *map) {
|
@@ -118,5 +124,6 @@ cmark_map *cmark_map_new(cmark_mem *mem, cmark_map_free_f free) {
|
|
118
124
|
cmark_map *map = (cmark_map *)mem->calloc(1, sizeof(cmark_map));
|
119
125
|
map->mem = mem;
|
120
126
|
map->free = free;
|
127
|
+
map->max_ref_size = UINT_MAX;
|
121
128
|
return map;
|
122
129
|
}
|