djc / askama

Type-safe, compiled Jinja-like templates for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support endcall

alexandervantrijffel opened this issue · comments

It would be great if endcall is supported to close a call block. I'm using djlint for formatting html template files. Because endcall is not supported by Askama, the djlint formatter processes call tags as unclosed call blocks which leads to incorrect indenting in files.

Example:

image

When endcall tags are added the code is correctly indented by djlint:

image

But this is not supported by Askama:

image

Happy to review a PR for this, are you able to submit one?

Hm, our {% call %} does not work the same as the same statement in jinja. I guess it's too late to rename our keyword for calling a macro.

I wonder how {% endcall %} can be added without breaking things. We could simply make it an alias for an empty comment block. This would make it easy to suppress whitespaces around {%- endcall -%}, and we would not have to change anything in the generator.

For ensuring backwards compatibility, an approach could be:

Let the Call node scan nodes until it finds either an endcall tag, a call tag or until it reaches the end of the document. If another call tag is found or the end of the document is reached before encountering an endcall tag, treat this call node as an unclosed call block. If an endcall tag is found, it's a valid call block.

I've tried to implement this in node.rs but didn't figure it out yet as I am not familiar with nom.

At least I did write a test case for this, perhaps that helps.

Wouldn't it be fine to make a breaking change and update the crate version accordingly?

Wouldn't it be fine to make a breaking change and update the crate version accordingly?

Depends on the size of the breaking change... I don't want to break everyone unless there's a very good reason.

Hm, our {% call %} does not work the same as the same statement in jinja. I guess it's too late to rename our keyword for calling a macro.

Not entirely clear to me what they do -- they pass the content of the block to the macro as the first/last argument?

Generating a noop comment node for {% endcall %} seems like a reasonably low-complexity solution.

Not entirely clear to me what they do -- they pass the content of the block to the macro as the first/last argument?

The called macro can use {{ caller() }} to insert the content between {%call%} and {%endcall%} of the caller.

If a macro {% call(arg1) macro1() %} calls {{ call macro2() }}, then macro2 can pass an argument arg1 back to the body of macro1.

Pff, that seems like a lot of complexity that seems like a bad fit for Askama.

I ran into this as well (and imagine how happy I was to find djlint, which seems like the only tool that's semi-reasonably able to indent askama's syntax), and found the "ignore_blocks": "call" djlint directive, which I treats call blocks correctly, by letting djlint know that it's not a block that needs indentation.

Ignoring the call block is indeed a solution to my issue @antifuchs , thanks for sharing!

@maintainers feel free to close this issue if you like.