A lightweight, dependency-free Dart package that adds fluent String
validation through extension methods — no utility classes, no static
method calls, just clean, readable code:
"john@gmail.com".isValidEmail; // true
"Password@123".isStrongPassword; // true
"https://flutter.dev".isValidUrl; // true
"+923001234567".isValidPhone; // true
"123".isNumeric; // true
- ✅ Zero dependencies — pure Dart, works in Flutter, server, and CLI apps
- ✅ Fluent, discoverable API via extension methods
- ✅ Centralized, non-duplicated regex patterns
- ✅ Clear separation between validators and extensions
- ✅ Extensively unit tested
- ✅ Fully documented with
dartdoc comments
- ✅ Zero analyzer warnings,
lints-compliant
- ✅ Easy to extend with new validators
Add this to your pubspec.yaml:
dependencies:
clean_string_validator: ^1.0.0
Then run:
dart pub get
Or, for Flutter projects:
flutter pub get
Import the single public entry point:
import 'package:clean_string_validator/clean_string_validator.dart';
That's it — every extension method below becomes available on any
String.
| Method |
Description |
.isValidEmail |
Checks for a syntactically valid email |
"john@gmail.com".isValidEmail; // true
| Method |
Description |
.isStrongPassword |
At least 8 chars, upper, lower, digit, and special character |
"Password@123".isStrongPassword; // true
| Method |
Description |
.isValidPhone |
Validates Pakistani and generic international numbers |
"+923001234567".isValidPhone; // true
"03001234567".isValidPhone; // true
| Method |
Description |
.isValidUrl |
Validates HTTP/HTTPS URLs |
"https://flutter.dev".isValidUrl; // true
| Method |
Description |
.isValidUsername |
3-20 chars: letters, numbers, underscores only |
"john_doe123".isValidUsername; // true
| Method |
Description |
.isNumeric |
Parses as any number |
.isInteger |
Parses as an integer |
.isDouble |
Parses as a double |
.isPositiveNumber |
Numeric value greater than zero |
.isNegativeNumber |
Numeric value less than zero |
"123".isNumeric; // true
"42".isInteger; // true
"42.5".isDouble; // true
"10".isPositiveNumber; // true
"-10".isNegativeNumber; // true
| Method |
Description |
.isValidDate |
Validates real YYYY-MM-DD calendar dates |
"2024-05-10".isValidDate; // true
"2024-02-30".isValidDate; // false
| Method |
Description |
.isJson |
Checks for syntactically valid JSON |
'{"name":"John"}'.isJson; // true
| Method |
Description |
.isUUID |
Validates UUID versions 1-5 |
"123e4567-e89b-12d3-a456-426614174000".isUUID; // true
| Method |
Description |
.isIPv4 |
Validates IPv4 addresses |
.isIPv6 |
Validates IPv6 addresses |
.isMacAddress |
Validates MAC addresses |
"192.168.0.1".isIPv4; // true
"::1".isIPv6; // true
"00:1B:44:11:3A:B7".isMacAddress; // true
| Method |
Description |
.isHexColor |
Validates 3 or 6 digit hex colors (# optional) |
"#fff".isHexColor; // true
"#ffffff".isHexColor; // true
| Method |
Description |
.isValidCreditCard |
Validates length and Luhn checksum |
"4539578763621486".isValidCreditCard; // true
| Method |
Description |
.isBlank |
Empty or whitespace only |
.isNotBlank |
Has non-whitespace content |
.hasText |
Alias for .isNotBlank |
.isWhitespace |
Non-empty and whitespace only |
.containsUppercase |
Has at least one uppercase letter |
.containsLowercase |
Has at least one lowercase letter |
.containsNumber |
Has at least one digit |
.containsSpecialCharacter |
Has at least one special character |
.containsOnlyLetters |
All characters are letters |
.containsOnlyDigits |
All characters are digits |
.isAlphabet |
Alias for .containsOnlyLetters |
.isAlphaNumeric |
All characters are letters or digits |
.hasMinLength(int) |
Length ≥ given value |
.hasMaxLength(int) |
Length ≤ given value |
.hasExactLength(int) |
Length equals given value |
.isUpperCase |
Entirely uppercase |
.isLowerCase |
Entirely lowercase |
.isTitleCase |
Every word capitalized (Hello World) |
clean_string_validator/
├── lib/
│ ├── clean_string_validator.dart # Public API barrel file
│ └── src/
│ ├── extensions/ # Fluent extension methods
│ ├── validators/ # Pure validation logic
│ ├── regex/ # Centralized regex patterns
│ └── utils/ # Shared helpers (Luhn, constants, etc.)
├── example/
│ └── main.dart
├── test/
│ └── ... # One test file per validator
├── CHANGELOG.md
├── LICENSE
└── pubspec.yaml
- No duplicated regex — every pattern lives in
regex_patterns.dart.
- Validators know nothing about extensions — they're plain,
testable static methods.
- Extensions only expose clean getters/methods — no business logic.
- This separation makes it trivial to add new validators (email
masking, OTP, PIN, slugs, country-specific rules, etc.) without
touching existing files.
Contributions are welcome! To add a new validator:
- Add any new regex to
lib/src/regex/regex_patterns.dart.
- Create a validator in
lib/src/validators/ with static methods.
- Create an extension in
lib/src/extensions/ that calls the validator.
- Export the new extension from
lib/clean_string_validator.dart.
- Add tests covering valid, invalid, empty, and boundary cases.
Please run dart analyze and dart test before submitting a pull
request.
This package is released under the MIT License.