import os import re def check_css_fluidity(content): """Checks for hardcoded px in CSS unless it's 0 or 1px.""" # Find patterns like "300px", "margin: 20px" px_pattern = re.compile(r'(\d+px)') matches = px_pattern.findall(content) # Ignore 0px, 1px, 2px (usually borders) critical_matches = [m for m in matches if int(m.replace('px', '')) > 2] return critical_matches def check_14kb_rule(file_path): """Checks if file size is below 14KB.""" size = os.path.getsize(file_path) return size < 14336 # 14KB in bytes def audit_file(file_path): results = [] # 14KB Check if file_path.endswith(('.html', '.css', '.js', '.jsx')): is_ok = check_14kb_rule(file_path) results.append({ "rule": "14KB Limit", "passed": is_ok, "details": f"Size: {os.path.getsize(file_path)} bytes" }) # Content Checks for JS/JSX if file_path.endswith(('.js', '.jsx')): with open(file_path, 'r', encoding='utf-8') as f: content = f.read() # 1. Loading States if any(x in content for x in ['form', 'onSubmit', 'handleSubmit']): has_loading = 'loading' in content.lower() or 'disabled' in content.lower() results.append({ "rule": "Loading/Disabled States", "passed": has_loading, "details": "Checking if form handles loading/disabled states." }) # 2. Required Fields has_validation = any(x in content.lower() for x in ['required', 'schema', 'validation', 'validate']) results.append({ "rule": "Field Validation", "passed": has_validation, "details": "Checking for required fields or schema validation." }) # 3. Error Handling has_error = any(x in content.lower() for x in ['error', 'catch', 'try']) results.append({ "rule": "Error Handling", "passed": has_error, "details": "Checking for API error handling or try/catch blocks." }) # 4. Visual Feedback has_feedback = any(x in content.lower() for x in ['toast', 'alert', 'sonner', 'message']) results.append({ "rule": "Visual Feedback (Toasts)", "passed": has_feedback, "details": "Checking for user feedback mechanisms (Toasts/Alerts)." }) # 5. Service Usage (instead of direct axios/fetch) if 'axios' in content and 'Service' not in content and 'useApiContract' not in content: results.append({ "rule": "Service Abstraction", "passed": False, "details": "Direct axios call found. API calls should be in Services or use useApiContract." }) # CSS Fluidity Check if file_path.endswith('.css'): with open(file_path, 'r', encoding='utf-8') as f: content = f.read() bad_px = check_css_fluidity(content) results.append({ "rule": "CSS Fluidity (clamp/min/max)", "passed": len(bad_px) == 0, "details": f"Found these hardcoded px: {bad_px}" if bad_px else "All good!" }) return results