forked from segmentio/go-camelcase
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkebab.go
74 lines (63 loc) · 1.52 KB
/
kebab.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
66
67
68
69
70
71
72
73
74
package strcase
const dashByte = '-'
// Kebab transform the given string as `kebab-case`.
func Kebab(s string) string {
idx := 0
hasLower := false
hasDash := false
lowercaseSinceDash := false
// loop through all good characters:
// - lowercase
// - digit
// - underscore (as long as the next character is lowercase or digit)
for ; idx < len(s); idx++ {
if isLower(s[idx]) {
hasLower = true
if hasDash {
lowercaseSinceDash = true
}
continue
} else if isDigit(s[idx]) {
continue
} else if s[idx] == dashByte && idx > 0 && idx < len(s)-1 && (isLower(s[idx+1]) || isDigit(s[idx+1])) {
hasDash = true
lowercaseSinceDash = false
continue
}
break
}
if idx == len(s) {
return s // no changes needed, can just borrow the string
}
// if we get here then we must need to manipulate the string
b := make([]byte, 0, 64)
b = append(b, s[:idx]...)
if isUpper(s[idx]) && (!hasLower || hasDash && !lowercaseSinceDash) {
for idx < len(s) && (isUpper(s[idx]) || isDigit(s[idx])) {
b = append(b, asciiLowercaseArray[s[idx]])
idx++
}
for idx < len(s) && (isLower(s[idx]) || isDigit(s[idx])) {
b = append(b, s[idx])
idx++
}
}
for idx < len(s) {
if !isAlphanumeric(s[idx]) {
idx++
continue
}
if len(b) > 0 {
b = append(b, dashByte)
}
for idx < len(s) && (isUpper(s[idx]) || isDigit(s[idx])) {
b = append(b, asciiLowercaseArray[s[idx]])
idx++
}
for idx < len(s) && (isLower(s[idx]) || isDigit(s[idx])) {
b = append(b, s[idx])
idx++
}
}
return string(b)
}