From 80844f24221c99484589019bacc26b1afc837167 Mon Sep 17 00:00:00 2001 From: Vadim Anufriev Date: Tue, 28 May 2024 19:49:38 +0400 Subject: [PATCH 1/5] add minijinja for templating example --- contrib/dyn_templates/README.md | 6 +- examples/templating/Cargo.toml | 2 +- examples/templating/src/main.rs | 17 +++++- examples/templating/src/minijinja.rs | 61 +++++++++++++++++++ examples/templating/src/tests.rs | 9 +++ .../templates/minijinja/error/404.html.j2 | 11 ++++ .../templates/minijinja/footer.html.j2 | 3 + .../templates/minijinja/index.html.j2 | 17 ++++++ .../templates/minijinja/layout.html.j2 | 11 ++++ .../templates/minijinja/nav.html.j2 | 1 + 10 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 examples/templating/src/minijinja.rs create mode 100644 examples/templating/templates/minijinja/error/404.html.j2 create mode 100644 examples/templating/templates/minijinja/footer.html.j2 create mode 100644 examples/templating/templates/minijinja/index.html.j2 create mode 100644 examples/templating/templates/minijinja/layout.html.j2 create mode 100644 examples/templating/templates/minijinja/nav.html.j2 diff --git a/contrib/dyn_templates/README.md b/contrib/dyn_templates/README.md index 317ce0e69e..29143724a9 100644 --- a/contrib/dyn_templates/README.md +++ b/contrib/dyn_templates/README.md @@ -9,11 +9,11 @@ This crate adds support for dynamic template rendering to Rocket. It automatically discovers templates, provides a `Responder` to render templates, -and automatically reloads templates when compiled in debug mode. At present, it -supports [Handlebars] and [Tera]. +and automatically reloads templates when compiled in debug mode. It supports [Handlebars], [Tera] and [MiniJinja]. [Tera]: https://docs.rs/crate/tera/1 [Handlebars]: https://docs.rs/crate/handlebars/5 +[MiniJinja]: https://docs.rs/crate/minijinja/2.0.1 # Usage @@ -23,7 +23,7 @@ supports [Handlebars] and [Tera]. ```toml [dependencies.rocket_dyn_templates] version = "0.1.0" - features = ["handlebars", "tera"] + features = ["handlebars", "tera", "minijinja"] ``` 1. Write your template files in Handlebars (`.hbs`) and/or Tera (`.tera`) in diff --git a/examples/templating/Cargo.toml b/examples/templating/Cargo.toml index 1fcee3c365..e2379c2a45 100644 --- a/examples/templating/Cargo.toml +++ b/examples/templating/Cargo.toml @@ -11,4 +11,4 @@ rocket = { path = "../../core/lib" } # in your application, you should enable only the template engine(s) used [dependencies.rocket_dyn_templates] path = "../../contrib/dyn_templates" -features = ["tera", "handlebars"] +features = ["tera", "handlebars", "minijinja"] diff --git a/examples/templating/src/main.rs b/examples/templating/src/main.rs index e849f427b7..4cc605dc19 100644 --- a/examples/templating/src/main.rs +++ b/examples/templating/src/main.rs @@ -1,16 +1,21 @@ -#[macro_use] extern crate rocket; +#[macro_use] +extern crate rocket; mod hbs; +mod minijinja; mod tera; -#[cfg(test)] mod tests; +#[cfg(test)] +mod tests; use rocket::response::content::RawHtml; use rocket_dyn_templates::Template; #[get("/")] fn index() -> RawHtml<&'static str> { - RawHtml(r#"See Tera or Handlebars."#) + RawHtml( + r#"See Tera, Handlebars, or MiniJinja."#, + ) } #[launch] @@ -19,10 +24,16 @@ fn rocket() -> _ { .mount("/", routes![index]) .mount("/tera", routes![tera::index, tera::hello, tera::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("/tera", catchers![tera::not_found]) + .register("/minijinja", catchers![minijinja::not_found]) .attach(Template::custom(|engines| { hbs::customize(&mut engines.handlebars); tera::customize(&mut engines.tera); + minijinja::customize(&mut engines.minijinja); })) } diff --git a/examples/templating/src/minijinja.rs b/examples/templating/src/minijinja.rs new file mode 100644 index 0000000000..3efaf9ac25 --- /dev/null +++ b/examples/templating/src/minijinja.rs @@ -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/")] +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 %} +
+

About - Here's another page!

