pub mod ast;
pub mod class;
pub mod error;
pub mod flowchart;
pub mod sequence;
pub mod state;
pub(crate) mod theme_hint;
pub use ast::*;
pub use error::*;
pub use flowchart::{
Flowchart, ParseOptions, parse_flowchart, parse_flowchart_with_options, strip_frontmatter,
};
pub(crate) use theme_hint::{extract_theme_hint, strip_theme_only_compat_syntax};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DiagramType {
Flowchart,
Class,
Sequence,
State,
}
#[must_use]
pub fn detect_diagram_type(input: &str) -> Option<DiagramType> {
let input = strip_frontmatter(input);
let first_word = input
.lines()
.map(|line| line.trim())
.find(|line| !line.is_empty() && !line.starts_with("%%"))
.and_then(|line| line.split_whitespace().next())?;
match first_word.to_ascii_lowercase().as_str() {
"graph" | "flowchart" => Some(DiagramType::Flowchart),
"classdiagram" => Some(DiagramType::Class),
"sequencediagram" => Some(DiagramType::Sequence),
"statediagram-v2" | "statediagram" => Some(DiagramType::State),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::{DiagramType, detect_diagram_type};
#[test]
fn detects_mermaid_logical_types() {
assert_eq!(
detect_diagram_type("graph TD\nA-->B\n"),
Some(DiagramType::Flowchart)
);
assert_eq!(
detect_diagram_type("classDiagram\nclass User"),
Some(DiagramType::Class)
);
assert_eq!(
detect_diagram_type("sequenceDiagram\nparticipant A"),
Some(DiagramType::Sequence)
);
assert_eq!(
detect_diagram_type("stateDiagram-v2\n[*] --> Idle"),
Some(DiagramType::State)
);
assert_eq!(
detect_diagram_type("stateDiagram\n[*] --> Idle"),
Some(DiagramType::State)
);
}
}