Skip to content

Delimiter does not propagate into lambdas #150

@devhl-labs

Description

@devhl-labs

Delimiter changes not propagated to lambda render callback

Description

When a template changes delimiters using {{=<% %>=}} or similar, the new delimiters work correctly in the outer template context, but the render callback provided to lambdas continues to use the default {{}} delimiters instead of the changed delimiters.

This means that lambda sections cannot properly render content when the parent template has changed delimiters.

Expected Behavior

The render callback passed to lambdas should respect delimiter changes made in the parent template, allowing lambdas to render content using the currently active delimiters.

Actual Behavior

The render callback always uses the default {{}} delimiters, regardless of delimiter changes in the parent template. This causes content within lambda sections to be output literally instead of being interpolated.

Minimal Reproducible Example

C# Version

using System;
using Stubble.Core.Builders;

var renderer = new StubbleBuilder().Build();

var data = new
{
    value = "World",
    lambdas = new
    {
        test = (Func<string, Func<string, string>, object>)((template, render) =>
        {
            return render(template);
        })
    }
};

var template = @"
{{=<% %>=}}
Outside lambda: <% value %>
Inside lambda: <%#lambdas.test%><% value %><%/lambdas.test%>
";

var result = renderer.Render(template, data);
Console.WriteLine(result);

Expected output:

Outside lambda: World
Inside lambda: World

Actual output:

Outside lambda: World
Inside lambda: <% value %>

PowerShell Version

# Load Stubble assembly
Add-Type -Path "path/to/Stubble.Core.dll"

$renderer = (New-Object Stubble.Core.Builders.StubbleBuilder).Build()

$testLambda = [System.Func[string, [System.Func[string, string]], object]] {
    param($template, $render)
    return $render.Invoke($template)
}.GetNewClosure()

$data = @{
    value = "World"
    lambdas = @{ test = $testLambda }
}

$template = @"
{{=<% %>=}}
Outside lambda: <% value %>
Inside lambda: <%#lambdas.test%><% value %><%/lambdas.test%>
"@

$result = $renderer.Render($template, $data)
Write-Host $result

Impact

This limitation prevents lambdas from being used effectively when:

  • Templates need to change delimiters to avoid conflicts with the output format
  • Lambdas need to render nested content with custom delimiters
  • Building template systems where delimiter changes are part of the template logic

Workaround

The only current workaround is to have the lambda create its own renderer instance and call renderer.Render() with a new data context, but this:

  1. Loses the ability to use the render callback for simple variable interpolation
  2. Requires passing the renderer instance to every lambda
  3. Adds significant overhead
  4. Defeats the purpose of the render callback parameter

Environment

  • Stubble.Core version: 1.10.8
  • .NET version: 8.0 / PowerShell 7+

Specification Reference

According to the Mustache specification, lambdas should receive a render callback that interpolates variables in the current context. While the spec doesn't explicitly address delimiter changes, the principle suggests that the render callback should use the current rendering context, including any delimiter changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions