88 lines
3.4 KiB
Python
88 lines
3.4 KiB
Python
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
|