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,
30 pub parent: Option<&'a Node>,
32}
33
34impl<'a> WalkCtx<'a> {
35 pub fn root() -> Self {
36 Self { depth: 0, index: 0, parent: None }
37 }
38 pub fn child(&self, parent: &'a Node, index: usize) -> Self {
39 Self { depth: self.depth + 1, index, parent: Some(parent) }
40 }
41}
42
43pub struct Walker<'a> {
48 doc: &'a Document,
49}
50
51impl<'a> Walker<'a> {
52 pub fn new(doc: &'a Document) -> Self {
53 Self { doc }
54 }
55
56 pub fn walk(self, sinks: &mut [&mut dyn NodeSink]) {
57 for (i, child) in self.doc.children.iter().enumerate() {
58 Self::walk_node(child, &WalkCtx { depth: 0, index: i, parent: None }, sinks);
59 }
60 }
61
62 fn walk_node(node: &'a Node, ctx: &WalkCtx<'a>, sinks: &mut [&mut dyn NodeSink]) {
63 for sink in sinks.iter_mut() {
64 sink.enter(node, ctx);
65 }
66 match node {
67 Node::Table(t) => {
69 for row in &t.children {
70 for cell in &row.cells {
71 for (i, kid) in cell.children.iter().enumerate() {
72 Self::walk_node(kid, &ctx.child(node, i), sinks);
73 }
74 }
75 }
76 },
77 _ => {
78 for (i, kid) in Node::children_of(node).iter().enumerate() {
79 Self::walk_node(kid, &ctx.child(node, i), sinks);
80 }
81 },
82 }
83 for sink in sinks.iter_mut().rev() {
84 sink.leave(node, ctx);
85 }
86 }
87}