package main import "strconv" // getString extracts a string value from a content map. Returns "" on miss/wrong-type. func getString(content map[string]any, key string) string { if v, ok := content[key].(string); ok { return v } return "" } // getStringWithDefault is like getString but returns dflt if the key is missing or non-string. func getStringWithDefault(content map[string]any, key, dflt string) string { if v, ok := content[key].(string); ok && v != "" { return v } return dflt } // getBool extracts a boolean value from a content map. Accepts bool, "true"/"false", // "on"/"off", "yes"/"no", and numerics. Returns dflt when missing or unparsable. func getBool(content map[string]any, key string, dflt bool) bool { switch v := content[key].(type) { case bool: return v case string: switch v { case "true", "on", "yes", "1": return true case "false", "off", "no", "0", "": return false } case float64: return v != 0 case int: return v != 0 } return dflt } // getSlice extracts a slice of object-shaped entries from a content map. func getSlice(content map[string]any, key string) []map[string]any { v, ok := content[key].([]any) if !ok { return nil } out := make([]map[string]any, 0, len(v)) for _, item := range v { if m, ok := item.(map[string]any); ok { out = append(out, m) } } return out } // getLink reads a {label, href} link object. Tolerates string values // (interpreted as href, label = href) and missing keys. func getLink(content map[string]any, key string) Link { v := content[key] switch x := v.(type) { case map[string]any: return Link{Label: getString(x, "label"), Href: getString(x, "href")} case string: return Link{Label: x, Href: x} } return Link{} } // Link is a {label, href} pair used by hero / nav / footer blocks. type Link struct { Label string Href string } // safeHref returns "#" when href is empty so templ.SafeURL never receives "". func safeHref(href string) string { if href == "" { return "#" } return href } // parseHeadingLevel parses a 1..6 heading level. Defaults to 2 for safety. func parseHeadingLevel(content map[string]any) int { switch v := content["level"].(type) { case float64: l := int(v) if l >= 1 && l <= 6 { return l } case int: if v >= 1 && v <= 6 { return v } case string: if l, err := strconv.Atoi(v); err == nil && l >= 1 && l <= 6 { return l } } return 2 }