Add parsing of whitespace trimming

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-09 13:14:58 +01:00
parent 6a233e978f
commit 587cfdea53

View file

@ -16,6 +16,7 @@ use winnow::combinator::eof;
use winnow::combinator::not; use winnow::combinator::not;
use winnow::combinator::opt; use winnow::combinator::opt;
use winnow::combinator::peek; use winnow::combinator::peek;
use winnow::combinator::preceded;
use winnow::combinator::repeat_till; use winnow::combinator::repeat_till;
use winnow::combinator::terminated; use winnow::combinator::terminated;
use winnow::combinator::trace; use winnow::combinator::trace;
@ -201,6 +202,7 @@ pub enum TokenKind {
Content, Content,
LeftDelim, LeftDelim,
RightDelim, RightDelim,
TrimWhitespace,
WantsOutput, WantsOutput,
Ident, Ident,
Whitespace, Whitespace,
@ -286,6 +288,7 @@ impl TemplateToken {
content => TokenKind::Content, content => TokenKind::Content,
left_delim => TokenKind::LeftDelim, left_delim => TokenKind::LeftDelim,
right_delim => TokenKind::RightDelim, right_delim => TokenKind::RightDelim,
trim_whitespace => TokenKind::TrimWhitespace,
wants_output => TokenKind::WantsOutput, wants_output => TokenKind::WantsOutput,
ident => TokenKind::Ident, ident => TokenKind::Ident,
whitespace => TokenKind::Whitespace, whitespace => TokenKind::Whitespace,
@ -344,9 +347,10 @@ fn parse_content<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<Templ
fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken>> { fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken>> {
let prev_whitespace = opt(parse_whitespace).parse_next(input)?; let prev_whitespace = opt(parse_whitespace).parse_next(input)?;
let left_delim = "{{".map(TemplateToken::left_delim).parse_next(input)?; let left_delim = "{{".map(TemplateToken::left_delim).parse_next(input)?;
let left_trim = opt("-".map(TemplateToken::trim_whitespace)).parse_next(input)?;
let wants_output = opt("=".map(TemplateToken::wants_output)).parse_next(input)?; let wants_output = opt("=".map(TemplateToken::wants_output)).parse_next(input)?;
let get_tokens = repeat_till(1.., parse_block_token, peek("}}")); let get_tokens = repeat_till(1.., parse_block_token, peek(preceded(opt("-"), "}}")));
let recover = take_until(0.., "}}").void(); let recover = take_until(0.., "}}").void();
let (inside_tokens, _): (Vec<_>, _) = get_tokens let (inside_tokens, _): (Vec<_>, _) = get_tokens
@ -357,14 +361,17 @@ fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<T
}) })
.parse_next(input)?; .parse_next(input)?;
let right_trim = opt("-".map(TemplateToken::trim_whitespace)).parse_next(input)?;
let right_delim = "}}".map(TemplateToken::right_delim).parse_next(input)?; let right_delim = "}}".map(TemplateToken::right_delim).parse_next(input)?;
let post_whitespace = opt(parse_whitespace).parse_next(input)?; let post_whitespace = opt(parse_whitespace).parse_next(input)?;
let mut tokens = vec![]; let mut tokens = vec![];
tokens.extend(prev_whitespace); tokens.extend(prev_whitespace);
tokens.push(left_delim); tokens.push(left_delim);
tokens.extend(left_trim);
tokens.extend(wants_output); tokens.extend(wants_output);
tokens.extend(inside_tokens); tokens.extend(inside_tokens);
tokens.extend(right_trim);
tokens.push(right_delim); tokens.push(right_delim);
tokens.extend(post_whitespace); tokens.extend(post_whitespace);
@ -595,4 +602,29 @@ mod tests {
) )
"#); "#);
} }
#[test]
fn parse_trim_whitespace() {
let input = "\n\n{{-= hello -}} \n\n";
let output = parse(input.into());
insta::assert_debug_snapshot!(output, @r#"
Ok(
ParsedTemplate {
tokens: [
[Whitespace]"\n\n" (0..2),
[LeftDelim]"{{" (2..4),
[TrimWhitespace]"-" (4..5),
[WantsOutput]"=" (5..6),
[Whitespace]" " (6..7),
[Ident]"hello" (7..12),
[Whitespace]" " (12..13),
[TrimWhitespace]"-" (13..14),
[RightDelim]"}}" (14..16),
[Whitespace]" \n\n" (16..19),
],
},
)
"#);
}
} }