casid / jte

Secure and speedy templates for Java and Kotlin.
https://jte.gg
Apache License 2.0
830 stars 62 forks source link

Conditional Attributes #380

Open tschuehly opened 1 month ago

tschuehly commented 1 month ago

Currently I cannot use a @if conditional around a html attribute

<div @if(comment.parentComment() != null)
            x-init="$dispatch('${comment.parentComment().toString()}')"
        @endif
>

I get the following exception:

CommentComponent.jte, error at line 9: Illegal HTML attribute name @if(comment.parentComment()! @if expressions in HTML attribute names are not allowed. In case you're trying to optimize the generated output, smart attributes will do just that: https://jte.gg/html-rendering/#smart-attributes

I really would like to do that as I don't necessarily want to put my alpine.js code into my java code and instead put it into my template.

kelunik commented 1 month ago

If the attribute value is null, it will be omitted, hope that helps.

tschuehly commented 1 month ago

If the attribute value is null, it will be omitted, hope that helps.

Yes I know that but I would need to put the if else in a ternary operator which is uglier imo.

@casid If you think this is ok/possible I could take a crack at changing the behaviour. Or is there a certain reason why the behaviour is as it is?

casid commented 1 month ago

@tschuehly this is because jte by default only allows writing into safe slots of a template. The parser expects to find an attribute name within this div. This needs to be done in order to decide how to escape the attribute content, which is a safe slot to write to. Having logical expressions in here would let the complexity of the parser explode, and also make it impossible to guarantee properly escaped templates.

tschuehly commented 1 month ago

@tschuehly this is because jte by default only allows writing into safe slots of a template. The parser expects to find an attribute name within this div. This needs to be done in order to decide how to escape the attribute content, which is a safe slot to write to. Having logical expressions in here would let the complexity of the parser explode, and also make it impossible to guarantee properly escaped templates.

Is there a way to extend the parser? So I could write a plugin where I could implement that behaviour?

casid commented 1 month ago

No there is not. The parser is already quite complex and I fear opening this rabbit hole would make everything a lot harder to maintain, while the benefit to it is rather low. The risk on the other hand quite high, to accidentially introduce unsafe behavior or break user code.

leonard84 commented 1 week ago

How about using a special constant OMIT that would remove the attribute from the output if it is encountered? Similar to the poison pill pattern. Then you could write it like this.

<div x-init="comment.parentComment() == null ? OMIT : $dispatch('${comment.parentComment().toString()}')">

kelunik commented 1 week ago

This constant already exists: null