commonmarker 0.23.10 → 2.1.1

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1156 -0
  3. data/Cargo.toml +7 -0
  4. data/README.md +237 -172
  5. data/ext/commonmarker/Cargo.toml +20 -0
  6. data/ext/commonmarker/extconf.rb +3 -6
  7. data/ext/commonmarker/src/lib.rs +103 -0
  8. data/ext/commonmarker/src/node.rs +1221 -0
  9. data/ext/commonmarker/src/options.rs +220 -0
  10. data/ext/commonmarker/src/plugins/syntax_highlighting.rs +166 -0
  11. data/ext/commonmarker/src/plugins.rs +6 -0
  12. data/ext/commonmarker/src/utils.rs +8 -0
  13. data/lib/commonmarker/config.rb +92 -40
  14. data/lib/commonmarker/constants.rb +7 -0
  15. data/lib/commonmarker/extension.rb +14 -0
  16. data/lib/commonmarker/node/ast.rb +8 -0
  17. data/lib/commonmarker/node/inspect.rb +14 -4
  18. data/lib/commonmarker/node.rb +29 -47
  19. data/lib/commonmarker/renderer.rb +1 -127
  20. data/lib/commonmarker/utils.rb +22 -0
  21. data/lib/commonmarker/version.rb +2 -2
  22. data/lib/commonmarker.rb +27 -25
  23. metadata +38 -191
  24. data/Rakefile +0 -109
  25. data/bin/commonmarker +0 -118
  26. data/commonmarker.gemspec +0 -38
  27. data/ext/commonmarker/arena.c +0 -104
  28. data/ext/commonmarker/autolink.c +0 -508
  29. data/ext/commonmarker/autolink.h +0 -8
  30. data/ext/commonmarker/blocks.c +0 -1622
  31. data/ext/commonmarker/buffer.c +0 -278
  32. data/ext/commonmarker/buffer.h +0 -116
  33. data/ext/commonmarker/case_fold_switch.inc +0 -4327
  34. data/ext/commonmarker/chunk.h +0 -135
  35. data/ext/commonmarker/cmark-gfm-core-extensions.h +0 -54
  36. data/ext/commonmarker/cmark-gfm-extension_api.h +0 -737
  37. data/ext/commonmarker/cmark-gfm-extensions_export.h +0 -42
  38. data/ext/commonmarker/cmark-gfm.h +0 -833
  39. data/ext/commonmarker/cmark-gfm_export.h +0 -42
  40. data/ext/commonmarker/cmark-gfm_version.h +0 -7
  41. data/ext/commonmarker/cmark.c +0 -55
  42. data/ext/commonmarker/cmark_ctype.c +0 -44
  43. data/ext/commonmarker/cmark_ctype.h +0 -33
  44. data/ext/commonmarker/commonmark.c +0 -514
  45. data/ext/commonmarker/commonmarker.c +0 -1308
  46. data/ext/commonmarker/commonmarker.h +0 -16
  47. data/ext/commonmarker/config.h +0 -76
  48. data/ext/commonmarker/core-extensions.c +0 -27
  49. data/ext/commonmarker/entities.inc +0 -2138
  50. data/ext/commonmarker/ext_scanners.c +0 -879
  51. data/ext/commonmarker/ext_scanners.h +0 -24
  52. data/ext/commonmarker/footnotes.c +0 -63
  53. data/ext/commonmarker/footnotes.h +0 -27
  54. data/ext/commonmarker/houdini.h +0 -57
  55. data/ext/commonmarker/houdini_href_e.c +0 -100
  56. data/ext/commonmarker/houdini_html_e.c +0 -66
  57. data/ext/commonmarker/houdini_html_u.c +0 -149
  58. data/ext/commonmarker/html.c +0 -502
  59. data/ext/commonmarker/html.h +0 -27
  60. data/ext/commonmarker/inlines.c +0 -1788
  61. data/ext/commonmarker/inlines.h +0 -29
  62. data/ext/commonmarker/iterator.c +0 -159
  63. data/ext/commonmarker/iterator.h +0 -26
  64. data/ext/commonmarker/latex.c +0 -468
  65. data/ext/commonmarker/linked_list.c +0 -37
  66. data/ext/commonmarker/man.c +0 -274
  67. data/ext/commonmarker/map.c +0 -129
  68. data/ext/commonmarker/map.h +0 -44
  69. data/ext/commonmarker/node.c +0 -1045
  70. data/ext/commonmarker/node.h +0 -167
  71. data/ext/commonmarker/parser.h +0 -59
  72. data/ext/commonmarker/plaintext.c +0 -218
  73. data/ext/commonmarker/plugin.c +0 -36
  74. data/ext/commonmarker/plugin.h +0 -34
  75. data/ext/commonmarker/references.c +0 -43
  76. data/ext/commonmarker/references.h +0 -26
  77. data/ext/commonmarker/registry.c +0 -63
  78. data/ext/commonmarker/registry.h +0 -24
  79. data/ext/commonmarker/render.c +0 -213
  80. data/ext/commonmarker/render.h +0 -62
  81. data/ext/commonmarker/scanners.c +0 -14056
  82. data/ext/commonmarker/scanners.h +0 -70
  83. data/ext/commonmarker/scanners.re +0 -341
  84. data/ext/commonmarker/strikethrough.c +0 -167
  85. data/ext/commonmarker/strikethrough.h +0 -9
  86. data/ext/commonmarker/syntax_extension.c +0 -149
  87. data/ext/commonmarker/syntax_extension.h +0 -34
  88. data/ext/commonmarker/table.c +0 -917
  89. data/ext/commonmarker/table.h +0 -12
  90. data/ext/commonmarker/tagfilter.c +0 -60
  91. data/ext/commonmarker/tagfilter.h +0 -8
  92. data/ext/commonmarker/tasklist.c +0 -156
  93. data/ext/commonmarker/tasklist.h +0 -8
  94. data/ext/commonmarker/utf8.c +0 -317
  95. data/ext/commonmarker/utf8.h +0 -35
  96. data/ext/commonmarker/xml.c +0 -182
  97. data/lib/commonmarker/renderer/html_renderer.rb +0 -256
