diff --git a/shared-operations/src/functions/common/pageIndexesUtils.ts b/shared-operations/src/functions/common/pageIndexesUtils.ts index 0b25f3391..7fd568a27 100644 --- a/shared-operations/src/functions/common/pageIndexesUtils.ts +++ b/shared-operations/src/functions/common/pageIndexesUtils.ts @@ -1,17 +1,22 @@ /** * @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). + * @param pageCount The number of pages of the pdfDocument. * @returns An inverted selection array of page indexes. */ -export 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)); +export function invertSelection(selection: number[], pageCount: number): number[] { + const newSelection = []; + for (let pageIndex = 0; pageIndex < pageCount; pageIndex++) { + if(!selection.includes(pageIndex)) + newSelection.push(pageIndex); + } + return newSelection; } + +// TODO: Port this to CommaArrayJoiExt.ts /** - * Parse the page selector string used in the 'PDF Page Organizer' + * Parse the page selector string * @param specification * @param totalPages * @returns diff --git a/shared-operations/src/functions/extractPages.ts b/shared-operations/src/functions/extractPages.ts index 4a9acdaa4..6bbbb650d 100644 --- a/shared-operations/src/functions/extractPages.ts +++ b/shared-operations/src/functions/extractPages.ts @@ -7,7 +7,6 @@ import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi"; import i18next from "i18next"; import { getPages } from "./common/getPagesByIndex"; -import { parsePageIndexSpecification } from "./common/pageIndexesUtils"; import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt"; export class ExtractPages extends Operator { @@ -39,15 +38,8 @@ export class ExtractPages extends Operator { /** PDF extraction, specify pages from one pdf and output them to a new pdf */ async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise { return oneToOne(input, async (input, index, max) => { - const pdfLibDocument = await input.pdfLibDocument; - let indexes = this.actionValues.pageIndexes; - - if (!Array.isArray(indexes)) { - indexes = parsePageIndexSpecification(indexes, pdfLibDocument.getPageCount()); - } - - const newFile = await getPages(input, indexes); + const newFile = await getPages(input, this.actionValues.pageIndexes); newFile.filename += "_extractedPages"; progressCallback({ curFileProgress: 1, operationProgress: index/max }); diff --git a/shared-operations/src/functions/removePages.ts b/shared-operations/src/functions/removePages.ts index 07058fc6d..a70fe29fc 100644 --- a/shared-operations/src/functions/removePages.ts +++ b/shared-operations/src/functions/removePages.ts @@ -1,21 +1,56 @@ - import { PdfFile } from "../wrappers/PdfFile"; +import { Operator, Progress, oneToOne } from "."; + +import Joi from "@stirling-tools/joi"; +import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi"; + +import i18next from "i18next"; + import { getPages } from "./common/getPagesByIndex"; -import { invertSelection, parsePageIndexSpecification } from "./common/pageIndexesUtils"; +import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt"; -export interface RemovePagesParamsType { - file: PdfFile; - pageSelector: string; -} -export async function removePages(params: RemovePagesParamsType) { - const { file, pageSelector } = params; - const pdfDoc = await file.pdfLibDocument; - const pageCount = pdfDoc.getPageCount(); +import { invertSelection } from "./common/pageIndexesUtils"; - const pageSelection = parsePageIndexSpecification(pageSelector, pageCount); - const pagesToKeep = invertSelection(pageSelection, pageCount); +export class RemovePages extends Operator { + static type = "removePages"; - const newFile = await getPages(file, pagesToKeep); - newFile.filename += "_removedPages"; - return newFile; + /** + * Validation & Localisation + */ + + protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")); + protected static valueSchema = Joi.object({ + pageIndexes: CommaArrayJoiExt.comma_array().items(Joi.number().integer()).required() + .label(i18next.t("values.pageIndexes.friendlyName", { ns: "removePages" })).description(i18next.t("values.pageIndexes.description", { ns: "removePages" })) + .example("1").example("1, 2, 3, 4").example("4, 2, 4, 3").required() + }); + protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description")); + + static schema = Joi.object({ + input: RemovePages.inputSchema, + values: RemovePages.valueSchema.required(), + output: RemovePages.outputSchema + }).label(i18next.t("friendlyName", { ns: "removePages" })).description(i18next.t("description", { ns: "removePages" })); + + + /** + * Logic + */ + + /** PDF extraction, specify pages from one pdf and output them to a new pdf */ + async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise { + return oneToOne(input, async (input, index, max) => { + + const pdfDoc = await input.pdfLibDocument; + const pageCount = pdfDoc.getPageCount(); + + const pagesToKeep = invertSelection(this.actionValues.pageIndexes, pageCount); + + const newFile = await getPages(input, pagesToKeep); + newFile.filename += "_removedPages"; + progressCallback({ curFileProgress: 1, operationProgress: index/max }); + + return newFile; + }); + } } \ No newline at end of file diff --git a/shared-operations/src/wrappers/CommaArrayJoiExt.ts b/shared-operations/src/wrappers/CommaArrayJoiExt.ts index 3f30864df..7ff0be82f 100644 --- a/shared-operations/src/wrappers/CommaArrayJoiExt.ts +++ b/shared-operations/src/wrappers/CommaArrayJoiExt.ts @@ -6,13 +6,13 @@ export default Joi.extend((joi) => { type: 'comma_array', base: joi.array(), messages: { - 'million.base': '{{#label}} must be a comma seperated list', + 'comma_array.base': '{{#label}} must be a comma seperated list', }, coerce: { from: 'string', method(value, helpers) { - if (typeof value !== 'string' || !/(\d+)(,\s*\d+)*/.test(value)) { + if (typeof value !== 'string' || !/(\d+)(,\s*\d+)*/.test(value)) { // is string and in format "[number], [number]" return; }