Files
renamer/internal/extension/normalize.go
2025-10-30 10:31:53 +08:00

60 lines
1.7 KiB
Go

package extension
import "strings"
// NormalizeSourceExtensions returns case-insensitive unique source extensions while preserving
// the first-seen display token for each canonical value. Duplicate entries are surfaced for warnings.
func NormalizeSourceExtensions(inputs []string) (canonical []string, display []string, duplicates []string) {
seen := make(map[string]struct{})
for _, raw := range inputs {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
continue
}
canon := CanonicalExtension(trimmed)
if _, exists := seen[canon]; exists {
duplicates = append(duplicates, trimmed)
continue
}
seen[canon] = struct{}{}
canonical = append(canonical, canon)
display = append(display, trimmed)
}
return canonical, display, duplicates
}
// NormalizeTargetExtension trims surrounding whitespace but preserves caller-provided casing.
func NormalizeTargetExtension(target string) string {
return strings.TrimSpace(target)
}
// CanonicalExtension is the shared case-folded representation used for comparisons and maps.
func CanonicalExtension(value string) string {
return strings.ToLower(strings.TrimSpace(value))
}
// ExtensionsEqual reports true when two extensions match case-insensitively.
func ExtensionsEqual(a, b string) bool {
return CanonicalExtension(a) == CanonicalExtension(b)
}
// IdentifyNoOpSources returns the original tokens that would be no-ops against the target extension.
func IdentifyNoOpSources(original []string, target string) []string {
if len(original) == 0 {
return nil
}
canonTarget := CanonicalExtension(target)
var noOps []string
for _, token := range original {
if CanonicalExtension(token) == canonTarget {
noOps = append(noOps, token)
}
}
return noOps
}