Support sections with bodies
This commit is contained in:
parent
95a3cff278
commit
5a0b3abf0e
@ -10,13 +10,14 @@ use nom::combinator::rest;
|
||||
use nom::combinator::value;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many1;
|
||||
use nom::multi::separated_list;
|
||||
use nom::sequence::delimited;
|
||||
use nom::sequence::preceded;
|
||||
use nom::sequence::tuple;
|
||||
use nom::IResult;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum DustTag<'a> {
|
||||
DTSpecial(Special),
|
||||
DTComment(Comment<'a>),
|
||||
@ -64,15 +65,27 @@ struct Span<'a> {
|
||||
contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Template<'a> {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct Section<'a> {
|
||||
path: Path<'a>,
|
||||
contents: Option<Block<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct Block<'a> {
|
||||
elements: Vec<TemplateElement<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Template<'a> {
|
||||
contents: Block<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum TemplateElement<'a> {
|
||||
TESpan(Span<'a>),
|
||||
TETag(DustTag<'a>),
|
||||
TESection(Section<'a>),
|
||||
}
|
||||
|
||||
fn dust_tag(i: &str) -> IResult<&str, DustTag> {
|
||||
@ -129,6 +142,22 @@ fn reference(i: &str) -> IResult<&str, Reference> {
|
||||
))
|
||||
}
|
||||
|
||||
fn section(i: &str) -> IResult<&str, Section> {
|
||||
let (i, opening_name) = delimited(tag("{#"), path, tag("}"))(i)?;
|
||||
let (i, inner) = opt(block)(i)?;
|
||||
let (i, _closing_name) = verify(delimited(tag("{/"), path, tag("}")), |name: &Path| {
|
||||
name == &opening_name
|
||||
})(i)?;
|
||||
|
||||
Ok((
|
||||
i,
|
||||
Section {
|
||||
path: opening_name,
|
||||
contents: inner,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
fn filter(i: &str) -> IResult<&str, Filter> {
|
||||
preceded(
|
||||
tag("|"),
|
||||
@ -150,19 +179,25 @@ fn span(i: &str) -> IResult<&str, Span> {
|
||||
Ok((remaining, Span { contents: body }))
|
||||
}
|
||||
|
||||
pub fn template(i: &str) -> IResult<&str, Template> {
|
||||
let (remaining, template_elements) = many0(alt((
|
||||
fn block(i: &str) -> IResult<&str, Block> {
|
||||
let (remaining, template_elements) = many1(alt((
|
||||
map(span, TemplateElement::TESpan),
|
||||
map(dust_tag, TemplateElement::TETag),
|
||||
map(section, TemplateElement::TESection),
|
||||
)))(i)?;
|
||||
Ok((
|
||||
remaining,
|
||||
Template {
|
||||
Block {
|
||||
elements: template_elements,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn template(i: &str) -> IResult<&str, Template> {
|
||||
let (remaining, contents) = block(i)?;
|
||||
Ok((remaining, Template { contents: contents }))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -264,4 +299,57 @@ mod tests {
|
||||
Err(Error(("{~lb}", ErrorKind::Verify)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_section_mismatched_paths() {
|
||||
assert_eq!(
|
||||
super::section("{#foo.bar}{/baz}"),
|
||||
Err(Error(("{/baz}", ErrorKind::Verify)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_section() {
|
||||
assert_eq!(
|
||||
super::section("{#foo.bar}{/foo.bar}"),
|
||||
Ok((
|
||||
"",
|
||||
Section {
|
||||
path: Path {
|
||||
keys: vec!["foo", "bar"]
|
||||
},
|
||||
contents: None
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
super::section("{#foo.bar}{/baz}"),
|
||||
Err(Error(("{/baz}", ErrorKind::Verify)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_section_with_body() {
|
||||
assert_eq!(
|
||||
super::section("{#foo.bar}hello {name}{/foo.bar}"),
|
||||
Ok((
|
||||
"",
|
||||
Section {
|
||||
path: Path {
|
||||
keys: vec!["foo", "bar"]
|
||||
},
|
||||
contents: Some(Block {
|
||||
elements: vec![
|
||||
TemplateElement::TESpan(Span { contents: "hello " }),
|
||||
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||
path: Path { keys: vec!["name"] },
|
||||
filters: Vec::new()
|
||||
}))
|
||||
]
|
||||
})
|
||||
}
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user