138 lines
3.4 KiB
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
|
||
|
|
}
|