commonmarker 0.2.1 → 0.3.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/Rakefile +0 -5
  4. data/ext/commonmarker/cmark/CMakeLists.txt +1 -1
  5. data/ext/commonmarker/cmark/Makefile +12 -7
  6. data/ext/commonmarker/cmark/README.md +12 -8
  7. data/ext/commonmarker/cmark/api_test/main.c +18 -2
  8. data/ext/commonmarker/cmark/benchmarks.md +4 -4
  9. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +12 -12
  10. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +106 -106
  11. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile2 +7 -7
  12. data/ext/commonmarker/cmark/build/CMakeFiles/progress.marks +1 -1
  13. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +1 -1
  14. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/link.txt +1 -1
  15. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/progress.marks +1 -1
  16. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/DependInfo.cmake +2 -0
  17. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/build.make +61 -9
  18. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmake_clean.cmake +2 -0
  19. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/link.txt +1 -1
  20. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/progress.make +2 -0
  21. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +3 -1
  22. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +81 -29
  23. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +3 -1
  24. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -1
  25. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/progress.make +19 -17
  26. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/C.includecache +56 -10
  27. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/DependInfo.cmake +2 -0
  28. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/blocks.c.o +0 -0
  29. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/build.make +60 -8
  30. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean.cmake +2 -0
  31. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark.c.o +0 -0
  32. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/commonmark.c.o +0 -0
  33. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.internal +27 -1
  34. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.make +27 -1
  35. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/flags.make +1 -1
  36. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/html.c.o +0 -0
  37. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/inlines.c.o +0 -0
  38. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/latex.c.o +0 -0
  39. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/link.txt +1 -1
  40. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/man.c.o +0 -0
  41. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/progress.make +19 -17
  42. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/render.c.o +0 -0
  43. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/scanners.c.o +0 -0
  44. data/ext/commonmarker/cmark/build/src/CMakeFiles/progress.marks +1 -1
  45. data/ext/commonmarker/cmark/build/src/Makefile +66 -0
  46. data/ext/commonmarker/cmark/build/src/cmake_install.cmake +3 -3
  47. data/ext/commonmarker/cmark/build/src/cmark_version.h +2 -2
  48. data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
  49. data/ext/commonmarker/cmark/build/src/libcmark.pc +1 -1
  50. data/ext/commonmarker/cmark/changelog.txt +144 -0
  51. data/ext/commonmarker/cmark/man/make_man_page.py +3 -3
  52. data/ext/commonmarker/cmark/man/man1/cmark.1 +10 -2
  53. data/ext/commonmarker/cmark/man/man3/cmark.3 +106 -85
  54. data/ext/commonmarker/cmark/src/CMakeLists.txt +5 -2
  55. data/ext/commonmarker/cmark/src/blocks.c +76 -9
  56. data/ext/commonmarker/cmark/src/cmark.c +9 -2
  57. data/ext/commonmarker/cmark/src/cmark.h +16 -3
  58. data/ext/commonmarker/cmark/src/commonmark.c +162 -309
  59. data/ext/commonmarker/cmark/src/html.c +30 -10
  60. data/ext/commonmarker/cmark/src/inlines.c +80 -72
  61. data/ext/commonmarker/cmark/src/latex.c +430 -0
  62. data/ext/commonmarker/cmark/src/main.c +12 -4
  63. data/ext/commonmarker/cmark/src/man.c +118 -156
  64. data/ext/commonmarker/cmark/src/node.h +1 -0
  65. data/ext/commonmarker/cmark/src/render.c +186 -0
  66. data/ext/commonmarker/cmark/src/render.h +66 -0
  67. data/ext/commonmarker/cmark/src/scanners.c +14586 -8944
  68. data/ext/commonmarker/cmark/src/scanners.h +16 -2
  69. data/ext/commonmarker/cmark/src/scanners.re +93 -9
  70. data/ext/commonmarker/cmark/test/__pycache__/cmark.cpython-34.pyc +0 -0
  71. data/ext/commonmarker/cmark/test/__pycache__/normalize.cpython-34.pyc +0 -0
  72. data/ext/commonmarker/cmark/test/smart_punct.txt +74 -10
  73. data/ext/commonmarker/cmark/test/spec.txt +726 -92
  74. data/ext/commonmarker/cmark/test/spec_tests.py +16 -13
  75. data/lib/commonmarker/config.rb +2 -0
  76. data/lib/commonmarker/version.rb +1 -1
  77. data/test/test_helper.rb +1 -1
  78. data/test/test_spec.rb +11 -10
  79. metadata +9 -6
  80. data/ext/commonmarker/cmark/algorithm.md +0 -116
  81. data/ext/commonmarker/cmark/src/debug.h +0 -36
  82. data/test/spec_tests.json +0 -4482
