Drop PDF files here
or click to browse
Maximum 20MB per file • Up to 5 files
`;
}
generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
escapeXML(text) {
return text
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
readFileAsArrayBuffer(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(new Error('Failed to read file'));
reader.readAsArrayBuffer(file);
});
}
handleError(fileObj, message) {
const progressBar = document.getElementById(`progress-${fileObj.id}`);
const downloadBtn = document.getElementById(`download-${fileObj.id}`);
if (progressBar) progressBar.style.width = '0%';
if (downloadBtn) {
downloadBtn.textContent = 'Failed';
downloadBtn.disabled = true;
}
this.showStatus(`✗ ${fileObj.file.name}: ${message}`, 'error');
}
downloadFile(fileObj) {
if (!fileObj.converted || !fileObj.downloadUrl) return;
const link = document.createElement('a');
link.href = fileObj.downloadUrl;
link.download = fileObj.fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
downloadAll() {
const convertedFiles = this.files.filter(f => f.converted);
if (convertedFiles.length === 0) {
this.showStatus('No converted files to download', 'error');
return;
}
this.showStatus(`Downloading ${convertedFiles.length} files...`, 'success');
convertedFiles.forEach((fileObj, index) => {
setTimeout(() => {
this.downloadFile(fileObj);
}, index * 500);
});
}
removeFile(fileId) {
const fileObj = this.files.find(f => f.id === fileId);
if (fileObj && fileObj.downloadUrl) {
URL.revokeObjectURL(fileObj.downloadUrl);
}
this.files = this.files.filter(f => f.id !== fileId);
const element = document.getElementById(`file-${fileId}`);
if (element) element.remove();
if (this.files.length === 0) {
document.getElementById('processingArea').style.display = 'none';
}
}
clearAll() {
this.files.forEach(fileObj => {
if (fileObj.downloadUrl) {
URL.revokeObjectURL(fileObj.downloadUrl);
}
});
this.files = [];
document.getElementById('fileList').innerHTML = '';
document.getElementById('processingArea').style.display = 'none';
this.hideStatus();
}
showProcessingArea() {
document.getElementById('processingArea').style.display = 'block';
}
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];
}
showStatus(message, type) {
const statusEl = document.getElementById('statusMessage');
statusEl.textContent = message;
statusEl.className = `status-message status-${type}`;
statusEl.style.display = 'block';
if (type === 'success') {
setTimeout(() => this.hideStatus(), 3000);
} else {
setTimeout(() => this.hideStatus(), 5000);
}
}
hideStatus() {
const statusEl = document.getElementById('statusMessage');
if (statusEl) statusEl.style.display = 'none';
}
splitIntoSections(chapter, totalPages) {
const sections = [];
const paragraphs = chapter.content.split('
').filter(p => p.trim());
const sectionsCount = Math.min(Math.ceil(totalPages / 5), 8);
const parasPerSection = Math.ceil(paragraphs.length / sectionsCount);
for (let i = 0; i < sectionsCount; i++) {
const startIdx = i * parasPerSection;
const endIdx = Math.min(startIdx + parasPerSection, paragraphs.length);
const sectionParas = paragraphs.slice(startIdx, endIdx);
if (sectionParas.length > 0) {
sections.push({
title: `Section ${i + 1}`,
content: '
' + sectionParas.join('
'),
pageStart: Math.floor((startIdx / paragraphs.length) * totalPages) + 1
});
}
}
return sections.length > 0 ? sections : [chapter];
}
}
// Initialize the converter
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
window.epubConverter = new PDFToEPUBConverter();
}, 200);
});window.addEventListener('load', () => {
if (!window.epubConverter) {
setTimeout(() => {
window.epubConverter = new PDFToEPUBConverter();
}, 100);
}
});