@@ -1,42 +0,0 @@
1
-
2
- #ifndef CMARK_GFM_EXPORT_H
3
- #define CMARK_GFM_EXPORT_H
4
-
5
- #ifdef CMARK_GFM_STATIC_DEFINE
6
- # define CMARK_GFM_EXPORT
7
- # define CMARK_GFM_NO_EXPORT
8
- #else
9
- # ifndef CMARK_GFM_EXPORT
10
- # ifdef libcmark_gfm_EXPORTS
11
- /* We are building this library */
12
- # define CMARK_GFM_EXPORT __attribute__((visibility("default")))
13
- # else
14
- /* We are using this library */
15
- # define CMARK_GFM_EXPORT __attribute__((visibility("default")))
16
- # endif
17
- # endif
18
-
19
- # ifndef CMARK_GFM_NO_EXPORT
20
- # define CMARK_GFM_NO_EXPORT __attribute__((visibility("hidden")))
21
- # endif
22
- #endif
23
-
24
- #ifndef CMARK_GFM_DEPRECATED
25
- # define CMARK_GFM_DEPRECATED __attribute__ ((__deprecated__))
26
- #endif
27
-
28
- #ifndef CMARK_GFM_DEPRECATED_EXPORT
29
- # define CMARK_GFM_DEPRECATED_EXPORT CMARK_GFM_EXPORT CMARK_GFM_DEPRECATED
30
- #endif
31
-
32
- #ifndef CMARK_GFM_DEPRECATED_NO_EXPORT
33
- # define CMARK_GFM_DEPRECATED_NO_EXPORT CMARK_GFM_NO_EXPORT CMARK_GFM_DEPRECATED
34
- #endif
35
-
36
- #if 0 /* DEFINE_NO_DEPRECATED */
37
- # ifndef CMARK_GFM_NO_DEPRECATED
38
- # define CMARK_GFM_NO_DEPRECATED
39
- # endif
40
- #endif
41
-
42
- #endif /* CMARK_GFM_EXPORT_H */
@@ -1,7 +0,0 @@
1
- #ifndef CMARK_GFM_VERSION_H
2
- #define CMARK_GFM_VERSION_H
3
-
4
- #define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 11)
5
- #define CMARK_GFM_VERSION_STRING "0.29.0.gfm.11"
6
-
7
- #endif
@@ -1,55 +0,0 @@
1
- #include <stdlib.h>
2
- #include <assert.h>
3
- #include <stdio.h>
4
- #include "registry.h"
5
- #include "node.h"
6
- #include "houdini.h"
7
- #include "cmark-gfm.h"
8
- #include "buffer.h"
9
-
10
- cmark_node_type CMARK_NODE_LAST_BLOCK = CMARK_NODE_FOOTNOTE_DEFINITION;
11
- cmark_node_type CMARK_NODE_LAST_INLINE = CMARK_NODE_FOOTNOTE_REFERENCE;
12
-
13
- int cmark_version(void) { return CMARK_GFM_VERSION; }
14
-
15
- const char *cmark_version_string(void) { return CMARK_GFM_VERSION_STRING; }
16
-
17
- static void *xcalloc(size_t nmem, size_t size) {
18
- void *ptr = calloc(nmem, size);
19
- if (!ptr) {
20
- fprintf(stderr, "[cmark] calloc returned null pointer, aborting\n");
21
- abort();
22
- }
23
- return ptr;
24
- }
25
-
26
- static void *xrealloc(void *ptr, size_t size) {
27
- void *new_ptr = realloc(ptr, size);
28
- if (!new_ptr) {
29
- fprintf(stderr, "[cmark] realloc returned null pointer, aborting\n");
30
- abort();
31
- }
32
- return new_ptr;
33
- }
34
-
35
- static void xfree(void *ptr) {
36
- free(ptr);
37
- }
38
-
39
- cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR = {xcalloc, xrealloc, xfree};
40
-
41
- cmark_mem *cmark_get_default_mem_allocator(void) {
42
- return &CMARK_DEFAULT_MEM_ALLOCATOR;
43
- }
44
-
45
- char *cmark_markdown_to_html(const char *text, size_t len, int options) {
46
- cmark_node *doc;
47
- char *result;
48
-
49
- doc = cmark_parse_document(text, len, options);
50
-
51
- result = cmark_render_html(doc, options, NULL);
52
- cmark_node_free(doc);
53
-
54
- return result;
55
- }
@@ -1,44 +0,0 @@
1
- #include <stdint.h>
2
-
3
- #include "cmark_ctype.h"
4
-
5
- /** 1 = space, 2 = punct, 3 = digit, 4 = alpha, 0 = other
6
- */
7
- static const uint8_t cmark_ctype_class[256] = {
8
- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
9
- /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
10
- /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11
- /* 2 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
12
- /* 3 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
13
- /* 4 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
14
- /* 5 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2,
15
- /* 6 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
16
- /* 7 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0,
17
- /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18
- /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
19
- /* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20
- /* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21
- /* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22
- /* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23
- /* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24
- /* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
25
-
26
- /**
27
- * Returns 1 if c is a "whitespace" character as defined by the spec.
28
- */
29
- int cmark_isspace(char c) { return cmark_ctype_class[(uint8_t)c] == 1; }
30
-
31
- /**
32
- * Returns 1 if c is an ascii punctuation character.
33
- */
34
- int cmark_ispunct(char c) { return cmark_ctype_class[(uint8_t)c] == 2; }
35
-
36
- int cmark_isalnum(char c) {
37
- uint8_t result;
38
- result = cmark_ctype_class[(uint8_t)c];
39
- return (result == 3 || result == 4);
40
- }
41
-
42
- int cmark_isdigit(char c) { return cmark_ctype_class[(uint8_t)c] == 3; }
43
-
44
- int cmark_isalpha(char c) { return cmark_ctype_class[(uint8_t)c] == 4; }
@@ -1,33 +0,0 @@
1
- #ifndef CMARK_CMARK_CTYPE_H
2
- #define CMARK_CMARK_CTYPE_H
3
-
4
- #ifdef __cplusplus
5
- extern "C" {
6
- #endif
7
-
8
- #include "cmark-gfm_export.h"
9
-
10
- /** Locale-independent versions of functions from ctype.h.
11
- * We want cmark to behave the same no matter what the system locale.
12
- */
13
-
14
- CMARK_GFM_EXPORT
15
- int cmark_isspace(char c);
16
-
17
- CMARK_GFM_EXPORT
18
- int cmark_ispunct(char c);
19
-
20
- CMARK_GFM_EXPORT
21
- int cmark_isalnum(char c);
22
-
23
- CMARK_GFM_EXPORT
24
- int cmark_isdigit(char c);
25
-
26
- CMARK_GFM_EXPORT
27
- int cmark_isalpha(char c);
28
-
29
- #ifdef __cplusplus
30
- }
31
- #endif
32
-
33
- #endif
@@ -1,514 +0,0 @@
1
- #include <stdlib.h>
2
- #include <stdio.h>
3
- #include <string.h>
4
- #include <stdint.h>
5
- #include <assert.h>
6
-
7
- #include "config.h"
8
- #include "cmark-gfm.h"
9
- #include "node.h"
10
- #include "buffer.h"
11
- #include "utf8.h"
12
- #include "scanners.h"
13
- #include "render.h"
14
- #include "syntax_extension.h"
15
-
16
- #define OUT(s, wrap, escaping) renderer->out(renderer, node, s, wrap, escaping)
17
- #define LIT(s) renderer->out(renderer, node, s, false, LITERAL)
18
- #define CR() renderer->cr(renderer)
19
- #define BLANKLINE() renderer->blankline(renderer)
20
- #define ENCODED_SIZE 20
21
- #define LISTMARKER_SIZE 20
22
-
23
- // Functions to convert cmark_nodes to commonmark strings.
24
-
25
- static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_node *node,
26
- cmark_escaping escape,
27
- int32_t c, unsigned char nextc) {
28
- bool needs_escaping = false;
29
- bool follows_digit =
30
- renderer->buffer->size > 0 &&
31
- cmark_isdigit(renderer->buffer->ptr[renderer->buffer->size - 1]);
32
- char encoded[ENCODED_SIZE];
33
-
34
- needs_escaping =
35
- c < 0x80 && escape != LITERAL &&
36
- ((escape == NORMAL &&
37
- (c < 0x20 ||
38
- c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
39
- c == '>' || c == '\\' || c == '`' || c == '~' || c == '!' ||
40
- (c == '&' && cmark_isalpha(nextc)) || (c == '!' && nextc == '[') ||
41
- (renderer->begin_content && (c == '-' || c == '+' || c == '=') &&
42
- // begin_content doesn't get set to false til we've passed digits
43
- // at the beginning of line, so...
44
- !follows_digit) ||
45
- (renderer->begin_content && (c == '.' || c == ')') && follows_digit &&
46
- (nextc == 0 || cmark_isspace(nextc))))) ||
47
- (escape == URL &&
48
- (c == '`' || c == '<' || c == '>' || cmark_isspace((char)c) || c == '\\' ||
49
- c == ')' || c == '(')) ||
50
- (escape == TITLE &&
51
- (c == '`' || c == '<' || c == '>' || c == '"' || c == '\\')));
52
-
53
- if (needs_escaping) {
54
- if (escape == URL && cmark_isspace((char)c)) {
55
- // use percent encoding for spaces
56
- snprintf(encoded, ENCODED_SIZE, "%%%2X", c);
57
- cmark_strbuf_puts(renderer->buffer, encoded);
58
- renderer->column += 3;
59
- } else if (cmark_ispunct((char)c)) {
60
- cmark_render_ascii(renderer, "\\");
61
- cmark_render_code_point(renderer, c);
62
- } else { // render as entity
63
- snprintf(encoded, ENCODED_SIZE, "&#%d;", c);
64
- cmark_strbuf_puts(renderer->buffer, encoded);
65
- renderer->column += (int)strlen(encoded);
66
- }
67
- } else {
68
- cmark_render_code_point(renderer, c);
69
- }
70
- }
71
-
72
- static int longest_backtick_sequence(const char *code) {
73
- int longest = 0;
74
- int current = 0;
75
- size_t i = 0;
76
- size_t code_len = strlen(code);
77
- while (i <= code_len) {
78
- if (code[i] == '`') {
79
- current++;
80
- } else {
81
- if (current > longest) {
82
- longest = current;
83
- }
84
- current = 0;
85
- }
86
- i++;
87
- }
88
- return longest;
89
- }
90
-
91
- static int shortest_unused_backtick_sequence(const char *code) {
92
- // note: if the shortest sequence is >= 32, this returns 32
93
- // so as not to overflow the bit array.
94
- uint32_t used = 1;
95
- int current = 0;
96
- size_t i = 0;
97
- size_t code_len = strlen(code);
98
- while (i <= code_len) {
99
- if (code[i] == '`') {
100
- current++;
101
- } else {
102
- if (current > 0 && current < 32) {
103
- used |= (1U << current);
104
- }
105
- current = 0;
106
- }
107
- i++;
108
- }
109
- // return number of first bit that is 0:
110
- i = 0;
111
- while (i < 32 && used & 1) {
112
- used = used >> 1;
113
- i++;
114
- }
115
- return (int)i;
116
- }
117
-
118
- static bool is_autolink(cmark_node *node) {
119
- cmark_chunk *title;
120
- cmark_chunk *url;
121
- cmark_node *link_text;
122
- char *realurl;
123
- int realurllen;
124
-
125
- if (node->type != CMARK_NODE_LINK) {
126
- return false;
127
- }
128
-
129
- url = &node->as.link.url;
130
- if (url->len == 0 || scan_scheme(url, 0) == 0) {
131
- return false;
132
- }
133
-
134
- title = &node->as.link.title;
135
- // if it has a title, we can't treat it as an autolink:
136
- if (title->len > 0) {
137
- return false;
138
- }
139
-
140
- link_text = node->first_child;
141
- if (link_text == NULL) {
142
- return false;
143
- }
144
- cmark_consolidate_text_nodes(link_text);
145
- realurl = (char *)url->data;
146
- realurllen = url->len;
147
- if (strncmp(realurl, "mailto:", 7) == 0) {
148
- realurl += 7;
149
- realurllen -= 7;
150
- }
151
- return (realurllen == link_text->as.literal.len &&
152
- strncmp(realurl, (char *)link_text->as.literal.data,
153
- link_text->as.literal.len) == 0);
154
- }
155
-
156
- static int S_render_node(cmark_renderer *renderer, cmark_node *node,
157
- cmark_event_type ev_type, int options) {
158
- int list_number;
159
- cmark_delim_type list_delim;
160
- int numticks;
161
- bool extra_spaces;
162
- int i;
163
- bool entering = (ev_type == CMARK_EVENT_ENTER);
164
- const char *info, *code, *title;
165
- char fencechar[2] = {'\0', '\0'};
166
- size_t info_len, code_len;
167
- char listmarker[LISTMARKER_SIZE];
168
- const char *emph_delim;
169
- bool first_in_list_item;
170
- bufsize_t marker_width;
171
- bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options) &&
172
- !(CMARK_OPT_HARDBREAKS & options);
173
-
174
- // Don't adjust tight list status til we've started the list.
175
- // Otherwise we loose the blank line between a paragraph and
176
- // a following list.
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
- }
188
- }
189
-
190
- if (node->extension && node->extension->commonmark_render_func) {
191
- node->extension->commonmark_render_func(node->extension, renderer, node, ev_type, options);
192
- return 1;
193
- }
194
-
195
- switch (node->type) {
196
- case CMARK_NODE_DOCUMENT:
197
- break;
198
-
199
- case CMARK_NODE_BLOCK_QUOTE:
200
- if (entering) {
201
- LIT("> ");
202
- renderer->begin_content = true;
203
- cmark_strbuf_puts(renderer->prefix, "> ");
204
- } else {
205
- cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 2);
206
- BLANKLINE();
207
- }
208
- break;
209
-
210
- case CMARK_NODE_LIST:
211
- if (!entering && node->next && (node->next->type == CMARK_NODE_CODE_BLOCK ||
212
- node->next->type == CMARK_NODE_LIST)) {
213
- // this ensures that a following indented code block or list will be
214
- // inteprereted correctly.
215
- CR();
216
- LIT("<!-- end list -->");
217
- BLANKLINE();
218
- }
219
- break;
220
-
221
- case CMARK_NODE_ITEM:
222
- if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
223
- marker_width = 4;
224
- } else {
225
- list_number = cmark_node_get_item_index(node);
226
- list_delim = cmark_node_get_list_delim(node->parent);
227
- // we ensure a width of at least 4 so
228
- // we get nice transition from single digits
229
- // to double
230
- snprintf(listmarker, LISTMARKER_SIZE, "%d%s%s", list_number,
231
- list_delim == CMARK_PAREN_DELIM ? ")" : ".",
232
- list_number < 10 ? " " : " ");
233
- marker_width = (bufsize_t)strlen(listmarker);
234
- }
235
- if (entering) {
236
- if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
237
- LIT(" - ");
238
- renderer->begin_content = true;
239
- } else {
240
- LIT(listmarker);
241
- renderer->begin_content = true;
242
- }
243
- for (i = marker_width; i--;) {
244
- cmark_strbuf_putc(renderer->prefix, ' ');
245
- }
246
- } else {
247
- cmark_strbuf_truncate(renderer->prefix,
248
- renderer->prefix->size - marker_width);
249
- CR();
250
- }
251
- break;
252
-
253
- case CMARK_NODE_HEADING:
254
- if (entering) {
255
- for (i = cmark_node_get_heading_level(node); i > 0; i--) {
256
- LIT("#");
257
- }
258
- LIT(" ");
259
- renderer->begin_content = true;
260
- renderer->no_linebreaks = true;
261
- } else {
262
- renderer->no_linebreaks = false;
263
- BLANKLINE();
264
- }
265
- break;
266
-
267
- case CMARK_NODE_CODE_BLOCK:
268
- first_in_list_item = node->prev == NULL && node->parent &&
269
- node->parent->type == CMARK_NODE_ITEM;
270
-
271
- if (!first_in_list_item) {
272
- BLANKLINE();
273
- }
274
- info = cmark_node_get_fence_info(node);
275
- info_len = strlen(info);
276
- fencechar[0] = strchr(info, '`') == NULL ? '`' : '~';
277
- code = cmark_node_get_literal(node);
278
- code_len = strlen(code);
279
- // use indented form if no info, and code doesn't
280
- // begin or end with a blank line, and code isn't
281
- // first thing in a list item
282
- if (info_len == 0 && (code_len > 2 && !cmark_isspace(code[0]) &&
283
- !(cmark_isspace(code[code_len - 1]) &&
284
- cmark_isspace(code[code_len - 2]))) &&
285
- !first_in_list_item) {
286
- LIT(" ");
287
- cmark_strbuf_puts(renderer->prefix, " ");
288
- OUT(cmark_node_get_literal(node), false, LITERAL);
289
- cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4);
290
- } else {
291
- numticks = longest_backtick_sequence(code) + 1;
292
- if (numticks < 3) {
293
- numticks = 3;
294
- }
295
- for (i = 0; i < numticks; i++) {
296
- LIT(fencechar);
297
- }
298
- LIT(" ");
299
- OUT(info, false, LITERAL);
300
- CR();
301
- OUT(cmark_node_get_literal(node), false, LITERAL);
302
- CR();
303
- for (i = 0; i < numticks; i++) {
304
- LIT(fencechar);
305
- }
306
- }
307
- BLANKLINE();
308
- break;
309
-
310
- case CMARK_NODE_HTML_BLOCK:
311
- BLANKLINE();
312
- OUT(cmark_node_get_literal(node), false, LITERAL);
313
- BLANKLINE();
314
- break;
315
-
316
- case CMARK_NODE_CUSTOM_BLOCK:
317
- BLANKLINE();
318
- OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
319
- false, LITERAL);
320
- BLANKLINE();
321
- break;
322
-
323
- case CMARK_NODE_THEMATIC_BREAK:
324
- BLANKLINE();
325
- LIT("-----");
326
- BLANKLINE();
327
- break;
328
-
329
- case CMARK_NODE_PARAGRAPH:
330
- if (!entering) {
331
- BLANKLINE();
332
- }
333
- break;
334
-
335
- case CMARK_NODE_TEXT:
336
- OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
337
- break;
338
-
339
- case CMARK_NODE_LINEBREAK:
340
- if (!(CMARK_OPT_HARDBREAKS & options)) {
341
- LIT(" ");
342
- }
343
- CR();
344
- break;
345
-
346
- case CMARK_NODE_SOFTBREAK:
347
- if (CMARK_OPT_HARDBREAKS & options) {
348
- LIT(" ");
349
- CR();
350
- } else if (!renderer->no_linebreaks && renderer->width == 0 &&
351
- !(CMARK_OPT_HARDBREAKS & options) &&
352
- !(CMARK_OPT_NOBREAKS & options)) {
353
- CR();
354
- } else {
355
- OUT(" ", allow_wrap, LITERAL);
356
- }
357
- break;
358
-
359
- case CMARK_NODE_CODE:
360
- code = cmark_node_get_literal(node);
361
- code_len = strlen(code);
362
- numticks = shortest_unused_backtick_sequence(code);
363
- extra_spaces = code_len == 0 ||
364
- code[0] == '`' || code[code_len - 1] == '`' ||
365
- code[0] == ' ' || code[code_len - 1] == ' ';
366
- for (i = 0; i < numticks; i++) {
367
- LIT("`");
368
- }
369
- if (extra_spaces) {
370
- LIT(" ");
371
- }
372
- OUT(cmark_node_get_literal(node), allow_wrap, LITERAL);
373
- if (extra_spaces) {
374
- LIT(" ");
375
- }
376
- for (i = 0; i < numticks; i++) {
377
- LIT("`");
378
- }
379
- break;
380
-
381
- case CMARK_NODE_HTML_INLINE:
382
- OUT(cmark_node_get_literal(node), false, LITERAL);
383
- break;
384
-
385
- case CMARK_NODE_CUSTOM_INLINE:
386
- OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
387
- false, LITERAL);
388
- break;
389
-
390
- case CMARK_NODE_STRONG:
391
- if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
392
- if (entering) {
393
- LIT("**");
394
- } else {
395
- LIT("**");
396
- }
397
- }
398
- break;
399
-
400
- case CMARK_NODE_EMPH:
401
- // If we have EMPH(EMPH(x)), we need to use *_x_*
402
- // because **x** is STRONG(x):
403
- if (node->parent && node->parent->type == CMARK_NODE_EMPH &&
404
- node->next == NULL && node->prev == NULL) {
405
- emph_delim = "_";
406
- } else {
407
- emph_delim = "*";
408
- }
409
- if (entering) {
410
- LIT(emph_delim);
411
- } else {
412
- LIT(emph_delim);
413
- }
414
- break;
415
-
416
- case CMARK_NODE_LINK:
417
- if (is_autolink(node)) {
418
- if (entering) {
419
- LIT("<");
420
- if (strncmp(cmark_node_get_url(node), "mailto:", 7) == 0) {
421
- LIT((const char *)cmark_node_get_url(node) + 7);
422
- } else {
423
- LIT((const char *)cmark_node_get_url(node));
424
- }
425
- LIT(">");
426
- // return signal to skip contents of node...
427
- return 0;
428
- }
429
- } else {
430
- if (entering) {
431
- LIT("[");
432
- } else {
433
- LIT("](");
434
- OUT(cmark_node_get_url(node), false, URL);
435
- title = cmark_node_get_title(node);
436
- if (strlen(title) > 0) {
437
- LIT(" \"");
438
- OUT(title, false, TITLE);
439
- LIT("\"");
440
- }
441
- LIT(")");
442
- }
443
- }
444
- break;
445
-
446
- case CMARK_NODE_IMAGE:
447
- if (entering) {
448
- LIT("![");
449
- } else {
450
- LIT("](");
451
- OUT(cmark_node_get_url(node), false, URL);
452
- title = cmark_node_get_title(node);
453
- if (strlen(title) > 0) {
454
- OUT(" \"", allow_wrap, LITERAL);
455
- OUT(title, false, TITLE);
456
- LIT("\"");
457
- }
458
- LIT(")");
459
- }
460
- break;
461
-
462
- case CMARK_NODE_FOOTNOTE_REFERENCE:
463
- if (entering) {
464
- LIT("[^");
465
-
466
- char *footnote_label = renderer->mem->calloc(node->parent_footnote_def->as.literal.len + 1, sizeof(char));
467
- memmove(footnote_label, node->parent_footnote_def->as.literal.data, node->parent_footnote_def->as.literal.len);
468
-
469
- OUT(footnote_label, false, LITERAL);
470
- renderer->mem->free(footnote_label);
471
-
472
- LIT("]");
473
- }
474
- break;
475
-
476
- case CMARK_NODE_FOOTNOTE_DEFINITION:
477
- if (entering) {
478
- renderer->footnote_ix += 1;
479
- LIT("[^");
480
-
481
- char *footnote_label = renderer->mem->calloc(node->as.literal.len + 1, sizeof(char));
482
- memmove(footnote_label, node->as.literal.data, node->as.literal.len);
483
-
484
- OUT(footnote_label, false, LITERAL);
485
- renderer->mem->free(footnote_label);
486
-
487
- LIT("]:\n");
488
-
489
- cmark_strbuf_puts(renderer->prefix, " ");
490
- } else {
491
- cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4);
492
- }
493
- break;
494
-
495
- default:
496
- assert(false);
497
- break;
498
- }
499
-
500
- return 1;
501
- }
502
-
503
- char *cmark_render_commonmark(cmark_node *root, int options, int width) {
504
- return cmark_render_commonmark_with_mem(root, options, width, cmark_node_mem(root));
505
- }
506
-
507
- char *cmark_render_commonmark_with_mem(cmark_node *root, int options, int width, cmark_mem *mem) {
508
- if (options & CMARK_OPT_HARDBREAKS) {
509
- // disable breaking on width, since it has
510
- // a different meaning with OPT_HARDBREAKS
511
- width = 0;
512
- }
513
- return cmark_render(mem, root, options, width, outc, S_render_node);
514
- }