commonmarker 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of commonmarker might be problematic. Click here for more details.

Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/ext/commonmarker/cmark/CMakeLists.txt +10 -4
  3. data/ext/commonmarker/cmark/Makefile +5 -5
  4. data/ext/commonmarker/cmark/api_test/CMakeLists.txt +1 -1
  5. data/ext/commonmarker/cmark/api_test/main.c +16 -0
  6. data/ext/commonmarker/cmark/build/CMakeCache.txt +3 -4
  7. data/ext/commonmarker/cmark/build/CMakeFiles/2.8.10.1/CMakeSystem.cmake +4 -4
  8. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +12 -12
  9. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +97 -142
  10. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile.cmake +0 -1
  11. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +1 -1
  12. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/link.txt +1 -1
  13. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +1 -1
  14. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +23 -23
  15. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +2 -2
  16. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -1
  17. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/blocks.c.o +0 -0
  18. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/buffer.c.o +0 -0
  19. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark.c.o +0 -0
  20. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/commonmark.c.o +0 -0
  21. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
  22. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/html.c.o +0 -0
  23. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/inlines.c.o +0 -0
  24. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/node.c.o +0 -0
  25. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/references.c.o +0 -0
  26. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/render.c.o +0 -0
  27. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/scanners.c.o +0 -0
  28. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/utf8.c.o +0 -0
  29. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/xml.c.o +0 -0
  30. data/ext/commonmarker/cmark/build/src/cmake_install.cmake +3 -3
  31. data/ext/commonmarker/cmark/build/src/cmark_version.h +2 -2
  32. data/ext/commonmarker/cmark/build/src/config.h +6 -6
  33. data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
  34. data/ext/commonmarker/cmark/build/src/libcmark.pc +1 -1
  35. data/ext/commonmarker/cmark/build/testdir/CTestTestfile.cmake +4 -4
  36. data/ext/commonmarker/cmark/changelog.txt +46 -0
  37. data/ext/commonmarker/cmark/man/man3/cmark.3 +21 -20
  38. data/ext/commonmarker/cmark/src/CMakeLists.txt +4 -6
  39. data/ext/commonmarker/cmark/src/bench.h +8 -8
  40. data/ext/commonmarker/cmark/src/blocks.c +917 -947
  41. data/ext/commonmarker/cmark/src/buffer.c +213 -288
  42. data/ext/commonmarker/cmark/src/buffer.h +19 -21
  43. data/ext/commonmarker/cmark/src/chunk.h +78 -82
  44. data/ext/commonmarker/cmark/src/cmark.c +9 -17
  45. data/ext/commonmarker/cmark/src/cmark.h +113 -157
  46. data/ext/commonmarker/cmark/src/cmark_ctype.c +24 -35
  47. data/ext/commonmarker/cmark/src/commonmark.c +390 -425
  48. data/ext/commonmarker/cmark/src/config.h.in +6 -6
  49. data/ext/commonmarker/cmark/src/houdini.h +21 -15
  50. data/ext/commonmarker/cmark/src/houdini_href_e.c +50 -57
  51. data/ext/commonmarker/cmark/src/houdini_html_e.c +36 -51
  52. data/ext/commonmarker/cmark/src/houdini_html_u.c +119 -124
  53. data/ext/commonmarker/cmark/src/html.c +289 -307
  54. data/ext/commonmarker/cmark/src/inlines.c +976 -1030
  55. data/ext/commonmarker/cmark/src/inlines.h +4 -2
  56. data/ext/commonmarker/cmark/src/iterator.c +96 -126
  57. data/ext/commonmarker/cmark/src/iterator.h +5 -5
  58. data/ext/commonmarker/cmark/src/latex.c +379 -401
  59. data/ext/commonmarker/cmark/src/main.c +168 -175
  60. data/ext/commonmarker/cmark/src/man.c +212 -226
  61. data/ext/commonmarker/cmark/src/node.c +746 -839
  62. data/ext/commonmarker/cmark/src/node.h +47 -48
  63. data/ext/commonmarker/cmark/src/parser.h +14 -14
  64. data/ext/commonmarker/cmark/src/references.c +101 -111
  65. data/ext/commonmarker/cmark/src/references.h +10 -8
  66. data/ext/commonmarker/cmark/src/render.c +144 -167
  67. data/ext/commonmarker/cmark/src/render.h +22 -41
  68. data/ext/commonmarker/cmark/src/scanners.c +27695 -20903
  69. data/ext/commonmarker/cmark/src/scanners.h +2 -1
  70. data/ext/commonmarker/cmark/src/scanners.re +1 -1
  71. data/ext/commonmarker/cmark/src/utf8.c +276 -419
  72. data/ext/commonmarker/cmark/src/utf8.h +6 -6
  73. data/ext/commonmarker/cmark/src/xml.c +129 -144
  74. data/ext/commonmarker/cmark/test/CMakeLists.txt +4 -4
  75. data/ext/commonmarker/cmark/test/smart_punct.txt +8 -0
  76. data/ext/commonmarker/cmark/test/spec.txt +109 -47
  77. data/lib/commonmarker/version.rb +1 -1
  78. metadata +2 -2
