commonmarker 0.23.10 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1220 -0
  3. data/Cargo.toml +7 -0
  4. data/README.md +217 -170
  5. data/ext/commonmarker/Cargo.toml +20 -0
  6. data/ext/commonmarker/extconf.rb +3 -6
  7. data/ext/commonmarker/src/lib.rs +183 -0
  8. data/ext/commonmarker/src/node.rs +1112 -0
  9. data/ext/commonmarker/src/options.rs +165 -0
  10. data/ext/commonmarker/src/plugins/syntax_highlighting.rs +74 -0
  11. data/ext/commonmarker/src/plugins.rs +3 -0
  12. data/ext/commonmarker/src/utils.rs +8 -0
  13. data/lib/commonmarker/config.rb +90 -40
  14. data/lib/commonmarker/constants.rb +7 -0
  15. data/lib/commonmarker/extension.rb +14 -0
  16. data/lib/commonmarker/node/ast.rb +8 -0
  17. data/lib/commonmarker/node/inspect.rb +14 -4
  18. data/lib/commonmarker/node.rb +29 -47
  19. data/lib/commonmarker/renderer.rb +1 -127
  20. data/lib/commonmarker/utils.rb +22 -0
  21. data/lib/commonmarker/version.rb +2 -2
  22. data/lib/commonmarker.rb +27 -25
  23. metadata +38 -186
  24. data/Rakefile +0 -109
  25. data/bin/commonmarker +0 -118
  26. data/commonmarker.gemspec +0 -38
  27. data/ext/commonmarker/arena.c +0 -104
  28. data/ext/commonmarker/autolink.c +0 -508
  29. data/ext/commonmarker/autolink.h +0 -8
  30. data/ext/commonmarker/blocks.c +0 -1622
  31. data/ext/commonmarker/buffer.c +0 -278
  32. data/ext/commonmarker/buffer.h +0 -116
  33. data/ext/commonmarker/case_fold_switch.inc +0 -4327
  34. data/ext/commonmarker/chunk.h +0 -135
  35. data/ext/commonmarker/cmark-gfm-core-extensions.h +0 -54
  36. data/ext/commonmarker/cmark-gfm-extension_api.h +0 -737
  37. data/ext/commonmarker/cmark-gfm-extensions_export.h +0 -42
  38. data/ext/commonmarker/cmark-gfm.h +0 -833
  39. data/ext/commonmarker/cmark-gfm_export.h +0 -42
  40. data/ext/commonmarker/cmark-gfm_version.h +0 -7
  41. data/ext/commonmarker/cmark.c +0 -55
  42. data/ext/commonmarker/cmark_ctype.c +0 -44
  43. data/ext/commonmarker/cmark_ctype.h +0 -33
  44. data/ext/commonmarker/commonmark.c +0 -514
  45. data/ext/commonmarker/commonmarker.c +0 -1308
  46. data/ext/commonmarker/commonmarker.h +0 -16
  47. data/ext/commonmarker/config.h +0 -76
  48. data/ext/commonmarker/core-extensions.c +0 -27
  49. data/ext/commonmarker/entities.inc +0 -2138
  50. data/ext/commonmarker/ext_scanners.c +0 -879
  51. data/ext/commonmarker/ext_scanners.h +0 -24
  52. data/ext/commonmarker/footnotes.c +0 -63
  53. data/ext/commonmarker/footnotes.h +0 -27
  54. data/ext/commonmarker/houdini.h +0 -57
  55. data/ext/commonmarker/houdini_href_e.c +0 -100
  56. data/ext/commonmarker/houdini_html_e.c +0 -66
  57. data/ext/commonmarker/houdini_html_u.c +0 -149
  58. data/ext/commonmarker/html.c +0 -502
  59. data/ext/commonmarker/html.h +0 -27
  60. data/ext/commonmarker/inlines.c +0 -1788
  61. data/ext/commonmarker/inlines.h +0 -29
  62. data/ext/commonmarker/iterator.c +0 -159
  63. data/ext/commonmarker/iterator.h +0 -26
  64. data/ext/commonmarker/latex.c +0 -468
  65. data/ext/commonmarker/linked_list.c +0 -37
  66. data/ext/commonmarker/man.c +0 -274
  67. data/ext/commonmarker/map.c +0 -129
  68. data/ext/commonmarker/map.h +0 -44
  69. data/ext/commonmarker/node.c +0 -1045
  70. data/ext/commonmarker/node.h +0 -167
  71. data/ext/commonmarker/parser.h +0 -59
  72. data/ext/commonmarker/plaintext.c +0 -218
  73. data/ext/commonmarker/plugin.c +0 -36
  74. data/ext/commonmarker/plugin.h +0 -34
  75. data/ext/commonmarker/references.c +0 -43
  76. data/ext/commonmarker/references.h +0 -26
  77. data/ext/commonmarker/registry.c +0 -63
  78. data/ext/commonmarker/registry.h +0 -24
  79. data/ext/commonmarker/render.c +0 -213
  80. data/ext/commonmarker/render.h +0 -62
  81. data/ext/commonmarker/scanners.c +0 -14056
  82. data/ext/commonmarker/scanners.h +0 -70
  83. data/ext/commonmarker/scanners.re +0 -341
  84. data/ext/commonmarker/strikethrough.c +0 -167
  85. data/ext/commonmarker/strikethrough.h +0 -9
  86. data/ext/commonmarker/syntax_extension.c +0 -149
  87. data/ext/commonmarker/syntax_extension.h +0 -34
  88. data/ext/commonmarker/table.c +0 -917
  89. data/ext/commonmarker/table.h +0 -12
  90. data/ext/commonmarker/tagfilter.c +0 -60
  91. data/ext/commonmarker/tagfilter.h +0 -8
  92. data/ext/commonmarker/tasklist.c +0 -156
  93. data/ext/commonmarker/tasklist.h +0 -8
  94. data/ext/commonmarker/utf8.c +0 -317
  95. data/ext/commonmarker/utf8.h +0 -35
  96. data/ext/commonmarker/xml.c +0 -182
  97. data/lib/commonmarker/renderer/html_renderer.rb +0 -256
