Files
photoprism/pkg/clean/dnslabel.go
2025-09-24 08:28:38 +02:00

65 lines
1.3 KiB
Go

package clean
import (
"strings"
"unicode"
)
// DNSLabel normalizes a string to a DNS label per our rules:
// - lowercase
// - allowed chars: [a-z0-9-]
// - other runes (including separators like space, '_', '.', '/', ':') map to '-'
// - collapses multiple '-' and trims leading/trailing '-'
// - maximum length 32 characters; trimming preserves start/end as alnum when possible
// Returns an empty string if no valid characters remain after normalization.
func DNSLabel(s string) string {
if s == "" {
return ""
}
const maxLen = 32
s = strings.ToLower(s)
var b strings.Builder
b.Grow(len(s))
prevDash := false
for _, r := range s {
switch {
case r >= 'a' && r <= 'z', r >= '0' && r <= '9', r == '-':
if r == '-' {
if prevDash {
continue
}
prevDash = true
} else {
prevDash = false
}
b.WriteRune(r)
default:
// Treat any separator/invalid as a single '-'.
// Includes space, underscore, dot, slash, colon, and others.
if unicode.IsSpace(r) || r != 0 {
if !prevDash {
b.WriteByte('-')
prevDash = true
}
}
}
}
out := strings.Trim(b.String(), "-")
if out == "" {
return ""
}
if len(out) > maxLen {
out = out[:maxLen]
out = strings.Trim(out, "-")
if out == "" {
return ""
}
}
return out
}