package template import ( "strings" "unicode" "golang.org/x/text/cases" "golang.org/x/text/language" ) // ToUpper converts a string to uppercase func ToUpper(s string) string { return strings.ToUpper(s) } // ToLower converts a string to lowercase func ToLower(s string) string { return strings.ToLower(s) } // ToCamelCase converts snake_case to camelCase // Examples: user_name → userName, http_request → httpRequest func ToCamelCase(s string) string { if s == "" { return "" } parts := strings.Split(s, "_") for i, part := range parts { if i == 0 { parts[i] = strings.ToLower(part) } else { parts[i] = capitalize(part) } } return strings.Join(parts, "") } // ToPascalCase converts snake_case to PascalCase // Examples: user_name → UserName, http_request → HTTPRequest func ToPascalCase(s string) string { if s == "" { return "" } parts := strings.Split(s, "_") for i, part := range parts { parts[i] = capitalize(part) } return strings.Join(parts, "") } // ToSnakeCase converts PascalCase/camelCase to snake_case // Examples: UserName → user_name, HTTPRequest → http_request func ToSnakeCase(s string) string { if s == "" { return "" } var result strings.Builder var prevUpper bool var nextUpper bool runes := []rune(s) for i, r := range runes { isUpper := unicode.IsUpper(r) if i+1 < len(runes) { nextUpper = unicode.IsUpper(runes[i+1]) } else { nextUpper = false } if i > 0 && isUpper { // Add underscore before uppercase letter if: // 1. Previous char was lowercase, OR // 2. Next char is lowercase (end of acronym) if !prevUpper || (!nextUpper && i+1 < len(runes)) { result.WriteRune('_') } } result.WriteRune(unicode.ToLower(r)) prevUpper = isUpper } return result.String() } // ToKebabCase converts snake_case or PascalCase/camelCase to kebab-case // Examples: user_name → user-name, UserName → user-name func ToKebabCase(s string) string { // First convert to snake_case, then replace underscores with hyphens snakeCase := ToSnakeCase(s) return strings.ReplaceAll(snakeCase, "_", "-") } // Title capitalizes the first letter of each word func Title(s string) string { caser := cases.Title(language.English) src := []byte(s) dest := []byte(s) _, _, _ = caser.Transform(dest, src, true) return string(dest) } // Pluralize converts a singular word to plural // Basic implementation with common English rules func Pluralize(s string) string { if s == "" { return "" } // Special cases irregular := map[string]string{ "person": "people", "child": "children", "tooth": "teeth", "foot": "feet", "man": "men", "woman": "women", "mouse": "mice", "goose": "geese", "ox": "oxen", "datum": "data", "medium": "media", "analysis": "analyses", "crisis": "crises", "status": "statuses", } if plural, ok := irregular[strings.ToLower(s)]; ok { return plural } // Already plural (ends in 's' but not 'ss' or 'us') if strings.HasSuffix(s, "s") && !strings.HasSuffix(s, "ss") && !strings.HasSuffix(s, "us") { return s } // Words ending in s, x, z, ch, sh if strings.HasSuffix(s, "s") || strings.HasSuffix(s, "x") || strings.HasSuffix(s, "z") || strings.HasSuffix(s, "ch") || strings.HasSuffix(s, "sh") { return s + "es" } // Words ending in consonant + y if len(s) >= 2 && strings.HasSuffix(s, "y") { prevChar := s[len(s)-2] if !isVowel(prevChar) { return s[:len(s)-1] + "ies" } } // Words ending in f or fe if strings.HasSuffix(s, "f") { return s[:len(s)-1] + "ves" } if strings.HasSuffix(s, "fe") { return s[:len(s)-2] + "ves" } // Words ending in consonant + o if len(s) >= 2 && strings.HasSuffix(s, "o") { prevChar := s[len(s)-2] if !isVowel(prevChar) { return s + "es" } } // Default: add 's' return s + "s" } // Singularize converts a plural word to singular // Basic implementation with common English rules func Singularize(s string) string { if s == "" { return "" } // Special cases irregular := map[string]string{ "people": "person", "children": "child", "teeth": "tooth", "feet": "foot", "men": "man", "women": "woman", "mice": "mouse", "geese": "goose", "oxen": "ox", "data": "datum", "media": "medium", "analyses": "analysis", "crises": "crisis", "statuses": "status", } if singular, ok := irregular[strings.ToLower(s)]; ok { return singular } // Words ending in ies if strings.HasSuffix(s, "ies") && len(s) > 3 { return s[:len(s)-3] + "y" } // Words ending in ves if strings.HasSuffix(s, "ves") { return s[:len(s)-3] + "f" } // Words ending in ses, xes, zes, ches, shes if strings.HasSuffix(s, "ses") || strings.HasSuffix(s, "xes") || strings.HasSuffix(s, "zes") || strings.HasSuffix(s, "ches") || strings.HasSuffix(s, "shes") { return s[:len(s)-2] } // Words ending in s (not ss) if strings.HasSuffix(s, "s") && !strings.HasSuffix(s, "ss") { return s[:len(s)-1] } // Already singular return s } // Trim trims whitespace from both ends func Trim(s string) string { return strings.TrimSpace(s) } // TrimPrefix removes the prefix from the string if present func TrimPrefix(s, prefix string) string { return strings.TrimPrefix(s, prefix) } // TrimSuffix removes the suffix from the string if present func TrimSuffix(s, suffix string) string { return strings.TrimSuffix(s, suffix) } // Replace replaces occurrences of old with new (n times, or all if n < 0) func Replace(s, old, newstr string, n int) string { return strings.Replace(s, old, newstr, n) } // StringContains checks if substr is within s func StringContains(s, substr string) bool { return strings.Contains(s, substr) } // HasPrefix checks if string starts with prefix func HasPrefix(s, prefix string) bool { return strings.HasPrefix(s, prefix) } // HasSuffix checks if string ends with suffix func HasSuffix(s, suffix string) bool { return strings.HasSuffix(s, suffix) } // Split splits string by separator func Split(s, sep string) []string { return strings.Split(s, sep) } // Join joins string slice with separator func Join(parts []string, sep string) string { return strings.Join(parts, sep) } // capitalize capitalizes the first letter and handles common acronyms func capitalize(s string) string { if s == "" { return "" } upper := strings.ToUpper(s) // Handle common acronyms acronyms := map[string]bool{ "ID": true, "UUID": true, "GUID": true, "URL": true, "URI": true, "HTTP": true, "HTTPS": true, "API": true, "JSON": true, "XML": true, "SQL": true, "HTML": true, "CSS": true, "RID": true, } if acronyms[upper] { return upper } // Capitalize first letter runes := []rune(s) runes[0] = unicode.ToUpper(runes[0]) return string(runes) } // isVowel checks if a byte is a vowel func isVowel(c byte) bool { c = byte(unicode.ToLower(rune(c))) return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' }