diff --git a/src/builder.rs b/src/builder.rs
index 83c5ca4..996fd24 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -4,6 +4,8 @@ use std::collections::HashMap;
use serde::Serialize;
use encoder::Error;
+use crate::Template;
+
use super::{Data, to_data};
/// `MapBuilder` is a helper type that construct `Data` types.
@@ -150,6 +152,21 @@ impl MapBuilder {
MapBuilder { data: data }
}
+ /// Adds a template to the `MapBuilder`.
+ ///
+ /// ```rust
+ /// use mustache::{MapBuilder, compile_str};
+ /// let user_template = compile_str("{{username}}").unwrap();
+ /// let data = MapBuilder::new()
+ /// .insert_template("user", user_template)
+ /// .build();
+ /// ```
+ #[inline]
+ pub fn insert_template(mut self, key: K, value: Template) -> MapBuilder {
+ self.data.insert(key.to_string(), Data::Template(value));
+ self
+ }
+
/// Return the built `Data`.
#[inline]
pub fn build(self) -> Data {
diff --git a/src/data.rs b/src/data.rs
index dbb7b20..b452dea 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -5,12 +5,15 @@ use std::fmt;
// for bug!
use log::{log, error};
+use crate::Template;
+
pub enum Data {
Null,
String(String),
Bool(bool),
Vec(Vec),
Map(HashMap),
+ Template(Template),
Fun(RefCell String + Send>>),
}
@@ -40,6 +43,7 @@ impl fmt::Debug for Data {
Data::Bool(v) => write!(f, "Bool({:?})", v),
Data::Vec(ref v) => write!(f, "VecVal({:?})", v),
Data::Map(ref v) => write!(f, "Map({:?})", v),
+ Data::Template(ref v) => write!(f, "Template({:?})", v),
Data::Fun(_) => write!(f, "Fun(...)"),
}
}
diff --git a/src/template.rs b/src/template.rs
index 49be26a..2c7c1c2 100644
--- a/src/template.rs
+++ b/src/template.rs
@@ -274,6 +274,7 @@ impl<'a> RenderContext<'a> {
self.render(wr, stack, children)?;
stack.pop();
}
+ Data::Template(_) => {}
Data::Fun(ref fcell) => {
let f = &mut *fcell.borrow_mut();
let tokens = self.render_fun(src, otag, ctag, f)?;
@@ -291,9 +292,16 @@ impl<'a> RenderContext<'a> {
stack: &mut Vec<&Data>,
name: &str,
indent: &str) -> Result<()> {
- match self.template.partials.get(name) {
+ match self
+ .find(&[name], stack)
+ .and_then(|d| match d {
+ Data::Template(t) => Some(&t.tokens),
+ _ => None,
+ })
+ .or_else(|| self.template.partials.get(name))
+ {
None => (),
- Some(ref tokens) => {
+ Some(tokens) => {
let mut indent = self.indent.clone() + indent;
mem::swap(&mut self.indent, &mut indent);
@@ -323,7 +331,7 @@ impl<'a> RenderContext<'a> {
Ok(tokens)
}
- fn find<'c>(&self, path: &[String], stack: &mut Vec<&'c Data>) -> Option<&'c Data> {
+ fn find<'c>(&self, path: &[impl AsRef], stack: &mut Vec<&'c Data>) -> Option<&'c Data> {
// If we have an empty path, we just want the top value in our stack.
if path.is_empty() {
match stack.last() {
@@ -342,7 +350,7 @@ impl<'a> RenderContext<'a> {
for data in stack.iter().rev() {
match **data {
Data::Map(ref m) => {
- if let Some(v) = m.get(&path[0]) {
+ if let Some(v) = m.get(path[0].as_ref()) {
value = Some(v);
break;
}
@@ -362,7 +370,7 @@ impl<'a> RenderContext<'a> {
for part in path[1..].iter() {
match *value {
Data::Map(ref m) => {
- match m.get(part) {
+ match m.get(part.as_ref()) {
Some(v) => {
value = v;
}
diff --git a/tests/template.rs b/tests/template.rs
index f6053a9..4422bee 100644
--- a/tests/template.rs
+++ b/tests/template.rs
@@ -431,6 +431,15 @@ fn assert_partials_data(template: Template) {
assert_eq!(render_data(&template, &Data::Map(ctx0)),
"Names
\n a\n\n".to_string());
+ let mut ctx0 = HashMap::new();
+ let mut ctx1 = HashMap::new();
+ ctx1.insert("name".to_string(), Data::String("a".to_string()));
+ ctx0.insert("names".to_string(), Data::Vec(vec![Data::Map(ctx1)]));
+ let user_partial = compile_str("{{>username}}\n");
+ ctx0.insert("user".to_string(), Data::Template(user_partial));
+ assert_eq!(render_data(&template, &Data::Map(ctx0)),
+ "Names
\n a\n\n".to_string());
+
let mut ctx0 = HashMap::new();
let mut ctx1 = HashMap::new();
ctx1.insert("name".to_string(), Data::String("a".to_string()));