markly 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/bin/markly +94 -0
  3. data/ext/markly/arena.c +103 -0
  4. data/ext/markly/autolink.c +425 -0
  5. data/ext/markly/autolink.h +8 -0
  6. data/ext/markly/blocks.c +1585 -0
  7. data/ext/markly/buffer.c +278 -0
  8. data/ext/markly/buffer.h +116 -0
  9. data/ext/markly/case_fold_switch.inc +4327 -0
  10. data/ext/markly/chunk.h +135 -0
  11. data/ext/markly/cmark-gfm-core-extensions.h +54 -0
  12. data/ext/markly/cmark-gfm-extension_api.h +736 -0
  13. data/ext/markly/cmark-gfm-extensions_export.h +42 -0
  14. data/ext/markly/cmark-gfm.h +817 -0
  15. data/ext/markly/cmark-gfm_export.h +42 -0
  16. data/ext/markly/cmark-gfm_version.h +7 -0
  17. data/ext/markly/cmark.c +55 -0
  18. data/ext/markly/cmark_ctype.c +44 -0
  19. data/ext/markly/cmark_ctype.h +33 -0
  20. data/ext/markly/commonmark.c +519 -0
  21. data/ext/markly/config.h +76 -0
  22. data/ext/markly/core-extensions.c +27 -0
  23. data/ext/markly/entities.inc +2138 -0
  24. data/ext/markly/ext_scanners.c +1159 -0
  25. data/ext/markly/ext_scanners.h +24 -0
  26. data/ext/markly/extconf.rb +7 -0
  27. data/ext/markly/footnotes.c +40 -0
  28. data/ext/markly/footnotes.h +25 -0
  29. data/ext/markly/houdini.h +57 -0
  30. data/ext/markly/houdini_href_e.c +100 -0
  31. data/ext/markly/houdini_html_e.c +66 -0
  32. data/ext/markly/houdini_html_u.c +149 -0
  33. data/ext/markly/html.c +465 -0
  34. data/ext/markly/html.h +27 -0
  35. data/ext/markly/inlines.c +1633 -0
  36. data/ext/markly/inlines.h +29 -0
  37. data/ext/markly/iterator.c +159 -0
  38. data/ext/markly/iterator.h +26 -0
  39. data/ext/markly/latex.c +466 -0
  40. data/ext/markly/linked_list.c +37 -0
  41. data/ext/markly/man.c +278 -0
  42. data/ext/markly/map.c +122 -0
  43. data/ext/markly/map.h +41 -0
  44. data/ext/markly/markly.c +1226 -0
  45. data/ext/markly/markly.h +16 -0
  46. data/ext/markly/node.c +979 -0
  47. data/ext/markly/node.h +118 -0
  48. data/ext/markly/parser.h +58 -0
  49. data/ext/markly/plaintext.c +235 -0
  50. data/ext/markly/plugin.c +36 -0
  51. data/ext/markly/plugin.h +34 -0
  52. data/ext/markly/references.c +42 -0
  53. data/ext/markly/references.h +26 -0
  54. data/ext/markly/registry.c +63 -0
  55. data/ext/markly/registry.h +24 -0
  56. data/ext/markly/render.c +205 -0
  57. data/ext/markly/render.h +62 -0
  58. data/ext/markly/scanners.c +20382 -0
  59. data/ext/markly/scanners.h +62 -0
  60. data/ext/markly/scanners.re +326 -0
  61. data/ext/markly/strikethrough.c +167 -0
  62. data/ext/markly/strikethrough.h +9 -0
  63. data/ext/markly/syntax_extension.c +149 -0
  64. data/ext/markly/syntax_extension.h +34 -0
  65. data/ext/markly/table.c +803 -0
  66. data/ext/markly/table.h +12 -0
  67. data/ext/markly/tagfilter.c +60 -0
  68. data/ext/markly/tagfilter.h +8 -0
  69. data/ext/markly/tasklist.c +156 -0
  70. data/ext/markly/tasklist.h +8 -0
  71. data/ext/markly/utf8.c +317 -0
  72. data/ext/markly/utf8.h +35 -0
  73. data/ext/markly/xml.c +181 -0
  74. data/lib/markly.rb +43 -0
  75. data/lib/markly/flags.rb +37 -0
  76. data/lib/markly/markly.so +0 -0
  77. data/lib/markly/node.rb +70 -0
  78. data/lib/markly/node/inspect.rb +59 -0
  79. data/lib/markly/renderer.rb +133 -0
  80. data/lib/markly/renderer/html_renderer.rb +252 -0
  81. data/lib/markly/version.rb +5 -0
  82. metadata +211 -0
