Fields created via Context.Field are now tracked on the page context, so ValidateAll() and ResetFields() with no arguments operate on all fields by default. Explicit field args still work for selective use. Also switches MinLen/MaxLen to utf8.RuneCountInString for correct unicode handling and replaces fmt.Errorf with errors.New where format strings are unnecessary.
131 lines
2.7 KiB
Go
131 lines
2.7 KiB
Go
package via
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// Rule defines a single validation check for a Field.
|
|
type Rule struct {
|
|
validate func(val string) error
|
|
}
|
|
|
|
// Required rejects empty or whitespace-only values.
|
|
func Required(msg ...string) Rule {
|
|
m := "This field is required"
|
|
if len(msg) > 0 {
|
|
m = msg[0]
|
|
}
|
|
return Rule{func(val string) error {
|
|
if strings.TrimSpace(val) == "" {
|
|
return errors.New(m)
|
|
}
|
|
return nil
|
|
}}
|
|
}
|
|
|
|
// MinLen rejects values shorter than n characters.
|
|
func MinLen(n int, msg ...string) Rule {
|
|
m := fmt.Sprintf("Must be at least %d characters", n)
|
|
if len(msg) > 0 {
|
|
m = msg[0]
|
|
}
|
|
return Rule{func(val string) error {
|
|
if utf8.RuneCountInString(val) < n {
|
|
return errors.New(m)
|
|
}
|
|
return nil
|
|
}}
|
|
}
|
|
|
|
// MaxLen rejects values longer than n characters.
|
|
func MaxLen(n int, msg ...string) Rule {
|
|
m := fmt.Sprintf("Must be at most %d characters", n)
|
|
if len(msg) > 0 {
|
|
m = msg[0]
|
|
}
|
|
return Rule{func(val string) error {
|
|
if utf8.RuneCountInString(val) > n {
|
|
return errors.New(m)
|
|
}
|
|
return nil
|
|
}}
|
|
}
|
|
|
|
// Min parses the value as an integer and rejects values less than n.
|
|
func Min(n int, msg ...string) Rule {
|
|
m := fmt.Sprintf("Must be at least %d", n)
|
|
if len(msg) > 0 {
|
|
m = msg[0]
|
|
}
|
|
return Rule{func(val string) error {
|
|
v, err := strconv.Atoi(val)
|
|
if err != nil {
|
|
return errors.New("Must be a valid number")
|
|
}
|
|
if v < n {
|
|
return errors.New(m)
|
|
}
|
|
return nil
|
|
}}
|
|
}
|
|
|
|
// Max parses the value as an integer and rejects values greater than n.
|
|
func Max(n int, msg ...string) Rule {
|
|
m := fmt.Sprintf("Must be at most %d", n)
|
|
if len(msg) > 0 {
|
|
m = msg[0]
|
|
}
|
|
return Rule{func(val string) error {
|
|
v, err := strconv.Atoi(val)
|
|
if err != nil {
|
|
return errors.New("Must be a valid number")
|
|
}
|
|
if v > n {
|
|
return errors.New(m)
|
|
}
|
|
return nil
|
|
}}
|
|
}
|
|
|
|
// Pattern rejects values that don't match the regular expression re.
|
|
func Pattern(re string, msg ...string) Rule {
|
|
m := "Invalid format"
|
|
if len(msg) > 0 {
|
|
m = msg[0]
|
|
}
|
|
compiled := regexp.MustCompile(re)
|
|
return Rule{func(val string) error {
|
|
if !compiled.MatchString(val) {
|
|
return errors.New(m)
|
|
}
|
|
return nil
|
|
}}
|
|
}
|
|
|
|
var emailRegexp = regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
|
|
|
|
// Email rejects values that don't look like an email address.
|
|
func Email(msg ...string) Rule {
|
|
m := "Invalid email address"
|
|
if len(msg) > 0 {
|
|
m = msg[0]
|
|
}
|
|
return Rule{func(val string) error {
|
|
if !emailRegexp.MatchString(val) {
|
|
return errors.New(m)
|
|
}
|
|
return nil
|
|
}}
|
|
}
|
|
|
|
// Custom creates a rule from a user-provided validation function.
|
|
// The function should return nil for valid input and an error for invalid input.
|
|
func Custom(fn func(string) error) Rule {
|
|
return Rule{validate: fn}
|
|
}
|