First off, thank you for considering contributing to Validator! It's people like you that make Validator such a great tool.
- Code of Conduct
- Getting Started
- How Can I Contribute?
- Development Workflow
- Coding Standards
- Community
This project and everyone participating in it is governed by our Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to nv3212@gmail.com.
-
Fork the repository
# Click the "Fork" button on GitHub -
Clone your fork
git clone https://github.com/space-code/validator.git cd validator -
Set up the development environment
# Install mise (if not already installed) curl https://mise.run | sh # Install project dependencies mise install
-
Create a feature branch
git checkout -b feature/your-feature-name
-
Open the project in Xcode
open Package.swift
validator/
├── Sources/
│ ├── ValidatorCore/ # Core validation logic
│ │ └── Classes/
│ │ ├── Core/ # Core validator classes and protocols
│ │ ├── Extensions/ # Core extensions
│ │ └── Rules/ # Built-in validation rules
│ └── ValidatorUI/ # UI integrations
│ └── Classes/
│ ├── Extensions/ # Shared UI extensions
│ ├── SUI/ # SwiftUI modifiers and components
│ └── UIKit/ # UIKit extensions and helpers
├── Tests/
├── ValidatorCoreTests/ # Core logic tests
└── ValidatorUITests/ # UI integration tests
Before creating a bug report, please check the existing issues to avoid duplicates.
When creating a bug report, use our bug report template and include:
- Clear title - Describe the issue concisely
- Reproduction steps - Detailed steps to reproduce the bug
- Expected behavior - What you expected to happen
- Actual behavior - What actually happened
- Environment - OS, Xcode version, Swift version
- Code samples - Minimal reproducible example
- Screenshots - If applicable
Example:
**Title:** LengthValidationRule fails with empty string when min is 0
**Steps to reproduce:**
1. Create a LengthValidationRule with min: 0
2. Validate an empty string
3. Expected: .valid, Actual: .invalidWe love feature suggestions! Use our feature request template and include:
- Problem statement - What problem does this solve?
- Proposed solution - How should it work?
- Alternatives - What alternatives did you consider?
- Use cases - Real-world scenarios
- API design - Example code showing usage
Documentation improvements are always welcome:
- Code comments - Add/improve inline documentation
- API documentation - Enhance DocC documentation
- README - Fix typos, add examples
- Guides - Write tutorials or how-to guides
- Translations - Help translate documentation
Use our documentation template for documentation issues.
- Check existing work - Look for related issues or PRs
- Discuss major changes - Open an issue for large features
- Follow coding standards - See Coding Standards
- Write tests - All code changes require tests
- Update documentation - Keep docs in sync with code
- Create a pull request - Use our PR template
We follow a simplified Git Flow:
main- Main development branch (default, all PRs target this branch)feature/*- New featuresfix/*- Bug fixesdocs/*- Documentation updatesrefactor/*- Code refactoringtest/*- Test improvements
Branch naming examples:
feature/email-validation-rule
fix/length-validator-edge-case
docs/update-swiftui-guide
refactor/validator-core-architecture
test/add-regex-validator-testsWe use Conventional Commits for clear, structured commit history.
Format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code style (formatting, missing semicolons)refactor- Code refactoringtest- Adding or updating testschore- Maintenance tasks (dependencies, tooling)perf- Performance improvementsci- CI/CD changes
Scopes:
core- ValidatorCore changesui- ValidatorUI changesuikit- UIKit integrationswiftui- SwiftUI integrationrules- Validation rulesdeps- Dependencies
Examples:
feat(rules): add email validation rule
Add EmailValidationRule with support for RFC 5322 compliant validation.
Includes comprehensive test coverage for edge cases.
Closes #123
---
fix(core): handle nil input in validator
Previously, the validator would crash with nil input.
Now returns .invalid with appropriate error message.
Fixes #456
---
docs(swiftui): add form validation examples
Add comprehensive examples for FormFieldManager usage
including error handling and state management patterns.
---
test(rules): increase coverage for LengthValidationRule
Add tests for:
- Unicode character handling
- Emoji counting
- Empty string edge casesCommit message rules:
- Use imperative mood ("add" not "added")
- Don't capitalize first letter
- No period at the end
- Keep subject line under 72 characters
- Separate subject from body with blank line
- Reference issues in footer
-
Update your branch
git checkout main git pull upstream main git checkout feature/your-feature git rebase main
-
Run tests and checks
# Run all tests swift test # Check code formatting mise run lint
-
Push to your fork
git push origin feature/your-feature
-
Create pull request
- Use our PR template
- Target the
mainbranch - Link related issues
- Request review from maintainers
-
Review process
- Address review comments
- Keep PR up to date with dev branch
- Squash commits if requested
- Wait for CI to pass
-
After merge
# Clean up local branch git checkout main git pull upstream main git branch -d feature/your-feature # Clean up remote branch git push origin --delete feature/your-feature
We follow the Swift API Design Guidelines and Ray Wenderlich Swift Style Guide.
Key points:
-
Naming
// ✅ Good func validate(input: String) -> ValidationResult let isValid: Bool // ❌ Bad func check(str: String) -> Bool let valid: Bool
-
Protocols
// ✅ Good - Use "I" prefix for protocols protocol IValidationRule { associatedtype Input func validate(input: Input) -> Bool } // ❌ Bad protocol ValidationRule { }
-
Access Control
// ✅ Good - Explicit access control public struct EmailValidationRule: IValidationRule { private let pattern: String public init(pattern: String) { self.pattern = pattern } }
-
Documentation
/// Validates email addresses using RFC 5322 compliant regex. /// /// This validator checks for valid email format including: /// - Local part validation /// - Domain validation /// - TLD requirements /// /// - Parameters: /// - pattern: Custom regex pattern (optional) /// - error: Error to return on validation failure /// /// - Example: /// ```swift /// let rule = EmailValidationRule(error: "Invalid email") /// let result = validator.validate(input: "user@example.com", rule: rule) /// ``` public struct EmailValidationRule: IValidationRule { // Implementation }
- No force unwrapping - Use optional binding or guards
- No force casting - Use conditional casting
- No magic numbers - Use named constants
- Single responsibility - One class, one purpose
- DRY principle - Don't repeat yourself
- SOLID principles - Follow SOLID design
Example:
// ✅ Good
private enum ValidationConstants {
static let minLength = 8
static let maxLength = 128
}
guard let email = input as? String else {
return .invalid([ValidationError(message: "Invalid input type")])
}
// ❌ Bad
let email = input as! String
if email.count < 8 || email.count > 128 {
return .invalid([ValidationError(message: "Invalid")])
}All code changes must include tests:
- Unit tests - Test individual components
- Integration tests - Test component interactions
- Edge cases - Test boundary conditions
- Error handling - Test failure scenarios
Coverage requirements:
- New code: minimum 80% coverage
- Modified code: maintain or improve existing coverage
- Critical paths: 100% coverage
Test structure:
import XCTest
@testable import ValidatorCore
final class EmailValidationRuleTests: XCTestCase {
var sut: EmailValidationRule!
override func setUp() {
super.setUp()
sut = EmailValidationRule(error: "Invalid email")
}
override func tearDown() {
sut = nil
super.tearDown()
}
// MARK: - Valid Email Tests
func testValidateWithValidEmail_ReturnsTrue() {
// Given
let email = "user@example.com"
// When
let result = sut.validate(input: email)
// Then
XCTAssertTrue(result)
}
// MARK: - Invalid Email Tests
func testValidateWithInvalidEmail_ReturnsFalse() {
// Given
let email = "invalid.email"
// When
let result = sut.validate(input: email)
// Then
XCTAssertFalse(result)
}
// MARK: - Edge Cases
func testValidateWithEmptyString_ReturnsFalse() {
XCTAssertFalse(sut.validate(input: ""))
}
}- Discussions - Join GitHub Discussions
- Issues - Track open issues
- Pull Requests - Review open PRs
Contributors are recognized in:
- GitHub contributors page
- Release notes
- Project README (for significant contributions)
- Check existing issues
- Search discussions
- Ask in Q&A discussions
- Email the maintainer: nv3212@gmail.com
Thank you for contributing to Validator! 🎉
Your efforts help make this project better for everyone.