Merge pull request #209 from smarden1/pr/even_triple_braces

Uneven braces in triples are incorrectly swallowing a character [repost of 208]
This commit is contained in:
Justin Hileman
2014-06-20 12:25:10 -07:00
2 changed files with 114 additions and 8 deletions
+33 -12
View File
@@ -84,6 +84,8 @@ class Mustache_Tokenizer
/**
* Scan and tokenize template source.
*
* @throws Mustache_Exception_SyntaxException when mismatched section tags are encountered.
*
* @param string $text Mustache template source to tokenize
* @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null)
*
@@ -151,7 +153,7 @@ class Mustache_Tokenizer
default:
if ($this->tagChange($this->ctag, $this->ctagLen, $text, $i)) {
$this->tokens[] = array(
$token = array(
self::TYPE => $this->tagType,
self::NAME => trim($this->buffer),
self::OTAG => $this->otag,
@@ -160,20 +162,39 @@ class Mustache_Tokenizer
self::INDEX => ($this->tagType === self::T_END_SECTION) ? $this->seenTag - $this->otagLen : $i + $this->ctagLen
);
if ($this->tagType === self::T_UNESCAPED) {
// Clean up `{{{ tripleStache }}}` style tokens.
if ($this->ctag === '}}') {
if (($i+2 < $len) && $text[$i + 2] === '}') {
$i++;
} else {
$msg = sprintf(
'Uneven closing tag encountered: on line %d',
$token[self::LINE]
);
throw new Mustache_Exception_SyntaxException($msg, $token);
}
} else {
$lastName = $token[self::NAME];
if (substr($lastName, -1) === '}') {
$token[self::NAME] = trim(substr($lastName, 0, -1));
} else {
$msg = sprintf(
'Uneven closing tag encountered: %s on line %d',
substr($lastName, -1),
$token[self::LINE]
);
throw new Mustache_Exception_SyntaxException($msg, $token);
}
}
}
$this->buffer = '';
$i += $this->ctagLen - 1;
$this->state = self::IN_TEXT;
if ($this->tagType === self::T_UNESCAPED) {
if ($this->ctag === '}}') {
$i++;
} else {
// Clean up `{{{ tripleStache }}}` style tokens.
$lastName = $this->tokens[count($this->tokens) - 1][self::NAME];
if (substr($lastName, -1) === '}') {
$this->tokens[count($this->tokens) - 1][self::NAME] = trim(substr($lastName, 0, -1));
}
}
}
$this->tokens[] = $token;
} else {
$this->buffer .= $text[$i];
}
+85
View File
@@ -24,6 +24,28 @@ class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase
$this->assertSame($expected, $tokenizer->scan($text, $delimiters));
}
/**
* @expectedException Mustache_Exception_SyntaxException
*/
public function testUnevenBracesThrowExceptions()
{
$tokenizer = new Mustache_Tokenizer;
$text = "{{{ name }}";
$tokenizer->scan($text, null);
}
/**
* @expectedException Mustache_Exception_SyntaxException
*/
public function testUnevenBracesWithCustomDelimiterThrowExceptions()
{
$tokenizer = new Mustache_Tokenizer;
$text = "<%{ name %>";
$tokenizer->scan($text, "<% %>");
}
public function getTokens()
{
return array(
@@ -188,6 +210,69 @@ class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase
),
)
),
// custom delimiters don't swallow the next character, even if it is a }, }}}, or the same delimiter
array(
"<% a %>} <% b %>%> <% c %>}}}",
"<% %>",
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'a',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 7,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::VALUE => "} ",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'b',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 16,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::VALUE => "%> ",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'c',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 26,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::VALUE => "}}}",
),
)
),
// unescaped custom delimiters are properly parsed
array(
"<%{ a }%>",
"<% %>",
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_UNESCAPED,
Mustache_Tokenizer::NAME => 'a',
Mustache_Tokenizer::OTAG => '<%',
Mustache_Tokenizer::CTAG => '%>',
Mustache_Tokenizer::LINE => 0,
Mustache_Tokenizer::INDEX => 9,
)
)
),
);
}
}