From 25186136bc61490e69df8092065e31b454c4b682 Mon Sep 17 00:00:00 2001 From: postscriptum Date: Fri, 4 Jul 2025 15:23:35 +0300 Subject: [PATCH] reorganize template format members --- src/nex.rs | 14 ++--- src/nex/format.rs | 111 ------------------------------------- src/nex/template.rs | 74 +++++++++++++++++++++++++ src/nex/template/format.rs | 23 ++++++++ 4 files changed, 104 insertions(+), 118 deletions(-) delete mode 100644 src/nex/format.rs create mode 100644 src/nex/template.rs create mode 100644 src/nex/template/format.rs diff --git a/src/nex.rs b/src/nex.rs index 38ef32f..95ec25b 100644 --- a/src/nex.rs +++ b/src/nex.rs @@ -1,12 +1,11 @@ mod attachment; -mod format; pub mod response; pub mod source; +mod template; use anyhow::{Result, bail}; use attachment::Attachment; use chrono::{DateTime, Utc}; -use format::Format; use response::{Clean, Sync, change::Change}; use source::Source; use std::{ @@ -15,13 +14,14 @@ use std::{ path::PathBuf, str::FromStr, }; +use template::Template; pub struct Nex { attachment: Attachment, filename: String, - format: Format, is_cleanup: bool, is_debug: bool, + template: Template, users: HashMap, } @@ -48,13 +48,13 @@ impl Nex { fs::create_dir_all(&p)?; users.insert(u.clone(), p); } - // init document format - let format = Format::init(&filename, pattern, time_format); + // init document template formatter + let template = Template::init(&filename, pattern, time_format); Ok(Self { attachment: Attachment::init(attachment_mode)?, filename, - format, + template, is_cleanup, is_debug, users, @@ -154,7 +154,7 @@ impl Nex { }; fs::write( &f, - self.format.to_string( + self.template.build( updated, content, link, diff --git a/src/nex/format.rs b/src/nex/format.rs deleted file mode 100644 index e21c731..0000000 --- a/src/nex/format.rs +++ /dev/null @@ -1,111 +0,0 @@ -use chrono::{DateTime, Utc}; - -pub enum Format { - /// Format as [Gemtext](https://geminiprotocol.net/docs/gemtext.gmi) - /// * detected in case, when the `format_filename` option has `.gmi` or `.gemtext` suffix in pattern - Gemtext { - pattern: String, - time_format: String, - }, - /// It is useful to enable clickable links - /// * detected in case, when the `format_filename` option has trailing slash in pattern - /// * the server should support appending a trailing slash in this case - Dir { - pattern: String, - time_format: String, - }, - /// Ignore markdown - Plain { - pattern: String, - time_format: String, - }, -} - -impl Format { - pub fn init(filename: &str, pattern: String, time_format: String) -> Self { - if filename.ends_with('/') { - Format::Dir { - pattern, - time_format, - } - } else if filename.ends_with(".gmi") | filename.ends_with(".gemtext") { - Format::Gemtext { - pattern, - time_format, - } - } else { - Format::Plain { - pattern, - time_format, - } - } - } - - pub fn to_string( - &self, - updated: Option>, - content: String, - link: String, - tags: Option>, - attachments: Option)>>, - ) -> String { - match self { - // implement separated templates @TODO - Self::Dir { - pattern, - time_format, - } - | Self::Gemtext { - pattern, - time_format, - } - | Self::Plain { - pattern, - time_format, - } => pattern - .replace( - "{content}", - &if pattern.contains("{tags}") { - content.replace("#", "") - } else { - content - }, - ) - .replace( - "{attachments}", - &attachments - .map(|a| { - let mut b = Vec::with_capacity(a.len()); - b.push("\n".to_string()); - for (link, alt) in a { - let mut t = Vec::with_capacity(2); - t.push(if matches!(self, Self::Dir { .. }) { - format!("=> ../{link}") - } else { - format!("=> {link}") - }); - if let Some(text) = alt { - t.push(text) - } - b.push(t.join(" ")) - } - b.join("\n") - }) - .unwrap_or_default(), - ) - .replace( - "{tags}", - &tags - .map(|t| format!("\n\n{}", t.join(", "))) - .unwrap_or_default(), - ) - .replace("{link}", &format!("\n\n=> {link}")) - .replace( - "{updated}", - &updated - .map(|t| format!("\n\n✏ {}", t.format(time_format))) - .unwrap_or_default(), - ), - } - } -} diff --git a/src/nex/template.rs b/src/nex/template.rs new file mode 100644 index 0000000..4343afd --- /dev/null +++ b/src/nex/template.rs @@ -0,0 +1,74 @@ +mod format; + +use chrono::{DateTime, Utc}; +use format::Format; + +pub struct Template { + format: Format, + pattern: String, + time_format: String, +} + +impl Template { + pub fn init(filename: &str, pattern: String, time_format: String) -> Self { + Self { + format: Format::init(filename), + pattern, + time_format, + } + } + pub fn build( + &self, + updated: Option>, + content: String, + link: String, + tags: Option>, + attachments: Option)>>, + ) -> String { + // implement separated templates @TODO + self.pattern + .replace( + "{content}", + &if self.pattern.contains("{tags}") { + content.replace("#", "") + } else { + content + }, + ) + .replace( + "{attachments}", + &attachments + .map(|a| { + let mut b = Vec::with_capacity(a.len()); + b.push("\n".to_string()); + for (link, alt) in a { + let mut t = Vec::with_capacity(2); + t.push(if matches!(self.format, Format::Dir) { + format!("=> ../{link}") + } else { + format!("=> {link}") + }); + if let Some(text) = alt { + t.push(text) + } + b.push(t.join(" ")) + } + b.join("\n") + }) + .unwrap_or_default(), + ) + .replace( + "{tags}", + &tags + .map(|t| format!("\n\n{}", t.join(", "))) + .unwrap_or_default(), + ) + .replace("{link}", &format!("\n\n=> {link}")) + .replace( + "{updated}", + &updated + .map(|t| format!("\n\n✏ {}", t.format(&self.time_format))) + .unwrap_or_default(), + ) + } +} diff --git a/src/nex/template/format.rs b/src/nex/template/format.rs new file mode 100644 index 0000000..006a8d0 --- /dev/null +++ b/src/nex/template/format.rs @@ -0,0 +1,23 @@ +pub enum Format { + /// [Gemtext](https://geminiprotocol.net/docs/gemtext.gmi) + /// * detected in case, when the `format_filename` option has `.gmi` or `.gemtext` suffix in pattern + Gemtext, + /// Enables clickable links + /// * detected in case, when the `format_filename` option has trailing slash in pattern + /// * the server should support appending a trailing slash in this case + Dir, + /// Ignore markdown + Plain, +} + +impl Format { + pub fn init(filename: &str) -> Self { + if filename.ends_with('/') { + Self::Dir + } else if filename.ends_with(".gmi") | filename.ends_with(".gemtext") { + Self::Gemtext + } else { + Self::Plain + } + } +}