+
+ {% endblock %} + "#, + ) + .expect("valid Jinja2 template"); +} diff --git a/examples/templating/src/tests.rs b/examples/templating/src/tests.rs index afdbc0450c..0df792e7cd 100644 --- a/examples/templating/src/tests.rs +++ b/examples/templating/src/tests.rs @@ -66,6 +66,7 @@ fn test_index() { let response = client.get("/").dispatch().into_string().unwrap(); assert!(response.contains("Tera")); assert!(response.contains("Handlebars")); + assert!(response.contains("MiniJinja")); } #[test] @@ -83,3 +84,11 @@ fn tera() { test_404("tera"); test_about("tera"); } + +#[test] +fn minijinja() { + test_root("minijinja"); + test_name("minijinja"); + // test_404("minijinja"); // FIXME: in progress + test_about("minijinja"); +} \ No newline at end of file diff --git a/examples/templating/templates/minijinja/error/404.html.j2 b/examples/templating/templates/minijinja/error/404.html.j2 new file mode 100644 index 0000000000..b04eb553f7 --- /dev/null +++ b/examples/templating/templates/minijinja/error/404.html.j2 @@ -0,0 +1,11 @@ + + + + + 404 - minijinja + + +

404: Hey! There's nothing here.

+ The page at {{ uri }} does not exist! + + diff --git a/examples/templating/templates/minijinja/footer.html.j2 b/examples/templating/templates/minijinja/footer.html.j2 new file mode 100644 index 0000000000..98266dbe77 --- /dev/null +++ b/examples/templating/templates/minijinja/footer.html.j2 @@ -0,0 +1,3 @@ + diff --git a/examples/templating/templates/minijinja/index.html.j2 b/examples/templating/templates/minijinja/index.html.j2 new file mode 100644 index 0000000000..55b6ba7ea0 --- /dev/null +++ b/examples/templating/templates/minijinja/index.html.j2 @@ -0,0 +1,17 @@ +{% extends "minijinja/layout" %} + +{% block page %} +
+

Hi {{ name }}!

+

Here are your items:

+
    + {% for item in items %} +
  • {{ item }}
  • + {% endfor %} +
+
+ +
+

Try going to /minijinja/hello/Your Name.

