Skip to content

Commit 4134d00

Browse files
committed
Fix parsing single-quoted string arguments
Fixes zordius/lightncandy#281 Fixes zordius/lightncandy#357 Fixes zordius/lightncandy#367
1 parent 8031f48 commit 4134d00

2 files changed

Lines changed: 39 additions & 6 deletions

File tree

src/Parser.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ protected static function advancedVariable(array $vars, Context $context, string
285285
/**
286286
* Detect quote characters in a string
287287
*
288-
* @return array<string,int>|null Expected ending string when there is a quote character
288+
* @return array{string,int}|null Expected ending string when there is a quote character
289289
*/
290290
protected static function detectQuote(string $string): ?array
291291
{
@@ -300,7 +300,7 @@ protected static function detectQuote(string $string): ?array
300300
}
301301

302302
// begin with \' without ending '
303-
if (preg_match('/^\\\\\'[^\']*$/', $string)) {
303+
if (preg_match('/^\'[^\']*$/', $string)) {
304304
return ['\'', 0];
305305
}
306306

@@ -315,7 +315,7 @@ protected static function detectQuote(string $string): ?array
315315
}
316316

317317
// =\' exists without ending '
318-
if (preg_match('/^[^\']*=\\\\\'[^\']*$/', $string)) {
318+
if (preg_match('/^[^\']*=\'[^\']*$/', $string)) {
319319
return ['\'', 0];
320320
}
321321

@@ -337,7 +337,7 @@ protected static function detectQuote(string $string): ?array
337337
protected static function analyze(string $token, Context $context): array
338338
{
339339
// Do not break quoted strings. Also, allow escaped quotes inside them.
340-
$count = preg_match_all('/(\s*)([^"\s]*"(\\\\\\\\.|[^"])*"|[^\'\s]*\'(\\\\\\\\.|[^\'])*\'|\S+)/', $token, $matches);
340+
$count = preg_match_all('/(\s*)([^"\s]*"(\\\\\\\\.|[^"])*"|[^\'\s]*\'(\\\\\\\\.|[^\'])*\'|\\S+)/', $token, $matches);
341341
// Parse arguments and deal with "..." or [...] or (...) or \'...\' or |...|
342342
if ($count > 0) {
343343
$vars = [];
@@ -350,15 +350,15 @@ protected static function analyze(string $token, Context $context): array
350350
$detected = static::detectQuote($t);
351351

352352
if ($expect === ')') {
353-
if ($detected && ($detected[0] !== ')')) {
353+
if ($detected && $detected[0] !== ')') {
354354
$quote = $detected[0];
355355
}
356356
if (substr($t, -1, 1) === $quote) {
357357
$quote = 0;
358358
}
359359
}
360360
// if we are inside quotes, we should later skip stack changes
361-
$quotes = preg_match("/^\".*\"$|^'.*'$/", $t);
361+
$quotes = preg_match("/^(\".*\")|('.*')$/", $t);
362362

363363
// continue from previous match when expect something
364364
if ($expect) {

tests/RegressionTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,18 @@ public static function issueProvider(): array
11611161
'expected' => 'ECHO: ECHO: foo bar (moo).',
11621162
],
11631163

1164+
[
1165+
'id' => 281,
1166+
'template' => "{{test 'foo bar' (toRegex '^(foo|bar|baz)')}}",
1167+
'options' => new Options(
1168+
helpers: [
1169+
'toRegex' => fn($regex) => "/$regex/",
1170+
'test' => fn(string $str, string $regex) => (bool) preg_match($regex, $str),
1171+
],
1172+
),
1173+
'expected' => 'true',
1174+
],
1175+
11641176
[
11651177
'id' => 284,
11661178
'template' => '{{> foo}}',
@@ -1340,6 +1352,16 @@ public static function issueProvider(): array
13401352
),
13411353
'expected' => 'ECHO: ECHO: foobar(moo).',
13421354
],
1355+
[
1356+
'id' => 357,
1357+
'template' => "{{{debug (debug 'foobar(moo).')}}}",
1358+
'options' => new Options(
1359+
helpers: [
1360+
'debug' => fn($arg1) => "ECHO: $arg1",
1361+
],
1362+
),
1363+
'expected' => 'ECHO: ECHO: foobar(moo).',
1364+
],
13431365
[
13441366
'id' => 357,
13451367
'template' => '{{echo (echo "foobar(moo)." (echo "moobar(foo)"))}}',
@@ -1351,6 +1373,17 @@ public static function issueProvider(): array
13511373
'expected' => 'ECHO: ECHO: foobar(moo).',
13521374
],
13531375

1376+
[
1377+
'id' => 367,
1378+
'template' => "{{#each (myfunc 'foo(bar)' ) }}{{.}},{{/each}}",
1379+
'options' => new Options(
1380+
helpers: [
1381+
'myfunc' => fn($arg) => explode('(', $arg),
1382+
],
1383+
),
1384+
'expected' => 'foo,bar),',
1385+
],
1386+
13541387
[
13551388
'id' => 369,
13561389
'template' => '{{#each paragraphs}}<p>{{this}}</p>{{else}}<p class="empty">{{foo}}</p>{{/each}}',

0 commit comments

Comments
 (0)