code: better Readme, implementing custom intializer

This commit is contained in:
Gabor Körber 2025-01-13 21:40:44 +01:00
parent 726a21b257
commit f821e2d7d7
5 changed files with 127 additions and 12 deletions

15
Cargo.lock generated
View File

@ -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]]

View File

@ -4,17 +4,35 @@
name = "loco-minijinja-engine"
version = "0.14.0"
edition = "2021"
# For releasing:
authors = ["Gabor Körber <gab@g4b.org>"]
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" }

View File

@ -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<Vec<Box<dyn Initializer>>> {
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<Vec<Box<dyn Initializer>>> {
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)

View File

@ -40,7 +40,10 @@ impl Hooks for App {
async fn initializers(_ctx: &AppContext) -> Result<Vec<Box<dyn Initializer>>> {
Ok(vec![Box::new(
loco_minijinja_engine::MinijinjaViewEngineInitializer,
loco_minijinja_engine::MinijinjaViewEngineConfigurableInitializer::new(
"assets/templates".to_string(),
None,
),
)])
}

View File

@ -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> {
Self::from_custom_dir(&TEMPLATES_DIR)
Self::from_custom(&TEMPLATES_DIR, None)
}
pub fn from_custom_dir<P: AsRef<Path>>(path: &P) -> Result<Self> {
pub fn from_custom<P: AsRef<Path>>(
path: &P,
custom_environment: Option<Environment<'static>>,
) -> Result<Self> {
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<Environment<'static>>,
}
#[async_trait]
impl Initializer for MinijinjaViewEngineConfigurableInitializer {
fn name(&self) -> String {
"minijinja".to_string()
}
async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
let custom_environment = self.custom_environment.clone(); // as this is a &self function, we have to clone here.
let jinja =
MinijinjaView::from_custom::<String>(&self.template_directory, custom_environment)?;
Ok(router.layer(Extension(ViewEngine::from(jinja))))
}
}
impl MinijinjaViewEngineConfigurableInitializer {
pub fn new(
template_directory: String,
custom_environment: Option<Environment<'static>>,
) -> Self {
MinijinjaViewEngineConfigurableInitializer {
template_directory: template_directory,
custom_environment: custom_environment,
}
}
}