Add MiniJinja for templating example (#2799)

Update guide to mention MiniJinja.
Adds MiniJinja to the templating example.
This commit is contained in:
Vadim Anufriev 2024-06-26 10:27:44 +04:00 committed by GitHub
parent 6857b82ec4
commit fb4b630405
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 137 additions and 11 deletions

View File

@ -9,11 +9,11 @@
This crate adds support for dynamic template rendering to Rocket. It This crate adds support for dynamic template rendering to Rocket. It
automatically discovers templates, provides a `Responder` to render templates, automatically discovers templates, provides a `Responder` to render templates,
and automatically reloads templates when compiled in debug mode. At present, it and automatically reloads templates when compiled in debug mode. It supports [Handlebars], [Tera] and [MiniJinja].
supports [Handlebars] and [Tera].
[Tera]: https://docs.rs/crate/tera/1 [Tera]: https://docs.rs/crate/tera/1
[Handlebars]: https://docs.rs/crate/handlebars/5 [Handlebars]: https://docs.rs/crate/handlebars/5
[MiniJinja]: https://docs.rs/crate/minijinja/2.0.1
# Usage # Usage
@ -23,7 +23,7 @@ supports [Handlebars] and [Tera].
```toml ```toml
[dependencies.rocket_dyn_templates] [dependencies.rocket_dyn_templates]
version = "0.1.0" version = "0.1.0"
features = ["handlebars", "tera"] features = ["handlebars", "tera", "minijinja"]
``` ```
1. Write your template files in Handlebars (`.hbs`) and/or Tera (`.tera`) in 1. Write your template files in Handlebars (`.hbs`) and/or Tera (`.tera`) in

View File

@ -354,7 +354,7 @@ are:
* [`Flash`] - Sets a "flash" cookie that is removed when accessed. * [`Flash`] - Sets a "flash" cookie that is removed when accessed.
* [`Json`] - Automatically serializes values into JSON. * [`Json`] - Automatically serializes values into JSON.
* [`MsgPack`] - Automatically serializes values into MessagePack. * [`MsgPack`] - Automatically serializes values into MessagePack.
* [`Template`] - Renders a dynamic template using handlebars or Tera. * [`Template`] - Renders a dynamic template using Handlebars, Tera or MiniJinja.
[`status`]: @api/master/rocket/response/status/ [`status`]: @api/master/rocket/response/status/
[`content`]: @api/master/rocket/response/content/ [`content`]: @api/master/rocket/response/content/
@ -589,7 +589,7 @@ reloading is disabled.
The [`Template`] API documentation contains more information about templates, The [`Template`] API documentation contains more information about templates,
including how to customize a template engine to add custom helpers and filters. including how to customize a template engine to add custom helpers and filters.
The [templating example](@git/master/examples/templating) uses both Tera and Handlebars The [templating example](@git/master/examples/templating) uses Tera, Handlebars and MiniJinja
templating to implement the same application. templating to implement the same application.
[configurable]: ../configuration/ [configurable]: ../configuration/

View File

@ -11,4 +11,4 @@ rocket = { path = "../../core/lib" }
# in your application, you should enable only the template engine(s) used # in your application, you should enable only the template engine(s) used
[dependencies.rocket_dyn_templates] [dependencies.rocket_dyn_templates]
path = "../../contrib/dyn_templates" path = "../../contrib/dyn_templates"
features = ["tera", "handlebars"] features = ["tera", "handlebars", "minijinja"]

View File

@ -1,16 +1,23 @@
#[macro_use] extern crate rocket; #[macro_use]
extern crate rocket;
mod hbs; mod hbs;
mod minijinja;
mod tera; mod tera;
#[cfg(test)] mod tests; #[cfg(test)]
mod tests;
use rocket::response::content::RawHtml; use rocket::response::content::RawHtml;
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
#[get("/")] #[get("/")]
fn index() -> RawHtml<&'static str> { fn index() -> RawHtml<&'static str> {
RawHtml(r#"See <a href="tera">Tera</a> or <a href="hbs">Handlebars</a>."#) RawHtml(
r#"See <a href="tera">Tera</a>,
<a href="hbs">Handlebars</a>,
or <a href="minijinja">MiniJinja</a>."#,
)
} }
#[launch] #[launch]
@ -19,10 +26,16 @@ fn rocket() -> _ {
.mount("/", routes![index]) .mount("/", routes![index])
.mount("/tera", routes![tera::index, tera::hello, tera::about]) .mount("/tera", routes![tera::index, tera::hello, tera::about])
.mount("/hbs", routes![hbs::index, hbs::hello, hbs::about]) .mount("/hbs", routes![hbs::index, hbs::hello, hbs::about])
.mount(
"/minijinja",
routes![minijinja::index, minijinja::hello, minijinja::about],
)
.register("/hbs", catchers![hbs::not_found]) .register("/hbs", catchers![hbs::not_found])
.register("/tera", catchers![tera::not_found]) .register("/tera", catchers![tera::not_found])
.register("/minijinja", catchers![minijinja::not_found])
.attach(Template::custom(|engines| { .attach(Template::custom(|engines| {
hbs::customize(&mut engines.handlebars); hbs::customize(&mut engines.handlebars);
tera::customize(&mut engines.tera); tera::customize(&mut engines.tera);
minijinja::customize(&mut engines.minijinja);
})) }))
} }

