Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: support {{if !myvariable}} #899

Open
schlichtanders opened this issue Oct 13, 2021 · 10 comments
Open

Feature Request: support {{if !myvariable}} #899

schlichtanders opened this issue Oct 13, 2021 · 10 comments

Comments

@schlichtanders
Copy link

it would be nice to have a simple way to negate an if statement.

Currently you have to write

{{if myvariable}} {{else}} ... {{end}} 

It would be nice to just write

{{if !myvariable}} ... {{end}}

My current Franklin.jl just stops working as soon as I try this

ERROR: Franklin.HTMLBlockError("I found a lonely {{end}}.")

using Franklin v0.10.59 and Julia 1.6.1

@tlienart
Copy link
Owner

Yes, there's a few issues open with this, for now indeed you have to go with your own custom stuff (eg defining your own hfun_check that takes two parameters the first one indicating whether it's !.

One reason behind this is that it quickly blows up to providing a full coding environment in moustaches which I think is undesirable (expands the surface a lot). In the wraps there's an option to pass a Julia code string that gets evaluated, in fact you could also do that now with hfun_eval and passing a quoted string then parsing it in the function (though not a one character change of course).

@schlichtanders
Copy link
Author

thank you for your explanation.

understood. I would say that for my case the {{ if }} {{ else }} ... {{ end }} version is the best and totally fine version.

In case you consider adding && and ||, then please ! too :).
It may make sense to summarize such tickets into a boolean-logic-support ticket

@tlienart
Copy link
Owner

the thought is to add this kind of stuff:

{{somefun e"""x && y"""}}

with the following intent: the e... gets parsed, the internal string gets evaluated in a sandbox, every symbol is assumed to be a page variable; the result of the evaluation assuming it's successful goes into a temporary variable that gets passed to somefun

So this would be equivalent to the following (here in a .md so that the var definition is in the same location for clarity):

+++
tmp = x && y
+++

{{somefun tmp}}

you could pass that to if blocks etc.

@schlichtanders
Copy link
Author

thank you.

If you would allow for such a e"""...""" syntax to make use of everything, why not directly supporting it, without an extra e"""...""" wrapping?

It should be the same amount of security and way more intuitive to use.

@tlienart
Copy link
Owner

It's not a question of security, it's a question of parsing. There needs to be a way for Franklin to know where are the boundaries of the function. And there needs to be a distinction with {{func """hello"""}} which passes the string "hello" to the function.

@schlichtanders
Copy link
Author

the distinction could be

{{somefun x && y}}

versus

{{somefun """x && y"""}}

however I think I now understand what you mean, because currently Franklin actually has a different semantics

{{somefun x}}

does not mean inserting the value of x, but passing "x" as the parameter name, i.e. interpreting it more like what would be

{{somefun "x"}}

in the context here

@tlienart
Copy link
Owner

tlienart commented Nov 4, 2021

@schlichtanders I've now implemented this in Xranklin (the in-dev next version) and it looks like this:

same as before:

{{whatever x y z}}  # same as before --> ["x", "y", "z"] passed to `hfun_whatever` to do what it wants with it
{{if x}} # same as before --> check 'get_local_var(:x)' if it evaluates to true run if block

new:

{{if e"$x && $y"}} --> checks 'get_local_var(:x) && get_local_var(:y)', if true run if block
{{whatever x e"foo($z)"}} --> passes ["x", "$(foo(get_local_var(:z)))"] to the hfun_whatever

note in the second case foo can be a standard Julia function or something defined in utils. For instance let's say it's defined in utils as foo(v) = v^2 and that there's a page variable z = 2 then the call above would pass ["x", "4"] to the hfun_whatever

so basically the new stuff are these "e-string" where you can specify some Julia logic and indicate what variables to get from the local environment using a $.

Any feedback on this?

@schlichtanders
Copy link
Author

@tlienart thank you for pinging - awesome to see that this is coming soon.

one feedback immediately popping into my mind: Not everything is nicely representable as a string.
If my function foo for whatever reason likes to return an array or struct, wouldn't it be nicer to just have

{{whatever x e"foo($z)"}} --> passes ["x", foo(get_local_var(:z))] to the hfun_whatever

@tlienart
Copy link
Owner

tlienart commented Nov 4, 2021

Yes I agree & this is actually just a matter of where things are interpreted; what actually gets passed is an array of string one of which is an "e-string", the hfun then does what it wants with it but most likely will just evaluate it and there it will be whatever value structure or whatever.

So I misrepresented this in my previous comment, it will in fact be similar to what you described

Thanks for the feedback!

@ndgnuh
Copy link

ndgnuh commented Jul 22, 2024

It's not a question of security, it's a question of parsing. There needs to be a way for Franklin to know where are the boundaries of the function. And there needs to be a distinction with {{func """hello"""}} which passes the string "hello" to the function.

I'm sorry if this is a dumb question. What if instead of e-string, we define pfun_*s (for predicates), which behave like hfun_ but returns Bool instead; and then we force the call like this?

<!-- with bool variables -->
{{ if my_boolean_var }} 
    <p>...</p>
{{ end }}

<!-- without arguments -->
{{ if my_condition() }} 
    <p>...</p>
{{ end }}

<!-- with arguments -->
{{ if my_condition(arg) }} 
    <p>...</p>
{{ end }}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants