UNPKG

mindee

Version:

Mindee Client Library for Node.js

129 lines (128 loc) 4.68 kB
import { PageOptionsOperation, PathInput } from "../input/index.js"; import { logger } from "../logger.js"; import path from "path"; import { loadOptionalDependency } from "../dependency/index.js"; import { MindeeInputSourceError, MindeePdfError } from "../errors/index.js"; import { ExtractedPdf } from "../pdf/extractedPdf.js"; import { createPdfFromInputSource, extractPages } from "../pdf/pdfOperation.js"; let pdfLib = null; async function getPdfLib() { if (!pdfLib) { const pdfLibImport = await loadOptionalDependency("@cantoo/pdf-lib", "Text Embedding"); pdfLib = pdfLibImport.default || pdfLibImport; } return pdfLib; } export class PdfExtractor { constructor(inputDocument) { /** * Buffer containing the PDF data. * @private */ this.sourcePdf = null; /** * Filename of the PDF. * @private */ this.filename = null; /** * Whether the extractor has been initialized. * @private */ this.initialized = false; /** * PDF library instance. * @private */ this.pdfLib = null; /** * List of extracted PDFs. * @private */ this.extractedPdfs = null; this.inputDocument = inputDocument; } async init() { this.pdfLib = await getPdfLib(); if (typeof this.inputDocument === "string") { logger.debug(`Loading from path: ${this.inputDocument}`); try { const tempPathInput = new PathInput({ inputPath: this.inputDocument }); await tempPathInput.init(); if (tempPathInput.isPdf()) { this.sourcePdf = tempPathInput.fileObject; } else { const pdfObject = await createPdfFromInputSource(tempPathInput); this.sourcePdf = Buffer.from(await pdfObject.save()); } } catch { throw new MindeeInputSourceError("Couldn't generate PDF from input."); } this.filename = path.basename(this.inputDocument); } else { logger.debug(`Loading document: ${this.inputDocument.filename}`); await this.inputDocument.init(); if (this.inputDocument.isPdf()) { this.sourcePdf = this.inputDocument.fileObject; } else { const pdfObject = await createPdfFromInputSource(this.inputDocument); const arrayBuffer = await pdfObject.save(); this.sourcePdf = Buffer.from(arrayBuffer); } this.filename = this.inputDocument.filename; } this.initialized = true; if (!this.sourcePdf) { throw new MindeePdfError("Could not load PDF source."); } } /** * Gets the number of pages in the PDF. * @returns The number of pages in the PDF. */ async getPageCount() { if (!this.initialized) { await this.init(); } const currentPdf = await this.pdfLib.PDFDocument.load(this.sourcePdf, { ignoreEncryption: true, password: "" }); return currentPdf.getPageCount(); } /** * Extracts pages from the PDF. * @param pageIndexes */ async extractSubDocuments(pageIndexes) { if (this.extractedPdfs && this.extractedPdfs.length > 0) { return this.extractedPdfs; } if (!this.initialized) { await this.init(); } this.extractedPdfs = []; for (const pageRange of pageIndexes) { logger.debug(`Extracting pages ${pageRange.join(", ")}`); if (pageRange.length === 0) { throw new MindeeInputSourceError("Empty indexes not allowed for extraction."); } const pageOptions = { pageIndexes: pageRange, operation: PageOptionsOperation.KeepOnly, onMinPages: 1, }; const splitName = path.basename(this.filename, path.extname(this.filename)); const startPage = String(pageRange[0] + 1).padStart(3, "0"); const endPage = String(pageRange[pageRange.length - 1] + 1).padStart(3, "0"); const fieldFilename = `${splitName}_page_${startPage}-${endPage}.pdf`; const page = await extractPages(this.sourcePdf, pageOptions); this.extractedPdfs.push(new ExtractedPdf(page.file, fieldFilename, pageRange)); } return this.extractedPdfs; } }