From 112a16bfde364dbc7d9455e859c9d883174b1c4d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 7 Aug 2011 10:07:35 +0200 Subject: [PATCH] changed name regex to allow more characters (the same as PHP - works for blocks, tags, functions, filters, and macros - closes #376) --- CHANGELOG | 1 + lib/Twig/Lexer.php | 2 +- .../Twig/Tests/Fixtures/filters/special_chars.test | 8 +++++ .../Tests/Fixtures/functions/special_chars.test | 8 +++++ .../Tests/Fixtures/tags/block/special_chars.test | 10 ++++++ .../Tests/Fixtures/tags/macro/special_chars.test | 12 +++++++ test/Twig/Tests/Fixtures/tags/special_chars.test | 8 +++++ test/Twig/Tests/LexerTest.php | 22 +++++++++++++ test/Twig/Tests/integrationTest.php | 34 ++++++++++++++++++++ 9 files changed, 104 insertions(+), 1 deletions(-) create mode 100644 test/Twig/Tests/Fixtures/filters/special_chars.test create mode 100644 test/Twig/Tests/Fixtures/functions/special_chars.test create mode 100644 test/Twig/Tests/Fixtures/tags/block/special_chars.test create mode 100644 test/Twig/Tests/Fixtures/tags/macro/special_chars.test create mode 100644 test/Twig/Tests/Fixtures/tags/special_chars.test diff --git a/CHANGELOG b/CHANGELOG index 401bd1f..742eb4b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * 1.2.0 + * changed name regex to match PHP one "[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*" (works for blocks, tags, functions, filters, and macros) * removed the possibility to use the "extends" tag from a block * added "if" modifier support to "for" loops diff --git a/lib/Twig/Lexer.php b/lib/Twig/Lexer.php index 5a2489a..868a814 100644 --- a/lib/Twig/Lexer.php +++ b/lib/Twig/Lexer.php @@ -35,7 +35,7 @@ class Twig_Lexer implements Twig_LexerInterface const STATE_BLOCK = 1; const STATE_VAR = 2; - const REGEX_NAME = '/[A-Za-z_][A-Za-z0-9_]*/A'; + const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A'; const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; const REGEX_STRING = '/"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; const PUNCTUATION = '()[]{}?:.,|'; diff --git a/test/Twig/Tests/Fixtures/filters/special_chars.test b/test/Twig/Tests/Fixtures/filters/special_chars.test new file mode 100644 index 0000000..cc91900 --- /dev/null +++ b/test/Twig/Tests/Fixtures/filters/special_chars.test @@ -0,0 +1,8 @@ +--TEST-- +"☃" custom filter +--TEMPLATE-- +{{ 'foo'|☃ }} +--DATA-- +return array() +--EXPECT-- +☃foo☃ diff --git a/test/Twig/Tests/Fixtures/functions/special_chars.test b/test/Twig/Tests/Fixtures/functions/special_chars.test new file mode 100644 index 0000000..f602b0d --- /dev/null +++ b/test/Twig/Tests/Fixtures/functions/special_chars.test @@ -0,0 +1,8 @@ +--TEST-- +"☃" custom function +--TEMPLATE-- +{{ ☃('foo') }} +--DATA-- +return array() +--EXPECT-- +☃foo☃ diff --git a/test/Twig/Tests/Fixtures/tags/block/special_chars.test b/test/Twig/Tests/Fixtures/tags/block/special_chars.test new file mode 100644 index 0000000..441570c --- /dev/null +++ b/test/Twig/Tests/Fixtures/tags/block/special_chars.test @@ -0,0 +1,10 @@ +--TEST-- +"☃" special chars in a block name +--TEMPLATE-- +{% block ☃ %} +☃ +{% endblock ☃ %} +--DATA-- +return array() +--EXPECT-- +☃ diff --git a/test/Twig/Tests/Fixtures/tags/macro/special_chars.test b/test/Twig/Tests/Fixtures/tags/macro/special_chars.test new file mode 100644 index 0000000..e61716e --- /dev/null +++ b/test/Twig/Tests/Fixtures/tags/macro/special_chars.test @@ -0,0 +1,12 @@ +--TEST-- +"☃" as a macro name +--TEMPLATE-- +{{ _self.☃('foo') }} + +{% macro ☃(foo) %} + ☃{{ foo }}☃ +{% endmacro %} +--DATA-- +return array() +--EXPECT-- +☃foo☃ diff --git a/test/Twig/Tests/Fixtures/tags/special_chars.test b/test/Twig/Tests/Fixtures/tags/special_chars.test new file mode 100644 index 0000000..d584d9e --- /dev/null +++ b/test/Twig/Tests/Fixtures/tags/special_chars.test @@ -0,0 +1,8 @@ +--TEST-- +"☃" custom tag +--TEMPLATE-- +{% ☃ %} +--DATA-- +return array() +--EXPECT-- +☃ diff --git a/test/Twig/Tests/LexerTest.php b/test/Twig/Tests/LexerTest.php index f3df09b..7594041 100644 --- a/test/Twig/Tests/LexerTest.php +++ b/test/Twig/Tests/LexerTest.php @@ -10,6 +10,28 @@ */ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase { + public function testNameLabelForTag() + { + $template = '{% ☃ %}'; + + $lexer = new Twig_Lexer(new Twig_Environment()); + $stream = $lexer->tokenize($template); + + $stream->expect(Twig_Token::BLOCK_START_TYPE); + $this->assertSame('☃', $stream->expect(Twig_Token::NAME_TYPE)->getValue()); + } + + public function testNameLabelForFunction() + { + $template = '{{ ☃() }}'; + + $lexer = new Twig_Lexer(new Twig_Environment()); + $stream = $lexer->tokenize($template); + + $stream->expect(Twig_Token::VAR_START_TYPE); + $this->assertSame('☃', $stream->expect(Twig_Token::NAME_TYPE)->getValue()); + } + public function testBracketsNesting() { $template = '{{ {"a":{"b":"c"}} }}'; diff --git a/test/Twig/Tests/integrationTest.php b/test/Twig/Tests/integrationTest.php index 3c26cfa..ef682f6 100644 --- a/test/Twig/Tests/integrationTest.php +++ b/test/Twig/Tests/integrationTest.php @@ -149,11 +149,34 @@ class Foo } } +class TestTokenParser_☃ extends Twig_TokenParser +{ + public function parse(Twig_Token $token) + { + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_Print(new Twig_Node_Expression_Constant('☃', -1), -1); + } + + public function getTag() + { + return '☃'; + } +} + class TestExtension extends Twig_Extension { + public function getTokenParsers() + { + return array( + new TestTokenParser_☃(), + ); + } + public function getFilters() { return array( + '☃' => new Twig_Filter_Method($this, '☃Filter'), 'escape_and_nl2br' => new Twig_Filter_Method($this, 'escape_and_nl2br', array('needs_environment' => true, 'is_safe' => array('html'))), 'nl2br' => new Twig_Filter_Method($this, 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))), 'escape_something' => new Twig_Filter_Method($this, 'escape_something', array('is_safe' => array('something'))), @@ -163,11 +186,22 @@ class TestExtension extends Twig_Extension public function getFunctions() { return array( + '☃' => new Twig_Function_Method($this, '☃Function'), 'safe_br' => new Twig_Function_Method($this, 'br', array('is_safe' => array('html'))), 'unsafe_br' => new Twig_Function_Method($this, 'br'), ); } + public function ☃Filter($value) + { + return "☃{$value}☃"; + } + + public function ☃Function($value) + { + return "☃{$value}☃"; + } + /** * nl2br which also escapes, for testing escaper filters */ -- 1.7.2.5