Merge branch 'partials'
This commit is contained in:
commit
ad33f98404
@ -1,11 +1,11 @@
|
|||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::escaped;
|
|
||||||
use nom::bytes::complete::escaped_transform;
|
use nom::bytes::complete::escaped_transform;
|
||||||
use nom::bytes::complete::is_a;
|
use nom::bytes::complete::is_a;
|
||||||
use nom::bytes::complete::is_not;
|
use nom::bytes::complete::is_not;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
use nom::bytes::complete::take_until;
|
use nom::bytes::complete::take_until;
|
||||||
use nom::character::complete::one_of;
|
use nom::character::complete::one_of;
|
||||||
|
use nom::character::complete::space1;
|
||||||
use nom::combinator::map;
|
use nom::combinator::map;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
@ -15,8 +15,10 @@ use nom::combinator::verify;
|
|||||||
use nom::multi::many0;
|
use nom::multi::many0;
|
||||||
use nom::multi::many1;
|
use nom::multi::many1;
|
||||||
use nom::multi::separated_list;
|
use nom::multi::separated_list;
|
||||||
|
use nom::multi::separated_nonempty_list;
|
||||||
use nom::sequence::delimited;
|
use nom::sequence::delimited;
|
||||||
use nom::sequence::preceded;
|
use nom::sequence::preceded;
|
||||||
|
use nom::sequence::separated_pair;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
|
|
||||||
@ -30,6 +32,7 @@ enum DustTag<'a> {
|
|||||||
DTNotExists(Container<'a>),
|
DTNotExists(Container<'a>),
|
||||||
DTBlock(NamedBlock<'a>),
|
DTBlock(NamedBlock<'a>),
|
||||||
DTInlinePartial(NamedBlock<'a>),
|
DTInlinePartial(NamedBlock<'a>),
|
||||||
|
DTPartial(ParameterizedBlock<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@ -86,6 +89,24 @@ struct NamedBlock<'a> {
|
|||||||
contents: Option<Body<'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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
struct Body<'a> {
|
struct Body<'a> {
|
||||||
elements: Vec<TemplateElement<'a>>,
|
elements: Vec<TemplateElement<'a>>,
|
||||||
@ -115,6 +136,7 @@ fn dust_tag(i: &str) -> IResult<&str, DustTag> {
|
|||||||
conditional("{^", DustTag::DTNotExists),
|
conditional("{^", DustTag::DTNotExists),
|
||||||
named_block("{+", DustTag::DTBlock),
|
named_block("{+", DustTag::DTBlock),
|
||||||
named_block("{<", DustTag::DTInlinePartial),
|
named_block("{<", DustTag::DTInlinePartial),
|
||||||
|
parameterized_self_closing_block("{>", DustTag::DTPartial),
|
||||||
))(i)
|
))(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
|
/// A series of keys separated by '.' to reference a variable in the context
|
||||||
fn path(i: &str) -> IResult<&str, Path> {
|
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
|
/// 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> {
|
fn filter(i: &str) -> IResult<&str, Filter> {
|
||||||
preceded(
|
preceded(
|
||||||
tag("|"),
|
tag("|"),
|
||||||
@ -620,4 +687,50 @@ mod tests {
|
|||||||
Ok(("", r#"foo"bar\baz"#.to_owned()))
|
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…
Reference in New Issue
Block a user