Skip to content

Whitespace control - Trim left spaces #3683

Open

Description

@brain-diminished

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?

Activity

  1. pudovmaxim commented on Apr 13, 2023

    @pudovmaxim

    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
    
  2. pudovmaxim commented on Apr 14, 2023

    @pudovmaxim

    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?

  3. stof commented on Apr 14, 2023

    @stof
    Member

    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).

  4. pudovmaxim commented on Apr 14, 2023

    @pudovmaxim

    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?

  5. stof commented on Apr 14, 2023

    @stof
    Member

    you cannot disable it globally.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions