From 0f35c770742944a43cb4d3e65e2270eac9e22a34 Mon Sep 17 00:00:00 2001 From: Saud Fatayerji Date: Wed, 8 Nov 2023 03:33:22 +0300 Subject: [PATCH] Migrating shared-operations to TS (WIP) --- .../declarations/shared-operations.d.ts | 53 -- package-lock.json | 470 +++++++++++++++++- ...ateSubDocument.js => createSubDocument.ts} | 2 +- .../functions/detectEmptyPages.js | 62 --- .../functions/detectEmptyPages.ts | 50 ++ shared-operations/functions/editMetadata.js | 55 -- shared-operations/functions/editMetadata.ts | 53 ++ .../{extractPages.js => extractPages.ts} | 2 +- ...{getImagesOnPage.js => getImagesOnPage.ts} | 7 +- .../functions/{impose.js => impose.ts} | 0 .../functions/{mergePDFs.js => mergePDFs.ts} | 2 +- .../{organizePages.js => organizePages.ts} | 28 +- ...emoveBlankPages.js => removeBlankPages.ts} | 4 +- .../{rotatePages.js => rotatePages.ts} | 2 +- .../{scaleContent.js => scaleContent.ts} | 2 +- .../functions/{scalePage.js => scalePage.ts} | 2 +- .../functions/{splitOn.js => splitOn.ts} | 50 +- .../functions/{splitPDF.js => splitPDF.ts} | 7 +- shared-operations/package.json | 1 + 19 files changed, 622 insertions(+), 230 deletions(-) delete mode 100644 client-ionic/declarations/shared-operations.d.ts rename shared-operations/functions/{createSubDocument.js => createSubDocument.ts} (84%) delete mode 100644 shared-operations/functions/detectEmptyPages.js create mode 100644 shared-operations/functions/detectEmptyPages.ts delete mode 100644 shared-operations/functions/editMetadata.js create mode 100644 shared-operations/functions/editMetadata.ts rename shared-operations/functions/{extractPages.js => extractPages.ts} (68%) rename shared-operations/functions/{getImagesOnPage.js => getImagesOnPage.ts} (54%) rename shared-operations/functions/{impose.js => impose.ts} (100%) rename shared-operations/functions/{mergePDFs.js => mergePDFs.ts} (79%) rename shared-operations/functions/{organizePages.js => organizePages.ts} (85%) rename shared-operations/functions/{removeBlankPages.js => removeBlankPages.ts} (95%) rename shared-operations/functions/{rotatePages.js => rotatePages.ts} (77%) rename shared-operations/functions/{scaleContent.js => scaleContent.ts} (86%) rename shared-operations/functions/{scalePage.js => scalePage.ts} (81%) rename shared-operations/functions/{splitOn.js => splitOn.ts} (77%) rename shared-operations/functions/{splitPDF.js => splitPDF.ts} (70%) diff --git a/client-ionic/declarations/shared-operations.d.ts b/client-ionic/declarations/shared-operations.d.ts deleted file mode 100644 index 7d910b508..000000000 --- a/client-ionic/declarations/shared-operations.d.ts +++ /dev/null @@ -1,53 +0,0 @@ - -declare module '@stirling-pdf/shared-operations/functions/editMetadata' { - export type Metadata = { - Title: string | null | undefined; // The title of the document. - Author: string | null | undefined; // The author of the document. - Subject: string | null | undefined; // The subject of the document. - Keywords: string[] | null | undefined; // An array of keywords associated with the document. - Producer: string | null | undefined; // The producer of the document. - Creator: string | null | undefined; // The creator of the document. - CreationDate: Date | null | undefined; // The date when the document was created. - ModificationDate: Date | null | undefined; // The date when the document was last modified. - } - export async function editMetadata(snapshot: string | Uint8Array | ArrayBuffer, metadata: Metadata): Promise; -} - -declare module '@stirling-pdf/shared-operations/functions/extractPages' { - export async function extractPages(snapshot: string | Uint8Array | ArrayBuffer, pagesToExtractArray: number[]): Promise; - export async function createSubDocument(pdfDoc: typeof import("pdf-lib").PDFDocument, pagesToExtractArray: number[]) -} - -declare module '@stirling-pdf/shared-operations/functions/mergePDFs' { - export async function mergePDFs(snapshots: (string | Uint8Array | ArrayBuffer)[]): Promise; -} - -declare module '@stirling-pdf/shared-operations/functions/organizePages' { - export async function organizePages( - snapshot: string | Uint8Array | ArrayBuffer, - operation: "CUSTOM_PAGE_ORDER" | - "REVERSE_ORDER" | - "DUPLEX_SORT" | - "BOOKLET_SORT" | - "ODD_EVEN_SPLIT" | - "REMOVE_FIRST" | - "REMOVE_LAST" | - "REMOVE_FIRST_AND_LAST", - customOrderString: string): Promise; -} - -declare module '@stirling-pdf/shared-operations/functions/rotatePages' { - export async function rotatePages(snapshot: string | Uint8Array | ArrayBuffer, rotation: number): Promise; -} - -declare module '@stirling-pdf/shared-operations/functions/scaleContent' { - export async function scaleContent(snapshot: string | Uint8Array | ArrayBuffer, scaleFactor: number): Promise; -} - -declare module '@stirling-pdf/shared-operations/functions/scalePage' { - export async function scalePage(snapshot: string | Uint8Array | ArrayBuffer, pageSize: {width:number,height:number}): Promise; -} - -declare module '@stirling-pdf/shared-operations/functions/splitPDF' { - export async function splitPDF(snapshot: string | Uint8Array | ArrayBuffer, splitAfterPageArray: number[]): Promise; -} diff --git a/package-lock.json b/package-lock.json index 58beb5a62..745f5d2e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3866,6 +3866,14 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/@swiftcarrot/color-fns": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@swiftcarrot/color-fns/-/color-fns-3.2.0.tgz", + "integrity": "sha512-6SCpc4LwmGGqWHpBY9WaBzJwPF4nfgvFfejOX7Ub0kTehJysFkLUAvGID8zEx39n0pGlfr9pTiQE/7/buC7X5w==", + "dependencies": { + "@babel/runtime": "^7.10.3" + } + }, "node_modules/@tauri-apps/api": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.5.1.tgz", @@ -4146,6 +4154,11 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/pako": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.3.tgz", + "integrity": "sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==" + }, "node_modules/@types/prop-types": { "version": "15.7.9", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", @@ -5098,8 +5111,7 @@ "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==" }, "node_modules/bluebird": { "version": "3.7.2", @@ -5339,6 +5351,11 @@ } ] }, + "node_modules/canny-edge-detector": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canny-edge-detector/-/canny-edge-detector-1.0.0.tgz", + "integrity": "sha512-SpewmkHDE1PbJ1/AVAcpvZKOufYpUXT0euMvhb5C4Q83Q9XEOmSXC+yR7jl3F4Ae1Ev6OtQKbFgdcPrOdHjzQg==" + }, "node_modules/canvas": { "version": "2.11.2", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", @@ -6997,6 +7014,14 @@ "node >=0.6.0" ] }, + "node_modules/fast-bmp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-bmp/-/fast-bmp-2.0.1.tgz", + "integrity": "sha512-MOSG2rHYJCjIfL3/Llseuj39yl5U3d3XLtWFLFm5ZSTublGEXyvNcwi4Npyv6nzDPRSbAP53rvVRUswgftWCcQ==", + "dependencies": { + "iobuffer": "^5.1.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -7041,6 +7066,28 @@ "node": ">= 6" } }, + "node_modules/fast-jpeg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-jpeg/-/fast-jpeg-1.0.1.tgz", + "integrity": "sha512-nyoYDzmdxgLOBfEhJGwYRsRLqGKziG/wic0SMct17dTVHkseTPvNwHCfihE47tcpGA1cTJO2MNsYYHezmkuA6w==", + "dependencies": { + "iobuffer": "^2.1.0", + "tiff": "^2.0.0" + } + }, + "node_modules/fast-jpeg/node_modules/iobuffer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-2.1.0.tgz", + "integrity": "sha512-0XZfU0STJ6NVHBZdMRPjF7jtkDEC5f4AxM/n5DSZOu11SQ+7tAl1csuEnEPoSPYWdaGZ/HOfn5Q837IEHddL2w==" + }, + "node_modules/fast-jpeg/node_modules/tiff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiff/-/tiff-2.1.0.tgz", + "integrity": "sha512-Q4zLT4+Csn/ZhFVacYCAl+w/1J51NW/m2y2yx7Qxp/bsHYOEsK7+5JOID2kfk+EvsaF0LbA6ccAkqiuXOmAbYw==", + "dependencies": { + "iobuffer": "^2.1.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -7053,6 +7100,26 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-list/-/fast-list-1.0.3.tgz", + "integrity": "sha512-Lm56Ci3EqefHNdIneRFuzhpPcpVVBz9fgqVmG3UQIxAefJv1mEYsZ1WQLTWqmdqeGEwbI2t6fbZgp9TqTYARuA==" + }, + "node_modules/fast-png": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.2.0.tgz", + "integrity": "sha512-fO4DewoEd9WwuP8DQcfj8Tlc88Jno6lJAjlDYzvJSqMIZwxUpRT4zuzPXgqygjJqngBdCbeQRaL/FVz3InExhA==", + "dependencies": { + "@types/pako": "^2.0.0", + "iobuffer": "^5.3.2", + "pako": "^2.1.0" + } + }, + "node_modules/fast-png/node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -7071,6 +7138,11 @@ "pend": "~1.2.0" } }, + "node_modules/fft.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/fft.js/-/fft.js-4.0.4.tgz", + "integrity": "sha512-f9c00hphOgeQTlDyavwTtu6RiK8AIFjD6+jvXkNkpeQ7rirK3uFWVpalkoS4LAwbdX7mfZ8aoBfFVQX1Re/8aw==" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -7107,6 +7179,14 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-type": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", + "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==", + "engines": { + "node": ">=6" + } + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -7563,6 +7643,11 @@ "node": ">=8" } }, + "node_modules/has-own": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-own/-/has-own-1.0.1.tgz", + "integrity": "sha512-RDKhzgQTQfMaLvIFhjahU+2gGnRBK6dYOd5Gd9BzkmnBneOCRYjRC003RIMrdAbH52+l+CnMS4bBCXGer8tEhg==" + }, "node_modules/has-property-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", @@ -7860,6 +7945,52 @@ "node": ">= 4" } }, + "node_modules/image-js": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/image-js/-/image-js-0.35.5.tgz", + "integrity": "sha512-JCtn+ggFG6qkVaKZkJDnMMLO6Xg9/WVDK+BIWcXHwT+XEdu8dzp/nlYzB5opxBkIoitWB2GGYRpF69WQmucJhQ==", + "dependencies": { + "@swiftcarrot/color-fns": "^3.2.0", + "blob-util": "^2.0.2", + "canny-edge-detector": "^1.0.0", + "fast-bmp": "^2.0.1", + "fast-jpeg": "^1.0.1", + "fast-list": "^1.0.3", + "fast-png": "^6.1.0", + "has-own": "^1.0.1", + "image-type": "^4.1.0", + "is-array-type": "^1.0.0", + "is-integer": "^1.0.7", + "jpeg-js": "^0.4.3", + "js-priority-queue": "^0.1.5", + "js-quantities": "^1.7.6", + "median-quickselect": "^1.0.1", + "ml-convolution": "0.2.0", + "ml-disjoint-set": "^1.0.0", + "ml-matrix": "^6.8.0", + "ml-matrix-convolution": "0.4.3", + "ml-regression": "^5.0.0", + "monotone-chain-convex-hull": "^1.0.0", + "new-array": "^1.0.0", + "robust-point-in-polygon": "^1.0.3", + "tiff": "^5.0.2", + "web-worker-manager": "^0.2.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/image-type": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/image-type/-/image-type-4.1.0.tgz", + "integrity": "sha512-CFJMJ8QK8lJvRlTCEgarL4ro6hfDQKif2HjSvYCdQZESaIPV4v9imrf7BQHK+sQeTeNeMpWciR9hyC/g8ybXEg==", + "dependencies": { + "file-type": "^10.10.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -7939,6 +8070,11 @@ "loose-envify": "^1.0.0" } }, + "node_modules/iobuffer": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.3.2.tgz", + "integrity": "sha512-kO3CjNfLZ9t+tHxAMd+Xk4v3D/31E91rMs1dHrm7ikEQrlZ8mLDbQ4z3tZfDM48zOkReas2jx8MWSAmN9+c8Fw==" + }, "node_modules/ionicons": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.2.1.tgz", @@ -7955,6 +8091,11 @@ "node": ">= 0.10" } }, + "node_modules/is-any-array": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-any-array/-/is-any-array-2.0.1.tgz", + "integrity": "sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==" + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -7985,6 +8126,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-array-type": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-array-type/-/is-array-type-1.0.0.tgz", + "integrity": "sha512-LLwKQdMAO/XUkq4XTed1VYqwR2OahiwkBg+yUtZT88LXX4MLXP28qGsVfSNVP8X0wc7fzDhcZD3nns/IK8UfKw==" + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -8115,6 +8261,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -8167,6 +8324,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-integer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.7.tgz", + "integrity": "sha512-RPQc/s9yBHSvpi+hs9dYiJ2cuFeU6x3TyyIp8O2H6SKEltIvJOzRj9ToyvcStDvPR/pS4rxgr1oBFajQjZ2Szg==", + "dependencies": { + "is-finite": "^1.0.0" + } + }, "node_modules/is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -8665,6 +8830,21 @@ "node": ">= 10.13.0" } }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, + "node_modules/js-priority-queue": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/js-priority-queue/-/js-priority-queue-0.1.5.tgz", + "integrity": "sha512-2dPmJT4GbXUpob7AZDR1wFMKz3Biy6oW69mwt5PTtdeoOgDin1i0p5gUV9k0LFeUxDpwkfr+JGMZDpcprjiY5w==" + }, + "node_modules/js-quantities": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/js-quantities/-/js-quantities-1.8.0.tgz", + "integrity": "sha512-swDw9RJpXACAWR16vAKoSojAsP6NI7cZjjnjKqhOyZSdybRUdmPr071foD3fejUKSU2JMHz99hflWkRWvfLTpQ==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9163,6 +9343,11 @@ "node": ">= 0.6" } }, + "node_modules/median-quickselect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/median-quickselect/-/median-quickselect-1.0.1.tgz", + "integrity": "sha512-/QL9ptNuLsdA68qO+2o10TKCyu621zwwTFdLvtu8rzRNKsn8zvuGoq/vDxECPyELFG8wu+BpyoMR9BnsJqfVZQ==" + }, "node_modules/memfs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.0.4.tgz", @@ -9343,6 +9528,204 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/ml-array-max": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/ml-array-max/-/ml-array-max-1.2.4.tgz", + "integrity": "sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==", + "dependencies": { + "is-any-array": "^2.0.0" + } + }, + "node_modules/ml-array-median": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/ml-array-median/-/ml-array-median-1.1.6.tgz", + "integrity": "sha512-V6bV6bTPFRX8v5CaAx/7fuRXC39LLTHfPSVZZafdNaqNz2PFL5zEA7gesjv8dMXh+gwPeUMtB5QPovlTBaa4sw==", + "dependencies": { + "is-any-array": "^2.0.0", + "median-quickselect": "^1.0.1" + } + }, + "node_modules/ml-array-min": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/ml-array-min/-/ml-array-min-1.2.3.tgz", + "integrity": "sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q==", + "dependencies": { + "is-any-array": "^2.0.0" + } + }, + "node_modules/ml-array-rescale": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ml-array-rescale/-/ml-array-rescale-1.3.7.tgz", + "integrity": "sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ==", + "dependencies": { + "is-any-array": "^2.0.0", + "ml-array-max": "^1.2.4", + "ml-array-min": "^1.2.3" + } + }, + "node_modules/ml-convolution": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ml-convolution/-/ml-convolution-0.2.0.tgz", + "integrity": "sha512-km5f81jFVnEWG0eFEKAwt00X3xGUIAcUqZZlUk+w0q2sZOz1vkEYhIKOXAlmaEi9rnrTknxW//Ttm399zPzDPg==", + "dependencies": { + "fft.js": "^4.0.3", + "next-power-of-two": "^1.0.0" + } + }, + "node_modules/ml-disjoint-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ml-disjoint-set/-/ml-disjoint-set-1.0.0.tgz", + "integrity": "sha512-UcEzgvRzVhsKpT66syfdhaK8R+av6GxDFmU37t+6WClT/kHDIN6OMRfO7OPwQIV8+L8FSc2E6lNKpvdqf6OgLw==" + }, + "node_modules/ml-distance-euclidean": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-distance-euclidean/-/ml-distance-euclidean-2.0.0.tgz", + "integrity": "sha512-yC9/2o8QF0A3m/0IXqCTXCzz2pNEzvmcE/9HFKOZGnTjatvBbsn4lWYJkxENkA4Ug2fnYl7PXQxnPi21sgMy/Q==" + }, + "node_modules/ml-fft": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ml-fft/-/ml-fft-1.3.5.tgz", + "integrity": "sha512-laAATDyUuWPbIlX57thIds41wqFLsB+Zl7i1yrLRo/4CFg+hFaF9Xle8InblQseyiaVtt1KSlDG+6lgUMPOj3g==" + }, + "node_modules/ml-kernel": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ml-kernel/-/ml-kernel-3.0.0.tgz", + "integrity": "sha512-R+ZR0Kl5xJ7vnxtlDqjZ26xVk7mAw7ctK4NlzRHviBFXxp7keC9+hWirMOdzi2DOQA0t6CaRwjElZ6SdirOmow==", + "dependencies": { + "ml-distance-euclidean": "^2.0.0", + "ml-kernel-gaussian": "^2.0.2", + "ml-kernel-polynomial": "^2.0.1", + "ml-kernel-sigmoid": "^1.0.1", + "ml-matrix": "^6.1.2" + } + }, + "node_modules/ml-kernel-gaussian": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ml-kernel-gaussian/-/ml-kernel-gaussian-2.0.2.tgz", + "integrity": "sha512-5MBrH2g9MBO53I6mcyXvMhyOLsmO2w21+26A1ZV/vYoxqpsov2PWkT8bhdFCEe0kgDupmAb6u81iOID/rhnarA==", + "dependencies": { + "ml-distance-euclidean": "^2.0.0" + } + }, + "node_modules/ml-kernel-polynomial": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ml-kernel-polynomial/-/ml-kernel-polynomial-2.0.1.tgz", + "integrity": "sha512-aGDNRPHDiKeJmBxB0L9wTxKNLfp5JytbdRIo5K+FTcmFjkWDe3YZPo6R6wBB5mxaJ5eqTRawzeV4RoIWHbakyQ==" + }, + "node_modules/ml-kernel-sigmoid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ml-kernel-sigmoid/-/ml-kernel-sigmoid-1.0.1.tgz", + "integrity": "sha512-mSbYOSbNQ7GsUAGrHuUHNsLgM3bZGpXkotw/FBdKZD9YMXfVOgQb1LvvvVeSlOR/ZdmX23qqaV0RnKSYWBF8og==" + }, + "node_modules/ml-matrix": { + "version": "6.10.8", + "resolved": "https://registry.npmjs.org/ml-matrix/-/ml-matrix-6.10.8.tgz", + "integrity": "sha512-AOWniClvQMbGx2V0mqzOScINLe+PjAjpjTN3zYRG7gV5Zp29fu9b2E0PfTdnupN03USOQMvkjT9/8yB4hEEahg==", + "dependencies": { + "is-any-array": "^2.0.1", + "ml-array-rescale": "^1.3.7" + } + }, + "node_modules/ml-matrix-convolution": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/ml-matrix-convolution/-/ml-matrix-convolution-0.4.3.tgz", + "integrity": "sha512-B4AATOjxDw4J0oVcoeYHsXrhMr31x9SWhVKZjWucDU+brwXLR0enMdqb1OuRy/REdpL5/iSshA46sS2B1dO2OQ==", + "dependencies": { + "ml-fft": "1.3.5", + "ml-stat": "^1.2.0" + } + }, + "node_modules/ml-regression": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ml-regression/-/ml-regression-5.0.0.tgz", + "integrity": "sha512-mBn0LpfEWV3Dk0dj+8PRNUqIHvO87rUY0PmCUTYv3MKfECx7TtlKyeacJeOBLZ4YAVixX8U5hn4HwRL6TpTYaw==", + "dependencies": { + "ml-kernel": "^3.0.0", + "ml-matrix": "^6.1.2", + "ml-regression-base": "^2.0.1", + "ml-regression-exponential": "^2.0.0", + "ml-regression-multivariate-linear": "^2.0.2", + "ml-regression-polynomial": "^2.0.0", + "ml-regression-power": "^2.0.0", + "ml-regression-robust-polynomial": "^2.0.0", + "ml-regression-simple-linear": "^2.0.2", + "ml-regression-theil-sen": "^2.0.0" + } + }, + "node_modules/ml-regression-base": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/ml-regression-base/-/ml-regression-base-2.1.6.tgz", + "integrity": "sha512-yTckvEc8szc6VrUTJSgAClShvCoPZdNt8pmyRe8aGsIWGjg6bYFotp9mDUwAB0snvKAbQWd6A4trL/PDCASLug==", + "dependencies": { + "is-any-array": "^2.0.0" + } + }, + "node_modules/ml-regression-exponential": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ml-regression-exponential/-/ml-regression-exponential-2.1.0.tgz", + "integrity": "sha512-6ZgGbzIkXnONfGGUU0LjIb9qb35WzVqdAFSX8vFr8UEhgXhfgEws9pGrBJu19VBEh7ZTtttcPObI3aoBscq4Kg==", + "dependencies": { + "ml-regression-base": "^2.1.3", + "ml-regression-simple-linear": "^2.0.3" + } + }, + "node_modules/ml-regression-multivariate-linear": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/ml-regression-multivariate-linear/-/ml-regression-multivariate-linear-2.0.4.tgz", + "integrity": "sha512-/vShPAlP+mB7P2mC5TuXwObSJNl/UBI71/bszt9ilTg6yLKy6btDLpAYyJNa6t+JnL5a7q+Yy4dCltfpvqXRIw==", + "dependencies": { + "ml-matrix": "^6.10.1" + } + }, + "node_modules/ml-regression-polynomial": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ml-regression-polynomial/-/ml-regression-polynomial-2.2.0.tgz", + "integrity": "sha512-WxFsEmi6oLxgq9TeaVoAA+vVUJFp1kGarX6WWClR8OmlanoIW5iLMnaeXfQcYuH8xNq4R1Cax2N9hYYmeWWkLg==", + "dependencies": { + "ml-matrix": "^6.8.0", + "ml-regression-base": "^2.1.3" + } + }, + "node_modules/ml-regression-power": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-regression-power/-/ml-regression-power-2.0.0.tgz", + "integrity": "sha512-u8O9Fy45+OeYm/4ZBcNDn5w3w+MHc6kZz/AWSJIwmJcyjz6PRkTZnNfgGYdVKwKKDlAOS7G/AFvMKSTWRNO4RQ==", + "dependencies": { + "ml-regression-base": "^2.0.1", + "ml-regression-simple-linear": "^2.0.2" + } + }, + "node_modules/ml-regression-robust-polynomial": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ml-regression-robust-polynomial/-/ml-regression-robust-polynomial-2.0.1.tgz", + "integrity": "sha512-WkxA224Cil1G3Ug/T1O8H/2IDADlca21oC5WDplcM+gQRTqtueT/Su4ubH70tG6s79XHM046HfO8xQSpDQxqqg==", + "dependencies": { + "ml-matrix": "^6.8.0", + "ml-regression-base": "^2.1.3" + } + }, + "node_modules/ml-regression-simple-linear": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ml-regression-simple-linear/-/ml-regression-simple-linear-2.0.5.tgz", + "integrity": "sha512-7DBYru8GvWLaYo4LUF9vU2DjzHuM6i6WGnVbEP9wq8nUFUZ2DlwN46m8Z/hNhTSR7+3T+RvhaSY+OqdBpaz8zw==", + "dependencies": { + "ml-regression-base": "^2.0.1" + } + }, + "node_modules/ml-regression-theil-sen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-regression-theil-sen/-/ml-regression-theil-sen-2.0.0.tgz", + "integrity": "sha512-RO//tYzo69XbWDO5LIPdGp8ef1MSTPPJY0bXNlmOLMSay7YR9FQqtNgqn29T9DSYTa863VAafRlCeXwDQNXkBw==", + "dependencies": { + "ml-array-median": "^1.1.1", + "ml-regression-base": "^2.0.1" + } + }, + "node_modules/ml-stat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/ml-stat/-/ml-stat-1.3.3.tgz", + "integrity": "sha512-F6plydFIKFZA+7j/pRsRrfRu4nwsruQvYD9QxHWc4hFUdASVznsKUL2hgAwgMVizY/P0+b1L9bVQexKES5y/uw==" + }, "node_modules/mlly": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", @@ -9355,6 +9738,11 @@ "ufo": "^1.3.0" } }, + "node_modules/monotone-chain-convex-hull": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/monotone-chain-convex-hull/-/monotone-chain-convex-hull-1.1.0.tgz", + "integrity": "sha512-iZGaoO2qtqIWaAfscTtsH2LolE06U4JzTw8AgtjT/yzYIA0aoAHDdwBtsesnQXfVRvS375Wu0Y1+FqdI5Y22GA==" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -9478,6 +9866,16 @@ "node": ">= 0.6" } }, + "node_modules/new-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/new-array/-/new-array-1.0.0.tgz", + "integrity": "sha512-K5AyFYbuHZ4e/ti52y7k18q8UHsS78FlRd85w2Fmsd6AkuLipDihPflKC0p3PN5i8II7+uHxo+CtkLiJDfmS5A==" + }, + "node_modules/next-power-of-two": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-power-of-two/-/next-power-of-two-1.0.0.tgz", + "integrity": "sha512-+z6QY1SxkDk6CQJAeaIZKmcNubBCRP7J8DMQUBglz/sSkNsZoJ1kULjqk9skNPPplzs4i9PFhYrvNDdtQleF/A==" + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -10757,6 +11155,44 @@ "node": "*" } }, + "node_modules/robust-orientation": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/robust-orientation/-/robust-orientation-1.2.1.tgz", + "integrity": "sha512-FuTptgKwY6iNuU15nrIJDLjXzCChWB+T4AvksRtwPS/WZ3HuP1CElCm1t+OBfgQKfWbtZIawip+61k7+buRKAg==", + "dependencies": { + "robust-scale": "^1.0.2", + "robust-subtract": "^1.0.0", + "robust-sum": "^1.0.0", + "two-product": "^1.0.2" + } + }, + "node_modules/robust-point-in-polygon": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/robust-point-in-polygon/-/robust-point-in-polygon-1.0.3.tgz", + "integrity": "sha512-pPzz7AevOOcPYnFv4Vs5L0C7BKOq6C/TfAw5EUE58CylbjGiPyMjAnPLzzSuPZ2zftUGwWbmLWPOjPOz61tAcA==", + "dependencies": { + "robust-orientation": "^1.0.2" + } + }, + "node_modules/robust-scale": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/robust-scale/-/robust-scale-1.0.2.tgz", + "integrity": "sha512-jBR91a/vomMAzazwpsPTPeuTPPmWBacwA+WYGNKcRGSh6xweuQ2ZbjRZ4v792/bZOhRKXRiQH0F48AvuajY0tQ==", + "dependencies": { + "two-product": "^1.0.2", + "two-sum": "^1.0.0" + } + }, + "node_modules/robust-subtract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-subtract/-/robust-subtract-1.0.0.tgz", + "integrity": "sha512-xhKUno+Rl+trmxAIVwjQMiVdpF5llxytozXJOdoT4eTIqmqsndQqFb1A0oiW3sZGlhMRhOi6pAD4MF1YYW6o/A==" + }, + "node_modules/robust-sum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/robust-sum/-/robust-sum-1.0.0.tgz", + "integrity": "sha512-AvLExwpaqUqD1uwLU6MwzzfRdaI6VEZsyvQ3IAQ0ZJ08v1H+DTyqskrf2ZJyh0BDduFVLN7H04Zmc+qTiahhAw==" + }, "node_modules/rollup": { "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", @@ -11607,6 +12043,20 @@ "readable-stream": "3" } }, + "node_modules/tiff": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/tiff/-/tiff-5.0.3.tgz", + "integrity": "sha512-R0WckwRGhawWDNdha8iPQCjHyOiaEEmfFjhmalUVCIEELsON7Y/XO3eeGmBkoCXQp0Gg2nmTozN92Z4hlwbsow==", + "dependencies": { + "iobuffer": "^5.0.4", + "pako": "^2.0.4" + } + }, + "node_modules/tiff/node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/tiny-invariant": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", @@ -11750,6 +12200,16 @@ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, + "node_modules/two-product": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/two-product/-/two-product-1.0.2.tgz", + "integrity": "sha512-vOyrqmeYvzjToVM08iU52OFocWT6eB/I5LUWYnxeAPGXAhAxXYU/Yr/R2uY5/5n4bvJQL9AQulIuxpIsMoT8XQ==" + }, + "node_modules/two-sum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/two-sum/-/two-sum-1.0.0.tgz", + "integrity": "sha512-phP48e8AawgsNUjEY2WvoIWqdie8PoiDZGxTDv70LDr01uX5wLEQbOgSP7Z/B6+SW5oLtbe8qaYX2fKJs3CGTw==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -12399,6 +12859,11 @@ "loose-envify": "^1.0.0" } }, + "node_modules/web-worker-manager": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/web-worker-manager/-/web-worker-manager-0.2.0.tgz", + "integrity": "sha512-WmGabA4GLth1ju9VLm/oMDcPMhMngHoBSdY1OMhrEJvNsPl7z2p+7RBOXjEi5zlP0dK+Shd3Wm+BdD5WZrNYBA==" + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -13191,6 +13656,7 @@ "version": "0.0.0", "license": "ISC", "dependencies": { + "image-js": "^0.35.5", "pdf-lib": "^1.17.1", "pdfjs-dist": "^4.0.189" } diff --git a/shared-operations/functions/createSubDocument.js b/shared-operations/functions/createSubDocument.ts similarity index 84% rename from shared-operations/functions/createSubDocument.js rename to shared-operations/functions/createSubDocument.ts index 8347ee40e..ffe67e36c 100644 --- a/shared-operations/functions/createSubDocument.js +++ b/shared-operations/functions/createSubDocument.ts @@ -1,7 +1,7 @@ import { PDFDocument } from 'pdf-lib'; -export async function createSubDocument(pdfDoc, pagesToExtractArray) { +export async function createSubDocument(pdfDoc: PDFDocument, pagesToExtractArray: number[]): Promise { const subDocument = await PDFDocument.create(); // Check that array max number is not larger pdf pages number diff --git a/shared-operations/functions/detectEmptyPages.js b/shared-operations/functions/detectEmptyPages.js deleted file mode 100644 index fab1d0312..000000000 --- a/shared-operations/functions/detectEmptyPages.js +++ /dev/null @@ -1,62 +0,0 @@ -import { getImagesOnPage } from "./getImagesOnPage.js"; -import PDFJS from 'pdfjs-dist'; - -export async function detectEmptyPages(snapshot, whiteThreashold, OpenCV) { - const pdfDoc = await PDFJS.getDocument(snapshot).promise; - - const emptyPages = []; - for (let i = 1; i <= pdfDoc.numPages; i++) { - const page = await pdfDoc.getPage(i); - console.log("Checking page " + i); - - if(!await hasText(page)) { - console.log(`Found text on Page ${i}, page is not empty`); - continue; - } - - if(!await areImagesBlank(page, whiteThreashold)) { - console.log(`Found non white image on Page ${i}, page is not empty`); - continue; - } - - console.log(`Page ${i} is empty.`); - emptyPages.push(i - 1); - } - return emptyPages; - - async function hasText(page) { - const textContent = await page.getTextContent(); - return textContent.items.length === 0; - } - - async function areImagesBlank(page, threshold) { - const images = await getImagesOnPage(page); - for (const image of images) { - if(!isImageBlank(image, threshold)) - return false; - } - return true; - } - - function isImageBlank(image, threshold) { - const src = new OpenCV.cv.Mat(image.width, image.height, OpenCV.cv.CV_8UC4); - src.data.set(image.data); - // Convert the image to grayscale - const gray = new OpenCV.cv.Mat(); - OpenCV.cv.cvtColor(src, gray, OpenCV.cv.COLOR_RGBA2GRAY); - - // Calculate the mean value of the grayscale image - const meanValue = OpenCV.cv.mean(gray); - - // Free memory - src.delete(); - gray.delete(); - - // Check if the mean value is below the threshold - if (meanValue[0] <= threshold) { - return true; - } else { - return false; - } - } -} \ No newline at end of file diff --git a/shared-operations/functions/detectEmptyPages.ts b/shared-operations/functions/detectEmptyPages.ts new file mode 100644 index 000000000..b394b884a --- /dev/null +++ b/shared-operations/functions/detectEmptyPages.ts @@ -0,0 +1,50 @@ +import { DocumentInitParameters, PDFPageProxy } from "pdfjs-dist/types/src/display/api.js"; +import PDFJS from 'pdfjs-dist'; +import { Image } from 'image-js'; + +import { getImagesOnPage } from "./getImagesOnPage.js"; + +export async function detectEmptyPages(snapshot: string | URL | ArrayBuffer | DocumentInitParameters, whiteThreashold: number) { + const pdfDoc = await PDFJS.getDocument(snapshot).promise; + + const emptyPages: number[] = []; + for (let i = 1; i <= pdfDoc.numPages; i++) { + const page = await pdfDoc.getPage(i); + console.log("Checking page " + i); + + if(!await hasText(page)) { + console.log(`Found text on Page ${i}, page is not empty`); + continue; + } + + if(!await areImagesBlank(page, whiteThreashold)) { + console.log(`Found non white image on Page ${i}, page is not empty`); + continue; + } + + console.log(`Page ${i} is empty.`); + emptyPages.push(i - 1); + } + return emptyPages; +} + +async function hasText(page: PDFPageProxy): Promise { + const textContent = await page.getTextContent(); + return textContent.items.length === 0; +} + +async function areImagesBlank(page: PDFPageProxy, threshold: number): Promise { + const images = await getImagesOnPage(page); + for (const image of images) { + if(!await isImageBlank(image, threshold)) + return false; + } + return true; +} + +async function isImageBlank(image: string | Uint8Array | ArrayBuffer, threshold: number): Promise { + var img = await Image.load(image); + var grey = img.grey(); + var mean = grey.getMean(); + return mean[0] <= threshold; +} \ No newline at end of file diff --git a/shared-operations/functions/editMetadata.js b/shared-operations/functions/editMetadata.js deleted file mode 100644 index 2703c5b6b..000000000 --- a/shared-operations/functions/editMetadata.js +++ /dev/null @@ -1,55 +0,0 @@ - -import { PDFDocument, ParseSpeeds } from 'pdf-lib'; - - -/** - * @typedef {Object} Metadata - * @property {string | null | undefined} Title - The title of the document. - * @property {string | null | undefined} Author - The author of the document. - * @property {string | null | undefined} Subject - The subject of the document. - * @property {string[] | null | undefined} Keywords - An array of keywords associated with the document. - * @property {string | null | undefined} Producer - The producer of the document. - * @property {string | null | undefined} Creator - The creator of the document. - * @property {Date | null | undefined} CreationDate - The date when the document was created. - * @property {Date | null | undefined} ModificationDate - The date when the document was last modified. - */ - -/** - * - * @param {Uint16Array} snapshot - * @param {Metadata} metadata - Set property to null or "" to clear, undefined properties will be skipped. - * @returns Promise - */ -export async function editMetadata(snapshot, metadata) { - // Load the original PDF file - const pdfDoc = await PDFDocument.load(snapshot, { - parseSpeed: ParseSpeeds.Fastest, - }); - - if(metadata.Title !== undefined) - pdfDoc.setTitle(metadata.Title); - - if(metadata.Author !== undefined) - pdfDoc.setAuthor(metadata.Author) - - if(metadata.Subject !== undefined) - pdfDoc.setSubject(metadata.Subject) - - if(metadata.Keywords !== undefined) - pdfDoc.setKeywords(metadata.Keywords) - - if(metadata.Producer !== undefined) - pdfDoc.setProducer(metadata.Producer) - - if(metadata.Creator !== undefined) - pdfDoc.setCreator(metadata.Creator) - - if(metadata.CreationDate !== undefined) - pdfDoc.setCreationDate(metadata.CreationDate) - - if(metadata.ModificationDate !== undefined) - pdfDoc.setModificationDate(metadata.ModificationDate) - - // Serialize the modified document - return pdfDoc.save(); -}; \ No newline at end of file diff --git a/shared-operations/functions/editMetadata.ts b/shared-operations/functions/editMetadata.ts new file mode 100644 index 000000000..18ee16ac5 --- /dev/null +++ b/shared-operations/functions/editMetadata.ts @@ -0,0 +1,53 @@ + +import { PDFDocument, ParseSpeeds } from 'pdf-lib'; + + +export type Metadata = { + Title: string | null | undefined; // The title of the document. + Author: string | null | undefined; // The author of the document. + Subject: string | null | undefined; // The subject of the document. + Keywords: string[] | null | undefined; // An array of keywords associated with the document. + Producer: string | null | undefined; // The producer of the document. + Creator: string | null | undefined; // The creator of the document. + CreationDate: Date | null | undefined; // The date when the document was created. + ModificationDate: Date | null | undefined; // The date when the document was last modified. +} +/** + * + * @param {Uint16Array} snapshot + * @param {Metadata} metadata - Set property to null or "" to clear, undefined properties will be skipped. + * @returns Promise + */ +export async function editMetadata(snapshot: string | Uint8Array | ArrayBuffer, metadata: Metadata): Promise { + // Load the original PDF file + const pdfDoc = await PDFDocument.load(snapshot, { + parseSpeed: ParseSpeeds.Fastest, + }); + + if(metadata.Title) + pdfDoc.setTitle(metadata.Title); + + if(metadata.Author) + pdfDoc.setAuthor(metadata.Author) + + if(metadata.Subject) + pdfDoc.setSubject(metadata.Subject) + + if(metadata.Keywords) + pdfDoc.setKeywords(metadata.Keywords) + + if(metadata.Producer) + pdfDoc.setProducer(metadata.Producer) + + if(metadata.Creator) + pdfDoc.setCreator(metadata.Creator) + + if(metadata.CreationDate) + pdfDoc.setCreationDate(metadata.CreationDate) + + if(metadata.ModificationDate) + pdfDoc.setModificationDate(metadata.ModificationDate) + + // Serialize the modified document + return pdfDoc.save(); +}; \ No newline at end of file diff --git a/shared-operations/functions/extractPages.js b/shared-operations/functions/extractPages.ts similarity index 68% rename from shared-operations/functions/extractPages.js rename to shared-operations/functions/extractPages.ts index 8fd971299..8b35018c3 100644 --- a/shared-operations/functions/extractPages.js +++ b/shared-operations/functions/extractPages.ts @@ -2,7 +2,7 @@ import { PDFDocument } from 'pdf-lib'; import { createSubDocument } from './createSubDocument'; -export async function extractPages(snapshot, pagesToExtractArray) { +export async function extractPages(snapshot: string | Uint8Array | ArrayBuffer, pagesToExtractArray: number[]): Promise{ const pdfDoc = await PDFDocument.load(snapshot) // TODO: invent a better format for pagesToExtractArray and convert it. diff --git a/shared-operations/functions/getImagesOnPage.js b/shared-operations/functions/getImagesOnPage.ts similarity index 54% rename from shared-operations/functions/getImagesOnPage.js rename to shared-operations/functions/getImagesOnPage.ts index 2f0977f44..3a8ef7f30 100644 --- a/shared-operations/functions/getImagesOnPage.js +++ b/shared-operations/functions/getImagesOnPage.ts @@ -1,11 +1,12 @@ +import { PDFPageProxy } from "pdfjs-dist/types/src/display/api.js"; import PDFJS from 'pdfjs-dist'; -export async function getImagesOnPage(page) { +export async function getImagesOnPage(page: PDFPageProxy) { const ops = await page.getOperatorList(); - const images = []; + const images: any = []; for (var j=0; j < ops.fnArray.length; j++) { - if (ops.fnArray[j] == PDFJS.OPS.paintJpegXObject || ops.fnArray[j] == PDFJS.OPS.paintImageXObject) { + if (ops.fnArray[j] == PDFJS.OPS.paintImageXObject) { const image = page.objs.get(ops.argsArray[j][0]); images.push(image); } diff --git a/shared-operations/functions/impose.js b/shared-operations/functions/impose.ts similarity index 100% rename from shared-operations/functions/impose.js rename to shared-operations/functions/impose.ts diff --git a/shared-operations/functions/mergePDFs.js b/shared-operations/functions/mergePDFs.ts similarity index 79% rename from shared-operations/functions/mergePDFs.js rename to shared-operations/functions/mergePDFs.ts index 3799d9fc5..ef4a30a44 100644 --- a/shared-operations/functions/mergePDFs.js +++ b/shared-operations/functions/mergePDFs.ts @@ -1,7 +1,7 @@ import { PDFDocument } from 'pdf-lib'; -export const mergePDFs = async (snapshots) => { +export async function mergePDFs(snapshots: (string | Uint8Array | ArrayBuffer)[]): Promise { const mergedPdf = await PDFDocument.create(); diff --git a/shared-operations/functions/organizePages.js b/shared-operations/functions/organizePages.ts similarity index 85% rename from shared-operations/functions/organizePages.js rename to shared-operations/functions/organizePages.ts index b92d975c9..33b0054fa 100644 --- a/shared-operations/functions/organizePages.js +++ b/shared-operations/functions/organizePages.ts @@ -1,19 +1,17 @@ import { PDFDocument } from 'pdf-lib'; -/** - * @typedef {"CUSTOM_PAGE_ORDER"|"REVERSE_ORDER"|"DUPLEX_SORT"|"BOOKLET_SORT"|"ODD_EVEN_SPLIT"|"REMOVE_FIRST"|"REMOVE_LAST"|"REMOVE_FIRST_AND_LAST"} OrderOperation - */ - -/** - * - * @param {Uint16Array} snapshot - * @param {OrderOperation} operation - * @param {string} customOrderString - * @param {import('pdf-lib')} PDFLib - * @returns - */ -export async function organizePages(snapshot, operation, customOrderString) { +export async function organizePages( + snapshot: string | Uint8Array | ArrayBuffer, + operation: "CUSTOM_PAGE_ORDER" | + "REVERSE_ORDER" | + "DUPLEX_SORT" | + "BOOKLET_SORT" | + "ODD_EVEN_SPLIT" | + "REMOVE_FIRST" | + "REMOVE_LAST" | + "REMOVE_FIRST_AND_LAST", + customOrderString: string): Promise { const pdfDoc = await PDFDocument.load(snapshot); let subDocument = await PDFDocument.create(); const copiedPages = await subDocument.copyPages(pdfDoc, pdfDoc.getPageIndices()); @@ -90,8 +88,8 @@ export async function organizePages(snapshot, operation, customOrderString) { return subDocument.save(); }; -function parseCustomPageOrder(customOrder, pageCount) { - const pageOrderArray = []; +function parseCustomPageOrder(customOrder: string, pageCount: number) { + const pageOrderArray: number[] = []; const ranges = customOrder.split(','); ranges.forEach((range) => { diff --git a/shared-operations/functions/removeBlankPages.js b/shared-operations/functions/removeBlankPages.ts similarity index 95% rename from shared-operations/functions/removeBlankPages.js rename to shared-operations/functions/removeBlankPages.ts index 5e97e1c7c..0e47d8fcb 100644 --- a/shared-operations/functions/removeBlankPages.js +++ b/shared-operations/functions/removeBlankPages.ts @@ -1,9 +1,9 @@ import { PDFDocument } from 'pdf-lib'; import { detectEmptyPages } from "./detectEmptyPages.js"; -export async function removeBlankPages(snapshot, whiteThreashold, OpenCV) { +export async function removeBlankPages(snapshot, whiteThreashold) { - const emptyPages = await detectEmptyPages(snapshot, whiteThreashold, OpenCV); + const emptyPages = await detectEmptyPages(snapshot, whiteThreashold); console.log("Empty Pages: ", emptyPages); diff --git a/shared-operations/functions/rotatePages.js b/shared-operations/functions/rotatePages.ts similarity index 77% rename from shared-operations/functions/rotatePages.js rename to shared-operations/functions/rotatePages.ts index 73bcb481a..7a0a4b5de 100644 --- a/shared-operations/functions/rotatePages.js +++ b/shared-operations/functions/rotatePages.ts @@ -1,7 +1,7 @@ import { PDFDocument, ParseSpeeds, degrees } from 'pdf-lib'; -export async function rotatePages(snapshot, rotation) { +export async function rotatePages(snapshot: string | Uint8Array | ArrayBuffer, rotation: number): Promise { // Load the original PDF file const pdfDoc = await PDFDocument.load(snapshot, { parseSpeed: ParseSpeeds.Fastest, diff --git a/shared-operations/functions/scaleContent.js b/shared-operations/functions/scaleContent.ts similarity index 86% rename from shared-operations/functions/scaleContent.js rename to shared-operations/functions/scaleContent.ts index 6fc21edba..8592d0851 100644 --- a/shared-operations/functions/scaleContent.js +++ b/shared-operations/functions/scaleContent.ts @@ -1,7 +1,7 @@ import { PDFDocument, ParseSpeeds } from 'pdf-lib'; -export async function scaleContent(snapshot, scaleFactor) { +export async function scaleContent(snapshot: string | Uint8Array | ArrayBuffer, scaleFactor: number): Promise { // Load the original PDF file const pdfDoc = await PDFDocument.load(snapshot, { parseSpeed: ParseSpeeds.Fastest, diff --git a/shared-operations/functions/scalePage.js b/shared-operations/functions/scalePage.ts similarity index 81% rename from shared-operations/functions/scalePage.js rename to shared-operations/functions/scalePage.ts index cfe5d6216..5e47adff9 100644 --- a/shared-operations/functions/scalePage.js +++ b/shared-operations/functions/scalePage.ts @@ -1,7 +1,7 @@ import { PDFDocument, ParseSpeeds } from 'pdf-lib'; -export async function scalePage(snapshot, pageSize) { +export async function scalePage(snapshot: string | Uint8Array | ArrayBuffer, pageSize: {width:number,height:number}): Promise { // Load the original PDF file const pdfDoc = await PDFDocument.load(snapshot, { parseSpeed: ParseSpeeds.Fastest, diff --git a/shared-operations/functions/splitOn.js b/shared-operations/functions/splitOn.ts similarity index 77% rename from shared-operations/functions/splitOn.js rename to shared-operations/functions/splitOn.ts index cc779b738..dd8bb86d0 100644 --- a/shared-operations/functions/splitOn.js +++ b/shared-operations/functions/splitOn.ts @@ -1,60 +1,52 @@ -import { detectEmptyPages } from "./shared/detectEmptyPages.js"; -import { getImagesOnPage } from "./shared/getImagesOnPage.js"; -import { createSubDocument } from "./shared/createSubDocument.js"; + +import { PDFDocument } from 'pdf-lib'; import PDFJS from 'pdfjs-dist'; -/** - * @typedef {"BAR_CODE"|"QR_CODE"|"BLANK_PAGE"} SplitType - */ +import { detectEmptyPages } from "./detectEmptyPages.js"; +import { getImagesOnPage } from "./getImagesOnPage.js"; +import { createSubDocument } from "./createSubDocument.js"; +import { TypedArray, DocumentInitParameters } from 'pdfjs-dist/types/src/display/api.js'; -/** - * - * @param {Uint16Array} snapshot - * @param {SplitType} type - * @param {} PDFJS - * @param {import('opencv-wasm')} OpenCV - * @param {} PDFLib - * @returns - */ -export async function splitOn(snapshot, type, whiteThreashold, OpenCV, PDFLib, jsQR) { - - let splitAtPages = []; +export async function splitOn( + snapshot: string | ArrayBuffer | Uint8Array, + type: "BAR_CODE"|"QR_CODE"|"BLANK_PAGE", + whiteThreashold: number, + jsQR: (arg0: any, arg1: number, arg2: number) => any) { + let splitAtPages: number[] = []; switch (type) { case "BAR_CODE": // TODO: Implement throw new Error("This split-type has not been implemented yet"); - break; case "QR_CODE": splitAtPages = await getPagesWithQRCode(snapshot); break; case "BLANK_PAGE": - splitAtPages = await detectEmptyPages(snapshot, whiteThreashold, OpenCV); + splitAtPages = await detectEmptyPages(snapshot, whiteThreashold); break; default: - throw new Error("An invalid split-type was provided.") - break; + throw new Error("An invalid split-type was provided."); } console.log("Split At Pages: ", splitAtPages); // Remove detected Pages & Split - const pdfDoc = await PDFLib.PDFDocument.load(snapshot); + const pdfDoc = await PDFDocument.load(snapshot); const numberOfPages = pdfDoc.getPages().length; - let pagesArray = []; + let pagesArray: number[] = []; let splitAfter = splitAtPages.shift(); - const subDocuments = []; + const subDocuments: Uint8Array[] = []; for (let i = 0; i < numberOfPages; i++) { console.log(i); if(i == splitAfter) { if(pagesArray.length > 0) { - subDocuments.push(await createSubDocument(pdfDoc, pagesArray, PDFLib)); + subDocuments.push(await createSubDocument(pdfDoc, pagesArray)); pagesArray = []; } splitAfter = splitAtPages.shift(); @@ -65,16 +57,16 @@ export async function splitOn(snapshot, type, whiteThreashold, OpenCV, PDFLib, j } } if(pagesArray.length > 0) { - subDocuments.push(await createSubDocument(pdfDoc, pagesArray, PDFLib)); + subDocuments.push(await createSubDocument(pdfDoc, pagesArray)); } pagesArray = []; return subDocuments; - async function getPagesWithQRCode(snapshot) { + async function getPagesWithQRCode(snapshot: string | ArrayBuffer | URL | TypedArray | DocumentInitParameters) { const pdfDoc = await PDFJS.getDocument(snapshot).promise; - const pagesWithQR = []; + const pagesWithQR: number[] = []; for (let i = 0; i < pdfDoc.numPages; i++) { console.log("Page:", i, "/", pdfDoc.numPages); const page = await pdfDoc.getPage(i + 1); diff --git a/shared-operations/functions/splitPDF.js b/shared-operations/functions/splitPDF.ts similarity index 70% rename from shared-operations/functions/splitPDF.js rename to shared-operations/functions/splitPDF.ts index 50280a33a..9519f2067 100644 --- a/shared-operations/functions/splitPDF.js +++ b/shared-operations/functions/splitPDF.ts @@ -1,9 +1,10 @@ import { PDFDocument } from 'pdf-lib'; -import { createSubDocument } from "./shared/extractPages.js"; +import { createSubDocument } from "./createSubDocument.js"; + +export async function splitPDF(snapshot: string | Uint8Array | ArrayBuffer, splitAfterPageArray: number[]): Promise { -export async function splitPDF(snapshot, splitAfterPageArray) { const pdfDoc = await PDFDocument.load(snapshot) const numberOfPages = pdfDoc.getPages().length; @@ -13,7 +14,7 @@ export async function splitPDF(snapshot, splitAfterPageArray) { const subDocuments = []; for (let i = 0; i < numberOfPages; i++) { - if(i > splitAfter && pagesArray.length > 0) { + if(splitAfter && i > splitAfter && pagesArray.length > 0) { subDocuments.push(await createSubDocument(pdfDoc, pagesArray)); splitAfter = splitAfterPageArray.shift(); pagesArray = []; diff --git a/shared-operations/package.json b/shared-operations/package.json index 7243ffb7c..d9d98cdd1 100644 --- a/shared-operations/package.json +++ b/shared-operations/package.json @@ -9,6 +9,7 @@ "author": "", "license": "ISC", "dependencies": { + "image-js": "^0.35.5", "pdf-lib": "^1.17.1", "pdfjs-dist": "^4.0.189" }