From d31fcf5400841c93d1599e3c801a5483dbd1da4b Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 22 Oct 2023 13:00:19 +0200 Subject: [PATCH 1/4] Implement inverse blocks --- .../com/handlebarsjs/HandlebarsParser.class.php | 13 ++++++++----- .../php/com/handlebarsjs/InverseOf.class.php | 17 +++++++++++++++++ .../unittest/InverseOfTest.class.php | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100755 src/main/php/com/handlebarsjs/InverseOf.class.php create mode 100755 src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php diff --git a/src/main/php/com/handlebarsjs/HandlebarsParser.class.php b/src/main/php/com/handlebarsjs/HandlebarsParser.class.php index 49194fe..39eec4e 100755 --- a/src/main/php/com/handlebarsjs/HandlebarsParser.class.php +++ b/src/main/php/com/handlebarsjs/HandlebarsParser.class.php @@ -9,7 +9,6 @@ TemplateFormatException, ParseState }; -use lang\MethodNotImplementedException; use text\Tokenizer; /** @@ -191,13 +190,17 @@ protected function initialize() { }); // ^ is either an else by its own, or a negated block - $this->withHandler('^', true, function($tag, $state) { - if ('^' === trim($tag)) { + $this->withHandler('^', true, function($tag, $state, $parse) { + $tag= trim($tag); + if ('^' === $tag) { $block= cast($state->parents[sizeof($state->parents) - 1], BlockNode::class); $state->target= $block->inverse(); - return; + } else { + $state->parents[]= $state->target; + $block= new InverseOf($this->blocks->newInstance($parse->options(substr($tag, 1)), $state)); + $state->target= $block->fn(); + $state->parents[]= $block; } - throw new MethodNotImplementedException('^blocks not yet implemented'); }); // Default diff --git a/src/main/php/com/handlebarsjs/InverseOf.class.php b/src/main/php/com/handlebarsjs/InverseOf.class.php new file mode 100755 index 0000000..9317c58 --- /dev/null +++ b/src/main/php/com/handlebarsjs/InverseOf.class.php @@ -0,0 +1,17 @@ +name, + $block->options, + /* fn: */ $block->inverse, + /* inverse: */ $block->fn, + $block->start, + $block->end + ); + } +} \ No newline at end of file diff --git a/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php new file mode 100755 index 0000000..0d6fde0 --- /dev/null +++ b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php @@ -0,0 +1,14 @@ +evaluate( + '{{^if people}}no people{{else}}some people{{/if}}', + ['people' => $input] + )); + } +} \ No newline at end of file From 26a3d6d580d43e5268b6efcbe352dbd7aa72b80b Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 22 Oct 2023 13:22:04 +0200 Subject: [PATCH 2/4] Add tests for inverse sections See https://github.com/handlebars-lang/handlebars.js/blob/master/spec/blocks.js#L144 --- .../unittest/InverseOfTest.class.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php index 0d6fde0..9af9593 100755 --- a/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php +++ b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php @@ -4,6 +4,30 @@ class InverseOfTest extends HelperTest { + #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] + public function inverse_section($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#people}}{{this}}{{/people}}{{^people}}no people{{/people}}', + ['people' => $input] + )); + } + + #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] + public function inverse_section_with_else($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#people}}{{this}}{{else}}no people{{/people}}', + ['people' => $input] + )); + } + + #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] + public function inverse_section_with_short_else($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#people}}{{this}}{{^}}no people{{/people}}', + ['people' => $input] + )); + } + #[Test, Values([[[], 'no people'], [['A', 'B'], 'some people']])] public function inverse_if_with_else($input, $outcome) { Assert::equals($outcome, $this->evaluate( @@ -11,4 +35,12 @@ public function inverse_if_with_else($input, $outcome) { ['people' => $input] )); } + + #[Test, Values([[[], 'no people'], [['A', 'B'], 'some people']])] + public function inverse_if_with_short_else($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{^if people}}no people{{^}}some people{{/if}}', + ['people' => $input] + )); + } } \ No newline at end of file From ed1fbf7eb50ea29b6e3a5c4e318229247ecd77d2 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 22 Oct 2023 13:26:10 +0200 Subject: [PATCH 3/4] Add test for context inside sections --- .../handlebarsjs/unittest/InverseOfTest.class.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php index 9af9593..389c8e1 100755 --- a/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php +++ b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php @@ -4,8 +4,16 @@ class InverseOfTest extends HelperTest { - #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] + #[Test, Values([[null, 'Guest'], [['name' => 'Test'], 'User Test']])] public function inverse_section($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#person}}User {{name}}{{/person}}{{^person}}Guest{{/person}}', + ['person' => $input] + )); + } + + #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] + public function inverse_iterator($input, $outcome) { Assert::equals($outcome, $this->evaluate( '{{#people}}{{this}}{{/people}}{{^people}}no people{{/people}}', ['people' => $input] @@ -13,7 +21,7 @@ public function inverse_section($input, $outcome) { } #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] - public function inverse_section_with_else($input, $outcome) { + public function inverse_iterator_with_else($input, $outcome) { Assert::equals($outcome, $this->evaluate( '{{#people}}{{this}}{{else}}no people{{/people}}', ['people' => $input] @@ -21,7 +29,7 @@ public function inverse_section_with_else($input, $outcome) { } #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] - public function inverse_section_with_short_else($input, $outcome) { + public function inverse_iterator_with_short_else($input, $outcome) { Assert::equals($outcome, $this->evaluate( '{{#people}}{{this}}{{^}}no people{{/people}}', ['people' => $input] From f24bb1c7322e8545f980f143028eae766ea00c06 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 22 Oct 2023 13:35:12 +0200 Subject: [PATCH 4/4] Add tests for inverse variables --- .../unittest/InverseOfTest.class.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php index 389c8e1..3c76e4d 100755 --- a/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php +++ b/src/test/php/com/handlebarsjs/unittest/InverseOfTest.class.php @@ -4,6 +4,30 @@ class InverseOfTest extends HelperTest { + #[Test, Values([[null, 'Guest'], ['Test', 'User Test']])] + public function inverse_variable($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#person}}User {{.}}{{/person}}{{^person}}Guest{{/person}}', + ['person' => $input] + )); + } + + #[Test, Values([[null, 'Guest'], ['Test', 'User Test']])] + public function inverse_variable_with_else($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#person}}User {{.}}{{else}}Guest{{/person}}', + ['person' => $input] + )); + } + + #[Test, Values([[null, 'Guest'], ['Test', 'User Test']])] + public function inverse_variable_with_short_else($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#person}}User {{.}}{{^}}Guest{{/person}}', + ['person' => $input] + )); + } + #[Test, Values([[null, 'Guest'], [['name' => 'Test'], 'User Test']])] public function inverse_section($input, $outcome) { Assert::equals($outcome, $this->evaluate( @@ -12,6 +36,22 @@ public function inverse_section($input, $outcome) { )); } + #[Test, Values([[null, 'Guest'], [['name' => 'Test'], 'User Test']])] + public function inverse_section_with_else($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#person}}User {{name}}{{else}}Guest{{/person}}', + ['person' => $input] + )); + } + + #[Test, Values([[null, 'Guest'], [['name' => 'Test'], 'User Test']])] + public function inverse_section_with_short_else($input, $outcome) { + Assert::equals($outcome, $this->evaluate( + '{{#person}}User {{name}}{{^}}Guest{{/person}}', + ['person' => $input] + )); + } + #[Test, Values([[[], 'no people'], [['A', 'B'], 'AB']])] public function inverse_iterator($input, $outcome) { Assert::equals($outcome, $this->evaluate(