Skip to content

Lambdas have no reference of the current context #151

@devhl-labs

Description

@devhl-labs

Stubble: No way to get current scope path from within a lambda

Problem

Stubble lambdas receive (template, render) but have no way to determine which object in the data tree is currently being rendered. The render callback is scoped to the current context, but there's no API to inspect what that context is or where it sits in the data hierarchy.

This makes it impossible to write a lambda that resolves a relative path (like items) against the correct parent when the same template is used inside nested {{#section}} blocks.

Repro

var data = new Dictionary<string, object>
{
    ["root_items"] = new[] { new { name = "WRONG" } },
    ["wrapper"] = new Dictionary<string, object>
    {
        ["items"] = new[]
        {
            new { name = "A", cat = "x" },
            new { name = "B", cat = "y" }
        }
    }
};

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

// Lambda that needs to find "items" relative to the current scope
Func<string, Func<string, string>, object> groupBy = (template, render) =>
{
    // render("{{items}}") returns nothing useful — it stringifies the array
    // render("{{.}}") returns the wrapper object stringified
    // There is no way to get "wrapper" as the current scope path
    // so the lambda can't resolve "items" relative to "wrapper"
    return render(template);
};

data["lambdas"] = new Dictionary<string, object> { ["groupBy"] = groupBy };

// this groups array 'items' by property cat, the logic for that is in the lambda, but remove for brevity
var template = "{{#wrapper}}{{#lambdas.groupBy}}items|cat:remaining string is the actual template rendered{{/lambdas.groupBy}}{{/wrapper}}";
var result = stubble.Render(template, data);
// Lambda has no way to know it's inside "wrapper" to resolve "items" correctly

Expected

A way to access the current context's identity or path from within a lambda, e.g.:

  • A Context parameter or property on the render callback
  • A {{.__path__}} built-in variable
  • An overload like Func<string, Func<string, string>, Context, object>

Current workaround

Inject a metadata key (__scopePath) into every object in the data tree before rendering, then read it back via render("{{__scopePath}}"). This works but mutates user data.

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