markly 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/conduct.md +133 -0
  4. data/ext/markly/arena.c +9 -8
  5. data/ext/markly/autolink.c +217 -134
  6. data/ext/markly/blocks.c +27 -2
  7. data/ext/markly/cmark-gfm-core-extensions.h +11 -11
  8. data/ext/markly/cmark-gfm-extension_api.h +1 -0
  9. data/ext/markly/cmark-gfm.h +18 -2
  10. data/ext/markly/cmark.c +3 -3
  11. data/ext/markly/commonmark.c +19 -34
  12. data/ext/markly/extconf.rb +8 -1
  13. data/ext/markly/html.c +22 -6
  14. data/ext/markly/inlines.c +148 -51
  15. data/ext/markly/latex.c +6 -4
  16. data/ext/markly/man.c +7 -11
  17. data/ext/markly/map.c +11 -4
  18. data/ext/markly/map.h +5 -2
  19. data/ext/markly/markly.c +582 -586
  20. data/ext/markly/markly.h +1 -1
  21. data/ext/markly/node.c +76 -10
  22. data/ext/markly/node.h +42 -1
  23. data/ext/markly/parser.h +1 -0
  24. data/ext/markly/plaintext.c +12 -29
  25. data/ext/markly/references.c +1 -0
  26. data/ext/markly/render.c +15 -7
  27. data/ext/markly/scanners.c +13916 -10380
  28. data/ext/markly/scanners.h +8 -0
  29. data/ext/markly/scanners.re +47 -8
  30. data/ext/markly/strikethrough.c +1 -1
  31. data/ext/markly/table.c +81 -31
  32. data/ext/markly/xml.c +2 -1
  33. data/lib/markly/flags.rb +16 -0
  34. data/lib/markly/node/inspect.rb +59 -53
  35. data/lib/markly/node.rb +125 -58
  36. data/lib/markly/renderer/generic.rb +129 -124
  37. data/lib/markly/renderer/html.rb +294 -275
  38. data/lib/markly/version.rb +7 -1
  39. data/lib/markly.rb +36 -30
  40. data/license.md +39 -0
  41. data/readme.md +36 -0
  42. data.tar.gz.sig +0 -0
  43. metadata +61 -29
  44. metadata.gz.sig +0 -0
  45. data/bin/markly +0 -94
  46. data/lib/markly/markly.bundle +0 -0
data/ext/markly/markly.h CHANGED
@@ -11,6 +11,6 @@
11
11
 
12
12
  #define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
13
13
 
14
- void Init_markly();
14
+ void Init_markly(void);
15
15
 
16
16
  #endif
data/ext/markly/node.c CHANGED
@@ -5,10 +5,42 @@
5
5
  #include "node.h"
6
6
  #include "syntax_extension.h"
7
7
 
8
+ /**
9
+ * Expensive safety checks are off by default, but can be enabled
10
+ * by calling cmark_enable_safety_checks().
11
+ */
12
+ static bool enable_safety_checks = false;
13
+
14
+ void cmark_enable_safety_checks(bool enable) {
15
+ enable_safety_checks = enable;
16
+ }
17
+
8
18
  static void S_node_unlink(cmark_node *node);
9
19
 
10
20
  #define NODE_MEM(node) cmark_node_mem(node)
11
21
 
22
+ void cmark_register_node_flag(cmark_node_internal_flags *flags) {
23
+ static cmark_node_internal_flags nextflag = CMARK_NODE__REGISTER_FIRST;
24
+
25
+ // flags should be a pointer to a global variable and this function
26
+ // should only be called once to initialize its value.
27
+ if (*flags) {
28
+ fprintf(stderr, "flag initialization error in cmark_register_node_flag\n");
29
+ abort();
30
+ }
31
+
32
+ // Check that we haven't run out of bits.
33
+ if (nextflag == 0) {
34
+ fprintf(stderr, "too many flags in cmark_register_node_flag\n");
35
+ abort();
36
+ }
37
+
38
+ *flags = nextflag;
39
+ nextflag <<= 1;
40
+ }
41
+
42
+ void cmark_init_standard_node_flags(void) {}
43
+
12
44
  bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