View File

@ -0,0 +1,61 @@
use rocket::response::Redirect;
use rocket::Request;
use rocket_dyn_templates::{context, minijinja::Environment, Template};
// use self::minijinja::;
#[get("/")]
pub fn index() -> Redirect {
Redirect::to(uri!("/minijinja", hello(name = "Your Name")))
}
#[get("/hello/<name>")]
pub fn hello(name: &str) -> Template {
Template::render(
"minijinja/index",
context! {
title: "Hello",
name: Some(name),
items: vec!["One", "Two", "Three"],
},
)
}
#[get("/about")]
pub fn about() -> Template {
Template::render(
"minijinja/about.html",
context! {
title: "About",
},
)
}
#[catch(404)]
pub fn not_found(req: &Request<'_>) -> Template {
println!("Handling 404 for URI: {}", req.uri());
Template::render(
"minijinja/error/404",
context! {
uri: req.uri()
},
)
}
pub fn customize(env: &mut Environment) {
env.add_template(
"minijinja/about.html",
r#"
{% extends "minijinja/layout" %}
{% block page %}
<section id="about">
<h1>About - Here's another page!</h1>
</section>
{% endblock %}
"#,
)
.expect("valid Jinja2 template");
}

View File

@ -40,11 +40,11 @@ fn test_404(base: &str) {
let client = Client::tracked(rocket()).unwrap(); let client = Client::tracked(rocket()).unwrap();
for bad_path in &["/hello", "/foo/bar", "/404"] { for bad_path in &["/hello", "/foo/bar", "/404"] {
let path = format!("/{}{}", base, bad_path); let path = format!("/{}{}", base, bad_path);
let escaped_path = RawStr::new(&path).html_escape(); let escaped_path = RawStr::new(&path).html_escape().to_lowercase();
let response = client.get(&path).dispatch(); let response = client.get(&path).dispatch();
assert_eq!(response.status(), Status::NotFound); assert_eq!(response.status(), Status::NotFound);
let response = response.into_string().unwrap(); let response = response.into_string().unwrap().to_lowercase();
assert!(response.contains(base)); assert!(response.contains(base));
assert! { assert! {
@ -66,6 +66,7 @@ fn test_index() {
let response = client.get("/").dispatch().into_string().unwrap(); let response = client.get("/").dispatch().into_string().unwrap();
assert!(response.contains("Tera")); assert!(response.contains("Tera"));
assert!(response.contains("Handlebars")); assert!(response.contains("Handlebars"));
assert!(response.contains("MiniJinja"));
} }
#[test] #[test]
@ -83,3 +84,11 @@ fn tera() {
test_404("tera"); test_404("tera");
test_about("tera"); test_about("tera");
} }
#[test]
fn minijinja() {
test_root("minijinja");
test_name("minijinja");
test_404("minijinja");
test_about("minijinja");
}

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>404 - minijinja</title>
</head>
<body>
<h1>404: Hey! There's nothing here.</h1>
The page at {{ uri }} does not exist!
</body>
</html>

View File

@ -0,0 +1,3 @@
<footer>
<a href="/">Home</a>
</footer>

View File

@ -0,0 +1,17 @@
{% extends "minijinja/layout" %}
{% block page %}
<section id="hello">
<h1>Hi {{ name }}!</h1>
<h3>Here are your items:</h3>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</section>
<section id="custom-helper">
<p>Try going to <a href="/minijinja/hello/Your%20Name">/minijinja/hello/Your Name</a>.</p>
</section>
{% endblock %}

View File

@ -0,0 +1,11 @@
<!doctype html>
<html>
<head>
<title>Rocket Example - {{ title }}</title>
</head>
<body>
{% include "minijinja/nav" %}
{% block page %}{% endblock %}
{% include "minijinja/footer" %}
</body>
</html>

View File

@ -0,0 +1 @@
<a href="/minijinja/hello/Unknown">Hello</a> | <a href="/minijinja/about">About</a>