djc / askama

Type-safe, compiled Jinja-like templates for Rust
Apache License 2.0
3.35k stars 215 forks source link

Compilation error when using nested template blocks with in a single template file #1022

Closed Stromdahl closed 3 months ago

Stromdahl commented 4 months ago

Hello! I Encountered a compilation error when using block fragments with Vec<&str> in a single template file. The error does not occur when the template is split into separate files.

This is working like expected

{% block index %}
Section 1: {{ s1 }}
{% endblock %}

{% block section %}
  Value ={{ value }}
{% endblock %}
use askama::Template;

#[derive(Template)]
#[template(path = "combain.txt", block="index")]
struct RenderInPlace<'a> {
   s1: Section<'a>
}

#[derive(Template)]
#[template(path = "combain.txt", block="section")]
struct Section<'a> {
   value: &'a str,
}
fn main() {
    let value = "x";

    let t = RenderInPlace { s1: Section { value } };
    println!("{}", t);
}
Section 1: 

  Value =x

When changing to Vec for the value i get a compilation error..

{% block index %}
Section 1: {{ s1 }}
{% endblock %}

{% block section %}
  {% for value in  values %}
    Value = {{ value }}
  {% endfor %}
{% endblock %}
use askama::Template;

#[derive(Template)]
#[template(path = "combain.txt", block="index")]
struct RenderInPlace<'a> {
   s1: Section<'a>
}

#[derive(Template)]
#[template(path = "combain.txt", block="section")]
struct Section<'a> {
   values: Vec<&'a str>,
}

fn main() {

    let values: Vec<&str>= vec!["a", "b", "c"];

    let t = RenderInPlace { s1: Section { values } };
    println!("{}", t);
}
error[E0609]: no field `value` on type `&Section<'a>`
 --> src/main.rs:9:10
  |
9 | #[derive(Template)]
  |          ^^^^^^^^ unknown field
  |
  = note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)

However when i split the template file in two it is working as expected. index.html

{% block index %}
Section 1: {{ s1 }}
{% endblock %}

section.html

{% block section %}
  {% for value in  values %}
    Value ={{ value }}
  {% endfor %}
{% endblock %}
use askama::Template;

#[derive(Template)]
#[template(path = "index.txt", block="index")]
struct RenderInPlace<'a> {
   s1: Section<'a>
}

#[derive(Template)]
#[template(path = "section.txt", block="section")]
struct Section<'a> {
   values: Vec<&'a str>,
}

fn main() {

    let values: Vec<&str>= vec!["a", "b", "c"];

    let t = RenderInPlace { s1: Section { values } };
    println!("{}", t);
}
Section 1: 

    Value =a

    Value =b

    Value =c
GuillaumeGomez commented 4 months ago

I had the same issue, investigating what's going on.

wrapperup commented 4 months ago

Ah, it's a bad assumption in the implementation. With my usage, it worked fine, but it still processes all the child nodes of any block, while discarding only writable things. So this means any nodes like the loop tag still gets parsed and generated.

GuillaumeGomez commented 4 months ago

I'm curious to see how you fixed it. The WritableBuffer needs to handle discard too (which I added) and you need to switch this status accordingly. However the handle of whitespace characters becomes tricky. ^^'