Kida 0.2.8

Yield directive, render-path performance, region defaults, and imported macro namespaces

Released 2026-03-18.

Kida 0.2.8 adds the{% yield %}directive for explicit slot forwarding, a set of render-path performance optimizations, region default expressions, and namespace injection for imported macros.

Highlights

  • {% yield %}directive — Context-independent slot rendering for nested macro composition. Unlike{% slot %} inside {% call %} blocks, {% yield %}always produces a render reference regardless of block context.
  • Render-path performance — mtime-basedauto_reloadstale checks, pre-computed block wrappers, single-pass context merge,lookup_scopefast path, and single-pass tag counting.
  • Region default expressions — Optional region parameters now support arbitrary expressions as defaults (e.g.meta=page.metadata, count=items | length), evaluated at call time.
  • Region_blocksparam — Region callables receive the block dispatch dict for inherited block rendering.
  • Imported macro namespaces — Imported macros carry their defining template's namespace so cross-template macro calls resolve correctly.

Added

Slot Forwarding

  • {% yield %} directive — Explicit slot forwarding for nested {% def %} / {% call %}chains. {% yield %} renders the caller's default slot; {% yield name %}renders a named slot. Replaces the fragile{% slot x %}{% slot x %}{% end %}workaround.

Regions

  • Region default expressions — Optional region parameters support arbitrary expressions as defaults. Defaults are evaluated at call time from the caller's context. Static analysis (depends_on) correctly captures paths from complex defaults.
  • Region_blocksparameter — Region callables now receive the block dispatch dict, enabling regions to render inherited blocks withinrender_block()flows.
  • Regions example — Newexamples/regions/with a working app, templates, and tests.

Macros

  • Imported macro namespace injectionMacroWrappernow injects the defining template's namespace as_outer_ctx, so imported macros can call sibling macros without the caller importing every dependency.

Changed

  • mtime-based stale checksauto_reload checks file mtime (nanosecond st_mtime_ns) before reading and hashing source. Skips the slow path when the file hasn't been modified.
  • Pre-computed block wrappersCachedBlocksDictbuilds wrapper functions once at init instead of creating a new closure on every.get(), .setdefault(), or []access.
  • Single-pass context merge_build_render_context uses {**globals, **args, **kwargs}dict unpacking instead of filteringUNDEFINED and calling .update()multiple times.
  • lookup_scope fast path — Skips the reversed() iterator when scope_stackis empty (the common case at template top level and in templates without nested{% set %}).
  • Single-pass tag countingestimate_template_weightscans template source once instead of four separatestr.count()calls for block, macro, extends, and include tags.
  • Compiler node dispatch table — Built once at__init__instead of being reconstructed per compilation pass.

Upgrade Notes

  1. No breaking changes. All additions are backward-compatible.
  2. Performance improvements apply automatically — no configuration changes needed.