1mod escape;
13pub mod html;
14pub mod mdx;
15use dmc_parser::ast::{Document, Node};
16pub use html::{HtmlEmitter, RenderOptions, render_html, render_html_with};
17pub use mdx::{MdxBodyEmitter, render_mdx_body};
18
19pub trait NodeSink {
21 fn enter(&mut self, node: &Node, ctx: &WalkCtx);
22 fn leave(&mut self, _node: &Node, _ctx: &WalkCtx) {}
23}
24
25pub struct WalkCtx<'a> {
27 pub depth: usize,
29 pub index: usize,
31 pub parent: Option<&'a Node>,
33}
34
35impl<'a> WalkCtx<'a> {
36 pub fn root() -> Self {
37 Self { depth: 0, index: 0, parent: None }
38 }
39 pub fn child(&self, parent: &'a Node, index: usize) -> Self {
40 Self { depth: self.depth + 1, index, parent: Some(parent) }
41 }
42}
43
44pub struct Walker<'a> {
53 doc: &'a Document,
54}
55
56impl<'a> Walker<'a> {
57 pub fn new(doc: &'a Document) -> Self {
58 Self { doc }
59 }
60
61 pub fn walk(self, sinks: &mut [&mut dyn NodeSink]) {
63 for (i, child) in self.doc.children.iter().enumerate() {
64 Self::walk_node(child, &WalkCtx { depth: 0, index: i, parent: None }, sinks);
65 }
66 }
67
68 fn walk_node(node: &'a Node, ctx: &WalkCtx<'a>, sinks: &mut [&mut dyn NodeSink]) {
69 for sink in sinks.iter_mut() {
70 sink.enter(node, ctx);
71 }
72 match node {
73 Node::Table(t) => {
75 for row in &t.children {
76 for cell in &row.cells {
77 for (i, kid) in cell.children.iter().enumerate() {
78 Self::walk_node(kid, &ctx.child(node, i), sinks);
79 }
80 }
81 }
82 },
83 _ => {
84 for (i, kid) in Node::children_of(node).iter().enumerate() {
85 Self::walk_node(kid, &ctx.child(node, i), sinks);
86 }
87 },
88 }
89 for sink in sinks.iter_mut().rev() {
90 sink.leave(node, ctx);
91 }
92 }
93}