62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
|
|
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
|
||
|
|
}
|