@@ -0,0 +1,1112 @@
1
+ use comrak::nodes::{
2
+ Ast as ComrakAst, AstNode as ComrakAstNode, ListDelimType, ListType, NodeCode, NodeCodeBlock,
3
+ NodeDescriptionItem, NodeFootnoteDefinition, NodeFootnoteReference, NodeHeading, NodeHtmlBlock,
4
+ NodeLink, NodeList, NodeMath, NodeMultilineBlockQuote, NodeShortCode, NodeTable,
5
+ NodeValue as ComrakNodeValue, TableAlignment,
6
+ };
7
+ use comrak::{arena_tree::Node as ComrakNode, ComrakOptions};
8
+ use magnus::RArray;
9
+ use magnus::{
10
+ function, method, r_hash::ForEach, scan_args, Module, Object, RHash, RModule, Symbol, Value,
11
+ };
12
+ use rctree::Node;
13
+ use typed_arena::Arena;
14
+
15
+ use std::cell::RefCell;
16
+
17
+ use crate::options::iterate_options_hash;
18
+
19
+ #[derive(Debug, Clone)]
20
+ #[magnus::wrap(class = "Commonmarker::Node::Ast", size, mark)]
21
+ pub struct CommonmarkerAst {
22
+ data: ComrakAst,
23
+ }
24
+
25
+ #[derive(Debug, Clone)]
26
+ #[magnus::wrap(class = "Commonmarker::Node", size, mark)]
27
+ pub struct CommonmarkerNode {
28
+ inner: Node<CommonmarkerAst>,
29
+ }
30
+
31
+ /// SAFETY: This is safe because we only access this data when the GVL is held.
32
+ unsafe impl Send for CommonmarkerNode {}
33
+
34
+ impl CommonmarkerNode {
35
+ pub fn new(args: &[Value]) -> Result<Self, magnus::Error> {
36
+ let args = scan_args::scan_args::<_, (), (), (), _, ()>(args)?;
37
+ let (node_type,): (Symbol,) = args.required;
38
+
39
+ let node = match node_type.to_string().as_str() {
40
+ "document" => ComrakNodeValue::Document,
41
+ "block_quote" => ComrakNodeValue::BlockQuote,
42
+ "footnote_definition" => {
43
+ let kwargs = scan_args::get_kwargs::<_, (String,), (Option<u32>,), ()>(
44
+ args.keywords,
45
+ &["name"],
46
+ &["total_references"],
47
+ )?;
48
+ let (name,) = kwargs.required;
49
+ let (total_reference,) = kwargs.optional;
50
+
51
+ ComrakNodeValue::FootnoteDefinition(NodeFootnoteDefinition {
52
+ // The name of the footnote.
53
+ name,
54
+ // Total number of references to this footnote
55
+ total_references: total_reference.unwrap_or(1),
56
+ })
57
+ }
58
+ "list" => {
59
+ let kwargs = scan_args::get_kwargs::<
60
+ _,
61
+ (Symbol,),
62
+ (
63
+ Option<usize>,
64
+ Option<usize>,
65
+ Option<usize>,
66
+ Option<String>,
67
+ Option<u8>,
68
+ Option<bool>,
69
+ ),
70
+ (),
71
+ >(
72
+ args.keywords,
73
+ &["type"],
74
+ &[
75
+ "marker_offset",
76
+ "padding",
77
+ "start",
78
+ "delimiter",
79
+ "bullet_char",
80
+ "tight",
81
+ ],
82
+ )?;
83
+
84
+ let (list_type,) = kwargs.required;
85
+ let (marker_offset, padding, start, delimiter, bullet_char, tight) =
86
+ kwargs.optional;
87
+
88
+ let commonmark_list_type = list_type.to_string();
89
+
90
+ if commonmark_list_type != "bullet" && commonmark_list_type != "ordered" {
91
+ return Err(magnus::Error::new(
92
+ magnus::exception::arg_error(),
93
+ "list type must be `bullet` or `ordered`",
94
+ ));
95
+ }
96
+
97
+ let comrak_list_type = if commonmark_list_type == "ordered" {
98
+ ListType::Ordered
99
+ } else {
100
+ ListType::Bullet
101
+ };
102
+
103
+ let comrak_delimiter = match delimiter.unwrap_or("".to_string()).as_str() {
104
+ ")" => ListDelimType::Paren,
105
+ _ => ListDelimType::Period,
106
+ };
107
+
108
+ ComrakNodeValue::List(NodeList {
109
+ // The kind of list (bullet (unordered) or ordered).
110
+ list_type: comrak_list_type,
111
+ // Number of spaces before the list marker.
112
+ marker_offset: marker_offset.unwrap_or(0),
113
+ // Number of characters between the start of the list marker and the item text (including the list marker(s)).
114
+ padding: padding.unwrap_or(0),
115
+ // For ordered lists, the ordinal the list starts at.
116
+ start: start.unwrap_or(0),
117
+ // For ordered lists, the delimiter after each number.
118
+ delimiter: comrak_delimiter,
119
+ // For bullet lists, the character used for each bullet.
120
+ bullet_char: bullet_char.unwrap_or(0),
121
+ // Whether the list is [tight](https://github.github.com/gfm/#tight), i.e. whether the
122
+ // paragraphs are wrapped in `<p>` tags when formatted as HTML.
123
+ tight: tight.unwrap_or(false),
124
+ })
125
+ }
126
+ "description_list" => ComrakNodeValue::DescriptionList,
127
+ "description_item" => {
128
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<usize>, Option<usize>), ()>(
129
+ args.keywords,
130
+ &[],
131
+ &["marker_offset", "padding"],
132
+ )?;
133
+
134
+ let (marker_offset, padding) = kwargs.optional;
135
+
136
+ ComrakNodeValue::DescriptionItem(NodeDescriptionItem {
137
+ // Number of spaces before the list marker.
138
+ marker_offset: marker_offset.unwrap_or(0),
139
+ // Number of characters between the start of the list marker and the item text (including the list marker(s)).
140
+ padding: padding.unwrap_or(0),
141
+ })
142
+ }
143
+ "description_term" => ComrakNodeValue::DescriptionTerm,
144
+ "description_details" => ComrakNodeValue::DescriptionDetails,
145
+ "code_block" => {
146
+ let kwargs = scan_args::get_kwargs::<
147
+ _,
148
+ (bool,),
149
+ (
150
+ Option<u8>,
151
+ Option<usize>,
152
+ Option<usize>,
153
+ Option<String>,
154
+ Option<String>,
155
+ ),
156
+ (),
157
+ >(
158
+ args.keywords,
159
+ &["fenced"],
160
+ &[
161
+ "fence_char",
162
+ "fence_length",
163
+ "fence_offset",
164
+ "info",
165
+ "literal",
166
+ ],
167
+ )?;
168
+ let (fenced,) = kwargs.required;
169
+ let (fence_char, fence_length, fence_offset, info, literal) = kwargs.optional;
170
+
171
+ ComrakNodeValue::CodeBlock(NodeCodeBlock {
172
+ // Whether the code block is fenced.
173
+ fenced,
174
+ // For fenced code blocks, the fence character itself (`` ` `` or `~`).
175
+ fence_char: fence_char.unwrap_or(b'`'),
176
+ // For fenced code blocks, the length of the fence.
177
+ fence_length: fence_length.unwrap_or(0),
178
+ // For fenced code blocks, the indentation level of the code within the block.
179
+ fence_offset: fence_offset.unwrap_or(0),
180
+
181
+ // For fenced code blocks, the [info string](https://github.github.com/gfm/#info-string) after
182
+ // the opening fence, if any.
183
+ info: info.unwrap_or(String::with_capacity(10)),
184
+
185
+ // The literal contents of the code block. As the contents are not interpreted as Markdown at
186
+ // all, they are contained within this structure, rather than inserted into a child inline of
187
+ // any kind.
188
+ literal: literal.unwrap_or(String::new()),
189
+ })
190
+ }
191
+ "html_block" => {
192
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<u8>, Option<String>), ()>(
193
+ args.keywords,
194
+ &[],
195
+ &["block_type", "literal"],
196
+ )?;
197
+
198
+ let (block_type, literal) = kwargs.optional;
199
+
200
+ ComrakNodeValue::HtmlBlock(NodeHtmlBlock {
201
+ // Number of spaces before the list marker.
202
+ block_type: block_type.unwrap_or(0),
203
+ // Number of characters between the start of the list marker and the item text (including the list marker(s)).
204
+ literal: literal.unwrap_or(String::new()),
205
+ })
206
+ }
207
+ "paragraph" => ComrakNodeValue::Paragraph,
208
+ "heading" => {
209
+ let kwargs = scan_args::get_kwargs::<_, (u8,), (Option<bool>,), ()>(
210
+ args.keywords,
211
+ &["level"],
212
+ &["setext"],
213
+ )?;
214
+
215
+ let (level,) = kwargs.required;
216
+ let (setext,) = kwargs.optional;
217
+
218
+ ComrakNodeValue::Heading(NodeHeading {
219
+ // Number of spaces before the list marker.
220
+ level,
221
+ // Number of characters between the start of the list marker and the item text (including the list marker(s)).
222
+ setext: setext.unwrap_or(false),
223
+ })
224
+ }
225
+ "thematic_break" => ComrakNodeValue::ThematicBreak,
226
+ "table" => {
227
+ let kwargs = scan_args::get_kwargs::<_, (RArray, usize, usize, usize), (), ()>(
228
+ args.keywords,
229
+ &[
230
+ "alignments",
231
+ "num_columns",
232
+ "num_rows",
233
+ "num_nonempty_cells",
234
+ ],
235
+ &[],
236
+ )?;
237
+
238
+ let (alignments, num_columns, num_rows, num_nonempty_cells) = kwargs.required;
239
+
240
+ let mut comrak_alignments = vec![];
241
+ alignments.each().for_each(|alignment| {
242
+ match alignment.unwrap().to_string().as_str() {
243
+ "left" => {
244
+ comrak_alignments.push(TableAlignment::Left);
245
+ }
246
+ "right" => {
247
+ comrak_alignments.push(TableAlignment::Right);
248
+ }
249
+ "center" => {
250
+ comrak_alignments.push(TableAlignment::Center);
251
+ }
252
+ _ => {
253
+ comrak_alignments.push(TableAlignment::None);
254
+ }
255
+ }
256
+ });
257
+ ComrakNodeValue::Table(NodeTable {
258
+ // The table alignments
259
+ alignments: comrak_alignments,
260
+
261
+ // Number of columns of the table
262
+ num_columns,
263
+
264
+ // Number of rows of the table
265
+ num_rows,
266
+
267
+ // Number of non-empty, non-autocompleted cells
268
+ num_nonempty_cells,
269
+ })
270
+ }
271
+ "table_row" => {
272
+ let kwargs =
273
+ scan_args::get_kwargs::<_, (bool,), (), ()>(args.keywords, &["header"], &[])?;
274
+
275
+ let (header,) = kwargs.required;
276
+
277
+ ComrakNodeValue::TableRow(header)
278
+ }
279
+ "table_cell" => ComrakNodeValue::TableCell,
280
+ "text" => {
281
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<String>,), ()>(
282
+ args.keywords,
283
+ &[],
284
+ &["content"],
285
+ )?;
286
+
287
+ let (content,) = kwargs.optional;
288
+
289
+ ComrakNodeValue::Text(content.unwrap_or("".to_string()))
290
+ }
291
+ "taskitem" => {
292
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<char>,), ()>(
293
+ args.keywords,
294
+ &[],
295
+ &["mark"],
296
+ )?;
297
+
298
+ let (mark,) = kwargs.optional;
299
+
300
+ ComrakNodeValue::TaskItem(mark)
301
+ }
302
+ "softbreak" => ComrakNodeValue::SoftBreak,
303
+ "linebreak" => ComrakNodeValue::LineBreak,
304
+ "code" => {
305
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<usize>, Option<String>), ()>(
306
+ args.keywords,
307
+ &[],
308
+ &["num_backticks", "literal"],
309
+ )?;
310
+
311
+ let (num_backticks, literal) = kwargs.optional;
312
+
313
+ ComrakNodeValue::Code(NodeCode {
314
+ // The number of backticks
315
+ num_backticks: num_backticks.unwrap_or(1),
316
+ // The content of the inline code span.
317
+ // As the contents are not interpreted as Markdown at all,
318
+ // they are contained within this structure,
319
+ // rather than inserted into a child inline of any kind
320
+ literal: literal.unwrap_or_default(),
321
+ })
322
+ }
323
+ "html_inline" => {
324
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<String>,), ()>(
325
+ args.keywords,
326
+ &[],
327
+ &["content"],
328
+ )?;
329
+
330
+ let (content,) = kwargs.optional;
331
+
332
+ ComrakNodeValue::HtmlInline(content.unwrap_or_default())
333
+ }
334
+ "emph" => ComrakNodeValue::Emph,
335
+ "strong" => ComrakNodeValue::Strong,
336
+ "strikethrough" => ComrakNodeValue::Strikethrough,
337
+ "superscript" => ComrakNodeValue::Superscript,
338
+ "link" => {
339
+ let kwargs = scan_args::get_kwargs::<_, (String,), (Option<String>,), ()>(
340
+ args.keywords,
341
+ &["url"],
342
+ &["title"],
343
+ )?;
344
+
345
+ let (url,) = kwargs.required;
346
+ let (title,) = kwargs.optional;
347
+
348
+ ComrakNodeValue::Link(NodeLink {
349
+ // The URL for the link destination or image source.
350
+ url,
351
+ // The title for the link or image.
352
+ //
353
+ // Note this field is used for the `title` attribute by the HTML formatter even for images;
354
+ // `alt` text is supplied in the image inline text.
355
+ title: title.unwrap_or_default(),
356
+ })
357
+ }
358
+ "image" => {
359
+ let kwargs = scan_args::get_kwargs::<_, (String,), (Option<String>,), ()>(
360
+ args.keywords,
361
+ &["url"],
362
+ &["title"],
363
+ )?;
364
+
365
+ let (url,) = kwargs.required;
366
+ let (title,) = kwargs.optional;
367
+
368
+ ComrakNodeValue::Image(NodeLink {
369
+ // The URL for the link destination or image source.
370
+ url,
371
+ // The title for the link or image.
372
+ //
373
+ // Note this field is used for the `title` attribute by the HTML formatter even for images;
374
+ // `alt` text is supplied in the image inline text.
375
+ title: title.unwrap_or_default(),
376
+ })
377
+ }
378
+ "footnote_reference" => {
379
+ let kwargs = scan_args::get_kwargs::<_, (String,), (Option<u32>, Option<u32>), ()>(
380
+ args.keywords,
381
+ &["name"],
382
+ &["ref_num", "ix"],
383
+ )?;
384
+
385
+ let (name,) = kwargs.required;
386
+ let (ref_num, ix) = kwargs.optional;
387
+
388
+ ComrakNodeValue::FootnoteReference(NodeFootnoteReference {
389
+ // The name of the footnote.
390
+ name,
391
+ // The index of reference to the same footnote
392
+ ref_num: ref_num.unwrap_or(0),
393
+ // The index of the footnote in the document.
394
+ ix: ix.unwrap_or(0),
395
+ })
396
+ }
397
+ // #[cfg(feature = "shortcodes")]
398
+ "shortcode" => {
399
+ let kwargs =
400
+ scan_args::get_kwargs::<_, (String,), (), ()>(args.keywords, &["code"], &[])?;
401
+
402
+ let (code,) = kwargs.required;
403
+
404
+ match NodeShortCode::try_from(code.as_str()) {
405
+ Ok(shortcode) => ComrakNodeValue::ShortCode(shortcode),
406
+ _ => {
407
+ return Err(magnus::Error::new(
408
+ magnus::exception::arg_error(),
409
+ "list type must be `bullet` or `ordered`",
410
+ ));
411
+ }
412
+ }
413
+ }
414
+ "math" => {
415
+ let kwargs = scan_args::get_kwargs::<_, (bool, bool, String), (), ()>(
416
+ args.keywords,
417
+ &["dollar_math", "display_math", "literal"],
418
+ &[],
419
+ )?;
420
+
421
+ let (dollar_math, display_math, literal) = kwargs.required;
422
+
423
+ ComrakNodeValue::Math(NodeMath {
424
+ // Whether this is dollar math (`$` or `$$`).
425
+ // `false` indicates it is code math
426
+ dollar_math,
427
+
428
+ // Whether this is display math (using `$$`)
429
+ display_math,
430
+
431
+ // The literal contents of the math span.
432
+ // As the contents are not interpreted as Markdown at all,
433
+ // they are contained within this structure,
434
+ // rather than inserted into a child inline of any kind.
435
+ literal,
436
+ })
437
+ }
438
+ "multiline_block_quote" => {
439
+ let kwargs = scan_args::get_kwargs::<_, (usize, usize), (), ()>(
440
+ args.keywords,
441
+ &["fence_length", "fence_offset"],
442
+ &[],
443
+ )?;
444
+
445
+ let (fence_length, fence_offset) = kwargs.required;
446
+
447
+ ComrakNodeValue::MultilineBlockQuote(NodeMultilineBlockQuote {
448
+ // The length of the fence.
449
+ fence_length,
450
+ // The indentation level of the fence marker.
451
+ fence_offset,
452
+ })
453
+ }
454
+
455
+ "escaped" => ComrakNodeValue::Escaped,
456
+ _ => panic!("unknown node type {}", node_type),
457
+ };
458
+
459
+ Ok(CommonmarkerNode {
460
+ inner: Node::new(CommonmarkerAst {
461
+ data: ComrakAst::new(node, (0, 0).into()),
462
+ }),
463
+ })
464
+ }
465
+
466
+ pub fn new_from_comrak_node<'a>(
467
+ comrak_root_node: &'a ComrakAstNode<'a>,
468
+ ) -> Result<CommonmarkerNode, magnus::Error> {
469
+ let comrak_ast = comrak_root_node.data.clone().into_inner();
470
+
471
+ fn iter_nodes<'a>(comrak_node: &'a ComrakAstNode<'a>) -> CommonmarkerNode {
472
+ let comrak_node_ast = comrak_node.data.clone().into_inner();
473
+ let commonmark_node = CommonmarkerNode {
474
+ inner: Node::new(CommonmarkerAst {
475
+ data: comrak_node_ast,
476
+ }),
477
+ };
478
+
479
+ for c in comrak_node.children() {
480
+ match commonmark_node.append_child_node(&iter_nodes(c)) {
481
+ Ok(_) => {}
482
+ Err(e) => {
483
+ panic!("cannot append node: {}", e);
484
+ }
485
+ }
486
+ }
487
+
488
+ commonmark_node
489
+ }
490
+
491
+ let commonmarker_root_node = CommonmarkerNode {
492
+ inner: Node::new(CommonmarkerAst { data: comrak_ast }),
493
+ };
494
+
495
+ for child in comrak_root_node.children() {
496
+ let new_child = iter_nodes(child);
497
+
498
+ commonmarker_root_node.append_child_node(&new_child)?;
499
+ }
500
+
501
+ Ok(commonmarker_root_node)
502
+ }
503
+
504
+ fn type_to_symbol(&self) -> Symbol {
505
+ let node = self.inner.borrow();
506
+ match node.data.value {
507
+ ComrakNodeValue::Document => Symbol::new("document"),
508
+ ComrakNodeValue::BlockQuote => Symbol::new("block_quote"),
509
+ ComrakNodeValue::FootnoteDefinition(_) => Symbol::new("footnote_definition"),
510
+ ComrakNodeValue::List(..) => Symbol::new("list"),
511
+ ComrakNodeValue::DescriptionList => Symbol::new("description_list"),
512
+ ComrakNodeValue::DescriptionItem(_) => Symbol::new("description_item"),
513
+ ComrakNodeValue::DescriptionTerm => Symbol::new("description_term"),
514
+ ComrakNodeValue::DescriptionDetails => Symbol::new("description_details"),
515
+ ComrakNodeValue::Item(..) => Symbol::new("item"),
516
+ ComrakNodeValue::CodeBlock(..) => Symbol::new("code_block"),
517
+ ComrakNodeValue::HtmlBlock(..) => Symbol::new("html_block"),
518
+ ComrakNodeValue::Paragraph => Symbol::new("paragraph"),
519
+ ComrakNodeValue::Heading(..) => Symbol::new("heading"),
520
+ ComrakNodeValue::ThematicBreak => Symbol::new("thematic_break"),
521
+ ComrakNodeValue::Table(..) => Symbol::new("table"),
522
+ ComrakNodeValue::TableRow(..) => Symbol::new("table_row"),
523
+ ComrakNodeValue::TableCell => Symbol::new("table_cell"),
524
+ ComrakNodeValue::Text(..) => Symbol::new("text"),
525
+ ComrakNodeValue::SoftBreak => Symbol::new("softbreak"),
526
+ ComrakNodeValue::LineBreak => Symbol::new("linebreak"),
527
+ ComrakNodeValue::Image(..) => Symbol::new("image"),
528
+ ComrakNodeValue::Link(..) => Symbol::new("link"),
529
+ ComrakNodeValue::Emph => Symbol::new("emph"),
530
+ ComrakNodeValue::Strong => Symbol::new("strong"),
531
+ ComrakNodeValue::Code(..) => Symbol::new("code"),
532
+ ComrakNodeValue::HtmlInline(..) => Symbol::new("html_inline"),
533
+ ComrakNodeValue::Strikethrough => Symbol::new("strikethrough"),
534
+ ComrakNodeValue::FrontMatter(_) => Symbol::new("frontmatter"),
535
+ ComrakNodeValue::TaskItem { .. } => Symbol::new("taskitem"),
536
+ ComrakNodeValue::Superscript => Symbol::new("superscript"),
537
+ ComrakNodeValue::FootnoteReference(..) => Symbol::new("footnote_reference"),
538
+ ComrakNodeValue::ShortCode(_) => Symbol::new("shortcode"),
539
+ ComrakNodeValue::MultilineBlockQuote(_) => Symbol::new("multiline_block_quote"),
540
+ ComrakNodeValue::Escaped => Symbol::new("escaped"),
541
+ ComrakNodeValue::Math(..) => Symbol::new("math"),
542
+ }
543
+ }
544
+
545
+ fn get_parent(&self) -> Option<CommonmarkerNode> {
546
+ self.inner.parent().map(|n| CommonmarkerNode { inner: n })
547
+ }
548
+
549
+ fn get_previous_sibling(&self) -> Option<CommonmarkerNode> {
550
+ self.inner
551
+ .previous_sibling()
552
+ .map(|n| CommonmarkerNode { inner: n })
553
+ }
554
+
555
+ fn get_next_sibling(&self) -> Option<CommonmarkerNode> {
556
+ self.inner
557
+ .next_sibling()
558
+ .map(|n| CommonmarkerNode { inner: n })
559
+ }
560
+
561
+ fn get_first_child(&self) -> Option<CommonmarkerNode> {
562
+ self.inner
563
+ .first_child()
564
+ .map(|n| CommonmarkerNode { inner: n })
565
+ }
566
+
567
+ fn get_last_child(&self) -> Option<CommonmarkerNode> {
568
+ self.inner
569
+ .last_child()
570
+ .map(|n| CommonmarkerNode { inner: n })
571
+ }
572
+
573
+ fn prepend_child_node(&self, new_child: &CommonmarkerNode) -> Result<bool, magnus::Error> {
574
+ let node = new_child.inner.clone();
575
+ node.detach();
576
+ self.inner.prepend(node);
577
+
578
+ Ok(true)
579
+ }
580
+
581
+ fn append_child_node(&self, new_child: &CommonmarkerNode) -> Result<bool, magnus::Error> {
582
+ let node = new_child.inner.clone();
583
+ node.detach();
584
+ self.inner.append(node);
585
+
586
+ Ok(true)
587
+ }
588
+
589
+ fn detach_node(&self) -> Result<CommonmarkerNode, magnus::Error> {
590
+ let node = self.inner.make_copy().borrow().data.clone();
591
+ self.inner.detach();
592
+
593
+ Ok(CommonmarkerNode {
594
+ inner: Node::new(CommonmarkerAst { data: node }),
595
+ })
596
+ }
597
+
598
+ fn get_sourcepos(&self) -> Result<RHash, magnus::Error> {
599
+ let node = self.inner.borrow();
600
+
601
+ let result = RHash::new();
602
+ result.aset(Symbol::new("start_line"), node.data.sourcepos.start.line)?;
603
+ result.aset(
604
+ Symbol::new("start_column"),
605
+ node.data.sourcepos.start.column,
606
+ )?;
607
+ result.aset(Symbol::new("end_line"), node.data.sourcepos.end.line)?;
608
+ result.aset(Symbol::new("end_column"), node.data.sourcepos.end.column)?;
609
+
610
+ Ok(result)
611
+ }
612
+
613
+ fn replace_node(&self, new_node: &CommonmarkerNode) -> Result<bool, magnus::Error> {
614
+ self.insert_node_after(new_node)?;
615
+ match self.detach_node() {
616
+ Ok(_) => Ok(true),
617
+ Err(e) => Err(e),
618
+ }
619
+ }
620
+
621
+ fn insert_node_before(&self, new_sibling: &CommonmarkerNode) -> Result<bool, magnus::Error> {
622
+ let node = new_sibling.inner.clone();
623
+ node.detach();
624
+ self.inner.insert_before(node);
625
+
626
+ Ok(true)
627
+ }
628
+
629
+ fn insert_node_after(&self, new_sibling: &CommonmarkerNode) -> Result<bool, magnus::Error> {
630
+ let node = new_sibling.inner.clone();
631
+ node.detach();
632
+ self.inner.insert_after(node);
633
+
634
+ Ok(true)
635
+ }
636
+
637
+ fn get_url(&self) -> Result<String, magnus::Error> {
638
+ let node = self.inner.borrow();
639
+
640
+ match &node.data.value {
641
+ ComrakNodeValue::Link(link) => Ok(link.url.to_string()),
642
+ ComrakNodeValue::Image(image) => Ok(image.url.to_string()),
643
+ _ => Err(magnus::Error::new(
644
+ magnus::exception::type_error(),
645
+ "node is not an image or link node",
646
+ )),
647
+ }
648
+ }
649
+
650
+ fn set_url(&self, new_url: String) -> Result<bool, magnus::Error> {
651
+ let mut node = self.inner.borrow_mut();
652
+
653
+ match node.data.value {
654
+ ComrakNodeValue::Link(ref mut link) => {
655
+ link.url = new_url;
656
+ Ok(true)
657
+ }
658
+ ComrakNodeValue::Image(ref mut image) => {
659
+ image.url = new_url;
660
+ Ok(true)
661
+ }
662
+ _ => Err(magnus::Error::new(
663
+ magnus::exception::type_error(),
664
+ "node is not an image or link node",
665
+ )),
666
+ }
667
+ }
668
+
669
+ fn get_string_content(&self) -> Result<String, magnus::Error> {
670
+ let node = self.inner.borrow();
671
+
672
+ match node.data.value {
673
+ ComrakNodeValue::Code(ref code) => return Ok(code.literal.to_string()),
674
+ ComrakNodeValue::CodeBlock(ref code_block) => {
675
+ return Ok(code_block.literal.to_string())
676
+ }
677
+ _ => {}
678
+ }
679
+
680
+ match node.data.value.text() {
681
+ Some(s) => Ok(s.to_string()),
682
+ None => Err(magnus::Error::new(
683
+ magnus::exception::type_error(),
684
+ "node does not have string content",
685
+ )),
686
+ }
687
+ }
688
+
689
+ fn set_string_content(&self, new_content: String) -> Result<bool, magnus::Error> {
690
+ let mut node = self.inner.borrow_mut();
691
+
692
+ match node.data.value {
693
+ ComrakNodeValue::Code(ref mut code) => {
694
+ code.literal = new_content;
695
+ return Ok(true);
696
+ }
697
+ ComrakNodeValue::CodeBlock(ref mut code_block) => {
698
+ code_block.literal = new_content;
699
+ return Ok(true);
700
+ }
701
+ _ => {}
702
+ }
703
+
704
+ match node.data.value.text_mut() {
705
+ Some(s) => {
706
+ *s = new_content;
707
+ Ok(true)
708
+ }
709
+ None => Err(magnus::Error::new(
710
+ magnus::exception::type_error(),
711
+ "node does not have string content",
712
+ )),
713
+ }
714
+ }
715
+
716
+ fn get_title(&self) -> Result<String, magnus::Error> {
717
+ let node = self.inner.borrow();
718
+
719
+ match &node.data.value {
720
+ ComrakNodeValue::Link(link) => Ok(link.title.to_string()),
721
+ ComrakNodeValue::Image(image) => Ok(image.title.to_string()),
722
+ _ => Err(magnus::Error::new(
723
+ magnus::exception::type_error(),
724
+ "node is not an image or link node",
725
+ )),
726
+ }
727
+ }
728
+
729
+ fn set_title(&self, new_title: String) -> Result<bool, magnus::Error> {
730
+ let mut node = self.inner.borrow_mut();
731
+
732
+ match node.data.value {
733
+ ComrakNodeValue::Link(ref mut link) => {
734
+ link.title = new_title;
735
+ Ok(true)
736
+ }
737
+ ComrakNodeValue::Image(ref mut image) => {
738
+ image.title = new_title;
739
+ Ok(true)
740
+ }
741
+ _ => Err(magnus::Error::new(
742
+ magnus::exception::type_error(),
743
+ "node is not an image or link node",
744
+ )),
745
+ }
746
+ }
747
+
748
+ fn get_header_level(&self) -> Result<u8, magnus::Error> {
749
+ let node = self.inner.borrow();
750
+
751
+ match &node.data.value {
752
+ ComrakNodeValue::Heading(heading) => Ok(heading.level),
753
+ _ => Err(magnus::Error::new(
754
+ magnus::exception::type_error(),
755
+ "node is not a heading node",
756
+ )),
757
+ }
758
+ }
759
+
760
+ fn set_header_level(&self, new_level: u8) -> Result<bool, magnus::Error> {
761
+ let mut node = self.inner.borrow_mut();
762
+
763
+ match node.data.value {
764
+ ComrakNodeValue::Heading(ref mut heading) => {
765
+ heading.level = new_level;
766
+ Ok(true)
767
+ }
768
+ _ => Err(magnus::Error::new(
769
+ magnus::exception::type_error(),
770
+ "node is not a heading node",
771
+ )),
772
+ }
773
+ }
774
+
775
+ fn get_list_type(&self) -> Result<Symbol, magnus::Error> {
776
+ let node = self.inner.borrow();
777
+
778
+ match &node.data.value {
779
+ ComrakNodeValue::List(list) => match list.list_type {
780
+ comrak::nodes::ListType::Bullet => Ok(Symbol::new("bullet")),
781
+ comrak::nodes::ListType::Ordered => Ok(Symbol::new("ordered")),
782
+ },
783
+ _ => Err(magnus::Error::new(
784
+ magnus::exception::type_error(),
785
+ "node is not a list node",
786
+ )),
787
+ }
788
+ }
789
+
790
+ fn set_list_type(&self, new_type: Symbol) -> Result<bool, magnus::Error> {
791
+ let mut node = self.inner.borrow_mut();
792
+
793
+ match node.data.value {
794
+ ComrakNodeValue::List(ref mut list) => {
795
+ match new_type.to_string().as_str() {
796
+ "bullet" => list.list_type = comrak::nodes::ListType::Bullet,
797
+ "ordered" => list.list_type = comrak::nodes::ListType::Ordered,
798
+ _ => return Ok(false),
799
+ }
800
+ Ok(true)
801
+ }
802
+ _ => Err(magnus::Error::new(
803
+ magnus::exception::type_error(),
804
+ "node is not a list node",
805
+ )),
806
+ }
807
+ }
808
+
809
+ fn get_list_start(&self) -> Result<usize, magnus::Error> {
810
+ let node = self.inner.borrow();
811
+
812
+ match &node.data.value {
813
+ ComrakNodeValue::List(list) => Ok(list.start),
814
+ _ => Err(magnus::Error::new(
815
+ magnus::exception::type_error(),
816
+ "node is not a list node",
817
+ )),
818
+ }
819
+ }
820
+
821
+ fn set_list_start(&self, new_start: usize) -> Result<bool, magnus::Error> {
822
+ let mut node = self.inner.borrow_mut();
823
+
824
+ match node.data.value {
825
+ ComrakNodeValue::List(ref mut list) => {
826
+ list.start = new_start;
827
+ Ok(true)
828
+ }
829
+ _ => Err(magnus::Error::new(
830
+ magnus::exception::type_error(),
831
+ "node is not a list node",
832
+ )),
833
+ }
834
+ }
835
+
836
+ fn get_list_tight(&self) -> Result<bool, magnus::Error> {
837
+ let node = self.inner.borrow();
838
+
839
+ match &node.data.value {
840
+ ComrakNodeValue::List(list) => Ok(list.tight),
841
+ _ => Err(magnus::Error::new(
842
+ magnus::exception::type_error(),
843
+ "node is not a list node",
844
+ )),
845
+ }
846
+ }
847
+
848
+ fn set_list_tight(&self, new_tight: bool) -> Result<bool, magnus::Error> {
849
+ let mut node = self.inner.borrow_mut();
850
+
851
+ match node.data.value {
852
+ ComrakNodeValue::List(ref mut list) => {
853
+ list.tight = new_tight;
854
+ Ok(true)
855
+ }
856
+ _ => Err(magnus::Error::new(
857
+ magnus::exception::type_error(),
858
+ "node is not a list node",
859
+ )),
860
+ }
861
+ }
862
+
863
+ fn get_fence_info(&self) -> Result<String, magnus::Error> {
864
+ let node = self.inner.borrow();
865
+
866
+ match &node.data.value {
867
+ ComrakNodeValue::CodeBlock(code_block) => Ok(code_block.info.to_string()),
868
+ _ => Err(magnus::Error::new(
869
+ magnus::exception::type_error(),
870
+ "node is not a code block node",
871
+ )),
872
+ }
873
+ }
874
+
875
+ fn set_fence_info(&self, new_info: String) -> Result<bool, magnus::Error> {
876
+ let mut node = self.inner.borrow_mut();
877
+
878
+ match node.data.value {
879
+ ComrakNodeValue::CodeBlock(ref mut code_block) => {
880
+ code_block.info = new_info;
881
+ Ok(true)
882
+ }
883
+ _ => Err(magnus::Error::new(
884
+ magnus::exception::type_error(),
885
+ "node is not a code block node",
886
+ )),
887
+ }
888
+ }
889
+
890
+ fn to_html(&self, args: &[Value]) -> Result<String, magnus::Error> {
891
+ let args = scan_args::scan_args::<(), (), (), (), _, ()>(args)?;
892
+
893
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<RHash>, Option<RHash>), ()>(
894
+ args.keywords,
895
+ &[],
896
+ &["options", "plugins"],
897
+ )?;
898
+ let (rb_options, _rb_plugins) = kwargs.optional;
899
+
900
+ let mut comrak_options = ComrakOptions::default();
901
+
902
+ if let Some(rb_options) = rb_options {
903
+ rb_options.foreach(|key: Symbol, value: RHash| {
904
+ iterate_options_hash(&mut comrak_options, key, value)?;
905
+ Ok(ForEach::Continue)
906
+ })?;
907
+ }
908
+
909
+ let arena: Arena<ComrakAstNode> = Arena::new();
910
+ fn iter_nodes<'a>(
911
+ arena: &'a Arena<comrak::arena_tree::Node<'a, RefCell<ComrakAst>>>,
912
+ node: &CommonmarkerNode,
913
+ ) -> &'a comrak::arena_tree::Node<'a, std::cell::RefCell<comrak::nodes::Ast>> {
914
+ let comrak_node: &'a mut ComrakAstNode = arena.alloc(ComrakNode::new(RefCell::new(
915
+ node.inner.borrow().data.clone(),
916
+ )));
917
+
918
+ for c in node.inner.children() {
919
+ let child = CommonmarkerNode { inner: c };
920
+ let child_node = iter_nodes(arena, &child);
921
+ comrak_node.append(child_node);
922
+ }
923
+
924
+ comrak_node
925
+ }
926
+
927
+ let comrak_root_node: ComrakNode<RefCell<ComrakAst>> =
928
+ ComrakNode::new(RefCell::new(self.inner.borrow().data.clone()));
929
+
930
+ for c in self.inner.children() {
931
+ let child = CommonmarkerNode { inner: c };
932
+
933
+ let new_child = iter_nodes(&arena, &child);
934
+
935
+ comrak_root_node.append(new_child);
936
+ }
937
+
938
+ let mut output = vec![];
939
+ match comrak::format_html(&comrak_root_node, &comrak_options, &mut output) {
940
+ Ok(_) => {}
941
+ Err(e) => {
942
+ return Err(magnus::Error::new(
943
+ magnus::exception::runtime_error(),
944
+ format!("cannot convert into html: {}", e),
945
+ ));
946
+ }
947
+ }
948
+
949
+ match std::str::from_utf8(&output) {
950
+ Ok(s) => Ok(s.to_string()),
951
+ Err(_e) => Err(magnus::Error::new(
952
+ magnus::exception::runtime_error(),
953
+ "cannot convert into utf-8",
954
+ )),
955
+ }
956
+ }
957
+
958
+ fn to_commonmark(&self, args: &[Value]) -> Result<String, magnus::Error> {
959
+ let args = scan_args::scan_args::<(), (), (), (), _, ()>(args)?;
960
+
961
+ let kwargs = scan_args::get_kwargs::<_, (), (Option<RHash>, Option<RHash>), ()>(
962
+ args.keywords,
963
+ &[],
964
+ &["options", "plugins"],
965
+ )?;
966
+ let (rb_options, _rb_plugins) = kwargs.optional;
967
+
968
+ let mut comrak_options = ComrakOptions::default();
969
+
970
+ if let Some(rb_options) = rb_options {
971
+ rb_options.foreach(|key: Symbol, value: RHash| {
972
+ iterate_options_hash(&mut comrak_options, key, value)?;
973
+ Ok(ForEach::Continue)
974
+ })?;
975
+ }
976
+
977
+ let arena: Arena<ComrakAstNode> = Arena::new();
978
+ fn iter_nodes<'a>(
979
+ arena: &'a Arena<comrak::arena_tree::Node<'a, RefCell<ComrakAst>>>,
980
+ node: &CommonmarkerNode,
981
+ ) -> &'a comrak::arena_tree::Node<'a, std::cell::RefCell<comrak::nodes::Ast>> {
982
+ let comrak_node: &'a mut ComrakAstNode = arena.alloc(ComrakNode::new(RefCell::new(
983
+ node.inner.borrow().data.clone(),
984
+ )));
985
+
986
+ for c in node.inner.children() {
987
+ let child = CommonmarkerNode { inner: c };
988
+ let child_node = iter_nodes(arena, &child);
989
+ comrak_node.append(child_node);
990
+ }
991
+
992
+ comrak_node
993
+ }
994
+
995
+ let comrak_root_node: ComrakNode<RefCell<ComrakAst>> =
996
+ ComrakNode::new(RefCell::new(self.inner.borrow().data.clone()));
997
+
998
+ for c in self.inner.children() {
999
+ let child = CommonmarkerNode { inner: c };
1000
+
1001
+ let new_child = iter_nodes(&arena, &child);
1002
+
1003
+ comrak_root_node.append(new_child);
1004
+ }
1005
+
1006
+ let mut output = vec![];
1007
+ match comrak::format_commonmark(&comrak_root_node, &comrak_options, &mut output) {
1008
+ Ok(_) => {}
1009
+ Err(e) => {
1010
+ return Err(magnus::Error::new(
1011
+ magnus::exception::runtime_error(),
1012
+ format!("cannot convert into html: {}", e),
1013
+ ));
1014
+ }
1015
+ }
1016
+
1017
+ match std::str::from_utf8(&output) {
1018
+ Ok(s) => Ok(s.to_string()),
1019
+ Err(_e) => Err(magnus::Error::new(
1020
+ magnus::exception::runtime_error(),
1021
+ "cannot convert into utf-8",
1022
+ )),
1023
+ }
1024
+ }
1025
+ }
1026
+
1027
+ pub fn init(m_commonmarker: RModule) -> Result<(), magnus::Error> {
1028
+ let c_node = m_commonmarker
1029
+ .define_class("Node", magnus::class::object())
1030
+ .expect("cannot define class Commonmarker::Node");
1031
+
1032
+ c_node.define_singleton_method("new", function!(CommonmarkerNode::new, -1))?;
1033
+
1034
+ c_node.define_method("type", method!(CommonmarkerNode::type_to_symbol, 0))?;
1035
+ c_node.define_method("parent", method!(CommonmarkerNode::get_parent, 0))?;
1036
+ c_node.define_method("first_child", method!(CommonmarkerNode::get_first_child, 0))?;
1037
+ c_node.define_method("last_child", method!(CommonmarkerNode::get_last_child, 0))?;
1038
+ c_node.define_method(
1039
+ "previous_sibling",
1040
+ method!(CommonmarkerNode::get_previous_sibling, 0),
1041
+ )?;
1042
+ c_node.define_method(
1043
+ "next_sibling",
1044
+ method!(CommonmarkerNode::get_next_sibling, 0),
1045
+ )?;
1046
+
1047
+ c_node.define_method("node_to_html", method!(CommonmarkerNode::to_html, -1))?;
1048
+ c_node.define_method(
1049
+ "node_to_commonmark",
1050
+ method!(CommonmarkerNode::to_commonmark, -1),
1051
+ )?;
1052
+
1053
+ c_node.define_method("replace", method!(CommonmarkerNode::replace_node, 1))?;
1054
+
1055
+ c_node.define_method(
1056
+ "insert_before",
1057
+ method!(CommonmarkerNode::insert_node_before, 1),
1058
+ )?;
1059
+ c_node.define_method(
1060
+ "insert_after",
1061
+ method!(CommonmarkerNode::insert_node_after, 1),
1062
+ )?;
1063
+
1064
+ c_node.define_method(
1065
+ "prepend_child",
1066
+ method!(CommonmarkerNode::prepend_child_node, 1),
1067
+ )?;
1068
+ c_node.define_method(
1069
+ "append_child",
1070
+ method!(CommonmarkerNode::append_child_node, 1),
1071
+ )?;
1072
+
1073
+ c_node.define_method("delete", method!(CommonmarkerNode::detach_node, 0))?;
1074
+
1075
+ c_node.define_method(
1076
+ "source_position",
1077
+ method!(CommonmarkerNode::get_sourcepos, 0),
1078
+ )?;
1079
+
1080
+ c_node.define_method(
1081
+ "string_content",
1082
+ method!(CommonmarkerNode::get_string_content, 0),
1083
+ )?;
1084
+ c_node.define_method(
1085
+ "string_content=",
1086
+ method!(CommonmarkerNode::set_string_content, 1),
1087
+ )?;
1088
+
1089
+ c_node.define_method("url", method!(CommonmarkerNode::get_url, 0))?;
1090
+ c_node.define_method("url=", method!(CommonmarkerNode::set_url, 1))?;
1091
+ c_node.define_method("title", method!(CommonmarkerNode::get_title, 0))?;
1092
+ c_node.define_method("title=", method!(CommonmarkerNode::set_title, 1))?;
1093
+
1094
+ c_node.define_method(
1095
+ "header_level",
1096
+ method!(CommonmarkerNode::get_header_level, 0),
1097
+ )?;
1098
+ c_node.define_method(
1099
+ "header_level=",
1100
+ method!(CommonmarkerNode::set_header_level, 1),
1101
+ )?;
1102
+ c_node.define_method("list_type", method!(CommonmarkerNode::get_list_type, 0))?;
1103
+ c_node.define_method("list_type=", method!(CommonmarkerNode::set_list_type, 1))?;
1104
+ c_node.define_method("list_start", method!(CommonmarkerNode::get_list_start, 0))?;
1105
+ c_node.define_method("list_start=", method!(CommonmarkerNode::set_list_start, 1))?;
1106
+ c_node.define_method("list_tight", method!(CommonmarkerNode::get_list_tight, 0))?;
1107
+ c_node.define_method("list_tight=", method!(CommonmarkerNode::set_list_tight, 1))?;
1108
+ c_node.define_method("fence_info", method!(CommonmarkerNode::get_fence_info, 0))?;
1109
+ c_node.define_method("fence_info=", method!(CommonmarkerNode::set_fence_info, 1))?;
1110
+
1111
+ Ok(())
1112
+ }