Phase 4: Jinja bridge for incremental s-expression migration

Two-way bridge: sexp() Jinja global renders s-expression components in
templates, register_components() loads definitions at startup. Includes
~link-card component test proving unified replacement of 5 per-service
Jinja fragment templates.

19 new tests (218 total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 14:34:42 +00:00
parent fbb7a1422c
commit 5d9f1586af
3 changed files with 360 additions and 0 deletions

View File

@@ -687,6 +687,27 @@ Each phase is independently deployable. The end state: a platform where the appl
- 27 tests: passthrough rendering (4), I/O collection (8), fragment resolution (3), query resolution (2), parallel I/O (1), request context (4), error handling (2), mixed content (3)
- **199 total tests across all 4 files, all passing**
### Phase 4: Jinja Bridge — COMPLETE
**Branch:** `sexpression`
**Delivered** (`shared/sexp/`):
- `jinja_bridge.py` — Two-way bridge between Jinja and s-expressions:
- `sexp(source, **kwargs)` — sync render for Jinja templates: `{{ sexp('(~card :title "Hi")') | safe }}`
- `sexp_async(source, **kwargs)` — async render with I/O resolution
- `register_components(sexp_source)` — load component definitions at startup
- `get_component_env()` — access the shared component registry
- `setup_sexp_bridge(app)` — register `sexp` and `sexp_async` as Jinja globals
- `_get_request_context()` — auto-builds RequestContext from Quart request
**Integration point**: Call `setup_sexp_bridge(app)` after `setup_jinja(app)` in app factories. Components registered via `register_components()` are available globally across all templates.
**First migration target: `~link-card`** — unified component replacing 5 separate Jinja templates (`blog/fragments/link_card.html`, `market/fragments/link_card.html`, `events/fragments/link_card.html`, `federation/fragments/link_card.html`, `artdag/l1/app/templates/fragments/link_card.html`). The s-expression component handles image/no-image, brand, and is usable from both Jinja templates and s-expression trees.
**Tests** (`shared/sexp/tests/test_jinja_bridge.py`):
- 19 tests: sexp() rendering (5), component registration (6), link-card migration (5), sexp_async (3)
- **218 total tests across all 5 files, all passing**
### Test Infrastructure — COMPLETE
**Delivered:**