1use 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum ExportFormat {
23 Docx,
25 Html,
27 Json,
29 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
60pub trait Exporter {
62 fn export(&self, adr: &Adr, path: &Path) -> Result<(), Error>;
68
69 fn export_all(&self, adrs: &[Adr], dir: &Path) -> Result<ExportResult, Error>;
75}
76
77#[derive(Debug, Default)]
79pub struct ExportResult {
80 pub exported: usize,
82 pub files: Vec<String>,
84 pub errors: Vec<String>,
86}
87
88pub 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 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}