package models import ( "strings" "time" "unicode" ) type Category struct { ID int64 `json:"id"` SiteID int64 `json:"site_id"` GUID string `json:"guid"` Name string `json:"name"` Slug string `json:"slug"` Description string `json:"description"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // CategoryWithCount is a Category plus the count of published posts in it. type CategoryWithCount struct { Category PostCount int DescriptionBrief string } // GenerateCategorySlug creates a URL-safe slug from a category name. // e.g. "Go Programming" -> "go-programming" func GenerateCategorySlug(name string) string { var sb strings.Builder prevDash := false for _, c := range strings.TrimSpace(name) { if unicode.IsLetter(c) || unicode.IsNumber(c) { sb.WriteRune(unicode.ToLower(c)) prevDash = false } else if unicode.IsSpace(c) || c == '-' || c == '_' { if !prevDash && sb.Len() > 0 { sb.WriteRune('-') prevDash = true } } } result := sb.String() return strings.TrimRight(result, "-") } // BriefDescription returns the first sentence or line of the description. func BriefDescription(desc string) string { if desc == "" { return "" } for i, c := range desc { if c == '\n' { return desc[:i] } if c == '.' && i+1 < len(desc) { return desc[:i+1] } } return desc }