1#![deny(missing_docs)]
2use std::{cell::RefCell, io};
42
43use comrak::{
44 arena_tree::Node,
45 nodes::{
46 Ast, NodeCode, NodeCodeBlock, NodeDescriptionItem, NodeFootnoteDefinition,
47 NodeFootnoteReference, NodeHeading, NodeHtmlBlock, NodeLink, NodeList, NodeMath,
48 NodeMultilineBlockQuote, NodeShortCode, NodeTable, NodeValue, NodeWikiLink,
49 },
50};
51
52#[allow(unused_variables)]
53pub trait MarkdownWalker {
78 fn from_markdown(markdown: impl AsRef<str>) -> io::Result<Self>
84 where
85 Self: Default,
86 {
87 use comrak::{parse_document, Arena, ExtensionOptions, Options};
88
89 let arena = Arena::new();
90 let extension = ExtensionOptions::builder()
91 .autolink(true)
92 .description_lists(true)
93 .footnotes(true)
94 .math_code(true)
95 .math_dollars(true)
96 .multiline_block_quotes(true)
97 .shortcodes(true)
98 .spoiler(true)
99 .strikethrough(true)
100 .subscript(true)
101 .superscript(true)
102 .table(true)
103 .tagfilter(true)
104 .tasklist(true)
105 .underline(true)
106 .wikilinks_title_after_pipe(true)
107 .wikilinks_title_before_pipe(true)
108 .build();
109
110 let options = Options {
111 extension,
112 ..Options::default()
113 };
114
115 let nodes = parse_document(&arena, markdown.as_ref(), &options);
116
117 let mut this = Self::default();
118 this.visit(nodes)?;
119
120 Ok(this)
121 }
122
123 fn visit<'arena>(&mut self, node: &'arena Node<'arena, RefCell<Ast>>) -> io::Result<()> {
129 use NodeValue::*;
130
131 match &node.data.borrow().value {
132 Document => self.visit_document(node)?,
133
134 Code(code) => self.visit_code(node, code)?,
135 CodeBlock(code_block) => self.visit_code_block(node, code_block)?,
136 EscapedTag(tag) => self.visit_escaped_tag(node, tag)?,
137 FrontMatter(frontmatter) => self.visit_front_matter(node, frontmatter)?,
138 FootnoteDefinition(footnote_definition) => {
139 self.visit_footnote_definition(node, footnote_definition)?
140 }
141 FootnoteReference(node_footnote_reference) => {
142 self.visit_footnote_reference(node, node_footnote_reference)?
143 }
144 Heading(heading) => self.visit_heading(node, heading)?,
145 HtmlBlock(html_block) => self.visit_html_block(node, html_block)?,
146 HtmlInline(inline) => self.visit_html_inline(node, inline)?,
147 Image(link) => self.visit_image(node, link)?,
148 Item(list) => self.visit_item(node, list)?,
149 Link(link) => self.visit_link(node, link)?,
150 List(list) => self.visit_list(node, list)?,
151 Math(math) => self.visit_math(node, math)?,
152 MultilineBlockQuote(multiline_block_quote) => {
153 self.visit_multiline_block_quote(node, multiline_block_quote)?
154 }
155 Raw(raw) => self.visit_raw(node, raw)?,
156 TaskItem(task_item) => self.visit_task_item(node, task_item)?,
157 Text(text) => self.visit_text(node, text)?,
158 ShortCode(short_code) => self.visit_short_code(node, short_code)?,
159 WikiLink(wiki_link) => self.visit_wiki_link(node, wiki_link)?,
160
161 DescriptionItem(description_item) => {
162 self.visit_description_item(node, description_item)?
163 }
164 DescriptionList => self.visit_description_list(node)?,
165 DescriptionTerm => self.visit_description_term(node)?,
166 DescriptionDetails => self.visit_description_details(node)?,
167
168 Table(table) => self.visit_table(node, table)?,
169 TableRow(table_row) => self.visit_table_row(node, table_row)?,
170 TableCell => self.visit_table_cell(node)?,
171
172 BlockQuote => self.visit_block_quote(node)?,
173 Emph => self.visit_emph(node)?,
174 Escaped => self.visit_escaped(node)?,
175 LineBreak => self.visit_line_break(node)?,
176 Paragraph => self.visit_paragraph(node)?,
177 SoftBreak => self.visit_soft_break(node)?,
178 SpoileredText => self.visit_spoilered_text(node)?,
179 Strikethrough => self.visit_strikethrough(node)?,
180 Strong => self.visit_strong(node)?,
181 Subscript => self.visit_subscript(node)?,
182 Superscript => self.visit_superscript(node)?,
183 ThematicBreak => self.visit_thematic_break(node)?,
184 Underline => self.visit_underline(node)?,
185 }
186
187 for child in node.children() {
188 self.visit(child)?;
189 }
190
191 Ok(())
192 }
193
194 fn visit_block_quote<'arena>(
196 &mut self,
197 node: &'arena Node<'arena, RefCell<Ast>>,
198 ) -> io::Result<()> {
199 Ok(())
200 }
201
202 fn visit_code<'arena>(
204 &mut self,
205 node: &'arena Node<'arena, RefCell<Ast>>,
206 code: &NodeCode,
207 ) -> io::Result<()> {
208 Ok(())
209 }
210
211 fn visit_code_block<'arena>(
213 &mut self,
214 node: &'arena Node<'arena, RefCell<Ast>>,
215 code_block: &NodeCodeBlock,
216 ) -> io::Result<()> {
217 Ok(())
218 }
219
220 fn visit_description_item<'arena>(
222 &mut self,
223 node: &'arena Node<'arena, RefCell<Ast>>,
224 description_item: &NodeDescriptionItem,
225 ) -> io::Result<()> {
226 Ok(())
227 }
228
229 fn visit_description_list<'arena>(
231 &mut self,
232 node: &'arena Node<'arena, RefCell<Ast>>,
233 ) -> io::Result<()> {
234 Ok(())
235 }
236
237 fn visit_description_term<'arena>(
239 &mut self,
240 node: &'arena Node<'arena, RefCell<Ast>>,
241 ) -> io::Result<()> {
242 Ok(())
243 }
244
245 fn visit_description_details<'arena>(
247 &mut self,
248 node: &'arena Node<'arena, RefCell<Ast>>,
249 ) -> io::Result<()> {
250 Ok(())
251 }
252
253 fn visit_document<'arena>(
255 &mut self,
256 node: &'arena Node<'arena, RefCell<Ast>>,
257 ) -> io::Result<()> {
258 Ok(())
259 }
260
261 fn visit_escaped<'arena>(
263 &mut self,
264 node: &'arena Node<'arena, RefCell<Ast>>,
265 ) -> io::Result<()> {
266 Ok(())
267 }
268
269 fn visit_escaped_tag<'arena>(
271 &mut self,
272 node: &'arena Node<'arena, RefCell<Ast>>,
273 tag: &String,
274 ) -> io::Result<()> {
275 Ok(())
276 }
277
278 fn visit_emph<'arena>(&mut self, node: &'arena Node<'arena, RefCell<Ast>>) -> io::Result<()> {
280 Ok(())
281 }
282
283 fn visit_footnote_definition<'arena>(
285 &mut self,
286 node: &'arena Node<'arena, RefCell<Ast>>,
287 footnote_definition: &NodeFootnoteDefinition,
288 ) -> io::Result<()> {
289 Ok(())
290 }
291
292 fn visit_footnote_reference<'arena>(
294 &mut self,
295 node: &'arena Node<'arena, RefCell<Ast>>,
296 footnote_reference: &NodeFootnoteReference,
297 ) -> io::Result<()> {
298 Ok(())
299 }
300
301 fn visit_front_matter<'arena>(
303 &mut self,
304 node: &'arena Node<'arena, RefCell<Ast>>,
305 frontmatter: &String,
306 ) -> io::Result<()> {
307 Ok(())
308 }
309
310 fn visit_heading<'arena>(
312 &mut self,
313 node: &'arena Node<'arena, RefCell<Ast>>,
314 heading: &NodeHeading,
315 ) -> io::Result<()> {
316 Ok(())
317 }
318
319 fn visit_html_block<'arena>(
321 &mut self,
322 node: &'arena Node<'arena, RefCell<Ast>>,
323 html_block: &NodeHtmlBlock,
324 ) -> io::Result<()> {
325 Ok(())
326 }
327
328 fn visit_html_inline<'arena>(
330 &mut self,
331 node: &'arena Node<'arena, RefCell<Ast>>,
332 inline: &String,
333 ) -> io::Result<()> {
334 Ok(())
335 }
336
337 fn visit_image<'arena>(
339 &mut self,
340 node: &'arena Node<'arena, RefCell<Ast>>,
341 link: &NodeLink,
342 ) -> io::Result<()> {
343 Ok(())
344 }
345
346 fn visit_item<'arena>(
348 &mut self,
349 node: &'arena Node<'arena, RefCell<Ast>>,
350 list: &NodeList,
351 ) -> io::Result<()> {
352 Ok(())
353 }
354
355 fn visit_link<'arena>(
357 &mut self,
358 node: &'arena Node<'arena, RefCell<Ast>>,
359 link: &NodeLink,
360 ) -> io::Result<()> {
361 Ok(())
362 }
363
364 fn visit_line_break<'arena>(
366 &mut self,
367 node: &'arena Node<'arena, RefCell<Ast>>,
368 ) -> io::Result<()> {
369 Ok(())
370 }
371
372 fn visit_list<'arena>(
374 &mut self,
375 node: &'arena Node<'arena, RefCell<Ast>>,
376 list: &NodeList,
377 ) -> io::Result<()> {
378 Ok(())
379 }
380
381 fn visit_math<'arena>(
383 &mut self,
384 node: &'arena Node<'arena, RefCell<Ast>>,
385 math: &NodeMath,
386 ) -> io::Result<()> {
387 Ok(())
388 }
389
390 fn visit_multiline_block_quote<'arena>(
392 &mut self,
393 node: &'arena Node<'arena, RefCell<Ast>>,
394 multiline_block_quote: &NodeMultilineBlockQuote,
395 ) -> io::Result<()> {
396 Ok(())
397 }
398
399 fn visit_paragraph<'arena>(
401 &mut self,
402 node: &'arena Node<'arena, RefCell<Ast>>,
403 ) -> io::Result<()> {
404 Ok(())
405 }
406
407 fn visit_raw<'arena>(
409 &mut self,
410 node: &'arena Node<'arena, RefCell<Ast>>,
411 raw: &String,
412 ) -> io::Result<()> {
413 Ok(())
414 }
415
416 fn visit_short_code<'arena>(
418 &mut self,
419 node: &'arena Node<'arena, RefCell<Ast>>,
420 short_code: &NodeShortCode,
421 ) -> io::Result<()> {
422 Ok(())
423 }
424
425 fn visit_soft_break<'arena>(
427 &mut self,
428 node: &'arena Node<'arena, RefCell<Ast>>,
429 ) -> io::Result<()> {
430 Ok(())
431 }
432
433 fn visit_spoilered_text<'arena>(
435 &mut self,
436 node: &'arena Node<'arena, RefCell<Ast>>,
437 ) -> io::Result<()> {
438 Ok(())
439 }
440
441 fn visit_strong<'arena>(&mut self, node: &'arena Node<'arena, RefCell<Ast>>) -> io::Result<()> {
443 Ok(())
444 }
445
446 fn visit_strikethrough<'arena>(
448 &mut self,
449 node: &'arena Node<'arena, RefCell<Ast>>,
450 ) -> io::Result<()> {
451 Ok(())
452 }
453
454 fn visit_subscript<'arena>(
456 &mut self,
457 node: &'arena Node<'arena, RefCell<Ast>>,
458 ) -> io::Result<()> {
459 Ok(())
460 }
461
462 fn visit_superscript<'arena>(
464 &mut self,
465 node: &'arena Node<'arena, RefCell<Ast>>,
466 ) -> io::Result<()> {
467 Ok(())
468 }
469
470 fn visit_table<'arena>(
472 &mut self,
473 node: &'arena Node<'arena, RefCell<Ast>>,
474 table: &NodeTable,
475 ) -> io::Result<()> {
476 Ok(())
477 }
478
479 fn visit_table_cell<'arena>(
481 &mut self,
482 node: &'arena Node<'arena, RefCell<Ast>>,
483 ) -> io::Result<()> {
484 Ok(())
485 }
486
487 fn visit_table_row<'arena>(
489 &mut self,
490 node: &'arena Node<'arena, RefCell<Ast>>,
491 table_row: &bool,
492 ) -> io::Result<()> {
493 Ok(())
494 }
495
496 fn visit_task_item<'arena>(
498 &mut self,
499 node: &'arena Node<'arena, RefCell<Ast>>,
500 task_item: &Option<char>,
501 ) -> io::Result<()> {
502 Ok(())
503 }
504
505 fn visit_text<'arena>(
507 &mut self,
508 node: &'arena Node<'arena, RefCell<Ast>>,
509 text: &String,
510 ) -> io::Result<()> {
511 Ok(())
512 }
513
514 fn visit_thematic_break<'arena>(
516 &mut self,
517 node: &'arena Node<'arena, RefCell<Ast>>,
518 ) -> io::Result<()> {
519 Ok(())
520 }
521
522 fn visit_underline<'arena>(
524 &mut self,
525 node: &'arena Node<'arena, RefCell<Ast>>,
526 ) -> io::Result<()> {
527 Ok(())
528 }
529
530 fn visit_wiki_link<'arena>(
532 &mut self,
533 node: &'arena Node<'arena, RefCell<Ast>>,
534 wiki_link: &NodeWikiLink,
535 ) -> io::Result<()> {
536 Ok(())
537 }
538}