themes-cyberpunk/helpers.go
Alex Dunmow 313ebaf296 initial: theme plugin cyberpunk
Bootstrapped during the 2026-06-06 BlockNinja consolidation. Was previously
an unversioned directory inside ~/src/blockninja-themes/cyberpunk.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 14:11:25 +08:00

103 lines
2.4 KiB
Go

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
}