markly 0.15.3 → 0.17.0

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 (55) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/context/getting-started.md +36 -0
  4. data/context/index.yaml +3 -3
  5. data/ext/markly/blocks.c +24 -6
  6. data/ext/markly/cmark-gfm.h +24 -0
  7. data/ext/markly/cmark-gfm_export.h +1 -0
  8. data/ext/markly/cmark-gfm_version.h +2 -2
  9. data/ext/markly/cmark.c +1 -1
  10. data/ext/markly/cmark_ctype.c +9 -0
  11. data/ext/markly/cmark_ctype.h +5 -0
  12. data/ext/markly/commonmark.c +21 -1
  13. data/ext/markly/config.h +0 -4
  14. data/ext/markly/extconf.rb +6 -1
  15. data/ext/markly/{table.c → extensions/table.c} +91 -46
  16. data/ext/markly/front_matter.c +141 -0
  17. data/ext/markly/front_matter.h +24 -0
  18. data/ext/markly/html.c +47 -23
  19. data/ext/markly/inlines.c +85 -3
  20. data/ext/markly/iterator.c +6 -1
  21. data/ext/markly/latex.c +3 -0
  22. data/ext/markly/man.c +3 -0
  23. data/ext/markly/markly.c +288 -201
  24. data/ext/markly/node.c +65 -5
  25. data/ext/markly/node.h +1 -0
  26. data/ext/markly/parser.h +19 -0
  27. data/ext/markly/plaintext.c +3 -0
  28. data/ext/markly/xml.c +19 -1
  29. data/lib/markly/flags.rb +10 -1
  30. data/lib/markly/node/inspect.rb +10 -3
  31. data/lib/markly/node.rb +53 -28
  32. data/lib/markly/renderer/generic.rb +42 -12
  33. data/lib/markly/renderer/headings.rb +24 -19
  34. data/lib/markly/renderer/html.rb +111 -10
  35. data/lib/markly/version.rb +4 -2
  36. data/lib/markly.rb +14 -13
  37. data/readme.md +22 -6
  38. data/releases.md +16 -0
  39. data.tar.gz.sig +0 -0
  40. metadata +23 -21
  41. metadata.gz.sig +0 -0
  42. /data/ext/markly/{autolink.c → extensions/autolink.c} +0 -0
  43. /data/ext/markly/{autolink.h → extensions/autolink.h} +0 -0
  44. /data/ext/markly/{cmark-gfm-core-extensions.h → extensions/cmark-gfm-core-extensions.h} +0 -0
  45. /data/ext/markly/{cmark-gfm-extensions_export.h → extensions/cmark-gfm-extensions_export.h} +0 -0
  46. /data/ext/markly/{core-extensions.c → extensions/core-extensions.c} +0 -0
  47. /data/ext/markly/{ext_scanners.c → extensions/ext_scanners.c} +0 -0
  48. /data/ext/markly/{ext_scanners.h → extensions/ext_scanners.h} +0 -0
  49. /data/ext/markly/{strikethrough.c → extensions/strikethrough.c} +0 -0
  50. /data/ext/markly/{strikethrough.h → extensions/strikethrough.h} +0 -0
  51. /data/ext/markly/{table.h → extensions/table.h} +0 -0
  52. /data/ext/markly/{tagfilter.c → extensions/tagfilter.c} +0 -0
  53. /data/ext/markly/{tagfilter.h → extensions/tagfilter.h} +0 -0
  54. /data/ext/markly/{tasklist.c → extensions/tasklist.c} +0 -0
  55. /data/ext/markly/{tasklist.h → extensions/tasklist.h} +0 -0
data/ext/markly/markly.c CHANGED
@@ -6,11 +6,11 @@
6
6
  #include "parser.h"
7
7
  #include "syntax_extension.h"
8
8
  #include "cmark-gfm-core-extensions.h"
9
+ #include "front_matter.h"
9
10
 
10
- static VALUE rb_Markly;
11
- static VALUE rb_Markly_Error;
12
- static VALUE rb_Markly_Node;
13
- static VALUE rb_Markly_Parser;
11
+ static VALUE Markly_Error;
12
+ static VALUE Markly_Node;
13
+ static VALUE Markly_Node_Fence;
14
14
 
15
15
  static VALUE sym_document;
16
16
  static VALUE sym_custom_block;
@@ -34,6 +34,7 @@ static VALUE sym_link;
34
34
  static VALUE sym_image;
35
35
  static VALUE sym_footnote_reference;
36
36
  static VALUE sym_footnote_definition;
37
+ static VALUE sym_front_matter;
37
38
 
38
39
  static VALUE sym_bullet_list;
39
40
  static VALUE sym_ordered_list;
@@ -42,8 +43,8 @@ static VALUE sym_left;
42
43
  static VALUE sym_right;
43
44
  static VALUE sym_center;
44
45
 
