Shopify/liquid — pull request #217 by csfrancis (2013-06-27 02:10:48+00:00)
Title: Strip unnecessary whitespace from for tags

## Problem

When rendering liquid templates, excessive whitespace can be generated within `for` tags, even when there is no actual output being generated by the tag. For example:

{% for tag in product.tags %}
{% assign firstbit = tag | split: '-' | first %}
{% unless firstbit == 'related' %}
{% capture mostRecentTagHTML %}{{ tag }}, {% endcapture %}
{% capture tagsHTML %}{{ tagsHTML }}{{ mostRecentTagHTML }}{% endcapture %}
{% endunless %}
{% endfor %}

The preceding liquid code is parsed into the following nodes:

["\n ",
#,
@markup="firstbit = tag | split: '-' | first ",
@tag_name="assign",
@to="firstbit">,
"\n ",
#],
@markup="firstbit == 'related' ",
@nodelist=
["\n ",
#,
"\">",
#,
", "],
@tag_name="capture",
@to="mostRecentTagHTML">,
"\n ",
#,
#],
@tag_name="capture",
@to="tagsHTML">,
"\n "],
@tag_name="unless">,
"\n "]

In this `for` block there is no visible output generated. However, every iteration of the loop outputs the whitespace nodes that are part of the indented template code. With a large number of iterations, this can cause a large amount of unnecessary rendering as well as bloating the size of the rendered output.

## Solution

This attempts to reduce the amount of unnecessary whitespace that can be generated by a liquid template, while also maintaining backward compatibility with existing templates.

The `parse` method in the `for` tag recursively scans child nodes for any tags that could potentially render output. In the case that no output would be rendered (such as in the case of computing a value, for example), then the whitespace nodes will be removed from the node list.

This is not a perfect solution, but it should help to mitigate the excess whitespace that is generated by some templates.

Thoughts?

cc: @hornairs, @boourns, @fw42, @camilo, @dylanahsmith