mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2024-12-31 00:08:08 +01:00
Made sort and extract pages functions conform to the new design pattern. Standardised naming of a few variables
This commit is contained in:
parent
53bf6ef4bc
commit
544a080db4
@ -25,7 +25,7 @@ To create your own, you have to understand a few key features first. You can als
|
|||||||
{
|
{
|
||||||
"type": "extract",
|
"type": "extract",
|
||||||
"values": {
|
"values": {
|
||||||
"pagesToExtractArray": [0, 2]
|
"pageIndexes": [0, 2]
|
||||||
},
|
},
|
||||||
"operations": []
|
"operations": []
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ You can also nest workflows like this:
|
|||||||
{
|
{
|
||||||
"type": "extract",
|
"type": "extract",
|
||||||
"values": {
|
"values": {
|
||||||
"pagesToExtractArray": [0, 2]
|
"pageIndexes": [0, 2]
|
||||||
},
|
},
|
||||||
"operations": [
|
"operations": [
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,8 @@ export async function editMetadata(snapshot: string | Uint8Array | ArrayBuffer,
|
|||||||
return dependantEditMetadata(snapshot, metadata);
|
return dependantEditMetadata(snapshot, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function extractPages(snapshot: string | Uint8Array | ArrayBuffer, pagesToExtractArray: number[]) {
|
export async function extractPages(snapshot: string | Uint8Array | ArrayBuffer, pageIndexes: number[]) {
|
||||||
return dependantExtractPages(snapshot, pagesToExtractArray);
|
return dependantExtractPages(snapshot, pageIndexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mergePDFs(snapshots: (string | Uint8Array | ArrayBuffer)[]) {
|
export async function mergePDFs(snapshots: (string | Uint8Array | ArrayBuffer)[]) {
|
||||||
|
@ -90,7 +90,7 @@ export const extractOnly = {
|
|||||||
operations: [
|
operations: [
|
||||||
{
|
{
|
||||||
type: "extract",
|
type: "extract",
|
||||||
values: { "pagesToExtractArray": [0, 2] },
|
values: { "pageIndexes": [0, 2] },
|
||||||
operations: []
|
operations: []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -20,8 +20,8 @@ import { splitOn as dependantSplitOn } from "./functions/splitOn.js";
|
|||||||
|
|
||||||
// TODO: Dynamic loading & undloading of libraries.
|
// TODO: Dynamic loading & undloading of libraries.
|
||||||
|
|
||||||
export async function extractPages(snapshot, pagesToExtractArray) {
|
export async function extractPages(snapshot, pageIndexes) {
|
||||||
return dependantExtractPages(snapshot, pagesToExtractArray, PDFLib);
|
return dependantExtractPages(snapshot, pageIndexes, PDFLib);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function impose(snapshot, nup, format) {
|
export async function impose(snapshot, nup, format) {
|
||||||
@ -52,8 +52,8 @@ export async function editMetadata(snapshot, metadata) {
|
|||||||
return dependantEditMetadata(snapshot, metadata, PDFLib);
|
return dependantEditMetadata(snapshot, metadata, PDFLib);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sortPagesWithPreset(snapshot, operation, fancyPageSelector) {
|
export async function sortPagesWithPreset(snapshot, operation) {
|
||||||
return dependantSortPagesWithPreset(snapshot, operation, fancyPageSelector, PDFLib);
|
return dependantSortPagesWithPreset(snapshot, operation, PDFLib);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeBlankPages(snapshot, whiteThreashold) {
|
export async function removeBlankPages(snapshot, whiteThreashold) {
|
||||||
|
21
shared-operations/src/functions/common/getPagesByIndex.ts
Normal file
21
shared-operations/src/functions/common/getPagesByIndex.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
import { PdfFile, RepresentationType } from '../../wrappers/PdfFile.js';
|
||||||
|
import { PDFDocument } from 'pdf-lib';
|
||||||
|
|
||||||
|
export async function getPages(file: PdfFile, pageIndexes: number[]): Promise<PdfFile> {
|
||||||
|
const pdfLibDocument = await file.pdfLibDocument;
|
||||||
|
const subDocument = await PDFDocument.create();
|
||||||
|
|
||||||
|
// Check that array max number is not larger pdf pages number
|
||||||
|
if(Math.max(...pageIndexes) >= pdfLibDocument.getPageCount()) {
|
||||||
|
throw new Error(`The PDF document only has ${pdfLibDocument.getPageCount()} pages and you tried to extract page ${Math.max(...pageIndexes)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const copiedPages = await subDocument.copyPages(pdfLibDocument, pageIndexes);
|
||||||
|
|
||||||
|
for (let i = 0; i < copiedPages.length; i++) {
|
||||||
|
subDocument.addPage(copiedPages[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PdfFile(file.originalFilename, subDocument, RepresentationType.PDFLibDocument, file.filename);
|
||||||
|
}
|
121
shared-operations/src/functions/common/pageIndexesSorting.ts
Normal file
121
shared-operations/src/functions/common/pageIndexesSorting.ts
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns A reversed list of page indexes.
|
||||||
|
*/
|
||||||
|
function reverseSort(pages: number|number[]): number[] {
|
||||||
|
const indexes = Array.isArray(pages) ? pages : [...Array(pages).keys()];
|
||||||
|
return indexes.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts page indexes as if all fronts were scanned then all backs in reverse (1, n, 2, n-1, ...).
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns A duplex-sorted list of page indexes.
|
||||||
|
*/
|
||||||
|
function duplexSort(pages: number|number[]): number[] {
|
||||||
|
const indexes = Array.isArray(pages) ? pages : [...Array(pages).keys()];
|
||||||
|
|
||||||
|
// Translated to JS from the original Java function
|
||||||
|
const newPageOrder: number[] = [];
|
||||||
|
const half = Math.floor((indexes.length + 1) / 2); // This ensures proper behavior with odd numbers of pages
|
||||||
|
|
||||||
|
for (let i = 1; i <= half; i++) {
|
||||||
|
newPageOrder.push(indexes[i - 1]);
|
||||||
|
if (i <= indexes.length - half) {
|
||||||
|
// Avoid going out of bounds
|
||||||
|
newPageOrder.push(indexes[indexes.length - i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arranges pages for booklet printing (last, first, second, second last, ...).
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns A booklet-sorted list of page indexes.
|
||||||
|
*/
|
||||||
|
function bookletSort(totalPages: number): number[] {
|
||||||
|
const newPageOrder: number[] = [];
|
||||||
|
for (let i = 0; i < totalPages / 2; i++) {
|
||||||
|
newPageOrder.push(i);
|
||||||
|
newPageOrder.push(totalPages - i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: find out what this does
|
||||||
|
* @param pages
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function sideStitchBooklet(totalPages: number): number[] {
|
||||||
|
const newPageOrder: number[] = [];
|
||||||
|
for (let i = 0; i < (totalPages + 3) / 4; i++) {
|
||||||
|
const begin = i * 4;
|
||||||
|
newPageOrder.push(Math.min(begin + 3, totalPages - 1));
|
||||||
|
newPageOrder.push(Math.min(begin, totalPages - 1));
|
||||||
|
newPageOrder.push(Math.min(begin + 1, totalPages - 1));
|
||||||
|
newPageOrder.push(Math.min(begin + 2, totalPages - 1));
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits and arranges pages into odd and even numbered pages.
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns An odd-even split list of page indexes.
|
||||||
|
*/
|
||||||
|
function oddEvenSplit(totalPages: number): number[] {
|
||||||
|
const newPageOrder: number[] = [];
|
||||||
|
for (let i = 1; i <= totalPages; i += 2) {
|
||||||
|
newPageOrder.push(i - 1);
|
||||||
|
}
|
||||||
|
for (let i = 2; i <= totalPages; i += 2) {
|
||||||
|
newPageOrder.push(i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the first page from the list of index selections.
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns The list of page indexes, without the first page.
|
||||||
|
*/
|
||||||
|
function removeFirst(totalPages: number): number[] {
|
||||||
|
return [...Array(totalPages-1).keys()].map(i => i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the last page from the list of index selections.
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns The list of page indexes, without the last page.
|
||||||
|
*/
|
||||||
|
function removeLast(totalPages: number): number[] {
|
||||||
|
return [...Array(totalPages-1).keys()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the first and last pages from the list of index selections.
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns The list of page indexes, without the first and last pages.
|
||||||
|
*/
|
||||||
|
function removeFirstAndLast(totalPages: number): number[] {
|
||||||
|
return [...Array(totalPages-2).keys()].map(i => i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SortFunction = (totalPages: number) => number[];
|
||||||
|
type Sorts = {
|
||||||
|
[key: string]: SortFunction;
|
||||||
|
};
|
||||||
|
export const sorts: Sorts = Object.freeze({
|
||||||
|
"REVERSE_ORDER": reverseSort,
|
||||||
|
"DUPLEX_SORT": duplexSort,
|
||||||
|
"BOOKLET_SORT": bookletSort,
|
||||||
|
"SIDE_STITCH_BOOKLET_SORT": sideStitchBooklet,
|
||||||
|
"ODD_EVEN_SPLIT": oddEvenSplit,
|
||||||
|
"REMOVE_FIRST": removeFirst,
|
||||||
|
"REMOVE_LAST": removeLast,
|
||||||
|
"REMOVE_FIRST_AND_LAST": removeFirstAndLast,
|
||||||
|
});
|
84
shared-operations/src/functions/common/pageIndexesUtils.ts
Normal file
84
shared-operations/src/functions/common/pageIndexesUtils.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* @param selection An array of page indexes already selected.
|
||||||
|
* @param pages A list of page indexes, or the number of total pages in the document (which will be converted into a list of page indexes).
|
||||||
|
* @returns An inverted selection array of page indexes.
|
||||||
|
*/
|
||||||
|
function invertSelection(selection: number[], pages: number|number[]): number[] {
|
||||||
|
const indexes = Array.isArray(pages) ? pages : [...Array(pages).keys()];
|
||||||
|
const pageIndexesCopy = [...indexes];
|
||||||
|
return pageIndexesCopy.filter(x => !selection.includes(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the page selector string used in the 'PDF Page Organizer'
|
||||||
|
* @param specification
|
||||||
|
* @param totalPages
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function parsePageIndexSpecification(specification: string, totalPages: number): number[] {
|
||||||
|
// Translated to JS from the original Java function
|
||||||
|
const pageOrderArr = specification.split(",")
|
||||||
|
const newPageOrder: number[] = [];
|
||||||
|
|
||||||
|
// loop through the page order array
|
||||||
|
pageOrderArr.forEach(element => {
|
||||||
|
if (element.toLocaleLowerCase() === "all") {
|
||||||
|
for (var i = 0; i < totalPages; i++) {
|
||||||
|
newPageOrder.push(i);
|
||||||
|
}
|
||||||
|
// As all pages are already added, no need to check further
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (element.match("\\d*n\\+?-?\\d*|\\d*\\+?n")) {
|
||||||
|
// Handle page order as a function
|
||||||
|
var coefficient = 0;
|
||||||
|
var constant = 0;
|
||||||
|
var coefficientExists = false;
|
||||||
|
var constantExists = false;
|
||||||
|
|
||||||
|
if (element.includes("n")) {
|
||||||
|
var parts = element.split("n");
|
||||||
|
if (!parts[0]) {
|
||||||
|
coefficient = parseInt(parts[0]);
|
||||||
|
coefficientExists = true;
|
||||||
|
}
|
||||||
|
if (parts.length > 1 && parts[1]) {
|
||||||
|
constant = parseInt(parts[1]);
|
||||||
|
constantExists = true;
|
||||||
|
}
|
||||||
|
} else if (element.includes("+")) {
|
||||||
|
constant = parseInt(element.replace("+", ""));
|
||||||
|
constantExists = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 1; i <= totalPages; i++) {
|
||||||
|
var pageNum = coefficientExists ? coefficient * i : i;
|
||||||
|
pageNum += constantExists ? constant : 0;
|
||||||
|
|
||||||
|
if (pageNum <= totalPages && pageNum > 0) {
|
||||||
|
newPageOrder.push(pageNum - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (element.includes("-")) {
|
||||||
|
// split the range into start and end page
|
||||||
|
const range = element.split("-");
|
||||||
|
const start = parseInt(range[0]);
|
||||||
|
var end = parseInt(range[1]);
|
||||||
|
// check if the end page is greater than total pages
|
||||||
|
if (end > totalPages) {
|
||||||
|
end = totalPages;
|
||||||
|
}
|
||||||
|
// loop through the range of pages
|
||||||
|
for (var j = start; j <= end; j++) {
|
||||||
|
// print the current index
|
||||||
|
newPageOrder.push(j - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if the element is a single page
|
||||||
|
newPageOrder.push(parseInt(element) - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
20
shared-operations/src/functions/extractPages.ts
Normal file
20
shared-operations/src/functions/extractPages.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
import { PdfFile } from '../wrappers/PdfFile.js';
|
||||||
|
import { getPages } from './common/getPagesByIndex.js';
|
||||||
|
|
||||||
|
export type ExtractPagesParamsType = {
|
||||||
|
file: PdfFile;
|
||||||
|
pageIndexes: string | number[];
|
||||||
|
}
|
||||||
|
export async function extractPages(params: ExtractPagesParamsType) {
|
||||||
|
const { file, pageIndexes } = params;
|
||||||
|
const pdfLibDocument = await file.pdfLibDocument;
|
||||||
|
|
||||||
|
var indexes = pageIndexes;
|
||||||
|
|
||||||
|
if (!Array.isArray(indexes)) {
|
||||||
|
indexes = parsePageIndexSpecification(indexes, pdfLibDocument.getPageCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
return getPages(file, indexes);
|
||||||
|
}
|
18
shared-operations/src/functions/removeBlankPages.ts
Normal file
18
shared-operations/src/functions/removeBlankPages.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
import { PdfFile } from '../wrappers/PdfFile.js';
|
||||||
|
import { detectEmptyPages } from './common/detectEmptyPages.js';
|
||||||
|
import { getPages } from './common/getPagesByIndex.js';
|
||||||
|
|
||||||
|
export type RemoveBlankPagesParamsType = {
|
||||||
|
file: PdfFile;
|
||||||
|
whiteThreashold: number;
|
||||||
|
}
|
||||||
|
export async function removeBlankPages(params: RemoveBlankPagesParamsType) {
|
||||||
|
const { file, whiteThreashold } = params;
|
||||||
|
const pageCount = await file.pdfLibDocument;
|
||||||
|
|
||||||
|
const emptyPages = await detectEmptyPages(file, whiteThreashold);
|
||||||
|
console.debug("Empty Pages: ", emptyPages);
|
||||||
|
const pagesToKeep = invertSelection(emptyPages, pageCount.getPageCount())
|
||||||
|
return getPages(file, pagesToKeep);
|
||||||
|
}
|
22
shared-operations/src/functions/sortPagesWithPreset.ts
Normal file
22
shared-operations/src/functions/sortPagesWithPreset.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
import { PdfFile } from '../wrappers/PdfFile.js';
|
||||||
|
import { sorts } from './common/pageIndexesSorting.js';
|
||||||
|
import { getPages } from './common/getPagesByIndex.js';
|
||||||
|
|
||||||
|
export type SortPagesWithPresetParamsType = {
|
||||||
|
file: PdfFile;
|
||||||
|
sortPreset: string;
|
||||||
|
}
|
||||||
|
export async function sortPagesWithPreset(params: SortPagesWithPresetParamsType) {
|
||||||
|
const { file, sortPreset } = params;
|
||||||
|
const pdfLibDocument = await file.pdfLibDocument;
|
||||||
|
|
||||||
|
if (!(sortPreset in sorts)) {
|
||||||
|
throw new Error("Supplied parameters not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortFunction = sorts[sortPreset];
|
||||||
|
const pageCount = pdfLibDocument.getPageCount();
|
||||||
|
const sortIndexes = sortFunction(pageCount);
|
||||||
|
return getPages(file, sortIndexes);
|
||||||
|
}
|
@ -3,7 +3,7 @@ import jsQR from "jsqr";
|
|||||||
|
|
||||||
import { detectEmptyPages } from "./common/detectEmptyPages.js";
|
import { detectEmptyPages } from "./common/detectEmptyPages.js";
|
||||||
import { getImagesOnPage } from "./common/getImagesOnPage.js";
|
import { getImagesOnPage } from "./common/getImagesOnPage.js";
|
||||||
import { selectPages } from "./subDocumentFunctions";
|
import { getPages } from "./common/getPagesByIndex.js";
|
||||||
import { PdfFile } from '../wrappers/PdfFile.js';
|
import { PdfFile } from '../wrappers/PdfFile.js';
|
||||||
|
|
||||||
export type SplitOnParamsType = {
|
export type SplitOnParamsType = {
|
||||||
@ -52,7 +52,7 @@ export async function splitOn(params: SplitOnParamsType) {
|
|||||||
console.log(i);
|
console.log(i);
|
||||||
if(i == splitAfter) {
|
if(i == splitAfter) {
|
||||||
if(pagesArray.length > 0) {
|
if(pagesArray.length > 0) {
|
||||||
subDocuments.push(await selectPages({file, pagesToExtractArray:pagesArray}));
|
subDocuments.push(await getPages(file, pagesArray));
|
||||||
pagesArray = [];
|
pagesArray = [];
|
||||||
}
|
}
|
||||||
splitAfter = splitAtPages.shift();
|
splitAfter = splitAtPages.shift();
|
||||||
@ -63,7 +63,7 @@ export async function splitOn(params: SplitOnParamsType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pagesArray.length > 0) {
|
if(pagesArray.length > 0) {
|
||||||
subDocuments.push(await selectPages({file, pagesToExtractArray:pagesArray}));
|
subDocuments.push(await getPages(file, pagesArray));
|
||||||
}
|
}
|
||||||
pagesArray = [];
|
pagesArray = [];
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import { selectPages } from "./subDocumentFunctions";
|
import { getPages } from "./common/getPagesByIndex";
|
||||||
import { PdfFile } from '../wrappers/PdfFile';
|
import { PdfFile } from '../wrappers/PdfFile';
|
||||||
|
|
||||||
export type SplitPdfParamsType = {
|
export type SplitPdfParamsType = {
|
||||||
@ -20,13 +20,13 @@ export async function splitPDF(params: SplitPdfParamsType): Promise<PdfFile[]> {
|
|||||||
|
|
||||||
for (let i = 0; i < numberOfPages; i++) {
|
for (let i = 0; i < numberOfPages; i++) {
|
||||||
if(splitAfter && i > splitAfter && pagesArray.length > 0) {
|
if(splitAfter && i > splitAfter && pagesArray.length > 0) {
|
||||||
subDocuments.push(await selectPages({file, pagesToExtractArray:pagesArray}));
|
subDocuments.push(await getPages(file, pagesArray));
|
||||||
splitAfter = splitAfterPageArray.shift();
|
splitAfter = splitAfterPageArray.shift();
|
||||||
pagesArray = [];
|
pagesArray = [];
|
||||||
}
|
}
|
||||||
pagesArray.push(i);
|
pagesArray.push(i);
|
||||||
}
|
}
|
||||||
subDocuments.push(await selectPages({file, pagesToExtractArray:pagesArray}));
|
subDocuments.push(await getPages(file, pagesArray));
|
||||||
pagesArray = [];
|
pagesArray = [];
|
||||||
|
|
||||||
return subDocuments;
|
return subDocuments;
|
||||||
|
@ -1,255 +0,0 @@
|
|||||||
|
|
||||||
import { PDFDocument } from 'pdf-lib';
|
|
||||||
import { PdfFile, RepresentationType } from '../wrappers/PdfFile.js';
|
|
||||||
import { detectEmptyPages } from "./common/detectEmptyPages.js";
|
|
||||||
|
|
||||||
|
|
||||||
export type SortPagesWithPresetParamsType = {
|
|
||||||
file: PdfFile;
|
|
||||||
sortPreset: string;
|
|
||||||
fancyPageSelector: string;
|
|
||||||
}
|
|
||||||
export async function sortPagesWithPreset(params: SortPagesWithPresetParamsType) {
|
|
||||||
const { file, sortPreset } = params;
|
|
||||||
|
|
||||||
if (sortPreset === "CUSTOM_PAGE_ORDER") {
|
|
||||||
return rearrangePages(params); // fancyPageSelector passed down with params
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortFunction = sorts[sortPreset];
|
|
||||||
if (!sortFunction) {
|
|
||||||
throw new Error("Operation not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
const pdfLibDocument = await file.pdfLibDocument;
|
|
||||||
|
|
||||||
const pageCount = pdfLibDocument.getPageCount();
|
|
||||||
const sortIndecies = sortFunction(pageCount);
|
|
||||||
return selectPages({file: file, pagesToExtractArray: sortIndecies});
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RearrangePagesParamsType = {
|
|
||||||
file: PdfFile;
|
|
||||||
sortPreset: string;
|
|
||||||
fancyPageSelector: string;
|
|
||||||
}
|
|
||||||
export async function rearrangePages(params: RearrangePagesParamsType): Promise<PdfFile> {
|
|
||||||
const { file, fancyPageSelector } = params;
|
|
||||||
|
|
||||||
const pdfLibDocument = await file.pdfLibDocument;
|
|
||||||
|
|
||||||
const pagesToExtractArray = parseFancyPageSelector(fancyPageSelector, pdfLibDocument.getPageCount());
|
|
||||||
const newDocument = selectPages({file: file, pagesToExtractArray});
|
|
||||||
return newDocument;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SelectPagesParamsType = {
|
|
||||||
file: PdfFile;
|
|
||||||
pagesToExtractArray: number[];
|
|
||||||
}
|
|
||||||
export async function selectPages(params: SelectPagesParamsType): Promise<PdfFile> {
|
|
||||||
const { file, pagesToExtractArray } = params;
|
|
||||||
|
|
||||||
const pdfLibDocument = await file.pdfLibDocument;
|
|
||||||
|
|
||||||
const subDocument = await PDFDocument.create();
|
|
||||||
|
|
||||||
// Check that array max number is not larger pdf pages number
|
|
||||||
if(Math.max(...pagesToExtractArray) >= pdfLibDocument.getPageCount()) {
|
|
||||||
throw new Error(`The PDF document only has ${pdfLibDocument.getPageCount()} pages and you tried to extract page ${Math.max(...pagesToExtractArray)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const copiedPages = await subDocument.copyPages(pdfLibDocument, pagesToExtractArray);
|
|
||||||
|
|
||||||
for (let i = 0; i < copiedPages.length; i++) {
|
|
||||||
subDocument.addPage(copiedPages[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PdfFile(file.originalFilename, subDocument, RepresentationType.PDFLibDocument, file.filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RemovePagesParamsType = {
|
|
||||||
file: PdfFile;
|
|
||||||
pagesToRemoveArray: number[];
|
|
||||||
}
|
|
||||||
export async function removePages(params: RemovePagesParamsType): Promise<PdfFile> {
|
|
||||||
const { file, pagesToRemoveArray } = params;
|
|
||||||
|
|
||||||
const pdfLibDocument = await file.pdfLibDocument;
|
|
||||||
|
|
||||||
const pagesToExtractArray = invertSelection(pagesToRemoveArray, pdfLibDocument.getPageIndices())
|
|
||||||
return selectPages({file: file, pagesToExtractArray});
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RemoveBlankPagesParamsType = {
|
|
||||||
file: PdfFile;
|
|
||||||
whiteThreashold: number;
|
|
||||||
}
|
|
||||||
export async function removeBlankPages(params: RemoveBlankPagesParamsType) {
|
|
||||||
const { file, whiteThreashold } = params;
|
|
||||||
|
|
||||||
const emptyPages = await detectEmptyPages(file, whiteThreashold);
|
|
||||||
console.log("Empty Pages: ", emptyPages);
|
|
||||||
return removePages({file, pagesToRemoveArray:emptyPages});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the page selector string used in the 'PDF Page Organizer'
|
|
||||||
* @param pageOrderArr
|
|
||||||
* @param totalPages
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function parseFancyPageSelector(pageNumbers: string, totalPages: number): number[] {
|
|
||||||
// Translated to JS from the original Java function
|
|
||||||
const pageOrderArr = pageNumbers.split(",")
|
|
||||||
const newPageOrder: number[] = [];
|
|
||||||
|
|
||||||
// loop through the page order array
|
|
||||||
pageOrderArr.forEach(element => {
|
|
||||||
if (element.toLocaleLowerCase() === "all") {
|
|
||||||
for (var i = 0; i < totalPages; i++) {
|
|
||||||
newPageOrder.push(i);
|
|
||||||
}
|
|
||||||
// As all pages are already added, no need to check further
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (element.match("\\d*n\\+?-?\\d*|\\d*\\+?n")) {
|
|
||||||
// Handle page order as a function
|
|
||||||
var coefficient = 0;
|
|
||||||
var constant = 0;
|
|
||||||
var coefficientExists = false;
|
|
||||||
var constantExists = false;
|
|
||||||
|
|
||||||
if (element.includes("n")) {
|
|
||||||
var parts = element.split("n");
|
|
||||||
if (!parts[0]) {
|
|
||||||
coefficient = parseInt(parts[0]);
|
|
||||||
coefficientExists = true;
|
|
||||||
}
|
|
||||||
if (parts.length > 1 && parts[1]) {
|
|
||||||
constant = parseInt(parts[1]);
|
|
||||||
constantExists = true;
|
|
||||||
}
|
|
||||||
} else if (element.includes("+")) {
|
|
||||||
constant = parseInt(element.replace("+", ""));
|
|
||||||
constantExists = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 1; i <= totalPages; i++) {
|
|
||||||
var pageNum = coefficientExists ? coefficient * i : i;
|
|
||||||
pageNum += constantExists ? constant : 0;
|
|
||||||
|
|
||||||
if (pageNum <= totalPages && pageNum > 0) {
|
|
||||||
newPageOrder.push(pageNum - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (element.includes("-")) {
|
|
||||||
// split the range into start and end page
|
|
||||||
const range = element.split("-");
|
|
||||||
const start = parseInt(range[0]);
|
|
||||||
var end = parseInt(range[1]);
|
|
||||||
// check if the end page is greater than total pages
|
|
||||||
if (end > totalPages) {
|
|
||||||
end = totalPages;
|
|
||||||
}
|
|
||||||
// loop through the range of pages
|
|
||||||
for (var j = start; j <= end; j++) {
|
|
||||||
// print the current index
|
|
||||||
newPageOrder.push(j - 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if the element is a single page
|
|
||||||
newPageOrder.push(parseInt(element) - 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return newPageOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
function invertSelection(selection: number[], pageIndecies: number[]): number[] {
|
|
||||||
const pageIndeciesCopy = [...pageIndecies];
|
|
||||||
return pageIndeciesCopy.filter(x => !selection.includes(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////
|
|
||||||
// Page Sorters //
|
|
||||||
//////////////////
|
|
||||||
function reverseSort(totalPages: number): number[] {
|
|
||||||
return [...Array(totalPages).keys()].reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
function duplexSort(totalPages: number): number[] {
|
|
||||||
// Translated to JS from the original Java function
|
|
||||||
const newPageOrder: number[] = [];
|
|
||||||
const half = Math.floor((totalPages + 1) / 2); // This ensures proper behavior with odd numbers of pages
|
|
||||||
|
|
||||||
for (let i = 1; i <= half; i++) {
|
|
||||||
newPageOrder.push(i - 1);
|
|
||||||
if (i <= totalPages - half) {
|
|
||||||
// Avoid going out of bounds
|
|
||||||
newPageOrder.push(totalPages - i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newPageOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bookletSort(totalPages: number): number[] {
|
|
||||||
const newPageOrder: number[] = [];
|
|
||||||
for (let i = 0; i < totalPages / 2; i++) {
|
|
||||||
newPageOrder.push(i);
|
|
||||||
newPageOrder.push(totalPages - i - 1);
|
|
||||||
}
|
|
||||||
return newPageOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sideStitchBooklet(totalPages: number): number[] {
|
|
||||||
const newPageOrder: number[] = [];
|
|
||||||
for (let i = 0; i < (totalPages + 3) / 4; i++) {
|
|
||||||
const begin = i * 4;
|
|
||||||
newPageOrder.push(Math.min(begin + 3, totalPages - 1));
|
|
||||||
newPageOrder.push(Math.min(begin, totalPages - 1));
|
|
||||||
newPageOrder.push(Math.min(begin + 1, totalPages - 1));
|
|
||||||
newPageOrder.push(Math.min(begin + 2, totalPages - 1));
|
|
||||||
}
|
|
||||||
return newPageOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
function oddEvenSplit(totalPages: number): number[] {
|
|
||||||
const newPageOrder: number[] = [];
|
|
||||||
for (let i = 1; i <= totalPages; i += 2) {
|
|
||||||
newPageOrder.push(i - 1);
|
|
||||||
}
|
|
||||||
for (let i = 2; i <= totalPages; i += 2) {
|
|
||||||
newPageOrder.push(i - 1);
|
|
||||||
}
|
|
||||||
return newPageOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeFirst(totalPages: number): number[] {
|
|
||||||
return [...Array(totalPages-1).keys()].map(i => i+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeLast(totalPages: number): number[] {
|
|
||||||
return [...Array(totalPages-1).keys()];
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeFirstAndLast(totalPages: number): number[] {
|
|
||||||
return [...Array(totalPages-2).keys()].map(i => i+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SortFunction = (totalPages: number) => number[];
|
|
||||||
type Sorts = {
|
|
||||||
[key: string]: SortFunction;
|
|
||||||
};
|
|
||||||
export const sorts: Sorts = Object.freeze({
|
|
||||||
"REVERSE_ORDER": reverseSort,
|
|
||||||
"DUPLEX_SORT": duplexSort,
|
|
||||||
"BOOKLET_SORT": bookletSort,
|
|
||||||
"SIDE_STITCH_BOOKLET_SORT": sideStitchBooklet,
|
|
||||||
"ODD_EVEN_SPLIT": oddEvenSplit,
|
|
||||||
"REMOVE_FIRST": removeFirst,
|
|
||||||
"REMOVE_LAST": removeLast,
|
|
||||||
"REMOVE_FIRST_AND_LAST": removeFirstAndLast,
|
|
||||||
});
|
|
@ -1,16 +1,12 @@
|
|||||||
|
|
||||||
import {
|
import { extractPages, ExtractPagesParamsType } from "./functions/extractPages";
|
||||||
sortPagesWithPreset, SortPagesWithPresetParamsType,
|
|
||||||
rearrangePages, RearrangePagesParamsType,
|
|
||||||
selectPages, SelectPagesParamsType,
|
|
||||||
removePages, RemovePagesParamsType,
|
|
||||||
removeBlankPages, RemoveBlankPagesParamsType
|
|
||||||
} from "./functions/subDocumentFunctions";
|
|
||||||
import { impose, ImposeParamsBaseType, ImposeParamsType } from "./functions/impose";
|
import { impose, ImposeParamsBaseType, ImposeParamsType } from "./functions/impose";
|
||||||
import { mergePDFs, MergeParamsType } from './functions/mergePDFs';
|
import { mergePDFs, MergeParamsType } from './functions/mergePDFs';
|
||||||
|
import { removeBlankPages, RemoveBlankPagesParamsType } from "./functions/removeBlankPages";
|
||||||
import { rotatePages, RotateParamsType } from './functions/rotatePages';
|
import { rotatePages, RotateParamsType } from './functions/rotatePages';
|
||||||
import { scaleContent, ScaleContentParamsType} from './functions/scaleContent';
|
import { scaleContent, ScaleContentParamsType} from './functions/scaleContent';
|
||||||
import { scalePage, ScalePageParamsType } from './functions/scalePage';
|
import { scalePage, ScalePageParamsType } from './functions/scalePage';
|
||||||
|
import { sortPagesWithPreset, SortPagesWithPresetParamsType } from './functions/sortPagesWithPreset'
|
||||||
import { splitOn, SplitOnParamsType } from './functions/splitOn';
|
import { splitOn, SplitOnParamsType } from './functions/splitOn';
|
||||||
import { splitPDF, SplitPdfParamsType } from './functions/splitPDF';
|
import { splitPDF, SplitPdfParamsType } from './functions/splitPDF';
|
||||||
import { updateMetadata, UpdateMetadataParams } from "./functions/updateMetadata";
|
import { updateMetadata, UpdateMetadataParams } from "./functions/updateMetadata";
|
||||||
@ -21,12 +17,14 @@ import { Override } from '../declarations/TypeScriptUtils'
|
|||||||
// Import injected libraries here!
|
// Import injected libraries here!
|
||||||
|
|
||||||
const toExport = {
|
const toExport = {
|
||||||
sortPagesWithPreset, rearrangePages, selectPages, removePages, removeBlankPages,
|
extractPages,
|
||||||
impose,
|
impose,
|
||||||
mergePDFs,
|
mergePDFs,
|
||||||
|
removeBlankPages,
|
||||||
rotatePages,
|
rotatePages,
|
||||||
scaleContent,
|
scaleContent,
|
||||||
scalePage,
|
scalePage,
|
||||||
|
sortPagesWithPreset,
|
||||||
splitOn,
|
splitOn,
|
||||||
splitPDF,
|
splitPDF,
|
||||||
updateMetadata,
|
updateMetadata,
|
||||||
@ -34,16 +32,14 @@ const toExport = {
|
|||||||
export default toExport;
|
export default toExport;
|
||||||
|
|
||||||
export type OperationsParametersBaseType = {
|
export type OperationsParametersBaseType = {
|
||||||
sortPagesWithPreset: SortPagesWithPresetParamsType;
|
extractPages: ExtractPagesParamsType;
|
||||||
rearrangePages: RearrangePagesParamsType;
|
|
||||||
selectPages: SelectPagesParamsType;
|
|
||||||
removePages: RemovePagesParamsType;
|
|
||||||
removeBlankPages: RemoveBlankPagesParamsType;
|
|
||||||
impose: ImposeParamsBaseType;
|
impose: ImposeParamsBaseType;
|
||||||
mergePDFs: MergeParamsType;
|
mergePDFs: MergeParamsType;
|
||||||
|
removeBlankPages: RemoveBlankPagesParamsType;
|
||||||
rotatePages: RotateParamsType;
|
rotatePages: RotateParamsType;
|
||||||
scaleContent: ScaleContentParamsType;
|
scaleContent: ScaleContentParamsType;
|
||||||
scalePage: ScalePageParamsType;
|
scalePage: ScalePageParamsType;
|
||||||
|
sortPagesWithPreset: SortPagesWithPresetParamsType;
|
||||||
splitOn: SplitOnParamsType;
|
splitOn: SplitOnParamsType;
|
||||||
splitPDF: SplitPdfParamsType;
|
splitPDF: SplitPdfParamsType;
|
||||||
updateMetadata: UpdateMetadataParams;
|
updateMetadata: UpdateMetadataParams;
|
||||||
|
@ -54,7 +54,7 @@ export async function * traverseOperations(operations: Action[], input: PdfFile[
|
|||||||
break;
|
break;
|
||||||
case "extract":
|
case "extract":
|
||||||
yield* nToN(input, action, async (input) => {
|
yield* nToN(input, action, async (input) => {
|
||||||
const newPdf = await Operations.selectPages({file: input, pagesToExtractArray: action.values["pagesToExtractArray"]});
|
const newPdf = await Operations.extractPages({file: input, pageIndexes: action.values["pageIndexes"]});
|
||||||
newPdf.filename += "_extractedPages";
|
newPdf.filename += "_extractedPages";
|
||||||
return newPdf;
|
return newPdf;
|
||||||
});
|
});
|
||||||
@ -96,7 +96,7 @@ export async function * traverseOperations(operations: Action[], input: PdfFile[
|
|||||||
break;
|
break;
|
||||||
case "sortPagesWithPreset":
|
case "sortPagesWithPreset":
|
||||||
yield* nToN(input, action, async (input) => {
|
yield* nToN(input, action, async (input) => {
|
||||||
const newPdf = await Operations.sortPagesWithPreset({file: input, sortPreset: action.values["sortPreset"], fancyPageSelector: action.values["fancyPageSelector"]});
|
const newPdf = await Operations.sortPagesWithPreset({file: input, sortPreset: action.values["sortPreset"]});
|
||||||
newPdf.filename += "_pagesOrganized";
|
newPdf.filename += "_pagesOrganized";
|
||||||
return newPdf;
|
return newPdf;
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user