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.
@@ -10,7 +10,8 @@ extern "C" {
10
10
  struct cmark_map_entry {
11
11
  struct cmark_map_entry *next;
12
12
  unsigned char *label;
13
- unsigned int age;
13
+ size_t age;
14
+ size_t size;
14
15
  };
15
16
 
16
17
  typedef struct cmark_map_entry cmark_map_entry;
@@ -23,7 +24,9 @@ struct cmark_map {
23
24
  cmark_mem *mem;
24
25
  cmark_map_entry *refs;
25
26
  cmark_map_entry **sorted;
26
- unsigned int size;
27
+ size_t size;
28
+ size_t ref_size;
29
+ size_t max_ref_size;
27
30
  cmark_map_free_f free;
28
31
  };
29
32
 
@@ -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
- // Verify that child is not an ancestor of node or equal to node.
61
- cur = node;
62
- do {
63
- if (cur == child) {
64
- return false;
65
- }
66
- cur = cur->parent;
67
- } while (cur != NULL);
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;
@@ -524,6 +564,31 @@ int cmark_node_set_list_tight(cmark_node *node, int tight) {
524
564
  }
525
565
  }
526
566
 
567
+ int cmark_node_get_item_index(cmark_node *node) {
568
+ if (node == NULL) {
569
+ return 0;
570
+ }
571
+
572
+ if (node->type == CMARK_NODE_ITEM) {
573
+ return node->as.list.start;
574
+ } else {
575
+ return 0;
576
+ }
577
+ }
578
+
579
+ int cmark_node_set_item_index(cmark_node *node, int idx) {
580
+ if (node == NULL || idx < 0) {
581
+ return 0;
582
+ }
583
+
584
+ if (node->type == CMARK_NODE_ITEM) {
585
+ node->as.list.start = idx;
586
+ return 1;
587
+ } else {
588
+ return 0;
589
+ }
590
+ }
591
+
527
592
  const char *cmark_node_get_fence_info(cmark_node *node) {
528
593
  if (node == NULL) {
529
594
  return NULL;
@@ -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,18 @@ struct cmark_node {
72
78
  int end_column;
73
79
  int internal_offset;
74
80
  uint16_t type;
75
- uint16_t flags;
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
+
79
93
  union {
80
94
  int ref_ix;
81
95
  int def_count;
@@ -95,6 +109,26 @@ struct cmark_node {
95
109
  } as;
96
110
  };
97
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
+
98
132
  static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) {
99
133
  return node->content.mem;
100
134
  }
@@ -118,6 +152,13 @@ static CMARK_INLINE bool CMARK_NODE_INLINE_P(cmark_node *node) {
118
152
 
119
153
  CMARK_GFM_EXPORT bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type);
120
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
+
121
162
  #ifdef __cplusplus
122
163
  }
123
164
  #endif
@@ -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;
@@ -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 (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) {
50
- tmp = get_containing_block(node);
51
- renderer->in_tight_list_item =
52
- tmp && // tmp might be NULL if there is no containing block
53
- ((tmp->type == CMARK_NODE_ITEM &&
54
- cmark_node_get_list_tight(tmp->parent)) ||
55
- (tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
56
- cmark_node_get_list_tight(tmp->parent->parent)));
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 = cmark_node_get_list_start(node->parent);
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
@@ -1304,4 +1304,5 @@ __attribute__((visibility("default"))) void Init_qiita_marker() {
1304
1304
  rb_define_method(rb_cNode, "html_escape_html", rb_html_escape_html, 1);
1305
1305
 
1306
1306
  cmark_gfm_core_extensions_ensure_registered();
1307
+ cmark_init_standard_node_flags();
1307
1308
  }
@@ -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++;
@@ -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 = NULL;
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