"""Shared Jinja2 environment with custom filters for the dashboard. Imported by both routers/pages.py and routers/api.py so the filters are registered exactly once.""" from __future__ import annotations from pathlib import Path from fastapi.templating import Jinja2Templates TEMPLATE_DIR = Path(__file__).resolve().parent / "templates" def _fmt_price(v: float | None) -> str: """Format a price in a way that's readable in dense terminal tables. Avoids scientific notation for large round numbers (FTSE 25,962, not 2.596e+04) and keeps enough precision for FX rates like 0.8725 EUR/GBP.""" if v is None: return "—" av = abs(v) if av >= 1000: return f"{v:,.2f}" if av >= 10: return f"{v:.2f}" if av >= 1: return f"{v:.4f}" return f"{v:.4f}" def _fmt_signed(v: float | None, decimals: int = 2) -> str: if v is None: return "—" return f"{v:+,.{decimals}f}" def _fmt_money(v: float | None) -> str: if v is None: return "—" return f"{v:,.2f}" templates = Jinja2Templates(directory=str(TEMPLATE_DIR)) templates.env.filters["price"] = _fmt_price templates.env.filters["signed"] = _fmt_signed templates.env.filters["money"] = _fmt_money