Twig
Twig copied to clipboard
Whitespace control - Trim left spaces
If an expression {{ }} or statement {% %} is directly followed by a linebreak, which is pretty often, it seems to be automatically removed.
For instance:
<tag>
{% set nothing = 42 %}
</tag>
would output:
<tag>
</tag>
and not:
<tag>
</tag>
If we extend this reasoning, wouldn't it make sense to also trim spaces at the left of the expression/statement, in the case there are only spaces at the start of the line? To illustrate, let's reuse previous example with indentation:
<tag>
{% set nothing = 42 %}
</tag>
It now outputs:
<tag>
</tag>
Currently, to maintain a good indentation, I always use a left space-only trim ~:
<tag>
{%~ set nothing = 42 %}
</tag>
The use of ~ being pretty much systematic, I think it would be fully legitimate to infer it when the left part of the current line contains only spaces. I would agree that deciding to remove left spaces would mean that we would force the removal of "information" that, in some case that I cannot think of at the moment, some might actually want to preserve. Then, once again, Twig already does something similar by implicitly removing some linebreaks.
Therefore, I think a more natural way to deduce removable content would be to arbitrate on the whole line: if only composed of spaces apart from the statement, the whole line would be trimmed, including the ending linebreak, otherwise none of it. Moreover, this rule makes sense on a statement or comment, but not so much on an expression, which is expected to output something.
Two last exemples:
<tag>{% for n in 0..3 %}
{{ n }}
{% endfor %}</tag>
outputs:
<tag> 0
1
2
3
</tag>
whilst I believe one could legitimately expect to obtain instead:
<tag>
0
1
2
3
</tag>
And:
<tag>{# Some comment #}
</tag>
outputs:
<tag></tag>
whilst we could expect instead:
<tag>
</tag>
To sum up, the idea is quite simple: if a whole line (including the finishing CR/LF) is only composed of spaces, comments and statements, it shouldn't be rendered. Otherwise, everything should be preserved (including the finishing CR/LF).
What do you think?
See https://twig.symfony.com/doc/3.x/templates.html#whitespace-control
See https://twig.symfony.com/doc/3.x/templates.html#whitespace-control
I have question about whitespace control related to this. My test scenario:
--TEST--
Test line ending
--TEMPLATE--
{# without modifiers #}
first line {% if 1 > 0 %}1{% endif %}
and second line on new line
first line {% if 1 > 0 %}2{% endif %}{# with comment at end line #}
and second line on new line
{# with triminig whitespace except newline #}
first line {%~ if 1 > 0 %}3{% endif ~%}
and second line on new line
{# with whitespace at end of line #}
first line {% if 1 > 0 %}4{% endif %}
and second line on new line
line before for
{% for i in range(1, 9) %}
{{- i -}}
{% endfor %}
new line after endfor
--DATA--
return []
--EXPECT--
first line 1
and second line on new line
first line 2
and second line on new line
first line 3
and second line on new line
first line 4
and second line on new line
line before for
123456789
new line after endfor
And output is
Test line ending (in whitespace/trim_line_ending.test)
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'first line 1\n
-and second line on new line\n
+'first line 1and second line on new line\n
\n
-first line 2\n
-and second line on new line\n
+first line 2and second line on new line\n
\n
-first line 3\n
+first line3\n
and second line on new line\n
\n
first line 4 \n
@@ @@
and second line on new line\n
\n
line before for\n
-123456789\n
-new line after endfor'
+123456789new line after endfor'
It not documented and lead to some kinds of errors. For example it can be dangerous in js:
var isFoo = {% if o.isFoo %}true{% else %}false{% endif %}
var isBar = true
and instead
var isFoo = true
var isBar = true
we got a wrong js-code
var isFoo = truevar isBar = true
I make demo on raw php and twig https://onlinephp.io/c/d6084 https://twigfiddle.com/9h6dsl
And twig already uses different approaches for removing line endings after output and execution tags. In php, removing line endings is useful for a few reasons. This was discussed on the mailing list in 1998 (25 years ago!) https://marc.info/?t=90279165800002&r=1&w=2
But why does this rule about deleting a newline after closing a tag exist in Twig?
It not documented and lead to some kinds of errors.
This is actually documented. It is the first sentence in the documentation section that I linked to you:
The first newline after a template tag is removed automatically (like in PHP).
This is actually documented. It is the first sentence in the documentation section that I linked to you:
Yes, sorry about that. Misunderstood the meaning and thought about the line ending at end of template.
But the question is still open:
Why is this principle from php is used in twig? And how is it possible to disable it globally?
you cannot disable it globally.