import { PDFDocument, degrees } from 'pdf-lib'; import type { PdfFile, SplitResult, Range } from './pdfTypes'; function createId() { return Math.random().toString(36).slice(2); } export async function loadPdfFromFile(file: File): Promise { const arrayBuffer = await file.arrayBuffer(); const doc = await PDFDocument.load(arrayBuffer); return { id: createId(), name: file.name, doc, pageCount: doc.getPageCount(), arrayBuffer, }; } export async function splitIntoSinglePages( pdf: PdfFile ): Promise { const { doc, name } = pdf; const title = doc.getTitle(); const author = doc.getAuthor(); const subject = doc.getSubject(); const keywords = doc.getKeywords(); const producer = doc.getProducer(); const creator = doc.getCreator(); const creationDate = doc.getCreationDate(); const modificationDate = doc.getModificationDate(); const results: SplitResult[] = []; for (let i = 0; i < doc.getPageCount(); i++) { const newDoc = await PDFDocument.create(); const [copiedPage] = await newDoc.copyPages(doc, [i]); newDoc.addPage(copiedPage); if (title) newDoc.setTitle(title); if (author) newDoc.setAuthor(author); if (subject) newDoc.setSubject(subject); if (keywords) newDoc.setKeywords(keywords); if (producer) newDoc.setProducer(producer); if (creator) newDoc.setCreator(creator); if (creationDate) newDoc.setCreationDate(creationDate); if (modificationDate) newDoc.setModificationDate(modificationDate); const bytes = await newDoc.save(); const blob = new Blob([bytes], { type: 'application/pdf' }); const base = name.replace(/\.pdf$/i, ''); const filename = `${base}_page_${String(i + 1).padStart(3, '0')}.pdf`; results.push({ pageIndex: i, blob, filename, }); } return results; } export async function extractRange( pdf: PdfFile, range: Range ): Promise { const { doc } = pdf; const pageCount = doc.getPageCount(); const fromIndex = Math.max(0, range.from - 1); const toIndex = Math.min(pageCount - 1, range.to - 1); if (fromIndex > toIndex) { throw new Error('Invalid range: from > to'); } const newDoc = await PDFDocument.create(); const indices: number[] = []; for (let i = fromIndex; i <= toIndex; i++) indices.push(i); const copiedPages = await newDoc.copyPages(doc, indices); copiedPages.forEach((p) => newDoc.addPage(p)); const bytes = await newDoc.save(); return new Blob([bytes], { type: 'application/pdf' }); } export async function mergePdfs(pdfs: PdfFile[]): Promise { const newDoc = await PDFDocument.create(); for (const pdf of pdfs) { const pageCount = pdf.doc.getPageCount(); const indices = Array.from({ length: pageCount }, (_, i) => i); const copiedPages = await newDoc.copyPages(pdf.doc, indices); copiedPages.forEach((p) => newDoc.addPage(p)); } const bytes = await newDoc.save(); return new Blob([bytes], { type: 'application/pdf' }); } export async function exportReordered( pdf: PdfFile, order: number[], rotations?: Record ): Promise { const { doc } = pdf; const pageCount = doc.getPageCount(); if (order.length === 0) { throw new Error('Order must contain at least one page'); } if (order.some((i) => i < 0 || i >= pageCount)) { throw new Error('Order contains invalid page indices'); } const newDoc = await PDFDocument.create(); const indices = [...order]; const copiedPages = await newDoc.copyPages(doc, indices); copiedPages.forEach((page, idx) => { const originalIndex = indices[idx]; const angle = rotations?.[originalIndex]; if (typeof angle === 'number' && angle % 360 !== 0) { page.setRotation(degrees(angle)); } newDoc.addPage(page); }); const bytes = await newDoc.save(); return new Blob([bytes], { type: 'application/pdf' }); }