mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-04 06:30:57 +00:00
added support for a new whitespace trimming option
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
* 1.39.0 (2019-XX-XX)
|
||||
|
||||
* n/a
|
||||
* added support for a new whitespace trimming option ({%~ ~%}, {{~ ~}}, {#~ ~#})
|
||||
|
||||
* 1.38.4 (2019-03-23)
|
||||
|
||||
|
||||
+39
-22
@@ -844,25 +844,28 @@ Whitespace Control
|
||||
.. versionadded:: 1.1
|
||||
Tag level whitespace control was added in Twig 1.1.
|
||||
|
||||
The first newline after a template tag is removed automatically (like in PHP.)
|
||||
.. versionadded:: 1.39
|
||||
Tag level Line whitespace control was added in Twig 1.39.
|
||||
|
||||
The first newline after a template tag is removed automatically (like in PHP).
|
||||
Whitespace is not further modified by the template engine, so each whitespace
|
||||
(spaces, tabs, newlines etc.) is returned unchanged.
|
||||
|
||||
Use the ``spaceless`` tag to remove whitespace *between HTML tags*:
|
||||
You can also control whitespace on a per tag level. By using the whitespace
|
||||
control modifiers on your tags, you can trim leading and or trailing whitespace.
|
||||
|
||||
.. code-block:: jinja
|
||||
Twig supports two modifiers:
|
||||
|
||||
{% spaceless %}
|
||||
<div>
|
||||
<strong>foo bar</strong>
|
||||
</div>
|
||||
{% endspaceless %}
|
||||
* *Whitespace trimming* via the ``-`` modifier: Removes all whitespace
|
||||
(including newlines);
|
||||
|
||||
{# output will be <div><strong>foo bar</strong></div> #}
|
||||
* *Line whitespace trimming* via the ``~`` modifier: Removes all whitespace
|
||||
(excluding newlines). Using this modifier on the right disables the default
|
||||
removal of the first newline inherited from PHP.
|
||||
|
||||
In addition to the spaceless tag you can also control whitespace on a per tag
|
||||
level. By using the whitespace control modifier on your tags, you can trim
|
||||
leading and or trailing whitespace:
|
||||
The modifiers can be used on either side of the tags like in ``{%-`` or ``-%}``
|
||||
and they consume all whitespace for that side of the tag. It is possible to use
|
||||
the modifiers on one side of a tag or on both sides:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
@@ -871,21 +874,35 @@ leading and or trailing whitespace:
|
||||
{%- if true -%}
|
||||
{{- value -}}
|
||||
{%- endif -%}
|
||||
|
||||
{# output 'no spaces' #}
|
||||
|
||||
The above sample shows the default whitespace control modifier, and how you can
|
||||
use it to remove whitespace around tags. Trimming space will consume all whitespace
|
||||
for that side of the tag. It is possible to use whitespace trimming on one side
|
||||
of a tag:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% set value = 'no spaces' %}
|
||||
<li> {{- value }} </li>
|
||||
<li>
|
||||
{{ value }} </li>
|
||||
{# outputs '<li>\n no spaces </li>' #}
|
||||
|
||||
<li>
|
||||
{{- value }} </li>
|
||||
{# outputs '<li>no spaces </li>' #}
|
||||
|
||||
<li>
|
||||
{{~ value }} </li>
|
||||
{# outputs '<li>\nno spaces </li>' #}
|
||||
|
||||
.. tip::
|
||||
|
||||
In addition to the whitespace modifiers, Twig also has a ``spaceless`` filter
|
||||
that removes whitespace **between HTML tags**:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% filter spaceless %}
|
||||
<div>
|
||||
<strong>foo bar</strong>
|
||||
</div>
|
||||
{% endfilter %}
|
||||
|
||||
{# output will be <div><strong>foo bar</strong></div> #}
|
||||
|
||||
Extensions
|
||||
----------
|
||||
|
||||
|
||||
+40
-8
@@ -62,6 +62,8 @@ class Lexer implements \Twig_LexerInterface
|
||||
'tag_block' => ['{%', '%}'],
|
||||
'tag_variable' => ['{{', '}}'],
|
||||
'whitespace_trim' => '-',
|
||||
'whitespace_line_trim' => '~',
|
||||
'whitespace_line_chars' => ' \t\0\x0B',
|
||||
'interpolation' => ['#{', '}'],
|
||||
], $options);
|
||||
|
||||
@@ -72,6 +74,8 @@ class Lexer implements \Twig_LexerInterface
|
||||
(?:'.
|
||||
preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1]).'\s*'. // -}}\s*
|
||||
'|'.
|
||||
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_variable'][1]).'['.$this->options['whitespace_line_chars'].']*'. // ~}}[ \t\0\x0B]*
|
||||
'|'.
|
||||
preg_quote($this->options['tag_variable'][1]). // }}
|
||||
')
|
||||
}Ax',
|
||||
@@ -82,22 +86,27 @@ class Lexer implements \Twig_LexerInterface
|
||||
(?:'.
|
||||
preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1]).'\s*\n?'. // -%}\s*\n?
|
||||
'|'.
|
||||
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1]).'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]*
|
||||
'|'.
|
||||
preg_quote($this->options['tag_block'][1]).'\n?'. // %}\n?
|
||||
')
|
||||
}Ax',
|
||||
|
||||
// {% endverbatim %}
|
||||
'lex_raw_data' => '{
|
||||
('.
|
||||
preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim']). // {%-
|
||||
'lex_raw_data' => '{'.
|
||||
preg_quote($this->options['tag_block'][0]). // {%
|
||||
'('.
|
||||
$this->options['whitespace_trim']. // -
|
||||
'|'.
|
||||
preg_quote($this->options['tag_block'][0]). // {%
|
||||
')\s*'.
|
||||
$this->options['whitespace_line_trim']. // ~
|
||||
')?\s*'.
|
||||
'(?:end%s)'. // endraw or endverbatim
|
||||
'\s*'.
|
||||
'(?:'.
|
||||
preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1]).'\s*'. // -%}
|
||||
'|'.
|
||||
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1]).'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]*
|
||||
'|'.
|
||||
preg_quote($this->options['tag_block'][1]). // %}
|
||||
')
|
||||
}sx',
|
||||
@@ -109,6 +118,8 @@ class Lexer implements \Twig_LexerInterface
|
||||
(?:'.
|
||||
preg_quote($this->options['whitespace_trim']).preg_quote($this->options['tag_comment'][1], '#').'\s*\n?'. // -#}\s*\n?
|
||||
'|'.
|
||||
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_comment'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~#}[ \t\0\x0B]*
|
||||
'|'.
|
||||
preg_quote($this->options['tag_comment'][1], '#').'\n?'. // #}\n?
|
||||
')
|
||||
}sx',
|
||||
@@ -121,6 +132,8 @@ class Lexer implements \Twig_LexerInterface
|
||||
(?:'.
|
||||
preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1]).'\s*'. // -%}\s*
|
||||
'|'.
|
||||
preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1]).'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]*
|
||||
'|'.
|
||||
preg_quote($this->options['tag_block'][1]). // %}
|
||||
')
|
||||
}Asx',
|
||||
@@ -137,6 +150,8 @@ class Lexer implements \Twig_LexerInterface
|
||||
preg_quote($this->options['tag_comment'][0], '#'). // {#
|
||||
')('.
|
||||
preg_quote($this->options['whitespace_trim']). // -
|
||||
'|'.
|
||||
preg_quote($this->options['whitespace_line_trim']). // ~
|
||||
')?
|
||||
}sx',
|
||||
'interpolation_start' => '{'.preg_quote($this->options['interpolation'][0]).'\s*}A',
|
||||
@@ -240,8 +255,17 @@ class Lexer implements \Twig_LexerInterface
|
||||
|
||||
// push the template text first
|
||||
$text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor);
|
||||
|
||||
// trim?
|
||||
if (isset($this->positions[2][$this->position][0])) {
|
||||
$text = rtrim($text);
|
||||
if ($this->options['whitespace_trim'] === $this->positions[2][$this->position][0]) {
|
||||
// whitespace_trim detected ({%-, {{- or {#-)
|
||||
$text = rtrim($text);
|
||||
} else {
|
||||
// whitespace_line_trim detected ({%~, {{~ or {#~)
|
||||
// don't trim \r and \n
|
||||
$text = rtrim($text, " \t\0\x0B");
|
||||
}
|
||||
}
|
||||
$this->pushToken(Token::TEXT_TYPE, $text);
|
||||
$this->moveCursor($textContent.$position[0]);
|
||||
@@ -378,8 +402,16 @@ class Lexer implements \Twig_LexerInterface
|
||||
$text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
|
||||
$this->moveCursor($text.$match[0][0]);
|
||||
|
||||
if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) {
|
||||
$text = rtrim($text);
|
||||
// trim?
|
||||
if (isset($match[1][0])) {
|
||||
if ($this->options['whitespace_trim'] === $match[1][0]) {
|
||||
// whitespace_trim detected ({%-, {{- or {#-)
|
||||
$text = rtrim($text);
|
||||
} else {
|
||||
// whitespace_line_trim detected ({%~, {{~ or {#~)
|
||||
// don't trim \r and \n
|
||||
$text = rtrim($text, " \t\0\x0B");
|
||||
}
|
||||
}
|
||||
|
||||
$this->pushToken(Token::TEXT_TYPE, $text);
|
||||
|
||||
-6
@@ -1,9 +1,6 @@
|
||||
--TEST--
|
||||
Whitespace trimming on tags.
|
||||
--TEMPLATE--
|
||||
{{ 5 * '{#-'|length }}
|
||||
{{ '{{-'|length * 5 + '{%-'|length }}
|
||||
|
||||
Trim on control tag:
|
||||
{% for i in range(1, 9) -%}
|
||||
{{ i }}
|
||||
@@ -53,9 +50,6 @@ end
|
||||
--DATA--
|
||||
return ['leading' => 'leading space', 'trailing' => 'trailing space', 'both' => 'both']
|
||||
--EXPECT--
|
||||
15
|
||||
18
|
||||
|
||||
Trim on control tag:
|
||||
123456789
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Whitespace trimming as strings.
|
||||
--TEMPLATE--
|
||||
{{ 5 * '{#-'|length }}
|
||||
{{ '{{-'|length * 5 + '{%-'|length }}
|
||||
--DATA--
|
||||
return []
|
||||
--EXPECT--
|
||||
15
|
||||
18
|
||||
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
Whitespace trimming on tags (left side).
|
||||
--TEMPLATE--
|
||||
**{% if true %}
|
||||
foo
|
||||
|
||||
{%- endif %}**
|
||||
|
||||
**
|
||||
|
||||
{{- 'foo' }}**
|
||||
|
||||
**
|
||||
|
||||
|
||||
{#- comment #}**
|
||||
|
||||
**{% verbatim %}
|
||||
foo
|
||||
|
||||
{%- endverbatim %}**
|
||||
--DATA--
|
||||
return []
|
||||
--EXPECT--
|
||||
**foo**
|
||||
|
||||
**foo**
|
||||
|
||||
****
|
||||
|
||||
**
|
||||
foo**
|
||||
@@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
Line whitespace trimming on tags (left side).
|
||||
--TEMPLATE--
|
||||
**{% if true %}
|
||||
foo
|
||||
{%~ endif %}**
|
||||
|
||||
**
|
||||
{{~ 'foo' }}**
|
||||
|
||||
**
|
||||
{#~ comment #}**
|
||||
|
||||
**{% verbatim %}
|
||||
foo
|
||||
|
||||
{%~ endverbatim %}**
|
||||
--DATA--
|
||||
return []
|
||||
--EXPECT--
|
||||
**foo
|
||||
**
|
||||
|
||||
**
|
||||
foo**
|
||||
|
||||
**
|
||||
**
|
||||
|
||||
**
|
||||
foo
|
||||
|
||||
**
|
||||
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
Line whitespace trimming on tags (right side).
|
||||
--TEMPLATE--
|
||||
**{% if true ~%}
|
||||
foo{% endif %}**
|
||||
|
||||
**{{ 'foo' ~}}
|
||||
foo
|
||||
**
|
||||
|
||||
**{# comment ~#}
|
||||
foo
|
||||
**
|
||||
|
||||
**{% verbatim ~%}
|
||||
foo{% endverbatim %}**
|
||||
--DATA--
|
||||
return []
|
||||
--EXPECT--
|
||||
**
|
||||
foo**
|
||||
|
||||
**foo
|
||||
foo
|
||||
**
|
||||
|
||||
**
|
||||
foo
|
||||
**
|
||||
|
||||
**
|
||||
foo**
|
||||
@@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
Whitespace trimming on tags (right side).
|
||||
--TEMPLATE--
|
||||
**{% if true -%}
|
||||
|
||||
foo{% endif %}**
|
||||
|
||||
**{{ 'foo' -}}
|
||||
|
||||
**
|
||||
|
||||
**{# comment -#}
|
||||
|
||||
**
|
||||
|
||||
**{% verbatim -%}
|
||||
|
||||
foo{% endverbatim %}**
|
||||
--DATA--
|
||||
return []
|
||||
--EXPECT--
|
||||
**foo**
|
||||
|
||||
**foo**
|
||||
|
||||
****
|
||||
|
||||
**foo**
|
||||
Reference in New Issue
Block a user