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