From 1ba7941656d9623063d58daa1127c1efb244179e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2019 08:03:42 +0100 Subject: [PATCH 1/5] removed unneeded usage of spaceless in tests --- test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test | 2 -- test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test | 2 -- 2 files changed, 4 deletions(-) diff --git a/test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test b/test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test index b7bef6463..0b82d4cf2 100644 --- a/test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test +++ b/test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test @@ -8,7 +8,6 @@ block_expr {{- parent() -}} {% endblock %} --TEMPLATE(base.twig)-- -{% spaceless %} {% block element -%}
{%- if item.children is defined %} @@ -18,7 +17,6 @@ block_expr {%- endif -%}
{%- endblock %} -{% endspaceless %} --DATA-- return [ 'item' => [ diff --git a/test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test b/test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test index 2d22852a7..18f660411 100644 --- a/test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test +++ b/test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test @@ -10,7 +10,6 @@ block_expr2 --TEMPLATE(base2.twig)-- {% extends "base.twig" %} --TEMPLATE(base.twig)-- -{% spaceless %} {% block element -%}
{%- if item.children is defined %} @@ -20,7 +19,6 @@ block_expr2 {%- endif -%}
{%- endblock %} -{% endspaceless %} --DATA-- return [ 'item' => [ From b823898ee19f08bb7ac1d017b38bf157ffc6f1c1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2019 08:06:13 +0100 Subject: [PATCH 2/5] added a spaceless filter --- CHANGELOG | 1 + doc/filters/spaceless.rst | 54 +++++++++++++++++++ doc/tags/spaceless.rst | 4 ++ src/Extension/CoreExtension.php | 11 ++++ .../Tests/Fixtures/filters/spaceless.test | 8 +++ 5 files changed, 78 insertions(+) create mode 100644 doc/filters/spaceless.rst create mode 100644 test/Twig/Tests/Fixtures/filters/spaceless.test diff --git a/CHANGELOG b/CHANGELOG index 1cfa561fe..c8781b64f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff --git a/doc/filters/spaceless.rst b/doc/filters/spaceless.rst new file mode 100644 index 000000000..013124d25 --- /dev/null +++ b/doc/filters/spaceless.rst @@ -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 + + {{ + "
+ foo +
+ "|spaceless }} + + {# output will be
foo
#} + +You can combine ``spaceless`` with the ``filter`` tag to apply the +transformation on large amounts of HTML: + +.. code-block:: jinja + + {% filter spaceless %} +
+ foo +
+ {% endfilter %} + + {# output will be
foo
#} + +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 ` of the documentation and learn how + you can also use the whitespace control modifier on your tags. diff --git a/doc/tags/spaceless.rst b/doc/tags/spaceless.rst index b39cb27ef..14858243f 100644 --- a/doc/tags/spaceless.rst +++ b/doc/tags/spaceless.rst @@ -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: diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index ac886ffca..c7271746c 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -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'), @@ -988,6 +989,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. * diff --git a/test/Twig/Tests/Fixtures/filters/spaceless.test b/test/Twig/Tests/Fixtures/filters/spaceless.test new file mode 100644 index 000000000..eadc1d496 --- /dev/null +++ b/test/Twig/Tests/Fixtures/filters/spaceless.test @@ -0,0 +1,8 @@ +--TEST-- +"spaceless" filter +--TEMPLATE-- +{{ "
foo
"|spaceless }} +--DATA-- +return [] +--EXPECT-- +
foo
From 743767bce86e1d8b9a23c9a960c7abfda2f1717b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2019 10:16:11 +0100 Subject: [PATCH 3/5] re-implemented the spaceless tag to reuse the filter tag logic --- src/Node/SpacelessNode.php | 2 ++ src/TokenParser/SpacelessTokenParser.php | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Node/SpacelessNode.php b/src/Node/SpacelessNode.php index 9beebf32c..6d2b1958a 100644 --- a/src/Node/SpacelessNode.php +++ b/src/Node/SpacelessNode.php @@ -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 */ class SpacelessNode extends Node diff --git a/src/TokenParser/SpacelessTokenParser.php b/src/TokenParser/SpacelessTokenParser.php index 5b5656bc6..3c3de4390 100644 --- a/src/TokenParser/SpacelessTokenParser.php +++ b/src/TokenParser/SpacelessTokenParser.php @@ -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) From a22a5c4bd140d4f2344ed6ce20a5bed513ccb737 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2019 10:20:57 +0100 Subject: [PATCH 4/5] fixed CS --- src/Extension/CoreExtension.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index c7271746c..4c6c63d8c 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -358,6 +358,7 @@ function twig_random(Environment $env, $values = null, $max = null) $min = $values; $max = $max; } + return mt_rand($min, $max); } From 83efde6a4d8326ba8430727cbd8990d67a03a67d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2019 10:58:47 +0100 Subject: [PATCH 5/5] Revert "re-implemented the spaceless tag to reuse the filter tag logic" This reverts commit 743767bce86e1d8b9a23c9a960c7abfda2f1717b. --- src/Node/SpacelessNode.php | 2 -- src/TokenParser/SpacelessTokenParser.php | 19 +++---------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/Node/SpacelessNode.php b/src/Node/SpacelessNode.php index 6d2b1958a..9beebf32c 100644 --- a/src/Node/SpacelessNode.php +++ b/src/Node/SpacelessNode.php @@ -18,8 +18,6 @@ use Twig\Compiler; * * It removes spaces between HTML tags. * - * @internal Not used anymore, to be removed in 3.0 - * * @author Fabien Potencier */ class SpacelessNode extends Node diff --git a/src/TokenParser/SpacelessTokenParser.php b/src/TokenParser/SpacelessTokenParser.php index 3c3de4390..5b5656bc6 100644 --- a/src/TokenParser/SpacelessTokenParser.php +++ b/src/TokenParser/SpacelessTokenParser.php @@ -11,10 +11,7 @@ namespace Twig\TokenParser; -use Twig\Node\BlockNode; -use Twig\Node\Expression\BlockReferenceExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\PrintNode; +use Twig\Node\SpacelessNode; use Twig\Token; /** @@ -33,23 +30,13 @@ class SpacelessTokenParser extends AbstractTokenParser { public function parse(Token $token) { - $this->parser->getStream()->injectTokens([ - new Token(Token::NAME_TYPE, 'spaceless', $token->getLine()), - ]); + $lineno = $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); - $block = new BlockNode($name, $body, $token->getLine()); - $this->parser->setBlock($name, $block); - - return new PrintNode($filter, $token->getLine(), $this->getTag()); + return new SpacelessNode($body, $lineno, $this->getTag()); } public function decideSpacelessEnd(Token $token)