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:
+33
-12
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user