diff --git a/contrib/src/lib.rs b/contrib/src/lib.rs index 146f1982..ea80752e 100644 --- a/contrib/src/lib.rs +++ b/contrib/src/lib.rs @@ -73,7 +73,7 @@ pub use msgpack::{MsgPack, MsgPackError}; mod templates; #[cfg(feature = "templates")] -pub use templates::Template; +pub use templates::{Template, Engines}; #[cfg(feature = "uuid")] mod uuid; diff --git a/contrib/src/templates/engine.rs b/contrib/src/templates/engine.rs index 55f84a02..7fa83b78 100644 --- a/contrib/src/templates/engine.rs +++ b/contrib/src/templates/engine.rs @@ -13,20 +13,61 @@ pub trait Engine: Send + Sync + 'static { fn render(&self, name: &str, context: C) -> Option; } +/// A structure exposing access to templating engines. +/// +/// Calling methods on the exposed template engine types may require importing +/// types from the respective templating engine library. These types should be +/// imported from the reexported crate at the root of `rocket_contrib` to avoid +/// version mismatches. For instance, when registering a Tera filter, the +/// [`tera::Value`] and [`tera::Result`] types are required. Import them from +/// `rocket_contrib::tera`. The example below illustrates this: +/// +/// ```rust +/// use std::collections::HashMap; +/// +/// use rocket_contrib::{Template, Engines}; +/// use rocket_contrib::tera::{self, Value}; +/// +/// fn my_filter(value: Value, _: HashMap) -> tera::Result { +/// # /* +/// ... +/// # */ unimplemented!(); +/// } +/// +/// Template::custom(|engines: &mut Engines| { +/// engines.tera.register_filter("my_filter", my_filter); +/// }); +/// ``` +/// +/// [`tera::Value`]: https://docs.rs/tera/0.10.10/tera/enum.Value.html +/// [`tera::Result`]: https://docs.rs/tera/0.10.10/tera/type.Result.html pub struct Engines { #[cfg(feature = "tera_templates")] + /// A [`Tera`] structure. This field is only available when the + /// `tera_templates` feature is enabled. When calling methods on the `Tera` + /// instance, ensure you use types imported from `rocket_contrib::tera` to + /// avoid version mismatches. + /// + /// [`Tera`]: https://docs.rs/tera/0.10.10/tera/struct.Tera.html pub tera: Tera, + /// A [`Handlebars`] structure. This field is only available when the + /// `handlebars_templates` feature is enabled. When calling methods on the + /// `Tera` instance, ensure you use types + /// imported from `rocket_contrib::handlebars` to avoid version mismatches. + /// + /// [`Handlebars`]: + /// https://docs.rs/handlebars/0.29.1/handlebars/struct.Handlebars.html #[cfg(feature = "handlebars_templates")] pub handlebars: Handlebars, } impl Engines { - pub const ENABLED_EXTENSIONS: &'static [&'static str] = &[ + pub(crate) const ENABLED_EXTENSIONS: &'static [&'static str] = &[ #[cfg(feature = "tera_templates")] Tera::EXT, #[cfg(feature = "handlebars_templates")] Handlebars::EXT, ]; - pub fn init(templates: &HashMap) -> Option { + pub(crate) fn init(templates: &HashMap) -> Option { fn inner(templates: &HashMap) -> Option { let named_templates = templates.iter() .filter(|&(_, i)| i.extension == E::EXT) @@ -50,20 +91,23 @@ impl Engines { }) } - pub fn render(&self, name: &str, info: &TemplateInfo, c: C) -> Option - where C: Serialize - { + pub(crate) fn render( + &self, + name: &str, + info: &TemplateInfo, + context: C + ) -> Option { #[cfg(feature = "tera_templates")] { if info.extension == Tera::EXT { - return Engine::render(&self.tera, name, c); + return Engine::render(&self.tera, name, context); } } #[cfg(feature = "handlebars_templates")] { if info.extension == Handlebars::EXT { - return Engine::render(&self.handlebars, name, c); + return Engine::render(&self.handlebars, name, context); } } diff --git a/contrib/src/templates/mod.rs b/contrib/src/templates/mod.rs index 9f296f70..1c3882e9 100644 --- a/contrib/src/templates/mod.rs +++ b/contrib/src/templates/mod.rs @@ -7,7 +7,9 @@ extern crate glob; mod engine; mod context; -use self::engine::{Engine, Engines}; +pub use self::engine::Engines; + +use self::engine::Engine; use self::context::Context; use self::serde::Serialize; use self::serde_json::{Value, to_value}; @@ -61,11 +63,10 @@ const DEFAULT_TEMPLATE_DIR: &'static str = "templates"; /// extensions should look like: `.html.hbs`, `.html.tera`, `.xml.hbs`, etc. /// /// Template discovery is actualized by the template fairing, which itself is -/// created via the -/// [`Template::fairing()`](/rocket_contrib/struct.Template.html#method.fairing) -/// method. In order for _any_ templates to be rendered, the template fairing -/// must be [attached](/rocket/struct.Rocket.html#method.attach) to the running -/// Rocket instance. +/// created via the [`Template::fairing()`] or [`Template::custom()`] method. In +/// order for _any_ templates to be rendered, the template fairing _must_ be +/// [attached](/rocket/struct.Rocket.html#method.attach) to the running Rocket +/// instance. Failure to do so will result in an error. /// /// Templates are rendered with the `render` method. The method takes in the /// name of a template and a context to render the template with. The context @@ -114,6 +115,15 @@ const DEFAULT_TEMPLATE_DIR: &'static str = "templates"; /// Template::render("index", &context) /// } /// ``` +/// +/// # Customizing +/// +/// You can use the [`Template::custom()`] method to construct a fairing with +/// customized templating engines. Among other things, this method allows you to +/// register template helpers and register templates from strings. +/// +/// [`Template::custom()`]: /rocket_contrib/struct.Template.html#method.custom +/// [`Template::fairing()`]: /rocket_contrib/struct.Template.html#method.fairing #[derive(Debug)] pub struct Template { name: Cow<'static, str>, @@ -133,10 +143,16 @@ pub struct TemplateInfo { impl Template { /// Returns a fairing that intializes and maintains templating state. /// - /// This fairing _must_ be attached to any `Rocket` instance that wishes to - /// render templates. Failure to attach this fairing will result in a - /// "Uninitialized template context: missing fairing." error message when a - /// template is attempted to be rendered. + /// This fairing, or the one returned by [`Template::custom()`], _must_ be + /// attached to any `Rocket` instance that wishes to render templates. + /// Failure to attach this fairing will result in a "Uninitialized template + /// context: missing fairing." error message when a template is attempted to + /// be rendered. + /// + /// If you wish to customize the internal templating engines, use + /// [`Template::custom()`] instead. + /// + /// [`Template::custom()`]: /rocket_contrib/struct.Template.html#method.custom /// /// # Example /// @@ -163,8 +179,11 @@ impl Template { /// Returns a fairing that intializes and maintains templating state. /// - /// This method allows you to configure the template context via the - /// closure. + /// Unlike [`Template::fairing()`], this method allows you to configure + /// templating engines via the parameter `f`. Note that only the enabled + /// templating engines will be accessible from the `Engines` type. + /// + /// [`Template::fairing()`]: /rocket_contrib/struct.Template.html#method.fairing /// /// # Example ///