From ba8854fba70e9f11735cbeeb8279a94507be3bf6 Mon Sep 17 00:00:00 2001 From: John Rayes Date: Fri, 10 May 2024 00:03:42 -0700 Subject: [PATCH] Make the regex for the cycle tag less greed --- src/Liquid/Tag/TagCycle.php | 41 +++++++------------------------ tests/Liquid/Tag/TagCycleTest.php | 6 ++++- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/Liquid/Tag/TagCycle.php b/src/Liquid/Tag/TagCycle.php index 21408474..21db218a 100644 --- a/src/Liquid/Tag/TagCycle.php +++ b/src/Liquid/Tag/TagCycle.php @@ -57,14 +57,15 @@ class TagCycle extends AbstractTag */ public function __construct($markup, array &$tokens, FileSystem $fileSystem = null) { - $simpleSyntax = new Regexp("/" . Liquid::get('QUOTED_FRAGMENT') . "/"); - $namedSyntax = new Regexp("/(" . Liquid::get('QUOTED_FRAGMENT') . ")\s*\:\s*(.*)/"); - - if ($namedSyntax->match($markup)) { - $this->variables = $this->variablesFromString($namedSyntax->matches[2]); - $this->name = $namedSyntax->matches[1]; - } elseif ($simpleSyntax->match($markup)) { - $this->variables = $this->variablesFromString($markup); + $simpleSyntax = preg_match_all('/(["\'])?(?(1)(?:(?!\1).)*+\1|[^\s,:|\'"]++)/', $markup, $matches); + $namedSyntax = preg_match('/^(["\'])?(?(1)(?:(?!\1).)*+\1|[^\s,:|\'"]++)\s*\:/', $markup, $namedMatches); + + if ($namedSyntax) { + $this->name = $matches[0][0]; + array_shift($matches[0]); + $this->variables = $matches[0]; + } elseif ($simpleSyntax) { + $this->variables = $matches[0]; $this->name = "'" . implode($this->variables) . "'"; } else { throw new ParseException("Syntax Error in 'cycle' - Valid syntax: cycle [name :] var [, var2, var3 ...]"); @@ -103,28 +104,4 @@ public function render(Context $context) return $result; } - - /** - * Extract variables from a string of markup - * - * @param string $markup - * - * @return array; - */ - private function variablesFromString($markup) - { - $regexp = new Regexp('/\s*(' . Liquid::get('QUOTED_FRAGMENT') . ')\s*/'); - $parts = explode(',', $markup); - $result = array(); - - foreach ($parts as $part) { - $regexp->match($part); - - if (!empty($regexp->matches[1])) { - $result[] = $regexp->matches[1]; - } - } - - return $result; - } } diff --git a/tests/Liquid/Tag/TagCycleTest.php b/tests/Liquid/Tag/TagCycleTest.php index 857a59a6..fe517ddb 100644 --- a/tests/Liquid/Tag/TagCycleTest.php +++ b/tests/Liquid/Tag/TagCycleTest.php @@ -36,11 +36,15 @@ public function testCycle() public function testMultipleCycles() { $this->assertTemplateResult('1 2 1 1 2 3 1', '{%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%}'); + $this->assertTemplateResult('onetwo:,three', '{%cycle "one","two:,three"%}{%cycle "one","two:,three"%}'); } public function testMultipleNamedCycles() { - $this->assertTemplateResult('one one two two one one', '{%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %}'); + $this->assertTemplateResult('one one two two one one', '{%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1 : "one", "two" %} {%cycle 2 : "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %}'); + $this->assertTemplateResult('one one two two one one', '{%cycle "first": "one", "two" %} {%cycle "second": "one", "two" %} {%cycle "first" : "one", "two" %} {%cycle "second" : "one", "two" %} {%cycle "first": "one", "two" %} {%cycle "second": "one", "two" %}'); + $this->assertTemplateResult('one one two two one one', '{%cycle 1: \'one\', \'two\' %} {%cycle 2: \'one\', \'two\' %} {%cycle 1 : \'one\', \'two\' %} {%cycle 2 : \'one\', \'two\' %} {%cycle 1: \'one\', \'two\' %} {%cycle 2: \'one\', \'two\' %}'); + $this->assertTemplateResult('one one two two one one', '{%cycle \'first\': \'one\', \'two\' %} {%cycle \'second\': \'one\', \'two\' %} {%cycle \'first\' : \'one\', \'two\' %} {%cycle \'second\' : \'one\', \'two\' %} {%cycle \'first\': \'one\', \'two\' %} {%cycle \'second\': \'one\', \'two\' %}'); } public function testMultipleNamedCyclesWithNamesFromContext()