Skip to content

Commit 2f68fce

Browse files
committed
Release 1.3.0
1 parent b37b84f commit 2f68fce

2 files changed

Lines changed: 32 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file.
33

44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
55

6+
## [1.3.0] Compat Mode - 2026-04-21
7+
8+
### Added
9+
- `compat` compile option to enable recursive field lookup. When set to `true`, if a template variable is not
10+
found in the current scope it will automatically be looked up in parent scopes, matching Mustache's behavior.
11+
- Official [Mustache spec](https://github.com/mustache/spec) tests are now run to verify `compat` functionality.
12+
13+
### Changed
14+
- Slightly improved compiler performance by removing unnecessary internal state.
15+
- Optimized rendering of indented partials.
16+
17+
### Fixed
18+
- Failure to invoke `@data` variables containing a closure when passed to `if` or `unless` helpers.
19+
- Hoisted block closures leaked into the caller's scope when a precompiled template was loaded via `include`/`require`.
20+
- Hash arguments passed to a partial were ignored when the partial was invoked in certain non-array contexts.
21+
- Block helpers returning a nested or non-list array were not stringified correctly.
22+
23+
624
## [1.2.3] Hoisted Closures - 2026-04-10
725
### Changed
826
- Improved rendering performance by hoisting the closures for block bodies and `{{else}}` clauses,
@@ -20,14 +38,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
2038
fixing numerous edge cases related to helpers and `@data` variables.
2139

2240
### Fixed
23-
- `../` expressions inside `{{else}}` blocks of `{{#if}}`, `{{#unless}}`, `{{#with}}`, and sections invoking `blockHelperMissing` resolved to the wrong context level.
24-
- A missing helper called via multi-segment path in a subexpression or `@data` variable failed to invoke `helperMissing`.
25-
- A non-function context property used as a helper (e.g. `{{foo "arg"}}` where `foo` is not a closure) incorrectly called `helperMissing` rather than throwing a distinct error.
41+
- `../` expressions inside `{{else}}` blocks of `{{#if}}`, `{{#unless}}`, `{{#with}}`,
42+
and sections invoking `blockHelperMissing` resolved to the wrong context level.
43+
- A missing helper called via a `@data` variable or multi-segment path in a subexpression failed to invoke `helperMissing`.
44+
- A non-function context property used as a helper (e.g. `{{foo "arg"}}` where `foo` is not a closure)
45+
incorrectly called `helperMissing` rather than throwing a distinct error.
2646
- No error thrown when calling a missing helper via a multi-segment path with arguments (e.g. `{{foo.bar "arg"}}`).
2747
- Closures in context data could not be used as block helpers (e.g. `{{#fn}}...{{/fn}}` where `fn` is a closure).
2848
- Closures in context data or `@data` variables failed to be passed `HelperOptions` as the last argument in certain cases.
2949
- Templates with hash arguments on complex paths (e.g. `{{foo.bar arg=val}}`) were not compiled correctly.
30-
- Closures in context data were not invoked when accessed via a multi-segment path (e.g. `{{foo.bar}}`), or via a literal path (e.g. `{{"foo"}}`) in `knownHelpersOnly` mode.
50+
- Closures in context data were not invoked when accessed via a multi-segment path (e.g. `{{foo.bar}}`),
51+
or via a literal path (e.g. `{{"foo"}}`) in `knownHelpersOnly` mode.
3152
- `@data` variables incorrectly took priority over helpers with the same name.
3253
- `knownHelpersOnly` was not enforced for `@data` expressions or complex paths used with arguments.
3354

@@ -245,6 +266,7 @@ Initial release after forking from LightnCandy 1.2.6.
245266
- HTML documentation.
246267
- Dozens of unnecessary feature flags.
247268

269+
[1.3.0]: https://github.com/devtheorem/php-handlebars/compare/v1.2.3...v1.3.0
248270
[1.2.3]: https://github.com/devtheorem/php-handlebars/compare/v1.2.2...v1.2.3
249271
[1.2.2]: https://github.com/devtheorem/php-handlebars/compare/v1.2.1...v1.2.2
250272
[1.2.1]: https://github.com/devtheorem/php-handlebars/compare/v1.2.0...v1.2.1

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ PHP Handlebars compiles and executes complex templates over 40% faster than Ligh
1010
| Library | Compile time | Runtime | Total time | Peak memory usage |
1111
|--------------------|--------------|---------|------------|-------------------|
1212
| LightnCandy 1.2.6 | 5.2 ms | 2.8 ms | 8.0 ms | 5.3 MB |
13-
| PHP Handlebars 1.2 | 3.2 ms | 1.4 ms | 4.6 ms | 1.9 MB |
13+
| PHP Handlebars 1.3 | 3.1 ms | 1.4 ms | 4.5 ms | 1.9 MB |
1414

1515
_Tested on PHP 8.5 with the JIT enabled. See the `benchmark` branch to run the same test._
1616

@@ -20,7 +20,7 @@ _Tested on PHP 8.5 with the JIT enabled. See the `benchmark` branch to run the s
2020
partials, hooks, `@data` variables, whitespace control, and `.length` on arrays.
2121
* Templates are parsed using [PHP Handlebars Parser](https://github.com/devtheorem/php-handlebars-parser),
2222
which implements the same lexical analysis and AST grammar specification as Handlebars.js.
23-
* Tested against the full [Handlebars.js spec](https://github.com/jbboehr/handlebars-spec).
23+
* Tested against the [Handlebars.js spec](https://github.com/jbboehr/handlebars-spec) and the [Mustache spec](https://github.com/mustache/spec).
2424

2525
## Installation
2626
```
@@ -70,6 +70,9 @@ echo $template(['first' => 'John']); // Error: "last" not defined
7070

7171
### Available Options
7272

73+
* `compat`: Set to `true` to enable recursive field lookup. If a template variable is not found in the current scope,
74+
it will automatically be looked up in parent scopes, matching Mustache's default behavior.
75+
7376
* `knownHelpers`: Associative array (`helperName => bool`) of helpers that will be registered at runtime.
7477
The compiler uses this to emit direct helper calls instead of dynamic dispatch, which is faster and required when `knownHelpersOnly` is set.
7578
Built-in helpers (`if`, `unless`, `each`, `with`, `lookup`, `log`) are pre-populated as `true` and may be excluded by setting them to `false`.
@@ -234,6 +237,6 @@ All syntax and language features from Handlebars.js 4.7.9 should work the same i
234237
with the following exceptions:
235238

236239
* Custom Decorators have not been implemented, as they are [deprecated in Handlebars.js](https://github.com/handlebars-lang/handlebars.js/blob/master/docs/decorators-api.md).
237-
* The `data` and `compat` compilation options have not been implemented.
240+
* The `data` compilation option has not been implemented.
238241
* The [runtime options to control prototype access](https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access),
239242
along with the `lookupProperty()` helper option method have not been implemented, since they aren't relevant for PHP.

0 commit comments

Comments
 (0)