Repository: djc/askama
Pull request #400 (2020-12-14 21:14:19)

Sync local repo with GitHub
I had a few commits still sitting on my laptop. I'd like to merge this (without rebasing or squashing) into main to make sure everyone will have the same state going forward.


Patch:
diff --git a/askama/Cargo.toml b/askama/Cargo.toml
index 0b3a897..da53a98 100644
--- a/askama/Cargo.toml
+++ b/askama/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "askama"
-version = "0.10.3"
+version = "0.10.5"
 authors = ["Dirkjan Ochtman <dirkjan@ochtman.nl>"]
 description = "Type-safe, compiled Jinja-like templates for Rust"
 documentation = "https://docs.rs/askama"
@@ -33,9 +33,9 @@ with-tide = ["askama_derive/tide"]
 with-warp = ["askama_derive/warp"]
 
 [dependencies]
-askama_derive = { version = "0.10.3", path = "../askama_derive" }
+askama_derive = { version = "0.10.5", path = "../askama_derive" }
 askama_escape = { version = "0.10", path = "../askama_escape" }
-askama_shared = { version = "0.10.4", path = "../askama_shared", default-features = false }
+askama_shared = { version = "0.11", path = "../askama_shared", default-features = false }
 mime = { version = "0.3", optional = true }
 mime_guess = { version = "2.0.0-alpha", optional = true }
 
diff --git a/askama_derive/Cargo.toml b/askama_derive/Cargo.toml
index 63d08bd..f3df891 100644
--- a/askama_derive/Cargo.toml
+++ b/askama_derive/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "askama_derive"
-version = "0.10.3"
+version = "0.10.5"
 authors = ["Dirkjan Ochtman <dirkjan@ochtman.nl>"]
 description = "Procedural macro package for Askama"
 homepage = "https://github.com/djc/askama"
@@ -23,6 +23,6 @@ tide = []
 warp = []
 
 [dependencies]
-askama_shared = { version = "0.10.4", path = "../askama_shared", default-features = false }
+askama_shared = { version = "0.11", path = "../askama_shared", default-features = false }
 proc-macro2 = "1"
 syn = "1"
diff --git a/askama_shared/Cargo.toml b/askama_shared/Cargo.toml
index 19946e7..f5ac4b6 100644
--- a/askama_shared/Cargo.toml
+++ b/askama_shared/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "askama_shared"
-version = "0.10.5"
+version = "0.11.1"
 authors = ["Dirkjan Ochtman <dirkjan@ochtman.nl>"]
 description = "Shared code for Askama"
 homepage = "https://github.com/djc/askama"
@@ -19,7 +19,9 @@ yaml = ["serde", "serde_yaml"]
 [dependencies]
 askama_escape = { version = "0.10", path = "../askama_escape" }
 humansize = { version = "1.1.0", optional = true }
