Merge branch 'partials'
This commit is contained in:
		
						commit
						ad33f98404
					
				| @ -1,11 +1,11 @@ | ||||
| use nom::branch::alt; | ||||
| use nom::bytes::complete::escaped; | ||||
| use nom::bytes::complete::escaped_transform; | ||||
| use nom::bytes::complete::is_a; | ||||
| use nom::bytes::complete::is_not; | ||||
| use nom::bytes::complete::tag; | ||||
| use nom::bytes::complete::take_until; | ||||
| use nom::character::complete::one_of; | ||||
| use nom::character::complete::space1; | ||||
| use nom::combinator::map; | ||||
| use nom::combinator::opt; | ||||
| use nom::combinator::recognize; | ||||
| @ -15,8 +15,10 @@ use nom::combinator::verify; | ||||
| use nom::multi::many0; | ||||
| use nom::multi::many1; | ||||
| use nom::multi::separated_list; | ||||
| use nom::multi::separated_nonempty_list; | ||||
| use nom::sequence::delimited; | ||||
| use nom::sequence::preceded; | ||||
| use nom::sequence::separated_pair; | ||||
| use nom::sequence::tuple; | ||||
| use nom::IResult; | ||||
| 
 | ||||
| @ -30,6 +32,7 @@ enum DustTag<'a> { | ||||
|     DTNotExists(Container<'a>), | ||||
|     DTBlock(NamedBlock<'a>), | ||||
|     DTInlinePartial(NamedBlock<'a>), | ||||
|     DTPartial(ParameterizedBlock<'a>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| @ -86,6 +89,24 @@ struct NamedBlock<'a> { | ||||
|     contents: Option<Body<'a>>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| struct ParameterizedBlock<'a> { | ||||
|     name: String, | ||||
|     params: Vec<KVPair<'a>>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| enum RValue<'a> { | ||||
|     RVPath(Path<'a>), | ||||
|     RVString(String), | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| struct KVPair<'a> { | ||||
|     key: &'a str, | ||||
|     value: RValue<'a>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| struct Body<'a> { | ||||
|     elements: Vec<TemplateElement<'a>>, | ||||
| @ -115,6 +136,7 @@ fn dust_tag(i: &str) -> IResult<&str, DustTag> { | ||||
|         conditional("{^", DustTag::DTNotExists), | ||||
|         named_block("{+", DustTag::DTBlock), | ||||
|         named_block("{<", DustTag::DTInlinePartial), | ||||
|         parameterized_self_closing_block("{>", DustTag::DTPartial), | ||||
|     ))(i) | ||||
| } | ||||
| 
 | ||||
| @ -152,7 +174,25 @@ fn key(i: &str) -> IResult<&str, &str> { | ||||
| 
 | ||||
| /// A series of keys separated by '.' to reference a variable in the context
 | ||||
| fn path(i: &str) -> IResult<&str, Path> { | ||||
|     map(separated_list(tag("."), key), |body| Path { keys: body })(i) | ||||
|     map(separated_nonempty_list(tag("."), key), |body| Path { | ||||
|         keys: body, | ||||
|     })(i) | ||||
| } | ||||
| 
 | ||||
| /// Either a literal or a path to a value
 | ||||
| fn rvalue(i: &str) -> IResult<&str, RValue> { | ||||
|     alt(( | ||||
|         map(path, RValue::RVPath), | ||||
|         map(quoted_string, RValue::RVString), | ||||
|     ))(i) | ||||
| } | ||||
| 
 | ||||
| /// Parameters for a partial
 | ||||
| fn key_value_pair(i: &str) -> IResult<&str, KVPair> { | ||||
|     map(separated_pair(key, tag("="), rvalue), |(k, v)| KVPair { | ||||
|         key: k, | ||||
|         value: v, | ||||
|     })(i) | ||||
| } | ||||
| 
 | ||||
| /// Display a value from the context
 | ||||
| @ -290,6 +330,33 @@ where | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn parameterized_self_closing_block<'a, F>( | ||||
|     open_matcher: &'static str, | ||||
|     constructor: F, | ||||
| ) -> impl Fn(&'a str) -> IResult<&'a str, DustTag<'a>> | ||||
| where | ||||
|     F: Fn(ParameterizedBlock<'a>) -> DustTag<'a>, | ||||
| { | ||||
|     move |i: &'a str| { | ||||
|         let (i, (name, params)) = delimited( | ||||
|             tag(open_matcher), | ||||
|             tuple(( | ||||
|                 alt((map(key, String::from), quoted_string)), | ||||
|                 opt(preceded(space1, separated_list(space1, key_value_pair))), | ||||
|             )), | ||||
|             tag("/}"), | ||||
|         )(i)?; | ||||
| 
 | ||||
|         Ok(( | ||||
|             i, | ||||
|             constructor(ParameterizedBlock { | ||||
|                 name: name, | ||||
|                 params: params.unwrap_or(Vec::new()), | ||||
|             }), | ||||
|         )) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn filter(i: &str) -> IResult<&str, Filter> { | ||||
|     preceded( | ||||
|         tag("|"), | ||||
| @ -620,4 +687,50 @@ mod tests { | ||||
|             Ok(("", r#"foo"bar\baz"#.to_owned())) | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn test_unquoted_partial() { | ||||
|         assert_eq!( | ||||
|             dust_tag(r#"{>foo bar=baz animal="cat"/}"#), | ||||
|             Ok(( | ||||
|                 "", | ||||
|                 DustTag::DTPartial(ParameterizedBlock { | ||||
|                     name: "foo".to_owned(), | ||||
|                     params: vec![ | ||||
|                         KVPair { | ||||
|                             key: "bar", | ||||
|                             value: RValue::RVPath(Path { keys: vec!["baz"] }) | ||||
|                         }, | ||||
|                         KVPair { | ||||
|                             key: "animal", | ||||
|                             value: RValue::RVString("cat".to_owned()) | ||||
|                         } | ||||
|                     ] | ||||
|                 }) | ||||
|             )) | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn test_quoted_partial() { | ||||
|         assert_eq!( | ||||
|             dust_tag(r#"{>"template name * with * special \" characters" bar=baz animal="cat"/}"#), | ||||
|             Ok(( | ||||
|                 "", | ||||
|                 DustTag::DTPartial(ParameterizedBlock { | ||||
|                     name: r#"template name * with * special " characters"#.to_owned(),
 | ||||
|                     params: vec![ | ||||
|                         KVPair { | ||||
|                             key: "bar", | ||||
|                             value: RValue::RVPath(Path { keys: vec!["baz"] }) | ||||
|                         }, | ||||
|                         KVPair { | ||||
|                             key: "animal", | ||||
|                             value: RValue::RVString("cat".to_owned()) | ||||
|                         } | ||||
|                     ] | ||||
|                 }) | ||||
|             )) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander