Skip to content

2.0.0 Compat Mode

Latest

Choose a tag to compare

@theodorejb theodorejb released this 28 Apr 03:13
· 3 commits to master since this release

Added

  • compat compile option to enable recursive field lookup. When set to true, if a template variable is not found in the current scope it will automatically be looked up in parent scopes, matching Mustache's behavior.
  • Official Mustache spec tests are now run to verify compat functionality.
  • partialResolver runtime option: a Closure(string $name): ?Closure called lazily the first time each unresolved partial is called. This replaces the previous compile-time partialResolver option.

Changed

  • Improved compiler performance and reduced memory usage by simplifying internal state.
  • Optimized rendering of indented partials.

Removed

  • partials and partialResolver compile-time options. These options baked partials into the generated PHP closure, causing each partial to be recompiled and duplicated across every template that referenced it. Partials should now be supplied when invoking a template via the partials or partialResolver runtime options.

    Upgrade: if you were passing partials via Options, move them to the runtime options instead:

    // Before
    $template = Handlebars::compile($source, new Options(
        partials: ['footer' => '<footer>...</footer>'],
        partialResolver: fn($name) => loadTemplate($name),
    ));
    echo $template($data);
    
    // After
    $template = Handlebars::compile($source);
    echo $template($data, [
        'partials' => ['footer' => Handlebars::compile('<footer>...</footer>')],
        'partialResolver' => fn($name) => Handlebars::compile(loadTemplate($name)),
    ]);

    This change makes it possible to precompile all partials in a directory, and then lazily import them on first use for optimal performance. See the example in the readme.

Fixed

  • Failure to invoke @data variables containing a closure when passed to if or unless helpers.
  • Hoisted block closures leaked into the caller's scope when a precompiled template was loaded via include/require.
  • Hash arguments passed to a partial were ignored when the partial was invoked in certain non-array contexts.
  • Block helpers returning a nested or non-list array were not stringified correctly.
  • Partials with literal names ({{> true}}, {{> false}}, {{> null}}, {{> undefined}}) were not resolved correctly: boolean names caused a type error, and null/undefined silently rendered nothing.