@@ -4,7 +4,6 @@
4
4
  #include <errno.h>
5
5
  #include "config.h"
6
6
  #include "cmark.h"
7
- #include "debug.h"
8
7
  #include "bench.h"
9
8
 
10
9
  #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -17,17 +16,19 @@ typedef enum {
17
16
  FORMAT_HTML,
18
17
  FORMAT_XML,
19
18
  FORMAT_MAN,
20
- FORMAT_COMMONMARK
19
+ FORMAT_COMMONMARK,
20
+ FORMAT_LATEX
21
21
  } writer_format;
22
22
 
23
23
  void print_usage()
24
24
  {
25
25
  printf("Usage: cmark [FILE*]\n");
26
26
  printf("Options:\n");
27
- printf(" --to, -t FORMAT Specify output format (html, xml, man, commonmark)\n");
27
+ printf(" --to, -t FORMAT Specify output format (html, xml, man, commonmark, latex)\n");
28
28
  printf(" --width WIDTH Specify wrap width (default 0 = nowrap)\n");
29
29
  printf(" --sourcepos Include source position attribute\n");
30
30
  printf(" --hardbreaks Treat newlines as hard line breaks\n");
31
+ printf(" --safe Suppress raw HTML and dangerous URLs\n");
31
32
  printf(" --smart Use smart punctuation\n");
32
33
  printf(" --normalize Consolidate adjacent text nodes\n");
33
34
  printf(" --help, -h Print usage information\n");
@@ -47,11 +48,14 @@ static void print_document(cmark_node *document, writer_format writer,
47
48
  result = cmark_render_xml(document, options);
48
49
  break;
49
50
  case FORMAT_MAN:
50
- result = cmark_render_man(document, options);
51
+ result = cmark_render_man(document, options, width);
51
52
  break;
52
53
  case FORMAT_COMMONMARK:
53
54
  result = cmark_render_commonmark(document, options, width);
54
55
  break;
56
+ case FORMAT_LATEX:
57
+ result = cmark_render_latex(document, options, width);
58
+ break;
55
59
  default:
56
60
  fprintf(stderr, "Unknown format %d\n", writer);
57
61
  exit(1);
@@ -90,6 +94,8 @@ int main(int argc, char *argv[])
90
94
  options |= CMARK_OPT_HARDBREAKS;
91
95
  } else if (strcmp(argv[i], "--smart") == 0) {
92
96
  options |= CMARK_OPT_SMART;
97
+ } else if (strcmp(argv[i], "--safe") == 0) {
98
+ options |= CMARK_OPT_SAFE;
93
99
  } else if (strcmp(argv[i], "--normalize") == 0) {
94
100
  options |= CMARK_OPT_NORMALIZE;
95
101
  } else if (strcmp(argv[i], "--validate-utf8") == 0) {
@@ -125,6 +131,8 @@ int main(int argc, char *argv[])
125
131
  writer = FORMAT_XML;
126
132
  } else if (strcmp(argv[i], "commonmark") == 0) {
127
133
  writer = FORMAT_COMMONMARK;
134
+ } else if (strcmp(argv[i], "latex") == 0) {
135
+ writer = FORMAT_LATEX;
128
136
  } else {
129
137
  fprintf(stderr,
130
138
  "Unknown format %s\n", argv[i]);
@@ -8,110 +8,83 @@
8
8
  #include "node.h"
9
9
  #include "buffer.h"
10
10
  #include "utf8.h"
11
+ #include "render.h"
11
12
 
12
- // Functions to convert cmark_nodes to groff man strings.
13
+ #define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping)
14
+ #define LIT(s) renderer->out(renderer, s, false, LITERAL)
15
+ #define CR() renderer->cr(renderer)
16
+ #define BLANKLINE() renderer->blankline(renderer)
13
17
 
14
- static void escape_man(cmark_strbuf *dest, const unsigned char *source, int length)
18
+ // Functions to convert cmark_nodes to groff man strings.
19
+ static
20
+ void S_outc(cmark_renderer *renderer,
21
+ cmark_escaping escape,
22
+ int32_t c,
23
+ unsigned char nextc)
15
24
  {
16
- int32_t c;
17
- int i = 0;
18
- int len;
19
- bool beginLine = true;
25
+ (void)(nextc);
20
26
 
21
- while (i < length) {
22
- len = utf8proc_iterate(source + i, length - i, &c);
23
- if (len == -1) { // error condition
24
- return; // return without rendering anything
27
+ if (escape == LITERAL) {
28
+ cmark_render_code_point(renderer, c);
29
+ return;
30
+ }
31
+
32
+ switch(c) {
33
+ case 46:
34
+ if (renderer->begin_line) {
35
+ cmark_render_ascii(renderer, "\\&.");
36
+ } else {
37
+ cmark_render_code_point(renderer, c);
25
38
  }
26
- switch(c) {
27
- case 46:
28
- if (beginLine) {
29
- cmark_strbuf_puts(dest, "\\&.");
30
- } else {
31
- utf8proc_encode_char(c, dest);
32
- }
33
- break;
34
- case 39:
35
- if (beginLine) {
36
- cmark_strbuf_puts(dest, "\\&'");
37
- } else {
38
- utf8proc_encode_char(c, dest);
39
- }
40
- break;
41
- case 45:
42
- cmark_strbuf_puts(dest, "\\-");
43
- break;
44
- case 92:
45
- cmark_strbuf_puts(dest, "\\e");
46
- break;
47
- case 8216: // left single quote
48
- cmark_strbuf_puts(dest, "\\[oq]");
49
- break;
50
- case 8217: // right single quote
51
- cmark_strbuf_puts(dest, "\\[cq]");
52
- break;
53
- case 8220: // left double quote
54
- cmark_strbuf_puts(dest, "\\[lq]");
55
- break;
56
- case 8221: // right double quote
57
- cmark_strbuf_puts(dest, "\\[rq]");
58
- break;
59
- case 8212: // em dash
60
- cmark_strbuf_puts(dest, "\\[em]");
61
- break;
62
- case 8211: // en dash
63
- cmark_strbuf_puts(dest, "\\[en]");
64
- break;
65
- default:
66
- utf8proc_encode_char(c, dest);
39
+ break;
40
+ case 39:
41
+ if (renderer->begin_line) {
42
+ cmark_render_ascii(renderer, "\\&'");
43
+ } else {
44
+ cmark_render_code_point(renderer, c);
67
45
  }
68
- beginLine = (c == 10);
69
- i += len;
46
+ break;
47
+ case 45:
48
+ cmark_render_ascii(renderer, "\\-");
49
+ break;
50
+ case 92:
51
+ cmark_render_ascii(renderer, "\\e");
52
+ break;
53
+ case 8216: // left single quote
54
+ cmark_render_ascii(renderer, "\\[oq]");
55
+ break;
56
+ case 8217: // right single quote
57
+ cmark_render_ascii(renderer, "\\[cq]");
58
+ break;
59
+ case 8220: // left double quote
60
+ cmark_render_ascii(renderer, "\\[lq]");
61
+ break;
62
+ case 8221: // right double quote
63
+ cmark_render_ascii(renderer, "\\[rq]");
64
+ break;
65
+ case 8212: // em dash
66
+ cmark_render_ascii(renderer, "\\[em]");
67
+ break;
68
+ case 8211: // en dash
69
+ cmark_render_ascii(renderer, "\\[en]");
70
+ break;
71
+ default:
72
+ cmark_render_code_point(renderer, c);
70
73
  }
71
74
  }
72
75
 
73
- static inline void cr(cmark_strbuf *man)
74
- {
75
- if (man->size && man->ptr[man->size - 1] != '\n')
76
- cmark_strbuf_putc(man, '\n');
77
- }
78
-
79
- struct render_state {
80
- cmark_strbuf* man;
81
- cmark_node *plain;
82
- };
83
-
84
76
  static int
85
- S_render_node(cmark_node *node, cmark_event_type ev_type,
86
- struct render_state *state)
77
+ S_render_node(cmark_renderer *renderer,
78
+ cmark_node *node,
79
+ cmark_event_type ev_type,
80
+ int options)
87
81
  {
88
82
  cmark_node *tmp;
89
- cmark_strbuf *man = state->man;
90
83
  int list_number;
91
84
  bool entering = (ev_type == CMARK_EVENT_ENTER);
92
85
 
93
- if (state->plain == node) { // back at original node
94
- state->plain = NULL;
95
- }
96
-
97
- if (state->plain != NULL) {
98
- switch(node->type) {
99
- case CMARK_NODE_TEXT:
100
- case CMARK_NODE_CODE:
101
- escape_man(man, node->as.literal.data,
102
- node->as.literal.len);
103
- break;
104
-
105
- case CMARK_NODE_LINEBREAK:
106
- case CMARK_NODE_SOFTBREAK:
107
- cmark_strbuf_putc(man, ' ');
108
- break;
109
-
110
- default:
111
- break;
112
- }
113
- return 1;
114
- }
86
+ // avoid unused parameter error:
87
+ (void)(options);
115
88
 
116
89
  switch (node->type) {
117
90
  case CMARK_NODE_DOCUMENT:
@@ -119,13 +92,13 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
119
92
 
120
93
  case CMARK_NODE_BLOCK_QUOTE:
121
94
  if (entering) {
122
- cr(man);
123
- cmark_strbuf_puts(man, ".RS");
124
- cr(man);
95
+ CR();
96
+ LIT(".RS");
97
+ CR();
125
98
  } else {
126
- cr(man);
127
- cmark_strbuf_puts(man, ".RE");
128
- cr(man);
99
+ CR();
100
+ LIT(".RE");
101
+ CR();
129
102
  }
130
103
  break;
131
104
 
@@ -134,11 +107,11 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
134
107
 
135
108
  case CMARK_NODE_ITEM:
136
109
  if (entering) {
137
- cr(man);
138
- cmark_strbuf_puts(man, ".IP ");
110
+ CR();
111
+ LIT(".IP ");
139
112
  if (cmark_node_get_list_type(node->parent) ==
140
113
  CMARK_BULLET_LIST) {
141
- cmark_strbuf_puts(man, "\\[bu] 2");
114
+ LIT("\\[bu] 2");
142
115
  } else {
143
116
  list_number = cmark_node_get_list_start(node->parent);
144
117
  tmp = node;
@@ -146,43 +119,45 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
146
119
  tmp = tmp->prev;
147
120
  list_number += 1;
148
121
  }
149
- cmark_strbuf_printf(man, "\"%d.\" 4", list_number);
122
+ char list_number_s[20];
123
+ sprintf(list_number_s, "\"%d.\" 4", list_number);
124
+ LIT(list_number_s);
150
125
  }
151
- cr(man);
126
+ CR();
152
127
  } else {
153
- cr(man);
128
+ CR();
154
129
  }
155
130
  break;
156
131
 
157
132
  case CMARK_NODE_HEADER:
158
133
  if (entering) {
159
- cr(man);
160
- cmark_strbuf_puts(man,
161
- cmark_node_get_header_level(node) == 1 ?
162
- ".SH" : ".SS");
163
- cr(man);
134
+ CR();
135
+ LIT(cmark_node_get_header_level(node) == 1 ?
136
+ ".SH" : ".SS");
137
+ CR();
164
138
  } else {
165
- cr(man);
139
+ CR();
166
140
  }
167
141
  break;
168
142
 
169
143
  case CMARK_NODE_CODE_BLOCK:
170
- cr(man);
171
- cmark_strbuf_puts(man, ".IP\n.nf\n\\f[C]\n");
172
- escape_man(man, node->as.code.literal.data,
173
- node->as.code.literal.len);
174
- cr(man);
175
- cmark_strbuf_puts(man, "\\f[]\n.fi");
176
- cr(man);
144
+ CR();
145
+ LIT(".IP\n.nf\n\\f[C]\n");
146
+ OUT(cmark_node_get_literal(node),
147
+ false,
148
+ NORMAL);
149
+ CR();
150
+ LIT("\\f[]\n.fi");
151
+ CR();
177
152
  break;
178
153
 
179
154
  case CMARK_NODE_HTML:
180
155
  break;
181
156
 
182
157
  case CMARK_NODE_HRULE:
183
- cr(man);
184
- cmark_strbuf_puts(man, ".PP\n * * * * *");
185
- cr(man);
158
+ CR();
159
+ LIT(".PP\n * * * * *");
160
+ CR();
186
161
  break;
187
162
 
188
163
  case CMARK_NODE_PARAGRAPH:
@@ -193,32 +168,36 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
193
168
  node->prev == NULL) {
194
169
  // no blank line or .PP
195
170
  } else {
196
- cr(man);
197
- cmark_strbuf_puts(man, ".PP\n");
171
+ CR();
172
+ LIT(".PP");
173
+ CR();
198
174
  }
199
175
  } else {
200
- cr(man);
176
+ CR();
201
177
  }
202
178
  break;
203
179
 
204
180
  case CMARK_NODE_TEXT:
205
- escape_man(man, node->as.literal.data,
206
- node->as.literal.len);
181
+ OUT(cmark_node_get_literal(node), true, NORMAL);
207
182
  break;
208
183
 
209
184
  case CMARK_NODE_LINEBREAK:
210
- cmark_strbuf_puts(man, ".PD 0\n.P\n.PD");
211
- cr(man);
185
+ LIT(".PD 0\n.P\n.PD");
186
+ CR();
212
187
  break;
213
188
 
214
189
  case CMARK_NODE_SOFTBREAK:
215
- cmark_strbuf_putc(man, '\n');
190
+ if (renderer->width == 0) {
191
+ CR();
192
+ } else {
193
+ OUT(" ", true, LITERAL);
194
+ }
216
195
  break;
217
196
 
218
197
  case CMARK_NODE_CODE:
219
- cmark_strbuf_puts(man, "\\f[C]");
220
- escape_man(man, node->as.literal.data, node->as.literal.len);
221
- cmark_strbuf_puts(man, "\\f[]");
198
+ LIT("\\f[C]");
199
+ OUT(cmark_node_get_literal(node), true, NORMAL);
200
+ LIT("\\f[]");
222
201
  break;
223
202
 
224
203
  case CMARK_NODE_INLINE_HTML:
@@ -226,33 +205,33 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
226
205
 
227
206
  case CMARK_NODE_STRONG:
228
207
  if (entering) {
229
- cmark_strbuf_puts(man, "\\f[B]");
208
+ LIT("\\f[B]");
230
209
  } else {
231
- cmark_strbuf_puts(man, "\\f[]");
210
+ LIT("\\f[]");
232
211
  }
233
212
  break;
234
213
 
235
214
  case CMARK_NODE_EMPH:
236
215
  if (entering) {
237
- cmark_strbuf_puts(man, "\\f[I]");
216
+ LIT("\\f[I]");
238
217
  } else {
239
- cmark_strbuf_puts(man, "\\f[]");
218
+ LIT("\\f[]");
240
219
  }
241
220
  break;
242
221
 
243
222
  case CMARK_NODE_LINK:
244
223
  if (!entering) {
245
- cmark_strbuf_printf(man, " (%s)",
246
- cmark_node_get_url(node));
224
+ LIT(" (");
225
+ OUT(cmark_node_get_url(node), true, URL);
226
+ LIT(")");
247
227
  }
248
228
  break;
249
229
 
250
230
  case CMARK_NODE_IMAGE:
251
231
  if (entering) {
252
- cmark_strbuf_puts(man, "[IMAGE: ");
253
- state->plain = node;
232
+ LIT("[IMAGE: ");
254
233
  } else {
255
- cmark_strbuf_puts(man, "]");
234
+ LIT("]");
256
235
  }
257
236
  break;
258
237
 
@@ -261,27 +240,10 @@ S_render_node(cmark_node *node, cmark_event_type ev_type,
261
240
  break;
262
241
  }
263
242
 
264
- // cmark_strbuf_putc(man, 'x');
265
243
  return 1;
266
244
  }
267
245
 
268
- char *cmark_render_man(cmark_node *root, int options)
246
+ char *cmark_render_man(cmark_node *root, int options, int width)
269
247
  {
270
- char *result;
271
- cmark_strbuf man = GH_BUF_INIT;
272
- struct render_state state = { &man, NULL };
273
- cmark_node *cur;
274
- cmark_event_type ev_type;
275
- cmark_iter *iter = cmark_iter_new(root);
276
-
277
- if (options == 0) options = 0; // avoid warning about unused parameters
278
-
279
- while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
280
- cur = cmark_iter_get_node(iter);
281
- S_render_node(cur, ev_type, &state);
282
- }
283
- result = (char *)cmark_strbuf_detach(&man);
284
-
285
- cmark_iter_free(iter);
286
- return result;
248
+ return cmark_render(root, options, width, S_outc, S_render_node);
287
249
  }