Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Python Code Linter | PEP 8 & Flake8 Compliance</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script> | |
tailwind.config = { | |
darkMode: 'class' | |
} | |
</script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
.code-editor { | |
min-height: 300px; | |
font-family: 'Courier New', monospace; | |
font-size: 14px; | |
line-height: 1.5; | |
tab-size: 4; | |
} | |
.report-item { | |
transition: all 0.2s ease; | |
} | |
.report-item:hover { | |
transform: translateX(5px); | |
} | |
.tab-active { | |
border-bottom: 3px solid #3b82f6; | |
} | |
.error-badge { | |
position: absolute; | |
top: -8px; | |
right: -8px; | |
font-size: 12px; | |
} | |
@keyframes pulse { | |
0%, 100% { | |
opacity: 1; | |
} | |
50% { | |
opacity: 0.5; | |
} | |
} | |
.animate-pulse { | |
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; | |
} | |
/* Dark mode transitions */ | |
body, .bg-white, .bg-gray-50, .border-gray-200, .border-gray-300, .divide-gray-200 { | |
transition: background-color 0.3s ease, border-color 0.3s ease; | |
} | |
/* Toggle switch styling */ | |
.toggle-checkbox:checked { | |
right: 0; | |
border-color: #68D391; | |
} | |
.toggle-checkbox:checked + .toggle-label { | |
background-color: #68D391; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-50 min-h-screen dark:bg-gray-900"> | |
<div class="container mx-auto px-4 py-8"> | |
<!-- Header --> | |
<header class="mb-8 text-center relative"> | |
<div class="absolute top-0 right-0"> | |
<div class="flex items-center"> | |
<span class="mr-2 text-sm text-gray-600 dark:text-gray-300"> | |
<i class="fas fa-sun"></i> | |
</span> | |
<div class="relative inline-block w-10 mr-2 align-middle select-none"> | |
<input type="checkbox" id="toggle" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/> | |
<label for="toggle" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label> | |
</div> | |
<span class="text-sm text-gray-600 dark:text-gray-300"> | |
<i class="fas fa-moon"></i> | |
</span> | |
</div> | |
</div> | |
<h1 class="text-4xl font-bold text-blue-600 dark:text-blue-400 mb-2"> | |
<i class="fas fa-code mr-2"></i>Python Code Linter | |
</h1> | |
<p class="text-gray-600 dark:text-gray-300 text-lg"> | |
Improve your Python code to meet Flake8 and PEP 8 standards | |
</p> | |
</header> | |
<!-- Main Content --> | |
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden"> | |
<!-- Tabs --> | |
<div class="flex border-b dark:border-gray-700"> | |
<button id="paste-tab" class="tab-active px-6 py-4 font-medium text-blue-600 dark:text-blue-400 focus:outline-none"> | |
<i class="fas fa-paste mr-2"></i>Paste Code | |
</button> | |
<button id="upload-tab" class="px-6 py-4 font-medium text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 focus:outline-none"> | |
<i class="fas fa-upload mr-2"></i>Upload File | |
</button> | |
<div class="ml-auto px-6 py-4"> | |
<span id="error-count" class="hidden bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 text-xs font-medium px-2.5 py-0.5 rounded-full"> | |
<span id="error-count-value">0</span> issues found | |
</span> | |
</div> | |
</div> | |
<!-- Tab Content --> | |
<div class="p-6"> | |
<!-- Paste Code Tab Content --> | |
<div id="paste-content" class="space-y-6"> | |
<div class="flex space-x-4"> | |
<div class="flex-1 relative"> | |
<label for="python-code" class="block mb-2 text-sm font-medium text-gray-700 dark:text-gray-300"> | |
Original Python Code | |
<span class="text-gray-500 dark:text-gray-400 text-xs">(Ctrl+Enter to lint)</span> | |
</label> | |
<div class="relative"> | |
<textarea id="python-code" class="code-editor w-full p-4 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-gray-100 dark:placeholder-gray-400" placeholder="Paste your Python code here..."></textarea> | |
<button id="clear-code" class="absolute top-2 right-2 p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
</div> | |
<div class="flex-1 relative"> | |
<label for="linted-code" class="block mb-2 text-sm font-medium text-gray-700 dark:text-gray-300"> | |
Linted Python Code | |
</label> | |
<div class="relative"> | |
<pre id="linted-code" class="code-editor w-full p-4 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 dark:text-gray-100 overflow-auto" style="white-space: pre-wrap;"></pre> | |
<button id="copy-code" class="absolute top-2 right-2 p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"> | |
<i class="fas fa-copy"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
<div class="flex justify-center"> | |
<button id="lint-button" class="px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors dark:bg-blue-700 dark:hover:bg-blue-600"> | |
<i class="fas fa-magic mr-2"></i>Lint My Code | |
</button> | |
</div> | |
</div> | |
<!-- Upload File Tab Content --> | |
<div id="upload-content" class="hidden space-y-6"> | |
<div class="flex items-center justify-center w-full"> | |
<label for="file-upload" class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 dark:border-gray-600 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600"> | |
<div class="flex flex-col items-center justify-center pt-5 pb-6"> | |
<i class="fas fa-file-upload text-4xl text-gray-400 dark:text-gray-300 mb-3"></i> | |
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400"> | |
<span class="font-semibold">Click to upload</span> or drag and drop | |
</p> | |
<p class="text-xs text-gray-500 dark:text-gray-400">.py files only</p> | |
</div> | |
<input id="file-upload" type="file" class="hidden" accept=".py" /> | |
</label> | |
</div> | |
<div class="hidden" id="upload-preview"> | |
<div class="flex items-center justify-between mb-4"> | |
<div> | |
<span id="uploaded-filename" class="font-medium text-gray-700 dark:text-gray-300"></span> | |
<span id="uploaded-filesize" class="text-sm text-gray-500 dark:text-gray-400 ml-2"></span> | |
</div> | |
<button id="remove-file" class="text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"> | |
<i class="fas fa-trash mr-1"></i>Remove | |
</button> | |
</div> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
<div> | |
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Original Code</h3> | |
<pre id="upload-original-code" class="code-editor w-full p-4 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 dark:text-gray-100 overflow-auto max-h-64"></pre> | |
</div> | |
<div> | |
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Linted Code</h3> | |
<pre id="upload-linted-code" class="code-editor w-full p-4 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 dark:text-gray-100 overflow-auto max-h-64"></pre> | |
</div> | |
</div> | |
<div class="mt-4 flex justify-center"> | |
<button id="lint-upload-button" class="px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors dark:bg-blue-700 dark:hover:bg-blue-600"> | |
<i class="fas fa-magic mr-2"></i>Lint Uploaded File | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Linting Report --> | |
<div id="report-section" class="hidden mt-8"> | |
<h2 class="text-xl font-semibold text-gray-800 dark:text-gray-200 mb-4"> | |
<i class="fas fa-clipboard-list mr-2"></i>Linting Report | |
</h2> | |
<div class="flex mb-4"> | |
<div class="flex-1"> | |
<div class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200"> | |
<i class="fas fa-check-circle mr-1"></i> | |
<span id="fixed-count">0</span> issues fixed | |
</div> | |
</div> | |
<div class="flex-1 text-right"> | |
<div class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200"> | |
<i class="fas fa-exclamation-triangle mr-1"></i> | |
<span id="remaining-count">0</span> issues remaining | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg border border-gray-200 dark:border-gray-600 overflow-hidden"> | |
<div id="report-items" class="divide-y divide-gray-200 dark:divide-gray-600 max-h-96 overflow-y-auto"> | |
<!-- Report items will be added here dynamically --> | |
</div> | |
</div> | |
<div class="mt-4 text-sm text-gray-500 dark:text-gray-400"> | |
<i class="fas fa-info-circle mr-1"></i> PEP 8 is the official style guide for Python code. Flake8 is a tool that checks your code against PEP 8 and other quality standards. | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Features Section --> | |
<div class="mt-12 grid grid-cols-1 md:grid-cols-3 gap-6"> | |
<div class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md"> | |
<div class="text-blue-500 dark:text-blue-400 text-2xl mb-3"> | |
<i class="fas fa-broom"></i> | |
</div> | |
<h3 class="font-semibold text-lg mb-2 dark:text-gray-200">Code Cleanup</h3> | |
<p class="text-gray-600 dark:text-gray-300">Automatically fix indentation, whitespace, line length, and other PEP 8 violations to make your code more readable.</p> | |
</div> | |
<div class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md"> | |
<div class="text-blue-500 dark:text-blue-400 text-2xl mb-3"> | |
<i class="fas fa-search"></i> | |
</div> | |
<h3 class="font-semibold text-lg mb-2 dark:text-gray-200">Comprehensive Checks</h3> | |
<p class="text-gray-600 dark:text-gray-300">Detects and reports on style issues, syntax errors, and potential bugs using Flake8's powerful analysis.</p> | |
</div> | |
<div class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md"> | |
<div class="text-blue-500 dark:text-blue-400 text-2xl mb-3"> | |
<i class="fas fa-graduation-cap"></i> | |
</div> | |
<h3 class="font-semibold text-lg mb-2 dark:text-gray-200">Learn Best Practices</h3> | |
<p class="text-gray-600 dark:text-gray-300">Detailed explanations help you understand and remember Python coding standards for future projects.</p> | |
</div> | |
</div> | |
<!-- Footer --> | |
<footer class="mt-12 text-center text-gray-500 dark:text-gray-400 text-sm"> | |
<p>Made with <i class="fas fa-heart text-red-500"></i> for Python developers</p> | |
<p class="mt-1">This tool helps improve code quality but doesn't replace thorough testing and code reviews.</p> | |
</footer> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// Dark mode toggle functionality | |
const toggle = document.getElementById('toggle'); | |
const html = document.documentElement; | |
// Check for saved user preference or use system preference | |
const savedTheme = localStorage.getItem('theme') || | |
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); | |
if (savedTheme === 'dark') { | |
html.classList.add('dark'); | |
toggle.checked = true; | |
} | |
// Toggle dark mode | |
toggle.addEventListener('change', function() { | |
if (this.checked) | |
</html> |