-nom = { version = "6", features = ["std"], default-features = false }
+# default for features for nom don't work result in linker errors:
+# https://github.com/rust-lang/rust/issues/62146
+nom = { version = "6", features = ["std"] }
 num-traits = { version = "0.2.6", optional = true }
 proc-macro2 = "1"
 quote = "1"
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index 320e55e..3b73170 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -308,12 +308,12 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
         )?;
 
         buf.writeln(
-            "fn into_response(self, app: &A) \
+            "fn into_response(self, app: &A, req: &::mendes::http::request::Parts) \
              -> ::mendes::http::Response<A::ResponseBody> {",
         )?;
 
         buf.writeln(&format!(
-            "::mendes::askama::into_response(app, &self, {:?})",
+            "::mendes::askama::into_response(app, req, &self, {:?})",
             self.input.path.extension()
         ))?;
         buf.writeln("}")?;
@@ -444,8 +444,8 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
                 Node::Cond(ref conds, ws) => {
                     self.write_cond(ctx, buf, conds, ws)?;
                 }
-                Node::Match(ws1, ref expr, ref arms, ws2) => {
-                    self.write_match(ctx, buf, ws1, expr, arms, ws2)?;
+                Node::Match(ws1, ref expr, inter, ref arms, ws2) => {
+                    self.write_match(ctx, buf, ws1, expr, inter, arms, ws2)?;
                 }
                 Node::Loop(ws1, ref var, ref iter, ref body, ws2) => {
                     self.write_loop(ctx, buf, ws1, var, iter, body, ws2)?;
@@ -505,9 +505,8 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
         let mut has_else = false;
         for (i, &(cws, ref cond, ref nodes)) in conds.iter().enumerate() {
             self.handle_ws(cws);
-            flushed += self.write_buf_writable(buf)?;
-            if i > 0 {
-                self.locals.pop();
+            if arm_sizes.is_empty() {
+                flushed += self.write_buf_writable(buf)?;
             }
 
             let mut arm_size = 0;
@@ -519,15 +518,8 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
                         buf.dedent()?;
                         buf.write("} else if ");
                     }
-                    // The following syntax `*(&(...) as &bool)` is used to
-                    // trigger Rust's automatic dereferencing, to coerce
-                    // e.g. `&&&&&bool` to `bool`. First `&(...) as &bool`
-                    // coerces e.g. `&&&bool` to `&bool`. Then `*(&bool)`
-                    // finally dereferences it to `bool`.
-                    buf.write("*(&(");
                     let expr_code = self.visit_expr_root(expr)?;
                     buf.write(&expr_code);
-                    buf.write(") as &bool)");
                 }
                 None => {
                     buf.dedent()?;
@@ -540,14 +532,14 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
             self.locals.push();
 
             arm_size += self.handle(ctx, nodes, buf, AstLevel::Nested)?;
+            arm_size += self.write_buf_writable(buf)?;
             arm_sizes.push(arm_size);
+
+            self.locals.pop();
         }
         self.handle_ws(ws);
-        flushed += self.write_buf_writable(buf)?;
         buf.writeln("}")?;
 
-        self.locals.pop();
-
         if !has_else {
             arm_sizes.push(0);
         }
@@ -561,28 +553,23 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
         buf: &mut Buffer,
         ws1: WS,
         expr: &Expr,
+        inter: Option<&'a str>,
         arms: &'a [When],
         ws2: WS,
     ) -> Result<usize, CompileError> {
         self.flush_ws(ws1);
         let flushed = self.write_buf_writable(buf)?;
         let mut arm_sizes = Vec::new();
+        if let Some(inter) = inter {
+            if !inter.is_empty() {
+                self.next_ws = Some(inter);
+            }
+        }
 
         let expr_code = self.visit_expr_root(expr)?;
         buf.writeln(&format!("match &{} {{", expr_code))?;
-
-        let mut arm_size = 0;
-        for (i, arm) in arms.iter().enumerate() {
+        for arm in arms {
             let &(ws, ref variant, ref params, ref body) = arm;
-            self.handle_ws(ws);
-
-            if i > 0 {
-                arm_sizes.push(arm_size + self.write_buf_writable(buf)?);
-
-                buf.writeln("}")?;
-                self.locals.pop();
-            }
-
             self.locals.push();
             match *variant {
                 Some(ref param) => {
@@ -629,17 +616,15 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
                 }
             }
             buf.writeln(" => {")?;
-
-            arm_size = self.handle(ctx, body, buf, AstLevel::Nested)?;
+            self.handle_ws(ws);
+            let arm_size = self.handle(ctx, body, buf, AstLevel::Nested)?;
+            arm_sizes.push(arm_size + self.write_buf_writable(buf)?);
+            buf.writeln("}")?;
+            self.locals.pop();
         }
 
-        self.handle_ws(ws2);
-        arm_sizes.push(arm_size + self.write_buf_writable(buf)?);
         buf.writeln("}")?;
-        self.locals.pop();
-
-        buf.writeln("}")?;
-
+        self.handle_ws(ws2);
         Ok(flushed + median(&mut arm_sizes))
     }
 
@@ -732,11 +717,10 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
             }
             names.write(arg);
 
-            values.write("&(");
+            values.write("&");
             values.write(&self.visit_expr_root(args.get(i).ok_or_else(|| {
                 CompileError::String(format!("macro '{}' takes more than {} arguments", name, i))
             })?)?);
-            values.write(")");
             self.locals.insert(arg);
         }
 
@@ -960,7 +944,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
                     let expression = match wrapped {
                         Wrapped => expr_buf.buf,
                         Unwrapped => format!(
-                            "::askama::MarkupDisplay::new_unsafe(&({}), {})",
+                            "::askama::MarkupDisplay::new_unsafe(&{}, {})",
                             expr_buf.buf, self.input.escaper
                         ),
                     };
diff --git a/askama_shared/src/heritage.rs b/askama_shared/src/heritage.rs
index 87f23e0..bc9e701 100644
--- a/askama_shared/src/heritage.rs
+++ b/askama_shared/src/heritage.rs
@@ -89,7 +89,7 @@ impl<'a> Context<'a> {
                     Node::Loop(_, _, _, nodes, _) => {
                         nested.push(nodes);
                     }
-                    Node::Match(_, _, arms, _) => {
+                    Node::Match(_, _, _, arms, _) => {
                         for (_, _, _, arm) in arms {
                             nested.push(arm);
                         }
diff --git a/askama_shared/src/parser.rs b/askama_shared/src/parser.rs
index a40e967..9344c07 100644
--- a/askama_shared/src/parser.rs
+++ b/askama_shared/src/parser.rs
@@ -1,7 +1,7 @@
 use nom::branch::alt;
 use nom::bytes::complete::{escaped, is_not, tag, take_until};
 use nom::character::complete::{anychar, char, digit1};
-use nom::combinator::{complete, map, opt, value};
+use nom::combinator::{complete, map, opt};
 use nom::error::ParseError;
 use nom::multi::{many0, many1, separated_list0, separated_list1};
 use nom::sequence::{delimited, pair, tuple};
@@ -19,7 +19,7 @@ pub enum Node<'a> {
     LetDecl(WS, Target<'a>),
     Let(WS, Target<'a>, Expr<'a>),
     Cond(Vec<(WS, Option<Expr<'a>>, Vec<Node<'a>>)>, WS),
-    Match(WS, Expr<'a>, Vec<When<'a>>, WS),
+    Match(WS, Expr<'a>, Option<&'a str>, Vec<When<'a>>, WS),
     Loop(WS, Target<'a>, Expr<'a>, Vec<Node<'a>>, WS),
     Extends(Expr<'a>),
     BlockDef(WS, &'a str, Vec<Node<'a>>, WS),
@@ -312,12 +312,10 @@ fn expr_var_call(i: &[u8]) -> IResult<&[u8], Expr> {
 }
 
 fn path(i: &[u8]) -> IResult<&[u8], Vec<&str>> {
-    let root = opt(value("", ws(tag("::"))));
     let tail = separated_list1(ws(tag("::")), identifier);
-    let (i, (root, start, _, rest)) = tuple((root, identifier, ws(tag("::")), tail))(i)?;
-    let mut path = Vec::new();
-    path.extend(root);
-    path.push(start);
+    let (i, (start, _, rest)) = tuple((identifier, ws(tag("::")), tail))(i)?;
+
+    let mut path = vec![start];
     path.extend(rest);
     Ok((i, path))
 }
@@ -575,32 +573,36 @@ fn expr_rust_macro(i: &[u8]) -> IResult<&[u8], Expr> {
 macro_rules! expr_prec_layer {
     ( $name:ident, $inner:ident, $op:expr ) => {
         fn $name(i: &[u8]) -> IResult<&[u8], Expr> {
-            let (i, left) = $inner(i)?;
-            let (i, right) = many0(pair(
-                ws(tag($op)),
+            let (i, (left, op_and_right)) = tuple((
                 $inner,
+                opt(pair(
+                    ws(tag($op)),
+                    expr_any,
+                ))
             ))(i)?;
-            Ok((
-                i,
-                right.into_iter().fold(left, |left, (op, right)| {
-                    Expr::BinOp(str::from_utf8(op).unwrap(), Box::new(left), Box::new(right))
-                }),
-            ))
+            Ok((i, match op_and_right {
+                Some((op, right)) => Expr::BinOp(
+                    str::from_utf8(op).unwrap(), Box::new(left), Box::new(right)
+                ),
+                None => left,
+            }))
         }
     };
     ( $name:ident, $inner:ident, $( $op:expr ),+ ) => {
         fn $name(i: &[u8]) -> IResult<&[u8], Expr> {
-            let (i, left) = $inner(i)?;
-            let (i, right) = many0(pair(
-                ws(alt(($( tag($op) ),*,))),
+            let (i, (left, op_and_right)) = tuple((
                 $inner,
+                opt(pair(
+                    ws(alt(($( tag($op) ),*,))),
+                    expr_any
+                ))
             ))(i)?;
-            Ok((
-                i,
-                right.into_iter().fold(left, |left, (op, right)| {
-                    Expr::BinOp(str::from_utf8(op).unwrap(), Box::new(left), Box::new(right))
-                }),
-            ))
+            Ok((i, match op_and_right {
+                Some((op, right)) => Expr::BinOp(
+                    str::from_utf8(op).unwrap(), Box::new(left), Box::new(right)
+                ),
+                None => left,
+            }))
         }
     }
 }
@@ -771,8 +773,8 @@ fn block_match<'a>(i: &'a [u8], s: &'a Syntax<'a>) -> IResult<&'a [u8], Node<'a>
         arms.push(arm);
     }
 
-    match inter {
-        Some(Node::Lit(_, val, rws)) => {
+    let inter = match inter {
+        Some(Node::Lit(lws, val, rws)) => {
             assert!(
                 val.is_empty(),
                 "only whitespace allowed between match and first when, found {}",
@@ -783,16 +785,18 @@ fn block_match<'a>(i: &'a [u8], s: &'a Syntax<'a>) -> IResult<&'a [u8], Node<'a>
                 "only whitespace allowed between match and first when, found {}",
                 rws
             );
+            Some(lws)
         }
-        None => {}
+        None => None,
         _ => panic!("only literals allowed between match and first when"),
-    }
+    };
 
     Ok((
         i,
         Node::Match(
             WS(pws1.is_some(), nws1.is_some()),
             expr,
+            inter,
             arms,
             WS(pws2.is_some(), nws2.is_some()),
         ),
@@ -1074,13 +1078,12 @@ pub fn parse<'a>(src: &'a str, syntax: &'a Syntax<'a>) -> Result<Vec<Node<'a>>,
 
 #[cfg(test)]
 mod tests {
-    use super::{Expr, Node, WS};
     use crate::Syntax;
 
     fn check_ws_split(s: &str, res: &(&str, &str, &str)) {
         let node = super::split_ws_parts(s.as_bytes());
         match node {
-            Node::Lit(lws, s, rws) => {
+            super::Node::Lit(lws, s, rws) => {
                 assert_eq!(lws, res.0);
                 assert_eq!(s, res.1);
                 assert_eq!(rws, res.2);
@@ -1115,9 +1118,12 @@ mod tests {
     fn test_parse_var_call() {
         assert_eq!(
             super::parse("{{ function(\"123\", 3) }}", &Syntax::default()).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                Expr::VarCall("function", vec![Expr::StrLit("123"), Expr::NumLit("3")]),
+            vec![super::Node::Expr(
+                super::WS(false, false),
+                super::Expr::VarCall(
+                    "function",
+                    vec![super::Expr::StrLit("123"), super::Expr::NumLit("3")]
+                ),
             )],
         );
     }
@@ -1126,35 +1132,16 @@ mod tests {
     fn test_parse_path_call() {
         assert_eq!(
             super::parse("{{ self::function(\"123\", 3) }}", &Syntax::default()).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                Expr::PathCall(
+            vec![super::Node::Expr(
+                super::WS(false, false),
+                super::Expr::PathCall(
                     vec!["self", "function"],
-                    vec![Expr::StrLit("123"), Expr::NumLit("3")],
+                    vec![super::Expr::StrLit("123"), super::Expr::NumLit("3")],
                 ),
             )],
         );
     }
 
-    #[test]
-    fn test_parse_root_path() {
-        let syntax = Syntax::default();
-        assert_eq!(
-            super::parse("{{ std::string::String::new() }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                Expr::PathCall(vec!["std", "string", "String", "new"], vec![]),
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ ::std::string::String::new() }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                Expr::PathCall(vec!["", "std", "string", "String", "new"], vec![]),
-            )],
-        );
-    }
-
     #[test]
     fn change_delimiters_parse_filter() {
         let syntax = Syntax {
@@ -1165,152 +1152,6 @@ mod tests {
 
         super::parse("{~ strvar|e ~}", &syntax).unwrap();
     }
-
-    #[test]
-    fn test_precedence() {
-        use Expr::*;
-        let syntax = Syntax::default();
-        assert_eq!(
-            super::parse("{{ a + b == c }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "==",
-                    BinOp("+", Var("a").into(), Var("b").into()).into(),
-                    Var("c").into(),
-                )
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ a + b * c - d / e }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "-",
-                    BinOp(
-                        "+",
-                        Var("a").into(),
-                        BinOp("*", Var("b").into(), Var("c").into()).into(),
-                    )
-                    .into(),
-                    BinOp("/", Var("d").into(), Var("e").into()).into(),
-                )
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ a * (b + c) / -d }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "/",
-                    BinOp(
-                        "*",
-                        Var("a").into(),
-                        Group(BinOp("+", Var("b").into(), Var("c").into()).into()).into()
-                    )
-                    .into(),
-                    Unary("-", Var("d").into()).into()
-                )
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ a || b && c || d && e }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "||",
-                    BinOp(
-                        "||",
-                        Var("a").into(),
-                        BinOp("&&", Var("b").into(), Var("c").into()).into(),
-                    )
-                    .into(),
-                    BinOp("&&", Var("d").into(), Var("e").into()).into(),
-                )
-            )],
-        );
-    }
-
-    #[test]
-    fn test_associativity() {
-        use Expr::*;
-        let syntax = Syntax::default();
-        assert_eq!(
-            super::parse("{{ a + b + c }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "+",
-                    BinOp("+", Var("a").into(), Var("b").into()).into(),
-                    Var("c").into()
-                )
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ a * b * c }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "*",
-                    BinOp("*", Var("a").into(), Var("b").into()).into(),
-                    Var("c").into()
-                )
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ a && b && c }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "&&",
-                    BinOp("&&", Var("a").into(), Var("b").into()).into(),
-                    Var("c").into()
-                )
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ a + b - c + d }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "+",
-                    BinOp(
-                        "-",
-                        BinOp("+", Var("a").into(), Var("b").into()).into(),
-                        Var("c").into()
-                    )
-                    .into(),
-                    Var("d").into()
-                )
-            )],
-        );
-        assert_eq!(
-            super::parse("{{ a == b != c > d > e == f }}", &syntax).unwrap(),
-            vec![Node::Expr(
-                WS(false, false),
-                BinOp(
-                    "==",
-                    BinOp(
-                        ">",
-                        BinOp(
-                            ">",
-                            BinOp(
-                                "!=",
-                                BinOp("==", Var("a").into(), Var("b").into()).into(),
-                                Var("c").into()
-                            )
-                            .into(),
-                            Var("d").into()
-                        )
-                        .into(),
-                        Var("e").into()
-                    )
-                    .into(),
-                    Var("f").into()
-                )
-            )],
-        );
-    }
 }
 
 type ParserError<'a, T> = Result<(&'a [u8], T), nom::Err<nom::error::Error<&'a [u8]>>>;
diff --git a/book/src/filters.md b/book/src/filters.md
index 47fafdb..25fbbe1 100644
--- a/book/src/filters.md
+++ b/book/src/filters.md
@@ -258,7 +258,7 @@ fn main() {
 
 ## The `json` filter
 
-Enabling the `serde-json` feature will enable the use of the `json` filter.
+Enabling the `serde-json` filter will enable the use of the `json` filter.
 This will output formatted JSON for any value that implements the required
 `Serialize` trait.
 
@@ -271,7 +271,7 @@ This will output formatted JSON for any value that implements the required
 
 ## The `yaml` filter
 
-Enabling the `serde-yaml` feature will enable the use of the `yaml` filter.
+Enabling the `serde-yaml` filter will enable the use of the `yaml` filter.
 This will output formatted JSON for any value that implements the required
 `Serialize` trait.
 


Test patch:
diff --git a/testing/templates/if-coerce.html b/testing/templates/if-coerce.html
deleted file mode 100644
index e32c2fe..0000000
--- a/testing/templates/if-coerce.html
+++ /dev/null
@@ -1,51 +0,0 @@
-{% macro foo(b) -%}
-    {% if b %}t{% else %}f{% endif -%}
-{% endmacro -%}
-
-{% macro bar(b) -%}
-    {%- call foo(b) -%}
-{% endmacro -%}
-
-{% macro baz(b) -%}
-    {%- call bar(b) -%}
-{% endmacro -%}
-
-{% macro qux(b) -%}
-    {%- call baz(b) -%}
-{% endmacro -%}
-
-{%- call foo(false) -%}
-{%- call bar(true) -%}
-{%- call baz(false) -%}
-{%- call qux(true) -%}
-
-{%- call qux(true && false) -%}
-{%- call qux(false || true) -%}
-
-{%- call qux(self.t) -%}
-{%- call qux(self.f) -%}
-{%- call qux(self.f || self.t) -%}
-
-{%- if false -%}
-if
-{%- else if false || true -%}
-elseif
-{%- else -%}
-else
-{%- endif -%}
-
-{%- if true && false -%}
-if
-{%- else if false -%}
-elseif
-{%- else -%}
-else
-{%- endif -%}
-
-{%- if false || true -%}
-if
-{%- else if (true && false) -%}
-elseif
-{%- else -%}
-else
-{%- endif -%}
diff --git a/testing/templates/macro-short-circuit.html b/testing/templates/macro-short-circuit.html
deleted file mode 100644
index 4a19b86..0000000
--- a/testing/templates/macro-short-circuit.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% macro foo(b) -%}
-    {{ b }}
-{%- endmacro -%}
-{% call foo(true) -%}
-{% call foo(true && true) -%}
-{% call foo(true && true && true) -%}
-{% call foo(false) -%}
-{% call foo(false || true) -%}
-{% call foo(false || false || true) -%}
diff --git a/testing/tests/coerce.rs b/testing/tests/coerce.rs
deleted file mode 100644
index 1a44781..0000000
--- a/testing/tests/coerce.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use askama::Template;
-
-#[derive(Template)]
-#[template(path = "if-coerce.html")]
-struct IfCoerceTemplate {
-    t: bool,
-    f: bool,
-}
-
-#[test]
-fn test_coerce() {
-    let t = IfCoerceTemplate { t: true, f: false };
-    assert_eq!(t.render().unwrap(), "ftftfttftelseifelseif");
-}
diff --git a/testing/tests/gen_ws_tests.py b/testing/tests/gen_ws_tests.py
deleted file mode 100644
index c2e24cb..0000000
--- a/testing/tests/gen_ws_tests.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from itertools import product, chain, zip_longest, tee
-
-
-# The amount of branches to generate
-BRANCHES = 2 # branches
-
-IF, ELSE_IF, ELSE, END_IF = 0, 1, 2, 3
-
-NL = "\\n"
-dash = lambda ws: [" ", "-"][ws]
-
-
-def trim(s, ws):
-    if ws[0]:
-        s = s.lstrip()
-    if ws[1]:
-        s = s.rstrip()
-    return s
-
-
-def cond_kind(i, n):
-    i += 1
-    if i == 1:
-        return IF # if
-    elif (i == n) and (i > 1):
-        return ELSE # else
-    elif i > n:
-        return END_IF # endif
-    else:
-        return ELSE_IF # else if
-
-
-# From: https://docs.python.org/3/library/itertools.html#itertools-recipes
-def pairwise(iterable):
-    a, b = tee(iterable)
-    next(b, None)
-    return zip(a, b)
-
-
-def write_cond(conds, active_branch):
-    n = len(conds) - 1
-
-    lits = []
-    for i in range(1, n + 2 + 1):
-        ws1 = "\\n" * i
-        ws2 = "\\r\\n" * i
-        lits.append((ws1, str(i), ws2))
-
-    conds = list(conds)
-    for i, (pws, nws) in enumerate(conds):
-        kind = cond_kind(i, n)
-        b = str(i == active_branch).lower()
-        cond = [f"if {b}", f"else if {b}", "else", "endif"][kind]
-        cond = f"{{%{dash(pws)} {cond} {dash(nws)}%}}"
-        conds[i] = cond
-
-    it = map("".join, lits)
-    it = filter(None, chain.from_iterable(zip_longest(it, conds)))
-    code = "".join(it)
-
-    expected = f"{lits[0][0]}{lits[0][1]}"
-    for i, (cond, (before, after)) in enumerate(zip(conds, pairwise(lits))):
-        kind = cond_kind(i, n)
-        pws = cond.startswith("{%-")
-        nws = cond.endswith("-%}")
-
-        cond = i == active_branch
-        prev_cond = i == (active_branch + 1)
-
-        if prev_cond or (kind == IF):
-            expected += before[2] * (not pws)
-        if cond or (kind == END_IF):
-            expected += after[0] * (not nws)
-            expected += after[1]
-
-    # FIXME: Askama does not include whitespace before eof
-    # expected += lits[-1][2]
-
-    return code, expected
-
-
-def write_match(contents, arms, match_ws):
-    before, expr, after = contents
-    code = before
-
-    pws, nws = match_ws[0]
-    code += f"{{%{dash(pws)} match {expr} {dash(nws)}%}}"
-
-    for (arm, expr), (pws, nws) in zip(arms, match_ws[1:-1]):
-        code += f"{{%{dash(pws)} when {arm} {dash(nws)}%}}{expr}"
-
-    pws, nws = match_ws[-1]
-    code += f"{{%{dash(pws)} endmatch {dash(nws)}%}}"
-    code += after
-
-    return code
-
-
-def write_match_result(active_arm, contents, arms, match_ws):
-    before, expr, after = contents
-    expected = ""
-
-    expected += trim(before, (False, match_ws[0][0]))
-    expected += trim(arms[active_arm][1], (match_ws[1:][active_arm][1], match_ws[1:][active_arm+1][0]))
-    expected += trim(after, (match_ws[-1][1], False))
-    return expected
-
-
-def write_cond_tests(f):
-    f.write("""
-macro_rules! test_template {
-    ($source:literal, $rendered:expr) => {{
-        #[derive(Template)]
-        #[template(source = $source, ext = "txt")]
-        struct CondWS;
-
-        assert_eq!(CondWS.render().unwrap(), $rendered);
-    }};
-}
-
-#[rustfmt::skip]
-#[test]
-fn test_cond_ws() {
-""")
-
-    for branches in range(1, BRANCHES + 1):
-        for x in product([False, True], repeat=(branches+1)*2):
-            # it = iter(x)
-            # conds = list(zip(it, it))
-            conds = list(zip(x[::2], x[1::2]))
-
-            for i in range(branches):
-                code, expected = write_cond(conds, i)
-                f.write(f'    test_template!("{code}", "{expected}");\n')
-
-        if branches != BRANCHES:
-            f.write("\n")
-    f.write("}\n")
-
-
-def write_match_tests(f):
-    f.write("""
-#[rustfmt::skip]
-macro_rules! test_match {
-    ($source:literal, $some_rendered:expr, $none_rendered:expr) => {{
-        #[derive(Template)]
-        #[template(source = $source, ext = "txt")]
-        struct MatchWS {
-            item: Option<&'static str>,
-        }
-
-        assert_eq!(MatchWS { item: Some("foo") }.render().unwrap(), $some_rendered);
-        assert_eq!(MatchWS { item: None }.render().unwrap(), $none_rendered);
-    }};
-}
-
-#[rustfmt::skip]
-#[test]
-fn test_match_ws() {
-""")
-
-    contents = "before ", "item", "      after"
-    arms = [("Some with (item)", "  foo   "), ("None", "    bar     ")]
-
-    for x in product([False, True], repeat=len(arms)*2+1):
-        x = [False, False, *x, False]
-        arms_ws = list(zip(x[::2], x[1::2]))
-
-        code = write_match(contents, arms, arms_ws)
-        some_expected = write_match_result(0, contents, arms, arms_ws)
-        none_expected = write_match_result(1, contents, arms, arms_ws)
-
-        f.write(f'    test_match!("{code}", "{some_expected}", "{none_expected}");\n')
-
-    f.write("}\n")
-
-
-if __name__ == "__main__":
-    with open("ws.rs", "w") as f:
-        f.write("// This file is auto generated by gen_ws_tests.py\n\n")
-        f.write("use askama::Template;\n")
-        write_cond_tests(f)
-        write_match_tests(f)
diff --git a/testing/tests/macro.rs b/testing/tests/macro.rs
index 459b1e2..51fbcdc 100644
--- a/testing/tests/macro.rs
+++ b/testing/tests/macro.rs
@@ -43,13 +43,3 @@ fn test_deep_import() {
     let t = DeepImportTemplate;
     assert_eq!(t.render().unwrap(), "foo");
 }
-
-#[derive(Template)]
-#[template(path = "macro-short-circuit.html")]
-struct ShortCircuitTemplate {}
-
-#[test]
-fn test_short_circuit() {
-    let t = ShortCircuitTemplate {};
-    assert_eq!(t.render().unwrap(), "truetruetruefalsetruetrue");
-}
diff --git a/testing/tests/matches.rs b/testing/tests/matches.rs
index d75a6c4..811f3ce 100644
--- a/testing/tests/matches.rs
+++ b/testing/tests/matches.rs
@@ -17,19 +17,19 @@ struct MatchOptRefTemplate<'a> {
 #[test]
 fn test_match_option() {
     let s = MatchOptTemplate { item: Some("foo") };
-    assert_eq!(s.render().unwrap(), "\nFound literal foo\n");
+    assert_eq!(s.render().unwrap(), "\n\nFound literal foo\n");
 
     let s = MatchOptTemplate { item: Some("bar") };
-    assert_eq!(s.render().unwrap(), "\nFound bar\n");
+    assert_eq!(s.render().unwrap(), "\n\nFound bar\n");
 
     let s = MatchOptTemplate { item: None };
-    assert_eq!(s.render().unwrap(), "\nNot Found\n");
+    assert_eq!(s.render().unwrap(), "\n\nNot Found\n");
 }
 
 #[test]
 fn test_match_ref_deref() {
     let s = MatchOptRefTemplate { item: &Some("foo") };
-    assert_eq!(s.render().unwrap(), "\nFound literal foo\n");
+    assert_eq!(s.render().unwrap(), "\n\nFound literal foo\n");
 }
 
 #[derive(Template)]
@@ -41,10 +41,10 @@ struct MatchLitTemplate<'a> {
 #[test]
 fn test_match_literal() {
     let s = MatchLitTemplate { item: "bar" };
-    assert_eq!(s.render().unwrap(), "\nFound literal bar\n");
+    assert_eq!(s.render().unwrap(), "\n\nFound literal bar\n");
 
     let s = MatchLitTemplate { item: "qux" };
-    assert_eq!(s.render().unwrap(), "\nElse found qux\n");
+    assert_eq!(s.render().unwrap(), "\n\nElse found qux\n");
 }
 
 #[derive(Template)]
@@ -56,10 +56,10 @@ struct MatchLitCharTemplate {
 #[test]
 fn test_match_literal_char() {
     let s = MatchLitCharTemplate { item: 'b' };
-    assert_eq!(s.render().unwrap(), "\nFound literal b\n");
+    assert_eq!(s.render().unwrap(), "\n\nFound literal b\n");
 
     let s = MatchLitCharTemplate { item: 'c' };
-    assert_eq!(s.render().unwrap(), "\nElse found c\n");
+    assert_eq!(s.render().unwrap(), "\n\nElse found c\n");
 }
 
 #[derive(Template)]
@@ -71,10 +71,10 @@ struct MatchLitNumTemplate {
 #[test]
 fn test_match_literal_num() {
     let s = MatchLitNumTemplate { item: 42 };
-    assert_eq!(s.render().unwrap(), "\nFound answer to everything\n");
+    assert_eq!(s.render().unwrap(), "\n\nFound answer to everything\n");
 
     let s = MatchLitNumTemplate { item: 23 };
-    assert_eq!(s.render().unwrap(), "\nElse found 23\n");
+    assert_eq!(s.render().unwrap(), "\n\nElse found 23\n");
 }
 
 #[allow(dead_code)]
@@ -99,7 +99,7 @@ fn test_match_custom_enum() {
             b: 255,
         },
     };
-    assert_eq!(s.render().unwrap(), "\nColorful: #A000FF\n");
+    assert_eq!(s.render().unwrap(), "\n\nColorful: #A000FF\n");
 }
 
 #[derive(Template)]
diff --git a/testing/tests/operators.rs b/testing/tests/operators.rs
index 05c1dab..99a2a4c 100644
--- a/testing/tests/operators.rs
+++ b/testing/tests/operators.rs
@@ -53,13 +53,3 @@ fn test_ranges() {
     };
     assert_eq!(t.render().unwrap(), "abcd\nbcd\n\na\nab");
 }
-
-#[derive(Template)]
-#[template(source = "{{ true && true }}{{ false || true }}", ext = "txt")]
-struct ShortCircuitTemplate {}
-
-#[test]
-fn test_short_circuit() {
-    let t = ShortCircuitTemplate {};
-    assert_eq!(t.render().unwrap(), "truetrue");
-}
diff --git a/testing/tests/simple.rs b/testing/tests/simple.rs
index 5ef03b1..7241005 100644
--- a/testing/tests/simple.rs
+++ b/testing/tests/simple.rs
@@ -290,15 +290,6 @@ fn test_path_func_call() {
     assert_eq!(PathFunctionTemplate.render().unwrap(), "Hello, world4123!");
 }
 
-#[derive(Template)]
-#[template(source = "{{ ::std::string::ToString::to_string(123) }}", ext = "txt")]
-struct RootPathFunctionTemplate;
-
-#[test]
-fn test_root_path_func_call() {
-    assert_eq!(RootPathFunctionTemplate.render().unwrap(), "123");
-}
-
 #[derive(Template)]
 #[template(source = "Hello, {{ Self::world3(self, \"123\", 4) }}!", ext = "txt")]
 struct FunctionTemplate;
diff --git a/testing/tests/whitespace.rs b/testing/tests/whitespace.rs
index ca72b23..93c601e 100644
--- a/testing/tests/whitespace.rs
+++ b/testing/tests/whitespace.rs
@@ -37,5 +37,5 @@ fn test_extra_whitespace() {
     let mut template = AllowWhitespaces::default();
     template.nested_1.nested_2.array = &["a0", "a1", "a2", "a3"];
     template.nested_1.nested_2.hash.insert("key", "value");
-    assert_eq!(template.render().unwrap(), "\n0\n0\n0\n0\n\n\n\n0\n0\n0\n0\n0\n\na0\na1\nvalue\n\n\n\n\n\n[\n  \"a0\",\n  \"a1\",\n  \"a2\",\n  \"a3\"\n]\n[\n  \"a0\",\n  \"a1\",\n  \"a2\",\n  \"a3\"\n][\n  \"a0\",\n  \"a1\",\n  \"a2\",\n  \"a3\"\n]\n[\n  \"a1\"\n][\n  \"a1\"\n]\n[\n  \"a1\",\n  \"a2\"\n][\n  \"a1\",\n  \"a2\"\n]\n[\n  \"a1\"\n][\n  \"a1\"\n]1-1-1\n3333 3\n2222 2\n0000 0\n3333 3\n\ntruefalse\nfalsefalsefalse\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+    assert_eq!(template.render().unwrap(), "\n0\n0\n0\n0\n\n\n\n0\n0\n0\n0\n0\n\na0\na1\nvalue\n\n\n\n\n\n[\n  \"a0\",\n  \"a1\",\n  \"a2\",\n  \"a3\"\n]\n[\n  \"a0\",\n  \"a1\",\n  \"a2\",\n  \"a3\"\n][\n  \"a0\",\n  \"a1\",\n  \"a2\",\n  \"a3\"\n]\n[\n  \"a1\"\n][\n  \"a1\"\n]\n[\n  \"a1\",\n  \"a2\"\n][\n  \"a1\",\n  \"a2\"\n]\n[\n  \"a1\"\n][\n  \"a1\"\n]1-1-1\n3333 3\n2222 2\n0000 0\n3333 3\n\ntruefalse\nfalsefalsefalse\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
 }
diff --git a/testing/tests/ws.rs b/testing/tests/ws.rs
deleted file mode 100644
index 3f62da5..0000000
--- a/testing/tests/ws.rs
+++ /dev/null
@@ -1,214 +0,0 @@
-// This file is auto generated by gen_ws_tests.py
-
-use askama::Template;
-
-macro_rules! test_template {
-    ($source:literal, $rendered:expr) => {{
-        #[derive(Template)]
-        #[template(source = $source, ext = "txt")]
-        struct CondWS;
-
-        assert_eq!(CondWS.render().unwrap(), $rendered);
-    }};
-}
-
-#[rustfmt::skip]
-#[test]
-fn test_cond_ws() {
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  endif  %}\n\n\n3\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n\n\n\n3");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  endif -%}\n\n\n3\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n3");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- endif  %}\n\n\n3\r\n\r\n\r\n", "\n1\r\n\n\n2\n\n\n3");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- endif -%}\n\n\n3\r\n\r\n\r\n", "\n1\r\n\n\n23");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  endif  %}\n\n\n3\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n\n\n\n3");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  endif -%}\n\n\n3\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n3");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- endif  %}\n\n\n3\r\n\r\n\r\n", "\n1\r\n2\n\n\n3");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- endif -%}\n\n\n3\r\n\r\n\r\n", "\n1\r\n23");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  endif  %}\n\n\n3\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n\n\n\n3");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  endif -%}\n\n\n3\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n3");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- endif  %}\n\n\n3\r\n\r\n\r\n", "\n1\n\n2\n\n\n3");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- endif -%}\n\n\n3\r\n\r\n\r\n", "\n1\n\n23");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  endif  %}\n\n\n3\r\n\r\n\r\n", "\n12\r\n\r\n\n\n\n3");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  endif -%}\n\n\n3\r\n\r\n\r\n", "\n12\r\n\r\n3");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- endif  %}\n\n\n3\r\n\r\n\r\n", "\n12\n\n\n3");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- endif -%}\n\n\n3\r\n\r\n\r\n", "\n123");
-
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n34");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n34");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n24");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n24");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n34");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n24");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n24");
-    test_template!("\n1\r\n{%  if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n34");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n34");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n34");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n24");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n24");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n\n\n\n34");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n24");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%  if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n24");
-    test_template!("\n1\r\n{%  if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\r\n34");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n34");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n134");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n24");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n24");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n34");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n24");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n2\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n24");
-    test_template!("\n1\r\n{%- if false  %}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n134");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n34");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\r\n\r\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%  else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n134");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n124");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n3\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n124");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else  %}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n1\n\n\n34");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n124");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%  endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\r\n\r\n\r\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n12\n\n\n\n4");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif  %}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n13\n\n\n\n4");
-    test_template!("\n1\r\n{%- if true -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n124");
-    test_template!("\n1\r\n{%- if false -%}\n\n2\r\n\r\n{%- else -%}\n\n\n3\r\n\r\n\r\n{%- endif -%}\n\n\n\n4\r\n\r\n\r\n\r\n", "\n134");
-}
-
-#[rustfmt::skip]
-macro_rules! test_match {
-    ($source:literal, $some_rendered:expr, $none_rendered:expr) => {{
-        #[derive(Template)]
-        #[template(source = $source, ext = "txt")]
-        struct MatchWS {
-            item: Option<&'static str>,
-        }
-
-        assert_eq!(MatchWS { item: Some("foo") }.render().unwrap(), $some_rendered);
-        assert_eq!(MatchWS { item: None }.render().unwrap(), $none_rendered);
-    }};
-}
-
-#[rustfmt::skip]
-#[test]
-fn test_match_ws() {
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%  when None  %}    bar     {%  endmatch  %}      after", "before   foo         after", "before     bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%  when None  %}    bar     {%- endmatch  %}      after", "before   foo         after", "before     bar      after");
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%  when None -%}    bar     {%  endmatch  %}      after", "before   foo         after", "before bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%  when None -%}    bar     {%- endmatch  %}      after", "before   foo         after", "before bar      after");
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%- when None  %}    bar     {%  endmatch  %}      after", "before   foo      after", "before     bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%- when None  %}    bar     {%- endmatch  %}      after", "before   foo      after", "before     bar      after");
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%- when None -%}    bar     {%  endmatch  %}      after", "before   foo      after", "before bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item)  %}  foo   {%- when None -%}    bar     {%- endmatch  %}      after", "before   foo      after", "before bar      after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%  when None  %}    bar     {%  endmatch  %}      after", "before foo         after", "before     bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%  when None  %}    bar     {%- endmatch  %}      after", "before foo         after", "before     bar      after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%  when None -%}    bar     {%  endmatch  %}      after", "before foo         after", "before bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%  when None -%}    bar     {%- endmatch  %}      after", "before foo         after", "before bar      after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%- when None  %}    bar     {%  endmatch  %}      after", "before foo      after", "before     bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%- when None  %}    bar     {%- endmatch  %}      after", "before foo      after", "before     bar      after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%- when None -%}    bar     {%  endmatch  %}      after", "before foo      after", "before bar           after");
-    test_match!("before {%  match item  %}{%  when Some with (item) -%}  foo   {%- when None -%}    bar     {%- endmatch  %}      after", "before foo      after", "before bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%  when None  %}    bar     {%  endmatch  %}      after", "before   foo         after", "before     bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%  when None  %}    bar     {%- endmatch  %}      after", "before   foo         after", "before     bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%  when None -%}    bar     {%  endmatch  %}      after", "before   foo         after", "before bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%  when None -%}    bar     {%- endmatch  %}      after", "before   foo         after", "before bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%- when None  %}    bar     {%  endmatch  %}      after", "before   foo      after", "before     bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%- when None  %}    bar     {%- endmatch  %}      after", "before   foo      after", "before     bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%- when None -%}    bar     {%  endmatch  %}      after", "before   foo      after", "before bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item)  %}  foo   {%- when None -%}    bar     {%- endmatch  %}      after", "before   foo      after", "before bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%  when None  %}    bar     {%  endmatch  %}      after", "before foo         after", "before     bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%  when None  %}    bar     {%- endmatch  %}      after", "before foo         after", "before     bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%  when None -%}    bar     {%  endmatch  %}      after", "before foo         after", "before bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%  when None -%}    bar     {%- endmatch  %}      after", "before foo         after", "before bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%- when None  %}    bar     {%  endmatch  %}      after", "before foo      after", "before     bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%- when None  %}    bar     {%- endmatch  %}      after", "before foo      after", "before     bar      after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%- when None -%}    bar     {%  endmatch  %}      after", "before foo      after", "before bar           after");
-    test_match!("before {%  match item  %}{%- when Some with (item) -%}  foo   {%- when None -%}    bar     {%- endmatch  %}      after", "before foo      after", "before bar      after");
-}