mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-17 11:12:28 +08:00
feat: fix and add KebabCase/UpperKebabCase
This commit is contained in:
@@ -157,24 +157,19 @@ func PadStart(source string, size int, padStr string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// KebabCase covert string to kebab-case
|
// KebabCase covert string to kebab-case
|
||||||
|
// non letters and numbers will be ignored
|
||||||
|
// eg. "Foo-#1😄$_%^&*(1bar" => "foo-1-1-bar"
|
||||||
func KebabCase(s string) string {
|
func KebabCase(s string) string {
|
||||||
re := regexp.MustCompile(`[\W|_]+`)
|
strs := splitIntoStrings(s, false)
|
||||||
space := " "
|
return strings.Join(strs, "-")
|
||||||
match := re.ReplaceAllString(s, space)
|
}
|
||||||
rs := strings.Split(match, space)
|
|
||||||
|
|
||||||
var result []string
|
// UpperKebabCase covert string to upper KEBAB-CASE
|
||||||
for _, v := range rs {
|
// non letters and numbers will be ignored
|
||||||
splitWords := splitWordsToLower(v)
|
// eg. "Foo-#1😄$_%^&*(1bar" => "FOO-1-1-BAR"
|
||||||
if len(splitWords) > 0 {
|
func UpperKebabCase(s string) string {
|
||||||
result = append(result, splitWords...)
|
strs := splitIntoStrings(s, true)
|
||||||
}
|
return strings.Join(strs, "-")
|
||||||
// if v != "" {
|
|
||||||
// result = append(result, strings.ToLower(v))
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(result, "-")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SnakeCase covert string to snake_case
|
// SnakeCase covert string to snake_case
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package strutil
|
package strutil
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
// splitWordsToLower split a string into worlds by uppercase char
|
// splitWordsToLower split a string into worlds by uppercase char
|
||||||
func splitWordsToLower(s string) []string {
|
func splitWordsToLower(s string) []string {
|
||||||
@@ -38,3 +41,99 @@ func upperIndex(s string) []int {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func splitIntoStrings(s string, upperCase bool) []string {
|
||||||
|
var runes [][]rune
|
||||||
|
lastCharType := 0
|
||||||
|
charType := 0
|
||||||
|
|
||||||
|
// split into fields based on type of unicode character
|
||||||
|
for _, r := range s {
|
||||||
|
switch true {
|
||||||
|
case isLower(r):
|
||||||
|
charType = 1
|
||||||
|
case isUpper(r):
|
||||||
|
charType = 2
|
||||||
|
case isDigit(r):
|
||||||
|
charType = 3
|
||||||
|
default:
|
||||||
|
charType = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if charType == lastCharType {
|
||||||
|
runes[len(runes)-1] = append(runes[len(runes)-1], r)
|
||||||
|
} else {
|
||||||
|
runes = append(runes, []rune{r})
|
||||||
|
}
|
||||||
|
lastCharType = charType
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(runes)-1; i++ {
|
||||||
|
if isUpper(runes[i][0]) && isLower(runes[i+1][0]) {
|
||||||
|
runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
|
||||||
|
runes[i] = runes[i][:len(runes[i])-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter all none letters and none digit
|
||||||
|
var result []string
|
||||||
|
for _, rs := range runes {
|
||||||
|
if len(rs) > 0 && (unicode.IsLetter(rs[0]) || isDigit(rs[0])) {
|
||||||
|
if upperCase {
|
||||||
|
result = append(result, string(toUpperAll(rs)))
|
||||||
|
} else {
|
||||||
|
result = append(result, string(toLowerAll(rs)))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// isDigit checks if a character is digit ('0' to '9')
|
||||||
|
func isDigit(r rune) bool {
|
||||||
|
return r >= '0' && r <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
// isLower checks if a character is lower case ('a' to 'z')
|
||||||
|
func isLower(r rune) bool {
|
||||||
|
return r >= 'a' && r <= 'z'
|
||||||
|
}
|
||||||
|
|
||||||
|
// isUpper checks if a character is upper case ('A' to 'Z')
|
||||||
|
func isUpper(r rune) bool {
|
||||||
|
return r >= 'A' && r <= 'Z'
|
||||||
|
}
|
||||||
|
|
||||||
|
// toLower converts a character 'A' to 'Z' to its lower case
|
||||||
|
func toLower(r rune) rune {
|
||||||
|
if r >= 'A' && r <= 'Z' {
|
||||||
|
return r + 32
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// toLowerAll converts a character 'A' to 'Z' to its lower case
|
||||||
|
func toLowerAll(rs []rune) []rune {
|
||||||
|
for i := range rs {
|
||||||
|
rs[i] = toLower(rs[i])
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
// toUpper converts a character 'a' to 'z' to its upper case
|
||||||
|
func toUpper(r rune) rune {
|
||||||
|
if r >= 'a' && r <= 'z' {
|
||||||
|
return r - 32
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// toUpperAll converts a character 'a' to 'z' to its upper case
|
||||||
|
func toUpperAll(rs []rune) []rune {
|
||||||
|
for i := range rs {
|
||||||
|
rs[i] = toUpper(rs[i])
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import (
|
|||||||
|
|
||||||
func TestCamelCase(t *testing.T) {
|
func TestCamelCase(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCamelCase")
|
assert := internal.NewAssert(t, "TestCamelCase")
|
||||||
|
|
||||||
cases := map[string]string{
|
cases := map[string]string{
|
||||||
|
"": "",
|
||||||
"foobar": "foobar",
|
"foobar": "foobar",
|
||||||
"&FOO:BAR$BAZ": "fooBarBaz",
|
"&FOO:BAR$BAZ": "fooBarBaz",
|
||||||
"fooBar": "fooBar",
|
"fooBar": "fooBar",
|
||||||
@@ -21,14 +23,13 @@ func TestCamelCase(t *testing.T) {
|
|||||||
for k, v := range cases {
|
for k, v := range cases {
|
||||||
assert.Equal(v, CamelCase(k))
|
assert.Equal(v, CamelCase(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal("", CamelCase(""))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCapitalize(t *testing.T) {
|
func TestCapitalize(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCapitalize")
|
assert := internal.NewAssert(t, "TestCapitalize")
|
||||||
|
|
||||||
cases := map[string]string{
|
cases := map[string]string{
|
||||||
|
"": "",
|
||||||
"Foo": "Foo",
|
"Foo": "Foo",
|
||||||
"_foo": "_foo",
|
"_foo": "_foo",
|
||||||
"foobar": "Foobar",
|
"foobar": "Foobar",
|
||||||
@@ -41,31 +42,52 @@ func TestCapitalize(t *testing.T) {
|
|||||||
for k, v := range cases {
|
for k, v := range cases {
|
||||||
assert.Equal(v, Capitalize(k))
|
assert.Equal(v, Capitalize(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal("", Capitalize(""))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKebabCase(t *testing.T) {
|
func TestKebabCase(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestKebabCase")
|
assert := internal.NewAssert(t, "TestKebabCase")
|
||||||
|
|
||||||
cases := map[string]string{
|
cases := map[string]string{
|
||||||
|
"": "",
|
||||||
|
"foo-bar": "foo-bar",
|
||||||
|
"--Foo---Bar-": "foo-bar",
|
||||||
"Foo Bar-": "foo-bar",
|
"Foo Bar-": "foo-bar",
|
||||||
"foo_Bar": "foo-bar",
|
"foo_Bar": "foo-bar",
|
||||||
"fooBar": "foo-bar",
|
"fooBar": "foo-bar",
|
||||||
"FOOBAR": "f-o-o-b-a-r",
|
"FOOBAR": "foobar",
|
||||||
"FOO_BAR": "f-o-o-b-a-r",
|
"FOO_BAR": "foo-bar",
|
||||||
"__FOO_BAR__": "f-o-o-b-a-r",
|
"__FOO_BAR__": "foo-bar",
|
||||||
"$foo@Bar": "foo-bar",
|
"$foo@Bar": "foo-bar",
|
||||||
" $#$Foo 22 bar ": "foo-22-bar",
|
" $#$Foo 22 bar ": "foo-22-bar",
|
||||||
|
"Foo-#1😄$_%^&*(1bar": "foo-1-1-bar",
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range cases {
|
for k, v := range cases {
|
||||||
assert.Equal(v, KebabCase(k))
|
assert.Equal(v, KebabCase(k))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal("", KebabCase(""))
|
func TestUpperKebabCase(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestUpperKebabCase")
|
||||||
|
|
||||||
// assert.Equal("foo-1-1bar", KebabCase("Foo-#1😄$_%^&*(1bar"))
|
cases := map[string]string{
|
||||||
|
"": "",
|
||||||
|
"foo-bar": "FOO-BAR",
|
||||||
|
"--Foo---Bar-": "FOO-BAR",
|
||||||
|
"Foo Bar-": "FOO-BAR",
|
||||||
|
"foo_Bar": "FOO-BAR",
|
||||||
|
"fooBar": "FOO-BAR",
|
||||||
|
"FOOBAR": "FOOBAR",
|
||||||
|
"FOO_BAR": "FOO-BAR",
|
||||||
|
"__FOO_BAR__": "FOO-BAR",
|
||||||
|
"$foo@Bar": "FOO-BAR",
|
||||||
|
" $#$Foo 22 bar ": "FOO-22-BAR",
|
||||||
|
"Foo-#1😄$_%^&*(1bar": "FOO-1-1-BAR",
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cases {
|
||||||
|
assert.Equal(v, UpperKebabCase(k))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSnakeCase(t *testing.T) {
|
func TestSnakeCase(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user