Finished transitioning to the new top-level ignored whitespace template element.
This commit is contained in:
parent
908ae078b0
commit
bafff8e7a0
@ -2,9 +2,7 @@ use nom::branch::alt;
|
|||||||
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, take_until, take_until_parser_matches};
|
||||||
use nom::bytes::complete::take_until;
|
|
||||||
use nom::bytes::complete::take_until_parser_matches;
|
|
||||||
use nom::character::complete::line_ending;
|
use nom::character::complete::line_ending;
|
||||||
use nom::character::complete::multispace0;
|
use nom::character::complete::multispace0;
|
||||||
use nom::character::complete::one_of;
|
use nom::character::complete::one_of;
|
||||||
@ -90,7 +88,7 @@ pub enum Filter {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Span<'a> {
|
pub struct Span<'a> {
|
||||||
pub contents: Vec<&'a str>,
|
pub contents: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@ -153,26 +151,23 @@ pub enum TemplateElement<'a> {
|
|||||||
///
|
///
|
||||||
/// These elements are always wrapped in curly braces
|
/// These elements are always wrapped in curly braces
|
||||||
fn dust_tag(i: &str) -> IResult<&str, DustTag> {
|
fn dust_tag(i: &str) -> IResult<&str, DustTag> {
|
||||||
preceded(
|
alt((
|
||||||
opt(span_end_of_line),
|
map(special, DustTag::DTSpecial),
|
||||||
alt((
|
map(comment, DustTag::DTComment),
|
||||||
map(special, DustTag::DTSpecial),
|
map(reference, DustTag::DTReference),
|
||||||
map(comment, DustTag::DTComment),
|
conditional("{#", DustTag::DTSection),
|
||||||
map(reference, DustTag::DTReference),
|
conditional("{?", DustTag::DTExists),
|
||||||
conditional("{#", DustTag::DTSection),
|
conditional("{^", DustTag::DTNotExists),
|
||||||
conditional("{?", DustTag::DTExists),
|
named_block("{+", DustTag::DTBlock),
|
||||||
conditional("{^", DustTag::DTNotExists),
|
named_block("{<", DustTag::DTInlinePartial),
|
||||||
named_block("{+", DustTag::DTBlock),
|
partial("{>", DustTag::DTPartial),
|
||||||
named_block("{<", DustTag::DTInlinePartial),
|
parameterized_block("{@", "gte", DustTag::DTHelperGreaterThenOrEquals),
|
||||||
partial("{>", DustTag::DTPartial),
|
parameterized_block("{@", "lte", DustTag::DTHelperLessThenOrEquals),
|
||||||
parameterized_block("{@", "gte", DustTag::DTHelperGreaterThenOrEquals),
|
parameterized_block("{@", "eq", DustTag::DTHelperEquals),
|
||||||
parameterized_block("{@", "lte", DustTag::DTHelperLessThenOrEquals),
|
parameterized_block("{@", "ne", DustTag::DTHelperNotEquals),
|
||||||
parameterized_block("{@", "eq", DustTag::DTHelperEquals),
|
parameterized_block("{@", "gt", DustTag::DTHelperGreaterThan),
|
||||||
parameterized_block("{@", "ne", DustTag::DTHelperNotEquals),
|
parameterized_block("{@", "lt", DustTag::DTHelperLessThan),
|
||||||
parameterized_block("{@", "gt", DustTag::DTHelperGreaterThan),
|
))(i)
|
||||||
parameterized_block("{@", "lt", DustTag::DTHelperLessThan),
|
|
||||||
)),
|
|
||||||
)(i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Special characters
|
/// Special characters
|
||||||
@ -487,32 +482,32 @@ fn filter(i: &str) -> IResult<&str, Filter> {
|
|||||||
/// Whitespace at the beginning of lines is ignored so we are matching
|
/// Whitespace at the beginning of lines is ignored so we are matching
|
||||||
/// a newline character followed by as much contiguous whitespace as
|
/// a newline character followed by as much contiguous whitespace as
|
||||||
/// possible, all of which will be thrown away by other parsers.
|
/// possible, all of which will be thrown away by other parsers.
|
||||||
fn span_end_of_line(i: &str) -> IResult<&str, (&str, &str)> {
|
fn ignore_new_line_leading_whitespace(i: &str) -> IResult<&str, IgnoredWhitespace> {
|
||||||
tuple((line_ending, multispace0))(i)
|
map(
|
||||||
|
recognize(tuple((line_ending, multispace0))),
|
||||||
|
IgnoredWhitespace::StartOfLine,
|
||||||
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_line(i: &str) -> IResult<&str, &str> {
|
/// Any text that is not a Dust element or ignored whitespace
|
||||||
verify(
|
fn span(i: &str) -> IResult<&str, Span> {
|
||||||
|
let (remaining, line) = verify(
|
||||||
take_until_parser_matches(alt((
|
take_until_parser_matches(alt((
|
||||||
tag("{"),
|
tag("{"),
|
||||||
line_ending,
|
line_ending,
|
||||||
recognize(all_consuming(eof_whitespace)),
|
recognize(all_consuming(eof_whitespace)),
|
||||||
))),
|
))),
|
||||||
|s: &str| s.len() > 0,
|
|s: &str| s.len() > 0,
|
||||||
)(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Any text that is not a Dust element
|
|
||||||
fn span(i: &str) -> IResult<&str, Span> {
|
|
||||||
let (remaining, lines) = preceded(
|
|
||||||
opt(span_end_of_line),
|
|
||||||
many1(terminated(span_line, opt(span_end_of_line))),
|
|
||||||
)(i)?;
|
)(i)?;
|
||||||
Ok((remaining, Span { contents: lines }))
|
Ok((remaining, Span { contents: line }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(i: &str) -> IResult<&str, Body> {
|
fn body(i: &str) -> IResult<&str, Body> {
|
||||||
let (remaining, template_elements) = many1(alt((
|
let (remaining, template_elements) = many1(alt((
|
||||||
|
map(
|
||||||
|
ignore_new_line_leading_whitespace,
|
||||||
|
TemplateElement::TEIgnoredWhitespace,
|
||||||
|
),
|
||||||
map(span, TemplateElement::TESpan),
|
map(span, TemplateElement::TESpan),
|
||||||
map(dust_tag, TemplateElement::TETag),
|
map(dust_tag, TemplateElement::TETag),
|
||||||
)))(i)?;
|
)))(i)?;
|
||||||
@ -621,24 +616,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_span_end_of_line() {
|
fn test_span_end_of_line() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
super::span_end_of_line("\n \t \n\nfoo"),
|
super::ignore_new_line_leading_whitespace("\n \t \n\nfoo"),
|
||||||
Ok(("foo", ("\n", " \t \n\n")))
|
Ok(("foo", IgnoredWhitespace::StartOfLine("\n \t \n\n")))
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_span_line() {
|
|
||||||
assert_eq!(
|
|
||||||
super::span_line("this is just some text"),
|
|
||||||
Ok(("", "this is just some text"))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
super::span_line("this is just some text {~lb}"),
|
|
||||||
Ok(("{~lb}", "this is just some text "))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
super::span_line("{~lb}"),
|
|
||||||
Err(Error(("{~lb}", ErrorKind::Verify)))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,7 +628,7 @@ mod tests {
|
|||||||
Ok((
|
Ok((
|
||||||
"",
|
"",
|
||||||
Span {
|
Span {
|
||||||
contents: vec!["this is just some text"]
|
contents: "this is just some text"
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
@ -658,7 +637,7 @@ mod tests {
|
|||||||
Ok((
|
Ok((
|
||||||
"{~lb}",
|
"{~lb}",
|
||||||
Span {
|
Span {
|
||||||
contents: vec!["this is just some text "]
|
contents: "this is just some text "
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
@ -667,20 +646,44 @@ mod tests {
|
|||||||
Err(Error(("{~lb}", ErrorKind::Verify)))
|
Err(Error(("{~lb}", ErrorKind::Verify)))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
super::span("this is \t \n\n \t \n \t multiline text\n {foo}"),
|
super::body("this is \t \n\n \t \n \t multiline text\n {foo}"),
|
||||||
Ok((
|
Ok((
|
||||||
"{foo}",
|
"",
|
||||||
Span {
|
Body {
|
||||||
contents: vec!["this is \t ", "multiline text"]
|
elements: vec![
|
||||||
|
TemplateElement::TESpan(Span {
|
||||||
|
contents: "this is \t "
|
||||||
|
}),
|
||||||
|
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
|
||||||
|
"\n\n \t \n \t "
|
||||||
|
)),
|
||||||
|
TemplateElement::TESpan(Span {
|
||||||
|
contents: "multiline text"
|
||||||
|
}),
|
||||||
|
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
|
||||||
|
"\n "
|
||||||
|
)),
|
||||||
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
|
path: Path { keys: vec!["foo"] },
|
||||||
|
filters: vec![]
|
||||||
|
}))
|
||||||
|
]
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
super::span("\n leading whitespace"),
|
super::body("\n leading whitespace"),
|
||||||
Ok((
|
Ok((
|
||||||
"",
|
"",
|
||||||
Span {
|
Body {
|
||||||
contents: vec!["leading whitespace"]
|
elements: vec![
|
||||||
|
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
|
||||||
|
"\n "
|
||||||
|
)),
|
||||||
|
TemplateElement::TESpan(Span {
|
||||||
|
contents: "leading whitespace"
|
||||||
|
}),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
@ -740,9 +743,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
contents: Some(Body {
|
contents: Some(Body {
|
||||||
elements: vec![
|
elements: vec![
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span { contents: "hello " }),
|
||||||
contents: vec!["hello "]
|
|
||||||
}),
|
|
||||||
TemplateElement::TETag(DustTag::DTReference(Reference {
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
path: Path { keys: vec!["name"] },
|
path: Path { keys: vec!["name"] },
|
||||||
filters: Vec::new()
|
filters: Vec::new()
|
||||||
@ -767,9 +768,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
contents: Some(Body {
|
contents: Some(Body {
|
||||||
elements: vec![
|
elements: vec![
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span { contents: "hello " }),
|
||||||
contents: vec!["hello "]
|
|
||||||
}),
|
|
||||||
TemplateElement::TETag(DustTag::DTReference(Reference {
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
path: Path { keys: vec!["name"] },
|
path: Path { keys: vec!["name"] },
|
||||||
filters: Vec::new()
|
filters: Vec::new()
|
||||||
@ -779,7 +778,7 @@ mod tests {
|
|||||||
else_contents: Some(Body {
|
else_contents: Some(Body {
|
||||||
elements: vec![
|
elements: vec![
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span {
|
||||||
contents: vec!["goodbye "]
|
contents: "goodbye "
|
||||||
}),
|
}),
|
||||||
TemplateElement::TETag(DustTag::DTReference(Reference {
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
path: Path { keys: vec!["name"] },
|
path: Path { keys: vec!["name"] },
|
||||||
@ -816,9 +815,7 @@ mod tests {
|
|||||||
name: "foo",
|
name: "foo",
|
||||||
contents: Some(Body {
|
contents: Some(Body {
|
||||||
elements: vec![
|
elements: vec![
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span { contents: "hello " }),
|
||||||
contents: vec!["hello "]
|
|
||||||
}),
|
|
||||||
TemplateElement::TETag(DustTag::DTReference(Reference {
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
path: Path { keys: vec!["name"] },
|
path: Path { keys: vec!["name"] },
|
||||||
filters: Vec::new()
|
filters: Vec::new()
|
||||||
@ -854,9 +851,7 @@ mod tests {
|
|||||||
name: "foo",
|
name: "foo",
|
||||||
contents: Some(Body {
|
contents: Some(Body {
|
||||||
elements: vec![
|
elements: vec![
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span { contents: "hello " }),
|
||||||
contents: vec!["hello "]
|
|
||||||
}),
|
|
||||||
TemplateElement::TETag(DustTag::DTReference(Reference {
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
path: Path { keys: vec!["name"] },
|
path: Path { keys: vec!["name"] },
|
||||||
filters: Vec::new()
|
filters: Vec::new()
|
||||||
@ -943,15 +938,13 @@ mod tests {
|
|||||||
contents: Some(Body {
|
contents: Some(Body {
|
||||||
elements: vec![
|
elements: vec![
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span {
|
||||||
contents: vec!["Pet the "]
|
contents: "Pet the "
|
||||||
}),
|
}),
|
||||||
TemplateElement::TETag(DustTag::DTReference(Reference {
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
path: Path { keys: vec!["name"] },
|
path: Path { keys: vec!["name"] },
|
||||||
filters: Vec::new()
|
filters: Vec::new()
|
||||||
})),
|
})),
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span { contents: "!" })
|
||||||
contents: vec!["!"]
|
|
||||||
})
|
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
else_contents: None
|
else_contents: None
|
||||||
@ -1002,9 +995,12 @@ mod tests {
|
|||||||
contents: Body {
|
contents: Body {
|
||||||
elements: vec![
|
elements: vec![
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span {
|
||||||
contents: vec!["- simple -"]
|
contents: "- simple -"
|
||||||
}),
|
}),
|
||||||
TemplateElement::TETag(DustTag::DTSpecial(Special::NewLine)),
|
TemplateElement::TETag(DustTag::DTSpecial(Special::NewLine)),
|
||||||
|
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
|
||||||
|
"\n"
|
||||||
|
)),
|
||||||
TemplateElement::TETag(DustTag::DTSection(Container {
|
TemplateElement::TETag(DustTag::DTSection(Container {
|
||||||
path: Path {
|
path: Path {
|
||||||
keys: vec!["names"]
|
keys: vec!["names"]
|
||||||
@ -1019,22 +1015,34 @@ mod tests {
|
|||||||
}),
|
}),
|
||||||
else_contents: None,
|
else_contents: None,
|
||||||
})),
|
})),
|
||||||
|
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
|
||||||
|
"\n"
|
||||||
|
)),
|
||||||
TemplateElement::TETag(DustTag::DTSpecial(Special::NewLine)),
|
TemplateElement::TETag(DustTag::DTSpecial(Special::NewLine)),
|
||||||
TemplateElement::TESpan(Span {
|
TemplateElement::TESpan(Span {
|
||||||
contents: vec!["- new lines -"]
|
contents: "- new lines -"
|
||||||
}),
|
}),
|
||||||
TemplateElement::TETag(DustTag::DTSpecial(Special::NewLine)),
|
TemplateElement::TETag(DustTag::DTSpecial(Special::NewLine)),
|
||||||
|
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
|
||||||
|
"\n"
|
||||||
|
)),
|
||||||
TemplateElement::TETag(DustTag::DTSection(Container {
|
TemplateElement::TETag(DustTag::DTSection(Container {
|
||||||
path: Path {
|
path: Path {
|
||||||
keys: vec!["names"]
|
keys: vec!["names"]
|
||||||
},
|
},
|
||||||
contents: Some(Body {
|
contents: Some(Body {
|
||||||
elements: vec![TemplateElement::TETag(DustTag::DTReference(
|
elements: vec![
|
||||||
Reference {
|
TemplateElement::TEIgnoredWhitespace(
|
||||||
|
IgnoredWhitespace::StartOfLine("\n")
|
||||||
|
),
|
||||||
|
TemplateElement::TETag(DustTag::DTReference(Reference {
|
||||||
path: Path { keys: vec![] },
|
path: Path { keys: vec![] },
|
||||||
filters: vec![]
|
filters: vec![]
|
||||||
}
|
})),
|
||||||
))]
|
TemplateElement::TEIgnoredWhitespace(
|
||||||
|
IgnoredWhitespace::StartOfLine("\n")
|
||||||
|
)
|
||||||
|
]
|
||||||
}),
|
}),
|
||||||
else_contents: None,
|
else_contents: None,
|
||||||
})),
|
})),
|
||||||
|
@ -85,10 +85,8 @@ impl<'a> DustRenderer<'a> {
|
|||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
for elem in &body.elements {
|
for elem in &body.elements {
|
||||||
match elem {
|
match elem {
|
||||||
TemplateElement::TESpan(span) => span
|
TemplateElement::TEIgnoredWhitespace(_) => {}
|
||||||
.contents
|
TemplateElement::TESpan(span) => output.push_str(span.contents),
|
||||||
.iter()
|
|
||||||
.for_each(|line: &&str| output.push_str(line)),
|
|
||||||
TemplateElement::TETag(dt) => {
|
TemplateElement::TETag(dt) => {
|
||||||
output.push_str(&self.render_tag(dt, context)?);
|
output.push_str(&self.render_tag(dt, context)?);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user