1Twig for Template Designers
2===========================
3
4This document describes the syntax and semantics of the template engine and
5will be most useful as reference to those creating Twig templates.
6
7Synopsis
8--------
9
10A template is a regular text file. It can generate any text-based format (HTML,
11XML, CSV, LaTeX, etc.). It doesn't have a specific extension, ``.html`` or
12``.xml`` are just fine.
13
14A template contains **variables** or **expressions**, which get replaced with
15values when the template is evaluated, and **tags**, which control the
16template's logic.
17
18Below is a minimal template that illustrates a few basics. We will cover further
19details later on:
20
21.. code-block:: html+twig
22
23    <!DOCTYPE html>
24    <html>
25        <head>
26            <title>My Webpage</title>
27        </head>
28        <body>
29            <ul id="navigation">
30            {% for item in navigation %}
31                <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
32            {% endfor %}
33            </ul>
34
35            <h1>My Webpage</h1>
36            {{ a_variable }}
37        </body>
38    </html>
39
40There are two kinds of delimiters: ``{% ... %}`` and ``{{ ... }}``. The first
41one is used to execute statements such as for-loops, the latter outputs the
42result of an expression.
43
44IDEs Integration
45----------------
46
47Many IDEs support syntax highlighting and auto-completion for Twig:
48
49* *Textmate* via the `Twig bundle`_
50* *Vim* via the `Jinja syntax plugin`_ or the `vim-twig plugin`_
51* *Netbeans* via the `Twig syntax plugin`_ (until 7.1, native as of 7.2)
52* *PhpStorm* (native as of 2.1)
53* *Eclipse* via the `Twig plugin`_
54* *Sublime Text* via the `Twig bundle`_
55* *GtkSourceView* via the `Twig language definition`_ (used by gedit and other projects)
56* *Coda* and *SubEthaEdit* via the `Twig syntax mode`_
57* *Coda 2* via the `other Twig syntax mode`_
58* *Komodo* and *Komodo Edit* via the Twig highlight/syntax check mode
59* *Notepad++* via the `Notepad++ Twig Highlighter`_
60* *Emacs* via `web-mode.el`_
61* *Atom* via the `PHP-twig for atom`_
62* *Visual Studio Code* via the `Twig pack`_
63
64Also, `TwigFiddle`_ is an online service that allows you to execute Twig templates
65from a browser; it supports all versions of Twig.
66
67Variables
68---------
69
70The application passes variables to the templates for manipulation in the
71template. Variables may have attributes or elements you can access, too. The
72visual representation of a variable depends heavily on the application providing
73it.
74
75Use a dot (``.``) to access attributes of a variable (methods or properties of a
76PHP object, or items of a PHP array):
77
78.. code-block:: twig
79
80    {{ foo.bar }}
81
82.. note::
83
84    It's important to know that the curly braces are *not* part of the
85    variable but the print statement. When accessing variables inside tags,
86    don't put the braces around them.
87
88.. sidebar:: Implementation
89
90    For convenience's sake ``foo.bar`` does the following things on the PHP
91    layer:
92
93    * check if ``foo`` is an array and ``bar`` a valid element;
94    * if not, and if ``foo`` is an object, check that ``bar`` is a valid property;
95    * if not, and if ``foo`` is an object, check that ``bar`` is a valid method
96      (even if ``bar`` is the constructor - use ``__construct()`` instead);
97    * if not, and if ``foo`` is an object, check that ``getBar`` is a valid method;
98    * if not, and if ``foo`` is an object, check that ``isBar`` is a valid method;
99    * if not, and if ``foo`` is an object, check that ``hasBar`` is a valid method;
100    * if not, return a ``null`` value.
101
102    Twig also supports a specific syntax for accessing items on PHP arrays,
103    ``foo['bar']``:
104
105    * check if ``foo`` is an array and ``bar`` a valid element;
106    * if not, return a ``null`` value.
107
108If a variable or attribute does not exist, you will receive a ``null`` value
109when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables``
110is set, Twig will throw an error (see :ref:`environment options<environment_options>`).
111
112.. note::
113
114    If you want to access a dynamic attribute of a variable, use the
115    :doc:`attribute<functions/attribute>` function instead.
116
117    The ``attribute`` function is also useful when the attribute contains
118    special characters (like ``-`` that would be interpreted as the minus
119    operator):
120
121    .. code-block:: twig
122
123        {# equivalent to the non-working foo.data-foo #}
124        {{ attribute(foo, 'data-foo') }}
125
126Global Variables
127~~~~~~~~~~~~~~~~
128
129The following variables are always available in templates:
130
131* ``_self``: references the current template name;
132* ``_context``: references the current context;
133* ``_charset``: references the current charset.
134
135Setting Variables
136~~~~~~~~~~~~~~~~~
137
138You can assign values to variables inside code blocks. Assignments use the
139:doc:`set<tags/set>` tag:
140
141.. code-block:: twig
142
143    {% set foo = 'foo' %}
144    {% set foo = [1, 2] %}
145    {% set foo = {'foo': 'bar'} %}
146
147Filters
148-------
149
150Variables can be modified by **filters**. Filters are separated from the
151variable by a pipe symbol (``|``). Multiple filters can be chained. The output
152of one filter is applied to the next.
153
154The following example removes all HTML tags from the ``name`` and title-cases
155it:
156
157.. code-block:: twig
158
159    {{ name|striptags|title }}
160
161Filters that accept arguments have parentheses around the arguments. This
162example joins the elements of a list by commas:
163
164.. code-block:: twig
165
166    {{ list|join(', ') }}
167
168To apply a filter on a section of code, wrap it with the
169:doc:`apply<tags/apply>` tag:
170
171.. code-block:: twig
172
173    {% apply upper %}
174        This text becomes uppercase
175    {% endapply %}
176
177Go to the :doc:`filters<filters/index>` page to learn more about built-in
178filters.
179
180.. note::
181
182    The ``apply`` tag was introduced in Twig 2.9; use the ``filter`` tag with
183    previous versions.
184
185Functions
186---------
187
188Functions can be called to generate content. Functions are called by their
189name followed by parentheses (``()``) and may have arguments.
190
191For instance, the ``range`` function returns a list containing an arithmetic
192progression of integers:
193
194.. code-block:: twig
195
196    {% for i in range(0, 3) %}
197        {{ i }},
198    {% endfor %}
199
200Go to the :doc:`functions<functions/index>` page to learn more about the
201built-in functions.
202
203.. _named-arguments:
204
205Named Arguments
206---------------
207
208.. code-block:: twig
209
210    {% for i in range(low=1, high=10, step=2) %}
211        {{ i }},
212    {% endfor %}
213
214Using named arguments makes your templates more explicit about the meaning of
215the values you pass as arguments:
216
217.. code-block:: twig
218
219    {{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
220
221    {# versus #}
222
223    {{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}
224
225Named arguments also allow you to skip some arguments for which you don't want
226to change the default value:
227
228.. code-block:: twig
229
230    {# the first argument is the date format, which defaults to the global date format if null is passed #}
231    {{ "now"|date(null, "Europe/Paris") }}
232
233    {# or skip the format value by using a named argument for the time zone #}
234    {{ "now"|date(timezone="Europe/Paris") }}
235
236You can also use both positional and named arguments in one call, in which
237case positional arguments must always come before named arguments:
238
239.. code-block:: twig
240
241    {{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}
242
243.. tip::
244
245    Each function and filter documentation page has a section where the names
246    of all arguments are listed when supported.
247
248Control Structure
249-----------------
250
251A control structure refers to all those things that control the flow of a
252program - conditionals (i.e. ``if``/``elseif``/``else``), ``for``-loops, as
253well as things like blocks. Control structures appear inside ``{% ... %}``
254blocks.
255
256For example, to display a list of users provided in a variable called
257``users``, use the :doc:`for<tags/for>` tag:
258
259.. code-block:: html+twig
260
261    <h1>Members</h1>
262    <ul>
263        {% for user in users %}
264            <li>{{ user.username|e }}</li>
265        {% endfor %}
266    </ul>
267
268The :doc:`if<tags/if>` tag can be used to test an expression:
269
270.. code-block:: html+twig
271
272    {% if users|length > 0 %}
273        <ul>
274            {% for user in users %}
275                <li>{{ user.username|e }}</li>
276            {% endfor %}
277        </ul>
278    {% endif %}
279
280Go to the :doc:`tags<tags/index>` page to learn more about the built-in tags.
281
282Comments
283--------
284
285To comment-out part of a line in a template, use the comment syntax ``{# ...
286#}``. This is useful for debugging or to add information for other template
287designers or yourself:
288
289.. code-block:: twig
290
291    {# note: disabled template because we no longer use this
292        {% for user in users %}
293            ...
294        {% endfor %}
295    #}
296
297Including other Templates
298-------------------------
299
300The :doc:`include<functions/include>` function is useful to include a template
301and return the rendered content of that template into the current one:
302
303.. code-block:: twig
304
305    {{ include('sidebar.html') }}
306
307By default, included templates have access to the same context as the template
308which includes them. This means that any variable defined in the main template
309will be available in the included template too:
310
311.. code-block:: twig
312
313    {% for box in boxes %}
314        {{ include('render_box.html') }}
315    {% endfor %}
316
317The included template ``render_box.html`` is able to access the ``box`` variable.
318
319The name of the template depends on the template loader. For instance, the
320``\Twig\Loader\FilesystemLoader`` allows you to access other templates by giving the
321filename. You can access templates in subdirectories with a slash:
322
323.. code-block:: twig
324
325    {{ include('sections/articles/sidebar.html') }}
326
327This behavior depends on the application embedding Twig.
328
329Template Inheritance
330--------------------
331
332The most powerful part of Twig is template inheritance. Template inheritance
333allows you to build a base "skeleton" template that contains all the common
334elements of your site and defines **blocks** that child templates can
335override.
336
337It's easier to understand the concept by starting with an example.
338
339Let's define a base template, ``base.html``, which defines an HTML skeleton
340document that might be used for a two-column page:
341
342.. code-block:: html+twig
343
344    <!DOCTYPE html>
345    <html>
346        <head>
347            {% block head %}
348                <link rel="stylesheet" href="style.css"/>
349                <title>{% block title %}{% endblock %} - My Webpage</title>
350            {% endblock %}
351        </head>
352        <body>
353            <div id="content">{% block content %}{% endblock %}</div>
354            <div id="footer">
355                {% block footer %}
356                    &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>.
357                {% endblock %}
358            </div>
359        </body>
360    </html>
361
362In this example, the :doc:`block<tags/block>` tags define four blocks that
363child templates can fill in. All the ``block`` tag does is to tell the
364template engine that a child template may override those portions of the
365template.
366
367A child template might look like this:
368
369.. code-block:: html+twig
370
371    {% extends "base.html" %}
372
373    {% block title %}Index{% endblock %}
374    {% block head %}
375        {{ parent() }}
376        <style type="text/css">
377            .important { color: #336699; }
378        </style>
379    {% endblock %}
380    {% block content %}
381        <h1>Index</h1>
382        <p class="important">
383            Welcome to my awesome homepage.
384        </p>
385    {% endblock %}
386
387The :doc:`extends<tags/extends>` tag is the key here. It tells the template
388engine that this template "extends" another template. When the template system
389evaluates this template, first it locates the parent. The extends tag should
390be the first tag in the template.
391
392Note that since the child template doesn't define the ``footer`` block, the
393value from the parent template is used instead.
394
395It's possible to render the contents of the parent block by using the
396:doc:`parent<functions/parent>` function. This gives back the results of the
397parent block:
398
399.. code-block:: html+twig
400
401    {% block sidebar %}
402        <h3>Table Of Contents</h3>
403        ...
404        {{ parent() }}
405    {% endblock %}
406
407.. tip::
408
409    The documentation page for the :doc:`extends<tags/extends>` tag describes
410    more advanced features like block nesting, scope, dynamic inheritance, and
411    conditional inheritance.
412
413.. note::
414
415    Twig also supports multiple inheritance via "horizontal reuse" with the help
416    of the :doc:`use<tags/use>` tag.
417
418HTML Escaping
419-------------
420
421When generating HTML from templates, there's always a risk that a variable
422will include characters that affect the resulting HTML. There are two
423approaches: manually escaping each variable or automatically escaping
424everything by default.
425
426Twig supports both, automatic escaping is enabled by default.
427
428The automatic escaping strategy can be configured via the
429:ref:`autoescape<environment_options>` option and defaults to ``html``.
430
431Working with Manual Escaping
432~~~~~~~~~~~~~~~~~~~~~~~~~~~~
433
434If manual escaping is enabled, it is **your** responsibility to escape variables
435if needed. What to escape? Any variable that comes from an untrusted source.
436
437Escaping works by using the :doc:`escape<filters/escape>` or ``e`` filter:
438
439.. code-block:: twig
440
441    {{ user.username|e }}
442
443By default, the ``escape`` filter uses the ``html`` strategy, but depending on
444the escaping context, you might want to explicitly use an other strategy:
445
446.. code-block:: twig
447
448    {{ user.username|e('js') }}
449    {{ user.username|e('css') }}
450    {{ user.username|e('url') }}
451    {{ user.username|e('html_attr') }}
452
453Working with Automatic Escaping
454~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
455
456Whether automatic escaping is enabled or not, you can mark a section of a
457template to be escaped or not by using the :doc:`autoescape<tags/autoescape>`
458tag:
459
460.. code-block:: twig
461
462    {% autoescape %}
463        Everything will be automatically escaped in this block (using the HTML strategy)
464    {% endautoescape %}
465
466By default, auto-escaping uses the ``html`` escaping strategy. If you output
467variables in other contexts, you need to explicitly escape them with the
468appropriate escaping strategy:
469
470.. code-block:: twig
471
472    {% autoescape 'js' %}
473        Everything will be automatically escaped in this block (using the JS strategy)
474    {% endautoescape %}
475
476Escaping
477--------
478
479It is sometimes desirable or even necessary to have Twig ignore parts it would
480otherwise handle as variables or blocks. For example if the default syntax is
481used and you want to use ``{{`` as raw string in the template and not start a
482variable you have to use a trick.
483
484The easiest way is to output the variable delimiter (``{{``) by using a variable
485expression:
486
487.. code-block:: twig
488
489    {{ '{{' }}
490
491For bigger sections it makes sense to mark a block
492:doc:`verbatim<tags/verbatim>`.
493
494Macros
495------
496
497Macros are comparable with functions in regular programming languages. They are
498useful to reuse HTML fragments to not repeat yourself. They are described in the
499:doc:`macro<tags/macro>` tag documentation.
500
501.. _twig-expressions:
502
503Expressions
504-----------
505
506Twig allows expressions everywhere.
507
508.. note::
509
510    The operator precedence is as follows, with the lowest-precedence operators
511    listed first: ``?:`` (ternary operator), ``b-and``, ``b-xor``, ``b-or``,
512    ``or``, ``and``, ``==``, ``!=``, ``<=>``, ``<``, ``>``, ``>=``, ``<=``,
513    ``in``, ``matches``, ``starts with``, ``ends with``, ``..``, ``+``, ``-``,
514    ``~``, ``*``, ``/``, ``//``, ``%``, ``is`` (tests), ``**``, ``??``, ``|``
515    (filters), ``[]``, and ``.``:
516
517    .. code-block:: twig
518
519        {% set greeting = 'Hello ' %}
520        {% set name = 'Fabien' %}
521
522        {{ greeting ~ name|lower }}   {# Hello fabien #}
523
524        {# use parenthesis to change precedence #}
525        {{ (greeting ~ name)|lower }} {# hello fabien #}
526
527Literals
528~~~~~~~~
529
530The simplest form of expressions are literals. Literals are representations
531for PHP types such as strings, numbers, and arrays. The following literals
532exist:
533
534* ``"Hello World"``: Everything between two double or single quotes is a
535  string. They are useful whenever you need a string in the template (for
536  example as arguments to function calls, filters or just to extend or include
537  a template). A string can contain a delimiter if it is preceded by a
538  backslash (``\``) -- like in ``'It\'s good'``. If the string contains a
539  backslash (e.g. ``'c:\Program Files'``) escape it by doubling it
540  (e.g. ``'c:\\Program Files'``).
541
542* ``42`` / ``42.23``: Integers and floating point numbers are created by
543  writing the number down. If a dot is present the number is a float,
544  otherwise an integer.
545
546* ``["foo", "bar"]``: Arrays are defined by a sequence of expressions
547  separated by a comma (``,``) and wrapped with squared brackets (``[]``).
548
549* ``{"foo": "bar"}``: Hashes are defined by a list of keys and values
550  separated by a comma (``,``) and wrapped with curly braces (``{}``):
551
552  .. code-block:: twig
553
554    {# keys as string #}
555    { 'foo': 'foo', 'bar': 'bar' }
556
557    {# keys as names (equivalent to the previous hash) #}
558    { foo: 'foo', bar: 'bar' }
559
560    {# keys as integer #}
561    { 2: 'foo', 4: 'bar' }
562
563    {# keys can be omitted if it is the same as the variable name #}
564    { foo }
565    {# is equivalent to the following #}
566    { 'foo': foo }
567
568    {# keys as expressions (the expression must be enclosed into parentheses) #}
569    {% set foo = 'foo' %}
570    { (foo): 'foo', (1 + 1): 'bar', (foo ~ 'b'): 'baz' }
571
572* ``true`` / ``false``: ``true`` represents the true value, ``false``
573  represents the false value.
574
575* ``null``: ``null`` represents no specific value. This is the value returned
576  when a variable does not exist. ``none`` is an alias for ``null``.
577
578Arrays and hashes can be nested:
579
580.. code-block:: twig
581
582    {% set foo = [1, {"foo": "bar"}] %}
583
584.. tip::
585
586    Using double-quoted or single-quoted strings has no impact on performance
587    but :ref:`string interpolation <templates-string-interpolation>` is only
588    supported in double-quoted strings.
589
590Math
591~~~~
592
593Twig allows you to do math in templates; the following operators are supported:
594
595* ``+``: Adds two numbers together (the operands are casted to numbers). ``{{
596  1 + 1 }}`` is ``2``.
597
598* ``-``: Subtracts the second number from the first one. ``{{ 3 - 2 }}`` is
599  ``1``.
600
601* ``/``: Divides two numbers. The returned value will be a floating point
602  number. ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``.
603
604* ``%``: Calculates the remainder of an integer division. ``{{ 11 % 7 }}`` is
605  ``4``.
606
607* ``//``: Divides two numbers and returns the floored integer result. ``{{ 20
608  // 7 }}`` is ``2``, ``{{ -20  // 7 }}`` is ``-3`` (this is just syntactic
609  sugar for the :doc:`round<filters/round>` filter).
610
611* ``*``: Multiplies the left operand with the right one. ``{{ 2 * 2 }}`` would
612  return ``4``.
613
614* ``**``: Raises the left operand to the power of the right operand. ``{{ 2 **
615  3 }}`` would return ``8``.
616
617.. _template_logic:
618
619Logic
620~~~~~
621
622You can combine multiple expressions with the following operators:
623
624* ``and``: Returns true if the left and the right operands are both true.
625
626* ``or``: Returns true if the left or the right operand is true.
627
628* ``not``: Negates a statement.
629
630* ``(expr)``: Groups an expression.
631
632.. note::
633
634    Twig also supports bitwise operators (``b-and``, ``b-xor``, and ``b-or``).
635
636.. note::
637
638    Operators are case sensitive.
639
640Comparisons
641~~~~~~~~~~~
642
643The following comparison operators are supported in any expression: ``==``,
644``!=``, ``<``, ``>``, ``>=``, and ``<=``.
645
646You can also check if a string ``starts with`` or ``ends with`` another
647string:
648
649.. code-block:: twig
650
651    {% if 'Fabien' starts with 'F' %}
652    {% endif %}
653
654    {% if 'Fabien' ends with 'n' %}
655    {% endif %}
656
657.. note::
658
659    For complex string comparisons, the ``matches`` operator allows you to use
660    `regular expressions`_:
661
662    .. code-block:: twig
663
664        {% if phone matches '/^[\\d\\.]+$/' %}
665        {% endif %}
666
667Containment Operator
668~~~~~~~~~~~~~~~~~~~~
669
670The ``in`` operator performs containment test. It returns ``true`` if the left
671operand is contained in the right:
672
673.. code-block:: twig
674
675    {# returns true #}
676
677    {{ 1 in [1, 2, 3] }}
678
679    {{ 'cd' in 'abcde' }}
680
681.. tip::
682
683    You can use this filter to perform a containment test on strings, arrays,
684    or objects implementing the ``Traversable`` interface.
685
686To perform a negative test, use the ``not in`` operator:
687
688.. code-block:: twig
689
690    {% if 1 not in [1, 2, 3] %}
691
692    {# is equivalent to #}
693    {% if not (1 in [1, 2, 3]) %}
694
695Test Operator
696~~~~~~~~~~~~~
697
698The ``is`` operator performs tests. Tests can be used to test a variable against
699a common expression. The right operand is name of the test:
700
701.. code-block:: twig
702
703    {# find out if a variable is odd #}
704
705    {{ name is odd }}
706
707Tests can accept arguments too:
708
709.. code-block:: twig
710
711    {% if post.status is constant('Post::PUBLISHED') %}
712
713Tests can be negated by using the ``is not`` operator:
714
715.. code-block:: twig
716
717    {% if post.status is not constant('Post::PUBLISHED') %}
718
719    {# is equivalent to #}
720    {% if not (post.status is constant('Post::PUBLISHED')) %}
721
722Go to the :doc:`tests<tests/index>` page to learn more about the built-in
723tests.
724
725Other Operators
726~~~~~~~~~~~~~~~
727
728The following operators don't fit into any of the other categories:
729
730* ``|``: Applies a filter.
731
732* ``..``: Creates a sequence based on the operand before and after the operator
733  (this is syntactic sugar for the :doc:`range<functions/range>` function):
734
735  .. code-block:: twig
736
737      {{ 1..5 }}
738
739      {# equivalent to #}
740      {{ range(1, 5) }}
741
742  Note that you must use parentheses when combining it with the filter operator
743  due to the :ref:`operator precedence rules <twig-expressions>`:
744
745  .. code-block:: twig
746
747      (1..5)|join(', ')
748
749* ``~``: Converts all operands into strings and concatenates them. ``{{ "Hello
750  " ~ name ~ "!" }}`` would return (assuming ``name`` is ``'John'``) ``Hello
751  John!``.
752
753* ``.``, ``[]``: Gets an attribute of a variable.
754
755* ``?:``: The ternary operator:
756
757  .. code-block:: twig
758
759      {{ foo ? 'yes' : 'no' }}
760      {{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
761      {{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
762
763* ``??``: The null-coalescing operator:
764
765  .. code-block:: twig
766
767      {# returns the value of foo if it is defined and not null, 'no' otherwise #}
768      {{ foo ?? 'no' }}
769
770.. _templates-string-interpolation:
771
772String Interpolation
773~~~~~~~~~~~~~~~~~~~~
774
775String interpolation (``#{expression}``) allows any valid expression to appear
776within a *double-quoted string*. The result of evaluating that expression is
777inserted into the string:
778
779.. code-block:: twig
780
781    {{ "foo #{bar} baz" }}
782    {{ "foo #{1 + 2} baz" }}
783
784.. _templates-whitespace-control:
785
786Whitespace Control
787------------------
788
789.. versionadded:: 2.8
790
791    Tag level line whitespace control was added in Twig 2.8.
792
793The first newline after a template tag is removed automatically (like in PHP).
794Whitespace is not further modified by the template engine, so each whitespace
795(spaces, tabs, newlines etc.) is returned unchanged.
796
797You can also control whitespace on a per tag level. By using the whitespace
798control modifiers on your tags, you can trim leading and or trailing whitespace.
799
800Twig supports two modifiers:
801
802* *Whitespace trimming* via the ``-`` modifier: Removes all whitespace
803  (including newlines);
804
805* *Line whitespace trimming* via the ``~`` modifier: Removes all whitespace
806  (excluding newlines). Using this modifier on the right disables the default
807  removal of the first newline inherited from PHP.
808
809The modifiers can be used on either side of the tags like in ``{%-`` or ``-%}``
810and they consume all whitespace for that side of the tag. It is possible to use
811the modifiers on one side of a tag or on both sides:
812
813.. code-block:: html+twig
814
815    {% set value = 'no spaces' %}
816    {#- No leading/trailing whitespace -#}
817    {%- if true -%}
818        {{- value -}}
819    {%- endif -%}
820    {# output 'no spaces' #}
821
822    <li>
823        {{ value }}    </li>
824    {# outputs '<li>\n    no spaces    </li>' #}
825
826    <li>
827        {{- value }}    </li>
828    {# outputs '<li>no spaces    </li>' #}
829
830    <li>
831        {{~ value }}    </li>
832    {# outputs '<li>\nno spaces    </li>' #}
833
834.. tip::
835
836    In addition to the whitespace modifiers, Twig also has a ``spaceless`` filter
837    that removes whitespace **between HTML tags**:
838
839    .. code-block:: html+twig
840
841        {% apply spaceless %}
842            <div>
843                <strong>foo bar</strong>
844            </div>
845        {% endapply %}
846
847        {# output will be <div><strong>foo bar</strong></div> #}
848
849    The ``apply`` tag was introduced in Twig 2.9; use the ``filter`` tag with
850    previous versions.
851
852Extensions
853----------
854
855Twig can be extended. If you want to create your own extensions, read the
856:ref:`Creating an Extension <creating_extensions>` chapter.
857
858.. _`Twig bundle`:                https://github.com/Anomareh/PHP-Twig.tmbundle
859.. _`Jinja syntax plugin`:        http://jinja.pocoo.org/docs/integration/#vim
860.. _`vim-twig plugin`:            https://github.com/lumiliet/vim-twig
861.. _`Twig syntax plugin`:         http://plugins.netbeans.org/plugin/37069/php-twig
862.. _`Twig plugin`:                https://github.com/pulse00/Twig-Eclipse-Plugin
863.. _`Twig language definition`:   https://github.com/gabrielcorpse/gedit-twig-template-language
864.. _`Twig syntax mode`:           https://github.com/bobthecow/Twig-HTML.mode
865.. _`other Twig syntax mode`:     https://github.com/muxx/Twig-HTML.mode
866.. _`Notepad++ Twig Highlighter`: https://github.com/Banane9/notepadplusplus-twig
867.. _`web-mode.el`:                http://web-mode.org/
868.. _`regular expressions`:        https://secure.php.net/manual/en/pcre.pattern.php
869.. _`PHP-twig for atom`:          https://github.com/reesef/php-twig
870.. _`TwigFiddle`:                 https://twigfiddle.com/
871.. _`Twig pack`:                  https://marketplace.visualstudio.com/items?itemName=bajdzis.vscode-twig-pack
872