45
- static void rb_Markly_Node_free(void *data) {
46
- // If a parent of this node is already freed, `rb_Markly_Node_freed` will ensure all the nodes are nullified.
46
+ static void Markly_Node_Type_free(void *data) {
47
+ // If a parent of this node is already freed, `Markly_Node_freed` will ensure all the nodes are nullified.
47
48
  if (data) {
48
49
  cmark_node *node = (cmark_node*)data;
49
50
 
@@ -55,7 +56,7 @@ static void rb_Markly_Node_free(void *data) {
55
56
  }
56
57
  }
57
58
 
58
- static void rb_Markly_Node_mark(void *data) {
59
+ static void Markly_Node_Type_mark(void *data) {
59
60
  cmark_node *node = data;
60
61
 
61
62
  // Mark the parent to make sure that the tree won't be freed as long as a child node is referenced.
@@ -75,23 +76,23 @@ static void rb_Markly_Node_mark(void *data) {
75
76
  }
76
77
  }
77
78
 
78
- static const rb_data_type_t rb_Markly_Node_Type = {
79
+ static const rb_data_type_t Markly_Node_Type = {
79
80
  .wrap_struct_name = "Markly::Node",
80
81
  .function = {
81
- .dmark = rb_Markly_Node_mark,
82
- .dfree = rb_Markly_Node_free,
82
+ .dmark = Markly_Node_Type_mark,
83
+ .dfree = Markly_Node_Type_free,
83
84
  },
84
85
  .data = NULL,
85
86
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
86
87
  };
87
88
 
88
- static void rb_Markly_Node_freed(cmark_mem *mem, void *user_data) {
89
+ static void Markly_Node_freed(cmark_mem *mem, void *user_data) {
89
90
  VALUE self = (VALUE)user_data;
90
91
 
91
92
  RTYPEDDATA_DATA(self) = NULL;
92
93
  }
93
94
 
94
- static VALUE rb_Markly_Node_wrap(cmark_node *node) {
95
+ static VALUE Markly_Node_wrap(cmark_node *node) {
95
96
  if (node == NULL)
96
97
  return Qnil;
97
98
 
@@ -101,18 +102,18 @@ static VALUE rb_Markly_Node_wrap(cmark_node *node) {
101
102
  return (VALUE)user_data;
102
103
  }
103
104
 
104
- VALUE self = TypedData_Wrap_Struct(rb_Markly_Node, &rb_Markly_Node_Type, node);
105
+ VALUE self = TypedData_Wrap_Struct(Markly_Node, &Markly_Node_Type, node);
105
106
  cmark_node_set_user_data(node, (void *)self);
106
- cmark_node_set_user_data_free_func(node, rb_Markly_Node_freed);
107
+ cmark_node_set_user_data_free_func(node, Markly_Node_freed);
107
108
 
108
109
  return self;
109
110
  }
110
111
 
111
- static void rb_Markly_Parser_free(void *data) {
112
+ static void Markly_Parser_Type_free(void *data) {
112
113
  cmark_parser_free(data);
113
114
  }
114
115
 
115
- static void rb_Markly_Parser_mark(void *data) {
116
+ static void Markly_Parser_Type_mark(void *data) {
116
117
  cmark_parser *parser = data;
117
118
 
118
119
  // Mark the parent to make sure that the tree won't be freed as long as a child node is referenced.
@@ -124,21 +125,21 @@ static void rb_Markly_Parser_mark(void *data) {
124
125
  }
125
126
  }
126
127
 
127
- static const rb_data_type_t rb_Markly_Parser_Type = {
128
+ static const rb_data_type_t Markly_Parser_Type = {
128
129
  .wrap_struct_name = "Markly::Parser",
129
130
  .function = {
130
- .dmark = rb_Markly_Parser_mark,
131
- .dfree = rb_Markly_Parser_free,
131
+ .dmark = Markly_Parser_Type_mark,
132
+ .dfree = Markly_Parser_Type_free,
132
133
  },
133
134
  .data = NULL,
134
135
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
135
136
  };
136
137
 
137
- static VALUE rb_Markly_Parser_alloc(VALUE self) {
138
- return TypedData_Wrap_Struct(self, &rb_Markly_Parser_Type, NULL);
138
+ static VALUE Markly_Parser_allocate(VALUE self) {
139
+ return TypedData_Wrap_Struct(self, &Markly_Parser_Type, NULL);
139
140
  }
140
141
 
141
- static VALUE rb_Markly_Parser_initialize(VALUE self, VALUE flags) {
142
+ static VALUE Markly_Parser_initialize(VALUE self, VALUE flags) {
142
143
  Check_Type(flags, T_FIXNUM);
143
144
 
144
145
  cmark_mem *mem = cmark_get_default_mem_allocator();
@@ -149,14 +150,14 @@ static VALUE rb_Markly_Parser_initialize(VALUE self, VALUE flags) {
149
150
  return self;
150
151
  }
151
152
 
152
- static VALUE rb_Markly_Parser_enable(VALUE self, VALUE extension) {
153
+ static VALUE Markly_Parser_enable(VALUE self, VALUE extension) {
153
154
  cmark_parser *parser = NULL;
154
155
 
155
156
  Check_Type(extension, T_SYMBOL);
156
157
 
157
158
  VALUE extension_name = rb_sym2str(extension);
158
159
 
159
- TypedData_Get_Struct(self, cmark_parser, &rb_Markly_Parser_Type, parser);
160
+ TypedData_Get_Struct(self, cmark_parser, &Markly_Parser_Type, parser);
160
161
 
161
162
  cmark_syntax_extension *syntax_extension =
162
163
  cmark_find_syntax_extension(StringValueCStr(extension_name));
@@ -170,18 +171,18 @@ static VALUE rb_Markly_Parser_enable(VALUE self, VALUE extension) {
170
171
  return Qnil;
171
172
  }
172
173
 
173
- static VALUE rb_Markly_Parser_parse(VALUE self, VALUE text) {
174
+ static VALUE Markly_Parser_parse(VALUE self, VALUE text) {
174
175
  cmark_parser *parser = NULL;
175
176
 
176
177
  StringValue(text);
177
178
 
178
- TypedData_Get_Struct(self, cmark_parser, &rb_Markly_Parser_Type, parser);
179
+ TypedData_Get_Struct(self, cmark_parser, &Markly_Parser_Type, parser);
179
180
 
180
181
  cmark_parser_feed(parser, RSTRING_PTR(text), RSTRING_LEN(text));
181
182
 
182
183
  cmark_node *root = cmark_parser_finish(parser);
183
184
 
184
- return rb_Markly_Node_wrap(root);
185
+ return Markly_Node_wrap(root);
185
186
  }
186
187
 
187
188
  /*
@@ -209,7 +210,7 @@ static VALUE rb_Markly_Parser_parse(VALUE self, VALUE text) {
209
210
  * - `:link`
210
211
  * - `:image`
211
212
  */
212
- static VALUE rb_node_new(VALUE self, VALUE type) {
213
+ static VALUE Markly_Node_new(VALUE self, VALUE type) {
213
214
  cmark_node_type node_type = 0;
214
215
  cmark_node *node;
215
216
 
@@ -260,26 +261,26 @@ static VALUE rb_node_new(VALUE self, VALUE type) {
260
261
  else if (type == sym_footnote_definition)
261
262
  node_type = CMARK_NODE_FOOTNOTE_DEFINITION;
262
263
  else
263
- rb_raise(rb_Markly_Error, "invalid node of type %d", node_type);
264
+ rb_raise(Markly_Error, "invalid node of type %d", node_type);
264
265
 
265
266
  node = cmark_node_new(node_type);
266
267
  if (node == NULL) {
267
- rb_raise(rb_Markly_Error, "could not create node of type %d", node_type);
268
+ rb_raise(Markly_Error, "could not create node of type %d", node_type);
268
269
  }
269
270
 
270
- return rb_Markly_Node_wrap(node);
271
+ return Markly_Node_wrap(node);
271
272
  }
272
273
 
273
- static VALUE rb_node_replace(VALUE self, VALUE other) {
274
+ static VALUE Markly_Node_replace(VALUE self, VALUE other) {
274
275
  cmark_node *current_node = NULL, *replacement_node = NULL;
275
276
 
276
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, current_node);
277
- TypedData_Get_Struct(other, cmark_node, &rb_Markly_Node_Type, replacement_node);
277
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, current_node);
278
+ TypedData_Get_Struct(other, cmark_node, &Markly_Node_Type, replacement_node);
278
279
 
279
280
  int result = cmark_node_replace(current_node, replacement_node);
280
281
 
281
282
  if (result == 0) {
282
- rb_raise(rb_Markly_Error, "could not replace node");
283
+ rb_raise(Markly_Error, "could not replace node");
283
284
  }
284
285
 
285
286
  return other;
@@ -297,10 +298,10 @@ static VALUE encode_utf8_string(const char *c_string) {
297
298
  *
298
299
  * Returns a {String} or {nil} if there is no string content.
299
300
  */
300
- static VALUE rb_node_get_string_content(VALUE self) {
301
+ static VALUE Markly_Node_get_string_content(VALUE self) {
301
302
  const char *text;
302
303
  cmark_node *node;
303
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
304
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
304
305
 
305
306
  text = cmark_node_get_literal(node);
306
307
 
@@ -318,16 +319,16 @@ static VALUE rb_node_get_string_content(VALUE self) {
318
319
  *
319
320
  * Raises Error if the string content can't be set.
320
321
  */
321
- static VALUE rb_node_set_string_content(VALUE self, VALUE s) {
322
+ static VALUE Markly_Node_set_string_content(VALUE self, VALUE s) {
322
323
  char *text;
323
324
  cmark_node *node;
324
325
  Check_Type(s, T_STRING);
325
326
 
326
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
327
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
327
328
  text = StringValueCStr(s);
328
329
 
329
330
  if (!cmark_node_set_literal(node, text)) {
330
- rb_raise(rb_Markly_Error, "could not set string content");
331
+ rb_raise(Markly_Error, "could not set string content");
331
332
  }
332
333
 
333
334
  return Qnil;
@@ -338,13 +339,13 @@ static VALUE rb_node_set_string_content(VALUE self, VALUE s) {
338
339
  *
339
340
  * Returns a {Symbol} representing the node's type.
340
341
  */
341
- static VALUE rb_node_get_type(VALUE self) {
342
+ static VALUE Markly_Node_get_type(VALUE self) {
342
343
  int node_type = 0;
343
344
  cmark_node *node = NULL;
344
345
  VALUE symbol = Qnil;
345
346
  const char *s = NULL;
346
347
 
347
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
348
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
348
349
 
349
350
  node_type = cmark_node_get_type(node);
350
351
  symbol = Qnil;
@@ -416,12 +417,15 @@ static VALUE rb_node_get_type(VALUE self) {
416
417
  case CMARK_NODE_FOOTNOTE_DEFINITION:
417
418
  symbol = sym_footnote_definition;
418
419
  break;
420
+ case CMARK_NODE_FRONT_MATTER:
421
+ symbol = sym_front_matter;
422
+ break;
419
423
  default:
420
424
  if (node->extension) {
421
425
  s = node->extension->get_type_string_func(node->extension, node);
422
426
  return ID2SYM(rb_intern(s));
423
427
  }
424
- rb_raise(rb_Markly_Error, "invalid node type %d", node_type);
428
+ rb_raise(Markly_Error, "invalid node type %d", node_type);
425
429
  }
426
430
 
427
431
  return symbol;
@@ -432,12 +436,12 @@ static VALUE rb_node_get_type(VALUE self) {
432
436
  *
433
437
  * Returns a {Hash} containing {Symbol} keys of the positions.
434
438
  */
435
- static VALUE rb_node_get_source_position(VALUE self) {
439
+ static VALUE Markly_Node_get_source_position(VALUE self) {
436
440
  int start_line, start_column, end_line, end_column;
437
441
  VALUE result;
438
442
 
439
443
  cmark_node *node;
440
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
444
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
441
445
 
442
446
  start_line = cmark_node_get_start_line(node);
443
447
  start_column = cmark_node_get_start_column(node);
@@ -458,9 +462,9 @@ static VALUE rb_node_get_source_position(VALUE self) {
458
462
  *
459
463
  * Returns a {String}.
460
464
  */
461
- static VALUE rb_node_get_type_string(VALUE self) {
465
+ static VALUE Markly_Node_get_type_string(VALUE self) {
462
466
  cmark_node *node;
463
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
467
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
464
468
 
465
469
  return rb_str_new2(cmark_node_get_type_string(node));
466
470
  }
@@ -469,9 +473,9 @@ static VALUE rb_node_get_type_string(VALUE self) {
469
473
  * Internal: Unlinks the node from the tree (fixing pointers in
470
474
  * parents and siblings appropriately).
471
475
  */
472
- static VALUE rb_node_unlink(VALUE self) {
476
+ static VALUE Markly_Node_unlink(VALUE self) {
473
477
  cmark_node *node;
474
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
478
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
475
479
 
476
480
  cmark_node_unlink(node);
477
481
 
@@ -482,26 +486,26 @@ static VALUE rb_node_unlink(VALUE self) {
482
486
  *
483
487
  * Returns a {Node} if a child exists, `nil` otherise.
484
488
  */
485
- static VALUE rb_node_first_child(VALUE self) {
489
+ static VALUE Markly_Node_first_child(VALUE self) {
486
490
  cmark_node *node, *child;
487
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
491
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
488
492
 
489
493
  child = cmark_node_first_child(node);
490
494
 
491
- return rb_Markly_Node_wrap(child);
495
+ return Markly_Node_wrap(child);
492
496
  }
493
497
 
494
498
  /* Public: Fetches the next sibling of the node.
495
499
  *
496
500
  * Returns a {Node} if a sibling exists, `nil` otherwise.
497
501
  */
498
- static VALUE rb_node_next(VALUE self) {
502
+ static VALUE Markly_Node_next(VALUE self) {
499
503
  cmark_node *node, *next;
500
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
504
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
501
505
 
502
506
  next = cmark_node_next(node);
503
507
 
504
- return rb_Markly_Node_wrap(next);
508
+ return Markly_Node_wrap(next);
505
509
  }
506
510
 
507
511
  /*
@@ -512,13 +516,13 @@ static VALUE rb_node_next(VALUE self) {
512
516
  * Returns `true` if successful.
513
517
  * Raises Error if the node can't be inserted.
514
518
  */
515
- static VALUE rb_node_insert_before(VALUE self, VALUE sibling) {
519
+ static VALUE Markly_Node_insert_before(VALUE self, VALUE sibling) {
516
520
  cmark_node *node1, *node2;
517
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node1);
518
- TypedData_Get_Struct(sibling, cmark_node, &rb_Markly_Node_Type, node2);
521
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node1);
522
+ TypedData_Get_Struct(sibling, cmark_node, &Markly_Node_Type, node2);
519
523
 
520
524
  if (!cmark_node_insert_before(node1, node2)) {
521
- rb_raise(rb_Markly_Error, "could not insert before");
525
+ rb_raise(Markly_Error, "could not insert before");
522
526
  }
523
527
 
524
528
  return Qtrue;
@@ -528,7 +532,7 @@ static VALUE rb_node_insert_before(VALUE self, VALUE sibling) {
528
532
  *
529
533
  * Returns a {String}.
530
534
  */
531
- static VALUE rb_render_html(VALUE self, VALUE rb_options, VALUE rb_extensions) {
535
+ static VALUE Markly_Node_render_html(VALUE self, VALUE rb_options, VALUE rb_extensions) {
532
536
  VALUE rb_ext_name;
533
537
  int i;
534
538
  cmark_node *node;
@@ -540,7 +544,7 @@ static VALUE rb_render_html(VALUE self, VALUE rb_options, VALUE rb_extensions) {
540
544
  int options = FIX2INT(rb_options);
541
545
  long extensions_len = RARRAY_LEN(rb_extensions);
542
546
 
543
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
547
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
544
548
 
545
549
  for (i = 0; i < extensions_len; ++i) {
546
550
  rb_ext_name = RARRAY_PTR(rb_extensions)[i];
@@ -574,7 +578,7 @@ static VALUE rb_render_html(VALUE self, VALUE rb_options, VALUE rb_extensions) {
574
578
  *
575
579
  * Returns a {String}.
576
580
  */
577
- static VALUE rb_render_commonmark(int argc, VALUE *argv, VALUE self) {
581
+ static VALUE Markly_Node_render_commonmark(int argc, VALUE *argv, VALUE self) {
578
582
  VALUE rb_options, rb_width;
579
583
  rb_scan_args(argc, argv, "11", &rb_options, &rb_width);
580
584
 
@@ -589,7 +593,7 @@ static VALUE rb_render_commonmark(int argc, VALUE *argv, VALUE self) {
589
593
  Check_Type(rb_options, T_FIXNUM);
590
594
 
591
595
  options = FIX2INT(rb_options);
592
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
596
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
593
597
 
594
598
  char *cmark = cmark_render_commonmark(node, options, width);
595
599
  VALUE ruby_cmark = rb_str_new2(cmark);
@@ -602,7 +606,7 @@ static VALUE rb_render_commonmark(int argc, VALUE *argv, VALUE self) {
602
606
  *
603
607
  * Returns a {String}.
604
608
  */
605
- static VALUE rb_render_plaintext(int argc, VALUE *argv, VALUE self) {
609
+ static VALUE Markly_Node_render_plaintext(int argc, VALUE *argv, VALUE self) {
606
610
  VALUE rb_options, rb_width;
607
611
  rb_scan_args(argc, argv, "11", &rb_options, &rb_width);
608
612
 
@@ -617,7 +621,7 @@ static VALUE rb_render_plaintext(int argc, VALUE *argv, VALUE self) {
617
621
  Check_Type(rb_options, T_FIXNUM);
618
622
 
619
623
  options = FIX2INT(rb_options);
620
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
624
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
621
625
 
622
626
  char *text = cmark_render_plaintext(node, options, width);
623
627
  VALUE ruby_text = rb_str_new2(text);
@@ -634,13 +638,13 @@ static VALUE rb_render_plaintext(int argc, VALUE *argv, VALUE self) {
634
638
  * Returns `true` if successful.
635
639
  * Raises Error if the node can't be inserted.
636
640
  */
637
- static VALUE rb_node_insert_after(VALUE self, VALUE sibling) {
641
+ static VALUE Markly_Node_insert_after(VALUE self, VALUE sibling) {
638
642
  cmark_node *node1, *node2;
639
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node1);
640
- TypedData_Get_Struct(sibling, cmark_node, &rb_Markly_Node_Type, node2);
643
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node1);
644
+ TypedData_Get_Struct(sibling, cmark_node, &Markly_Node_Type, node2);
641
645
 
642
646
  if (!cmark_node_insert_after(node1, node2)) {
643
- rb_raise(rb_Markly_Error, "could not insert after");
647
+ rb_raise(Markly_Error, "could not insert after");
644
648
  }
645
649
 
646
650
  return Qtrue;
@@ -654,13 +658,13 @@ static VALUE rb_node_insert_after(VALUE self, VALUE sibling) {
654
658
  * Returns `true` if successful.
655
659
  * Raises Error if the node can't be inserted.
656
660
  */
657
- static VALUE rb_node_prepend_child(VALUE self, VALUE child) {
661
+ static VALUE Markly_Node_prepend_child(VALUE self, VALUE child) {
658
662
  cmark_node *node1, *node2;
659
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node1);
660
- TypedData_Get_Struct(child, cmark_node, &rb_Markly_Node_Type, node2);
663
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node1);
664
+ TypedData_Get_Struct(child, cmark_node, &Markly_Node_Type, node2);
661
665
 
662
666
  if (!cmark_node_prepend_child(node1, node2)) {
663
- rb_raise(rb_Markly_Error, "could not prepend child");
667
+ rb_raise(Markly_Error, "could not prepend child");
664
668
  }
665
669
 
666
670
  return Qtrue;
@@ -674,13 +678,13 @@ static VALUE rb_node_prepend_child(VALUE self, VALUE child) {
674
678
  * Returns `true` if successful.
675
679
  * Raises Error if the node can't be inserted.
676
680
  */
677
- static VALUE rb_node_append_child(VALUE self, VALUE child) {
681
+ static VALUE Markly_Node_append_child(VALUE self, VALUE child) {
678
682
  cmark_node *node1, *node2;
679
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node1);
680
- TypedData_Get_Struct(child, cmark_node, &rb_Markly_Node_Type, node2);
683
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node1);
684
+ TypedData_Get_Struct(child, cmark_node, &Markly_Node_Type, node2);
681
685
 
682
686
  if (!cmark_node_append_child(node1, node2)) {
683
- rb_raise(rb_Markly_Error, "could not append child");
687
+ rb_raise(Markly_Error, "could not append child");
684
688
  }
685
689
 
686
690
  return Qtrue;
@@ -690,39 +694,39 @@ static VALUE rb_node_append_child(VALUE self, VALUE child) {
690
694
  *
691
695
  * Returns a {Node} if a child exists, `nil` otherise.
692
696
  */
693
- static VALUE rb_node_last_child(VALUE self) {
697
+ static VALUE Markly_Node_last_child(VALUE self) {
694
698
  cmark_node *node, *child;
695
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
699
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
696
700
 
697
701
  child = cmark_node_last_child(node);
698
702
 
699
- return rb_Markly_Node_wrap(child);
703
+ return Markly_Node_wrap(child);
700
704
  }
701
705
 
702
706
  /* Public: Fetches the parent of the current node.
703
707
  *
704
708
  * Returns a {Node} if a parent exists, `nil` otherise.
705
709
  */
706
- static VALUE rb_node_parent(VALUE self) {
710
+ static VALUE Markly_Node_parent(VALUE self) {
707
711
  cmark_node *node, *parent;
708
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
712
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
709
713
 
710
714
  parent = cmark_node_parent(node);
711
715
 
712
- return rb_Markly_Node_wrap(parent);
716
+ return Markly_Node_wrap(parent);
713
717
  }
714
718
 
715
719
  /* Public: Fetches the previous sibling of the current node.
716
720
  *
717
721
  * Returns a {Node} if a parent exists, `nil` otherise.
718
722
  */
719
- static VALUE rb_node_previous(VALUE self) {
723
+ static VALUE Markly_Node_previous(VALUE self) {
720
724
  cmark_node *node, *previous;
721
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
725
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
722
726
 
723
727
  previous = cmark_node_previous(node);
724
728
 
725
- return rb_Markly_Node_wrap(previous);
729
+ return Markly_Node_wrap(previous);
726
730
  }
727
731
 
728
732
  /*
@@ -731,14 +735,14 @@ static VALUE rb_node_previous(VALUE self) {
731
735
  * Returns a {String}.
732
736
  * Raises a Error if the URL can't be retrieved.
733
737
  */
734
- static VALUE rb_node_get_url(VALUE self) {
738
+ static VALUE Markly_Node_get_url(VALUE self) {
735
739
  const char *text;
736
740
  cmark_node *node;
737
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
741
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
738
742
 
739
743
  text = cmark_node_get_url(node);
740
744
  if (text == NULL) {
741
- rb_raise(rb_Markly_Error, "could not get url");
745
+ rb_raise(Markly_Error, "could not get url");
742
746
  }
743
747
 
744
748
  return rb_str_new2(text);
@@ -751,16 +755,16 @@ static VALUE rb_node_get_url(VALUE self) {
751
755
  *
752
756
  * Raises a Error if the URL can't be set.
753
757
  */
754
- static VALUE rb_node_set_url(VALUE self, VALUE url) {
758
+ static VALUE Markly_Node_set_url(VALUE self, VALUE url) {
755
759
  cmark_node *node;
756
760
  char *text;
757
761
  Check_Type(url, T_STRING);
758
762
 
759
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
763
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
760
764
  text = StringValueCStr(url);
761
765
 
762
766
  if (!cmark_node_set_url(node, text)) {
763
- rb_raise(rb_Markly_Error, "could not set url");
767
+ rb_raise(Markly_Error, "could not set url");
764
768
  }
765
769
 
766
770
  return Qnil;
@@ -772,14 +776,14 @@ static VALUE rb_node_set_url(VALUE self, VALUE url) {
772
776
  * Returns a {String}.
773
777
  * Raises a Error if the title can't be retrieved.
774
778
  */
775
- static VALUE rb_node_get_title(VALUE self) {
779
+ static VALUE Markly_Node_get_title(VALUE self) {
776
780
  const char *text;
777
781
  cmark_node *node;
778
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
782
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
779
783
 
780
784
  text = cmark_node_get_title(node);
781
785
  if (text == NULL) {
782
- rb_raise(rb_Markly_Error, "could not get title");
786
+ rb_raise(Markly_Error, "could not get title");
783
787
  }
784
788
 
785
789
  return rb_str_new2(text);
@@ -792,16 +796,16 @@ static VALUE rb_node_get_title(VALUE self) {
792
796
  *
793
797
  * Raises a Error if the title can't be set.
794
798
  */
795
- static VALUE rb_node_set_title(VALUE self, VALUE title) {
799
+ static VALUE Markly_Node_set_title(VALUE self, VALUE title) {
796
800
  char *text;
797
801
  cmark_node *node;
798
802
  Check_Type(title, T_STRING);
799
803
 
800
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
804
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
801
805
  text = StringValueCStr(title);
802
806
 
803
807
  if (!cmark_node_set_title(node, text)) {
804
- rb_raise(rb_Markly_Error, "could not set title");
808
+ rb_raise(Markly_Error, "could not set title");
805
809
  }
806
810
 
807
811
  return Qnil;
@@ -813,15 +817,15 @@ static VALUE rb_node_set_title(VALUE self, VALUE title) {
813
817
  * Returns a {Number} representing the header level.
814
818
  * Raises a Error if the header level can't be retrieved.
815
819
  */
816
- static VALUE rb_node_get_header_level(VALUE self) {
820
+ static VALUE Markly_Node_get_header_level(VALUE self) {
817
821
  int header_level;
818
822
  cmark_node *node;
819
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
823
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
820
824
 
821
825
  header_level = cmark_node_get_header_level(node);
822
826
 
823
827
  if (header_level == 0) {
824
- rb_raise(rb_Markly_Error, "could not get header_level");
828
+ rb_raise(Markly_Error, "could not get header_level");
825
829
  }
826
830
 
827
831
  return INT2NUM(header_level);
@@ -834,16 +838,16 @@ static VALUE rb_node_get_header_level(VALUE self) {
834
838
  *
835
839
  * Raises a Error if the header level can't be set.
836
840
  */
837
- static VALUE rb_node_set_header_level(VALUE self, VALUE level) {
841
+ static VALUE Markly_Node_set_header_level(VALUE self, VALUE level) {
838
842
  int l;
839
843
  cmark_node *node;
840
844
  Check_Type(level, T_FIXNUM);
841
845
 
842
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
846
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
843
847
  l = FIX2INT(level);
844
848
 
845
849
  if (!cmark_node_set_header_level(node, l)) {
846
- rb_raise(rb_Markly_Error, "could not set header_level");
850
+ rb_raise(Markly_Error, "could not set header_level");
847
851
  }
848
852
 
849
853
  return Qnil;
@@ -855,11 +859,11 @@ static VALUE rb_node_set_header_level(VALUE self, VALUE level) {
855
859
  * Returns a {Symbol}.
856
860
  * Raises a Error if the title can't be retrieved.
857
861
  */
858
- static VALUE rb_node_get_list_type(VALUE self) {
862
+ static VALUE Markly_Node_get_list_type(VALUE self) {
859
863
  int list_type;
860
864
  cmark_node *node;
861
865
  VALUE symbol;
862
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
866
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
863
867
 
864
868
  list_type = cmark_node_get_list_type(node);
865
869
 
@@ -868,7 +872,7 @@ static VALUE rb_node_get_list_type(VALUE self) {
868
872
  } else if (list_type == CMARK_ORDERED_LIST) {
869
873
  symbol = sym_ordered_list;
870
874
  } else {
871
- rb_raise(rb_Markly_Error, "could not get list_type");
875
+ rb_raise(Markly_Error, "could not get list_type");
872
876
  }
873
877
 
874
878
  return symbol;
@@ -881,23 +885,23 @@ static VALUE rb_node_get_list_type(VALUE self) {
881
885
  *
882
886
  * Raises a Error if the list type can't be set.
883
887
  */
884
- static VALUE rb_node_set_list_type(VALUE self, VALUE list_type) {
888
+ static VALUE Markly_Node_set_list_type(VALUE self, VALUE list_type) {
885
889
  int type = 0;
886
890
  cmark_node *node;
887
891
  Check_Type(list_type, T_SYMBOL);
888
892
 
889
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
893
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
890
894
 
891
895
  if (list_type == sym_bullet_list) {
892
896
  type = CMARK_BULLET_LIST;
893
897
  } else if (list_type == sym_ordered_list) {
894
898
  type = CMARK_ORDERED_LIST;
895
899
  } else {
896
- rb_raise(rb_Markly_Error, "invalid list_type");
900
+ rb_raise(Markly_Error, "invalid list_type");
897
901
  }
898
902
 
899
903
  if (!cmark_node_set_list_type(node, type)) {
900
- rb_raise(rb_Markly_Error, "could not set list_type");
904
+ rb_raise(Markly_Error, "could not set list_type");
901
905
  }
902
906
 
903
907
  return Qnil;
@@ -910,13 +914,13 @@ static VALUE rb_node_set_list_type(VALUE self, VALUE list_type) {
910
914
  * Returns a {Number} representing the starting number.
911
915
  * Raises a Error if the starting number can't be retrieved.
912
916
  */
913
- static VALUE rb_node_get_list_start(VALUE self) {
917
+ static VALUE Markly_Node_get_list_start(VALUE self) {
914
918
  cmark_node *node;
915
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
919
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
916
920
 
917
921
  if (cmark_node_get_type(node) != CMARK_NODE_LIST ||
918
922
  cmark_node_get_list_type(node) != CMARK_ORDERED_LIST) {
919
- rb_raise(rb_Markly_Error, "can't get list_start for non-ordered list %d",
923
+ rb_raise(Markly_Error, "can't get list_start for non-ordered list %d",
920
924
  cmark_node_get_list_type(node));
921
925
  }
922
926
 
@@ -931,16 +935,16 @@ static VALUE rb_node_get_list_start(VALUE self) {
931
935
  *
932
936
  * Raises a Error if the starting number can't be set.
933
937
  */
934
- static VALUE rb_node_set_list_start(VALUE self, VALUE start) {
938
+ static VALUE Markly_Node_set_list_start(VALUE self, VALUE start) {
935
939
  int s;
936
940
  cmark_node *node;
937
941
  Check_Type(start, T_FIXNUM);
938
942
 
939
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
943
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
940
944
  s = FIX2INT(start);
941
945
 
942
946
  if (!cmark_node_set_list_start(node, s)) {
943
- rb_raise(rb_Markly_Error, "could not set list_start");
947
+ rb_raise(Markly_Error, "could not set list_start");
944
948
  }
945
949
 
946
950
  return Qnil;
@@ -952,13 +956,13 @@ static VALUE rb_node_set_list_start(VALUE self, VALUE start) {
952
956
  * Returns a `true` if the list is tight, `false` otherwise.
953
957
  * Raises a Error if the starting number can't be retrieved.
954
958
  */
955
- static VALUE rb_node_get_list_tight(VALUE self) {
959
+ static VALUE Markly_Node_get_list_tight(VALUE self) {
956
960
  int flag;
957
961
  cmark_node *node;
958
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
962
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
959
963
 
960
964
  if (cmark_node_get_type(node) != CMARK_NODE_LIST) {
961
- rb_raise(rb_Markly_Error, "can't get list_tight for non-list");
965
+ rb_raise(Markly_Error, "can't get list_tight for non-list");
962
966
  }
963
967
 
964
968
  flag = cmark_node_get_list_tight(node);
@@ -973,14 +977,14 @@ static VALUE rb_node_get_list_tight(VALUE self) {
973
977
  *
974
978
  * Raises a Error if the tightness can't be set.
975
979
  */
976
- static VALUE rb_node_set_list_tight(VALUE self, VALUE tight) {
980
+ static VALUE Markly_Node_set_list_tight(VALUE self, VALUE tight) {
977
981
  int t;
978
982
  cmark_node *node;
979
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
983
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
980
984
  t = RTEST(tight);
981
985
 
982
986
  if (!cmark_node_set_list_tight(node, t)) {
983
- rb_raise(rb_Markly_Error, "could not set list_tight");
987
+ rb_raise(Markly_Error, "could not set list_tight");
984
988
  }
985
989
 
986
990
  return Qnil;
@@ -992,15 +996,15 @@ static VALUE rb_node_set_list_tight(VALUE self, VALUE tight) {
992
996
  * Returns a {String} representing the fence info.
993
997
  * Raises a Error if the fence info can't be retrieved.
994
998
  */
995
- static VALUE rb_node_get_fence_info(VALUE self) {
999
+ static VALUE Markly_Node_get_fence_info(VALUE self) {
996
1000
  const char *fence_info;
997
1001
  cmark_node *node;
998
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1002
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
999
1003
 
1000
1004
  fence_info = cmark_node_get_fence_info(node);
1001
1005
 
1002
1006
  if (fence_info == NULL) {
1003
- rb_raise(rb_Markly_Error, "could not get fence_info");
1007
+ rb_raise(Markly_Error, "could not get fence_info");
1004
1008
  }
1005
1009
 
1006
1010
  return rb_str_new2(fence_info);
@@ -1013,25 +1017,96 @@ static VALUE rb_node_get_fence_info(VALUE self) {
1013
1017
  *
1014
1018
  * Raises a Error if the fence info can't be set.
1015
1019
  */
1016
- static VALUE rb_node_set_fence_info(VALUE self, VALUE info) {
1020
+ static VALUE Markly_Node_set_fence_info(VALUE self, VALUE info) {
1017
1021
  char *text;
1018
1022
  cmark_node *node;
1019
1023
  Check_Type(info, T_STRING);
1020
1024
 
1021
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1025
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1022
1026
  text = StringValueCStr(info);
1023
1027
 
1024
1028
  if (!cmark_node_set_fence_info(node, text)) {
1025
- rb_raise(rb_Markly_Error, "could not set fence_info");
1029
+ rb_raise(Markly_Error, "could not set fence_info");
1030
+ }
1031
+
1032
+ return Qnil;
1033
+ }
1034
+
1035
+ /*
1036
+ * Public: Gets the code info of the current node (must be a `:code_block`,
1037
+ * `:front_matter`, or inline `:code` node).
1038
+ *
1039
+ * Returns a {String} representing the code info.
1040
+ * Raises a Error if the code info can't be retrieved.
1041
+ */
1042
+ static VALUE Markly_Node_get_code_info(VALUE self) {
1043
+ const char *code_info;
1044
+ cmark_node *node;
1045
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1046
+
1047
+ code_info = cmark_node_get_code_info(node);
1048
+
1049
+ if (code_info == NULL) {
1050
+ rb_raise(Markly_Error, "could not get code_info");
1051
+ }
1052
+
1053
+ return rb_str_new2(code_info);
1054
+ }
1055
+
1056
+ /*
1057
+ * Public: Sets the code info of the current node (must be a `:code_block`,
1058
+ * `:front_matter`, or inline `:code` node).
1059
+ *
1060
+ * info - A {String} representing the new code info, or `nil` to clear it.
1061
+ *
1062
+ * Raises a Error if the code info can't be set.
1063
+ */
1064
+ static VALUE Markly_Node_set_code_info(VALUE self, VALUE info) {
1065
+ const char *text = NULL;
1066
+ cmark_node *node;
1067
+
1068
+ if (!NIL_P(info)) {
1069
+ Check_Type(info, T_STRING);
1070
+ text = StringValueCStr(info);
1071
+ }
1072
+
1073
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1074
+
1075
+ if (!cmark_node_set_code_info(node, text)) {
1076
+ rb_raise(Markly_Error, "could not set code_info");
1026
1077
  }
1027
1078
 
1028
1079
  return Qnil;
1029
1080
  }
1030
1081
 
1031
- static VALUE rb_node_get_tasklist_item_checked(VALUE self) {
1082
+ /*
1083
+ * Public: Gets fencing details for the current node.
1084
+ *
1085
+ * Returns a {Markly::Node::Fence} for fenced code blocks, `nil` otherwise.
1086
+ */
1087
+ static VALUE Markly_Node_get_fence(VALUE self) {
1088
+ int fence_length = 0;
1089
+ int fence_offset = 0;
1090
+ char fence_character = '\0';
1091
+ cmark_node *node;
1092
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1093
+
1094
+ if (!cmark_node_get_fenced(node, &fence_length, &fence_offset, &fence_character)) {
1095
+ return Qnil;
1096
+ }
1097
+
1098
+ return rb_struct_new(
1099
+ Markly_Node_Fence,
1100
+ rb_str_new(&fence_character, 1),
1101
+ INT2NUM(fence_length),
1102
+ INT2NUM(fence_offset)
1103
+ );
1104
+ }
1105
+
1106
+ static VALUE Markly_Node_tasklist_item_checked_p(VALUE self) {
1032
1107
  int tasklist_state;
1033
1108
  cmark_node *node;
1034
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1109
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1035
1110
 
1036
1111
  tasklist_state = cmark_gfm_extensions_get_tasklist_item_checked(node);
1037
1112
 
@@ -1050,14 +1125,14 @@ static VALUE rb_node_get_tasklist_item_checked(VALUE self) {
1050
1125
  * Returns a {Boolean} representing the new checkbox state.
1051
1126
  * Raises a Error if the checkbox state can't be set.
1052
1127
  */
1053
- static VALUE rb_node_set_tasklist_item_checked(VALUE self, VALUE item_checked) {
1128
+ static VALUE Markly_Node_set_tasklist_item_checked(VALUE self, VALUE item_checked) {
1054
1129
  int tasklist_state;
1055
1130
  cmark_node *node;
1056
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1131
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1057
1132
  tasklist_state = RTEST(item_checked);
1058
1133
 
1059
1134
  if (!cmark_gfm_extensions_set_tasklist_item_checked(node, tasklist_state)) {
1060
- rb_raise(rb_Markly_Error, "could not set tasklist_item_checked");
1135
+ rb_raise(Markly_Error, "could not set tasklist_item_checked");
1061
1136
  };
1062
1137
 
1063
1138
  if (tasklist_state) {
@@ -1067,28 +1142,28 @@ static VALUE rb_node_set_tasklist_item_checked(VALUE self, VALUE item_checked) {
1067
1142
  }
1068
1143
  }
1069
1144
 
1070
- static VALUE rb_node_get_parent_footnote_def(VALUE self) {
1145
+ static VALUE Markly_Node_get_parent_footnote_def(VALUE self) {
1071
1146
  cmark_node *node;
1072
1147
  cmark_node *parent;
1073
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1148
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1074
1149
 
1075
1150
  parent = cmark_node_parent_footnote_def(node);
1076
1151
 
1077
- return rb_Markly_Node_wrap(parent);
1152
+ return Markly_Node_wrap(parent);
1078
1153
  }
1079
1154
 
1080
- static VALUE rb_node_get_table_alignments(VALUE self) {
1155
+ static VALUE Markly_Node_get_table_alignments(VALUE self) {
1081
1156
  uint16_t column_count, i;
1082
1157
  uint8_t *alignments;
1083
1158
  cmark_node *node;
1084
1159
  VALUE ary;
1085
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1160
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1086
1161
 
1087
1162
  column_count = cmark_gfm_extensions_get_table_columns(node);
1088
1163
  alignments = cmark_gfm_extensions_get_table_alignments(node);
1089
1164
 
1090
1165
  if (!column_count || !alignments) {
1091
- rb_raise(rb_Markly_Error, "could not get column_count or alignments");
1166
+ rb_raise(Markly_Error, "could not get column_count or alignments");
1092
1167
  }
1093
1168
 
1094
1169
  ary = rb_ary_new();
@@ -1106,12 +1181,12 @@ static VALUE rb_node_get_table_alignments(VALUE self) {
1106
1181
  }
1107
1182
 
1108
1183
  /* Internal: Escapes href URLs safely. */
1109
- static VALUE rb_html_escape_href(VALUE self, VALUE rb_text) {
1184
+ static VALUE Markly_Node_html_escape_href(VALUE self, VALUE rb_text) {
1110
1185
  char *result;
1111
1186
  cmark_node *node;
1112
1187
  Check_Type(rb_text, T_STRING);
1113
1188
 
1114
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1189
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1115
1190
 
1116
1191
  cmark_mem *mem = cmark_node_mem(node);
1117
1192
  cmark_strbuf buf = CMARK_BUF_INIT(mem);
@@ -1126,12 +1201,12 @@ static VALUE rb_html_escape_href(VALUE self, VALUE rb_text) {
1126
1201
  }
1127
1202
 
1128
1203
  /* Internal: Escapes HTML content safely. */
1129
- static VALUE rb_html_escape_html(VALUE self, VALUE rb_text) {
1204
+ static VALUE Markly_Node_html_escape_html(VALUE self, VALUE rb_text) {
1130
1205
  char *result;
1131
1206
  cmark_node *node;
1132
1207
  Check_Type(rb_text, T_STRING);
1133
1208
 
1134
- TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);
1209
+ TypedData_Get_Struct(self, cmark_node, &Markly_Node_Type, node);
1135
1210
 
1136
1211
  cmark_mem *mem = cmark_node_mem(node);
1137
1212
  cmark_strbuf buf = CMARK_BUF_INIT(mem);
@@ -1145,7 +1220,7 @@ static VALUE rb_html_escape_html(VALUE self, VALUE rb_text) {
1145
1220
  return rb_text;
1146
1221
  }
1147
1222
 
1148
- VALUE rb_Markly_extensions(VALUE self) {
1223
+ static VALUE Markly_extensions(VALUE self) {
1149
1224
  cmark_llist *exts, *it;
1150
1225
  cmark_syntax_extension *ext;
1151
1226
  VALUE ary = rb_ary_new();
@@ -1162,7 +1237,7 @@ VALUE rb_Markly_extensions(VALUE self) {
1162
1237
  return ary;
1163
1238
  }
1164
1239
 
1165
- __attribute__((visibility("default"))) void Init_markly(void) {
1240
+ static void Init_Markly_Node(VALUE Markly) {
1166
1241
  sym_document = ID2SYM(rb_intern("document"));
1167
1242
  sym_custom_block = ID2SYM(rb_intern("custom_block"));
1168
1243
  sym_custom_inline = ID2SYM(rb_intern("custom_inline"));
@@ -1185,6 +1260,7 @@ __attribute__((visibility("default"))) void Init_markly(void) {
1185
1260
  sym_image = ID2SYM(rb_intern("image"));
1186
1261
  sym_footnote_reference = ID2SYM(rb_intern("footnote_reference"));
1187
1262
  sym_footnote_definition = ID2SYM(rb_intern("footnote_definition"));
1263
+ sym_front_matter = ID2SYM(rb_intern("front_matter"));
1188
1264
 
1189
1265
  sym_bullet_list = ID2SYM(rb_intern("bullet_list"));
1190
1266
  sym_ordered_list = ID2SYM(rb_intern("ordered_list"));
@@ -1193,63 +1269,74 @@ __attribute__((visibility("default"))) void Init_markly(void) {
1193
1269
  sym_right = ID2SYM(rb_intern("right"));
1194
1270
  sym_center = ID2SYM(rb_intern("center"));
1195
1271
 
1196
- rb_Markly = rb_define_module("Markly");
1197
- rb_define_singleton_method(rb_Markly, "extensions", rb_Markly_extensions, 0);
1198
-
1199
- rb_Markly_Error = rb_define_class_under(rb_Markly, "Error", rb_eStandardError);
1272
+ Markly_Node = rb_define_class_under(Markly, "Node", rb_cObject);
1273
+ rb_undef_alloc_func(Markly_Node);
1274
+ rb_define_singleton_method(Markly_Node, "new", Markly_Node_new, 1);
1275
+ Markly_Node_Fence = rb_struct_define_under(Markly_Node, "Fence", "character", "length", "indent", NULL);
1276
+
1277
+ rb_define_method(Markly_Node, "replace", Markly_Node_replace, 1);
1278
+
1279
+ rb_define_method(Markly_Node, "string_content", Markly_Node_get_string_content, 0);
1280
+ rb_define_method(Markly_Node, "string_content=", Markly_Node_set_string_content, 1);
1281
+ rb_define_method(Markly_Node, "type", Markly_Node_get_type, 0);
1282
+ rb_define_method(Markly_Node, "type_string", Markly_Node_get_type_string, 0);
1283
+ rb_define_method(Markly_Node, "source_position", Markly_Node_get_source_position, 0);
1284
+ rb_define_method(Markly_Node, "delete", Markly_Node_unlink, 0);
1285
+ rb_define_method(Markly_Node, "first_child", Markly_Node_first_child, 0);
1286
+ rb_define_method(Markly_Node, "next", Markly_Node_next, 0);
1287
+ rb_define_method(Markly_Node, "insert_before", Markly_Node_insert_before, 1);
1288
+ rb_define_method(Markly_Node, "_render_html", Markly_Node_render_html, 2);
1289
+ rb_define_method(Markly_Node, "_render_commonmark", Markly_Node_render_commonmark, -1);
1290
+ rb_define_method(Markly_Node, "_render_plaintext", Markly_Node_render_plaintext, -1);
1291
+ rb_define_method(Markly_Node, "insert_after", Markly_Node_insert_after, 1);
1292
+ rb_define_method(Markly_Node, "prepend_child", Markly_Node_prepend_child, 1);
1293
+ rb_define_method(Markly_Node, "append_child", Markly_Node_append_child, 1);
1294
+ rb_define_method(Markly_Node, "last_child", Markly_Node_last_child, 0);
1295
+ rb_define_method(Markly_Node, "parent", Markly_Node_parent, 0);
1296
+ rb_define_method(Markly_Node, "previous", Markly_Node_previous, 0);
1297
+ rb_define_method(Markly_Node, "url", Markly_Node_get_url, 0);
1298
+ rb_define_method(Markly_Node, "url=", Markly_Node_set_url, 1);
1299
+ rb_define_method(Markly_Node, "title", Markly_Node_get_title, 0);
1300
+ rb_define_method(Markly_Node, "title=", Markly_Node_set_title, 1);
1301
+ rb_define_method(Markly_Node, "header_level", Markly_Node_get_header_level, 0);
1302
+ rb_define_method(Markly_Node, "header_level=", Markly_Node_set_header_level, 1);
1303
+ rb_define_method(Markly_Node, "list_type", Markly_Node_get_list_type, 0);
1304
+ rb_define_method(Markly_Node, "list_type=", Markly_Node_set_list_type, 1);
1305
+ rb_define_method(Markly_Node, "list_start", Markly_Node_get_list_start, 0);
1306
+ rb_define_method(Markly_Node, "list_start=", Markly_Node_set_list_start, 1);
1307
+ rb_define_method(Markly_Node, "list_tight", Markly_Node_get_list_tight, 0);
1308
+ rb_define_method(Markly_Node, "list_tight=", Markly_Node_set_list_tight, 1);
1309
+ rb_define_method(Markly_Node, "fence_info", Markly_Node_get_fence_info, 0);
1310
+ rb_define_method(Markly_Node, "fence_info=", Markly_Node_set_fence_info, 1);
1311
+ rb_define_method(Markly_Node, "code_info", Markly_Node_get_code_info, 0);
1312
+ rb_define_method(Markly_Node, "code_info=", Markly_Node_set_code_info, 1);
1313
+ rb_define_method(Markly_Node, "fence", Markly_Node_get_fence, 0);
1314
+ rb_define_method(Markly_Node, "table_alignments", Markly_Node_get_table_alignments, 0);
1315
+ rb_define_method(Markly_Node, "tasklist_item_checked?", Markly_Node_tasklist_item_checked_p, 0);
1316
+ rb_define_method(Markly_Node, "tasklist_item_checked=", Markly_Node_set_tasklist_item_checked, 1);
1317
+
1318
+ rb_define_method(Markly_Node, "parent_footnote_def", Markly_Node_get_parent_footnote_def, 0);
1319
+
1320
+ rb_define_method(Markly_Node, "html_escape_href", Markly_Node_html_escape_href, 1);
1321
+ rb_define_method(Markly_Node, "html_escape_html", Markly_Node_html_escape_html, 1);
1322
+ }
1323
+
1324
+ static void Init_Markly_Parser(VALUE Markly) {
1325
+ VALUE Markly_Parser = rb_define_class_under(Markly, "Parser", rb_cObject);
1326
+ rb_define_alloc_func(Markly_Parser, Markly_Parser_allocate);
1327
+ rb_define_method(Markly_Parser, "initialize", Markly_Parser_initialize, 1);
1328
+ rb_define_method(Markly_Parser, "enable", Markly_Parser_enable, 1);
1329
+ rb_define_method(Markly_Parser, "parse", Markly_Parser_parse, 1);
1330
+ }
1331
+
1332
+ __attribute__((visibility("default"))) void Init_markly(void) {
1333
+ VALUE Markly = rb_define_module("Markly");
1334
+ rb_define_singleton_method(Markly, "extensions", Markly_extensions, 0);
1200
1335
 
1201
- rb_Markly_Parser = rb_define_class_under(rb_Markly, "Parser", rb_cObject);
1202
- rb_define_alloc_func(rb_Markly_Parser, rb_Markly_Parser_alloc);
1203
- rb_define_method(rb_Markly_Parser, "initialize", rb_Markly_Parser_initialize, 1);
1204
- rb_define_method(rb_Markly_Parser, "enable", rb_Markly_Parser_enable, 1);
1205
- rb_define_method(rb_Markly_Parser, "parse", rb_Markly_Parser_parse, 1);
1336
+ Markly_Error = rb_define_class_under(Markly, "Error", rb_eStandardError);
1206
1337
 
1207
- rb_Markly_Node = rb_define_class_under(rb_Markly, "Node", rb_cObject);
1208
- rb_undef_alloc_func(rb_Markly_Node);
1209
- rb_define_singleton_method(rb_Markly_Node, "new", rb_node_new, 1);
1210
-
1211
- rb_define_method(rb_Markly_Node, "replace", rb_node_replace, 1);
1212
-
1213
- rb_define_method(rb_Markly_Node, "string_content", rb_node_get_string_content, 0);
1214
- rb_define_method(rb_Markly_Node, "string_content=", rb_node_set_string_content, 1);
1215
- rb_define_method(rb_Markly_Node, "type", rb_node_get_type, 0);
1216
- rb_define_method(rb_Markly_Node, "type_string", rb_node_get_type_string, 0);
1217
- rb_define_method(rb_Markly_Node, "source_position", rb_node_get_source_position, 0);
1218
- rb_define_method(rb_Markly_Node, "delete", rb_node_unlink, 0);
1219
- rb_define_method(rb_Markly_Node, "first_child", rb_node_first_child, 0);
1220
- rb_define_method(rb_Markly_Node, "next", rb_node_next, 0);
1221
- rb_define_method(rb_Markly_Node, "insert_before", rb_node_insert_before, 1);
1222
- rb_define_method(rb_Markly_Node, "_render_html", rb_render_html, 2);
1223
- rb_define_method(rb_Markly_Node, "_render_commonmark", rb_render_commonmark, -1);
1224
- rb_define_method(rb_Markly_Node, "_render_plaintext", rb_render_plaintext, -1);
1225
- rb_define_method(rb_Markly_Node, "insert_after", rb_node_insert_after, 1);
1226
- rb_define_method(rb_Markly_Node, "prepend_child", rb_node_prepend_child, 1);
1227
- rb_define_method(rb_Markly_Node, "append_child", rb_node_append_child, 1);
1228
- rb_define_method(rb_Markly_Node, "last_child", rb_node_last_child, 0);
1229
- rb_define_method(rb_Markly_Node, "parent", rb_node_parent, 0);
1230
- rb_define_method(rb_Markly_Node, "previous", rb_node_previous, 0);
1231
- rb_define_method(rb_Markly_Node, "url", rb_node_get_url, 0);
1232
- rb_define_method(rb_Markly_Node, "url=", rb_node_set_url, 1);
1233
- rb_define_method(rb_Markly_Node, "title", rb_node_get_title, 0);
1234
- rb_define_method(rb_Markly_Node, "title=", rb_node_set_title, 1);
1235
- rb_define_method(rb_Markly_Node, "header_level", rb_node_get_header_level, 0);
1236
- rb_define_method(rb_Markly_Node, "header_level=", rb_node_set_header_level, 1);
1237
- rb_define_method(rb_Markly_Node, "list_type", rb_node_get_list_type, 0);
1238
- rb_define_method(rb_Markly_Node, "list_type=", rb_node_set_list_type, 1);
1239
- rb_define_method(rb_Markly_Node, "list_start", rb_node_get_list_start, 0);
1240
- rb_define_method(rb_Markly_Node, "list_start=", rb_node_set_list_start, 1);
1241
- rb_define_method(rb_Markly_Node, "list_tight", rb_node_get_list_tight, 0);
1242
- rb_define_method(rb_Markly_Node, "list_tight=", rb_node_set_list_tight, 1);
1243
- rb_define_method(rb_Markly_Node, "fence_info", rb_node_get_fence_info, 0);
1244
- rb_define_method(rb_Markly_Node, "fence_info=", rb_node_set_fence_info, 1);
1245
- rb_define_method(rb_Markly_Node, "table_alignments", rb_node_get_table_alignments, 0);
1246
- rb_define_method(rb_Markly_Node, "tasklist_item_checked?", rb_node_get_tasklist_item_checked, 0);
1247
- rb_define_method(rb_Markly_Node, "tasklist_item_checked=", rb_node_set_tasklist_item_checked, 1);
1248
-
1249
- rb_define_method(rb_Markly_Node, "parent_footnote_def", rb_node_get_parent_footnote_def, 0);
1250
-
1251
- rb_define_method(rb_Markly_Node, "html_escape_href", rb_html_escape_href, 1);
1252
- rb_define_method(rb_Markly_Node, "html_escape_html", rb_html_escape_html, 1);
1338
+ Init_Markly_Node(Markly);
1339
+ Init_Markly_Parser(Markly);
1253
1340
 
1254
1341
  cmark_gfm_core_extensions_ensure_registered();
1255
1342
  }