dmc-parser 0.1.0

Typed AST parser for the dmc MDX compiler
Documentation
mod common;
use common::*;
use dmc_parser::ast::*;

#[test]
fn thematic_break_emits_node() {
  let d = parse_doc("---\n");
  // first child may be HorizontalRule or might be a Paragraph if first-line --- is consumed by lex_frontmatter
  // For `---` not at column 0 of file start, lexer emits ThematicBreak - but `---` IS at start.
  // It will try to be frontmatter; without closing --- it falls back to ThematicBreak (per lex_frontmatter logic).
  let has_hr = d.children.iter().any(|n| matches!(n, Node::HorizontalRule(_)));
  assert!(has_hr, "got {:?}", d.children);
}

#[test]
fn thematic_break_via_stars() {
  let d = parse_doc("***\n");
  let has_hr = d.children.iter().any(|n| matches!(n, Node::HorizontalRule(_)));
  assert!(has_hr, "got {:?}", d.children);
}

#[test]
fn thematic_break_via_underscores() {
  let d = parse_doc("___\n");
  let has_hr = d.children.iter().any(|n| matches!(n, Node::HorizontalRule(_)));
  assert!(has_hr, "got {:?}", d.children);
}

#[test]
fn blockquote_single_line() {
  let d = parse_doc("> quoted text\n");
  let bq = d
    .children
    .iter()
    .find_map(|n| match n {
      Node::Blockquote(b) => Some(b),
      _ => None,
    })
    .expect("bq");
  // its first child is a Paragraph; that paragraph contains text
  assert!(!bq.children.is_empty());
}

#[test]
fn blockquote_multi_line_collapses() {
  // CommonMark: consecutive `>` lines join into one paragraph with a
  // space between. Both lines must end up in the same paragraph.
  let d = parse_doc("> one\n> two\n");
  let bq = d
    .children
    .iter()
    .find_map(|n| match n {
      Node::Blockquote(b) => Some(b),
      _ => None,
    })
    .expect("bq");
  assert_eq!(bq.children.len(), 1, "expected 1 paragraph, got {}", bq.children.len());
  let para = match &bq.children[0] {
    Node::Paragraph(p) => p,
    _ => panic!("expected paragraph"),
  };
  let flat: String = para
    .children
    .iter()
    .filter_map(|n| match n {
      Node::Text(t) => Some(t.value.as_str()),
      _ => None,
    })
    .collect();
  assert!(flat.contains("one"));
  assert!(flat.contains("two"));
}