forked from dingoblog/dingo
/
slug.go
65 lines (62 loc) · 1.89 KB
/
slug.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package model
import (
"strconv"
"strings"
"unicode"
)
// GenerateSlug generates a URL-friendly slug. The table is one of "posts",
// "tags", "navigation", or "users".
func GenerateSlug(input string, table string) string {
output := strings.Map(func(r rune) rune {
switch {
case r == ' ', r == '-':
return '-'
case r == '_', unicode.IsLetter(r), unicode.IsDigit(r):
return r
default:
return -1
}
}, strings.ToLower(strings.TrimSpace(input)))
// Maximum of 75 characters for slugs right now
maxLength := 75
if len([]rune(output)) > maxLength {
runes := []rune(output)[:maxLength]
// Try to cut at '-' until length of (maxLength - (maxLength / 2)) characters
for i := (maxLength - 1); i > (maxLength - (maxLength / 2)); i-- {
if runes[i] == '-' {
runes = runes[:i]
break
}
}
output = string(runes)
}
// Don't allow a few specific slugs that are used by the blog
if table == "posts" && (output == "rss" || output == "tag" || output == "author" || output == "page" || output == "admin") {
output = generateUniqueSlug(output, table, 2)
} else if table == "tags" || table == "navigation" { // We want duplicate tag and navigation slugs
return output
}
return generateUniqueSlug(output, table, 1)
}
func generateUniqueSlug(slug string, table string, suffix int) string {
// Recursive function
slugToCheck := slug
if suffix > 1 { // If this is not the first try, add the suffix and try again
slugToCheck = slug + "-" + strconv.Itoa(suffix)
}
var err error
if table == "tags" { // Not needed at the moment. Tags with the same name should have the same slug.
tag := &Tag{Slug: slugToCheck}
err = tag.GetTagBySlug()
} else if table == "posts" {
post := new(Post)
err = post.GetPostBySlug(slugToCheck)
} else if table == "users" {
u := new(User)
err = u.GetUserBySlug()
}
if err == nil {
return generateUniqueSlug(slug, table, suffix+1)
}
return slugToCheck
}