Files
OpsLog/internal/qslcard/render.go
T
2026-06-11 21:54:35 +02:00

77 lines
2.1 KiB
Go

package qslcard
import (
"sync"
"hamlog/internal/applog"
)
// CountryInfo resolves the "auto" country element: a display label and the
// ISO code of the embedded flag ("" = no flag available).
type CountryInfo struct {
Label string `json:"label"`
FlagISO string `json:"flag_iso"`
}
// RenderModel is a template with every placeholder filled, ready for the
// frontend to instantiate as SVG (editor preview and final rasterization use
// the same model so output cannot drift from preview).
type RenderModel struct {
Template Template `json:"template"`
QSOFields map[string]string `json:"qso_fields"` // values for qso_box.fields
}
// warnedPlaceholders dedupes the "unknown placeholder" log line so a bulk
// render doesn't flood the log.
var warnedPlaceholders sync.Map
// Resolve substitutes {profile.*} and {qso.*} placeholders from vars (keys
// are the full "namespace.key" form) and resolves the country element. An
// unknown placeholder resolves to "" and is logged once.
func Resolve(t Template, vars map[string]string, country CountryInfo) RenderModel {
resolve := func(text string) string {
return placeholderRe.ReplaceAllStringFunc(text, func(m string) string {
key := m[1 : len(m)-1] // strip braces → "namespace.key"
if v, ok := vars[key]; ok {
return v
}
if _, seen := warnedPlaceholders.LoadOrStore(key, true); !seen {
applog.Printf("qslcard: unknown placeholder %q resolves to empty", m)
}
return ""
})
}
out := t
out.Elements = make([]Element, len(t.Elements))
copy(out.Elements, t.Elements)
for i := range out.Elements {
e := &out.Elements[i]
switch e.Type {
case ElemCallsign, ElemOperator, ElemInfoLine:
e.Text = resolve(e.Text)
case ElemCountry:
if e.Flag == "auto" {
e.Flag = country.FlagISO
}
if e.Label == "auto" {
e.Label = country.Label
}
}
}
if t.QSOBox != nil {
box := *t.QSOBox
box.Title = resolve(box.Title)
box.Footer = resolve(box.Footer)
out.QSOBox = &box
}
model := RenderModel{Template: out, QSOFields: map[string]string{}}
if out.QSOBox != nil {
for _, f := range out.QSOBox.Fields {
model.QSOFields[f] = vars["qso."+f]
}
}
return model
}