// Package reporttemplate provides embedded Markdown templates and partials. package reporttemplate import ( "bytes" "embed" "fmt" "text/template" ) //go:embed templates/*.md.tmpl templates/partials/*.md.tmpl var assets embed.FS var templates = map[string]string{ "daily": "templates/daily.md.tmpl", "hourly": "templates/hourly.md.tmpl", "today": "templates/today.md.tmpl", "tomorrow": "templates/tomorrow.md.tmpl", } var templatePartials = []string{ "templates/partials/alert_digest.md.tmpl", "templates/partials/daypart_forecast.md.tmpl", "templates/partials/precipitation_timing.md.tmpl", "templates/partials/today_daypart_forecast.md.tmpl", } func Template(id string) (string, error) { path, ok := templates[id] if !ok { return "", fmt.Errorf("unknown report template %q", id) } data, err := assets.ReadFile(path) if err != nil { return "", fmt.Errorf("read report template %q: %w", id, err) } return string(data), nil } func Render(id string, data any) ([]byte, error) { source, err := Template(id) if err != nil { return nil, err } tmpl, err := template.New(id).Funcs(templateFuncs()).Option("missingkey=error").Parse(source) if err != nil { return nil, fmt.Errorf("parse report template %q: %w", id, err) } for _, path := range templatePartials { partial, err := assets.ReadFile(path) if err != nil { return nil, fmt.Errorf("read report template partial %q: %w", path, err) } tmpl, err = tmpl.Parse(string(partial)) if err != nil { return nil, fmt.Errorf("parse report template partial %q: %w", path, err) } } var out bytes.Buffer if err := tmpl.Execute(&out, data); err != nil { return nil, fmt.Errorf("render report template %q: %w", id, err) } return out.Bytes(), nil }