feature #2872 Add spaceless filter (fabpot)

This PR was squashed before being merged into the 1.x branch (closes #2872).

Discussion
----------

Add spaceless filter

Commits
-------

a22a5c4b fixed CS
743767bc re-implemented the spaceless tag to reuse the filter tag logic
b823898e added a spaceless filter
1ba79416 removed unneeded usage of spaceless in tests
This commit is contained in:
Fabien Potencier
2019-03-07 10:24:21 +01:00
9 changed files with 97 additions and 7 deletions
+1
View File
@@ -1,5 +1,6 @@
* 1.38.0 (2019-XX-XX)
* added a spaceless filter
* added max value to the "random" function
* made namespace classes the default classes (PSR-0 ones are aliases now)
* removed duplicated directory separator in FilesystemLoader
+54
View File
@@ -0,0 +1,54 @@
``spaceless``
=============
.. versionadded:: 1.38
The ``spaceless`` filter was added in Twig 1.38.
Use the ``spaceless`` filter to remove whitespace *between HTML tags*, not
whitespace within HTML tags or whitespace in plain text:
.. code-block:: jinja
{{
"<div>
<strong>foo</strong>
</div>
"|spaceless }}
{# output will be <div><strong>foo</strong></div> #}
You can combine ``spaceless`` with the ``filter`` tag to apply the
transformation on large amounts of HTML:
.. code-block:: jinja
{% filter spaceless %}
<div>
<strong>foo</strong>
</div>
{% endfilter %}
{# output will be <div><strong>foo</strong></div> #}
This tag is not meant to "optimize" the size of the generated HTML content but
merely to avoid extra whitespace between HTML tags to avoid browser rendering
quirks under some circumstances.
.. tip::
If you want to optimize the size of the generated HTML content, gzip
compress the output instead.
.. tip::
If you want to create a tag that actually removes all extra whitespace in
an HTML string, be warned that this is not as easy as it seems to be
(think of ``textarea`` or ``pre`` tags for instance). Using a third-party
library like Tidy is probably a better idea.
.. tip::
For more information on whitespace control, read the
:ref:`dedicated section <templates-whitespace-control>` of the documentation and learn how
you can also use the whitespace control modifier on your tags.
+4
View File
@@ -1,6 +1,10 @@
``spaceless``
=============
.. tip::
As of Twig 1.38, use the :doc:`spaceless <../filters/spaceless>` filter instead.
Use the ``spaceless`` tag to remove whitespace *between HTML tags*, not
whitespace within HTML tags or whitespace in plain text:
+12
View File
@@ -184,6 +184,7 @@ class CoreExtension extends AbstractExtension
new TwigFilter('striptags', 'strip_tags'),
new TwigFilter('trim', 'twig_trim_filter'),
new TwigFilter('nl2br', 'nl2br', ['pre_escape' => 'html', 'is_safe' => ['html']]),
new TwigFilter('spaceless', 'twig_spaceless', ['is_safe' => ['html']]),
// array helpers
new TwigFilter('join', 'twig_join_filter'),
@@ -357,6 +358,7 @@ function twig_random(Environment $env, $values = null, $max = null)
$min = $values;
$max = $max;
}
return mt_rand($min, $max);
}
@@ -988,6 +990,16 @@ function twig_trim_filter($string, $characterMask = null, $side = 'both')
}
}
/**
* Removes whitespaces between HTML tags.
*
* @return string
*/
function twig_spaceless($content)
{
return preg_replace('/>\s+</', '><', $content);
}
/**
* Escapes a string.
*
+2
View File
@@ -18,6 +18,8 @@ use Twig\Compiler;
*
* It removes spaces between HTML tags.
*
* @internal Not used anymore, to be removed in 3.0
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class SpacelessNode extends Node
+16 -3
View File
@@ -11,7 +11,10 @@
namespace Twig\TokenParser;
use Twig\Node\SpacelessNode;
use Twig\Node\BlockNode;
use Twig\Node\Expression\BlockReferenceExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\PrintNode;
use Twig\Token;
/**
@@ -30,13 +33,23 @@ class SpacelessTokenParser extends AbstractTokenParser
{
public function parse(Token $token)
{
$lineno = $token->getLine();
$this->parser->getStream()->injectTokens([
new Token(Token::NAME_TYPE, 'spaceless', $token->getLine()),
]);
$name = $this->parser->getVarName();
$ref = new BlockReferenceExpression(new ConstantExpression($name, $token->getLine()), null, $token->getLine(), $this->getTag());
$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
$body = $this->parser->subparse([$this, 'decideSpacelessEnd'], true);
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
return new SpacelessNode($body, $lineno, $this->getTag());
$block = new BlockNode($name, $body, $token->getLine());
$this->parser->setBlock($name, $block);
return new PrintNode($filter, $token->getLine(), $this->getTag());
}
public function decideSpacelessEnd(Token $token)
@@ -0,0 +1,8 @@
--TEST--
"spaceless" filter
--TEMPLATE--
{{ " <div> <div> foo </div> </div>"|spaceless }}
--DATA--
return []
--EXPECT--
<div><div> foo </div></div>
@@ -8,7 +8,6 @@ block_expr
{{- parent() -}}
{% endblock %}
--TEMPLATE(base.twig)--
{% spaceless %}
{% block element -%}
<div>
{%- if item.children is defined %}
@@ -18,7 +17,6 @@ block_expr
{%- endif -%}
</div>
{%- endblock %}
{% endspaceless %}
--DATA--
return [
'item' => [
@@ -10,7 +10,6 @@ block_expr2
--TEMPLATE(base2.twig)--
{% extends "base.twig" %}
--TEMPLATE(base.twig)--
{% spaceless %}
{% block element -%}
<div>
{%- if item.children is defined %}
@@ -20,7 +19,6 @@ block_expr2
{%- endif -%}
</div>
{%- endblock %}
{% endspaceless %}
--DATA--
return [
'item' => [