Skip to main content

dmc_transform/builtin/
assign_heading_ids.rs

1//! Heading id assignment. See `transformers/assign-heading-ids.md` for
2//! full docs.
3
4use crate::pipeline::Transformer;
5use dmc_diagnostic::Code;
6use dmc_diagnostic::metadata::SourceMeta;
7use dmc_parser::Slugger;
8use dmc_parser::ast::*;
9
10#[derive(Default, Debug)]
11pub struct AssignHeadingIds;
12
13impl AssignHeadingIds {
14  pub fn new() -> Self {
15    Self
16  }
17}
18
19impl Transformer for AssignHeadingIds {
20  fn name(&self) -> &str {
21    "assign-heading-ids"
22  }
23
24  fn transform(
25    &self,
26    doc: &mut Document,
27    _meta: &SourceMeta,
28    _diag_engine: &mut duck_diagnostic::DiagnosticEngine<Code>,
29  ) {
30    let mut slugger = Slugger::new();
31    walk(&mut doc.children, &mut slugger);
32  }
33}
34
35fn walk(nodes: &mut [Node], slugger: &mut Slugger) {
36  for node in nodes {
37    if let Node::Heading(h) = node {
38      if h.id.is_none() {
39        let text = Heading::plain_text(&h.children);
40        h.id = Some(slugger.slug(&text));
41      }
42      // Headings can't contain other headings; no need to recurse.
43      continue;
44    }
45    if let Some(children) = Node::children_of_mut(node) {
46      walk(children, slugger);
47    }
48  }
49}