feat:Setup Prettier for code formatting

This commit is contained in:
NanditaPatil-dotcom
2025-10-17 11:37:32 +05:30
parent 87c191213c
commit f1d830d81d
96 changed files with 9420 additions and 7154 deletions

View File

@@ -1,5 +1,12 @@
import { state } from '../state.js';
import { showLoader, hideLoader, showAlert, renderPageThumbnails, renderFileDisplay, switchView } from '../ui.js';
import {
showLoader,
hideLoader,
showAlert,
renderPageThumbnails,
renderFileDisplay,
switchView,
} from '../ui.js';
import { readFileAsArrayBuffer } from '../utils/helpers.js';
import { setupCanvasEditor } from '../canvasEditor.js';
import { toolLogic } from '../logic/index.js';
@@ -7,352 +14,426 @@ import { renderDuplicateOrganizeThumbnails } from '../logic/duplicate-organize.j
import { PDFDocument as PDFLibDocument } from 'pdf-lib';
import { icons, createIcons } from 'lucide';
import Sortable from 'sortablejs';
import { multiFileTools, simpleTools, singlePdfLoadTools } from '../config/pdf-tools.js';
import {
multiFileTools,
simpleTools,
singlePdfLoadTools,
} from '../config/pdf-tools.js';
import * as pdfjsLib from 'pdfjs-dist';
async function handleSinglePdfUpload(toolId, file) {
showLoader('Loading PDF...');
try {
const pdfBytes = await readFileAsArrayBuffer(file);
state.pdfDoc = await PDFLibDocument.load(pdfBytes as ArrayBuffer, {
ignoreEncryption: true
});
hideLoader();
showLoader('Loading PDF...');
try {
const pdfBytes = await readFileAsArrayBuffer(file);
state.pdfDoc = await PDFLibDocument.load(pdfBytes as ArrayBuffer, {
ignoreEncryption: true,
});
hideLoader();
if (state.pdfDoc.isEncrypted && toolId !== 'decrypt' && toolId !== 'change-permissions') {
showAlert('Protected PDF', 'This PDF is password-protected. Please use the Decrypt or Change Permissions tool first.');
switchView('grid');
return;
}
const optionsDiv = document.querySelector('[id$="-options"], [id$="-preview"], [id$="-organizer"], [id$="-rotator"], [id$="-editor"]');
if (optionsDiv) optionsDiv.classList.remove('hidden');
const processBtn = document.getElementById('process-btn');
if (processBtn) {
(processBtn as HTMLButtonElement).disabled = false;
processBtn.classList.remove('hidden');
const logic = toolLogic[toolId];
if (logic) {
const func = typeof logic.process === 'function' ? logic.process : logic;
processBtn.onclick = func;
}
}
if (['split', 'delete-pages', 'add-blank-page', 'extract-pages', 'add-header-footer'].includes(toolId)) {
document.getElementById('total-pages').textContent = state.pdfDoc.getPageCount().toString();
}
if (toolId === 'organize' || toolId === 'rotate') {
await renderPageThumbnails(toolId, state.pdfDoc);
if (toolId === 'rotate') {
const rotateAllControls = document.getElementById('rotate-all-controls');
const rotateAllLeftBtn = document.getElementById('rotate-all-left-btn');
const rotateAllRightBtn = document.getElementById('rotate-all-right-btn');
rotateAllControls.classList.remove('hidden');
createIcons({ icons });
const rotateAll = (direction) => {
document.querySelectorAll('.page-rotator-item').forEach(item => {
const currentRotation = parseInt((item as HTMLElement).dataset.rotation || '0');
const newRotation = (currentRotation + (direction * 90) + 360) % 360;
(item as HTMLElement).dataset.rotation = newRotation.toString();
const thumbnail = item.querySelector('canvas, img');
if (thumbnail) {
(thumbnail as HTMLElement).style.transform = `rotate(${newRotation}deg)`;
}
});
};
rotateAllLeftBtn.onclick = () => rotateAll(-1);
rotateAllRightBtn.onclick = () => rotateAll(1);
}
}
if (toolId === 'duplicate-organize') {
await renderDuplicateOrganizeThumbnails();
}
if (['crop', 'redact'].includes(toolId)) {
await setupCanvasEditor(toolId);
}
if (toolId === 'view-metadata') {
const resultsDiv = document.getElementById('metadata-results');
showLoader('Analyzing full PDF metadata...');
try {
const pdfBytes = await readFileAsArrayBuffer(state.files[0]);
const pdfjsDoc = await pdfjsLib.getDocument({ data: pdfBytes as ArrayBuffer }).promise;
const [metadata, fieldObjects] = await Promise.all([
pdfjsDoc.getMetadata(),
pdfjsDoc.getFieldObjects()
]);
const { info, metadata: rawXmpString } = metadata;
resultsDiv.textContent = ''; // Clear safely
const createSection = (title) => {
const wrapper = document.createElement('div');
wrapper.className = 'mb-4';
const h3 = document.createElement('h3');
h3.className = 'text-lg font-semibold text-white mb-2';
h3.textContent = title;
const ul = document.createElement('ul');
ul.className = 'space-y-3 text-sm bg-gray-900 p-4 rounded-lg border border-gray-700';
wrapper.append(h3, ul);
return { wrapper, ul };
};
const createListItem = (key, value) => {
const li = document.createElement('li');
li.className = 'flex flex-col sm:flex-row';
const strong = document.createElement('strong');
strong.className = 'w-40 flex-shrink-0 text-gray-400';
strong.textContent = key;
const div = document.createElement('div');
div.className = 'flex-grow text-white break-all';
div.textContent = value;
li.append(strong, div);
return li;
};
const parsePdfDate = (pdfDate) => {
if (!pdfDate || typeof pdfDate !== 'string' || !pdfDate.startsWith('D:')) return pdfDate;
try {
const year = pdfDate.substring(2, 6);
const month = pdfDate.substring(6, 8);
const day = pdfDate.substring(8, 10);
const hour = pdfDate.substring(10, 12);
const minute = pdfDate.substring(12, 14);
const second = pdfDate.substring(14, 16);
return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}Z`).toLocaleString();
} catch { return pdfDate; }
};
const infoSection = createSection('Info Dictionary');
if (info && Object.keys(info).length > 0) {
for (const key in info) {
let value = info[key] || '- Not Set -';
if ((key === 'CreationDate' || key === 'ModDate') && typeof value === 'string') {
value = parsePdfDate(value);
}
infoSection.ul.appendChild(createListItem(key, String(value)));
}
} else {
infoSection.ul.innerHTML = `<li><span class="text-gray-500 italic">- No Info Dictionary data found -</span></li>`;
}
resultsDiv.appendChild(infoSection.wrapper);
const fieldsSection = createSection('Interactive Form Fields');
if (fieldObjects && Object.keys(fieldObjects).length > 0) {
for (const fieldName in fieldObjects) {
const field = fieldObjects[fieldName][0];
const value = (field as any).fieldValue || '- Not Set -';
fieldsSection.ul.appendChild(createListItem(fieldName, String(value)));
}
} else {
fieldsSection.ul.innerHTML = `<li><span class="text-gray-500 italic">- No interactive form fields found -</span></li>`;
}
resultsDiv.appendChild(fieldsSection.wrapper);
const xmpSection = createSection('XMP Metadata (Raw XML)');
const xmpContainer = document.createElement('div');
xmpContainer.className = 'bg-gray-900 p-4 rounded-lg border border-gray-700';
if (rawXmpString) {
const pre = document.createElement('pre');
pre.className = 'text-xs text-gray-300 whitespace-pre-wrap break-all';
pre.textContent = String(rawXmpString);
xmpContainer.appendChild(pre);
} else {
xmpContainer.innerHTML = `<p class="text-gray-500 italic">- No XMP metadata found -</p>`;
}
xmpSection.wrapper.appendChild(xmpContainer);
resultsDiv.appendChild(xmpSection.wrapper);
resultsDiv.classList.remove('hidden');
} catch (e) {
console.error("Failed to view metadata or fields:", e);
showAlert('Error', 'Could not fully analyze the PDF. It may be corrupted or have an unusual structure.');
} finally {
hideLoader();
}
}
if (toolId === 'edit-metadata') {
const form = document.getElementById('metadata-form');
const container = document.getElementById('custom-metadata-container');
const addBtn = document.getElementById('add-custom-meta-btn');
const formatDateForInput = (date) => {
if (!date) return '';
const pad = (num) => num.toString().padStart(2, '0');
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
};
(document.getElementById('meta-title') as HTMLInputElement).value = state.pdfDoc.getTitle() || '';
(document.getElementById('meta-author') as HTMLInputElement).value = state.pdfDoc.getAuthor() || '';
(document.getElementById('meta-subject') as HTMLInputElement).value = state.pdfDoc.getSubject() || '';
(document.getElementById('meta-keywords') as HTMLInputElement).value = state.pdfDoc.getKeywords() || '';
(document.getElementById('meta-creator') as HTMLInputElement).value = state.pdfDoc.getCreator() || '';
(document.getElementById('meta-producer') as HTMLInputElement).value = state.pdfDoc.getProducer() || '';
(document.getElementById('meta-creation-date') as HTMLInputElement).value = formatDateForInput(state.pdfDoc.getCreationDate());
(document.getElementById('meta-mod-date') as HTMLInputElement).value = formatDateForInput(state.pdfDoc.getModificationDate());
addBtn.onclick = () => {
const fieldWrapper = document.createElement('div');
fieldWrapper.className = 'flex items-center gap-2 custom-field-wrapper';
const keyInput = document.createElement('input');
keyInput.type = 'text';
keyInput.placeholder = 'Key (e.g., Department)';
keyInput.className = 'custom-meta-key w-1/3 bg-gray-800 border border-gray-600 text-white rounded-lg p-2';
const valueInput = document.createElement('input');
valueInput.type = 'text';
valueInput.placeholder = 'Value (e.g., Marketing)';
valueInput.className = 'custom-meta-value flex-grow bg-gray-800 border border-gray-600 text-white rounded-lg p-2';
const removeBtn = document.createElement('button');
removeBtn.type = 'button';
removeBtn.className = 'btn p-2 text-red-500 hover:bg-gray-700 rounded-full';
removeBtn.innerHTML = '<i data-lucide="trash-2"></i>';
removeBtn.addEventListener('click', () => fieldWrapper.remove());
fieldWrapper.append(keyInput, valueInput, removeBtn);
container.appendChild(fieldWrapper);
createIcons({ icons });
};
form.classList.remove('hidden');
createIcons({ icons });
}
if (toolId === 'cropper') {
document.getElementById('cropper-ui-container').classList.remove('hidden');
}
if (toolId === 'page-dimensions') {
toolLogic['page-dimensions']();
}
if (toolLogic[toolId] && typeof toolLogic[toolId].setup === 'function') {
toolLogic[toolId].setup();
}
} catch (e) {
hideLoader();
showAlert('Error', 'Could not load PDF. The file may be invalid, corrupted, or password-protected.');
console.error(e);
if (
state.pdfDoc.isEncrypted &&
toolId !== 'decrypt' &&
toolId !== 'change-permissions'
) {
showAlert(
'Protected PDF',
'This PDF is password-protected. Please use the Decrypt or Change Permissions tool first.'
);
switchView('grid');
return;
}
const optionsDiv = document.querySelector(
'[id$="-options"], [id$="-preview"], [id$="-organizer"], [id$="-rotator"], [id$="-editor"]'
);
if (optionsDiv) optionsDiv.classList.remove('hidden');
const processBtn = document.getElementById('process-btn');
if (processBtn) {
(processBtn as HTMLButtonElement).disabled = false;
processBtn.classList.remove('hidden');
const logic = toolLogic[toolId];
if (logic) {
const func =
typeof logic.process === 'function' ? logic.process : logic;
processBtn.onclick = func;
}
}
if (
[
'split',
'delete-pages',
'add-blank-page',
'extract-pages',
'add-header-footer',
].includes(toolId)
) {
document.getElementById('total-pages').textContent = state.pdfDoc
.getPageCount()
.toString();
}
if (toolId === 'organize' || toolId === 'rotate') {
await renderPageThumbnails(toolId, state.pdfDoc);
if (toolId === 'rotate') {
const rotateAllControls = document.getElementById(
'rotate-all-controls'
);
const rotateAllLeftBtn = document.getElementById('rotate-all-left-btn');
const rotateAllRightBtn = document.getElementById(
'rotate-all-right-btn'
);
rotateAllControls.classList.remove('hidden');
createIcons({ icons });
const rotateAll = (direction) => {
document.querySelectorAll('.page-rotator-item').forEach((item) => {
const currentRotation = parseInt(
(item as HTMLElement).dataset.rotation || '0'
);
const newRotation = (currentRotation + direction * 90 + 360) % 360;
(item as HTMLElement).dataset.rotation = newRotation.toString();
const thumbnail = item.querySelector('canvas, img');
if (thumbnail) {
(thumbnail as HTMLElement).style.transform =
`rotate(${newRotation}deg)`;
}
});
};
rotateAllLeftBtn.onclick = () => rotateAll(-1);
rotateAllRightBtn.onclick = () => rotateAll(1);
}
}
if (toolId === 'duplicate-organize') {
await renderDuplicateOrganizeThumbnails();
}
if (['crop', 'redact'].includes(toolId)) {
await setupCanvasEditor(toolId);
}
if (toolId === 'view-metadata') {
const resultsDiv = document.getElementById('metadata-results');
showLoader('Analyzing full PDF metadata...');
try {
const pdfBytes = await readFileAsArrayBuffer(state.files[0]);
const pdfjsDoc = await pdfjsLib.getDocument({
data: pdfBytes as ArrayBuffer,
}).promise;
const [metadata, fieldObjects] = await Promise.all([
pdfjsDoc.getMetadata(),
pdfjsDoc.getFieldObjects(),
]);
const { info, metadata: rawXmpString } = metadata;
resultsDiv.textContent = ''; // Clear safely
const createSection = (title) => {
const wrapper = document.createElement('div');
wrapper.className = 'mb-4';
const h3 = document.createElement('h3');
h3.className = 'text-lg font-semibold text-white mb-2';
h3.textContent = title;
const ul = document.createElement('ul');
ul.className =
'space-y-3 text-sm bg-gray-900 p-4 rounded-lg border border-gray-700';
wrapper.append(h3, ul);
return { wrapper, ul };
};
const createListItem = (key, value) => {
const li = document.createElement('li');
li.className = 'flex flex-col sm:flex-row';
const strong = document.createElement('strong');
strong.className = 'w-40 flex-shrink-0 text-gray-400';
strong.textContent = key;
const div = document.createElement('div');
div.className = 'flex-grow text-white break-all';
div.textContent = value;
li.append(strong, div);
return li;
};
const parsePdfDate = (pdfDate) => {
if (
!pdfDate ||
typeof pdfDate !== 'string' ||
!pdfDate.startsWith('D:')
)
return pdfDate;
try {
const year = pdfDate.substring(2, 6);
const month = pdfDate.substring(6, 8);
const day = pdfDate.substring(8, 10);
const hour = pdfDate.substring(10, 12);
const minute = pdfDate.substring(12, 14);
const second = pdfDate.substring(14, 16);
return new Date(
`${year}-${month}-${day}T${hour}:${minute}:${second}Z`
).toLocaleString();
} catch {
return pdfDate;
}
};
const infoSection = createSection('Info Dictionary');
if (info && Object.keys(info).length > 0) {
for (const key in info) {
let value = info[key] || '- Not Set -';
if (
(key === 'CreationDate' || key === 'ModDate') &&
typeof value === 'string'
) {
value = parsePdfDate(value);
}
infoSection.ul.appendChild(createListItem(key, String(value)));
}
} else {
infoSection.ul.innerHTML = `<li><span class="text-gray-500 italic">- No Info Dictionary data found -</span></li>`;
}
resultsDiv.appendChild(infoSection.wrapper);
const fieldsSection = createSection('Interactive Form Fields');
if (fieldObjects && Object.keys(fieldObjects).length > 0) {
for (const fieldName in fieldObjects) {
const field = fieldObjects[fieldName][0];
const value = (field as any).fieldValue || '- Not Set -';
fieldsSection.ul.appendChild(
createListItem(fieldName, String(value))
);
}
} else {
fieldsSection.ul.innerHTML = `<li><span class="text-gray-500 italic">- No interactive form fields found -</span></li>`;
}
resultsDiv.appendChild(fieldsSection.wrapper);
const xmpSection = createSection('XMP Metadata (Raw XML)');
const xmpContainer = document.createElement('div');
xmpContainer.className =
'bg-gray-900 p-4 rounded-lg border border-gray-700';
if (rawXmpString) {
const pre = document.createElement('pre');
pre.className = 'text-xs text-gray-300 whitespace-pre-wrap break-all';
pre.textContent = String(rawXmpString);
xmpContainer.appendChild(pre);
} else {
xmpContainer.innerHTML = `<p class="text-gray-500 italic">- No XMP metadata found -</p>`;
}
xmpSection.wrapper.appendChild(xmpContainer);
resultsDiv.appendChild(xmpSection.wrapper);
resultsDiv.classList.remove('hidden');
} catch (e) {
console.error('Failed to view metadata or fields:', e);
showAlert(
'Error',
'Could not fully analyze the PDF. It may be corrupted or have an unusual structure.'
);
} finally {
hideLoader();
}
}
if (toolId === 'edit-metadata') {
const form = document.getElementById('metadata-form');
const container = document.getElementById('custom-metadata-container');
const addBtn = document.getElementById('add-custom-meta-btn');
const formatDateForInput = (date) => {
if (!date) return '';
const pad = (num) => num.toString().padStart(2, '0');
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
};
(document.getElementById('meta-title') as HTMLInputElement).value =
state.pdfDoc.getTitle() || '';
(document.getElementById('meta-author') as HTMLInputElement).value =
state.pdfDoc.getAuthor() || '';
(document.getElementById('meta-subject') as HTMLInputElement).value =
state.pdfDoc.getSubject() || '';
(document.getElementById('meta-keywords') as HTMLInputElement).value =
state.pdfDoc.getKeywords() || '';
(document.getElementById('meta-creator') as HTMLInputElement).value =
state.pdfDoc.getCreator() || '';
(document.getElementById('meta-producer') as HTMLInputElement).value =
state.pdfDoc.getProducer() || '';
(
document.getElementById('meta-creation-date') as HTMLInputElement
).value = formatDateForInput(state.pdfDoc.getCreationDate());
(document.getElementById('meta-mod-date') as HTMLInputElement).value =
formatDateForInput(state.pdfDoc.getModificationDate());
addBtn.onclick = () => {
const fieldWrapper = document.createElement('div');
fieldWrapper.className = 'flex items-center gap-2 custom-field-wrapper';
const keyInput = document.createElement('input');
keyInput.type = 'text';
keyInput.placeholder = 'Key (e.g., Department)';
keyInput.className =
'custom-meta-key w-1/3 bg-gray-800 border border-gray-600 text-white rounded-lg p-2';
const valueInput = document.createElement('input');
valueInput.type = 'text';
valueInput.placeholder = 'Value (e.g., Marketing)';
valueInput.className =
'custom-meta-value flex-grow bg-gray-800 border border-gray-600 text-white rounded-lg p-2';
const removeBtn = document.createElement('button');
removeBtn.type = 'button';
removeBtn.className =
'btn p-2 text-red-500 hover:bg-gray-700 rounded-full';
removeBtn.innerHTML = '<i data-lucide="trash-2"></i>';
removeBtn.addEventListener('click', () => fieldWrapper.remove());
fieldWrapper.append(keyInput, valueInput, removeBtn);
container.appendChild(fieldWrapper);
createIcons({ icons });
};
form.classList.remove('hidden');
createIcons({ icons });
}
if (toolId === 'cropper') {
document
.getElementById('cropper-ui-container')
.classList.remove('hidden');
}
if (toolId === 'page-dimensions') {
toolLogic['page-dimensions']();
}
if (toolLogic[toolId] && typeof toolLogic[toolId].setup === 'function') {
toolLogic[toolId].setup();
}
} catch (e) {
hideLoader();
showAlert(
'Error',
'Could not load PDF. The file may be invalid, corrupted, or password-protected.'
);
console.error(e);
}
}
function handleMultiFileUpload(toolId) {
const processBtn = document.getElementById('process-btn');
if (processBtn) {
(processBtn as HTMLButtonElement).disabled = false;
const logic = toolLogic[toolId];
if (logic) {
const func = typeof logic.process === 'function' ? logic.process : logic;
processBtn.onclick = func;
}
const processBtn = document.getElementById('process-btn');
if (processBtn) {
(processBtn as HTMLButtonElement).disabled = false;
const logic = toolLogic[toolId];
if (logic) {
const func = typeof logic.process === 'function' ? logic.process : logic;
processBtn.onclick = func;
}
}
if (toolId === 'merge') {
toolLogic.merge.setup();
} else if (toolId === 'alternate-merge') {
toolLogic['alternate-merge'].setup();
} else if (toolId === 'image-to-pdf') {
const imageList = document.getElementById('image-list');
imageList.textContent = ''; // Clear safely
if (toolId === 'merge') {
toolLogic.merge.setup();
} else if (toolId === 'alternate-merge') {
toolLogic['alternate-merge'].setup();
} else if (toolId === 'image-to-pdf') {
const imageList = document.getElementById('image-list');
imageList.textContent = ''; // Clear safely
state.files.forEach(file => {
const url = URL.createObjectURL(file);
const li = document.createElement('li');
li.className = "relative group cursor-move";
li.dataset.fileName = file.name;
state.files.forEach((file) => {
const url = URL.createObjectURL(file);
const li = document.createElement('li');
li.className = 'relative group cursor-move';
li.dataset.fileName = file.name;
const img = document.createElement('img');
img.src = url;
img.className = "w-full h-full object-cover rounded-md border-2 border-gray-600";
const img = document.createElement('img');
img.src = url;
img.className =
'w-full h-full object-cover rounded-md border-2 border-gray-600';
const p = document.createElement('p');
p.className = "absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 text-white text-xs text-center truncate p-1";
p.textContent = file.name; // Safe insertion
const p = document.createElement('p');
p.className =
'absolute bottom-0 left-0 right-0 bg-black bg-opacity-50 text-white text-xs text-center truncate p-1';
p.textContent = file.name; // Safe insertion
li.append(img, p);
imageList.appendChild(li);
});
li.append(img, p);
imageList.appendChild(li);
});
Sortable.create(imageList);
}
Sortable.create(imageList);
}
}
export function setupFileInputHandler(toolId) {
const fileInput = document.getElementById('file-input');
const isMultiFileTool = multiFileTools.includes(toolId);
let isFirstUpload = true;
const fileInput = document.getElementById('file-input');
const isMultiFileTool = multiFileTools.includes(toolId);
let isFirstUpload = true;
const processFiles = async (newFiles) => {
if (newFiles.length === 0) return;
const processFiles = async (newFiles) => {
if (newFiles.length === 0) return;
if (!isMultiFileTool || isFirstUpload) {
state.files = newFiles;
} else {
state.files = [...state.files, ...newFiles];
}
isFirstUpload = false;
if (!isMultiFileTool || isFirstUpload) {
state.files = newFiles;
} else {
state.files = [...state.files, ...newFiles];
}
isFirstUpload = false;
const fileDisplayArea = document.getElementById('file-display-area');
if (fileDisplayArea) {
renderFileDisplay(fileDisplayArea, state.files);
}
const fileDisplayArea = document.getElementById('file-display-area');
if (fileDisplayArea) {
renderFileDisplay(fileDisplayArea, state.files);
}
const fileControls = document.getElementById('file-controls');
if (fileControls) {
fileControls.classList.remove('hidden');
createIcons({ icons });
}
const fileControls = document.getElementById('file-controls');
if (fileControls) {
fileControls.classList.remove('hidden');
createIcons({ icons });
}
if (isMultiFileTool) {
handleMultiFileUpload(toolId);
} else if (singlePdfLoadTools.includes(toolId)) {
await handleSinglePdfUpload(toolId, state.files[0]);
} else if (simpleTools.includes(toolId)) {
const optionsDivId = toolId === 'change-permissions' ? 'permissions-options' : `${toolId}-options`;
const optionsDiv = document.getElementById(optionsDivId);
if (optionsDiv) optionsDiv.classList.remove('hidden');
const processBtn = document.getElementById('process-btn');
if (processBtn) {
(processBtn as HTMLButtonElement).disabled = false;
processBtn.onclick = () => {
const logic = toolLogic[toolId];
if (logic) {
const func = typeof logic.process === 'function' ? logic.process : logic;
func();
}
};
}
} else if (toolId === 'edit') {
const file = state.files[0];
if (!file) return;
if (isMultiFileTool) {
handleMultiFileUpload(toolId);
} else if (singlePdfLoadTools.includes(toolId)) {
await handleSinglePdfUpload(toolId, state.files[0]);
} else if (simpleTools.includes(toolId)) {
const optionsDivId =
toolId === 'change-permissions'
? 'permissions-options'
: `${toolId}-options`;
const optionsDiv = document.getElementById(optionsDivId);
if (optionsDiv) optionsDiv.classList.remove('hidden');
const processBtn = document.getElementById('process-btn');
if (processBtn) {
(processBtn as HTMLButtonElement).disabled = false;
processBtn.onclick = () => {
const logic = toolLogic[toolId];
if (logic) {
const func =
typeof logic.process === 'function' ? logic.process : logic;
func();
}
};
}
} else if (toolId === 'edit') {
const file = state.files[0];
if (!file) return;
const pdfWrapper = document.getElementById('embed-pdf-wrapper');
const pdfContainer = document.getElementById('embed-pdf-container');
const pdfWrapper = document.getElementById('embed-pdf-wrapper');
const pdfContainer = document.getElementById('embed-pdf-container');
pdfContainer.textContent = ''; // Clear safely
pdfContainer.textContent = ''; // Clear safely
if (state.currentPdfUrl) {
URL.revokeObjectURL(state.currentPdfUrl);
}
pdfWrapper.classList.remove('hidden');
const fileURL = URL.createObjectURL(file);
state.currentPdfUrl = fileURL;
if (state.currentPdfUrl) {
URL.revokeObjectURL(state.currentPdfUrl);
}
pdfWrapper.classList.remove('hidden');
const fileURL = URL.createObjectURL(file);
state.currentPdfUrl = fileURL;
const script = document.createElement('script');
script.type = 'module';
script.textContent = `
const script = document.createElement('script');
script.type = 'module';
script.textContent = `
import EmbedPDF from 'https://snippet.embedpdf.com/embedpdf.js';
EmbedPDF.init({
type: 'container',
@@ -361,55 +442,62 @@ export function setupFileInputHandler(toolId) {
theme: 'dark',
});
`;
document.head.appendChild(script);
document.head.appendChild(script);
const backBtn = document.getElementById('back-to-grid');
const urlRevoker = () => {
URL.revokeObjectURL(fileURL);
state.currentPdfUrl = null;
backBtn.removeEventListener('click', urlRevoker);
};
backBtn.addEventListener('click', urlRevoker);
}
};
const backBtn = document.getElementById('back-to-grid');
const urlRevoker = () => {
URL.revokeObjectURL(fileURL);
state.currentPdfUrl = null;
backBtn.removeEventListener('click', urlRevoker);
};
backBtn.addEventListener('click', urlRevoker);
}
};
fileInput.addEventListener('change', (e) => processFiles(Array.from((e.target as HTMLInputElement).files || [])));
fileInput.addEventListener('change', (e) =>
processFiles(Array.from((e.target as HTMLInputElement).files || []))
);
const setupAddMoreButton = () => {
const addMoreBtn = document.getElementById('add-more-btn');
if (addMoreBtn) {
addMoreBtn.addEventListener('click', () => fileInput.click());
}
};
const setupAddMoreButton = () => {
const addMoreBtn = document.getElementById('add-more-btn');
if (addMoreBtn) {
addMoreBtn.addEventListener('click', () => fileInput.click());
}
};
const setupClearButton = () => {
const clearBtn = document.getElementById('clear-files-btn');
if (clearBtn) {
clearBtn.addEventListener('click', () => {
state.files = [];
isFirstUpload = true;
(fileInput as HTMLInputElement).value = '';
const setupClearButton = () => {
const clearBtn = document.getElementById('clear-files-btn');
if (clearBtn) {
clearBtn.addEventListener('click', () => {
state.files = [];
isFirstUpload = true;
(fileInput as HTMLInputElement).value = '';
const fileDisplayArea = document.getElementById('file-display-area');
if (fileDisplayArea) fileDisplayArea.textContent = '';
const fileDisplayArea = document.getElementById('file-display-area');
if (fileDisplayArea) fileDisplayArea.textContent = '';
const fileControls = document.getElementById('file-controls');
if (fileControls) fileControls.classList.add('hidden');
const fileControls = document.getElementById('file-controls');
if (fileControls) fileControls.classList.add('hidden');
const toolSpecificUI = ['file-list', 'page-merge-preview', 'image-list', 'alternate-file-list'];
toolSpecificUI.forEach(id => {
const el = document.getElementById(id);
if (el) el.textContent = '';
});
const toolSpecificUI = [
'file-list',
'page-merge-preview',
'image-list',
'alternate-file-list',
];
toolSpecificUI.forEach((id) => {
const el = document.getElementById(id);
if (el) el.textContent = '';
});
const processBtn = document.getElementById('process-btn');
if (processBtn) (processBtn as HTMLButtonElement).disabled = true;
});
}
};
const processBtn = document.getElementById('process-btn');
if (processBtn) (processBtn as HTMLButtonElement).disabled = true;
});
}
};
setTimeout(() => {
setupAddMoreButton();
setupClearButton();
}, 100);
setTimeout(() => {
setupAddMoreButton();
setupClearButton();
}, 100);
}

View File

@@ -7,35 +7,35 @@ import { createIcons, icons } from 'lucide';
const SETUP_AFTER_UPLOAD = ['sign-pdf'];
export function setupToolInterface(toolId: any) {
window.scrollTo({
top: 0,
left: 0,
behavior: 'instant' as ScrollBehavior
});
state.activeTool = toolId;
dom.toolContent.innerHTML = toolTemplates[toolId]();
createIcons({icons});
switchView('tool');
window.scrollTo({
top: 0,
left: 0,
behavior: 'instant' as ScrollBehavior,
});
const fileInput = document.getElementById('file-input');
const processBtn = document.getElementById('process-btn');
state.activeTool = toolId;
dom.toolContent.innerHTML = toolTemplates[toolId]();
createIcons({ icons });
switchView('tool');
if (!fileInput && processBtn) {
const logic = toolLogic[toolId];
if (logic) {
const func = typeof logic.process === 'function' ? logic.process : logic;
processBtn.onclick = func;
}
const fileInput = document.getElementById('file-input');
const processBtn = document.getElementById('process-btn');
if (!fileInput && processBtn) {
const logic = toolLogic[toolId];
if (logic) {
const func = typeof logic.process === 'function' ? logic.process : logic;
processBtn.onclick = func;
}
}
if (toolLogic[toolId] && typeof toolLogic[toolId].setup === 'function') {
if (!SETUP_AFTER_UPLOAD.includes(toolId)) {
toolLogic[toolId].setup();
}
if (toolLogic[toolId] && typeof toolLogic[toolId].setup === 'function') {
if (!SETUP_AFTER_UPLOAD.includes(toolId)) {
toolLogic[toolId].setup();
}
}
if (fileInput) {
setupFileInputHandler(toolId);
}
}
if (fileInput) {
setupFileInputHandler(toolId);
}
}