Files
audiobook-maker-pro-v4/static/js/pdf-handler.js
Ashim Kumar 8e02b9ad09 first commit
2026-02-20 13:53:36 +06:00

229 lines
7.2 KiB
JavaScript

/**
* Document Handler Module (PDF, DOCX, DOC)
* UPDATED: Updates workflow progress after document load
*/
function initPdfHandler() {
const uploadZone = document.getElementById('uploadZone');
const docInput = document.getElementById('docInput');
if (!uploadZone || !docInput) return;
uploadZone.addEventListener('click', (e) => {
if (e.target.closest('button')) return;
docInput.click();
});
docInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
handleDocumentFile(file);
}
});
uploadZone.addEventListener('dragover', (e) => {
e.preventDefault();
uploadZone.classList.add('drag-over');
});
uploadZone.addEventListener('dragleave', () => {
uploadZone.classList.remove('drag-over');
});
uploadZone.addEventListener('drop', (e) => {
e.preventDefault();
uploadZone.classList.remove('drag-over');
const files = e.dataTransfer.files;
if (files.length > 0) {
const file = files[0];
const name = file.name.toLowerCase();
if (name.endsWith('.pdf') || name.endsWith('.docx') || name.endsWith('.doc')) {
handleDocumentFile(file);
} else {
alert('Please drop a valid PDF, DOCX, or DOC file.');
}
}
});
console.log('📄 Document handler initialized (PDF, DOCX, DOC)');
}
function handleDocumentFile(file) {
const name = file.name.toLowerCase();
if (name.endsWith('.pdf')) {
handlePdfFile(file);
} else if (name.endsWith('.docx') || name.endsWith('.doc')) {
handleWordFile(file);
} else {
alert('Unsupported file type. Please upload a PDF, DOCX, or DOC file.');
}
}
async function handlePdfFile(file) {
if (!file.name.toLowerCase().endsWith('.pdf')) {
alert('Please select a valid PDF file.');
return;
}
showLoader('Processing PDF...', `Extracting content from ${file.name}`);
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('/api/upload-pdf', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.error) {
throw new Error(data.error);
}
console.log(`✅ PDF processed: ${data.page_count} pages, ${data.blocks.length} blocks`);
const projectName = file.name.replace('.pdf', '');
document.getElementById('projectName').value = projectName;
currentProject.name = projectName;
renderDocumentBlocks(data.blocks);
document.getElementById('uploadSection').style.display = 'none';
document.getElementById('editorSection').style.display = 'block';
hideLoader();
showNotification(`PDF processed: ${data.blocks.length} blocks extracted`, 'success');
updateWorkflowProgress('edit');
} catch (error) {
hideLoader();
console.error('PDF processing error:', error);
alert('Failed to process PDF: ' + error.message);
}
}
async function handleWordFile(file) {
const name = file.name.toLowerCase();
if (!name.endsWith('.docx') && !name.endsWith('.doc')) {
alert('Please select a valid DOCX or DOC file.');
return;
}
const fileType = name.endsWith('.docx') ? 'DOCX' : 'DOC';
showLoader(`Processing ${fileType}...`, `Extracting content from ${file.name}`);
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('/api/upload-docx', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.error) {
throw new Error(data.error);
}
console.log(`${fileType} processed: ${data.blocks.length} blocks`);
const projectName = file.name.replace(/\.(docx|doc)$/i, '');
document.getElementById('projectName').value = projectName;
currentProject.name = projectName;
renderDocumentBlocks(data.blocks);
document.getElementById('uploadSection').style.display = 'none';
document.getElementById('editorSection').style.display = 'block';
hideLoader();
showNotification(`${fileType} processed: ${data.blocks.length} blocks extracted`, 'success');
updateWorkflowProgress('edit');
} catch (error) {
hideLoader();
console.error(`${fileType} processing error:`, error);
alert(`Failed to process ${fileType}: ` + error.message);
}
}
function renderDocumentBlocks(blocks) {
const editor = document.getElementById('markdownEditor');
editor.innerHTML = '';
editorBlocks = [];
const emptyMessage = document.getElementById('emptyEditorMessage');
if (emptyMessage) {
emptyMessage.style.display = 'none';
}
addChapterMarker(1);
for (const block of blocks) {
let type = 'paragraph';
let content = block.content || '';
if (block.type === 'image') {
type = 'image';
} else if (block.type === 'heading1' || content.startsWith('# ')) {
type = 'heading1';
} else if (block.type === 'heading2' || content.startsWith('## ')) {
type = 'heading2';
} else if (block.type === 'heading3' || content.startsWith('### ')) {
type = 'heading3';
} else if (block.type === 'list_item' || content.startsWith('- ')) {
type = 'bulletList';
} else if (block.type === 'quote' || content.startsWith('> ')) {
type = 'quote';
} else if (block.type === 'table') {
type = 'table';
}
let images = [];
if (block.type === 'image' && block.data) {
images = [{
data: block.data,
format: block.format || 'png',
alt_text: 'Document Image',
position: 'before'
}];
content = `![Document Image](embedded-image.${block.format || 'png'})`;
}
const lastChild = editor.lastElementChild;
const blockId = addBlock(type, content, lastChild, images);
if (block.type === 'image' && block.data) {
const blockEl = document.getElementById(blockId);
if (blockEl) {
const contentDiv = blockEl.querySelector('.md-block-content');
if (contentDiv) {
contentDiv.innerHTML = `
<div class="image-block">
<img src="data:image/${block.format || 'png'};base64,${block.data}" alt="Document Image">
</div>
`;
}
}
}
const blockEl = document.getElementById(blockId);
if (blockEl) {
ensureNewBlockLineAfter(blockEl);
}
}
repairAllNewBlockLines();
}
function renderPdfBlocks(blocks) {
renderDocumentBlocks(blocks);
}