added the spaceless tag
authorFabien Potencier <fabien.potencier@gmail.com>
Fri, 19 Nov 2010 12:20:22 +0000 (13:20 +0100)
committerFabien Potencier <fabien.potencier@gmail.com>
Fri, 19 Nov 2010 12:26:23 +0000 (13:26 +0100)
CHANGELOG
doc/02-Twig-for-Template-Designers.markdown
lib/Twig/Extension/Core.php
lib/Twig/Node/Spaceless.php [new file with mode: 0644]
lib/Twig/TokenParser/Spaceless.php [new file with mode: 0644]
test/Twig/Tests/Fixtures/tags/spaceless/simple.test [new file with mode: 0644]
test/Twig/Tests/Node/SpacelessTest.php [new file with mode: 0644]

index 4401c17..02eae89 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,6 +13,7 @@ Backward incompatibilities:
    (the old behavior is still possible by adding the "only" keyword)
  * Moved Exceptions to Twig_Error_* (Twig_SyntaxError/Twig_RuntimeError are now Twig_Error_Syntax/Twig_Error_Runtime)
 
+ * added the spaceless tag
  * removed trim_blocks option
  * added support for is*() methods for attributes (foo.bar now looks for foo->getBar() or foo->isBar())
  * changed all exceptions to extend Twig_Error
index 341dee7..4a9d801 100644 (file)
@@ -170,6 +170,17 @@ 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:
+
+    [twig]
+    {% spaceless %}
+        <div>
+            <strong>foo</strong>
+        </div>
+    {% endspaceless %}
+
+    {# output will be <div><strong>foo</strong></div> #}
+
 Escaping
 --------
 
index c061c1f..84b45ff 100644 (file)
@@ -29,6 +29,7 @@ class Twig_Extension_Core extends Twig_Extension
             new Twig_TokenParser_Macro(),
             new Twig_TokenParser_Import(),
             new Twig_TokenParser_Set(),
+            new Twig_TokenParser_Spaceless(),
         );
     }
 
diff --git a/lib/Twig/Node/Spaceless.php b/lib/Twig/Node/Spaceless.php
new file mode 100644 (file)
index 0000000..c7fddda
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a spaceless node.
+ *
+ * It removes spaces between HTML tags.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class Twig_Node_Spaceless extends Twig_Node
+{
+    public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
+    {
+        parent::__construct(array('body' => $body), array(), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile($compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write("ob_start();\n")
+            ->subcompile($this->getNode('body'))
+            ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
+        ;
+    }
+}
diff --git a/lib/Twig/TokenParser/Spaceless.php b/lib/Twig/TokenParser/Spaceless.php
new file mode 100644 (file)
index 0000000..bd533c2
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_TokenParser_Spaceless extends Twig_TokenParser
+{
+    /**
+     * Parses a token and returns a node.
+     *
+     * @param Twig_Token $token A Twig_Token instance
+     *
+     * @return Twig_NodeInterface A Twig_NodeInterface instance
+     */
+    public function parse(Twig_Token $token)
+    {
+        $lineno = $token->getLine();
+
+        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $body = $this->parser->subparse(array($this, 'decideSpacelessEnd'), true);
+        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+
+        return new Twig_Node_Spaceless($body, $lineno, $this->getTag());
+    }
+
+    public function decideSpacelessEnd($token)
+    {
+        return $token->test('endspaceless');
+    }
+
+    /**
+     * Gets the tag name associated with this token parser.
+     *
+     * @param string The tag name
+     */
+    public function getTag()
+    {
+        return 'spaceless';
+    }
+}
diff --git a/test/Twig/Tests/Fixtures/tags/spaceless/simple.test b/test/Twig/Tests/Fixtures/tags/spaceless/simple.test
new file mode 100644 (file)
index 0000000..dd06dec
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+"spaceless" tag removes whites between HTML tags
+--TEMPLATE--
+{% spaceless %}
+
+    <div>   <div>   foo   </div>   </div>
+
+{% endspaceless %}
+--DATA--
+return array()
+--EXPECT--
+<div><div>   foo   </div></div>
diff --git a/test/Twig/Tests/Node/SpacelessTest.php b/test/Twig/Tests/Node/SpacelessTest.php
new file mode 100644 (file)
index 0000000..55892f4
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once dirname(__FILE__).'/TestCase.php';
+
+class Twig_Tests_Node_SpacelessTest extends Twig_Tests_Node_TestCase
+{
+    /**
+     * @covers Twig_Node_Spaceless::__construct
+     */
+    public function testConstructor()
+    {
+        $body = new Twig_Node(array(new Twig_Node_Text('<div>   <div>   foo   </div>   </div>', 0)));
+        $node = new Twig_Node_Spaceless($body, 0);
+
+        $this->assertEquals($body, $node->getNode('body'));
+    }
+
+    /**
+     * @covers Twig_Node_Spaceless::compile
+     * @dataProvider getTests
+     */
+    public function testCompile($node, $source, $environment = null)
+    {
+        parent::testCompile($node, $source, $environment);
+    }
+
+    public function getTests()
+    {
+        $body = new Twig_Node(array(new Twig_Node_Text('<div>   <div>   foo   </div>   </div>', 0)));
+        $node = new Twig_Node_Spaceless($body, 0);
+
+        return array(
+            array($node, <<<EOF
+ob_start();
+echo "<div>   <div>   foo   </div>   </div>";
+echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));
+EOF
+            ),
+        );
+    }
+}