13
45
  if (child_type == CMARK_NODE_DOCUMENT) {
14
46
  return false;
@@ -48,8 +80,6 @@ bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
48
80
  }
49
81
 
50
82
  static bool S_can_contain(cmark_node *node, cmark_node *child) {
51
- cmark_node *cur;
52
-
53
83
  if (node == NULL || child == NULL) {
54
84
  return false;
55
85
  }
@@ -57,14 +87,16 @@ static bool S_can_contain(cmark_node *node, cmark_node *child) {
57
87
  return 0;
58
88
  }
59
89
 
60
- // 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;
@@ -337,6 +377,7 @@ const char *cmark_node_get_literal(cmark_node *node) {
337
377
  case CMARK_NODE_HTML_INLINE:
338
378
  case CMARK_NODE_CODE:
339
379
  case CMARK_NODE_FOOTNOTE_REFERENCE:
380
+ case CMARK_NODE_FOOTNOTE_DEFINITION:
340
381
  return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);
341
382
 
342
383
  case CMARK_NODE_CODE_BLOCK:
@@ -524,6 +565,31 @@ int cmark_node_set_list_tight(cmark_node *node, int tight) {
524
565
  }
525
566
  }
526
567
 
568
+ int cmark_node_get_item_index(cmark_node *node) {
569
+ if (node == NULL) {
570
+ return 0;
571
+ }
572
+
573
+ if (node->type == CMARK_NODE_ITEM) {
574
+ return node->as.list.start;
575
+ } else {
576
+ return 0;
577
+ }
578
+ }
579
+
580
+ int cmark_node_set_item_index(cmark_node *node, int idx) {
581
+ if (node == NULL || idx < 0) {
582
+ return 0;
583
+ }
584
+
585
+ if (node->type == CMARK_NODE_ITEM) {
586
+ node->as.list.start = idx;
587
+ return 1;
588
+ } else {
589
+ return 0;
590
+ }
591
+ }
592
+
527
593
  const char *cmark_node_get_fence_info(cmark_node *node) {
528
594
  if (node == NULL) {
529
595
  return NULL;
data/ext/markly/node.h CHANGED
@@ -52,8 +52,14 @@ enum cmark_node__internal_flags {
52
52
  CMARK_NODE__OPEN = (1 << 0),
53
53
  CMARK_NODE__LAST_LINE_BLANK = (1 << 1),
54
54
  CMARK_NODE__LAST_LINE_CHECKED = (1 << 2),
55
+
56
+ // Extensions can register custom flags by calling `cmark_register_node_flag`.
57
+ // This is the starting value for the custom flags.
58
+ CMARK_NODE__REGISTER_FIRST = (1 << 3),
55
59
  };
56
60
 
61
+ typedef uint16_t cmark_node_internal_flags;
62
+
57
63
  struct cmark_node {
58
64
  cmark_strbuf content;
59
65
 
@@ -72,10 +78,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
data/ext/markly/parser.h CHANGED
@@ -46,6 +46,7 @@ struct cmark_parser {
46
46
  /* Options set by the user, see the Options section in cmark.h */
47
47
  int options;
48
48
  bool last_buffer_ended_with_cr;
49
+ size_t total_size;
49
50
  cmark_llist *syntax_extensions;
50
51
  cmark_llist *inline_syntax_extensions;
51
52
  cmark_ispunct_func backslash_ispunct;
@@ -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
@@ -32,6 +32,7 @@ void cmark_reference_create(cmark_map *map, cmark_chunk *label,
32
32
  ref->title = cmark_clean_title(map->mem, title);
33
33
  ref->entry.age = map->size;
34
34
  ref->entry.next = map->refs;
35
+ ref->entry.size = ref->url.len + ref->title.len;
35
36
 
36
37
  map->refs = (cmark_map_entry *)ref;
37
38
  map->size++;
data/ext/markly/render.c CHANGED
@@ -31,13 +31,7 @@ static void S_out(cmark_renderer *renderer, cmark_node *node,
31
31
  cmark_chunk remainder = cmark_chunk_literal("");
32
32
  int k = renderer->buffer->size - 1;
33
33
 
34
- cmark_syntax_extension *ext = 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