fixed a bug when a literal '\n' were present in a template text
authorfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Sat, 28 Nov 2009 11:25:56 +0000 (11:25 +0000)
committerfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Sat, 28 Nov 2009 11:25:56 +0000 (11:25 +0000)
git-svn-id: http://svn.twig-project.org/trunk@146 93ef8e89-cb99-4229-a87c-7fa0fa45744b

CHANGELOG
lib/Twig/Compiler.php
lib/Twig/Lexer.php
lib/Twig/TokenStream.php

index 6811b4e..01e8629 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,7 @@ If you have custom loaders, you MUST upgrade them for this release: The
 Twig_Loader base class has been removed, and the Twig_LoaderInterface has also
 been changed (see the source code for more information or the documentation).
 
+ * fixed a bug when a literal '\n' were present in a template text
  * refactored loaders
 
 * 0.9.3 (2009-11-11)
index aba6004..720f9b0 100644 (file)
@@ -113,7 +113,7 @@ class Twig_Compiler implements Twig_CompilerInterface
    */
   public function string($value)
   {
-    $this->source .= sprintf('"%s"', str_replace('\\\n', "\n", addcslashes($value, "\t\"\$\\")));
+    $this->source .= sprintf('"%s"', addcslashes($value, "\t\"\$\\"));
 
     return $this;
   }
index ad1b3a7..fa6b082 100644 (file)
@@ -29,6 +29,8 @@ class Twig_Lexer implements Twig_LexerInterface
   protected $env;
   protected $options;
 
+  const LINE_DELIMITER = '<TWIG_NL>';
+
   const POSITION_DATA  = 0;
   const POSITION_BLOCK = 1;
   const POSITION_VAR   = 2;
@@ -59,7 +61,7 @@ class Twig_Lexer implements Twig_LexerInterface
    */
   public function tokenize($code, $filename = 'n/a')
   {
-    $this->code = preg_replace('/(\r\n|\r|\n)/', '\n', $code);
+    $this->code = preg_replace('/(\r\n|\r|\n)/', self::LINE_DELIMITER, $code);
     $this->filename = $filename;
     $this->cursor = 0;
     $this->lineno = 1;
@@ -153,7 +155,7 @@ class Twig_Lexer implements Twig_LexerInterface
     // as simple text token
     if (!preg_match('/(.*?)('.preg_quote($this->options['tag_comment'][0], '/').'|'.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')/A', $this->code, $match, null, $this->cursor))
     {
-      $rv = new Twig_Token(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor), $this->lineno);
+      $rv = new Twig_Token(Twig_Token::TEXT_TYPE, $this->fixNewLines(substr($this->code, $this->cursor)), $this->lineno);
       $this->cursor = $this->end;
 
       return $rv;
@@ -162,8 +164,8 @@ class Twig_Lexer implements Twig_LexerInterface
     // update the lineno on the instance
     $lineno = $this->lineno;
 
-    $this->cursor += strlen($match[0]);
-    $this->lineno += substr_count($match[0], '\n');
+    $this->moveCursor($match[0]);
+    $this->moveLineNo($match[0]);
 
     // array of tokens
     $result = array();
@@ -172,8 +174,8 @@ class Twig_Lexer implements Twig_LexerInterface
     $text = $match[1];
     if (!empty($text))
     {
-      $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $text, $lineno);
-      $lineno += substr_count($text, '\n');
+      $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $this->fixNewLines($text), $lineno);
+      $lineno += substr_count($text, self::LINE_DELIMITER);
     }
 
     $token = $match[2];
@@ -184,17 +186,17 @@ class Twig_Lexer implements Twig_LexerInterface
         {
           throw new Twig_SyntaxError('unclosed comment', $this->lineno, $this->filename);
         }
-        $this->cursor += strlen($match[0]);
-        $this->lineno += substr_count($match[0], '\n');
+        $this->moveCursor($match[0]);
+        $this->moveLineNo($match[0]);
         break;
 
       case $this->options['tag_block'][0]:
         // raw data?
         if (preg_match('/\s*raw\s*'.preg_quote($this->options['tag_block'][1], '/').'(.*?)'.preg_quote($this->options['tag_block'][0], '/').'\s*endraw\s*'.preg_quote($this->options['tag_block'][1], '/').'/A', $this->code, $match, null, $this->cursor))
         {
-          $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $match[1], $lineno);
-          $this->cursor += strlen($match[0]);
-          $this->lineno += substr_count($match[0], '\n');
+          $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $this->fixNewLines($match[1]), $lineno);
+          $this->moveCursor($match[0]);
+          $this->moveLineNo($match[0]);
           $this->position = self::POSITION_DATA;
         }
         else