+
+{% endblock %} diff --git a/examples/templating/templates/minijinja/layout.html.j2 b/examples/templating/templates/minijinja/layout.html.j2 new file mode 100644 index 0000000000..b3c2ff844b --- /dev/null +++ b/examples/templating/templates/minijinja/layout.html.j2 @@ -0,0 +1,11 @@ + + + + Rocket Example - {{ title }} + + + {% include "minijinja/nav" %} + {% block page %}{% endblock %} + {% include "minijinja/footer" %} + + diff --git a/examples/templating/templates/minijinja/nav.html.j2 b/examples/templating/templates/minijinja/nav.html.j2 new file mode 100644 index 0000000000..67dcde4348 --- /dev/null +++ b/examples/templating/templates/minijinja/nav.html.j2 @@ -0,0 +1 @@ +Hello | About From a3c2bce4620c6275760c9a032b35d9e1b12ad550 Mon Sep 17 00:00:00 2001 From: Vadim Anufriev Date: Tue, 28 May 2024 20:34:55 +0400 Subject: [PATCH 2/5] fix tests --- examples/templating/src/tests.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/templating/src/tests.rs b/examples/templating/src/tests.rs index 0df792e7cd..e4caa030fd 100644 --- a/examples/templating/src/tests.rs +++ b/examples/templating/src/tests.rs @@ -40,17 +40,20 @@ fn test_404(base: &str) { let client = Client::tracked(rocket()).unwrap(); for bad_path in &["/hello", "/foo/bar", "/404"] { let path = format!("/{}{}", base, bad_path); - let escaped_path = RawStr::new(&path).html_escape(); + + let escaped_path_upper = RawStr::new(&path).html_escape(); + let escaped_path_lower = escaped_path_upper.to_lowercase(); let response = client.get(&path).dispatch(); assert_eq!(response.status(), Status::NotFound); let response = response.into_string().unwrap(); - assert!(response.contains(base)); - assert! { - response.contains(&format!("{} does not exist", path)) - || response.contains(&format!("{} does not exist", escaped_path)) - }; + assert!(response.contains(base)); + assert!( + response.contains(&format!("{} does not exist", path)) || + response.contains(&format!("{} does not exist", escaped_path_upper)) || + response.contains(&format!("{} does not exist", escaped_path_lower)) + ); } } @@ -89,6 +92,6 @@ fn tera() { fn minijinja() { test_root("minijinja"); test_name("minijinja"); - // test_404("minijinja"); // FIXME: in progress + test_404("minijinja"); test_about("minijinja"); } \ No newline at end of file From 24269ca9d37f7faf1b458ac532250f81f53364ee Mon Sep 17 00:00:00 2001 From: Vadim Anufriev Date: Thu, 30 May 2024 11:47:25 +0400 Subject: [PATCH 3/5] fix tests and whitespaces --- examples/templating/src/main.rs | 4 +++- examples/templating/src/minijinja.rs | 2 +- examples/templating/src/tests.rs | 17 +++++++---------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/examples/templating/src/main.rs b/examples/templating/src/main.rs index 4cc605dc19..4eae318192 100644 --- a/examples/templating/src/main.rs +++ b/examples/templating/src/main.rs @@ -14,7 +14,9 @@ use rocket_dyn_templates::Template; #[get("/")] fn index() -> RawHtml<&'static str> { RawHtml( - r#"See Tera, Handlebars, or MiniJinja."#, + r#"See Tera, + Handlebars, + or MiniJinja."#, ) } diff --git a/examples/templating/src/minijinja.rs b/examples/templating/src/minijinja.rs index 3efaf9ac25..799a1a9c50 100644 --- a/examples/templating/src/minijinja.rs +++ b/examples/templating/src/minijinja.rs @@ -35,7 +35,7 @@ pub fn about() -> Template { #[catch(404)] pub fn not_found(req: &Request<'_>) -> Template { println!("Handling 404 for URI: {}", req.uri()); - + Template::render( "minijinja/error/404", context! { diff --git a/examples/templating/src/tests.rs b/examples/templating/src/tests.rs index e4caa030fd..449840386c 100644 --- a/examples/templating/src/tests.rs +++ b/examples/templating/src/tests.rs @@ -40,20 +40,17 @@ fn test_404(base: &str) { let client = Client::tracked(rocket()).unwrap(); for bad_path in &["/hello", "/foo/bar", "/404"] { let path = format!("/{}{}", base, bad_path); - - let escaped_path_upper = RawStr::new(&path).html_escape(); - let escaped_path_lower = escaped_path_upper.to_lowercase(); + let escaped_path = RawStr::new(&path).html_escape().to_lowercase(); let response = client.get(&path).dispatch(); 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(&format!("{} does not exist", path)) || - response.contains(&format!("{} does not exist", escaped_path_upper)) || - response.contains(&format!("{} does not exist", escaped_path_lower)) - ); + assert!(response.contains(base)); + assert! { + response.contains(&format!("{} does not exist", path)) + || response.contains(&format!("{} does not exist", escaped_path)) + }; } } From 75a424dbb144d0664d910ae519fb091f3b9694ac Mon Sep 17 00:00:00 2001 From: Vadim Anufriev Date: Fri, 31 May 2024 11:16:40 +0400 Subject: [PATCH 4/5] update docs --- docs/guide/06-responses.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/06-responses.md b/docs/guide/06-responses.md index 9343b5964e..f5cb7e1971 100644 --- a/docs/guide/06-responses.md +++ b/docs/guide/06-responses.md @@ -354,7 +354,7 @@ are: * [`Flash`] - Sets a "flash" cookie that is removed when accessed. * [`Json`] - Automatically serializes values into JSON. * [`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/ [`content`]: @api/master/rocket/response/content/ @@ -589,7 +589,7 @@ reloading is disabled. The [`Template`] API documentation contains more information about templates, 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. [configurable]: ../configuration/ From a120f971781e2e9b8d5b8204871ae016d96267fa Mon Sep 17 00:00:00 2001 From: Matthew Pomes Date: Wed, 26 Jun 2024 00:56:59 -0500 Subject: [PATCH 5/5] Fix capitalization --- docs/guide/06-responses.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/06-responses.md b/docs/guide/06-responses.md index f5cb7e1971..31a10d323c 100644 --- a/docs/guide/06-responses.md +++ b/docs/guide/06-responses.md @@ -354,7 +354,7 @@ are: * [`Flash`] - Sets a "flash" cookie that is removed when accessed. * [`Json`] - Automatically serializes values into JSON. * [`MsgPack`] - Automatically serializes values into MessagePack. - * [`Template`] - Renders a dynamic template using handlebars, Tera or MiniJinja. + * [`Template`] - Renders a dynamic template using Handlebars, Tera or MiniJinja. [`status`]: @api/master/rocket/response/status/ [`content`]: @api/master/rocket/response/content/