ratatui-markdown 0.2.0

Markdown rendering, collapsible JSON/TOML trees, and rich scroll widgets for ratatui
Documentation
mod layout;
mod parser;
mod render;
mod types;

pub use types::{Direction, EdgeType, MermaidDiagram, MermaidEdge, MermaidNode, NodeShape};

use ratatui::text::Line;
use crate::theme::RichTextTheme;

pub fn render_mermaid(
    source: &str,
    max_width: usize,
    max_height: Option<usize>,
    theme: &impl RichTextTheme,
) -> Option<Vec<Line<'static>>> {
    let diagram = parser::parse(source).ok()?;
    let direction = diagram.direction.clone();
    let layout = layout::compute_layout(&diagram, max_width, max_height);
    let lines = render::render_layout(&layout, &direction, theme);
    Some(lines)
}

#[cfg(test)]
mod tests {
    use super::*;
    use anyhow::Context as _;

    #[test]
    fn test_parse_simple_flowchart() -> anyhow::Result<()> {
        let diagram = parser::parse("graph TD\nA[Start] --> B[End]")
            .map_err(|e| anyhow::anyhow!("{e}"))?;
        assert_eq!(diagram.nodes.len(), 2, "expected 2 nodes, got {:?}", diagram.nodes);
        assert_eq!(diagram.edges.len(), 1, "expected 1 edge, got {:?}", diagram.edges);
        assert_eq!(diagram.direction, Direction::TopDown);
        Ok(())
    }

    #[test]
    fn test_parse_with_labels() -> anyhow::Result<()> {
        let diagram = parser::parse("graph TD\nA -->|yes| B")
            .map_err(|e| anyhow::anyhow!("{e}"))?;
        assert_eq!(diagram.nodes.len(), 2);
        assert_eq!(diagram.edges[0].label.as_deref(), Some("yes"));
        Ok(())
    }

    #[test]
    fn test_parse_lr_direction() -> anyhow::Result<()> {
        let diagram = parser::parse("graph LR\nA --> B")
            .map_err(|e| anyhow::anyhow!("{e}"))?;
        assert_eq!(diagram.direction, Direction::LeftRight);
        Ok(())
    }
}