diff --git a/v2/maker.go b/v2/maker.go index 24b26e9..2f60597 100644 --- a/v2/maker.go +++ b/v2/maker.go @@ -35,6 +35,7 @@ var makers = map[string]MakeCheckFunc{ nameMaxLen: makeMaxLen, nameMinLen: makeMinLen, nameRequired: makeRequired, + nameTitle: makeTitle, nameTrimLeft: makeTrimLeft, nameTrimRight: makeTrimRight, nameTrimSpace: makeTrimSpace, diff --git a/v2/title.go b/v2/title.go new file mode 100644 index 0000000..5d4fd54 --- /dev/null +++ b/v2/title.go @@ -0,0 +1,51 @@ +// Copyright (c) 2023-2024 Onur Cinar. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. +// https://github.com/cinar/checker + +package v2 + +import ( + "reflect" + "strings" + "unicode" +) + +const ( + // nameTitle is the name of the title normalizer. + nameTitle = "title" +) + +// Title returns the value of the string with the first letter of each word in upper case. +func Title(value string) (string, error) { + var sb strings.Builder + begin := true + + for _, c := range value { + if unicode.IsLetter(c) { + if begin { + c = unicode.ToUpper(c) + begin = false + } else { + c = unicode.ToLower(c) + } + } else { + begin = true + } + + sb.WriteRune(c) + } + + return sb.String(), nil +} + +// reflectTitle returns the value of the string with the first letter of each word in upper case. +func reflectTitle(value reflect.Value) (reflect.Value, error) { + newValue, err := Title(value.Interface().(string)) + return reflect.ValueOf(newValue), err +} + +// makeTitle returns the title normalizer function. +func makeTitle(_ string) CheckFunc[reflect.Value] { + return reflectTitle +} diff --git a/v2/title_test.go b/v2/title_test.go new file mode 100644 index 0000000..ad278d1 --- /dev/null +++ b/v2/title_test.go @@ -0,0 +1,47 @@ +// Copyright (c) 2023-2024 Onur Cinar. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. +// https://github.com/cinar/checker + +package v2_test + +import ( + "testing" + + v2 "github.com/cinar/checker/v2" +) + +func TestTitle(t *testing.T) { + input := "the checker" + expected := "The Checker" + + actual, err := v2.Title(input) + if err != nil { + t.Fatal(err) + } + + if actual != expected { + t.Fatalf("actual %s expected %s", actual, expected) + } +} + +func TestReflectTitle(t *testing.T) { + type Book struct { + Chapter string `checkers:"title"` + } + + book := &Book{ + Chapter: "the checker", + } + + expected := "The Checker" + + errs, ok := v2.CheckStruct(book) + if !ok { + t.Fatalf("got unexpected errors %v", errs) + } + + if book.Chapter != expected { + t.Fatalf("actual %s expected %s", book.Chapter, expected) + } +}