@@ -218,8 +220,8 @@ class Twig_Lexer implements Twig_LexerInterface
     if (preg_match('/\s*'.preg_quote($this->options['tag_block'][1], '/').'/A', $this->code, $match, null, $this->cursor))
     {
       $lineno = $this->lineno;
-      $this->cursor += strlen($match[0]);
-      $this->lineno += substr_count($match[0], '\n');
+      $this->moveCursor($match[0]);
+      $this->moveLineNo($match[0]);
       $this->position = self::POSITION_DATA;
 
       return new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $lineno);
@@ -233,8 +235,8 @@ class Twig_Lexer implements Twig_LexerInterface
     if (preg_match('/\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A', $this->code, $match, null, $this->cursor))
     {
       $lineno = $this->lineno;
-      $this->cursor += strlen($match[0]);
-      $this->lineno += substr_count($match[0], '\n');
+      $this->moveCursor($match[0]);
+      $this->moveLineNo($match[0]);
       $this->position = self::POSITION_DATA;
 
       return new Twig_Token(Twig_Token::VAR_END_TYPE, '', $lineno);
@@ -250,8 +252,8 @@ class Twig_Lexer implements Twig_LexerInterface
     // whitespace
     while (preg_match('/\s+/A', $this->code, $match, null, $this->cursor))
     {
-      $this->cursor += strlen($match[0]);
-      $this->lineno += substr_count($match[0], '\n');
+      $this->moveCursor($match[0]);
+      $this->moveLineNo($match[0]);
     }
 
     // sanity check
@@ -263,21 +265,21 @@ class Twig_Lexer implements Twig_LexerInterface
     // first parse operators
     if (preg_match(self::REGEX_OPERATOR, $this->code, $match, null, $this->cursor))
     {
-      $this->cursor += strlen($match[0]);
+      $this->moveCursor($match[0]);
 
       return new Twig_Token(Twig_Token::OPERATOR_TYPE, $match[0], $this->lineno);
     }
     // now names
     else if (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor))
     {
-      $this->cursor += strlen($match[0]);
+      $this->moveCursor($match[0]);
 
       return new Twig_Token(Twig_Token::NAME_TYPE, $match[0], $this->lineno);
     }
     // then numbers
     else if (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor))
     {
-      $this->cursor += strlen($match[0]);
+      $this->moveCursor($match[0]);
       $value = (float)$match[0];
       if ((int)$value === $value)
       {
@@ -289,8 +291,8 @@ class Twig_Lexer implements Twig_LexerInterface
     // and finally strings
     else if (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor))
     {
-      $this->cursor += strlen($match[0]);
-      $this->lineno += substr_count($match[0], '\n');
+      $this->moveCursor($match[0]);
+      $this->moveLineNo($match[0]);
       $value = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
 
       return new Twig_Token(Twig_Token::STRING_TYPE, $value, $this->lineno);
@@ -299,4 +301,19 @@ class Twig_Lexer implements Twig_LexerInterface
     // unlexable
     throw new Twig_SyntaxError(sprintf("Unexpected character '%s'", $this->code[$this->cursor]), $this->lineno, $this->filename);
   }
+
+  protected function moveLineNo($text)
+  {
+    $this->lineno += substr_count($text, self::LINE_DELIMITER);
+  }
+
+  protected function moveCursor($text)
+  {
+    $this->cursor += strlen($text);
+  }
+
+  protected function fixNewLines($text)
+  {
+    return str_replace(self::LINE_DELIMITER, "\n", $text);
+  }
 }
index cae0be9..b14165e 100644 (file)
@@ -69,10 +69,10 @@ class Twig_TokenStream
       Twig_Token::BLOCK_END_TYPE === $this->current->getType() &&
       Twig_Token::TEXT_TYPE === $token->getType() &&
       $token->getValue() &&
-      '\n' === substr($token->getValue(), 0, 2)
+      "\n" === substr($token->getValue(), 0, 1)
     )
     {
-      $value = substr($token->getValue(), 2);
+      $value = substr($token->getValue(), 1);
 
       if (!$value)
       {