Skip to content
New issue

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

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

Already on GitHub? # to your account

Leading whitespace control doesn't strip newlines but trailing whitespace control does strip newlines #201

Open
brycelelbach opened this issue Jun 5, 2021 · 0 comments

Comments

@brycelelbach
Copy link
Contributor

brycelelbach commented Jun 5, 2021

Today:

  • Leading whitespace control (e.g. {{- }}, {{%- %}, {#- #}) only strips leading whitespaces until either a non-whitespace character, an Inja construct, or the start of the line, excluding any newline characters.
  • Trailing whitespace control (e.g. {{ -}}, {{% -%}, {# -#}) strips whitespace until either a non-whitespace character or Inja construct, including any newline characters.

This behavior is inconsistent and a bit surprising.

It would be nice if we had a form of that would only strip until it consumes one newline.

Imagine I have template code like this:

START

{% if exists("children") -%}
  {%- for child in children -%}
    {{- child }}
  {%- endfor -%}
{%- endif %}

END

If children doesn't exist, then I want no additional blank lines emitted - I just want the blank line after START and before END to be emitted. E.g. I want this output if children doesn't exist:

START


END

If I add leading whitespace stripping to the {% if ... -%}, it will not strip the blank line after START:

START

{%- if exists("children") -%}
  {%- for child in children -%}
    {{- child }}
  {%- endfor -%}
{%- endif %}

END

The above code will produce the following output, with three blank lines - the blank line after START (which I want), the blank line before END (which I want) and a blank line from the {%- endif %}.

START



END

But if I add trailing whitespace stripping to the {%- endif %}, it will eat the blank line before END!

START

{%- if exists("children") -%}
  {%- for child in children -%}
    {{- child }}
  {%- endfor -%}
{%- endif -%}

END

Producing this output with only one blank line, the blank line after START:

START

END

In fact, a trailing whitespace control will eat all whitespace until the next non-whitespace character. This is inconsistent with the behavior of a leading whitespace control, which will only eat whitespace until the previous newline. Presumably this is because lines before that have already been output and can't be trimmed.

Here's a full Godbolt example demonstrating the problem.

I can achieve what I want by deleting the newline before END and not using trailing whitespace control on the {%- endif %}, or by adding an empty comment or noop expression on the line before END, but this makes the template code more complicated and harder to read.

It would be better if either:

  1. We fixed trailing whitespace control to consume whitespace characters until the end of the line, including the newline.
  2. We don't change the semantics of the existing trailing whitespace control ({{ -}}, {{% -%}, {# -#}), but we add a new form of trailing whitespace control that only consumes whitespace characters until the end of the line, including the newline.

I think (1) is the cleaner solution, but it'll change existing semantics, and thus might break people's code. This isn't just cosmetic; in some cases, whitespace and blank lines are significant, such as in Markdown.

If we were to go the route of (2), I'd suggest a syntax like /.

   Syntax    Semantics
{{- }}
{%- %}
{#- #}
Strip whitespace characters before the Inja construct until either a non-whitespace character, an Inja construct, or the start of the line, excluding any newline characters. (Status Quo)
{{ -}}
{% -%}
{# -#}
Strip whitespace characters after the Inja construct until either a non-whitespace character or an Inja construct, including any newline characters. (Status Quo)
{{ /}}
{% /%}
{# /#}
Strip whitespace characters after the Inja construct until either a non-whitespace character, an Inja construct, or the start of the line, excluding any newline characters. (Proposed)
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

2 participants