From 1b00492787ceff6e8cc57e93391437a31e25574e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Tue, 12 Oct 2021 19:24:40 +0200 Subject: [PATCH] Allow whitespace trimming in {{raw}} blocks --- askama_shared/src/generator.rs | 4 ++-- askama_shared/src/parser.rs | 35 ++++++++++++++++++---------------- testing/templates/raw-ws.html | 2 ++ testing/tests/simple.rs | 10 ++++++++++ 4 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 testing/templates/raw-ws.html diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs index 78ada4b3a..d6317feb9 100644 --- a/askama_shared/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -439,9 +439,9 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> { self.flush_ws(m.ws1); self.prepare_ws(m.ws2); } - Node::Raw(ws1, contents, ws2) => { + Node::Raw(ws1, lws, val, rws, ws2) => { self.handle_ws(ws1); - self.buf_writable.push(Writable::Lit(contents)); + self.visit_lit(lws, val, rws); self.handle_ws(ws2); } Node::Import(ws, _, _) => { diff --git a/askama_shared/src/parser.rs b/askama_shared/src/parser.rs index 44902d0dc..535c7f298 100644 --- a/askama_shared/src/parser.rs +++ b/askama_shared/src/parser.rs @@ -4,7 +4,7 @@ use std::str; use nom::branch::alt; use nom::bytes::complete::{escaped, is_not, tag, take_till, take_until}; use nom::character::complete::{anychar, char, digit1}; -use nom::combinator::{complete, cut, eof, map, not, opt, recognize, value}; +use nom::combinator::{complete, consumed, cut, eof, map, not, opt, peek, recognize, value}; use nom::error::{Error, ErrorKind}; use nom::multi::{fold_many0, many0, many1, separated_list0, separated_list1}; use nom::sequence::{delimited, pair, preceded, terminated, tuple}; @@ -28,7 +28,7 @@ pub enum Node<'a> { Include(Ws, &'a str), Import(Ws, &'a str, &'a str), Macro(&'a str, Macro<'a>), - Raw(Ws, &'a str, Ws), + Raw(Ws, &'a str, &'a str, &'a str, Ws), Break(Ws), Continue(Ws), } @@ -1048,29 +1048,32 @@ fn block_macro<'a>(i: &'a str, s: &State<'_>) -> IResult<&'a str, Node<'a>> { } fn block_raw<'a>(i: &'a str, s: &State<'_>) -> IResult<&'a str, Node<'a>> { + let endraw = tuple(( + |i| tag_block_start(i, s), + opt(char('-')), + ws(tag("endraw")), + opt(char('-')), + peek(|i| tag_block_end(i, s)), + )); + let mut p = tuple(( opt(char('-')), ws(tag("raw")), cut(tuple(( opt(char('-')), |i| tag_block_end(i, s), - take_until("{% endraw %}"), - |i| tag_block_start(i, s), - opt(char('-')), - ws(tag("endraw")), - opt(char('-')), + consumed(skip_till(endraw)), ))), )); - let (i, (pws1, _, (nws1, _, contents, _, pws2, _, nws2))) = p(i)?; - Ok(( - i, - Node::Raw( - Ws(pws1.is_some(), nws1.is_some()), - contents, - Ws(pws2.is_some(), nws2.is_some()), - ), - )) + let (_, (pws1, _, (nws1, _, (contents, (i, (_, pws2, _, nws2, _)))))) = p(i)?; + let (lws, val, rws) = match split_ws_parts(contents) { + Node::Lit(lws, val, rws) => (lws, val, rws), + _ => unreachable!(), + }; + let ws1 = Ws(pws1.is_some(), nws1.is_some()); + let ws2 = Ws(pws2.is_some(), nws2.is_some()); + Ok((i, Node::Raw(ws1, lws, val, rws, ws2))) } fn break_statement<'a>(i: &'a str, s: &State<'_>) -> IResult<&'a str, Node<'a>> { diff --git a/testing/templates/raw-ws.html b/testing/templates/raw-ws.html new file mode 100644 index 000000000..d590be719 --- /dev/null +++ b/testing/templates/raw-ws.html @@ -0,0 +1,2 @@ +<{% raw -%} {{hello}} {%- endraw %}> +< {%- raw %}{{bye}}{% endraw -%} > diff --git a/testing/tests/simple.rs b/testing/tests/simple.rs index c71290047..e66485a22 100644 --- a/testing/tests/simple.rs +++ b/testing/tests/simple.rs @@ -433,6 +433,16 @@ fn test_raw_complex() { ); } +#[derive(Template)] +#[template(path = "raw-ws.html")] +struct RawTemplateWs; + +#[test] +fn test_raw_ws() { + let template = RawTemplateWs; + assert_eq!(template.render().unwrap(), "<{{hello}}>\n<{{bye}}>"); +} + mod without_import_on_derive { #[derive(askama::Template)] #[template(source = "foo", ext = "txt")]