sql_splitter/graph/format/
mod.rs

1//! Output format implementations for ERD visualization.
2
3mod dot;
4mod html;
5mod json;
6mod mermaid;
7
8pub use dot::to_dot;
9pub use html::to_html;
10pub use json::to_json;
11pub use mermaid::to_mermaid;
12
13use std::fmt;
14use std::str::FromStr;
15
16/// Output format for ERD export
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
18pub enum OutputFormat {
19    /// Graphviz DOT format (ERD style)
20    #[default]
21    Dot,
22    /// Mermaid erDiagram format
23    Mermaid,
24    /// JSON format for programmatic use
25    Json,
26    /// Interactive HTML with toggleable dark mode
27    Html,
28}
29
30impl FromStr for OutputFormat {
31    type Err = String;
32
33    fn from_str(s: &str) -> Result<Self, Self::Err> {
34        match s.to_lowercase().as_str() {
35            "dot" | "graphviz" => Ok(OutputFormat::Dot),
36            "mermaid" | "mmd" => Ok(OutputFormat::Mermaid),
37            "json" => Ok(OutputFormat::Json),
38            "html" => Ok(OutputFormat::Html),
39            _ => Err(format!(
40                "Unknown format: {}. Valid options: dot, mermaid, json, html",
41                s
42            )),
43        }
44    }
45}
46
47impl fmt::Display for OutputFormat {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        match self {
50            OutputFormat::Dot => write!(f, "dot"),
51            OutputFormat::Mermaid => write!(f, "mermaid"),
52            OutputFormat::Json => write!(f, "json"),
53            OutputFormat::Html => write!(f, "html"),
54        }
55    }
56}
57
58impl OutputFormat {
59    /// Get file extension for this format
60    pub fn extension(&self) -> &'static str {
61        match self {
62            OutputFormat::Dot => "dot",
63            OutputFormat::Mermaid => "mmd",
64            OutputFormat::Json => "json",
65            OutputFormat::Html => "html",
66        }
67    }
68
69    /// Detect format from file extension
70    pub fn from_extension(ext: &str) -> Option<Self> {
71        match ext.to_lowercase().as_str() {
72            "dot" | "gv" => Some(OutputFormat::Dot),
73            "mmd" | "mermaid" => Some(OutputFormat::Mermaid),
74            "json" => Some(OutputFormat::Json),
75            "html" | "htm" => Some(OutputFormat::Html),
76            "png" | "svg" | "pdf" => Some(OutputFormat::Dot), // Will be rendered
77            _ => None,
78        }
79    }
80}
81
82/// Layout direction for diagram
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
84pub enum Layout {
85    /// Left to right
86    #[default]
87    LR,
88    /// Top to bottom
89    TB,
90}
91
92impl FromStr for Layout {
93    type Err = String;
94
95    fn from_str(s: &str) -> Result<Self, Self::Err> {
96        match s.to_lowercase().as_str() {
97            "lr" | "left-right" | "horizontal" => Ok(Layout::LR),
98            "tb" | "td" | "top-bottom" | "top-down" | "vertical" => Ok(Layout::TB),
99            _ => Err(format!("Unknown layout: {}. Valid options: lr, tb", s)),
100        }
101    }
102}
103
104impl fmt::Display for Layout {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        match self {
107            Layout::LR => write!(f, "lr"),
108            Layout::TB => write!(f, "tb"),
109        }
110    }
111}