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