Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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("<strong>{{username}}</strong>").unwrap();
/// let data = MapBuilder::new()
/// .insert_template("user", user_template)
/// .build();
/// ```
#[inline]
pub fn insert_template<K: ToString>(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 {
Expand Down
4 changes: 4 additions & 0 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Data>),
Map(HashMap<String, Data>),
Template(Template),
Fun(RefCell<Box<dyn FnMut(String) -> String + Send>>),
}

Expand Down Expand Up @@ -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(...)"),
}
}
Expand Down
18 changes: 13 additions & 5 deletions src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand All @@ -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);
Expand Down Expand Up @@ -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<str>], 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() {
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
9 changes: 9 additions & 0 deletions tests/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,15 @@ fn assert_partials_data(template: Template) {
assert_eq!(render_data(&template, &Data::Map(ctx0)),
"<h2>Names</h2>\n <strong>a</strong>\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("<span>{{>username}}</span>\n");
ctx0.insert("user".to_string(), Data::Template(user_partial));
assert_eq!(render_data(&template, &Data::Map(ctx0)),
"<h2>Names</h2>\n <span>a</span>\n\n".to_string());

let mut ctx0 = HashMap::new();
let mut ctx1 = HashMap::new();
ctx1.insert("name".to_string(), Data::String("a".to_string()));
Expand Down