qiita_marker 0.23.6.2 → 0.23.9.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
- 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
|
}
|