🛡️ FormGuard
Enterprise-Grade Form Validation for Modern Web Applications
Zero dependencies • Lightweight • Accessible • Secure • Framework Agnostic
FormGuard delivers enterprise-grade form validation with HTML-first configuration, advanced async validation, comprehensive accessibility features, and bulletproof security - all in just ~14KB gzipped.
🚀 Quick Start • 📖 Documentation • 🎯 Examples • 🤝 Contributing
✨ Why FormGuard?
🎯 Developer Experience
|
🚀 Performance & Security
|
♿ Accessibility First
|
🌍 Enterprise Ready
|
🚀 Quick Start
📦 Installation
# 📦 Package Managers
npm install @sc4rfurry-github/formguard
yarn add @sc4rfurry-github/formguard
pnpm add @sc4rfurry-github/formguard
bun add @sc4rfurry-github/formguard
# 🌐 CDN (Latest)
https://unpkg.com/@sc4rfurry-github/formguard@latest/dist/formguard.min.js
https://cdn.jsdelivr.net/npm/@sc4rfurry-github/formguard@latest/dist/formguard.min.js
# 🌐 CDN (Specific Version)
https://unpkg.com/@sc4rfurry-github/formguard@1.0.0/dist/formguard.min.js
⚡ 30-Second Setup
<!-- 1️⃣ Add validation attributes to your form -->
<form id="signup-form">
<input
type="email"
name="email"
data-validate="required|email"
placeholder="Enter your email"
aria-label="Email address"
>
<input
type="password"
name="password"
data-validate="required|min:8|pattern:^(?=.*[A-Za-z])(?=.*\d)"
placeholder="Create a password"
aria-label="Password (minimum 8 characters)"
>
<button type="submit">Sign Up</button>
</form>
// 2️⃣ Initialize FormGuard
import { FormGuard } from '@sc4rfurry-github/formguard';
const formGuard = new FormGuard('#signup-form', {
validateOn: 'blur',
focusInvalid: true,
announceErrors: true
});
// 3️⃣ That's it! FormGuard handles the rest ✨
🎯 Core Features
🏗️ HTML-First Validation
Define validation rules directly in your HTML - no JavaScript configuration needed.
<input data-validate="required|email|unique:/api/check-email" name="email">
<input data-validate="required|min:8|match:password" name="confirm-password">
⚡ Smart Async Validation
Built-in race condition prevention, request cancellation, and retry mechanisms.
<input data-validate="remote:/api/validate-username" name="username">
🎨 Flexible Error Display
Multiple error placement options with customizable templates.
const formGuard = new FormGuard(form, {
errorPlacement: 'after', // 'before', 'append', 'custom'
errorTemplate: '<div class="error-message" role="alert"></div>'
});
🧩 Conditional Validation
Validate fields only when certain conditions are met.
<input type="checkbox" name="subscribe" id="subscribe">
<input
name="newsletter-email"
data-validate="email"
data-validate-if="subscribe:checked"
>
📖 Documentation
🗂️ Table of Contents
🔧 Installation • ✅ Validation Rules • 🚀 Advanced Features • 🌍 Internationalization • 🔒 Security • 📚 API Reference • 🎯 Examples • 🌐 Browser Support
🔧 Installation
# npm
npm install @sc4rfurry-github/formguard
# Yarn
yarn add @sc4rfurry-github/formguard
# pnpm (recommended for performance)
pnpm add @sc4rfurry-github/formguard
# Bun (fastest)
bun add formguard
<!-- Latest version (recommended) -->
<script src="https://unpkg.com/formguard@latest/dist/formguard.min.js"></script>
<!-- Specific version (for production) -->
<script src="https://unpkg.com/formguard@1.0.0/dist/formguard.min.js"></script>
<!-- jsDelivr CDN (alternative) -->
<script src="https://cdn.jsdelivr.net/npm/formguard@latest/dist/formguard.min.js"></script>
// ES6 Modules (recommended)
import { FormGuard } from '@sc4rfurry-github/formguard';
// Default import
import FormGuard from '@sc4rfurry-github/formguard';
// CommonJS
const { FormGuard } = require('@sc4rfurry-github/formguard');
// AMD
define(['formguard'], function(FormGuard) {
// Your code here
});
// Global (CDN)
const formGuard = new window.FormGuard('#form');
✅ Validation Rules
🎯 Built-in Validators
Validator | Usage Example | Description |
---|---|---|
required |
data-validate="required" |
Field must have a non-empty value |
email |
data-validate="email" |
RFC 5321/5322 compliant email validation |
min |
data-validate="min:5" |
Minimum length (strings) or value (numbers) |
max |
data-validate="max:100" |
Maximum length (strings) or value (numbers) |
pattern |
data-validate="pattern:^[A-Z]+$" |
Custom regex pattern with ReDoS protection |
match |
data-validate="match:password" |
Must match another field's value |
url |
data-validate="url" |
Valid URL format validation |
number |
data-validate="number" |
Numeric value (integer or decimal) |
integer |
data-validate="integer" |
Integer value only |
date |
data-validate="date" |
Valid date format |
creditcard |
data-validate="creditcard" |
Credit card with type detection |
phone |
data-validate="phone" |
Phone number with country support |
remote |
data-validate="remote:/api/check" |
Server-side async validation |
unique |
data-validate="unique:/api/unique" |
Uniqueness validation via API |
🔗 Combining Validators
Chain multiple validators using the pipe (|
) separator:
<!-- Email with uniqueness check -->
<input data-validate="required|email|unique:/api/check-email" name="email">
<!-- Strong password requirements -->
<input data-validate="required|min:8|pattern:^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*?&])" name="password">
<!-- Confirm password -->
<input data-validate="required|match:password" name="confirm-password">
🎨 Enhanced Validator Features
<!-- Basic email validation -->
<input data-validate="email" type="email" name="email">
<!-- Email with additional constraints -->
<input data-validate="required|email|max:254" name="business-email">
Features:
- ✅ RFC 5321/5322 compliance
- ✅ Length validation (320 char max)
- ✅ Domain structure validation
- ✅ Comprehensive error messages
- ✅ International domain support
<!-- Any card type -->
<input data-validate="creditcard" name="card-number">
<!-- Specific card type -->
<input data-validate="creditcard:visa" name="visa-card">
<input data-validate="creditcard:mastercard" name="mc-card">
Supported Cards:
- 💳 Visa, Mastercard, American Express
- 💳 Discover, Diners Club, JCB
- 💳 Automatic type detection
- 💳 Test card number detection
- 💳 Luhn algorithm validation
<!-- International format -->
<input data-validate="phone" name="phone">
<!-- Country-specific -->
<input data-validate="phone:us" name="us-phone">
<input data-validate="phone:uk" name="uk-phone">
Features:
- 🌍 International format support
- 🏳️ Country-specific validation
- 🔍 Pattern validation for obvious fakes
- 📏 Length validation
- 🚫 Sequential/repeated digit detection
🚀 Advanced Features
🎯 Conditional Validation
Validate fields only when specific conditions are met:
<!-- Validate email only if subscription is checked -->
<label>
<input type="checkbox" name="subscribe" id="subscribe">
Subscribe to newsletter
</label>
<input
name="newsletter-email"
data-validate="email"
data-validate-if="subscribe:checked"
placeholder="Enter email for newsletter"
>
<!-- State field required only for US -->
<select name="country" id="country">
<option value="">Select Country</option>
<option value="us">United States</option>
<option value="ca">Canada</option>
<option value="uk">United Kingdom</option>
</select>
<input
name="state"
data-validate="required"
data-validate-if="country:us"
placeholder="State (required for US)"
>
<!-- Multiple conditions -->
<input
name="tax-id"
data-validate="required|pattern:^\d{2}-\d{7}$"
data-validate-if="country:us,business-type:corporation"
placeholder="Tax ID (format: XX-XXXXXXX)"
>
Supported Conditions:
- ✅
field:value
- Field has specific value - ✅
field:checked
- Checkbox/radio is checked - ✅
field:!empty
- Field is not empty - ✅
field:value1,value2
- Field has one of multiple values
👥 Group Validation
Group related fields for targeted validation:
<form id="registration-form">
<!-- Personal Information Group -->
<fieldset>
<legend>Personal Information</legend>
<input
name="firstName"
data-validate="required|min:2"
data-group="personal"
placeholder="First Name"
>
<input
name="lastName"
data-validate="required|min:2"
data-group="personal"
placeholder="Last Name"
>
<input
name="birthDate"
data-validate="required|date"
data-group="personal"
type="date"
>
</fieldset>
<!-- Contact Information Group -->
<fieldset>
<legend>Contact Information</legend>
<input
name="email"
data-validate="required|email|unique:/api/check-email"
data-group="contact"
type="email"
placeholder="Email Address"
>
<input
name="phone"
data-validate="required|phone"
data-group="contact"
placeholder="Phone Number"
>
</fieldset>
<!-- Address Information Group -->
<fieldset>
<legend>Address Information</legend>
<input
name="street"
data-validate="required|min:5"
data-group="address"
placeholder="Street Address"
>
<input
name="city"
data-validate="required|min:2"
data-group="address"
placeholder="City"
>
<input
name="zipCode"
data-validate="required|pattern:^\d{5}(-\d{4})?$"
data-group="address"
placeholder="ZIP Code"
>
</fieldset>
</form>
// Group validation methods
const formGuard = new FormGuard('#registration-form');
// Validate specific group
const isPersonalValid = await formGuard.validateGroup('personal');
console.log('Personal info valid:', isPersonalValid);
// Validate multiple groups
const contactValid = await formGuard.validateGroup('contact');
const addressValid = await formGuard.validateGroup('address');
// Validate all groups at once
const allGroupsValid = await formGuard.validateAllGroups();
// Get group-specific errors
const personalErrors = formGuard.getGroupErrors('personal');
const contactErrors = formGuard.getGroupErrors('contact');
// Clear group errors
formGuard.clearGroupErrors('personal');
// Get all validation groups
const groups = formGuard.getValidationGroups();
console.log('Available groups:', groups); // ['personal', 'contact', 'address']
⚡ Smart Async Validation
FormGuard provides robust async validation with built-in safeguards:
<!-- Username availability check -->
<input
name="username"
data-validate="required|min:3|unique:/api/check-username"
placeholder="Choose a username"
>
<!-- Email uniqueness validation -->
<input
name="email"
data-validate="required|email|remote:/api/validate-email"
type="email"
placeholder="Email address"
>
<!-- Custom async validation -->
<input
name="domain"
data-validate="required|remote:/api/check-domain?field=domain"
placeholder="Your domain name"
>
Built-in Protections:
- 🚫 Race Condition Prevention: Cancels previous requests when new ones start
- ⏱️ Request Timeout: Configurable timeout with fallback
- 🔄 Retry Logic: Automatic retry on network failures
- 🧠 Memory Management: Automatic cleanup of async operations
- 📊 Request Throttling: Prevents API spam
const formGuard = new FormGuard('#form', {
debounce: 500, // Wait 500ms before async validation
asyncTimeout: 5000, // 5 second timeout for async requests
maxAsyncPromises: 50, // Max concurrent async validations
retryAttempts: 2 // Retry failed requests twice
});
// Monitor async validation using DOM events
formGuard.form.addEventListener('formguard:async-start', (event) => {
console.log('Async validation started for:', event.detail.field.name);
});
formGuard.form.addEventListener('formguard:async-complete', (event) => {
console.log('Async validation completed:', event.detail.field.name, event.detail.result);
});
🌍 Internationalization
FormGuard provides comprehensive internationalization with automatic language detection and custom translation support:
🚀 Quick Setup
const formGuard = new FormGuard('#form', {
i18n: {
language: 'es', // Set to Spanish
fallbackLanguage: 'en', // Fallback to English
autoDetect: true // Auto-detect user language
}
});
// Change language dynamically
formGuard.setLanguage('fr');
console.log('Current language:', formGuard.getLanguage()); // 'fr'
🌐 Built-in Languages
🇺🇸 English (en) Default |
🇪🇸 Spanish (es) Español |
🇫🇷 French (fr) Français |
🇩🇪 German (de) Deutsch |
🎨 Custom Translations
// Add translations for a single language
formGuard.addMessages('es', {
required: 'Este campo es obligatorio',
email: 'Ingrese un email válido',
min: 'Mínimo {0} caracteres',
max: 'Máximo {0} caracteres'
});
// Add multi-language translations
formGuard.addMessages({
en: {
strongPassword: 'Password must contain uppercase, lowercase, number, and special character',
usernameAvailable: 'Username is available',
usernameTaken: 'Username is already taken'
},
es: {
strongPassword: 'La contraseña debe contener mayúsculas, minúsculas, números y caracteres especiales',
usernameAvailable: 'Nombre de usuario disponible',
usernameTaken: 'El nombre de usuario ya está en uso'
},
fr: {
strongPassword: 'Le mot de passe doit contenir des majuscules, minuscules, chiffres et caractères spéciaux',
usernameAvailable: 'Nom d\'utilisateur disponible',
usernameTaken: 'Le nom d\'utilisateur est déjà pris'
}
});
🔍 Smart Language Detection
FormGuard automatically detects the user's preferred language using this priority order:
- Explicit Configuration -
i18n.language
option - Stored Preference -
localStorage.getItem('formguard-language')
- Document Language -
<html lang="...">
attribute - Browser Language -
navigator.language
- Fallback Language -
i18n.fallbackLanguage
(default: 'en')
// Language detection in action
const formGuard = new FormGuard('#form', {
i18n: {
autoDetect: true,
fallbackLanguage: 'en'
}
});
// Save user preference
formGuard.setLanguage('de'); // Automatically saved to localStorage
🔒 Security Features
FormGuard is built with security as a first-class citizen, protecting against common web vulnerabilities:
🚫 XSS Prevention
// Automatic sanitization of all user inputs
const formGuard = new FormGuard('#form', {
sanitizeInputs: true, // Sanitize all input values
sanitizeMessages: true, // Sanitize error messages
allowedTags: ['b', 'i', 'em'], // Whitelist allowed HTML tags
escapeHtml: true // Escape HTML entities
});
// Safe error message handling
formGuard.setFieldError(field, '<script>alert("xss")</script>');
// Automatically sanitized to: <script>alert("xss")</script>
⚡ ReDoS Protection
Protection against Regular Expression Denial of Service attacks:
// Safe patterns - will validate normally
pattern('test123', '^[a-zA-Z0-9]+$'); // ✅ Safe
pattern('email@domain.com', '^[^@]+@[^@]+$'); // ✅ Safe
// Dangerous patterns - automatically detected and blocked
pattern('aaaaaaaaaaaX', '(a+)+$'); // ❌ Nested quantifiers
pattern('test', '([a-zA-Z]+)*$'); // ❌ Exponential backtracking
pattern('input', '(a|a)*$'); // ❌ Alternation ambiguity
// Configure ReDoS protection
const formGuard = new FormGuard('#form', {
security: {
enableReDoSProtection: true,
maxPatternLength: 1000,
patternTimeout: 100, // 100ms timeout for regex execution
blockDangerousPatterns: true
}
});
🧠 Memory Management
Prevent memory leaks and resource exhaustion:
const formGuard = new FormGuard('#form', {
memory: {
maxStateEntries: 1000, // Max validation states to keep
stateCleanupInterval: 300000, // Cleanup every 5 minutes
maxAsyncPromises: 100, // Max concurrent async operations
enableAutoCleanup: true, // Automatic memory cleanup
cleanupOnDestroy: true // Clean up when destroyed
}
});
// Manual memory management
formGuard.cleanupMemory(); // Force cleanup
formGuard.getMemoryUsage(); // Get current memory stats
🔐 Input Validation & Sanitization
// Comprehensive input protection
const formGuard = new FormGuard('#form', {
security: {
maxInputLength: 10000, // Prevent oversized inputs
blockSuspiciousPatterns: true, // Block common attack patterns
validateFileUploads: true, // Validate file types and sizes
sanitizeFileNames: true, // Sanitize uploaded file names
preventDirectoryTraversal: true // Block path traversal attempts
}
});
📊 Security Monitoring
// Monitor security events using DOM events
formGuard.form.addEventListener('formguard:security-violation', (event) => {
console.warn('Security violation detected:', event.detail);
// Log to security monitoring system
});
formGuard.form.addEventListener('formguard:suspicious-activity', (event) => {
console.warn('Suspicious activity:', event.detail);
// Implement rate limiting or blocking
});
� API Reference
Constructor
const formGuard = new FormGuard(selector, options);
Parameters:
selector
(string|HTMLElement) - Form selector or DOM elementoptions
(object) - Configuration options
🎯 Validation Methods
// Validate entire form
const isValid = await formGuard.validate();
// Validate specific field
const fieldValid = await formGuard.validateField(field);
// Validate field group
const groupValid = await formGuard.validateGroup('groupName');
// Validate all groups
const allGroupsValid = await formGuard.validateAllGroups();
// Manual validation trigger
formGuard.triggerValidation(field, 'blur');
📊 State Management
// Check form validity
const isValid = formGuard.isValid();
// Get all errors
const errors = formGuard.getErrors();
// Returns: { fieldName: 'Error message', ... }
// Get error count
const errorCount = formGuard.getErrorCount();
// Get validation groups
const groups = formGuard.getValidationGroups();
// Returns: ['personal', 'contact', 'address']
// Get group-specific errors
const groupErrors = formGuard.getGroupErrors('personal');
🎨 Field Management
// Set field error
formGuard.setFieldError(field, 'Custom error message');
// Clear field error
formGuard.clearFieldError(field);
// Clear all errors
formGuard.clearAllErrors();
// Clear group errors
formGuard.clearGroupErrors('groupName');
// Get field state
const fieldState = formGuard.getFieldState(field);
// Returns: { isValid: boolean, errors: string[], isDirty: boolean }
🌍 Internationalization
// Set language
formGuard.setLanguage('es');
// Get current language
const currentLang = formGuard.getLanguage();
// Add custom messages
formGuard.addMessages('es', {
required: 'Campo requerido',
email: 'Email inválido'
});
// Get available languages
const languages = formGuard.getAvailableLanguages();
🔄 Lifecycle Management
// Reset form validation
formGuard.reset();
// Destroy instance and cleanup
formGuard.destroy();
// Check if destroyed
const isDestroyed = formGuard.isDestroyed;
Synchronous Validators
formGuard.addCustomValidators({
// Strong password validator
strongPassword: (value) => {
const hasUpper = /[A-Z]/.test(value);
const hasLower = /[a-z]/.test(value);
const hasNumber = /\d/.test(value);
const hasSpecial = /[!@#$%^&*]/.test(value);
return (hasUpper && hasLower && hasNumber && hasSpecial) ||
'Password must contain uppercase, lowercase, number, and special character';
},
// Age validator
minimumAge: (value, minAge = 18) => {
const birthDate = new Date(value);
const today = new Date();
const age = today.getFullYear() - birthDate.getFullYear();
return age >= minAge || `Must be at least ${minAge} years old`;
},
// Custom pattern with friendly message
socialSecurity: (value) => {
const ssnPattern = /^\d{3}-\d{2}-\d{4}$/;
return ssnPattern.test(value) || 'Please enter SSN in format: XXX-XX-XXXX';
}
});
Asynchronous Validators
formGuard.addCustomValidators({
// Username availability
availableUsername: async (value, params, field) => {
if (!value || value.length < 3) return true; // Skip if empty or too short
try {
const response = await fetch(`/api/check-username?username=${encodeURIComponent(value)}`);
const data = await response.json();
return data.available || 'Username is already taken';
} catch (error) {
return 'Unable to verify username availability';
}
},
// Email domain validation
validEmailDomain: async (value, allowedDomains = []) => {
if (!value.includes('@')) return true;
const domain = value.split('@')[1];
try {
const response = await fetch(`/api/validate-domain?domain=${domain}`);
const data = await response.json();
return data.isValid || `Email domain ${domain} is not allowed`;
} catch (error) {
return 'Unable to validate email domain';
}
},
// Complex business logic validation
validateBusinessRules: async (value, params, field) => {
const formData = new FormData(field.form);
try {
const response = await fetch('/api/validate-business-rules', {
method: 'POST',
body: formData
});
const result = await response.json();
return result.isValid || result.message;
} catch (error) {
return 'Validation service unavailable';
}
}
});
Validator Parameters
// Validators can accept parameters
formGuard.addCustomValidators({
between: (value, min, max) => {
const num = parseFloat(value);
return (num >= min && num <= max) || `Value must be between ${min} and ${max}`;
},
fileSize: (value, maxSizeMB = 5) => {
if (!value || !value.files || !value.files[0]) return true;
const fileSizeMB = value.files[0].size / (1024 * 1024);
return fileSizeMB <= maxSizeMB || `File size must be less than ${maxSizeMB}MB`;
}
});
// Usage in HTML
// <input data-validate="between:18,65" name="age">
// <input data-validate="fileSize:10" type="file" name="upload">
🎯 Examples
📝 Complete Registration Form
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Registration - FormGuard Demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<form id="registration-form" novalidate>
<h2>Create Your Account</h2>
<!-- Personal Information -->
<fieldset>
<legend>Personal Information</legend>
<div class="form-group">
<label for="firstName">First Name *</label>
<input
type="text"
id="firstName"
name="firstName"
data-validate="required|min:2|max:50"
data-validate-group="personal"
placeholder="Enter your first name"
aria-describedby="firstName-help"
>
<small id="firstName-help">Minimum 2 characters</small>
</div>
<div class="form-group">
<label for="lastName">Last Name *</label>
<input
type="text"
id="lastName"
name="lastName"
data-validate="required|min:2|max:50"
data-validate-group="personal"
placeholder="Enter your last name"
>
</div>
<div class="form-group">
<label for="birthDate">Date of Birth *</label>
<input
type="date"
id="birthDate"
name="birthDate"
data-validate="required|minimumAge:18"
data-validate-group="personal"
>
</div>
</fieldset>
<!-- Account Information -->
<fieldset>
<legend>Account Information</legend>
<div class="form-group">
<label for="username">Username *</label>
<input
type="text"
id="username"
name="username"
data-validate="required|min:3|max:20|pattern:^[a-zA-Z0-9_]+$|availableUsername"
data-validate-group="account"
placeholder="Choose a unique username"
aria-describedby="username-help"
>
<small id="username-help">3-20 characters, letters, numbers, and underscores only</small>
</div>
<div class="form-group">
<label for="email">Email Address *</label>
<input
type="email"
id="email"
name="email"
data-validate="required|email|unique:/api/check-email"
data-validate-group="account"
placeholder="Enter your email address"
>
</div>
<div class="form-group">
<label for="password">Password *</label>
<input
type="password"
id="password"
name="password"
data-validate="required|min:8|strongPassword"
data-validate-group="account"
placeholder="Create a strong password"
aria-describedby="password-help"
>
<small id="password-help">Must contain uppercase, lowercase, number, and special character</small>
</div>
<div class="form-group">
<label for="confirmPassword">Confirm Password *</label>
<input
type="password"
id="confirmPassword"
name="confirmPassword"
data-validate="required|match:password"
data-validate-group="account"
placeholder="Confirm your password"
>
</div>
</fieldset>
<!-- Optional Newsletter -->
<fieldset>
<legend>Preferences</legend>
<div class="form-group">
<label>
<input
type="checkbox"
name="newsletter"
id="newsletter"
>
Subscribe to our newsletter
</label>
</div>
<div class="form-group">
<label for="newsletterEmail">Newsletter Email</label>
<input
type="email"
id="newsletterEmail"
name="newsletterEmail"
data-validate="email"
data-validate-if="newsletter:checked"
placeholder="Email for newsletter (optional)"
>
</div>
</fieldset>
<div class="form-actions">
<button type="button" id="validate-personal">Validate Personal Info</button>
<button type="button" id="validate-account">Validate Account Info</button>
<button type="submit">Create Account</button>
</div>
</form>
<script src="https://unpkg.com/formguard@latest/dist/formguard.min.js"></script>
<script>
// Initialize FormGuard
const formGuard = new FormGuard('#registration-form', {
validateOn: 'blur',
focusInvalid: true,
announceErrors: true,
i18n: {
language: 'en',
autoDetect: true
}
});
// Add custom validators
formGuard.addCustomValidators({
minimumAge: (value, minAge = 18) => {
const birthDate = new Date(value);
const today = new Date();
const age = today.getFullYear() - birthDate.getFullYear();
const monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
return age >= minAge || `You must be at least ${minAge} years old`;
},
strongPassword: (value) => {
const hasUpper = /[A-Z]/.test(value);
const hasLower = /[a-z]/.test(value);
const hasNumber = /\d/.test(value);
const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(value);
if (!hasUpper) return 'Password must contain at least one uppercase letter';
if (!hasLower) return 'Password must contain at least one lowercase letter';
if (!hasNumber) return 'Password must contain at least one number';
if (!hasSpecial) return 'Password must contain at least one special character';
return true;
},
availableUsername: async (value) => {
if (!value || value.length < 3) return true;
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 500));
const unavailableUsernames = ['admin', 'user', 'test', 'demo'];
return !unavailableUsernames.includes(value.toLowerCase()) ||
'This username is not available';
}
});
// Group validation buttons
document.getElementById('validate-personal').addEventListener('click', async () => {
const isValid = await formGuard.validateGroup('personal');
alert(isValid ? 'Personal information is valid!' : 'Please fix personal information errors');
});
document.getElementById('validate-account').addEventListener('click', async () => {
const isValid = await formGuard.validateGroup('account');
alert(isValid ? 'Account information is valid!' : 'Please fix account information errors');
});
// Form submission
document.getElementById('registration-form').addEventListener('submit', async (e) => {
e.preventDefault();
const isValid = await formGuard.validate();
if (isValid) {
alert('Registration successful!');
// Submit form data to server
} else {
alert('Please fix all errors before submitting');
}
});
</script>
</body>
</html>
🌐 Browser Support
Browser | Version | Notes |
---|---|---|
🌐 Chrome | 90+ | Full support for all features |
🦊 Firefox | 88+ | Full support for all features |
🧭 Safari | 14+ | Full support for all features |
🌊 Edge | 90+ | Full support for all features |
🎭 Opera | 76+ | Full support for all features |
🔧 Feature Requirements
JavaScript Features:
- ✅ ES6+ (Arrow functions, async/await, destructuring, modules)
- ✅ Promise support with async/await
- ✅ Map and Set collections
- ✅ Template literals and tagged templates
DOM APIs:
- ✅ MutationObserver (for dynamic form changes)
- ✅ IntersectionObserver (for performance optimization)
- ✅ Fetch API (for async validation)
- ✅ AbortController (for request cancellation)
CSS Features:
- ✅ CSS Custom Properties (for theming)
- ✅ CSS Grid and Flexbox (for layout)
- ✅ CSS transitions and animations
Accessibility:
- ✅ ARIA attributes and roles
- ✅ Screen reader compatibility
- ✅ Keyboard navigation support
- ✅ Focus management
📊 Performance
⚡ Performance Metrics
- 📦 Bundle Size: ~13KB gzipped (smaller than most alternatives)
- 🧠 Memory Usage: Configurable limits with automatic cleanup
- ⚡ Validation Speed: <1ms for sync validators, optimized async handling
- 🎨 DOM Updates: RAF-batched for smooth 60fps performance
- 🔄 Async Operations: Intelligent debouncing and request cancellation
- ♻️ Memory Management: Automatic garbage collection and cleanup
🤝 Contributing
🚀 Quick Start for Contributors
# 1️⃣ Fork and clone the repository
git clone https://github.com/sc4rfurry/FormGuard.git
cd FormGuard
# 2️⃣ Install dependencies
npm install
# 3️⃣ Run tests to ensure everything works
npm test
# 4️⃣ Start development server
npm run dev
# 5️⃣ Make your changes and test
npm run test:watch
# 6️⃣ Build for production
npm run build
# 7️⃣ Run linting
npm run lint
# 8️⃣ Format code
npm run format
# Run all tests
npm test
# Run tests in watch mode (recommended for development)
npm run test:watch
# Run tests with coverage report
npm run test:coverage
# Run specific test file
npm test -- validators.test.js
# Run tests for specific pattern
npm test -- --testNamePattern="email validation"
Test Coverage Requirements:
- 🎯 Minimum 90% code coverage
- ✅ Unit tests for all validators
- ✅ Integration tests for form workflows
- ✅ Accessibility tests for screen readers
- ✅ Performance tests for large forms
📋 Contribution Process
- 🍴 Fork the repository
- 🌿 Create a feature branch (
git checkout -b feature/amazing-feature
) - 💻 Make your changes with tests
- ✅ Ensure all tests pass (
npm test
) - 📝 Commit your changes (
git commit -m 'Add amazing feature'
) - 🚀 Push to your branch (
git push origin feature/amazing-feature
) - 🔄 Open a Pull Request
📊 Project Stats
📄 License
FormGuard is MIT Licensed
This means you can use FormGuard in any project, commercial or personal, with attribution.
🙏 Acknowledgments
Special thanks to our amazing contributors and the open source community!
- 🌟 Contributors: Thank you to everyone who has contributed code, documentation, and ideas
- 🎯 Inspiration: Built following modern web standards and accessibility guidelines
- 🛠️ Tools: Powered by Jest, Rollup, and other amazing open source tools
- 🌍 Community: Grateful for feedback and support from developers worldwide
🔗 Links & Resources
📚 Documentation & Guides
📖 Full Documentation • 🎯 Examples • 🔧 API Reference
🤝 Community & Support
💬 Discussions • 🐛 Issues • 📧 Contact
🚀 Development
🔄 Changelog • 🛣️ Roadmap • 🤝 Contributing
Made with ❤️ by sc4rfurry
FormGuard - Enterprise-Grade Form Validation for Modern Web Applications
⭐ Star us on GitHub • 🚀 Get Started • 📖 Read the Docs
If FormGuard has helped your project, please consider giving it a ⭐ on GitHub!