The control of the white-space in a template is a problem that to some extent haunts every template engine in the business.
Let see this template. I have marked the components of template with colors: text, interpolation, FTL tag. With the [BR]-s I visualize the line breaks.
<p>List of users:[BR]
<#assign users = [{"name":"Joe", "hidden":false},[BR]
{"name":"James Bond", "hidden":true},[BR]
{"name":"Julia", "hidden":false}]>[BR]
<ul>[BR]
<#list users as user>[BR]
<#if !user.hidden>[BR]
<li>${user.name}[BR]
</#if>[BR]
</#list>[BR]
</ul>[BR]
<p>That's all.
If FreeMarker were to output all text as is, the output would be:
<p>List of users:[BR] [BR] <ul>[BR] [BR] [BR] <li>Joe[BR] [BR] [BR] [BR] [BR] [BR] <li>Julia[BR] [BR] [BR] </ul>[BR] <p>That's all.
You have a lot of unwanted spaces and line breaks here. Fortunately neither HTML nor XML is typically white-space sensitive, but this amount of superfluous white-space can be annoying, and needlessly increases the size of produced HTML. Of course, it is even bigger problem when outputting white-space-sensitive formats.
FreeMarker provides the following tools to cope with this problem:
-
Tools to ignore certain white-space of the template files (parse time white-space removal):
-
White-space stripping: This feature automatically ignores typical superfluous white-space around FTL tags. It can be enabled or disabled on per template manner.
-
Trimmer directives:
t
,rt
,lt
. With these directives you can explicitly tell FreeMarker to ignore certain white-space. Read the reference for more information. -
ftl
parameterstrip_text
: This removes all top-level text from the template. It is useful for templates that contain macro definitions only (and some other non-outputting directives), because it removes the line-breaks that you use between the macro definitions and between the other top-level directives to improve the readability of the template.
-
-
Tools that remove white-space from the output (on-the-fly white-space removal):
-
compress
directive.
-
White-space stripping
If this feature is enabled for a template, then it automatically ignores (i.e. does not print to the output) two kind of typical superfluous white-space:
-
Indentation white-space, and trailing white-space at the end of the line (includes the line break) will be ignored in lines that contains only FTL tags (e.g.
<@myMacro/>
,<#if ...>
) and/or FTL comments (e.g.<#-- blah -->
), apart from the the ignored white-space itself. For example, if a line contains only an<#if ...>
, then the indentation before the tag and the line break after the tag will be ignored. However, if the line contains<#if ...>x
, then the white-space in that line will not be ignored, because of thex
, as that is not FTL tag. Note that according these rules, a line that contains<#if ...><#list ...>
is subject to white-space ignoring, while a line that contains<#if ...> <#list ...>
is not, because the white-space between the two FTL tags is embedded white-space, not indentation or trailing white-space. -
White-space sandwiched between the following directives is ignored:
macro
,function
,assign
,global
,local
,ftl
,import
, but only if there is only white-space and/or FTL comments between the directives. In practice it means that you can put empty lines between macro definitions and assignments as spacing for better readability, without printing needless empty lines (line breaks) to the output.
The output of the last example with white-space stripping enabled will be:
<p>List of users:[BR] <ul>[BR] <li>Joe[BR] <li>Julia[BR] </ul>[BR] <p>That's all.
This is because after stripping the template becomes the following; the ignored text is not colored:
<p>List of users:[BR] <#assign users = [{"name":"Joe", "hidden":false},[BR] {"name":"James Bond", "hidden":true},[BR] {"name":"Julia", "hidden":false}]>[BR] <ul>[BR] <#list users as user>[BR] <#if !user.hidden>[BR] <li>${user.name}[BR] </#if>[BR] </#list>[BR] </ul>[BR] <p>That's all.
White-space stripping can be enabled/disabled in per template
manner with the ftl
directive.
If you don't specify this with the ftl
directive,
then white-space stripping will be enabled or disabled depending on
how the programmer has configured FreeMarker. The factory default is
white-space stripping enabled, and the programmers probably left it
so (recommended). Note that enabling white-space stripping does
not degrade the performance of template
execution; white-space stripping is done during template
loading.
White-space stripping can be disabled for a single line with
the nt
directive (for No Trim).
Using compress directive
Another solution is to use the compress
directive. As opposed to white-space stripping, this works
directly on the generated output, not on the template. That is, it
will investigate the printed output on the fly, and does not
investigate the FTL program that creates the output. It aggressively
removes indentations, empty lines and repeated spaces/tabs (for more
information read the reference). So the output
of:
<#compress> <#assign users = [{"name":"Joe", "hidden":false}, {"name":"James Bond", "hidden":true}, {"name":"Julia", "hidden":false}]> List of users: <#list users as user> <#if !user.hidden> - ${user.name} </#if> </#list> That's all. </#compress>
will be:
List of users: - Joe - Julia That's all.
Note that compress
is totally independent
of white-space stripping. So it is possible that the white-space of
template is stripped, and later the produced output is
compress
-ed.
Also, by default a user-defined directve called
compress
is available in the data-model (due to
backward compatibility). This is the same as the directive, except
that you may optionally set the single_line
parameter, which will remove all intervening line breaks. If you
replace
<#compress>...</#compress>
on the last example with <@compress
single_line=true>...</@compress>
,
then you get this output:
List of users: - Joe - Julia That's all.