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