package content import ( "fmt" "html/template" "strings" "unicode/utf16" "thermograph/frontend/internal/config" "thermograph/frontend/internal/format" ) // FuncMap builds the template helper set (the Jinja globals/filters // content.py registered on its Environment). Pass it to render.New at boot — // html/template resolves names at parse time. // // Unit-dependent helpers (temp, temp_bare) take the active unit as their // FIRST argument: the Python scoped it in a ContextVar, but html/template // FuncMaps are engine-global, so per-request state must arrive through the // call. Every page context carries the active unit under the "unit" key // (same value as "unit_default"), so template call sites are // {{temp $.unit .high_f}} where Jinja had {{ temp(m.high_f) }}. func FuncMap(cfg config.Config) template.FuncMap { return template.FuncMap{ // temp / temp_bare / temp_class accept the loosely-typed values the // templates hand them: nullable *float64 payload fields, plain // float64s, and int literals (Jinja's {{ temp(-10) }}). "temp": func(unit, f any) template.HTML { return format.Temp(unitArg(unit), floatArg(f)) }, "temp_bare": func(unit, f any) template.HTML { return format.TempBare(unitArg(unit), floatArg(f)) }, "temp_class": func(f any) string { return format.TempClass(floatArg(f)) }, // The `ordinal` filter: {{ c.percentile|ordinal }} -> {{ordinal .percentile}}. "ordinal": format.PctOrdinal, // Search-engine ownership-verification tags, from env (empty // when unset). No backend dependency — the same two variables the // Python read, resolved once into config. "head_verify": func() template.HTML { return headVerifyHTML(cfg.GoogleVerify, cfg.BingVerify) }, // Jinja's |tojson (glossary_term.html.j2's inline JSON-LD): JSON with // the HTML-unsafe characters escaped so it can sit inside