Skip to content

Commit 68cd5a3

Browse files
committed
Add support for .length on strings
1 parent 1ac566c commit 68cd5a3

4 files changed

Lines changed: 30 additions & 12 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ possible to swap out Mustache for Handlebars and continue using the same templat
88
## Features
99

1010
* Supports all Handlebars syntax and language features, including expressions, subexpressions, helpers,
11-
partials, hooks, `@data` variables, whitespace control, and `.length` on arrays.
11+
partials, hooks, `@data` variables, whitespace control, and `.length` on arrays and strings.
1212
* Templates are parsed using [PHP Handlebars Parser](https://github.com/devtheorem/php-handlebars-parser),
1313
which implements the same lexical analysis and AST grammar specification as Handlebars.js.
1414
* Tested against the [Handlebars.js spec](https://github.com/jbboehr/handlebars-spec)

src/Runtime.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,17 @@ public static function nullCheck(mixed $base, string $key): mixed
143143
}
144144

145145
/**
146-
* Terminal .length lookup: returns count() for arrays (since PHP arrays have no native .length
147-
* property), an explicit 'length' key if present, or null for non-array bases.
148-
* When $strict is true, throws for any non-array base, mirroring HBS.js strict-mode behavior.
146+
* Terminal .length lookup: returns an explicit 'length' key if present, and otherwise
147+
* count() for arrays and strlen() for strings, since PHP doesn't have native .length properties.
149148
*/
150149
public static function lookupLength(mixed $base, bool $strict = false): mixed
151150
{
152151
if (is_array($base)) {
153152
return array_key_exists('length', $base) ? $base['length'] : count($base);
154153
}
154+
if (is_string($base)) {
155+
return strlen($base);
156+
}
155157
return $strict ? self::strictLookup($base, 'length') : null;
156158
}
157159

tests/ErrorTest.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,6 @@ public static function renderErrorProvider(): array
8383
'data' => ['foo' => false],
8484
'expected' => '"length" not defined in false',
8585
],
86-
'strict mode .length on string' => [
87-
'template' => '{{foo.length}}',
88-
'options' => new Options(strict: true),
89-
'data' => ['foo' => 'hello'],
90-
'expected' => '"length" not defined in "hello"',
91-
],
9286
'strict mode .length on integer' => [
9387
'template' => '{{foo.length}}',
9488
'options' => new Options(strict: true),

tests/RegressionTest.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function testLog(): void
6161
#[DataProvider("ifElseProvider")]
6262
#[DataProvider("sectionProvider")]
6363
#[DataProvider("contextProvider")]
64-
#[DataProvider("arrayLengthProvider")]
64+
#[DataProvider("lengthProvider")]
6565
#[DataProvider("dataClosuresProvider")]
6666
#[DataProvider("missingDataProvider")]
6767
#[DataProvider("syntaxProvider")]
@@ -2238,7 +2238,7 @@ public static function contextProvider(): array
22382238
}
22392239

22402240
/** @return array<string, RegIssue> */
2241-
public static function arrayLengthProvider(): array
2241+
public static function lengthProvider(): array
22422242
{
22432243
return [
22442244
'LNC#216 - {{array.length}} evaluation support - empty array' => [
@@ -2276,6 +2276,28 @@ public static function arrayLengthProvider(): array
22762276
'data' => ['foo' => ['length' => fn() => 'testing']],
22772277
'expected' => 'testing',
22782278
],
2279+
'string length' => [
2280+
'template' => '{{foo.length}}',
2281+
'data' => ['foo' => 'hello'],
2282+
'expected' => '5',
2283+
],
2284+
'string length - empty string' => [
2285+
'template' => '{{foo.length}}',
2286+
'data' => ['foo' => ''],
2287+
'expected' => '0',
2288+
],
2289+
'string length - strict mode' => [
2290+
'template' => '{{foo.length}}',
2291+
'options' => new Options(strict: true),
2292+
'data' => ['foo' => 'hello'],
2293+
'expected' => '5',
2294+
],
2295+
'string length - strict mode empty string' => [
2296+
'template' => '{{foo.length}}',
2297+
'options' => new Options(strict: true),
2298+
'data' => ['foo' => ''],
2299+
'expected' => '0',
2300+
],
22792301
];
22802302
}
22812303

0 commit comments

Comments
 (0)