@@ -0,0 +1,16 @@
1
+ #ifndef MARKLY_H
2
+ #define MARKLY_H
3
+
4
+ #ifndef __MSXML_LIBRARY_DEFINED__
5
+ #define __MSXML_LIBRARY_DEFINED__
6
+ #endif
7
+
8
+ #include "cmark-gfm.h"
9
+ #include "ruby.h"
10
+ #include "ruby/encoding.h"
11
+
12
+ #define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
13
+
14
+ void Init_markly();
15
+
16
+ #endif
@@ -0,0 +1,979 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+
4
+ #include "config.h"
5
+ #include "node.h"
6
+ #include "syntax_extension.h"
7
+
8
+ static void S_node_unlink(cmark_node *node);
9
+
10
+ #define NODE_MEM(node) cmark_node_mem(node)
11
+
12
+ bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
13
+ if (child_type == CMARK_NODE_DOCUMENT) {
14
+ return false;
15
+ }
16
+
17
+ if (node->extension && node->extension->can_contain_func) {
18
+ return node->extension->can_contain_func(node->extension, node, child_type) != 0;
19
+ }
20
+
21
+ switch (node->type) {
22
+ case CMARK_NODE_DOCUMENT:
23
+ case CMARK_NODE_BLOCK_QUOTE:
24
+ case CMARK_NODE_FOOTNOTE_DEFINITION:
25
+ case CMARK_NODE_ITEM:
26
+ return CMARK_NODE_TYPE_BLOCK_P(child_type) && child_type != CMARK_NODE_ITEM;
27
+
28
+ case CMARK_NODE_LIST:
29
+ return child_type == CMARK_NODE_ITEM;
30
+
31
+ case CMARK_NODE_CUSTOM_BLOCK:
32
+ return true;
33
+
34
+ case CMARK_NODE_PARAGRAPH:
35
+ case CMARK_NODE_HEADING:
36
+ case CMARK_NODE_EMPH:
37
+ case CMARK_NODE_STRONG:
38
+ case CMARK_NODE_LINK:
39
+ case CMARK_NODE_IMAGE:
40
+ case CMARK_NODE_CUSTOM_INLINE:
41
+ return CMARK_NODE_TYPE_INLINE_P(child_type);
42
+
43
+ default:
44
+ break;
45
+ }
46
+
47
+ return false;
48
+ }
49
+
50
+ static bool S_can_contain(cmark_node *node, cmark_node *child) {
51
+ cmark_node *cur;
52
+
53
+ if (node == NULL || child == NULL) {
54
+ return false;
55
+ }
56
+ if (NODE_MEM(node) != NODE_MEM(child)) {
57
+ return 0;
58
+ }
59
+
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);
68
+
69
+ return cmark_node_can_contain_type(node, (cmark_node_type) child->type);
70
+ }
71
+
72
+ cmark_node *cmark_node_new_with_mem_and_ext(cmark_node_type type, cmark_mem *mem, cmark_syntax_extension *extension) {
73
+ cmark_node *node = (cmark_node *)mem->calloc(1, sizeof(*node));
74
+ cmark_strbuf_init(mem, &node->content, 0);
75
+ node->type = (uint16_t)type;
76
+ node->extension = extension;
77
+
78
+ switch (node->type) {
79
+ case CMARK_NODE_HEADING:
80
+ node->as.heading.level = 1;
81
+ break;
82
+
83
+ case CMARK_NODE_LIST: {
84
+ cmark_list *list = &node->as.list;
85
+ list->list_type = CMARK_BULLET_LIST;
86
+ list->start = 0;
87
+ list->tight = false;
88
+ break;
89
+ }
90
+
91
+ default:
92
+ break;
93
+ }
94
+
95
+ if (node->extension && node->extension->opaque_alloc_func) {
96
+ node->extension->opaque_alloc_func(node->extension, mem, node);
97
+ }
98
+
99
+ return node;
100
+ }
101
+
102
+ cmark_node *cmark_node_new_with_ext(cmark_node_type type, cmark_syntax_extension *extension) {
103
+ extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
104
+ return cmark_node_new_with_mem_and_ext(type, &CMARK_DEFAULT_MEM_ALLOCATOR, extension);
105
+ }
106
+
107
+ cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem)
108
+ {
109
+ return cmark_node_new_with_mem_and_ext(type, mem, NULL);
110
+ }
111
+
112
+ cmark_node *cmark_node_new(cmark_node_type type) {
113
+ return cmark_node_new_with_ext(type, NULL);
114
+ }
115
+
116
+ static void free_node_as(cmark_node *node) {
117
+ switch (node->type) {
118
+ case CMARK_NODE_CODE_BLOCK:
119
+ cmark_chunk_free(NODE_MEM(node), &node->as.code.info);
120
+ cmark_chunk_free(NODE_MEM(node), &node->as.code.literal);
121
+ break;
122
+ case CMARK_NODE_TEXT:
123
+ case CMARK_NODE_HTML_INLINE:
124
+ case CMARK_NODE_CODE:
125
+ case CMARK_NODE_HTML_BLOCK:
126
+ case CMARK_NODE_FOOTNOTE_REFERENCE:
127
+ case CMARK_NODE_FOOTNOTE_DEFINITION:
128
+ cmark_chunk_free(NODE_MEM(node), &node->as.literal);
129
+ break;
130
+ case CMARK_NODE_LINK:
131
+ case CMARK_NODE_IMAGE:
132
+ cmark_chunk_free(NODE_MEM(node), &node->as.link.url);
133
+ cmark_chunk_free(NODE_MEM(node), &node->as.link.title);
134
+ break;
135
+ case CMARK_NODE_CUSTOM_BLOCK:
136
+ case CMARK_NODE_CUSTOM_INLINE:
137
+ cmark_chunk_free(NODE_MEM(node), &node->as.custom.on_enter);
138
+ cmark_chunk_free(NODE_MEM(node), &node->as.custom.on_exit);
139
+ break;
140
+ default:
141
+ break;
142
+ }
143
+ }
144
+
145
+ // Free a cmark_node list and any children.
146
+ static void S_free_nodes(cmark_node *e) {
147
+ cmark_node *next;
148
+ while (e != NULL) {
149
+ cmark_strbuf_free(&e->content);
150
+
151
+ if (e->user_data && e->user_data_free_func)
152
+ e->user_data_free_func(NODE_MEM(e), e->user_data);
153
+
154
+ if (e->as.opaque && e->extension && e->extension->opaque_free_func)
155
+ e->extension->opaque_free_func(e->extension, NODE_MEM(e), e);
156
+
157
+ free_node_as(e);
158
+
159
+ if (e->last_child) {
160
+ // Splice children into list
161
+ e->last_child->next = e->next;
162
+ e->next = e->first_child;
163
+ }
164
+ next = e->next;
165
+ NODE_MEM(e)->free(e);
166
+ e = next;
167
+ }
168
+ }
169
+
170
+ void cmark_node_free(cmark_node *node) {
171
+ S_node_unlink(node);
172
+ node->next = NULL;
173
+ S_free_nodes(node);
174
+ }
175
+
176
+ cmark_node_type cmark_node_get_type(cmark_node *node) {
177
+ if (node == NULL) {
178
+ return CMARK_NODE_NONE;
179
+ } else {
180
+ return (cmark_node_type)node->type;
181
+ }
182
+ }
183
+
184
+ int cmark_node_set_type(cmark_node * node, cmark_node_type type) {
185
+ cmark_node_type initial_type;
186
+
187
+ if (type == node->type)
188
+ return 1;
189
+
190
+ initial_type = (cmark_node_type) node->type;
191
+ node->type = (uint16_t)type;
192
+
193
+ if (!S_can_contain(node->parent, node)) {
194
+ node->type = (uint16_t)initial_type;
195
+ return 0;
196
+ }
197
+
198
+ /* We rollback the type to free the union members appropriately */
199
+ node->type = (uint16_t)initial_type;
200
+ free_node_as(node);
201
+
202
+ node->type = (uint16_t)type;
203
+
204
+ return 1;
205
+ }
206
+
207
+ const char *cmark_node_get_type_string(cmark_node *node) {
208
+ if (node == NULL) {
209
+ return "NONE";
210
+ }
211
+
212
+ if (node->extension && node->extension->get_type_string_func) {
213
+ return node->extension->get_type_string_func(node->extension, node);
214
+ }
215
+
216
+ switch (node->type) {
217
+ case CMARK_NODE_NONE:
218
+ return "none";
219
+ case CMARK_NODE_DOCUMENT:
220
+ return "document";
221
+ case CMARK_NODE_BLOCK_QUOTE:
222
+ return "block_quote";
223
+ case CMARK_NODE_LIST:
224
+ return "list";
225
+ case CMARK_NODE_ITEM:
226
+ return "item";
227
+ case CMARK_NODE_CODE_BLOCK:
228
+ return "code_block";
229
+ case CMARK_NODE_HTML_BLOCK:
230
+ return "html_block";
231
+ case CMARK_NODE_CUSTOM_BLOCK:
232
+ return "custom_block";
233
+ case CMARK_NODE_PARAGRAPH:
234
+ return "paragraph";
235
+ case CMARK_NODE_HEADING:
236
+ return "heading";
237
+ case CMARK_NODE_THEMATIC_BREAK:
238
+ return "thematic_break";
239
+ case CMARK_NODE_TEXT:
240
+ return "text";
241
+ case CMARK_NODE_SOFTBREAK:
242
+ return "softbreak";
243
+ case CMARK_NODE_LINEBREAK:
244
+ return "linebreak";
245
+ case CMARK_NODE_CODE:
246
+ return "code";
247
+ case CMARK_NODE_HTML_INLINE:
248
+ return "html_inline";
249
+ case CMARK_NODE_CUSTOM_INLINE:
250
+ return "custom_inline";
251
+ case CMARK_NODE_EMPH:
252
+ return "emph";
253
+ case CMARK_NODE_STRONG:
254
+ return "strong";
255
+ case CMARK_NODE_LINK:
256
+ return "link";
257
+ case CMARK_NODE_IMAGE:
258
+ return "image";
259
+ }
260
+
261
+ return "<unknown>";
262
+ }
263
+
264
+ cmark_node *cmark_node_next(cmark_node *node) {
265
+ if (node == NULL) {
266
+ return NULL;
267
+ } else {
268
+ return node->next;
269
+ }
270
+ }
271
+
272
+ cmark_node *cmark_node_previous(cmark_node *node) {
273
+ if (node == NULL) {
274
+ return NULL;
275
+ } else {
276
+ return node->prev;
277
+ }
278
+ }
279
+
280
+ cmark_node *cmark_node_parent(cmark_node *node) {
281
+ if (node == NULL) {
282
+ return NULL;
283
+ } else {
284
+ return node->parent;
285
+ }
286
+ }
287
+
288
+ cmark_node *cmark_node_first_child(cmark_node *node) {
289
+ if (node == NULL) {
290
+ return NULL;
291
+ } else {
292
+ return node->first_child;
293
+ }
294
+ }
295
+
296
+ cmark_node *cmark_node_last_child(cmark_node *node) {
297
+ if (node == NULL) {
298
+ return NULL;
299
+ } else {
300
+ return node->last_child;
301
+ }
302
+ }
303
+
304
+ void *cmark_node_get_user_data(cmark_node *node) {
305
+ if (node == NULL) {
306
+ return NULL;
307
+ } else {
308
+ return node->user_data;
309
+ }
310
+ }
311
+
312
+ int cmark_node_set_user_data(cmark_node *node, void *user_data) {
313
+ if (node == NULL) {
314
+ return 0;
315
+ }
316
+ node->user_data = user_data;
317
+ return 1;
318
+ }
319
+
320
+ int cmark_node_set_user_data_free_func(cmark_node *node,
321
+ cmark_free_func free_func) {
322
+ if (node == NULL) {
323
+ return 0;
324
+ }
325
+ node->user_data_free_func = free_func;
326
+ return 1;
327
+ }
328
+
329
+ const char *cmark_node_get_literal(cmark_node *node) {
330
+ if (node == NULL) {
331
+ return NULL;
332
+ }
333
+
334
+ switch (node->type) {
335
+ case CMARK_NODE_HTML_BLOCK:
336
+ case CMARK_NODE_TEXT:
337
+ case CMARK_NODE_HTML_INLINE:
338
+ case CMARK_NODE_CODE:
339
+ case CMARK_NODE_FOOTNOTE_REFERENCE:
340
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);
341
+
342
+ case CMARK_NODE_CODE_BLOCK:
343
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.literal);
344
+
345
+ default:
346
+ break;
347
+ }
348
+
349
+ return NULL;
350
+ }
351
+
352
+ int cmark_node_set_literal(cmark_node *node, const char *content) {
353
+ if (node == NULL) {
354
+ return 0;
355
+ }
356
+
357
+ switch (node->type) {
358
+ case CMARK_NODE_HTML_BLOCK:
359
+ case CMARK_NODE_TEXT:
360
+ case CMARK_NODE_HTML_INLINE:
361
+ case CMARK_NODE_CODE:
362
+ case CMARK_NODE_FOOTNOTE_REFERENCE:
363
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.literal, content);
364
+ return 1;
365
+
366
+ case CMARK_NODE_CODE_BLOCK:
367
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.literal, content);
368
+ return 1;
369
+
370
+ default:
371
+ break;
372
+ }
373
+
374
+ return 0;
375
+ }
376
+
377
+ const char *cmark_node_get_string_content(cmark_node *node) {
378
+ return (char *) node->content.ptr;
379
+ }
380
+
381
+ int cmark_node_set_string_content(cmark_node *node, const char *content) {
382
+ cmark_strbuf_sets(&node->content, content);
383
+ return true;
384
+ }
385
+
386
+ int cmark_node_get_heading_level(cmark_node *node) {
387
+ if (node == NULL) {
388
+ return 0;
389
+ }
390
+
391
+ switch (node->type) {
392
+ case CMARK_NODE_HEADING:
393
+ return node->as.heading.level;
394
+
395
+ default:
396
+ break;
397
+ }
398
+
399
+ return 0;
400
+ }
401
+
402
+ int cmark_node_set_heading_level(cmark_node *node, int level) {
403
+ if (node == NULL || level < 1 || level > 6) {
404
+ return 0;
405
+ }
406
+
407
+ switch (node->type) {
408
+ case CMARK_NODE_HEADING:
409
+ node->as.heading.level = level;
410
+ return 1;
411
+
412
+ default:
413
+ break;
414
+ }
415
+
416
+ return 0;
417
+ }
418
+
419
+ cmark_list_type cmark_node_get_list_type(cmark_node *node) {
420
+ if (node == NULL) {
421
+ return CMARK_NO_LIST;
422
+ }
423
+
424
+ if (node->type == CMARK_NODE_LIST) {
425
+ return node->as.list.list_type;
426
+ } else {
427
+ return CMARK_NO_LIST;
428
+ }
429
+ }
430
+
431
+ int cmark_node_set_list_type(cmark_node *node, cmark_list_type type) {
432
+ if (!(type == CMARK_BULLET_LIST || type == CMARK_ORDERED_LIST)) {
433
+ return 0;
434
+ }
435
+
436
+ if (node == NULL) {
437
+ return 0;
438
+ }
439
+
440
+ if (node->type == CMARK_NODE_LIST) {
441
+ node->as.list.list_type = type;
442
+ return 1;
443
+ } else {
444
+ return 0;
445
+ }
446
+ }
447
+
448
+ cmark_delim_type cmark_node_get_list_delim(cmark_node *node) {
449
+ if (node == NULL) {
450
+ return CMARK_NO_DELIM;
451
+ }
452
+
453
+ if (node->type == CMARK_NODE_LIST) {
454
+ return node->as.list.delimiter;
455
+ } else {
456
+ return CMARK_NO_DELIM;
457
+ }
458
+ }
459
+
460
+ int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim) {
461
+ if (!(delim == CMARK_PERIOD_DELIM || delim == CMARK_PAREN_DELIM)) {
462
+ return 0;
463
+ }
464
+
465
+ if (node == NULL) {
466
+ return 0;
467
+ }
468
+
469
+ if (node->type == CMARK_NODE_LIST) {
470
+ node->as.list.delimiter = delim;
471
+ return 1;
472
+ } else {
473
+ return 0;
474
+ }
475
+ }
476
+
477
+ int cmark_node_get_list_start(cmark_node *node) {
478
+ if (node == NULL) {
479
+ return 0;
480
+ }
481
+
482
+ if (node->type == CMARK_NODE_LIST) {
483
+ return node->as.list.start;
484
+ } else {
485
+ return 0;
486
+ }
487
+ }
488
+
489
+ int cmark_node_set_list_start(cmark_node *node, int start) {
490
+ if (node == NULL || start < 0) {
491
+ return 0;
492
+ }
493
+
494
+ if (node->type == CMARK_NODE_LIST) {
495
+ node->as.list.start = start;
496
+ return 1;
497
+ } else {
498
+ return 0;
499
+ }
500
+ }
501
+
502
+ int cmark_node_get_list_tight(cmark_node *node) {
503
+ if (node == NULL) {
504
+ return 0;
505
+ }
506
+
507
+ if (node->type == CMARK_NODE_LIST) {
508
+ return node->as.list.tight;
509
+ } else {
510
+ return 0;
511
+ }
512
+ }
513
+
514
+ int cmark_node_set_list_tight(cmark_node *node, int tight) {
515
+ if (node == NULL) {
516
+ return 0;
517
+ }
518
+
519
+ if (node->type == CMARK_NODE_LIST) {
520
+ node->as.list.tight = tight == 1;
521
+ return 1;
522
+ } else {
523
+ return 0;
524
+ }
525
+ }
526
+
527
+ const char *cmark_node_get_fence_info(cmark_node *node) {
528
+ if (node == NULL) {
529
+ return NULL;
530
+ }
531
+
532
+ if (node->type == CMARK_NODE_CODE_BLOCK) {
533
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.info);
534
+ } else {
535
+ return NULL;
536
+ }
537
+ }
538
+
539
+ int cmark_node_set_fence_info(cmark_node *node, const char *info) {
540
+ if (node == NULL) {
541
+ return 0;
542
+ }
543
+
544
+ if (node->type == CMARK_NODE_CODE_BLOCK) {
545
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.info, info);
546
+ return 1;
547
+ } else {
548
+ return 0;
549
+ }
550
+ }
551
+
552
+ int cmark_node_get_fenced(cmark_node *node, int *length, int *offset, char *character) {
553
+ if (node == NULL) {
554
+ return 0;
555
+ }
556
+
557
+ if (node->type == CMARK_NODE_CODE_BLOCK) {
558
+ *length = node->as.code.fence_length;
559
+ *offset = node->as.code.fence_offset;
560
+ *character = node->as.code.fence_char;
561
+ return node->as.code.fenced;
562
+ } else {
563
+ return 0;
564
+ }
565
+ }
566
+
567
+ int cmark_node_set_fenced(cmark_node * node, int fenced,
568
+ int length, int offset, char character) {
569
+ if (node == NULL) {
570
+ return 0;
571
+ }
572
+
573
+ if (node->type == CMARK_NODE_CODE_BLOCK) {
574
+ node->as.code.fenced = (int8_t)fenced;
575
+ node->as.code.fence_length = (uint8_t)length;
576
+ node->as.code.fence_offset = (uint8_t)offset;
577
+ node->as.code.fence_char = character;
578
+ return 1;
579
+ } else {
580
+ return 0;
581
+ }
582
+ }
583
+
584
+ const char *cmark_node_get_url(cmark_node *node) {
585
+ if (node == NULL) {
586
+ return NULL;
587
+ }
588
+
589
+ switch (node->type) {
590
+ case CMARK_NODE_LINK:
591
+ case CMARK_NODE_IMAGE:
592
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.url);
593
+ default:
594
+ break;
595
+ }
596
+
597
+ return NULL;
598
+ }
599
+
600
+ int cmark_node_set_url(cmark_node *node, const char *url) {
601
+ if (node == NULL) {
602
+ return 0;
603
+ }
604
+
605
+ switch (node->type) {
606
+ case CMARK_NODE_LINK:
607
+ case CMARK_NODE_IMAGE:
608
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.url, url);
609
+ return 1;
610
+ default:
611
+ break;
612
+ }
613
+
614
+ return 0;
615
+ }
616
+
617
+ const char *cmark_node_get_title(cmark_node *node) {
618
+ if (node == NULL) {
619
+ return NULL;
620
+ }
621
+
622
+ switch (node->type) {
623
+ case CMARK_NODE_LINK:
624
+ case CMARK_NODE_IMAGE:
625
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.title);
626
+ default:
627
+ break;
628
+ }
629
+
630
+ return NULL;
631
+ }
632
+
633
+ int cmark_node_set_title(cmark_node *node, const char *title) {
634
+ if (node == NULL) {
635
+ return 0;
636
+ }
637
+
638
+ switch (node->type) {
639
+ case CMARK_NODE_LINK:
640
+ case CMARK_NODE_IMAGE:
641
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.title, title);
642
+ return 1;
643
+ default:
644
+ break;
645
+ }
646
+
647
+ return 0;
648
+ }
649
+
650
+ const char *cmark_node_get_on_enter(cmark_node *node) {
651
+ if (node == NULL) {
652
+ return NULL;
653
+ }
654
+
655
+ switch (node->type) {
656
+ case CMARK_NODE_CUSTOM_INLINE:
657
+ case CMARK_NODE_CUSTOM_BLOCK:
658
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_enter);
659
+ default:
660
+ break;
661
+ }
662
+
663
+ return NULL;
664
+ }
665
+
666
+ int cmark_node_set_on_enter(cmark_node *node, const char *on_enter) {
667
+ if (node == NULL) {
668
+ return 0;
669
+ }
670
+
671
+ switch (node->type) {
672
+ case CMARK_NODE_CUSTOM_INLINE:
673
+ case CMARK_NODE_CUSTOM_BLOCK:
674
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_enter, on_enter);
675
+ return 1;
676
+ default:
677
+ break;
678
+ }
679
+
680
+ return 0;
681
+ }
682
+
683
+ const char *cmark_node_get_on_exit(cmark_node *node) {
684
+ if (node == NULL) {
685
+ return NULL;
686
+ }
687
+
688
+ switch (node->type) {
689
+ case CMARK_NODE_CUSTOM_INLINE:
690
+ case CMARK_NODE_CUSTOM_BLOCK:
691
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_exit);
692
+ default:
693
+ break;
694
+ }
695
+
696
+ return NULL;
697
+ }
698
+
699
+ int cmark_node_set_on_exit(cmark_node *node, const char *on_exit) {
700
+ if (node == NULL) {
701
+ return 0;
702
+ }
703
+
704
+ switch (node->type) {
705
+ case CMARK_NODE_CUSTOM_INLINE:
706
+ case CMARK_NODE_CUSTOM_BLOCK:
707
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_exit, on_exit);
708
+ return 1;
709
+ default:
710
+ break;
711
+ }
712
+
713
+ return 0;
714
+ }
715
+
716
+ cmark_syntax_extension *cmark_node_get_syntax_extension(cmark_node *node) {
717
+ if (node == NULL) {
718
+ return NULL;
719
+ }
720
+
721
+ return node->extension;
722
+ }
723
+
724
+ int cmark_node_set_syntax_extension(cmark_node *node, cmark_syntax_extension *extension) {
725
+ if (node == NULL) {
726
+ return 0;
727
+ }
728
+
729
+ node->extension = extension;
730
+ return 1;
731
+ }
732
+
733
+ int cmark_node_get_start_line(cmark_node *node) {
734
+ if (node == NULL) {
735
+ return 0;
736
+ }
737
+ return node->start_line;
738
+ }
739
+
740
+ int cmark_node_get_start_column(cmark_node *node) {
741
+ if (node == NULL) {
742
+ return 0;
743
+ }
744
+ return node->start_column;
745
+ }
746
+
747
+ int cmark_node_get_end_line(cmark_node *node) {
748
+ if (node == NULL) {
749
+ return 0;
750
+ }
751
+ return node->end_line;
752
+ }
753
+
754
+ int cmark_node_get_end_column(cmark_node *node) {
755
+ if (node == NULL) {
756
+ return 0;
757
+ }
758
+ return node->end_column;
759
+ }
760
+
761
+ // Unlink a node without adjusting its next, prev, and parent pointers.
762
+ static void S_node_unlink(cmark_node *node) {
763
+ if (node == NULL) {
764
+ return;
765
+ }
766
+
767
+ if (node->prev) {
768
+ node->prev->next = node->next;
769
+ }
770
+ if (node->next) {
771
+ node->next->prev = node->prev;
772
+ }
773
+
774
+ // Adjust first_child and last_child of parent.
775
+ cmark_node *parent = node->parent;
776
+ if (parent) {
777
+ if (parent->first_child == node) {
778
+ parent->first_child = node->next;
779
+ }
780
+ if (parent->last_child == node) {
781
+ parent->last_child = node->prev;
782
+ }
783
+ }
784
+ }
785
+
786
+ void cmark_node_unlink(cmark_node *node) {
787
+ S_node_unlink(node);
788
+
789
+ node->next = NULL;
790
+ node->prev = NULL;
791
+ node->parent = NULL;
792
+ }
793
+
794
+ int cmark_node_insert_before(cmark_node *node, cmark_node *sibling) {
795
+ if (node == NULL || sibling == NULL) {
796
+ return 0;
797
+ }
798
+
799
+ if (!node->parent || !S_can_contain(node->parent, sibling)) {
800
+ return 0;
801
+ }
802
+
803
+ S_node_unlink(sibling);
804
+
805
+ cmark_node *old_prev = node->prev;
806
+
807
+ // Insert 'sibling' between 'old_prev' and 'node'.
808
+ if (old_prev) {
809
+ old_prev->next = sibling;
810
+ }
811
+ sibling->prev = old_prev;
812
+ sibling->next = node;
813
+ node->prev = sibling;
814
+
815
+ // Set new parent.
816
+ cmark_node *parent = node->parent;
817
+ sibling->parent = parent;
818
+
819
+ // Adjust first_child of parent if inserted as first child.
820
+ if (parent && !old_prev) {
821
+ parent->first_child = sibling;
822
+ }
823
+
824
+ return 1;
825
+ }
826
+
827
+ int cmark_node_insert_after(cmark_node *node, cmark_node *sibling) {
828
+ if (node == NULL || sibling == NULL) {
829
+ return 0;
830
+ }
831
+
832
+ if (!node->parent || !S_can_contain(node->parent, sibling)) {
833
+ return 0;
834
+ }
835
+
836
+ S_node_unlink(sibling);
837
+
838
+ cmark_node *old_next = node->next;
839
+
840
+ // Insert 'sibling' between 'node' and 'old_next'.
841
+ if (old_next) {
842
+ old_next->prev = sibling;
843
+ }
844
+ sibling->next = old_next;
845
+ sibling->prev = node;
846
+ node->next = sibling;
847
+
848
+ // Set new parent.
849
+ cmark_node *parent = node->parent;
850
+ sibling->parent = parent;
851
+
852
+ // Adjust last_child of parent if inserted as last child.
853
+ if (parent && !old_next) {
854
+ parent->last_child = sibling;
855
+ }
856
+
857
+ return 1;
858
+ }
859
+
860
+ int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode) {
861
+ if (!cmark_node_insert_before(oldnode, newnode)) {
862
+ return 0;
863
+ }
864
+ cmark_node_unlink(oldnode);
865
+ return 1;
866
+ }
867
+
868
+ int cmark_node_prepend_child(cmark_node *node, cmark_node *child) {
869
+ if (!S_can_contain(node, child)) {
870
+ return 0;
871
+ }
872
+
873
+ S_node_unlink(child);
874
+
875
+ cmark_node *old_first_child = node->first_child;
876
+
877
+ child->next = old_first_child;
878
+ child->prev = NULL;
879
+ child->parent = node;
880
+ node->first_child = child;
881
+
882
+ if (old_first_child) {
883
+ old_first_child->prev = child;
884
+ } else {
885
+ // Also set last_child if node previously had no children.
886
+ node->last_child = child;
887
+ }
888
+
889
+ return 1;
890
+ }
891
+
892
+ int cmark_node_append_child(cmark_node *node, cmark_node *child) {
893
+ if (!S_can_contain(node, child)) {
894
+ return 0;
895
+ }
896
+
897
+ S_node_unlink(child);
898
+
899
+ cmark_node *old_last_child = node->last_child;
900
+
901
+ child->next = NULL;
902
+ child->prev = old_last_child;
903
+ child->parent = node;
904
+ node->last_child = child;
905
+
906
+ if (old_last_child) {
907
+ old_last_child->next = child;
908
+ } else {
909
+ // Also set first_child if node previously had no children.
910
+ node->first_child = child;
911
+ }
912
+
913
+ return 1;
914
+ }
915
+
916
+ static void S_print_error(FILE *out, cmark_node *node, const char *elem) {
917
+ if (out == NULL) {
918
+ return;
919
+ }
920
+ fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
921
+ cmark_node_get_type_string(node), node->start_line,
922
+ node->start_column);
923
+ }
924
+
925
+ int cmark_node_check(cmark_node *node, FILE *out) {
926
+ cmark_node *cur;
927
+ int errors = 0;
928
+
929
+ if (!node) {
930
+ return 0;
931
+ }
932
+
933
+ cur = node;
934
+ for (;;) {
935
+ if (cur->first_child) {
936
+ if (cur->first_child->prev != NULL) {
937
+ S_print_error(out, cur->first_child, "prev");
938
+ cur->first_child->prev = NULL;
939
+ ++errors;
940
+ }
941
+ if (cur->first_child->parent != cur) {
942
+ S_print_error(out, cur->first_child, "parent");
943
+ cur->first_child->parent = cur;
944
+ ++errors;
945
+ }
946
+ cur = cur->first_child;
947
+ continue;
948
+ }
949
+
950
+ next_sibling:
951
+ if (cur == node) {
952
+ break;
953
+ }
954
+ if (cur->next) {
955
+ if (cur->next->prev != cur) {
956
+ S_print_error(out, cur->next, "prev");
957
+ cur->next->prev = cur;
958
+ ++errors;
959
+ }
960
+ if (cur->next->parent != cur->parent) {
961
+ S_print_error(out, cur->next, "parent");
962
+ cur->next->parent = cur->parent;
963
+ ++errors;
964
+ }
965
+ cur = cur->next;
966
+ continue;
967
+ }
968
+
969
+ if (cur->parent->last_child != cur) {
970
+ S_print_error(out, cur->parent, "last_child");
971
+ cur->parent->last_child = cur;
972
+ ++errors;
973
+ }
974
+ cur = cur->parent;
975
+ goto next_sibling;
976
+ }
977
+
978
+ return errors;
979
+ }