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;