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

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

2 participants