askama icon indicating copy to clipboard operation
askama copied to clipboard

Template node structs & whitespace semantics

Open couchand opened this issue 1 year ago • 1 comments

This is the first set of changes extracted from #782.

These changes focus on clarifying the semantics of the whitespace of each Node. This PR refrains from abstracting out the common whitespace-handling patterns that emerge here, leaving that for a follow-on PR.

We make the following changes here:

  • Adding Node variant parsing tests
  • (Mostly) consistently using one struct per Node variant
  • Clarifying the semantics of each and every Ws value (though since the whitespace patterns aren't yet abstracted this clarification is still incomplete)

There should be no visible effects of these changes, they are purely distilling towards greater insight. As described in the comments to #782, the general goal is to differentiate between the "inner" whitespace (within nested blocks) and the "outer" whitespace (around every node except lit).

Outer whitespace is the first field of each non-Lit variant of Node. Inner whitespace is on each nested-block-type node, stored alongside the Vec<Node> value that represents the nested block. For instance, for the template

{%- if test +%}FooBar{%+ endif -%}

Would result in the Rust value

Node::Cond(
    Ws(Some(Whitespace::Suppress), Some(Whitespace::Suppress)),
    vec![
        Cond {
            test: CondTest {
                target: None,
                expr: Expr::Var("test"),
            },
            block: vec![Node::Lit("FooBar")],
            ws: Ws(Some(Whitespace::Preserve), Some(Whitespace::Preserve)),
        }
    ]
)

Thanks for your review, your time and effort are appreciated!

couchand avatar Jun 24 '23 03:06 couchand

#834 extracts a parser crate and improves the parser API a bunch.

djc avatar Jul 31 '23 08:07 djc