| <!doctype html> |
| <!-- Generated by FreeMarker/Docgen from DocBook --> |
| <html lang="en" class="page-type-section"> |
| <head prefix="og: http://ogp.me/ns#"> |
| <meta charset="utf-8"> |
| <title>White-space handling - Apache FreeMarker Manual</title> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <meta name="format-detection" content="telephone=no"> |
| <meta property="og:site_name" content="Apache FreeMarker Manual"> |
| <meta property="og:title" content="White-space handling"> |
| <meta property="og:locale" content="en_US"> |
| <meta property="og:url" content="https://freemarker.apache.org/docs/dgui_misc_whitespace.html"> |
| <link rel="canonical" href="https://freemarker.apache.org/docs/dgui_misc_whitespace.html"> |
| <link rel="icon" href="favicon.png" type="image/png"> |
| <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:500,700,400,300|Droid+Sans+Mono"> |
| <link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1707770044859"> |
| <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/cookie-bar/cookiebar-latest.min.js"></script> |
| </head> |
| <body itemscope itemtype="https://schema.org/Code"> |
| <meta itemprop="url" content="https://freemarker.apache.org/docs/"> |
| <meta itemprop="name" content="Apache FreeMarker Manual"> |
| |
| <!--[if lte IE 9]> |
| <div class="oldBrowserWarning" style="display: block"> |
| Unsupported web browser - Use a modern browser to view this website! |
| </div> |
| <![endif]--> <div class="oldBrowserWarning"> |
| Unsupported web browser - Use a modern browser to view this website! |
| </div> |
| <div class="header-top-bg"><div class="site-width header-top"><div id="hamburger-menu" role="button"></div> <div class="logo"> |
| <a href="https://freemarker.apache.org" role="banner"><img itemprop="image" src="logo.png" alt="FreeMarker"></a> </div> |
| <ul class="tabs"><li><a href="https://freemarker.apache.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="https://freemarker.apache.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://issues.apache.org/jira/projects/FREEMARKER" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="https://freemarker.apache.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">Manual</a><div class="navigation-header"></div><form method="get" class="search-form" action="search-results.html"><fieldset><legend class="sr-only">Search form</legend><label for="search-field" class="sr-only">Search query</label><input id="search-field" name="q" type="search" class="search-input" placeholder="Search" spellcheck="false" autocorrect="off" autocomplete="off"><button type="submit" class="search-btn"><span class="sr-only">Search</span></button></fieldset></form></div><div class="site-width breadcrumb-row"> <div class="breadcrumbs"> |
| <ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="index.html"><span itemprop="name">Apache FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="dgui.html"><span itemprop="name">Template Author's Guide</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="dgui_misc.html"><span itemprop="name">Miscellaneous</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="dgui_misc_whitespace.html"><span itemprop="name">White-space handling</span></a></li></ul> </div> |
| <div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div> <div class="main-content site-width"> |
| <div class="content-wrapper"> |
| <div id="table-of-contents-wrapper" class="col-left"> |
| <script>var breadcrumb = ["Apache FreeMarker Manual","Template Author\'s Guide","Miscellaneous","White-space handling"];</script> |
| <script src="toc.js?1707770044859"></script> |
| <script src="docgen-resources/main.min.js?1707770044859"></script> |
| </div> |
| <div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="dgui_misc_computer_vs_human_format.html"><span>Previous</span></a><a class="paging-arrow next" href="dgui_misc_alternativesyntax.html"><span>Next</span></a></div><div class="title-wrapper"> |
| <h1 class="content-header header-section1" id="dgui_misc_whitespace" itemprop="headline">White-space handling</h1> |
| </div></div><div class="page-menu"> |
| <div class="page-menu-title">Page Contents</div> |
| <ul><li><a class="page-menu-link" href="#dgui_misc_whitespace_stripping" data-menu-target="dgui_misc_whitespace_stripping">White-space stripping</a></li><li><a class="page-menu-link" href="#autoid_30" data-menu-target="autoid_30">Using compress directive</a></li></ul> </div><p>The control of the <a href="gloss.html#gloss.whiteSpace">white-space</a> in a template is a |
| problem that to some extent haunts every template engine in the |
| business.</p><p>Let see this template. I have marked the components of template |
| with colors: <span class="marked-text">text</span>, <span class="marked-interpolation">interpolation</span>, <span class="marked-ftl-tag">FTL tag</span>. With the <em><span class="marked-invisible-text">[BR]</span></em>-s I visualize the <a href="gloss.html#gloss.lineBreak">line breaks</a>.</p> |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><span class="marked-text"><p>List of users:<em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-ftl-tag"><#assign users = [{"name":"Joe", "hidden":false},<em><span class="marked-invisible-text">[BR]</span></em> |
| {"name":"James Bond", "hidden":true},<em><span class="marked-invisible-text">[BR]</span></em> |
| {"name":"Julia", "hidden":false}]></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <ul><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-ftl-tag"><#list users as user></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-ftl-tag"><#if !user.hidden></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <li><span class="marked-interpolation">${user.name}</span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-ftl-tag"></#if></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-ftl-tag"></#list></span><em><span class="marked-invisible-text">[BR]</span></em> |
| </ul><em><span class="marked-invisible-text">[BR]</span></em> |
| <p>That's all.</span></pre> </div> |
| <p>If FreeMarker were to output all <span class="marked-text">text</span> as is, the output would be:</p> |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body"><span class="marked-text"><p>List of users:<em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <ul><em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <li></span>Joe<span class="marked-text"><em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <li></span>Julia<span class="marked-text"><em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| <em><span class="marked-invisible-text">[BR]</span></em> |
| </ul><em><span class="marked-invisible-text">[BR]</span></em> |
| <p>That's all.</span></pre> </div> |
| <p>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.</p><p>FreeMarker provides the following tools to cope with this |
| problem:</p><ul> |
| <li> |
| <p>Tools to ignore certain white-space of the template files |
| <span class="marked-for-programmers">(parse time white-space |
| removal)</span>:</p> |
| |
| <ul> |
| <li> |
| <p>White-space stripping: This feature automatically |
| ignores typical superfluous white-space around FTL tags. It |
| can be enabled or disabled on per template manner.</p> |
| </li> |
| |
| <li> |
| <p>Trimmer directives: <code class="inline-code">t</code>, |
| <code class="inline-code">rt</code>, <code class="inline-code">lt</code>. With these |
| directives you can explicitly tell FreeMarker to ignore |
| certain white-space. Read <a href="ref_directive_t.html#ref.directive.t">the |
| reference</a> for more information.</p> |
| </li> |
| |
| <li> |
| <p><a href="ref_directive_ftl.html#ref.directive.ftl"><code>ftl</code></a> |
| parameter <code class="inline-code">strip_text</code>: 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.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>Tools that remove white-space from the output <span class="marked-for-programmers">(on-the-fly white-space |
| removal)</span>:</p> |
| |
| <ul> |
| <li> |
| <p><code class="inline-code">compress</code> directive.</p> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="dgui_misc_whitespace_stripping">White-space stripping</h2> |
| |
| |
| |
| |
| <p>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:</p> |
| |
| <ul> |
| <li> |
| <p>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. |
| <code class="inline-code"><@myMacro/></code>, <code class="inline-code"><#if |
| <em class="code-color">...</em>></code>) and/or FTL |
| comments (e.g. <code class="inline-code"><#-- blah --></code>), apart |
| from the the ignored white-space itself. For example, if a line |
| contains only an <code class="inline-code"><#if |
| <em class="code-color">...</em>></code>, then the |
| indentation before the tag and the line break after the tag will |
| be ignored. However, if the line contains <code class="inline-code"><#if |
| <em class="code-color">...</em>>x</code>, then the |
| white-space in that line will not be ignored, because of the |
| <code class="inline-code">x</code>, as that is not FTL tag. Note that |
| according these rules, a line that contains <code class="inline-code"><#if |
| <em class="code-color">...</em>><#list |
| <em class="code-color">...</em>></code> is subject to |
| white-space ignoring, while a line that contains |
| <code class="inline-code"><#if <em class="code-color">...</em>> <#list |
| <em class="code-color">...</em>></code> is not, because the |
| white-space between the two FTL tags is embedded white-space, |
| not indentation or trailing white-space.</p> |
| </li> |
| |
| <li> |
| <p>White-space sandwiched between the following directives is |
| ignored: <code class="inline-code">macro</code>, <code class="inline-code">function</code>, |
| <code class="inline-code">assign</code>, <code class="inline-code">global</code>, |
| <code class="inline-code">local</code>, <code class="inline-code">ftl</code>, |
| <code class="inline-code">import</code>, but only if there is |
| <em>only</em> 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.</p> |
| </li> |
| </ul> |
| |
| <p>The output of the last example with white-space stripping |
| enabled will be:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body"><span class="marked-text"><p>List of users:<em><span class="marked-invisible-text">[BR]</span></em> |
| <ul><em><span class="marked-invisible-text">[BR]</span></em> |
| <li></span>Joe<span class="marked-text"><em><span class="marked-invisible-text">[BR]</span></em> |
| <li></span>Julia<span class="marked-text"><em><span class="marked-invisible-text">[BR]</span></em> |
| </ul><em><span class="marked-invisible-text">[BR]</span></em> |
| <p>That's all.</span></pre> </div> |
| |
| |
| <p>This is because after stripping the template becomes the |
| following; the ignored text is not <span class="marked-text">colored</span>:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><span class="marked-text"><p>List of users:<em><span class="marked-invisible-text">[BR]</span></em></span> |
| <span class="marked-ftl-tag"><#assign users = [{"name":"Joe", "hidden":false},<em><span class="marked-invisible-text">[BR]</span></em> |
| {"name":"James Bond", "hidden":true},<em><span class="marked-invisible-text">[BR]</span></em> |
| {"name":"Julia", "hidden":false}]></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-text"><ul><em><span class="marked-invisible-text">[BR]</span></em></span> |
| <span class="marked-ftl-tag"><#list users as user></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-ftl-tag"><#if !user.hidden></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-text"> <li><span class="marked-interpolation">${user.name}</span><em><span class="marked-invisible-text">[BR]</span></em></span> |
| <span class="marked-ftl-tag"></#if></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-ftl-tag"></#list></span><em><span class="marked-invisible-text">[BR]</span></em> |
| <span class="marked-text"></ul><em><span class="marked-invisible-text">[BR]</span></em> |
| <p>That's all.</span></pre> </div> |
| |
| |
| <p>White-space stripping can be enabled/disabled in per template |
| manner with the <a href="ref_directive_ftl.html#ref.directive.ftl"><code>ftl</code> directive</a>. |
| If you don't specify this with the <code class="inline-code">ftl</code> 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 (<span class="marked-for-programmers">recommended</span>). <span class="marked-for-programmers">Note that enabling white-space stripping does |
| <em>not</em> degrade the performance of template |
| execution; white-space stripping is done during template |
| loading.</span></p> |
| |
| <p>White-space stripping can be disabled for a single line with |
| the <a href="ref_directive_nt.html#ref.directive.nt"><code>nt</code></a> |
| directive (for No Trim).</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_30">Using compress directive</h2> |
| |
| |
| |
| |
| <p>Another solution is to use the <a href="ref_directive_compress.html#ref.directive.compress"><code>compress</code> |
| directive</a>. 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 <a href="ref_directive_compress.html#ref.directive.compress">reference</a>). So the output |
| of:</p> |
| |
| |
| |
| <div class="code-block role-template"> |
| <div class="code-block-label">Template</div><pre class="code-block-body"><strong><#compress></strong> |
| <#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. |
| <strong></#compress></strong></pre> </div> |
| |
| |
| <p>will be:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">List of users: |
| - Joe |
| - Julia |
| That's all.</pre> </div> |
| |
| |
| <p>Note that <code class="inline-code">compress</code> 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 |
| <code class="inline-code">compress</code>-ed.</p> |
| |
| <p>Also, by default a user-defined directve called |
| <code class="inline-code">compress</code> is available in the data-model (due to |
| backward compatibility). This is the same as the directive, except |
| that you may optionally set the <code class="inline-code">single_line</code> |
| parameter, which will remove all intervening line breaks. If you |
| replace |
| <code class="inline-code"><#compress><em class="code-color">...</em></#compress></code> |
| on the last example with <code class="inline-code"><@compress |
| single_line=true><em class="code-color">...</em></@compress></code>, |
| then you get this output:</p> |
| |
| |
| |
| <div class="code-block role-output"> |
| <div class="code-block-label">Output</div><pre class="code-block-body">List of users: - Joe - Julia That's all.</pre> </div> |
| |
| <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="dgui_misc_computer_vs_human_format.html"><span>Previous</span></a><a class="paging-arrow next" href="dgui_misc_alternativesyntax.html"><span>Next</span></a></div></div></div></div> </div> |
| </div> |
| <div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="https://freemarker.apache.org/">What is FreeMarker?</a></li><li><a href="https://freemarker.apache.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="app_faq.html">FAQ</a></li><li><a itemprop="license" href="app_license.html">License</a></li><li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy policy</a></li></ul></div><div class="column"><h3 class="column-header">Often used / Reference</h3><ul><li><a href="https://try.freemarker.apache.org/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li><li><a href="api/freemarker/core/Configurable.html#setSetting-java.lang.String-java.lang.String-">Configuration settings</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/apache/freemarker">Github project page</a></li><li><a href="https://issues.apache.org/jira/projects/FREEMARKER">Report a bug</a></li><li><a href="https://freemarker.apache.org/report-security-vulnerabilities.html">Report security vulnerability</a></li><li><a href="https://stackoverflow.com/questions/ask?tags=freemarker">Get help on StackOverflow</a></li><li><a href="https://twitter.com/freemarker">Announcements on Twitter</a></li><li><a href="https://freemarker.apache.org/mailing-lists.html">Discuss on mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/apache/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="https://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"> <p class="last-generated"> |
| Last generated: |
| <time itemprop="dateModified" datetime="2024-02-12T20:34:04Z" title="Monday, February 12, 2024 at 8:34:04 PM Greenwich Mean Time">2024-02-12 20:34:04 GMT</time>, for Freemarker 2.3.32 </p> |
| <p class="copyright"> |
| © <span itemprop="copyrightYear">1999</span>–2024 |
| <a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a>. Apache FreeMarker, FreeMarker, Apache Incubator, Apache, the Apache FreeMarker logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. </p> |
| </div></div></div></body> |
| </html> |