From 8c6e47ac738a9fc5e7105ba18390ee2a2280ddf2 Mon Sep 17 00:00:00 2001 From: ReeseHatfield Date: Wed, 16 Sep 2026 08:14:20 -0400 Subject: [PATCH 01/10] pull in templater from attend --- src/static/templater.rs | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/static/templater.rs diff --git a/src/static/templater.rs b/src/static/templater.rs new file mode 100644 index 0000000..e99ed97 --- /dev/null +++ b/src/static/templater.rs @@ -0,0 +1,58 @@ +use derive_more::Deref; +use std::collections::HashMap; +use std::error::Error; + +/// HTML String, new-type wrapper +#[derive(Debug, Deref)] +pub struct Html(pub String); + +// going to need this in the binary eventually anyway +const FRONTEND_TEMPLATE: &str = include_str!("../templates/index.html"); + +/// Loads the embedded HTML template as the HTML new-type +/// +/// # Returns +/// +/// - `Result>` - HTML string wrapper, propogating error value. +/// +pub fn load_template() -> Result> { + // let mut buf: String = String::new(); + + // let mut file = File::open(path)?; + // let contents = file.read_to_string(&mut buf)?; + + // Ok(HTML(contents.to_string())) + + Ok(Html(FRONTEND_TEMPLATE.to_string())) +} + +/// Renders a given template with its paramaters swapped out +/// +/// # Arguments +/// +/// - `html` (`HTML`) - An HTML string containing template keys. +/// These keys should having two curly braces and a space around them. Something like: +/// ```html +///

Record your attendance for {{ DATE }}

s +/// ``` +/// - `map` (`HashMap`) - Map of template keys to template values. So something like +/// ```html +///

Record your attendance for {{ DATE }}

+/// ``` +/// with the map record of <"DATE", "10-05-2026"> would render was +/// ```html +///

Record your attendance for 10-05-2026

