import { PDFDocument, PDFName } from 'pdf-lib'; import { createIcons, icons } from 'lucide'; // State management const pageState: { pdfDoc: PDFDocument | null; file: File | null } = { pdfDoc: null, file: null, }; // UI helpers function showLoader(message: string = 'Processing...') { const loader = document.getElementById('loader-modal'); const loaderText = document.getElementById('loader-text'); if (loader) loader.classList.remove('hidden'); if (loaderText) loaderText.textContent = message; } function hideLoader() { const loader = document.getElementById('loader-modal'); if (loader) loader.classList.add('hidden'); } function showAlert(title: string, message: string, type: string = 'error', callback?: () => void) { const modal = document.getElementById('alert-modal'); const alertTitle = document.getElementById('alert-title'); const alertMessage = document.getElementById('alert-message'); const okBtn = document.getElementById('alert-ok'); if (alertTitle) alertTitle.textContent = title; if (alertMessage) alertMessage.textContent = message; if (modal) modal.classList.remove('hidden'); if (okBtn) { const newOkBtn = okBtn.cloneNode(true) as HTMLElement; okBtn.replaceWith(newOkBtn); newOkBtn.addEventListener('click', () => { modal?.classList.add('hidden'); if (callback) callback(); }); } } function downloadFile(blob: Blob, filename: string) { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); } function updateFileDisplay() { const displayArea = document.getElementById('file-display-area'); if (!displayArea || !pageState.file || !pageState.pdfDoc) return; const fileSize = pageState.file.size < 1024 * 1024 ? `${(pageState.file.size / 1024).toFixed(1)} KB` : `${(pageState.file.size / 1024 / 1024).toFixed(2)} MB`; const pageCount = pageState.pdfDoc.getPageCount(); displayArea.innerHTML = `

${pageState.file.name}

${fileSize} • ${pageCount} page${pageCount !== 1 ? 's' : ''}

`; createIcons({ icons }); document.getElementById('remove-file')?.addEventListener('click', () => resetState()); } function resetState() { pageState.pdfDoc = null; pageState.file = null; const displayArea = document.getElementById('file-display-area'); if (displayArea) displayArea.innerHTML = ''; document.getElementById('options-panel')?.classList.add('hidden'); const fileInput = document.getElementById('file-input') as HTMLInputElement; if (fileInput) fileInput.value = ''; } // File handling async function handleFileUpload(file: File) { if (!file || file.type !== 'application/pdf') { showAlert('Error', 'Please upload a valid PDF file.'); return; } showLoader('Loading PDF...'); try { const arrayBuffer = await file.arrayBuffer(); pageState.pdfDoc = await PDFDocument.load(arrayBuffer); pageState.file = file; updateFileDisplay(); document.getElementById('options-panel')?.classList.remove('hidden'); } catch (error) { console.error(error); showAlert('Error', 'Failed to load PDF file.'); } finally { hideLoader(); } } // Process function async function processRemoveAnnotations() { if (!pageState.pdfDoc) { showAlert('Error', 'Please upload a PDF file first.'); return; } showLoader('Removing annotations...'); try { const pages = pageState.pdfDoc.getPages(); // Remove all annotations from all pages for (let i = 0; i < pages.length; i++) { const page = pages[i]; const annotRefs = page.node.Annots()?.asArray() || []; if (annotRefs.length > 0) { page.node.delete(PDFName.of('Annots')); } } const newPdfBytes = await pageState.pdfDoc.save(); downloadFile(new Blob([new Uint8Array(newPdfBytes)], { type: 'application/pdf' }), 'annotations-removed.pdf'); showAlert('Success', 'Annotations removed successfully!', 'success', () => { resetState(); }); } catch (e) { console.error(e); showAlert('Error', 'Could not remove annotations.'); } finally { hideLoader(); } } // Initialize document.addEventListener('DOMContentLoaded', () => { const fileInput = document.getElementById('file-input') as HTMLInputElement; const dropZone = document.getElementById('drop-zone'); const processBtn = document.getElementById('process-btn'); const backBtn = document.getElementById('back-to-tools'); fileInput?.addEventListener('change', (e) => { const file = (e.target as HTMLInputElement).files?.[0]; if (file) handleFileUpload(file); }); dropZone?.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('border-indigo-500'); }); dropZone?.addEventListener('dragleave', () => { dropZone.classList.remove('border-indigo-500'); }); dropZone?.addEventListener('drop', (e) => { e.preventDefault(); dropZone.classList.remove('border-indigo-500'); const file = e.dataTransfer?.files[0]; if (file) handleFileUpload(file); }); processBtn?.addEventListener('click', processRemoveAnnotations); backBtn?.addEventListener('click', () => { window.location.href = '../../index.html'; }); });