diff --git a/Cargo.toml b/Cargo.toml index ec7338b83..e0277dec9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ serde = "^1.0.0" serde_json = "^1.0.0" regex = "^1.0.0" lazy_static = "^1.0.0" +walkdir = "^1.0.0" [dev-dependencies] env_logger = "^0.4.0" diff --git a/examples/render-cli.rs b/examples/render-cli.rs index 405e0e119..17da10838 100644 --- a/examples/render-cli.rs +++ b/examples/render-cli.rs @@ -41,9 +41,10 @@ fn main() { let mut handlebars = Handlebars::new(); handlebars - .register_template_file(&filename, &filename) + .register_templates_directory() .ok() .unwrap(); + match handlebars.render(&filename, &data) { Ok(data) => { println!("{}", data); diff --git a/src/error.rs b/src/error.rs index 362162f49..6dd3b4f4b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,4 @@ +use std::convert::From; use std::io::Error as IOError; use std::error::Error; use std::fmt; @@ -242,3 +243,4 @@ impl TemplateRenderError { } } } + diff --git a/src/lib.rs b/src/lib.rs index 93d61637a..528ae6ec8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -308,6 +308,7 @@ extern crate serde; #[allow(unused_imports)] #[macro_use] extern crate serde_json; +extern crate walkdir; pub use self::template::Template; pub use self::error::{RenderError, TemplateError, TemplateFileError, TemplateRenderError}; diff --git a/src/registry.rs b/src/registry.rs index f90fef3f7..4072ca85e 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::io::prelude::*; -use std::fs::File; +use std::io; +use std::fs::{File, read_dir}; use std::path::Path; use std::fmt::{self, Debug, Formatter}; @@ -16,6 +17,8 @@ use directives::{self, DirectiveDef}; use support::str::StringWriter; use error::{RenderError, TemplateError, TemplateFileError, TemplateRenderError}; +use walkdir::{WalkDir, DirEntry}; + lazy_static!{ static ref DEFAULT_REPLACE: Regex = Regex::new(">|<|\"|&").unwrap(); } @@ -174,6 +177,43 @@ impl Registry { self.register_template_source(name, &mut file) } + /// Register a template from a directory + pub fn register_templates_directory

( + &mut self, + tpl_extension: &'static str, + dir_path: P, + ) -> Result<(), TemplateFileError> + where + P: AsRef, + { + let dir_path = dir_path.as_ref(); + let prefix_len = if dir_path.to_string_lossy().ends_with("/") { + dir_path.to_string_lossy().len() + } else { + dir_path.to_string_lossy().len() + 1 + }; + + let walker = WalkDir::new(dir_path); + let mut dir_iter = walker.min_depth(1).into_iter(); + match dir_iter.find(|e| e.is_err()) { + Some(Err(err)) => { + let path_string: String = dir_path.to_string_lossy().to_owned().to_string(); + Err(TemplateFileError::IOError(io::Error::from(err), path_string)) + }, + _ => { + for p in dir_iter.filter_map(|e| e.ok()) { + let tpl_path = p.path(); + let tpl_file_path = p.path().to_string_lossy(); + let tpl_name = &tpl_file_path[prefix_len..tpl_file_path.len() - tpl_extension.len()]; + let tpl_canonical_name = tpl_name.replace("\\", "/"); + self.register_template_file(&tpl_canonical_name, &tpl_path)?; + } + + Ok(()) + }, + } + } + /// Register a template from `std::io::Read` source pub fn register_template_source( &mut self,