diff --git a/src/core/editor/pdf_editor.js b/src/core/editor/pdf_editor.js index 93e57aa75..66c3554b3 100644 --- a/src/core/editor/pdf_editor.js +++ b/src/core/editor/pdf_editor.js @@ -997,13 +997,6 @@ class PDFEditor { // async. this.oldPages[newPageIndex] = null; }; - // Image entries don't carry document identity, so ignore them when - // deciding whether we're operating on a single source PDF. - const docPageInfos = pageInfos.filter(info => !!info.document); - this.isSingleFile = - docPageInfos.length === 1 || - (docPageInfos.length > 0 && - docPageInfos.every(info => info.document === docPageInfos[0].document)); const allDocumentData = []; if (annotationStorage) { @@ -1099,7 +1092,11 @@ class PDFEditor { } } await Promise.all(promises); + if (this.oldPages.length === 0) { + throw new Error("extractPages: nothing to extract."); + } const copyCounts = new Map(); + const documents = new Set(); for (let i = 0, ii = this.oldPages.length; i < ii; i++) { const pageData = this.oldPages[i]; if (pageData === undefined) { @@ -1110,8 +1107,10 @@ class PDFEditor { const copyLevel = copyCounts.get(page) ?? 0; copyCounts.set(page, copyLevel + 1); pageData.copyLevel = copyLevel; + documents.add(pageData.documentData.document); } } + this.isSingleFile = documents.size === 1; promises.length = 0; this.#collectValidDestinations(allDocumentData); diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index bb2883ef9..e9f2a16af 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -7757,6 +7757,44 @@ small scripts as well as for`); await loadingTask.destroy(); }); + it("extracts only an image when all source pages are excluded", async function () { + if (isNodeJS) { + pending("Cannot create a bitmap from Node.js."); + } + let loadingTask = getDocument(buildGetDocumentParams("empty.pdf")); + let pdfDoc = await loadingTask.promise; + const bitmap = await getImageBitmap("firefox_logo.png"); + + const data = await pdfDoc.extractPages([ + { document: null, excludePages: [0] }, + { image: bitmap }, + ]); + expect(data).not.toBeNull(); + await loadingTask.destroy(); + + loadingTask = getDocument({ data }); + pdfDoc = await loadingTask.promise; + expect(pdfDoc.numPages).toEqual(1); + + const pdfPage = await pdfDoc.getPage(1); + const { fnArray } = await pdfPage.getOperatorList(); + expect(fnArray).toContain(OPS.paintImageXObject); + + await loadingTask.destroy(); + }); + + it("returns null when every source page is excluded", async function () { + const loadingTask = getDocument(buildGetDocumentParams("basicapi.pdf")); + const pdfDoc = await loadingTask.promise; + + const data = await pdfDoc.extractPages([ + { document: null, excludePages: [[0, 2]] }, + ]); + expect(data).toBeNull(); + + await loadingTask.destroy(); + }); + it("preserves EmbeddedFiles (attachments) when extracting pages", async function () { let loadingTask = getDocument(buildGetDocumentParams("attachment.pdf")); let pdfDoc = await loadingTask.promise;