Files
nebula/internal/generator/strings.go

138 lines
3.4 KiB
Go

package generator
import (
"regexp"
"strings"
)
var (
kebabRegex = regexp.MustCompile(`[-_]`)
mdLinkRegex = regexp.MustCompile(`\[([^\]]+)\]\([^)]+\)`)
)
// ToPascalCase converts kebab-case or snake_case to PascalCase
func ToPascalCase(s string) string {
parts := kebabRegex.Split(s, -1)
for i, p := range parts {
if len(p) > 0 {
parts[i] = strings.ToUpper(p[:1]) + p[1:]
}
}
return strings.Join(parts, "")
}
// ToCamelCase converts kebab-case or snake_case to camelCase
func ToCamelCase(s string) string {
p := ToPascalCase(s)
if len(p) > 0 {
return strings.ToLower(p[:1]) + p[1:]
}
return p
}
// StripWaPrefix removes the "wa-" prefix from component names
func StripWaPrefix(s string) string {
return strings.TrimPrefix(s, "wa-")
}
// ToGoType converts TypeScript type to Go type
func ToGoType(tsType string) string {
tsType = strings.TrimSpace(tsType)
switch {
case tsType == "boolean":
return "bool"
case tsType == "number":
return "float64"
case tsType == "string":
return "string"
case tsType == "string | undefined", tsType == "string | null":
return "string"
case tsType == "number | undefined", tsType == "number | null":
return "float64"
case tsType == "boolean | undefined", tsType == "boolean | null":
return "bool"
case strings.HasPrefix(tsType, "'") && strings.Contains(tsType, "|"):
// Union of string literals -> string
return "string"
case strings.Contains(tsType, "|"):
// Complex union, default to string
return "string"
default:
return "string"
}
}
// ToBuilderType returns the type used in builder methods (always non-pointer for fluent API)
func ToBuilderType(tsType string) string {
return ToGoType(tsType)
}
// IsBoolean checks if the TypeScript type is boolean
func IsBoolean(tsType string) bool {
return strings.Contains(tsType, "boolean")
}
// IsNumber checks if the TypeScript type is numeric
func IsNumber(tsType string) bool {
return tsType == "number" || strings.HasPrefix(tsType, "number")
}
// CleanDescription cleans markdown and truncates description
func CleanDescription(s string) string {
if s == "" {
return ""
}
// Take first line
lines := strings.Split(s, "\n")
first := strings.TrimSpace(lines[0])
// Strip markdown links
first = mdLinkRegex.ReplaceAllString(first, "$1")
// Remove backticks
first = strings.ReplaceAll(first, "`", "")
// Truncate
if len(first) > 120 {
first = first[:117] + "..."
}
return first
}
// ExtractEnumValues extracts string literal values from a union type
func ExtractEnumValues(tsType string) []string {
if !strings.Contains(tsType, "'") {
return nil
}
re := regexp.MustCompile(`'([^']+)'`)
matches := re.FindAllStringSubmatch(tsType, -1)
values := make([]string, 0, len(matches))
for _, m := range matches {
if len(m) > 1 {
values = append(values, m[1])
}
}
return values
}
// ToEventName converts wa-event-name to OnEventName
func ToEventName(s string) string {
s = strings.TrimPrefix(s, "wa-")
return "On" + ToPascalCase(s)
}
// ToSlotName converts slot name to Go-friendly name
func ToSlotName(s string) string {
if s == "" {
return "Default"
}
return ToPascalCase(s)
}
// EscapeGoString escapes a string for use in Go source code
func EscapeGoString(s string) string {
s = strings.ReplaceAll(s, "\\", "\\\\")
s = strings.ReplaceAll(s, "\"", "\\\"")
s = strings.ReplaceAll(s, "\n", "\\n")
s = strings.ReplaceAll(s, "\t", "\\t")
return s
}