//! The bundled templates (DOC-01). use gpui::App; /// The three bundled templates (DOC-01). #[derive(Clone, Copy, Debug, PartialEq)] pub enum Template { Blank, Report, Letter, } pub const TEMPLATES: [Template; 3] = [Template::Blank, Template::Report, Template::Letter]; impl Template { pub fn key(self) -> &'static str { match self { Template::Blank => "blank", Template::Report => "report", Template::Letter => "letter", } } /// The paragraphs, as (heading level, text); 0 is body. fn lines(self, cx: &App) -> Vec<(u8, String)> { let text = |key: &str| ely_ui::i18n::text(cx, key, &[]).to_string(); match self { Template::Blank => vec![(0, String::new())], Template::Report => vec![ (9, text("doc.report.title")), (1, text("doc.report.summary")), (0, text("doc.body")), (1, text("doc.report.details")), (0, text("doc.body")), ], Template::Letter => vec![ (0, text("doc.letter.sender")), (0, text("doc.letter.date")), (0, String::new()), (0, text("doc.letter.recipient")), (0, String::new()), (0, text("doc.letter.greeting")), (0, text("doc.body")), (0, String::new()), (0, text("doc.letter.closing")), (0, text("doc.letter.sender")), ], } } /// Flat ODF text; level 9 is the Title style. pub fn fodt(self, cx: &App) -> String { let body: String = self .lines(cx) .into_iter() .map(|(level, text)| { let text = escape(&text); match level { 0 => format!("{text}"), 9 => format!("{text}"), level => format!("{text}"), } }) .collect(); format!( "\n{body}\n" ) } /// The template as the picker's markdown preview. pub fn preview(self, cx: &App) -> String { self.lines(cx) .into_iter() .map(|(level, text)| match level { 0 => text, 9 => format!("# {text}"), level => format!("{} {text}", "#".repeat(usize::from(level) + 1)), }) .collect::>() .join("\n\n") } } /// XML-escapes template text. fn escape(text: &str) -> String { text.replace('&', "&") .replace('<', "<") .replace('>', ">") } #[cfg(test)] mod tests { use super::*; #[test] fn template_text_is_escaped() { assert_eq!(escape("a"), "a<b & c>"); } }