From f821e2d7d770f0ec218c2357b6ab615d50b97d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabor=20K=C3=B6rber?= Date: Mon, 13 Jan 2025 21:40:44 +0100 Subject: [PATCH] code: better Readme, implementing custom intializer --- Cargo.lock | 15 +++++++++ Cargo.toml | 18 ++++++++++ README.md | 46 ++++++++++++++++++++++++++ examples/usage_example/src/app.rs | 5 ++- src/lib.rs | 55 ++++++++++++++++++++++++------- 5 files changed, 127 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac76a95..5aaa306 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1589,6 +1589,8 @@ dependencies = [ "minijinja", "minijinja-autoreload", "serde", + "serde_json", + "tracing-subscriber", ] [[package]] @@ -3024,6 +3026,16 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.19" @@ -3034,12 +3046,15 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9b290e5..06a29f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,17 +4,35 @@ name = "loco-minijinja-engine" version = "0.14.0" edition = "2021" +# For releasing: +authors = ["Gabor Körber "] +description = "Initializers to use Minijinja Templating Engine in Loco.rs" +repository = "https://github.com/g4borg/loco_minijinja_engine" +homepage = "https://github.com/g4borg/loco_minijinja_engine" +# documentation = "https://docs.rs/my_library" +keywords = ["loco", "loco.rs", "minijinja"] +categories = ["convenience", "bindings"] +# license = "MIT OR Apache-2.0" +readme = "README.md" + [features] +# default = ["autoreloader"] autoreloader = ["dep:minijinja-autoreload"] [workspace.dependencies] loco-rs = { version = "0.14.0", default-features = false } + [dependencies] async-trait = "0.1" axum = "0.8" loco-rs = { workspace = true } +tracing-subscriber = { version = "0.3", features = [ + "env-filter", + "json", +] } # required by loco-rs to build correctly minijinja = { version = "2.6", features = ["loader"] } minijinja-autoreload = { version = "2.6", optional = true } serde = "1.0" +serde_json = { version = "1" } diff --git a/README.md b/README.md index b5eb612..0759902 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,49 @@ # Minijinja Engine for Loco.rs This crate allows you to integrate [Minijinja](https://github.com/mitsuhiko/minijinja) as Template renderer into [Loco.rs](https://github.com/loco-rs/loco) + +## Usage + +### Use autoreloader + +The `autoreloader` feature automatically uses the `minijinja-autoreloader` instead of a single environment. + +Just set in your Cargo.toml: + +```toml +loco-minijinja-engine = { features = ["autoreloader"] } +``` + +### Default Settings + +If you want the standard initializer, so access `"assets/templates"` as your template directory, and a standard minijinja renderer as it comes out of the box, just use in your `app.rs`: + +```rust +... + + async fn initializers(_ctx: &AppContext) -> Result>> { + Ok(vec![Box::new(loco_minijinja_engine::MinijinjaViewEngineInitializer)]) + } + +... +``` + +### Custom Environment or Template Directory + +If you want a different directory for your templates, e.g. stay with `"assets/views"` like the Tera setup in loco, use the custom initializer in your `app.rs`: + +```rust +... + + async fn initializers(_ctx: &AppContext) -> Result>> { + let environment = Environment::new(); + Ok(vec![Box::new( + loco_minijinja_engine::MinijinjaViewEngineConfigurableInitializer::new( + "assets/views".to_string(), + Some(environment), + ), + )]) + } +``` + +(Note, that because of the trait layout, I cannot prevent two clones and 'static for the custom Environment, so if you need anything more dynamic, feel free to copypaste the initializer, and initialize the Environment in the closure) diff --git a/examples/usage_example/src/app.rs b/examples/usage_example/src/app.rs index 6713554..99e0127 100644 --- a/examples/usage_example/src/app.rs +++ b/examples/usage_example/src/app.rs @@ -40,7 +40,10 @@ impl Hooks for App { async fn initializers(_ctx: &AppContext) -> Result>> { Ok(vec![Box::new( - loco_minijinja_engine::MinijinjaViewEngineInitializer, + loco_minijinja_engine::MinijinjaViewEngineConfigurableInitializer::new( + "assets/templates".to_string(), + None, + ), )]) } diff --git a/src/lib.rs b/src/lib.rs index 837aa53..d73b056 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ use loco_rs::{ errors::Error, Result, }; -use minijinja::{filters::default, path_loader, Environment}; +use minijinja::{path_loader, Environment}; #[cfg(feature = "autoreloader")] use minijinja_autoreload::AutoReloader; use serde::Serialize; @@ -28,10 +28,13 @@ pub struct MinijinjaView<'a> { impl MinijinjaView<'_> { pub fn build() -> Result { - Self::from_custom_dir(&TEMPLATES_DIR) + Self::from_custom(&TEMPLATES_DIR, None) } - pub fn from_custom_dir>(path: &P) -> Result { + pub fn from_custom>( + path: &P, + custom_environment: Option>, + ) -> Result { if !path.as_ref().exists() { return Err(Error::string(&format!( "missing templates directory: `{}`", @@ -43,20 +46,19 @@ impl MinijinjaView<'_> { #[cfg(feature = "autoreloader")] let reloader = AutoReloader::new(move |notifier| { - let mut environment = Environment::new(); + let cust_env = custom_environment.clone(); + let mut env = cust_env.unwrap_or_else(Environment::new); let template_path = template_path.clone(); - - environment.set_loader(path_loader(&template_path)); - + env.set_loader(path_loader(&template_path)); notifier.watch_path(template_path, true); - Ok(environment) + Ok(env) }); #[cfg(not(feature = "autoreloader"))] let environment = { - let mut environment = Environment::new(); - environment.set_loader(path_loader(&template_path)); - environment + let mut env = custom_environment.unwrap_or_else(Environment::new); + env.set_loader(path_loader(&template_path)); + env }; Ok(Self { @@ -126,3 +128,34 @@ impl Initializer for MinijinjaViewEngineInitializer { Ok(router.layer(Extension(ViewEngine::from(jinja)))) } } + +pub struct MinijinjaViewEngineConfigurableInitializer { + template_directory: String, + custom_environment: Option>, +} + +#[async_trait] +impl Initializer for MinijinjaViewEngineConfigurableInitializer { + fn name(&self) -> String { + "minijinja".to_string() + } + + async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result { + let custom_environment = self.custom_environment.clone(); // as this is a &self function, we have to clone here. + let jinja = + MinijinjaView::from_custom::(&self.template_directory, custom_environment)?; + Ok(router.layer(Extension(ViewEngine::from(jinja)))) + } +} + +impl MinijinjaViewEngineConfigurableInitializer { + pub fn new( + template_directory: String, + custom_environment: Option>, + ) -> Self { + MinijinjaViewEngineConfigurableInitializer { + template_directory: template_directory, + custom_environment: custom_environment, + } + } +}