From a66d8c1402d42624106c769fc91d3de0fdf3bd67 Mon Sep 17 00:00:00 2001
From: Nikita Vasilev
Date: Sat, 22 Nov 2025 23:43:13 +0400
Subject: [PATCH] docs(contributing): update project structure
---
CODE_OF_CONDUCT.md | 133 +++++++++++++
CONTRIBUTING.md | 469 +++++++++++++++++++++++++++++++++++++++++++++
README.md | 457 +++++++++++++++++++++++++++++--------------
3 files changed, 913 insertions(+), 146 deletions(-)
create mode 100644 CODE_OF_CONDUCT.md
create mode 100644 CONTRIBUTING.md
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..fa7ff7a
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,133 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+nv3212@gmail.com.
+
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..b681d0c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,469 @@
+# Contributing to Validator
+
+First off, thank you for considering contributing to Validator! It's people like you that make Validator such a great tool.
+
+## Table of Contents
+
+- [Code of Conduct](#code-of-conduct)
+- [Getting Started](#getting-started)
+ - [Development Setup](#development-setup)
+ - [Project Structure](#project-structure)
+- [How Can I Contribute?](#how-can-i-contribute)
+ - [Reporting Bugs](#reporting-bugs)
+ - [Suggesting Features](#suggesting-features)
+ - [Improving Documentation](#improving-documentation)
+ - [Submitting Code](#submitting-code)
+- [Development Workflow](#development-workflow)
+ - [Branching Strategy](#branching-strategy)
+ - [Commit Guidelines](#commit-guidelines)
+ - [Pull Request Process](#pull-request-process)
+- [Coding Standards](#coding-standards)
+ - [Swift Style Guide](#swift-style-guide)
+ - [Code Quality](#code-quality)
+ - [Testing Requirements](#testing-requirements)
+- [Community](#community)
+
+## Code of Conduct
+
+This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to nv3212@gmail.com.
+
+## Getting Started
+
+### Development Setup
+
+1. **Fork the repository**
+ ```bash
+ # Click the "Fork" button on GitHub
+ ```
+
+2. **Clone your fork**
+ ```bash
+ git clone https://github.com/space-code/validator.git
+ cd validator
+ ```
+
+3. **Set up the development environment**
+ ```bash
+ # Install mise (if not already installed)
+ curl https://mise.run | sh
+
+ # Install project dependencies
+ mise install
+ ```
+
+4. **Create a feature branch**
+ ```bash
+ git checkout -b feature/your-feature-name
+ ```
+
+5. **Open the project in Xcode**
+ ```bash
+ open Package.swift
+ ```
+
+### Project Structure
+
+```
+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
+```
+
+## How Can I Contribute?
+
+### Reporting Bugs
+
+Before creating a bug report, please check the [existing issues](https://github.com/space-code/validator/issues) to avoid duplicates.
+
+When creating a bug report, use our [bug report template](.github/ISSUE_TEMPLATE/bug_report.md) 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:**
+```markdown
+**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: .invalid
+```
+
+### Suggesting Features
+
+We love feature suggestions! Use our [feature request template](.github/ISSUE_TEMPLATE/feature_request.md) 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
+
+### Improving Documentation
+
+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](.github/ISSUE_TEMPLATE/documentation.md) for documentation issues.
+
+### Submitting Code
+
+1. **Check existing work** - Look for related issues or PRs
+2. **Discuss major changes** - Open an issue for large features
+3. **Follow coding standards** - See [Coding Standards](#coding-standards)
+4. **Write tests** - All code changes require tests
+5. **Update documentation** - Keep docs in sync with code
+6. **Create a pull request** - Use our [PR template](.github/PULL_REQUEST_TEMPLATE.md)
+
+## Development Workflow
+
+### Branching Strategy
+
+We follow a simplified Git Flow:
+
+- **`main`** - Main development branch (default, all PRs target this branch)
+- **`feature/*`** - New features
+- **`fix/*`** - Bug fixes
+- **`docs/*`** - Documentation updates
+- **`refactor/*`** - Code refactoring
+- **`test/*`** - Test improvements
+
+**Branch naming examples:**
+```bash
+feature/email-validation-rule
+fix/length-validator-edge-case
+docs/update-swiftui-guide
+refactor/validator-core-architecture
+test/add-regex-validator-tests
+```
+
+### Commit Guidelines
+
+We use [Conventional Commits](https://www.conventionalcommits.org/) for clear, structured commit history.
+
+**Format:**
+```
+():
+
+
+
+
## Description
-Validator is a framework written in Swift that provides functions that can be used to validate the contents of an input value.
+Validator is a modern, lightweight Swift framework that provides elegant and type-safe input validation. Built with Swift's powerful type system, it seamlessly integrates with both UIKit and SwiftUI, making form validation effortless across all Apple platforms.
+
+## Features
+
+✨ **Type-Safe Validation** - Leverages Swift's type system for compile-time safety
+🎯 **Rich Rule Set** - Built-in validators for common use cases
+🔧 **Extensible** - Easy to create custom validation rules
+📱 **UIKit Integration** - First-class support for UITextField and other UIKit components
+🎨 **SwiftUI Native** - Property wrappers and view modifiers for declarative validation
+📋 **Form Management** - Validate multiple fields with centralized state management
+⚡ **Lightweight** - Minimal footprint with zero dependencies
+🧪 **Well Tested** - Comprehensive test coverage
+
+## Table of Contents
-- [Usage](#usage)
-- [Validation Rules](#validation-rules)
-- [Custom Validation Rules](#custom-validation-rules)
- [Requirements](#requirements)
- [Installation](#installation)
-- [Communication](#communication)
+- [Quick Start](#quick-start)
+- [Usage](#usage)
+ - [Core Validation](#core-validation)
+ - [UIKit Integration](#uikit-integration)
+ - [SwiftUI Integration](#swiftui-integration)
+ - [Form Validation](#form-validation)
+- [Built-in Validators](#built-in-validators)
+- [Custom Validators](#custom-validators)
- [Contributing](#contributing)
-- [Author](#author)
- [License](#license)
+## Requirements
+
+| Platform | Minimum Version |
+|-----------|----------------|
+| iOS | 16.0+ |
+| macOS | 13.0+ |
+| tvOS | 16.0+ |
+| watchOS | 9.0+ |
+| visionOS | 1.0+ |
+| Xcode | 15.3+ |
+| Swift | 5.10+ |
+
## Usage
The package contains two libraries: `ValidatorCore` encompasses all validation logic and predefined validators, while `ValidatorUI` implements extensions for integrating the validator into UI objects. It supports both `SwiftUI` and `UIKit`.
-### Basic usage
+## Installation
+
+### Swift Package Manager
-If you need to validate some data, you can use the `Validator` object for this purpose as follows:
+Add the following dependency to your `Package.swift`:
+
+```swift
+dependencies: [
+ .package(url: "https://github.com/space-code/validator.git", from: "1.2.0")
+]
+```
+
+Or add it through Xcode:
+
+1. File > Add Package Dependencies
+2. Enter package URL: `https://github.com/space-code/validator.git`
+3. Select version requirements
+
+## Quick Start
```swift
import ValidatorCore
let validator = Validator()
-let result = validator.validate(input: "text", rule: LengthValidationRule(min: 4, error: "Text must be at least 4 characters long"))
+let result = validator.validate(
+ input: "user@example.com",
+ rule: RegexValidationRule(
+ pattern: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}",
+ error: "Invalid email address"
+ )
+)
switch result {
case .valid:
- print("Text is valid")
-case let .invalid(errors):
- // handle validation errors
- print("Validation errors: \(errors.map(\.message))")
+ print("✅ Valid input")
+case .invalid(let errors):
+ print("❌ Validation failed: \(errors.map(\.message))")
}
```
-### UIKit
+## Usage
+
+The framework provides two main libraries:
+
+- **ValidatorCore** - Core validation logic and predefined validators
+- **ValidatorUI** - UI integration for UIKit and SwiftUI
-If you want to validate a user's input data, you can import `ValidatorUI` and integrate validation logic into UI components. Your UI object must conform to `IUIValidatable` prototocol that requires to define an `inputValue` and `validateOnInputChange(_:)` method.
+### Core Validation
-`ValidatorUI` supports an extension for convenient integration of the validator into `UITextField` objects:
+Validate any input with the `Validator` class:
+
+```swift
+import ValidatorCore
+
+let validator = Validator()
+let result = validator.validate(
+ input: "password123",
+ rule: LengthValidationRule(
+ min: 8,
+ error: "Password must be at least 8 characters"
+ )
+)
+```
+
+### UIKit Integration
+
+Import `ValidatorUI` to add validation to UIKit components:
```swift
import UIKit
@@ -59,213 +130,307 @@ import ValidatorUI
import ValidatorCore
class ViewController: UIViewController {
-
- let textField: UITextField = UITextField()
-
+ let emailField = UITextField()
+
override func viewDidLoad() {
super.viewDidLoad()
- /// Adds validation rule to the text field.
- textField.add(rule: LengthValidationRule(max: 10, error: "Text must be at most 10 characters"))
- /// Enables automatic validation on input change.
- textField.validateOnInputChange(isEnabled: true)
- /// Handle the validation result.
- textField.validationHandler = { result in
+ // Add validation rules
+ emailField.add(
+ rule: RegexValidationRule(
+ pattern: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}",
+ error: "Please enter a valid email"
+ )
+ )
+
+ // Enable real-time validation
+ emailField.validateOnInputChange(isEnabled: true)
+
+ // Handle validation results
+ emailField.validationHandler = { result in
switch result {
case .valid:
- print("Text is valid")
- case let .invalid(errors):
- print("Validation errors: \(errors)")
+ self.updateUI(isValid: true)
+ case .invalid(let errors):
+ self.showErrors(errors)
}
}
}
-
- /// Setup UITextField ...
}
```
-### SwiftUI
+### SwiftUI Integration
-If you need to validate a single field, you can use the validation view extension and handle the validation result in a validation handler:
+#### Single Field Validation
+
+Use the `.validation()` modifier for simple field validation:
```swift
import SwiftUI
import ValidatorUI
import ValidatorCore
-struct ContentView: View {
- @State private var text: String = ""
-
- private let validationRules: [any IValidationRule] = [
- LengthValidationRule(max: 10, error: "Text error")
- ]
+struct LoginView: View {
+ @State private var email = ""
var body: some View {
- VStack {
- TextField("Text", text: $text)
- .validation($text, rules: validationRules) { result in
- // Handle a validation result here
+ TextField("Email", text: $email)
+ .validation($email, rules: [
+ RegexValidationRule(
+ pattern: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}",
+ error: "Invalid email"
+ )
+ ]) { result in
+ if case .invalid(let errors) = result {
+ print("Validation errors: \(errors)")
}
- }
+ }
}
}
```
-You can also use a view modifier where you can pass an error view:
+Or use `.validate()` with a custom error view:
```swift
-import SwiftUI
-import ValidatorUI
-import ValidatorCore
-
-struct ContentView: View {
- @State private var text: String = ""
-
- private let validationRules: [any IValidationRule] = [
- LengthValidationRule(max: 10, error: "Text must be at most 10 characters")
- ]
+struct LoginView: View {
+ @State private var password = ""
var body: some View {
- VStack {
- TextField("Enter text", text: $text)
- .validate(item: $text, rules: validationRules) { errors in
- Text("Text exceeds 10 characters")
+ VStack(alignment: .leading) {
+ SecureField("Password", text: $password)
+ .validate(item: $password, rules: [
+ LengthValidationRule(min: 8, error: "Too short")
+ ]) { errors in
+ ForEach(errors, id: \.message) { error in
+ Text(error.message)
+ .foregroundColor(.red)
+ .font(.caption)
+ }
}
}
}
}
```
-### SwiftUI Forms
+### Form Validation
-`ValidatorUI` supports form validation. If your screen contains a number of input fields and you want to handle validation results in one place, you can use a validation form manager as follows:
+Manage multiple fields with `FormFieldManager`:
```swift
+import Combine
import SwiftUI
import ValidatorUI
import ValidatorCore
-class Form: ObservableObject {
- @Published
- var manager = FormFieldManager()
-
- @FormField(rules: [LengthValidationRule(max: 20, error: "First name is too long")])
- var firstName: String = ""
-
- @FormField(rules: [LengthValidationRule(min: 5, error: "Last name is too short")])
- var lastName: String = ""
+class RegistrationForm: ObservableObject {
+ @Published var manager = FormFieldManager()
+
+ @FormField(rules: [
+ LengthValidationRule(min: 2, max: 50, error: "Invalid name length")
+ ])
+ var firstName = ""
- lazy var firstNameValidationContainer = _firstName.validate(manager: manager)
- lazy var lastNameValidationContainer = _lastName.validate(manager: manager)
+ @FormField(rules: [
+ LengthValidationRule(min: 2, max: 50, error: "Invalid name length")
+ ])
+ var lastName = ""
+
+ @FormField(rules: [
+ RegexValidationRule(
+ pattern: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}",
+ error: "Invalid email"
+ )
+ ])
+ var email = ""
+
+ lazy var firstNameContainer = _firstName.validate(manager: manager)
+ lazy var lastNameContainer = _lastName.validate(manager: manager)
+ lazy var emailContainer = _email.validate(manager: manager)
}
-struct ContentView: View {
- @ObservedObject private var form = Form()
+struct RegistrationView: View {
+ @StateObject private var form = RegistrationForm()
+ @State private var isFormValid = false
var body: some View {
- VStack {
- TextField("First Name", text: $form.firstName)
- .validate(validationContainer: form.firstNameValidationContainer) { errors in
- Text(errors.map { $0.message }.joined(separator: " "))
- }
- TextField("Last Name", text: $form.lastName)
- .validate(validationContainer: form.lastNameValidationContainer) { errors in
- Text(errors.map { $0.message }.joined(separator: " "))
- }
- Button(action: { self.form.manager.validate() }, label: { Text("Validate") })
-
- Spacer()
- }
- .onReceive(
- form.manager.$isValid,
- perform: { value in
- if value {
- print("All form fields are valid")
- } else {
- print("Some form fields are invalid")
+ Form {
+ Section("Personal Information") {
+ TextField("First Name", text: $form.firstName)
+ .validate(validationContainer: form.firstNameContainer) { errors in
+ ErrorView(errors: errors)
+ }
+
+ TextField("Last Name", text: $form.lastName)
+ .validate(validationContainer: form.lastNameContainer) { errors in
+ ErrorView(errors: errors)
+ }
+ }
+
+ Section("Contact") {
+ TextField("Email", text: $form.email)
+ .validate(validationContainer: form.emailContainer) { errors in
+ ErrorView(errors: errors)
+ }
+ }
+
+ Section {
+ Button("Submit") {
+ form.manager.validate()
}
+ .disabled(!isFormValid)
}
- )
+ }
+ .onReceive(form.manager.$isValid) { newValue in
+ isFormValid = newValue
+ }
+ }
+
+ private func submitForm() {
+ print("✅ Form is valid, submitting...")
}
}
```
-## Validation Rules
+## Built-in Validators
-| **Validator** | **Description** |
-|----------------------------|-------------------------------------------------------------------------------------|
-| **LengthValidationRule** | To validate whether a string is matching a specific length |
-| **NonEmptyValidationRule** | To validate whether a string is empty or blank |
-| **PrefixValidationRule** | To validate whether a string contains a prefix |
-| **SuffixValidationRule** | To validate whether a string contains a suffix |
-| **RegexValidationRule** | To validate if a pattern is matched |
-| **URLValidationRule** | To validate whether a string contains a URL |
-| **CreditCardValidationRule** | To validate whether a string has a valid credit card number |
+| Validator | Description | Example |
+|-----------|-------------|---------|
+| `LengthValidationRule` | Validates string length (min/max) | `LengthValidationRule(min: 3, max: 20, error: "Length must be 3-20 characters")` |
+| `NonEmptyValidationRule` | Ensures string is not empty or blank | `NonEmptyValidationRule(error: "Field is required")` |
+| `PrefixValidationRule` | Validates string prefix | `PrefixValidationRule(prefix: "https://", error: "URL must start with https://")` |
+| `SuffixValidationRule` | Validates string suffix | `SuffixValidationRule(suffix: ".com", error: "Domain must end with .com")` |
+| `RegexValidationRule` | Pattern matching validation | `RegexValidationRule(pattern: "^\\d{3}-\\d{4}$", error: "Invalid phone format")` |
+| `URLValidationRule` | Validates URL format | `URLValidationRule(error: "Please enter a valid URL")` |
+| `CreditCardValidationRule` | Validates credit card numbers (Luhn algorithm) | `CreditCardValidationRule(error: "Invalid card number")` |
-## Custom Validation Rules
+## Custom Validators
-To implement a custom validation rule, you can conform to the `IValidationRule` protocol, which requires defining a validation type and implementing validation logic. For example:
+Create custom validation rules by conforming to `IValidationRule`:
```swift
-/// A non empty validation rule.
-public struct NonEmptyValidationRule: IValidationRule {
- // MARK: Types
-
- public typealias Input = String
-
- // MARK: Properties
-
- /// The validation error.
- public let error: IValidationError
-
- // MARK: Initialization
+import ValidatorCore
- public init(error: IValidationError) {
+struct EmailDomainValidationRule: IValidationRule {
+ typealias Input = String
+
+ let allowedDomains: [String]
+ let error: IValidationError
+
+ init(allowedDomains: [String], error: IValidationError) {
+ self.allowedDomains = allowedDomains
self.error = error
}
-
- // MARK: IValidationRule
-
- public func validate(input: String) -> Bool {
- !input.isEmpty
+
+ func validate(input: String) -> Bool {
+ guard let domain = input.split(separator: "@").last else {
+ return false
+ }
+ return allowedDomains.contains(String(domain))
}
}
-```
-
-## Requirements
-- iOS 16.0+ / macOS 13+ / tvOS 16.0+ / watchOS 9.0+
-- Xcode 15.3
-- Swift 5.10
-## Installation
-### Swift Package Manager
+// Usage
+let rule = EmailDomainValidationRule(
+ allowedDomains: ["company.com", "company.org"],
+ error: "Only company email addresses are allowed"
+)
+```
-The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but `validator` does support its use on supported platforms.
+### Composing Validators
-Once you have your Swift package set up, adding `validator` as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`.
+Combine multiple validators for complex validation logic:
```swift
-dependencies: [
- .package(url: "https://github.com/space-code/validator.git", .upToNextMajor(from: "1.2.0"))
-]
+// Define reusable validation rules
+let lengthRule = LengthValidationRule(
+ min: 8,
+ max: 128,
+ error: "Password must be 8-128 characters"
+)
+
+let uppercaseRule = RegexValidationRule(
+ pattern: ".*[A-Z].*",
+ error: "Must contain uppercase letter"
+)
+
+let lowercaseRule = RegexValidationRule(
+ pattern: ".*[a-z].*",
+ error: "Must contain lowercase letter"
+)
+
+let numberRule = RegexValidationRule(
+ pattern: ".*[0-9].*",
+ error: "Must contain number"
+)
+
+let specialCharRule = RegexValidationRule(
+ pattern: ".*[!@#$%^&*(),.?\":{}|<>].*",
+ error: "Must contain special character"
+)
+
+// UIKit: Pass all rules to your text field
+passwordField.add(rules: [
+ lengthRule,
+ uppercaseRule,
+ lowercaseRule,
+ numberRule,
+ specialCharRule
+])
+
+// SwiftUI: Use in validation modifier
+SecureField("Password", text: $password)
+ .validation($password, rules: [
+ lengthRule,
+ uppercaseRule,
+ lowercaseRule,
+ numberRule,
+ specialCharRule
+ ]) { result in
+ if case .invalid(let errors) = result {
+ self.passwordErrors = errors
+ }
+ }
```
## Communication
-- If you **found a bug**, open an issue.
-- If you **have a feature request**, open an issue.
-- If you **want to contribute**, submit a pull request.
+
+- 🐛 **Found a bug?** [Open an issue](https://github.com/space-code/validator/issues/new?template=bug_report.md)
+- 💡 **Have a feature request?** [Open an issue](https://github.com/space-code/validator/issues/new?template=feature_request.md)
+- ❓ **Questions?** [Start a discussion](https://github.com/space-code/validator/discussions)
+- 🔒 **Security issue?** Email nv3212@gmail.com
## Contributing
-Bootstrapping development environment
-```
+We love contributions! Please read our [Contributing Guide](CONTRIBUTING.md) to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes.
+
+### Development Setup
+
+Bootstrap the development environment:
+
+```bash
mise install
```
-Please feel free to help out with this project! If you see something that could be made better or want a new feature, open up an issue or send a Pull Request!
+### Code of Conduct
+
+This project adheres to the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
## Author
-Nikita Vasilev, nv3212@gmail.com
+
+**Nikita Vasilev**
+- Email: nv3212@gmail.com
+- GitHub: [@ns-vasilev](https://github.com/ns-vasilev)
## License
-validator is available under the MIT license. See the LICENSE file for more info.
+
+Validator is released under the MIT license. See [LICENSE](LICENSE) for details.
+
+---
+
+
+
+**[⬆ back to top](#validator)**
+
+Made with ❤️ by [space-code](https://github.com/space-code)
+
+