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.
@@ -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) | 6)
5
- #define CMARK_GFM_VERSION_STRING "0.29.0.gfm.6"
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
@@ -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 (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) {
193
- tmp = get_containing_block(node);
194
- renderer->in_tight_list_item =
195
- tmp && // tmp might be NULL if there is no containing block
196
- ((tmp->type == CMARK_NODE_ITEM &&
197
- cmark_node_get_list_tight(tmp->parent)) ||
198
- (tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
199
- cmark_node_get_list_tight(tmp->parent->parent)));
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 = cmark_node_get_list_start(node->parent);
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 (entering) {
409
- LIT("**");
410
- } else {
411
- LIT("**");
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
 
@@ -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 aria-label=\"Back to content\">↩</a>");
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 aria-label=\"Back to content\">↩<sup class=\"footnote-ref\">");
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 (entering) {
367
- cmark_strbuf_puts(html, "<strong>");
368
- } else {
369
- cmark_strbuf_puts(html, "</strong>");
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
 
@@ -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
- cmark_node_append_child(link, make_str_with_entities(subj, start_column + 1, end_column - 1, &url));
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, delimiter *stack_bottom) {
655
- delimiter *closer = subj->last_delim;
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
- delimiter *openers_bottom[3][128];
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
- while (closer != NULL && closer->previous != stack_bottom) {
673
- closer = closer->previous;
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 != stack_bottom &&
684
- opener != openers_bottom[closer->length % 3][closer->delim_char]) {
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->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE);
713
- if (opener_found) {
714
- cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
715
- opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE);
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
- opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE);
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->previous;
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 && subj->last_delim != stack_bottom) {
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
- cmark_node_append_child(emph, tmp);
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
- matchlen = scan_html_tag(&subj->input, subj->pos);
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
- if (!opener->active) {
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->previous_delimiter);
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
- cmark_node_append_child(inl, tmp);
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->previous_delimiter);
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 earlier link
1263
- // delimiters. (This code can be removed if we decide to allow links
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
- opener = subj->last_bracket;
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
- cmark_node_append_child(parent, new_inl);
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, NULL);
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);
@@ -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 (entering) {
389
- LIT("\\textbf{");
390
- } else {
391
- LIT("}");
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
 
@@ -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 = cmark_node_get_list_start(node->parent);
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 (entering) {
229
- LIT("\\f[B]");
230
- } else {
231
- LIT("\\f[]");
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
 
@@ -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
- unsigned int i = 0, last = 0, size = map->size;
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 (!ref)
95
- return NULL;
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 ref[0];
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
  }