shabang
shabang

Reputation: 170

Displaying a link in a Twig temple

It seems easy, but I encounter a weird behavior.

In a twig file :

{% set my_html = '<a href="#">Hello world</a>' %}
{{- true is not same as(false) ? (true is same as(false) ? ('1'~my_html)|raw : ('2'~my_html)|raw) -}}

The printed part is ('2'~my_html)|raw and it works fine : I see a real link.

Output is :

2Hello world

Now, it works only because I apply the raw filter to ('1'~my_html)... Try this :

{% set my_html = '<a href="#">Hello world</a>' %}
{{- true is not same as(false) ? (true is same as(false) ? ('1'~my_html) : ('2'~my_html)|raw) -}}

And it will display : 2<a href="#">Hello world</a>

I don't understand why I need to apply a filter on something else to get the expected result ? Is it a bug ?

Upvotes: 1

Views: 65

Answers (2)

Nima
Nima

Reputation: 3409

This is a documented behavior of the raw filter. I quote the note from that page:

Be careful when using the raw filter inside expressions:

{% autoescape %}
    {% set hello = '<strong>Hello</strong>' %}
    {% set hola = '<strong>Hola</strong>' %}

    {{ false ? '<strong>Hola</strong>' : hello|raw }}
    does not render the same as
    {{ false ? hola : hello|raw }}
    but renders the same as
    {{ (false ? hola : hello)|raw }} {% endautoescape %}

The first ternary statement is not escaped: hello is marked as being safe and Twig does not escape static values (see escape). In the second ternary statement, even if hello is marked as safe, hola remains unsafe and so is the whole expression. The third ternary statement is marked as safe and the result is not escaped.

And a comment on a github issue clarifies that the concatenation operator marks your string as unsafe. So in your case

{% set my_html = '<' %}
{#  ('1'~my_html) is not safe, so the whole expression is not #}
{{ false
    ? ('1'~my_html)
    : ('2'~my_html)|raw
}}

includes two strings: a safe one, ('2'~my_html)|raw) and an unsafe one, ('1'~my_html) (because it does not apply the raw filter), so as the note from raw documentation says, the whole expression stays unsafe and autoescaping is applied. But in the other case when both strings are marked safe, the whole expression becomes safe and the autoesaping is not applied:

{% set my_html = '<' %}
{# now both strings are safe, so is the whole expression #}
{{ false
    ? ('1'~my_html)|raw
    : ('2'~my_html)|raw
}}

Upvotes: 1

DarkBee
DarkBee

Reputation: 15625

This is not a bug but, due to the fact the default settings of twig will autoescape variables.
You can read more about it in the documentation.

Upvotes: 0

Related Questions