+/// ``` +/// # Returns +/// +/// - `HTML` - HTML with all templates filled out +/// +pub fn render_template(html: Html, map: HashMap) -> Html { + let mut update_me = html.clone(); + map.iter().for_each(|(key, value)| { + // { is escaped with {, so to replace {{ key }} you need {{{{ {key} }}}} + update_me = update_me.replace(&format!("{{{{ {key} }}}}"), value); + }); + + Html(update_me) +} From 419c0c15a971df17f76fa5e13bb67d29f1b7e1a7 Mon Sep 17 00:00:00 2001 From: ReeseHatfield Date: Wed, 16 Sep 2026 10:42:00 -0400 Subject: [PATCH 02/10] update to use Template --- Cargo.lock | 54 ++++++++++++++++++ Cargo.toml | 1 + src/cmd/init.rs | 44 +++++++------- src/lib.rs | 3 +- .../html-templates/.gitignore | 0 .../html-templates/custom.css | 0 .../html-templates/favicon.png | Bin .../html-templates/ferris.png | Bin .../html-templates/index.html | 0 .../html-templates/main.js | 0 .../html-templates/slides.html | 0 .../html-templates/vite.config.js | 0 .../md-templates/.gitignore | 0 .../md-templates/custom.css | 0 .../md-templates/favicon.png | Bin .../md-templates/ferris.png | Bin .../md-templates/index.html | 0 .../md-templates/main.js | 0 .../md-templates/slides.md | 0 .../md-templates/vite.config.js | 0 src/templates/mod.rs | 2 + src/{ => templates}/template.rs | 2 +- src/{static => templates}/templater.rs | 35 +++++------- 23 files changed, 95 insertions(+), 46 deletions(-) rename src/{static => templates}/html-templates/.gitignore (100%) rename src/{static => templates}/html-templates/custom.css (100%) rename src/{static => templates}/html-templates/favicon.png (100%) rename src/{static => templates}/html-templates/ferris.png (100%) rename src/{static => templates}/html-templates/index.html (100%) rename src/{static => templates}/html-templates/main.js (100%) rename src/{static => templates}/html-templates/slides.html (100%) rename src/{static => templates}/html-templates/vite.config.js (100%) rename src/{static => templates}/md-templates/.gitignore (100%) rename src/{static => templates}/md-templates/custom.css (100%) rename src/{static => templates}/md-templates/favicon.png (100%) rename src/{static => templates}/md-templates/ferris.png (100%) rename src/{static => templates}/md-templates/index.html (100%) rename src/{static => templates}/md-templates/main.js (100%) rename src/{static => templates}/md-templates/slides.md (100%) rename src/{static => templates}/md-templates/vite.config.js (100%) create mode 100644 src/templates/mod.rs rename src/{ => templates}/template.rs (91%) rename src/{static => templates}/templater.rs (52%) diff --git a/Cargo.lock b/Cargo.lock index e74b78e..c5991a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,6 +236,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -287,6 +296,29 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.101", + "unicode-xid", +] + [[package]] name = "dirs" version = "6.0.0" @@ -1083,6 +1115,7 @@ dependencies = [ "clap", "clap-markdown", "ctrlc", + "derive_more", "dirs", "inquire", "open", @@ -1263,6 +1296,15 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.0.7" @@ -1359,6 +1401,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.219" @@ -1797,6 +1845,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 6992872..484ecce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ chrono = { version = "0.4.41", features = ["serde"] } clap = { version = "4.5.38", features = ["derive"] } clap-markdown = "0.1.5" ctrlc = "3.4.7" +derive_more = { version = "2.1.1", features = ["full"] } dirs = "6.0.0" inquire = "0.7.5" open = "5.3.3" diff --git a/src/cmd/init.rs b/src/cmd/init.rs index 7fc6ec0..36bc9a7 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -9,7 +9,7 @@ use clap::Args; use spinners::{Spinner, Spinners}; use strum::IntoEnumIterator; -use crate::{config, template::Template}; +use crate::{config, templates::template::CLITemplate}; /// Options for the `oseda init` command #[derive(Args, Debug)] @@ -42,24 +42,24 @@ pub struct InitOptions { } // embed all the static markdown template files into binary -const MD_VITE_CONFIG_JS: &str = include_str!("../static/md-templates/vite.config.js"); -const MD_INDEX_HTML: &str = include_str!("../static/md-templates/index.html"); -const MD_MAIN_JS: &str = include_str!("../static/md-templates/main.js"); -const MD_SLIDES: &str = include_str!("../static/md-templates/slides.md"); -const MD_CUSTOM_CSS: &str = include_str!("../static/md-templates/custom.css"); -const MD_FERRIS: &[u8] = include_bytes!("../static/md-templates/ferris.png"); -const MD_GITIGNORE: &str = include_str!("../static/md-templates/.gitignore"); -const MD_FAVICON: &[u8] = include_bytes!("../static/md-templates/favicon.png"); +const MD_VITE_CONFIG_JS: &str = include_str!("../templates/md-templates/vite.config.js"); +const MD_INDEX_HTML: &str = include_str!("../templates/md-templates/index.html"); +const MD_MAIN_JS: &str = include_str!("../templates/md-templates/main.js"); +const MD_SLIDES: &str = include_str!("../templates/md-templates/slides.md"); +const MD_CUSTOM_CSS: &str = include_str!("../templates/md-templates/custom.css"); +const MD_FERRIS: &[u8] = include_bytes!("../templates/md-templates/ferris.png"); +const MD_GITIGNORE: &str = include_str!("../templates/md-templates/.gitignore"); +const MD_FAVICON: &[u8] = include_bytes!("../templates/md-templates/favicon.png"); // do the same with the html templates -const HTML_VITE_CONFIG_JS: &str = include_str!("../static/html-templates/vite.config.js"); -const HTML_INDEX_HTML: &str = include_str!("../static/html-templates/index.html"); -const HTML_MAIN_JS: &str = include_str!("../static/html-templates/main.js"); -const HTML_SLIDES: &str = include_str!("../static/html-templates/slides.html"); -const HTML_CUSTOM_CSS: &str = include_str!("../static/html-templates/custom.css"); -const HTML_FERRIS: &[u8] = include_bytes!("../static/html-templates/ferris.png"); -const HTML_GITIGNORE: &str = include_str!("../static/html-templates/.gitignore"); -const HTML_FAVICON: &[u8] = include_bytes!("../static/html-templates/favicon.png"); +const HTML_VITE_CONFIG_JS: &str = include_str!("../templates/html-templates/vite.config.js"); +const HTML_INDEX_HTML: &str = include_str!("../templates/html-templates/index.html"); +const HTML_MAIN_JS: &str = include_str!("../templates/html-templates/main.js"); +const HTML_SLIDES: &str = include_str!("../templates/html-templates/slides.html"); +const HTML_CUSTOM_CSS: &str = include_str!("../templates/html-templates/custom.css"); +const HTML_FERRIS: &[u8] = include_bytes!("../templates/html-templates/ferris.png"); +const HTML_GITIGNORE: &str = include_str!("../templates/html-templates/.gitignore"); +const HTML_FAVICON: &[u8] = include_bytes!("../templates/html-templates/favicon.png"); /// Initialize an Oseda project with the provided options /// @@ -77,7 +77,7 @@ const HTML_FAVICON: &[u8] = include_bytes!("../static/html-templates/favicon.png pub fn init(opts: InitOptions) -> Result<(), Box> { let template = match opts.template { Some(ref arg_template) => { - Template::from_str(arg_template).map_err(|_| "Invalid template".to_string())? + CLITemplate::from_str(arg_template).map_err(|_| "Invalid template".to_string())? } None => prompt_template()?, }; @@ -134,7 +134,7 @@ pub fn init(opts: InitOptions) -> Result<(), Box> { // 99% sure we'll only ever have to maintain these two template schemas match template { - Template::Markdown => { + CLITemplate::Markdown => { // fs::write(format!("{}/package.json", &conf.title), MD_PACKAGE_JSON)?; fs::write(format!("{}/vite.config.js", &conf.title), MD_VITE_CONFIG_JS)?; fs::write(format!("{}/index.html", &conf.title), MD_INDEX_HTML)?; @@ -153,7 +153,7 @@ pub fn init(opts: InitOptions) -> Result<(), Box> { fs::write(format!("{}/public/ferris.png", &conf.title), MD_FERRIS)?; fs::write(format!("{}/public/favicon.png", &conf.title), MD_FAVICON)?; } - Template::HTML => { + CLITemplate::HTML => { // fs::write(format!("{}/package.json", &conf.title), HTML_PACKAGE_JSON)?; fs::write( format!("{}/vite.config.js", &conf.title), @@ -180,8 +180,8 @@ pub fn init(opts: InitOptions) -> Result<(), Box> { Ok(()) } -fn prompt_template() -> Result> { - let template_opts: Vec