git_adr/export/
mod.rs

1//! Export functionality for git-adr.
2//!
3//! This module provides export capabilities:
4//! - DOCX export
5//! - HTML export
6//! - JSON export
7
8use crate::core::Adr;
9use crate::Error;
10use std::path::Path;
11
12mod docx;
13mod html;
14mod json;
15
16pub use self::docx::DocxExporter;
17pub use self::html::HtmlExporter;
18pub use self::json::JsonExporter;
19
20/// Export format.
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum ExportFormat {
23    /// DOCX (Microsoft Word) format.
24    Docx,
25    /// HTML format.
26    Html,
27    /// JSON format.
28    Json,
29    /// Markdown format.
30    Markdown,
31}
32
33impl std::fmt::Display for ExportFormat {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        match self {
36            Self::Docx => write!(f, "docx"),
37            Self::Html => write!(f, "html"),
38            Self::Json => write!(f, "json"),
39            Self::Markdown => write!(f, "markdown"),
40        }
41    }
42}
43
44impl std::str::FromStr for ExportFormat {
45    type Err = Error;
46
47    fn from_str(s: &str) -> Result<Self, Self::Err> {
48        match s.to_lowercase().as_str() {
49            "docx" | "word" => Ok(Self::Docx),
50            "html" => Ok(Self::Html),
51            "json" => Ok(Self::Json),
52            "markdown" | "md" => Ok(Self::Markdown),
53            _ => Err(Error::InvalidFormat {
54                format: s.to_string(),
55            }),
56        }
57    }
58}
59
60/// Exporter trait for different formats.
61pub trait Exporter {
62    /// Export a single ADR to the given path.
63    ///
64    /// # Errors
65    ///
66    /// Returns an error if export fails.
67    fn export(&self, adr: &Adr, path: &Path) -> Result<(), Error>;
68
69    /// Export multiple ADRs to a directory.
70    ///
71    /// # Errors
72    ///
73    /// Returns an error if export fails.
74    fn export_all(&self, adrs: &[Adr], dir: &Path) -> Result<ExportResult, Error>;
75}
76
77/// Result of an export operation.
78#[derive(Debug, Default)]
79pub struct ExportResult {
80    /// Number of files exported.
81    pub exported: usize,
82    /// Paths to exported files.
83    pub files: Vec<String>,
84    /// Errors encountered.
85    pub errors: Vec<String>,
86}
87
88/// Export ADRs to the specified format.
89///
90/// # Errors
91///
92/// Returns an error if export fails.
93pub fn export_adrs(adrs: &[Adr], dir: &Path, format: ExportFormat) -> Result<ExportResult, Error> {
94    match format {
95        ExportFormat::Docx => DocxExporter::new().export_all(adrs, dir),
96        ExportFormat::Html => HtmlExporter::new().export_all(adrs, dir),
97        ExportFormat::Json => JsonExporter::new().export_all(adrs, dir),
98        ExportFormat::Markdown => {
99            // Markdown export is just copying the original content
100            let mut result = ExportResult::default();
101            for adr in adrs {
102                let path = dir.join(format!("{}.md", adr.id));
103                let content = adr.to_markdown()?;
104                std::fs::write(&path, content).map_err(|e| Error::IoError {
105                    message: format!("Failed to write {}: {e}", path.display()),
106                })?;
107                result.exported += 1;
108                result.files.push(path.display().to_string());
109            }
110            Ok(result)
111        },
112    }
113}