Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>PDF Magic Converter | Read, OCR & Convert Files</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
.dropzone { | |
border: 2px dashed #3b82f6; | |
transition: all 0.3s ease; | |
} | |
.dropzone.active { | |
border-color: #10b981; | |
background-color: #f0f9ff; | |
} | |
.progress-bar { | |
transition: width 0.3s ease; | |
} | |
.pdf-viewer { | |
height: 70vh; | |
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
} | |
.format-option:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
} | |
.sidebar { | |
transition: all 0.3s ease; | |
} | |
@media (max-width: 768px) { | |
.sidebar { | |
transform: translateX(-100%); | |
} | |
.sidebar.open { | |
transform: translateX(0); | |
} | |
} | |
</style> | |
</head> | |
<body class="bg-gray-50 font-sans"> | |
<!-- Mobile Menu Button --> | |
<button id="menuToggle" class="md:hidden fixed top-4 left-4 z-50 bg-blue-500 text-white p-2 rounded-lg shadow-lg"> | |
<i class="fas fa-bars"></i> | |
</button> | |
<!-- Sidebar --> | |
<div id="sidebar" class="sidebar fixed top-0 left-0 h-full w-64 bg-white shadow-lg z-40 p-4 overflow-y-auto"> | |
<div class="flex items-center mb-8"> | |
<i class="fas fa-file-pdf text-red-500 text-2xl mr-2"></i> | |
<h1 class="text-xl font-bold text-gray-800">PDF Magic</h1> | |
</div> | |
<div class="mb-6"> | |
<h2 class="text-sm uppercase font-semibold text-gray-500 mb-2">Navigation</h2> | |
<ul> | |
<li class="mb-1"> | |
<a href="#" class="flex items-center p-2 text-blue-600 rounded-lg bg-blue-50"> | |
<i class="fas fa-home mr-3"></i> | |
<span>Dashboard</span> | |
</a> | |
</li> | |
<li class="mb-1"> | |
<a href="#" class="flex items-center p-2 text-gray-600 hover:bg-gray-100 rounded-lg"> | |
<i class="fas fa-history mr-3"></i> | |
<span>Recent Files</span> | |
</a> | |
</li> | |
<li class="mb-1"> | |
<a href="#" class="flex items-center p-2 text-gray-600 hover:bg-gray-100 rounded-lg"> | |
<i class="fas fa-cog mr-3"></i> | |
<span>Settings</span> | |
</a> | |
</li> | |
</ul> | |
</div> | |
<div> | |
<h2 class="text-sm uppercase font-semibold text-gray-500 mb-2">Tools</h2> | |
<ul> | |
<li class="mb-1"> | |
<a href="#" class="flex items-center p-2 text-gray-600 hover:bg-gray-100 rounded-lg"> | |
<i class="fas fa-file-export mr-3"></i> | |
<span>Batch Convert</span> | |
</a> | |
</li> | |
<li class="mb-1"> | |
<a href="#" class="flex items-center p-2 text-gray-600 hover:bg-gray-100 rounded-lg"> | |
<i class="fas fa-key mr-3"></i> | |
<span>Secure PDF</span> | |
</a> | |
</li> | |
<li class="mb-1"> | |
<a href="#" class="flex items-center p-2 text-gray-600 hover:bg-gray-100 rounded-lg"> | |
<i class="fas fa-font mr-3"></i> | |
<span>OCR Settings</span> | |
</a> | |
</li> | |
</ul> | |
</div> | |
<div class="mt-8 pt-4 border-t border-gray-200"> | |
<div class="flex items-center"> | |
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-600"> | |
<i class="fas fa-user"></i> | |
</div> | |
<div class="ml-3"> | |
<p class="text-sm font-medium text-gray-700">John Doe</p> | |
<p class="text-xs text-gray-500">Free Plan</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Main Content --> | |
<div class="ml-0 md:ml-64 p-4 md:p-8"> | |
<div class="max-w-6xl mx-auto"> | |
<header class="mb-8"> | |
<h1 class="text-3xl font-bold text-gray-800 mb-2">PDF Converter with OCR</h1> | |
<p class="text-gray-600">Upload your PDF files, extract text with OCR if needed, and convert to any format</p> | |
</header> | |
<!-- Upload Section --> | |
<div class="bg-white rounded-xl shadow-md p-6 mb-8"> | |
<div id="dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer"> | |
<div class="flex flex-col items-center justify-center"> | |
<i class="fas fa-file-upload text-4xl text-blue-500 mb-4"></i> | |
<h3 class="text-xl font-semibold text-gray-700 mb-2">Drag & Drop your PDF file here</h3> | |
<p class="text-gray-500 mb-4">or click to browse files</p> | |
<input type="file" id="fileInput" class="hidden" accept=".pdf"> | |
<button id="browseBtn" class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-6 rounded-lg transition duration-200"> | |
Select File | |
</button> | |
</div> | |
</div> | |
<div id="fileInfo" class="hidden mt-4 p-4 bg-blue-50 rounded-lg"> | |
<div class="flex items-center"> | |
<i class="fas fa-file-pdf text-red-500 text-2xl mr-3"></i> | |
<div class="flex-1"> | |
<div class="flex justify-between items-center"> | |
<span id="fileName" class="font-medium text-gray-800">sample.pdf</span> | |
<span id="fileSize" class="text-sm text-gray-500">2.4 MB</span> | |
</div> | |
<div class="w-full bg-gray-200 rounded-full h-2.5 mt-2"> | |
<div id="uploadProgress" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div> | |
</div> | |
</div> | |
<button id="cancelUpload" class="ml-4 text-gray-500 hover:text-gray-700"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Processing Options --> | |
<div id="processingOptions" class="hidden bg-white rounded-xl shadow-md p-6 mb-8"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Processing Options</h2> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
<!-- OCR Options --> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<div class="flex items-center mb-3"> | |
<i class="fas fa-font text-blue-500 mr-2"></i> | |
<h3 class="font-medium text-gray-700">OCR Settings</h3> | |
</div> | |
<div class="space-y-3"> | |
<div class="flex items-center"> | |
<input id="autoOcr" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked> | |
<label for="autoOcr" class="ml-2 block text-sm text-gray-700">Auto-detect and apply OCR if needed</label> | |
</div> | |
<div class="ml-6 space-y-2"> | |
<div class="flex items-center"> | |
<input id="ocrEnglish" type="radio" name="ocrLanguage" value="eng" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300" checked> | |
<label for="ocrEnglish" class="ml-2 block text-sm text-gray-700">English</label> | |
</div> | |
<div class="flex items-center"> | |
<input id="ocrSpanish" type="radio" name="ocrLanguage" value="spa" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"> | |
<label for="ocrSpanish" class="ml-2 block text-sm text-gray-700">Spanish</label> | |
</div> | |
<div class="flex items-center"> | |
<input id="ocrFrench" type="radio" name="ocrLanguage" value="fra" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"> | |
<label for="ocrFrench" class="ml-2 block text-sm text-gray-700">French</label> | |
</div> | |
</div> | |
<div class="flex items-center mt-2"> | |
<input id="enhanceOcr" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked> | |
<label for="enhanceOcr" class="ml-2 block text-sm text-gray-700">Enhance image quality before OCR</label> | |
</div> | |
</div> | |
</div> | |
<!-- Conversion Options --> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<div class="flex items-center mb-3"> | |
<i class="fas fa-exchange-alt text-blue-500 mr-2"></i> | |
<h3 class="font-medium text-gray-700">Conversion Options</h3> | |
</div> | |
<div class="space-y-3"> | |
<label class="block text-sm font-medium text-gray-700">Output Format</label> | |
<div class="grid grid-cols-3 gap-2"> | |
<button data-format="docx" class="format-option bg-white border border-gray-200 rounded-lg p-3 text-center hover:border-blue-300 transition"> | |
<i class="fas fa-file-word text-blue-500 text-2xl mb-1"></i> | |
<span class="block text-xs font-medium">DOCX</span> | |
</button> | |
<button data-format="txt" class="format-option bg-white border border-gray-200 rounded-lg p-3 text-center hover:border-blue-300 transition"> | |
<i class="fas fa-file-alt text-gray-500 text-2xl mb-1"></i> | |
<span class="block text-xs font-medium">TXT</span> | |
</button> | |
<button data-format="html" class="format-option bg-white border border-gray-200 rounded-lg p-3 text-center hover:border-blue-300 transition"> | |
<i class="fas fa-code text-orange-500 text-2xl mb-1"></i> | |
<span class="block text-xs font-medium">HTML</span> | |
</button> | |
<button data-format="epub" class="format-option bg-white border border-gray-200 rounded-lg p-3 text-center hover:border-blue-300 transition"> | |
<i class="fas fa-book text-purple-500 text-2xl mb-1"></i> | |
<span class="block text-xs font-medium">EPUB</span> | |
</button> | |
<button data-format="odt" class="format-option bg-white border border-gray-200 rounded-lg p-3 text-center hover:border-blue-300 transition"> | |
<i class="fas fa-file-alt text-blue-400 text-2xl mb-1"></i> | |
<span class="block text-xs font-medium">ODT</span> | |
</button> | |
<button data-format="markdown" class="format-option bg-white border border-gray-200 rounded-lg p-3 text-center hover:border-blue-300 transition"> | |
<i class="fas fa-file-code text-gray-700 text-2xl mb-1"></i> | |
<span class="block text-xs font-medium">Markdown</span> | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="mt-6 flex justify-end"> | |
<button id="processBtn" class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-6 rounded-lg transition duration-200 flex items-center"> | |
<i class="fas fa-cog mr-2"></i> Process File | |
</button> | |
</div> | |
</div> | |
<!-- Results Section --> | |
<div id="resultsSection" class="hidden bg-white rounded-xl shadow-md p-6"> | |
<div class="flex justify-between items-center mb-4"> | |
<h2 class="text-xl font-semibold text-gray-800">Results</h2> | |
<div class="flex space-x-2"> | |
<button id="downloadBtn" class="bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4 rounded-lg transition duration-200 flex items-center"> | |
<i class="fas fa-download mr-2"></i> Download | |
</button> | |
<button id="newFileBtn" class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-2 px-4 rounded-lg transition duration-200 flex items-center"> | |
<i class="fas fa-plus mr-2"></i> New File | |
</button> | |
</div> | |
</div> | |
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> | |
<!-- Original PDF Viewer --> | |
<div class="lg:col-span-1"> | |
<div class="bg-gray-100 rounded-lg p-3 mb-2"> | |
<h3 class="font-medium text-gray-700 flex items-center"> | |
<i class="fas fa-file-pdf text-red-500 mr-2"></i> Original PDF | |
</h3> | |
</div> | |
<div class="pdf-viewer bg-gray-50 rounded-lg overflow-hidden"> | |
<div class="h-full flex items-center justify-center text-gray-400"> | |
<div class="text-center"> | |
<i class="fas fa-file-pdf text-5xl mb-2"></i> | |
<p>PDF Preview</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Extracted Text --> | |
<div class="lg:col-span-2"> | |
<div class="bg-gray-100 rounded-lg p-3 mb-2"> | |
<h3 class="font-medium text-gray-700 flex items-center"> | |
<i class="fas fa-font text-blue-500 mr-2"></i> Extracted Text | |
</h3> | |
</div> | |
<div class="pdf-viewer bg-white border border-gray-200 rounded-lg p-4 overflow-y-auto"> | |
<div id="extractedText" class="prose max-w-none"> | |
<p class="text-gray-500 italic">Text will appear here after processing...</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Conversion Status --> | |
<div id="conversionStatus" class="mt-6 hidden"> | |
<div class="bg-blue-50 border-l-4 border-blue-500 p-4"> | |
<div class="flex"> | |
<div class="flex-shrink-0"> | |
<i class="fas fa-cog fa-spin text-blue-500"></i> | |
</div> | |
<div class="ml-3"> | |
<h3 class="text-sm font-medium text-blue-800">Processing your file</h3> | |
<div class="mt-2 text-sm text-blue-700"> | |
<p id="statusMessage">Performing OCR and converting to DOCX...</p> | |
<div class="w-full bg-gray-200 rounded-full h-2.5 mt-2"> | |
<div id="processProgress" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Features Section --> | |
<div class="mt-12"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6 text-center">Why Choose PDF Magic?</h2> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
<div class="text-blue-500 mb-4"> | |
<i class="fas fa-robot text-3xl"></i> | |
</div> | |
<h3 class="text-lg font-semibold mb-2">Smart OCR</h3> | |
<p class="text-gray-600">Automatically detects scanned documents and applies high-quality OCR to extract text with precision.</p> | |
</div> | |
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
<div class="text-green-500 mb-4"> | |
<i class="fas fa-exchange-alt text-3xl"></i> | |
</div> | |
<h3 class="text-lg font-semibold mb-2">Multi-format Conversion</h3> | |
<p class="text-gray-600">Convert your PDFs to DOCX, TXT, HTML, EPUB and more using powerful Pandoc engine.</p> | |
</div> | |
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
<div class="text-purple-500 mb-4"> | |
<i class="fas fa-lock text-3xl"></i> | |
</div> | |
<h3 class="text-lg font-semibold mb-2">Secure Processing</h3> | |
<p class="text-gray-600">Your files are processed securely in your browser and never uploaded to our servers.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Mobile menu toggle | |
document.getElementById('menuToggle').addEventListener('click', function() { | |
document.getElementById('sidebar').classList.toggle('open'); | |
}); | |
// File upload handling | |
const dropzone = document.getElementById('dropzone'); | |
const fileInput = document.getElementById('fileInput'); | |
const browseBtn = document.getElementById('browseBtn'); | |
const fileInfo = document.getElementById('fileInfo'); | |
const fileName = document.getElementById('fileName'); | |
const fileSize = document.getElementById('fileSize'); | |
const uploadProgress = document.getElementById('uploadProgress'); | |
const cancelUpload = document.getElementById('cancelUpload'); | |
const processingOptions = document.getElementById('processingOptions'); | |
const resultsSection = document.getElementById('resultsSection'); | |
const processBtn = document.getElementById('processBtn'); | |
const downloadBtn = document.getElementById('downloadBtn'); | |
const newFileBtn = document.getElementById('newFileBtn'); | |
const conversionStatus = document.getElementById('conversionStatus'); | |
const statusMessage = document.getElementById('statusMessage'); | |
const processProgress = document.getElementById('processProgress'); | |
const extractedText = document.getElementById('extractedText'); | |
const formatOptions = document.querySelectorAll('.format-option'); | |
let selectedFormat = 'docx'; | |
let currentFile = null; | |
// Highlight dropzone when dragging over | |
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
dropzone.addEventListener(eventName, preventDefaults, false); | |
}); | |
function preventDefaults(e) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
['dragenter', 'dragover'].forEach(eventName => { | |
dropzone.addEventListener(eventName, highlight, false); | |
}); | |
['dragleave', 'drop'].forEach(eventName => { | |
dropzone.addEventListener(eventName, unhighlight, false); | |
}); | |
function highlight() { | |
dropzone.classList.add('active'); | |
} | |
function unhighlight() { | |
dropzone.classList.remove('active'); | |
} | |
// Handle dropped files | |
dropzone.addEventListener('drop', handleDrop, false); | |
function handleDrop(e) { | |
const dt = e.dataTransfer; | |
const files = dt.files; | |
handleFiles(files); | |
} | |
// Handle file selection via button | |
browseBtn.addEventListener('click', () => { | |
fileInput.click(); | |
}); | |
fileInput.addEventListener('change', () => { | |
if (fileInput.files.length) { | |
handleFiles(fileInput.files); | |
} | |
}); | |
// Cancel upload | |
cancelUpload.addEventListener('click', () => { | |
resetUpload(); | |
}); | |
// New file button | |
newFileBtn.addEventListener('click', resetUpload); | |
// Format selection | |
formatOptions.forEach(option => { | |
option.addEventListener('click', function() { | |
formatOptions.forEach(opt => opt.classList.remove('border-blue-500', 'bg-blue-50')); | |
this.classList.add('border-blue-500', 'bg-blue-50'); | |
selectedFormat = this.dataset.format; | |
}); | |
}); | |
// Process file button | |
processBtn.addEventListener('click', processFile); | |
// Download button | |
downloadBtn.addEventListener('click', () => { | |
alert(`Downloading file in ${selectedFormat.toUpperCase()} format`); | |
// In a real app, this would trigger the download of the converted file | |
}); | |
function handleFiles(files) { | |
currentFile = files[0]; | |
// Update file info | |
fileName.textContent = currentFile.name; | |
fileSize.textContent = formatFileSize(currentFile.size); | |
// Show file info and hide dropzone | |
fileInfo.classList.remove('hidden'); | |
dropzone.classList.add('hidden'); | |
// Simulate upload progress | |
let progress = 0; | |
const interval = setInterval(() => { | |
progress += Math.random() * 10; | |
if (progress >= 100) { | |
progress = 100; | |
clearInterval(interval); | |
uploadComplete(); | |
} | |
uploadProgress.style.width = `${progress}%`; | |
}, 200); | |
} | |
function uploadComplete() { | |
processingOptions.classList.remove('hidden'); | |
} | |
function processFile() { | |
processingOptions.classList.add('hidden'); | |
conversionStatus.classList.remove('hidden'); | |
resultsSection.classList.remove('hidden'); | |
// Simulate processing steps | |
let progress = 0; | |
const steps = [ | |
{progress: 20, message: "Analyzing PDF content..."}, | |
{progress: 40, message: "Detecting text layers..."}, | |
{progress: 60, message: "Applying OCR to scanned pages..."}, | |
{progress: 80, message: `Converting to ${selectedFormat.toUpperCase()} format...`}, | |
{progress: 100, message: "Conversion complete!"} | |
]; | |
let currentStep = 0; | |
const processInterval = setInterval(() => { | |
if (currentStep < steps.length) { | |
progress = steps[currentStep].progress; | |
statusMessage.textContent = steps[currentStep].message; | |
processProgress.style.width = `${progress}%`; | |
currentStep++; | |
// Update extracted text at certain steps | |
if (currentStep === 3) { | |
extractedText.innerHTML = ` | |
<h1>Sample Extracted Document</h1> | |
<p>This is text that was extracted from your PDF document using our advanced OCR technology.</p> | |
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam in dui mauris. Vivamus hendrerit arcu sed erat molestie vehicula.</p> | |
<h2>Section 1</h2> | |
<p>Sed auctor neque eu tellus rhoncus ut eleifend nibh porttitor. Ut in nulla enim. Phasellus molestie magna non est bibendum non venenatis nisl tempor.</p> | |
<p>This text would normally be extracted from your actual PDF file.</p> | |
`; | |
} | |
} else { | |
clearInterval(processInterval); | |
conversionStatus.classList.add('hidden'); | |
} | |
}, 1500); | |
} | |
function resetUpload() { | |
fileInfo.classList.add('hidden'); | |
processingOptions.classList.add('hidden'); | |
resultsSection.classList.add('hidden'); | |
conversionStatus.classList.add('hidden'); | |
dropzone.classList.remove('hidden'); | |
uploadProgress.style.width = '0%'; | |
processProgress.style.width = '0%'; | |
fileInput.value = ''; | |
currentFile = null; | |
extractedText.innerHTML = '<p class="text-gray-500 italic">Text will appear here after processing...</p>'; | |
} | |
function formatFileSize(bytes) { | |
if (bytes === 0) return '0 Bytes'; | |
const k = 1024; | |
const sizes = ['Bytes', 'KB', 'MB', 'GB']; | |
const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; | |
} | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=RedSparkie/epub" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |