rocket_dyn_templates_community/
lib.rs

1//! Dynamic templating engine support for Rocket.
2//!
3//! This crate adds support for dynamic template rendering to Rocket. It
4//! automatically discovers templates, provides a `Responder` to render
5//! templates, and automatically reloads templates when compiled in debug mode.
6//! At present, it supports [Handlebars] and [Tera].
7//!
8//! # Usage
9//!
10//!   1. Depend on `rocket_dyn_templates`. Enable the feature(s) corresponding
11//!      to your templating engine(s) of choice:
12//!
13//!      ```toml
14//!      [dependencies.rocket_dyn_templates]
15//!      package = "rocket_dyn_templates-community"
16//!      version = "0.3.2"
17//!      features = ["handlebars", "tera", "minijinja"]
18//!      ```
19//!
20//!   2. Write your templates inside of the [configurable]
21//!      `${ROCKET_ROOT}/templates`. The filename _must_ end with an extension
22//!      corresponding to an enabled engine. The second-to-last extension should
23//!      correspond to the file's type:
24//!
25//!      | Engine       | Extension | Example                                    |
26//!      |--------------|-----------|--------------------------------------------|
27//!      | [Tera]       | `.tera`   | `${ROCKET_ROOT}/templates/index.html.tera` |
28//!      | [Handlebars] | `.hbs`    | `${ROCKET_ROOT}/templates/index.html.hbs`  |
29//!      | [MiniJinja]  | `.j2`     | `${ROCKET_ROOT}/templates/index.html.j2`   |
30//!
31//!      [configurable]: #configuration
32//!      [Tera]: https://docs.rs/crate/tera/1
33//!      [Handlebars]: https://docs.rs/crate/handlebars/6
34//!      [MiniJinja]: https://docs.rs/minijinja/2
35//!
36//!   3. Attach `Template::fairing()` and return a [`Template`] from your routes
37//!      via [`Template::render()`], supplying the name of the template file
38//!      **minus the last two extensions**:
39//!
40//!      ```rust
41//!      # #[macro_use] extern crate rocket;
42//!      # extern crate rocket_dyn_templates_community as rocket_dyn_templates;
43//!      use rocket_dyn_templates::{Template, context};
44//!
45//!      #[get("/")]
46//!      fn index() -> Template {
47//!          Template::render("index", context! { field: "value" })
48//!      }
49//!
50//!      #[launch]
51//!      fn rocket() -> _ {
52//!          rocket::build().attach(Template::fairing())
53//!      }
54//!      ```
55//!
56//! ## Configuration
57//!
58//! This crate reads one configuration parameter from the configured figment:
59//!
60//!   * `template_dir` (**default: `templates/`**)
61//!
62//!     A path to a directory to search for template files in. Relative paths
63//!     are considered relative to the configuration file, or there is no file,
64//!     the current working directory.
65//!
66//! For example, to change the default and set `template_dir` to different
67//! values based on whether the application was compiled for debug or release
68//! from a `Rocket.toml` file (read by the default figment), you might write:
69//!
70//! ```toml
71//! [debug]
72//! template_dir = "static/templates"
73//!
74//! [release]
75//! template_dir = "/var/opt/www/templates"
76//! ```
77//!
78//! **Note:** `template_dir` defaults to `templates/`. It _does not_ need to be
79//! specified if the default suffices.
80//!
81//! See the [configuration chapter] of the guide for more information on
82//! configuration.
83//!
84//! [configuration chapter]: https://rocket.rs/master/guide/configuration
85//!
86//! ## Template Naming and Content-Types
87//!
88//! Templates are rendered by _name_ via [`Template::render()`], which returns a
89//! [`Template`] responder. The _name_ of the template is the path to the
90//! template file, relative to `template_dir`, minus at most two extensions.
91//!
92//! The `Content-Type` of the response is automatically determined by the
93//! non-engine extension using [`ContentType::from_extension()`]. If there is no
94//! such extension or it is unknown, `text/plain` is used.
95//!
96//! The following table contains examples:
97//!
98//! | template path                                 | [`Template::render()`] call       | content-type |
99//! |-----------------------------------------------|-----------------------------------|--------------|
100//! | {template_dir}/index.html.hbs                 | `render("index")`                 | HTML         |
101//! | {template_dir}/index.tera                     | `render("index")`                 | `text/plain` |
102//! | {template_dir}/index.hbs                      | `render("index")`                 | `text/plain` |
103//! | {template_dir}/dir/index.hbs                  | `render("dir/index")`             | `text/plain` |
104//! | {template_dir}/dir/data.json.tera             | `render("dir/data")`              | JSON         |
105//! | {template_dir}/data.template.xml.hbs          | `render("data.template")`         | XML          |
106//! | {template_dir}/subdir/index.template.html.hbs | `render("subdir/index.template")` | HTML         |
107//!
108//! The recommended naming scheme is to use two extensions: one for the file
109//! type, and one for the template extension. This means that template
110//! extensions should look like: `.html.hbs`, `.html.tera`, `.xml.hbs`, and so
111//! on.
112//!
113//! [`ContentType::from_extension()`]: ../rocket/http/struct.ContentType.html#method.from_extension
114//!
115//! ### Rendering Context
116//!
117//! In addition to a name, [`Template::render()`] requires a context to use
118//! during rendering. The context can be any [`Serialize`] type that serializes
119//! to an `Object` (a dictionary) value. The [`context!`] macro can be used to
120//! create inline `Serialize`-able context objects.
121//!
122//! [`Serialize`]: rocket::serde::Serialize
123//!
124//! ```rust
125//! # #[macro_use] extern crate rocket;
126//! # extern crate rocket_dyn_templates_community as rocket_dyn_templates;
127//! use rocket::serde::Serialize;
128//! use rocket_dyn_templates::{Template, context};
129//!
130//! #[get("/")]
131//! fn index() -> Template {
132//!     // Using the `context! { }` macro.
133//!     Template::render("index", context! {
134//!         site_name: "Rocket - Home Page",
135//!         version: 127,
136//!     })
137//! }
138//!
139//! #[get("/")]
140//! fn index2() -> Template {
141//!     #[derive(Serialize)]
142//!     #[serde(crate = "rocket::serde")]
143//!     struct IndexContext {
144//!         site_name: &'static str,
145//!         version: u8
146//!     }
147//!
148//!     // Using an existing `IndexContext`, which implements `Serialize`.
149//!     Template::render("index", IndexContext {
150//!         site_name: "Rocket - Home Page",
151//!         version: 127,
152//!     })
153//! }
154//! ```
155//!
156//! ### Discovery, Automatic Reloads, and Engine Customization
157//!
158//! As long as one of [`Template::fairing()`], [`Template::custom()`], or
159//! [`Template::try_custom()`] is [attached], any file in the configured
160//! `template_dir` ending with a known engine extension (as described in the
161//! [usage section](#usage)) can be rendered. The latter two fairings allow
162//! customizations such as registering helpers and templates from strings.
163//!
164//! _**Note:** Templates that are registered directly via [`Template::custom()`],
165//! use whatever name provided during that registration; no extensions are
166//! automatically removed._
167//!
168//! In debug mode (without the `--release` flag passed to `cargo`), templates
169//! are **automatically reloaded** from disk when changes are made. In release
170//! builds, template reloading is disabled to improve performance and cannot be
171//! enabled.
172//!
173//! [attached]: rocket::Rocket::attach()
174//!
175//! ### Metadata and Rendering to `String`
176//!
177//! The [`Metadata`] request guard allows dynamically querying templating
178//! metadata, such as whether a template is known to exist
179//! ([`Metadata::contains_template()`]), and to render templates to `String`
180//! ([`Metadata::render()`]).
181
182#![doc(html_root_url = "https://api.rocket.rs/master/rocket_dyn_templates")]
183#![doc(html_favicon_url = "https://rocket.rs/images/favicon.ico")]
184#![doc(html_logo_url = "https://rocket.rs/images/logo-boxed.png")]
185
186#[macro_use]
187extern crate rocket;
188
189#[doc(inline)]
190#[cfg(feature = "tera")]
191/// The tera templating engine library, reexported.
192pub use tera;
193
194#[doc(inline)]
195#[cfg(feature = "handlebars")]
196/// The handlebars templating engine library, reexported.
197pub use handlebars;
198
199#[doc(inline)]
200#[cfg(feature = "minijinja")]
201/// The minijinja templating engine library, reexported.
202pub use minijinja;
203
204#[doc(hidden)]
205pub use rocket::serde;
206
207mod context;
208mod engine;
209mod fairing;
210mod metadata;
211mod template;
212
213pub use engine::Engines;
214pub use metadata::Metadata;
215pub use template::Template;