mod escape;
pub mod html;
pub mod mdx;
use dmc_parser::ast::{Document, Node};
pub use html::{HtmlEmitter, render_html};
pub use mdx::{MdxBodyEmitter, render_mdx_body};
pub trait NodeSink {
fn enter(&mut self, node: &Node, ctx: &WalkCtx);
fn leave(&mut self, _node: &Node, _ctx: &WalkCtx) {}
}
pub struct WalkCtx<'a> {
pub depth: usize,
pub index: usize,
pub parent: Option<&'a Node>,
}
impl<'a> WalkCtx<'a> {
pub fn root() -> Self {
Self { depth: 0, index: 0, parent: None }
}
pub fn child(&self, parent: &'a Node, index: usize) -> Self {
Self { depth: self.depth + 1, index, parent: Some(parent) }
}
}
pub struct Walker<'a> {
doc: &'a Document,
}
impl<'a> Walker<'a> {
pub fn new(doc: &'a Document) -> Self {
Self { doc }
}
pub fn walk(self, sinks: &mut [&mut dyn NodeSink]) {
for (i, child) in self.doc.children.iter().enumerate() {
Self::walk_node(child, &WalkCtx { depth: 0, index: i, parent: None }, sinks);
}
}
fn walk_node(node: &'a Node, ctx: &WalkCtx<'a>, sinks: &mut [&mut dyn NodeSink]) {
for sink in sinks.iter_mut() {
sink.enter(node, ctx);
}
match node {
Node::Table(t) => {
for row in &t.children {
for cell in &row.cells {
for (i, kid) in cell.children.iter().enumerate() {
Self::walk_node(kid, &ctx.child(node, i), sinks);
}
}
}
},
_ => {
for (i, kid) in Node::children_of(node).iter().enumerate() {
Self::walk_node(kid, &ctx.child(node, i), sinks);
}
},
}
for sink in sinks.iter_mut().rev() {
sink.leave(node, ctx);
}
}
}