Skip to content

fix: preserve parent data context for primitive optional blocks#91

Open
yashhzd wants to merge 1 commit intoaccordproject:mainfrom
yashhzd:yashhzd/i2/fix-variables-in-conditional-optional-blocks
Open

fix: preserve parent data context for primitive optional blocks#91
yashhzd wants to merge 1 commit intoaccordproject:mainfrom
yashhzd:yashhzd/i2/fix-variables-in-conditional-optional-blocks

Conversation

@yashhzd
Copy link

@yashhzd yashhzd commented Feb 26, 2026

Description

Fixes a bug where named variables inside {{#optional}} blocks with primitive types (string, number, boolean) would fail at runtime because the JSON path resolver incorrectly navigated into the property scope.

Root cause: OptionalDefinition is classified as a NAVIGATION_NODE, so getJsonPath would append the property name to the path. For {{age}} inside {{#optional age}}, this produced $['age']['age'] instead of the correct $['age']. Additionally, generateOptionalBlocks tried to treat primitive values as objects during pre-processing.

Closes accordproject/template-playground#2

Changes

TemplateMarkInterpreter.ts

  1. getJsonPath — Skip path navigation for OptionalDefinition nodes that guard primitive types (detected via ModelUtil.isPrimitiveType). This ensures variables inside primitive optional blocks resolve from the parent data context.

  2. generateOptionalBlocks — Skip pre-processing for primitive optional values (typeof value !== 'object'). Primitive values don't need recursive agreement generation — the normal traverse handles them correctly with the full parent data context.

Test Updates

  • Updated optional_comprehensive/template.md and optional-nested/template.md to use named variables (e.g., {{age}}) instead of {{this}} for primitive optional blocks
  • Added new conditional-variables test template with model, template, and data files

All 28 tests pass (27 existing + 1 new). The 3 pre-existing failures in TemplateArchiveProcessor.test.ts are unrelated (missing --experimental-vm-modules flag).

Related

This fix works in conjunction with a companion PR on markdown-transform that addresses the type-checking (parsing) side of the same issue.

Author Checklist

  • Code compiles and passes tests
  • New tests added for changed behavior
  • Existing test templates updated for consistency
  • Signed-off-by for DCO

When an optional block guards a primitive value (string, number,
boolean), the runtime incorrectly navigated into the property scope,
causing named variables like {{age}} inside {{#optional age}} to
resolve as $['age']['age'] instead of $['age']. This also affected
the pre-processing step which tried to treat primitive values as
objects.

Changes:
- getJsonPath: skip path navigation for primitive OptionalDefinition
  nodes so variables resolve from the parent data context
- generateOptionalBlocks: skip pre-processing for primitive optional
  values and let the normal traverse handle them
- Update test templates to use named variables instead of {{this}}
  for primitive optionals
- Add conditional-variables test template

Closes accordproject/template-playground#2

Signed-off-by: Yash Goel <162511050+yashhzd@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cannot use variables inside an #if block

1 participant