@@ -20,443 +20,408 @@
20
20
 
21
21
  // Functions to convert cmark_nodes to commonmark strings.
22
22
 
23
- static inline void outc(cmark_renderer *renderer,
24
- cmark_escaping escape,
25
- int32_t c,
26
- unsigned char nextc)
27
- {
28
- bool needs_escaping = false;
29
- needs_escaping =
30
- escape != LITERAL &&
31
- ((escape == NORMAL &&
32
- (c == '*' || c == '_' || c == '[' || c == ']' || c == '#' ||
33
- c == '<' || c == '>' || c == '\\' || c == '`' || c == '!' ||
34
- (c == '&' && isalpha(nextc)) ||
35
- (c == '!' && nextc == '[') ||
36
- (renderer->begin_line &&
37
- (c == '-' || c == '+' || c == '=')) ||
38
- ((c == '.' || c == ')') &&
39
- isdigit(renderer->buffer->ptr[renderer->buffer->size - 1])))) ||
40
- (escape == URL &&
41
- (c == '`' || c == '<' || c == '>' || isspace(c) ||
42
- c == '\\' || c == ')' || c == '(')) ||
43
- (escape == TITLE &&
44
- (c == '`' || c == '<' || c == '>' || c == '"' ||
45
- c == '\\')));
46
-
47
- if (needs_escaping) {
48
- if (isspace(c)) {
49
- // use percent encoding for spaces
50
- cmark_strbuf_printf(renderer->buffer, "%%%2x", c);
51
- renderer->column += 3;
52
- } else {
53
- cmark_render_ascii(renderer, "\\");
54
- cmark_render_code_point(renderer, c);
55
- }
56
- } else {
57
- cmark_render_code_point(renderer, c);
58
- }
23
+ static inline void outc(cmark_renderer *renderer, cmark_escaping escape,
24
+ int32_t c, unsigned char nextc) {
25
+ bool needs_escaping = false;
26
+ char encoded[20];
27
+
28
+ needs_escaping =
29
+ escape != LITERAL &&
30
+ ((escape == NORMAL &&
31
+ (c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
32
+ c == '>' || c == '\\' || c == '`' || c == '!' ||
33
+ (c == '&' && isalpha(nextc)) || (c == '!' && nextc == '[') ||
34
+ (renderer->begin_line && (c == '-' || c == '+' || c == '=')) ||
35
+ ((c == '.' || c == ')') &&
36
+ isdigit(renderer->buffer->ptr[renderer->buffer->size - 1])))) ||
37
+ (escape == URL && (c == '`' || c == '<' || c == '>' || isspace(c) ||
38
+ c == '\\' || c == ')' || c == '(')) ||
39
+ (escape == TITLE &&
40
+ (c == '`' || c == '<' || c == '>' || c == '"' || c == '\\')));
41
+
42
+ if (needs_escaping) {
43
+ if (isspace(c)) {
44
+ // use percent encoding for spaces
45
+ sprintf(encoded, "%%%2x", c);
46
+ cmark_strbuf_puts(renderer->buffer, encoded);
47
+ renderer->column += 3;
48
+ } else {
49
+ cmark_render_ascii(renderer, "\\");
50
+ cmark_render_code_point(renderer, c);
51
+ }
52
+ } else {
53
+ cmark_render_code_point(renderer, c);
54
+ }
59
55
  }
60
56
 
61
- static int
62
- longest_backtick_sequence(const char *code)
63
- {
64
- int longest = 0;
65
- int current = 0;
66
- size_t i = 0;
67
- size_t code_len = safe_strlen(code);
68
- while (i <= code_len) {
69
- if (code[i] == '`') {
70
- current++;
71
- } else {
72
- if (current > longest) {
73
- longest = current;
74
- }
75
- current = 0;
76
- }
77
- i++;
78
- }
79
- return longest;
57
+ static int longest_backtick_sequence(const char *code) {
58
+ int longest = 0;
59
+ int current = 0;
60
+ size_t i = 0;
61
+ size_t code_len = safe_strlen(code);
62
+ while (i <= code_len) {
63
+ if (code[i] == '`') {
64
+ current++;
65
+ } else {
66
+ if (current > longest) {
67
+ longest = current;
68
+ }
69
+ current = 0;
70
+ }
71
+ i++;
72
+ }
73
+ return longest;
80
74
  }
81
75
 
82
- static int
83
- shortest_unused_backtick_sequence(const char *code)
84
- {
85
- int32_t used = 1;
86
- int current = 0;
87
- size_t i = 0;
88
- size_t code_len = safe_strlen(code);
89
- while (i <= code_len) {
90
- if (code[i] == '`') {
91
- current++;
92
- } else {
93
- if (current) {
94
- used |= (1 << current);
95
- }
96
- current = 0;
97
- }
98
- i++;
99
- }
100
- // return number of first bit that is 0:
101
- i = 0;
102
- while (used & 1) {
103
- used = used >> 1;
104
- i++;
105
- }
106
- return i;
76
+ static int shortest_unused_backtick_sequence(const char *code) {
77
+ int32_t used = 1;
78
+ int current = 0;
79
+ size_t i = 0;
80
+ size_t code_len = safe_strlen(code);
81
+ while (i <= code_len) {
82
+ if (code[i] == '`') {
83
+ current++;
84
+ } else {
85
+ if (current) {
86
+ used |= (1 << current);
87
+ }
88
+ current = 0;
89
+ }
90
+ i++;
91
+ }
92
+ // return number of first bit that is 0:
93
+ i = 0;
94
+ while (used & 1) {
95
+ used = used >> 1;
96
+ i++;
97
+ }
98
+ return i;
107
99
  }
108
100
 
109
- static bool
110
- is_autolink(cmark_node *node)
111
- {
112
- cmark_chunk *title;
113
- cmark_chunk *url;
114
- cmark_node *link_text;
115
- char *realurl;
116
- int realurllen;
117
-
118
- if (node->type != CMARK_NODE_LINK) {
119
- return false;
120
- }
121
-
122
- url = &node->as.link.url;
123
- if (url->len == 0 || scan_scheme(url, 0) == 0) {
124
- return false;
125
- }
126
-
127
- title = &node->as.link.title;
128
- // if it has a title, we can't treat it as an autolink:
129
- if (title->len > 0) {
130
- return false;
131
- }
132
-
133
- link_text = node->first_child;
134
- cmark_consolidate_text_nodes(link_text);
135
- realurl = (char*)url->data;
136
- realurllen = url->len;
137
- if (strncmp(realurl, "mailto:", 7) == 0) {
138
- realurl += 7;
139
- realurllen -= 7;
140
- }
141
- return (realurllen == link_text->as.literal.len &&
142
- strncmp(realurl,
143
- (char*)link_text->as.literal.data,
144
- link_text->as.literal.len) == 0);
101
+ static bool is_autolink(cmark_node *node) {
102
+ cmark_chunk *title;
103
+ cmark_chunk *url;
104
+ cmark_node *link_text;
105
+ char *realurl;
106
+ int realurllen;
107
+
108
+ if (node->type != CMARK_NODE_LINK) {
109
+ return false;
110
+ }
111
+
112
+ url = &node->as.link.url;
113
+ if (url->len == 0 || scan_scheme(url, 0) == 0) {
114
+ return false;
115
+ }
116
+
117
+ title = &node->as.link.title;
118
+ // if it has a title, we can't treat it as an autolink:
119
+ if (title->len > 0) {
120
+ return false;
121
+ }
122
+
123
+ link_text = node->first_child;
124
+ cmark_consolidate_text_nodes(link_text);
125
+ realurl = (char *)url->data;
126
+ realurllen = url->len;
127
+ if (strncmp(realurl, "mailto:", 7) == 0) {
128
+ realurl += 7;
129
+ realurllen -= 7;
130
+ }
131
+ return (realurllen == link_text->as.literal.len &&
132
+ strncmp(realurl, (char *)link_text->as.literal.data,
133
+ link_text->as.literal.len) == 0);
145
134
  }
146
135
 
147
136
  // if node is a block node, returns node.
148
137
  // otherwise returns first block-level node that is an ancestor of node.
149
- static cmark_node*
150
- get_containing_block(cmark_node *node)
151
- {
152
- while (node &&
153
- (node->type < CMARK_NODE_FIRST_BLOCK ||
154
- node->type > CMARK_NODE_LAST_BLOCK)) {
155
- node = node->parent;
156
- }
157
- return node;
138
+ static cmark_node *get_containing_block(cmark_node *node) {
139
+ while (node && (node->type < CMARK_NODE_FIRST_BLOCK ||
140
+ node->type > CMARK_NODE_LAST_BLOCK)) {
141
+ node = node->parent;
142
+ }
143
+ return node;
158
144
  }
159
145
 
160
- static int
161
- S_render_node(cmark_renderer *renderer,
162
- cmark_node *node,
163
- cmark_event_type ev_type,
164
- int options)
165
- {
166
- cmark_node *tmp;
167
- int list_number;
168
- cmark_delim_type list_delim;
169
- int numticks;
170
- int i;
171
- bool entering = (ev_type == CMARK_EVENT_ENTER);
172
- const char *info, *code, *title;
173
- size_t info_len, code_len;
174
- cmark_strbuf listmarker = GH_BUF_INIT;
175
- char *emph_delim;
176
- bufsize_t marker_width;
177
-
178
- // Don't adjust tight list status til we've started the list.
179
- // Otherwise we loose the blank line between a paragraph and
180
- // a following list.
181
- if (!(node->type == CMARK_NODE_ITEM && node->prev == NULL &&
182
- entering)) {
183
- tmp = get_containing_block(node);
184
- renderer->in_tight_list_item =
185
- (tmp->type == CMARK_NODE_ITEM &&
186
- cmark_node_get_list_tight(tmp->parent)) ||
187
- (tmp &&
188
- tmp->parent &&
189
- tmp->parent->type == CMARK_NODE_ITEM &&
190
- cmark_node_get_list_tight(tmp->parent->parent));
191
- }
192
-
193
- switch (node->type) {
194
- case CMARK_NODE_DOCUMENT:
195
- break;
196
-
197
- case CMARK_NODE_BLOCK_QUOTE:
198
- if (entering) {
199
- LIT("> ");
200
- cmark_strbuf_puts(renderer->prefix, "> ");
201
- } else {
202
- cmark_strbuf_truncate(renderer->prefix,
203
- renderer->prefix->size - 2);
204
- BLANKLINE();
205
- }
206
- break;
207
-
208
- case CMARK_NODE_LIST:
209
- if (!entering && node->next &&
210
- (node->next->type == CMARK_NODE_CODE_BLOCK ||
211
- node->next->type == CMARK_NODE_LIST)) {
212
- // this ensures 2 blank lines after list,
213
- // if before code block or list:
214
- LIT("\n");
215
- }
216
- break;
217
-
218
- case CMARK_NODE_ITEM:
219
- if (cmark_node_get_list_type(node->parent) ==
220
- CMARK_BULLET_LIST) {
221
- marker_width = 2;
222
- } else {
223
- list_number = cmark_node_get_list_start(node->parent);
224
- list_delim = cmark_node_get_list_delim(node->parent);
225
- tmp = node;
226
- while (tmp->prev) {
227
- tmp = tmp->prev;
228
- list_number += 1;
229
- }
230
- // we ensure a width of at least 4 so
231
- // we get nice transition from single digits
232
- // to double
233
- cmark_strbuf_printf(&listmarker,
234
- "%d%s%s", list_number,
235
- list_delim == CMARK_PAREN_DELIM ?
236
- ")" : ".",
237
- list_number < 10 ? " " : " ");
238
- marker_width = listmarker.size;
239
- }
240
- if (entering) {
241
- if (cmark_node_get_list_type(node->parent) ==
242
- CMARK_BULLET_LIST) {
243
- LIT("* ");
244
- cmark_strbuf_puts(renderer->prefix, " ");
245
- } else {
246
- LIT((char *)listmarker.ptr);
247
- for (i = marker_width; i--;) {
248
- cmark_strbuf_putc(renderer->prefix, ' ');
249
- }
250
- }
251
- } else {
252
- cmark_strbuf_truncate(renderer->prefix,
253
- renderer->prefix->size -
254
- marker_width);
255
- CR();
256
- }
257
- cmark_strbuf_free(&listmarker);
258
- break;
259
-
260
- case CMARK_NODE_HEADER:
261
- if (entering) {
262
- for (int i = cmark_node_get_header_level(node); i > 0; i--) {
263
- LIT("#");
264
- }
265
- LIT(" ");
266
- renderer->no_wrap = true;
267
- } else {
268
- renderer->no_wrap = false;
269
- BLANKLINE();
270
- }
271
- break;
272
-
273
- case CMARK_NODE_CODE_BLOCK:
274
- BLANKLINE();
275
- info = cmark_node_get_fence_info(node);
276
- info_len = safe_strlen(info);
277
- code = cmark_node_get_literal(node);
278
- code_len = safe_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 &&
283
- (code_len > 2 &&
284
- !isspace(code[0]) &&
285
- !(isspace(code[code_len - 1]) &&
286
- isspace(code[code_len - 2]))) &&
287
- !(node->prev == NULL && node->parent &&
288
- node->parent->type == CMARK_NODE_ITEM)) {
289
- LIT(" ");
290
- cmark_strbuf_puts(renderer->prefix, " ");
291
- OUT(cmark_node_get_literal(node), false, LITERAL);
292
- cmark_strbuf_truncate(renderer->prefix,
293
- renderer->prefix->size - 4);
294
- } else {
295
- numticks = longest_backtick_sequence(code) + 1;
296
- if (numticks < 3) {
297
- numticks = 3;
298
- }
299
- for (i = 0; i < numticks; i++) {
300
- LIT("`");
301
- }
302
- LIT(" ");
303
- OUT(info, false, LITERAL);
304
- CR();
305
- OUT(cmark_node_get_literal(node), false, LITERAL);
306
- CR();
307
- for (i = 0; i < numticks; i++) {
308
- LIT("`");
309
- }
310
- }
311
- BLANKLINE();
312
- break;
313
-
314
- case CMARK_NODE_HTML:
315
- BLANKLINE();
316
- OUT(cmark_node_get_literal(node), false, LITERAL);
317
- BLANKLINE();
318
- break;
319
-
320
- case CMARK_NODE_HRULE:
321
- BLANKLINE();
322
- LIT("-----");
323
- BLANKLINE();
324
- break;
325
-
326
- case CMARK_NODE_PARAGRAPH:
327
- if (!entering) {
328
- BLANKLINE();
329
- }
330
- break;
331
-
332
- case CMARK_NODE_TEXT:
333
- OUT(cmark_node_get_literal(node), true, NORMAL);
334
- break;
335
-
336
- case CMARK_NODE_LINEBREAK:
337
- if (!(CMARK_OPT_HARDBREAKS & options)) {
338
- LIT("\\");
339
- }
340
- CR();
341
- break;
342
-
343
- case CMARK_NODE_SOFTBREAK:
344
- if (renderer->width == 0 &&
345
- !(CMARK_OPT_HARDBREAKS & options)) {
346
- CR();
347
- } else {
348
- OUT(" ", true, LITERAL);
349
- }
350
- break;
351
-
352
- case CMARK_NODE_CODE:
353
- code = cmark_node_get_literal(node);
354
- code_len = safe_strlen(code);
355
- numticks = shortest_unused_backtick_sequence(code);
356
- for (i = 0; i < numticks; i++) {
357
- LIT("`");
358
- }
359
- if (code_len == 0 || code[0] == '`') {
360
- LIT(" ");
361
- }
362
- OUT(cmark_node_get_literal(node), true, LITERAL);
363
- if (code_len == 0 || code[code_len - 1] == '`') {
364
- LIT(" ");
365
- }
366
- for (i = 0; i < numticks; i++) {
367
- LIT("`");
368
- }
369
- break;
370
-
371
- case CMARK_NODE_INLINE_HTML:
372
- OUT(cmark_node_get_literal(node), false, LITERAL);
373
- break;
374
-
375
- case CMARK_NODE_STRONG:
376
- if (entering) {
377
- LIT("**");
378
- } else {
379
- LIT("**");
380
- }
381
- break;
382
-
383
- case CMARK_NODE_EMPH:
384
- // If we have EMPH(EMPH(x)), we need to use *_x_*
385
- // because **x** is STRONG(x):
386
- if (node->parent && node->parent->type == CMARK_NODE_EMPH &&
387
- node->next == NULL && node->prev == NULL) {
388
- emph_delim = "_";
389
- } else {
390
- emph_delim = "*";
391
- }
392
- if (entering) {
393
- LIT(emph_delim);
394
- } else {
395
- LIT(emph_delim);
396
- }
397
- break;
398
-
399
- case CMARK_NODE_LINK:
400
- if (is_autolink(node)) {
401
- if (entering) {
402
- LIT("<");
403
- if (strncmp(cmark_node_get_url(node),
404
- "mailto:", 7) == 0) {
405
- LIT((char *)cmark_node_get_url(node) + 7);
406
- } else {
407
- LIT((char *)cmark_node_get_url(node));
408
- }
409
- LIT(">");
410
- // return signal to skip contents of node...
411
- return 0;
412
- }
413
- } else {
414
- if (entering) {
415
- LIT("[");
416
- } else {
417
- LIT("](");
418
- OUT(cmark_node_get_url(node), false, URL);
419
- title = cmark_node_get_title(node);
420
- if (safe_strlen(title) > 0) {
421
- LIT(" \"");
422
- OUT(title, false, TITLE);
423
- LIT("\"");
424
- }
425
- LIT(")");
426
- }
427
- }
428
- break;
429
-
430
- case CMARK_NODE_IMAGE:
431
- if (entering) {
432
- LIT("![");
433
- } else {
434
- LIT("](");
435
- OUT(cmark_node_get_url(node), false, URL);
436
- title = cmark_node_get_title(node);
437
- if (safe_strlen(title) > 0) {
438
- OUT(" \"", true, LITERAL);
439
- OUT(title, false, TITLE);
440
- LIT("\"");
441
- }
442
- LIT(")");
443
- }
444
- break;
445
-
446
- default:
447
- assert(false);
448
- break;
449
- }
450
-
451
- return 1;
146
+ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
147
+ cmark_event_type ev_type, int options) {
148
+ cmark_node *tmp;
149
+ int list_number;
150
+ cmark_delim_type list_delim;
151
+ int numticks;
152
+ int i;
153
+ bool entering = (ev_type == CMARK_EVENT_ENTER);
154
+ const char *info, *code, *title;
155
+ size_t info_len, code_len;
156
+ char listmarker[20];
157
+ char *emph_delim;
158
+ bufsize_t marker_width;
159
+
160
+ // Don't adjust tight list status til we've started the list.
161
+ // Otherwise we loose the blank line between a paragraph and
162
+ // a following list.
163
+ if (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) {
164
+ tmp = get_containing_block(node);
165
+ renderer->in_tight_list_item =
166
+ (tmp->type == CMARK_NODE_ITEM &&
167
+ cmark_node_get_list_tight(tmp->parent)) ||
168
+ (tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
169
+ cmark_node_get_list_tight(tmp->parent->parent));
170
+ }
171
+
172
+ switch (node->type) {
173
+ case CMARK_NODE_DOCUMENT:
174
+ break;
175
+
176
+ case CMARK_NODE_BLOCK_QUOTE:
177
+ if (entering) {
178
+ LIT("> ");
179
+ cmark_strbuf_puts(renderer->prefix, "> ");
180
+ } else {
181
+ cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 2);
182
+ BLANKLINE();
183
+ }
184
+ break;
185
+
186
+ case CMARK_NODE_LIST:
187
+ if (!entering && node->next && (node->next->type == CMARK_NODE_CODE_BLOCK ||
188
+ node->next->type == CMARK_NODE_LIST)) {
189
+ // this ensures 2 blank lines after list,
190
+ // if before code block or list:
191
+ LIT("\n");
192
+ }
193
+ break;
194
+
195
+ case CMARK_NODE_ITEM:
196
+ if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
197
+ marker_width = 2;
198
+ } else {
199
+ list_number = cmark_node_get_list_start(node->parent);
200
+ list_delim = cmark_node_get_list_delim(node->parent);
201
+ tmp = node;
202
+ while (tmp->prev) {
203
+ tmp = tmp->prev;
204
+ list_number += 1;
205
+ }
206
+ // we ensure a width of at least 4 so
207
+ // we get nice transition from single digits
208
+ // to double
209
+ sprintf(listmarker, "%d%s%s", list_number,
210
+ list_delim == CMARK_PAREN_DELIM ? ")" : ".",
211
+ list_number < 10 ? " " : " ");
212
+ marker_width = safe_strlen(listmarker);
213
+ }
214
+ if (entering) {
215
+ if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
216
+ LIT("* ");
217
+ cmark_strbuf_puts(renderer->prefix, " ");
218
+ } else {
219
+ LIT(listmarker);
220
+ for (i = marker_width; i--;) {
221
+ cmark_strbuf_putc(renderer->prefix, ' ');
222
+ }
223
+ }
224
+ } else {
225
+ cmark_strbuf_truncate(renderer->prefix,
226
+ renderer->prefix->size - marker_width);
227
+ CR();
228
+ }
229
+ break;
230
+
231
+ case CMARK_NODE_HEADER:
232
+ if (entering) {
233
+ for (int i = cmark_node_get_header_level(node); i > 0; i--) {
234
+ LIT("#");
235
+ }
236
+ LIT(" ");
237
+ renderer->no_wrap = true;
238
+ } else {
239
+ renderer->no_wrap = false;
240
+ BLANKLINE();
241
+ }
242
+ break;
243
+
244
+ case CMARK_NODE_CODE_BLOCK:
245
+ BLANKLINE();
246
+ info = cmark_node_get_fence_info(node);
247
+ info_len = safe_strlen(info);
248
+ code = cmark_node_get_literal(node);
249
+ code_len = safe_strlen(code);
250
+ // use indented form if no info, and code doesn't
251
+ // begin or end with a blank line, and code isn't
252
+ // first thing in a list item
253
+ if (info_len == 0 &&
254
+ (code_len > 2 && !isspace(code[0]) &&
255
+ !(isspace(code[code_len - 1]) && isspace(code[code_len - 2]))) &&
256
+ !(node->prev == NULL && node->parent &&
257
+ node->parent->type == CMARK_NODE_ITEM)) {
258
+ LIT(" ");
259
+ cmark_strbuf_puts(renderer->prefix, " ");
260
+ OUT(cmark_node_get_literal(node), false, LITERAL);
261
+ cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4);
262
+ } else {
263
+ numticks = longest_backtick_sequence(code) + 1;
264
+ if (numticks < 3) {
265
+ numticks = 3;
266
+ }
267
+ for (i = 0; i < numticks; i++) {
268
+ LIT("`");
269
+ }
270
+ LIT(" ");
271
+ OUT(info, false, LITERAL);
272
+ CR();
273
+ OUT(cmark_node_get_literal(node), false, LITERAL);
274
+ CR();
275
+ for (i = 0; i < numticks; i++) {
276
+ LIT("`");
277
+ }
278
+ }
279
+ BLANKLINE();
280
+ break;
281
+
282
+ case CMARK_NODE_HTML:
283
+ BLANKLINE();
284
+ OUT(cmark_node_get_literal(node), false, LITERAL);
285
+ BLANKLINE();
286
+ break;
287
+
288
+ case CMARK_NODE_HRULE:
289
+ BLANKLINE();
290
+ LIT("-----");
291
+ BLANKLINE();
292
+ break;
293
+
294
+ case CMARK_NODE_PARAGRAPH:
295
+ if (!entering) {
296
+ BLANKLINE();
297
+ }
298
+ break;
299
+
300
+ case CMARK_NODE_TEXT:
301
+ OUT(cmark_node_get_literal(node), true, NORMAL);
302
+ break;
303
+
304
+ case CMARK_NODE_LINEBREAK:
305
+ if (!(CMARK_OPT_HARDBREAKS & options)) {
306
+ LIT("\\");
307
+ }
308
+ CR();
309
+ break;
310
+
311
+ case CMARK_NODE_SOFTBREAK:
312
+ if (renderer->width == 0 && !(CMARK_OPT_HARDBREAKS & options)) {
313
+ CR();
314
+ } else {
315
+ OUT(" ", true, LITERAL);
316
+ }
317
+ break;
318
+
319
+ case CMARK_NODE_CODE:
320
+ code = cmark_node_get_literal(node);
321
+ code_len = safe_strlen(code);
322
+ numticks = shortest_unused_backtick_sequence(code);
323
+ for (i = 0; i < numticks; i++) {
324
+ LIT("`");
325
+ }
326
+ if (code_len == 0 || code[0] == '`') {
327
+ LIT(" ");
328
+ }
329
+ OUT(cmark_node_get_literal(node), true, LITERAL);
330
+ if (code_len == 0 || code[code_len - 1] == '`') {
331
+ LIT(" ");
332
+ }
333
+ for (i = 0; i < numticks; i++) {
334
+ LIT("`");
335
+ }
336
+ break;
337
+
338
+ case CMARK_NODE_INLINE_HTML:
339
+ OUT(cmark_node_get_literal(node), false, LITERAL);
340
+ break;
341
+
342
+ case CMARK_NODE_STRONG:
343
+ if (entering) {
344
+ LIT("**");
345
+ } else {
346
+ LIT("**");
347
+ }
348
+ break;
349
+
350
+ case CMARK_NODE_EMPH:
351
+ // If we have EMPH(EMPH(x)), we need to use *_x_*
352
+ // because **x** is STRONG(x):
353
+ if (node->parent && node->parent->type == CMARK_NODE_EMPH &&
354
+ node->next == NULL && node->prev == NULL) {
355
+ emph_delim = "_";
356
+ } else {
357
+ emph_delim = "*";
358
+ }
359
+ if (entering) {
360
+ LIT(emph_delim);
361
+ } else {
362
+ LIT(emph_delim);
363
+ }
364
+ break;
365
+
366
+ case CMARK_NODE_LINK:
367
+ if (is_autolink(node)) {
368
+ if (entering) {
369
+ LIT("<");
370
+ if (strncmp(cmark_node_get_url(node), "mailto:", 7) == 0) {
371
+ LIT((char *)cmark_node_get_url(node) + 7);
372
+ } else {
373
+ LIT((char *)cmark_node_get_url(node));
374
+ }
375
+ LIT(">");
376
+ // return signal to skip contents of node...
377
+ return 0;
378
+ }
379
+ } else {
380
+ if (entering) {
381
+ LIT("[");
382
+ } else {
383
+ LIT("](");
384
+ OUT(cmark_node_get_url(node), false, URL);
385
+ title = cmark_node_get_title(node);
386
+ if (safe_strlen(title) > 0) {
387
+ LIT(" \"");
388
+ OUT(title, false, TITLE);
389
+ LIT("\"");
390
+ }
391
+ LIT(")");
392
+ }
393
+ }
394
+ break;
395
+
396
+ case CMARK_NODE_IMAGE:
397
+ if (entering) {
398
+ LIT("![");
399
+ } else {
400
+ LIT("](");
401
+ OUT(cmark_node_get_url(node), false, URL);
402
+ title = cmark_node_get_title(node);
403
+ if (safe_strlen(title) > 0) {
404
+ OUT(" \"", true, LITERAL);
405
+ OUT(title, false, TITLE);
406
+ LIT("\"");
407
+ }
408
+ LIT(")");
409
+ }
410
+ break;
411
+
412
+ default:
413
+ assert(false);
414
+ break;
415
+ }
416
+
417
+ return 1;
452
418
  }
453
419
 
454
- char *cmark_render_commonmark(cmark_node *root, int options, int width)
455
- {
456
- if (options & CMARK_OPT_HARDBREAKS) {
457
- // disable breaking on width, since it has
458
- // a different meaning with OPT_HARDBREAKS
459
- width = 0;
460
- }
461
- return cmark_render(root, options, width, outc, S_render_node);
420
+ char *cmark_render_commonmark(cmark_node *root, int options, int width) {
421
+ if (options & CMARK_OPT_HARDBREAKS) {
422
+ // disable breaking on width, since it has
423
+ // a different meaning with OPT_HARDBREAKS
424
+ width = 0;
425
+ }
426
+ return cmark_render(root, options, width, outc, S_render_node);
462
427
  }