From 34fb76d8b4050939b96a6656c6bcbef9241d5d1f Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Mon, 27 Dec 2021 08:40:30 +0800 Subject: [PATCH 1/5] feat: add rust-embed support as template source --- Cargo.toml | 1 + src/registry.rs | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 82b48b299..34504e7c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ serde = "1.0.0" serde_json = "1.0.39" walkdir = { version = "2.2.3", optional = true } rhai = { version = "1", optional = true, features = ["sync", "serde"] } +rust-embed = { version = "6.3.0", optional = true } [dev-dependencies] env_logger = "0.9" diff --git a/src/registry.rs b/src/registry.rs index 7cde7271d..9061a9559 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -30,6 +30,9 @@ use rhai::Engine; #[cfg(feature = "script_helper")] use crate::helpers::scripting::ScriptHelper; +#[cfg(feature = "rust-embed")] +use rust_embed::RustEmbed; + /// This type represents an *escape fn*, that is a function whose purpose it is /// to escape potentially problematic characters in a string. /// @@ -322,6 +325,25 @@ impl<'reg> Registry<'reg> { Ok(()) } + /// Register templates using a RustEmbed type + #[cfg(feature = "rust-embed")] + #[cfg_attr(docsrs, doc(cfg(feature = "rust-embed")))] + pub fn register_embed_templates(&mut self) -> Result<(), TemplateError> + where + E: RustEmbed, + { + for item in E::iter() { + let file_name = item.as_ref(); + if let Some(file) = E::get(file_name) { + let data = file.data; + + let tpl_content = String::from_utf8_lossy(data.as_ref()); + self.register_template_string(&file_name.to_owned(), tpl_content)?; + } + } + Ok(()) + } + /// Remove a template from the registry pub fn unregister_template(&mut self, name: &str) { self.templates.remove(name); From 62ebdb0cb6ee87310c53379697a1cdbdbe151014 Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Mon, 27 Dec 2021 22:16:24 +0800 Subject: [PATCH 2/5] test: Add test for rustembed --- tests/embed.rs | 26 ++++++++++++++++++++++++++ tests/templates/hello.hbs | 1 + 2 files changed, 27 insertions(+) create mode 100644 tests/embed.rs create mode 100644 tests/templates/hello.hbs diff --git a/tests/embed.rs b/tests/embed.rs new file mode 100644 index 000000000..fe91cc1db --- /dev/null +++ b/tests/embed.rs @@ -0,0 +1,26 @@ +#[macro_use] +extern crate serde_json; + +use handlebars::Handlebars; + +#[test] +#[cfg(feature = "rust-embed")] +fn test_embed() { + use rust_embed::RustEmbed; + + #[derive(RustEmbed)] + #[folder = "tests/templates/"] + #[include = "*.hbs"] + struct Templates; + + let mut hbs = Handlebars::new(); + hbs.register_embed_templates::().unwrap(); + + assert_eq!(1, hbs.get_templates().len()); + + let data = json!({ + "name": "Andy" + }); + + assert_eq!(hbs.render("hello.hbs", &data).unwrap(), "Hello, Andy\n"); +} diff --git a/tests/templates/hello.hbs b/tests/templates/hello.hbs new file mode 100644 index 000000000..a2344af53 --- /dev/null +++ b/tests/templates/hello.hbs @@ -0,0 +1 @@ +Hello, {{name}} From 725bf45a65f6d96b7dc94ba9d6e0c583c84b1198 Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Tue, 28 Dec 2021 21:56:00 +0800 Subject: [PATCH 3/5] doc: add docstring for rustembed method --- src/registry.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/registry.rs b/src/registry.rs index 9061a9559..cc59675fa 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -325,7 +325,20 @@ impl<'reg> Registry<'reg> { Ok(()) } - /// Register templates using a RustEmbed type + /// Register templates using a + /// [RustEmbed](https://github.com/pyros2097/rust-embed) type + /// + /// File names from embed struct are used as template name. + /// + /// ```skip + /// #[derive(RustEmbed)] + /// #[folder = "templates"] + /// struct Assets; + /// + /// let mut hbs = Handlebars::new(); + /// hbs.register_embed_templates::(); + /// ``` + /// #[cfg(feature = "rust-embed")] #[cfg_attr(docsrs, doc(cfg(feature = "rust-embed")))] pub fn register_embed_templates(&mut self) -> Result<(), TemplateError> From a2905d5c389b9ebc9a7cde8add5a5c1230760ab1 Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Tue, 28 Dec 2021 22:04:40 +0800 Subject: [PATCH 4/5] doc: Add doc for template loading features in front page --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 1def62146..a50603dda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -166,6 +166,14 @@ //! # } //! ``` //! +//! #### Additional features for loading template from +//! +//! * Feature `dir_source` enables template loading +//! `register_templates_directory` from given directory. +//! * Feature `rust-embed` enables template loading +//! `register_embed_templates` from embedded resources in rust struct +//! generated with `RustEmbed`. +//! //! ### Rendering Something //! //! Since handlebars is originally based on JavaScript type system. It supports dynamic features like duck-typing, truthy/falsey values. But for a static language like Rust, this is a little difficult. As a solution, we are using the `serde_json::value::Value` internally for data rendering. From 0bee0424d5246f9d1086d6e2afd59530fa21a24a Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Tue, 28 Dec 2021 22:19:36 +0800 Subject: [PATCH 5/5] fix: LS on windows causing failed test --- tests/embed.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/embed.rs b/tests/embed.rs index fe91cc1db..019f27db9 100644 --- a/tests/embed.rs +++ b/tests/embed.rs @@ -22,5 +22,8 @@ fn test_embed() { "name": "Andy" }); - assert_eq!(hbs.render("hello.hbs", &data).unwrap(), "Hello, Andy\n"); + assert_eq!( + hbs.render("hello.hbs", &data).unwrap().trim(), + "Hello, Andy" + ); }