diff --git a/src/core/editor/pdf_editor.js b/src/core/editor/pdf_editor.js index 2f9d003e394c0..cf1862d9dc83d 100644 --- a/src/core/editor/pdf_editor.js +++ b/src/core/editor/pdf_editor.js @@ -470,6 +470,8 @@ class PDFEditor { * included ranges (inclusive) or indices. * @property {Array|number>} [excludePages] * excluded ranges (inclusive) or indices. + * @property {Array} [pageIndices] + * position of the pages in the final document. */ /** @@ -482,10 +484,18 @@ class PDFEditor { let newIndex = 0; this.hasSingleFile = pageInfos.length === 1; const allDocumentData = []; - for (const { document, includePages, excludePages } of pageInfos) { + for (const { + document, + includePages, + excludePages, + pageIndices, + } of pageInfos) { if (!document) { continue; } + if (pageIndices) { + newIndex = -1; + } const documentData = new DocumentData(document); allDocumentData.push(documentData); promises.push(this.#collectDocumentData(documentData)); @@ -504,6 +514,7 @@ class PDFEditor { (deletedIndices ||= new Set()).add(page); } } + let pageIndex = 0; for (let i = 0, ii = document.numPages; i < ii; i++) { if (deletedIndices?.has(i)) { continue; @@ -539,7 +550,23 @@ class PDFEditor { if (!takePage) { continue; } - const newPageIndex = newIndex++; + let newPageIndex; + if (pageIndices) { + newPageIndex = pageIndices[pageIndex++]; + } + if (newPageIndex === undefined) { + if (newIndex !== -1) { + newPageIndex = newIndex++; + } else { + for ( + newPageIndex = 0; + this.oldPages[newPageIndex] === undefined; + newPageIndex++ + ) { + /* empty */ + } + } + } promises.push( document.getPage(i).then(page => { this.oldPages[newPageIndex] = new PageData(page, documentData); diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 50673ad4b57c4..c3f6a7d2d5c25 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -5968,5 +5968,43 @@ small scripts as well as for`); await loadingTask.destroy(); }); }); + + describe("Extract pages and reorganize them", function () { + it("extract page and check destinations", async function () { + let loadingTask = getDocument( + buildGetDocumentParams("tracemonkey.pdf") + ); + let pdfDoc = await loadingTask.promise; + const data = await pdfDoc.extractPages([ + { document: null, includePages: [1, 3, 5], pageIndices: [1, 2, 0] }, + ]); + await loadingTask.destroy(); + loadingTask = getDocument(data); + pdfDoc = await loadingTask.promise; + + expect(pdfDoc.numPages).toEqual(3); + + // Page 6 in the original document. + const firstPage = await pdfDoc.getPage(1); + let { items: textItems } = await firstPage.getTextContent(); + expect( + mergeText(textItems).includes("4. Nested Trace Tree Formation") + ).toBeTrue(); + + // Page 2 in the original document. + const secondPage = await pdfDoc.getPage(2); + ({ items: textItems } = await secondPage.getTextContent()); + expect( + mergeText(textItems).includes("2. Overview: Example Tracing Run") + ).toBeTrue(); + + // Page 4 in the original document. + const thirdPage = await pdfDoc.getPage(3); + ({ items: textItems } = await thirdPage.getTextContent()); + expect(mergeText(textItems).includes("3. Trace Trees")).toBeTrue(); + + await loadingTask.destroy(); + }); + }); }); });