diff --git a/examples/README.md b/examples/README.md index 14d9f124..0382ddb3 100644 --- a/examples/README.md +++ b/examples/README.md @@ -29,6 +29,7 @@ Here you can find a lot of small crabs 🦀. * [markup](templates/markup) * [tera](templates/tera) * [maud](templates/maud) + * [minijinja](templates/minijinja) * [Tracing aka logging](tracing) ## Usage diff --git a/examples/templates/minijinja/Cargo.toml b/examples/templates/minijinja/Cargo.toml new file mode 100644 index 00000000..7e9d07ef --- /dev/null +++ b/examples/templates/minijinja/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "template-minijinja" +version = "0.1.0" +edition.workspace = true +publish = false + +[dependencies] +viz.workspace = true + +serde.workspace = true +tokio = { workspace = true, features = [ "rt-multi-thread", "macros" ] } +minijinja = { version = "1", features = ["loader"] } +once_cell = "1.19" diff --git a/examples/templates/minijinja/src/main.rs b/examples/templates/minijinja/src/main.rs new file mode 100644 index 00000000..df72c376 --- /dev/null +++ b/examples/templates/minijinja/src/main.rs @@ -0,0 +1,68 @@ +#![deny(warnings)] +#![allow(clippy::unused_async)] + +use std::{net::SocketAddr, sync::Arc}; + +use minijinja::{context, path_loader, Environment}; +use once_cell::sync::Lazy; +use serde::Serialize; +use tokio::net::TcpListener; +use viz::{serve, BytesMut, Error, Request, Response, ResponseExt, Result, Router, Tree}; + +static MINIJINJA: Lazy = Lazy::new(|| { + let mut env = Environment::new(); + env.set_loader(path_loader("examples/templates/minijinja/templates")); + env +}); + +#[derive(Serialize)] +struct User<'a> { + url: &'a str, + username: &'a str, +} + +async fn index(_: Request) -> Result { + let mut buf = BytesMut::with_capacity(512); + buf.extend( + MINIJINJA + .get_template("index.html") + .map_err(Error::normal)? + .render(context! { + title => "Viz.rs", + users => &vec![ + User { + url: "https://github.com/rust-lang", + username: "rust-lang", + }, + User { + url: "https://github.com/viz-rs", + username: "viz-rs", + }, + ], + }) + .map_err(Error::normal)? + .as_bytes(), + ); + + Ok(Response::html(buf.freeze())) +} + +#[tokio::main] +async fn main() -> Result<()> { + let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); + let listener = TcpListener::bind(addr).await?; + println!("listening on http://{addr}"); + + let app = Router::new().get("/", index); + let tree = Arc::new(Tree::from(app)); + + loop { + let (stream, addr) = listener.accept().await?; + let tree = tree.clone(); + tokio::task::spawn(async move { + if let Err(err) = serve(stream, tree, Some(addr)).await { + eprintln!("Error while serving HTTP connection: {err}"); + } + }); + } +} diff --git a/examples/templates/minijinja/templates/index.html b/examples/templates/minijinja/templates/index.html new file mode 100644 index 00000000..afa290fa --- /dev/null +++ b/examples/templates/minijinja/templates/index.html @@ -0,0 +1,9 @@ +{% extends "layout.html" %} +{% block title %} Viz & MiniJinja {% endblock title %} +{% block body %} + +{% endblock %} diff --git a/examples/templates/minijinja/templates/layout.html b/examples/templates/minijinja/templates/layout.html new file mode 100644 index 00000000..c313cb8f --- /dev/null +++ b/examples/templates/minijinja/templates/layout.html @@ -0,0 +1,10 @@ + + + + {% block title %}{% endblock %} + + + + {% block body %}{% endblock %} + +