From 9c1588d1506d1d194e90bc91e6fda8c0e4225be7 Mon Sep 17 00:00:00 2001 From: sbplat <71648843+sbplat@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:17:54 -0500 Subject: [PATCH] refactor: apply eslint --- .eslintrc.js | 17 +- client-tauri/src/App.tsx | 98 +++---- .../src/components/DynamicParameterFields.tsx | 42 +-- client-tauri/src/components/NavBar.tsx | 260 +++++++++--------- .../src/components/toolbar/LanguagePicker.tsx | 44 +-- .../src/declarations/shared-operations.d.ts | 2 +- client-tauri/src/main.tsx | 10 +- client-tauri/src/pages/About.tsx | 10 +- client-tauri/src/pages/Dashboard.tsx | 10 +- client-tauri/src/pages/Home.tsx | 6 +- client-tauri/src/pages/NoMatch.tsx | 16 +- client-tauri/src/pages/convert/ToPdf.tsx | 2 +- .../src/pages/page-operations/Impose.tsx | 2 +- client-tauri/src/utils/file-utils.ts | 2 +- client-tauri/src/utils/libre-office-utils.tsx | 12 +- client-tauri/src/utils/pdf-operations.ts | 8 +- client-tauri/src/utils/tauri-wrapper.ts | 58 ++-- client-tauri/vite.config.ts | 42 +-- server-node/src/index.ts | 10 +- server-node/src/routes/api/api-controller.ts | 6 +- .../api/dynamic-operations-controller.ts | 26 +- .../src/routes/api/workflow-controller.ts | 34 +-- server-node/src/utils/endpoint-utils.ts | 24 +- server-node/src/utils/libre-office-utils.ts | 22 +- shared-operations/declarations/pdfcpu.d.ts | 2 +- .../src/functions/arrangePages.ts | 12 +- .../src/functions/common/detectEmptyPages.ts | 10 +- .../src/functions/common/detectQRCodePages.ts | 4 +- .../src/functions/common/getImagesOnPage.ts | 8 +- .../src/functions/common/getPagesByIndex.ts | 4 +- .../functions/common/pageIndexesSorting.ts | 18 +- .../src/functions/common/pageIndexesUtils.ts | 18 +- .../src/functions/common/sortPdfArray.ts | 72 ++--- .../src/functions/common/splitPagesByIndex.ts | 4 +- .../src/functions/extractPages.ts | 12 +- shared-operations/src/functions/impose.ts | 22 +- shared-operations/src/functions/index.ts | 4 +- shared-operations/src/functions/mergePDFs.ts | 10 +- .../src/functions/removeBlankPages.ts | 14 +- .../src/functions/removePages.ts | 10 +- .../src/functions/rotatePages.ts | 18 +- .../src/functions/scaleContent.ts | 12 +- shared-operations/src/functions/scalePage.ts | 30 +- .../src/functions/splitPagesByPreset.ts | 32 +-- .../src/functions/splitPdfByIndex.ts | 10 +- .../src/functions/updateMetadata.ts | 34 +-- .../src/locales/i18next.config.ts | 10 +- .../src/workflow/getOperatorByName.ts | 6 +- .../src/workflow/organizeWaitOperations.ts | 10 +- .../src/workflow/traverseOperations.ts | 38 +-- .../src/workflow/validateOperations.ts | 4 +- shared-operations/src/wrappers/PdfFile.ts | 90 +++--- shared-operations/src/wrappers/PdfFileJoi.ts | 2 +- 53 files changed, 647 insertions(+), 636 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b9ca50cb9..3d0e38f78 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,7 +4,9 @@ module.exports = { "es2021": true }, "extends": [ - "plugin:@typescript-eslint/strict" + "eslint:recommended", + "plugin:@typescript-eslint/strict-type-checked", + "plugin:@typescript-eslint/stylistic-type-checked" ], "overrides": [ { @@ -22,7 +24,12 @@ module.exports = { "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", - "sourceType": "module" + "sourceType": "module", + "project": [ + "./client-tauri/tsconfig.json", + "./server-node/tsconfig.json", + "./shared-operations/tsconfig.json" + ] }, "plugins": [ "@typescript-eslint" @@ -47,7 +54,11 @@ module.exports = { ], "semi": [ "error", - "always" + "always", + { + "omitLastInOneLineBlock": true, + "omitLastInOneLineClassBody": true + } ] } }; diff --git a/client-tauri/src/App.tsx b/client-tauri/src/App.tsx index 46494d33f..338324903 100644 --- a/client-tauri/src/App.tsx +++ b/client-tauri/src/App.tsx @@ -1,80 +1,80 @@ -import { Suspense } from 'react'; +import { Suspense } from "react"; import { Routes, Route, Outlet } from "react-router-dom"; import Home from "./pages/Home"; import About from "./pages/About"; import Dashboard from "./pages/Dashboard"; -import ToPdf from "./pages/convert/ToPdf" -import Impose from "./pages/page-operations/Impose" +import ToPdf from "./pages/convert/ToPdf"; +import Impose from "./pages/page-operations/Impose"; import NoMatch from "./pages/NoMatch"; import NavBar from "./components/NavBar"; -import 'bootstrap/dist/css/bootstrap.min.css'; +import "bootstrap/dist/css/bootstrap.min.css"; import { Container } from "react-bootstrap"; import i18n from "i18next"; import { useTranslation, initReactI18next } from "react-i18next"; -import LanguageDetector from 'i18next-browser-languagedetector'; -import ar from './locales/ar.json'; -import en from './locales/en.json'; +import LanguageDetector from "i18next-browser-languagedetector"; +import ar from "./locales/ar.json"; +import en from "./locales/en.json"; -import './general.css' +import "./general.css"; i18n - .use(LanguageDetector) - .use(initReactI18next) // passes i18n down to react-i18next - .init({ - fallbackLng: "en", - resources: { ar,en }, - }); + .use(LanguageDetector) + .use(initReactI18next) // passes i18n down to react-i18next + .init({ + fallbackLng: "en", + resources: { ar,en }, + }); export default function App() { - return ( - - {/* Routes nest inside one another. Nested route paths build upon + return ( + + {/* Routes nest inside one another. Nested route paths build upon parent route paths, and nested route elements render inside parent route elements. See the note about below. */} - - }> - } /> - } /> - } /> + + }> + } /> + } /> + } /> - {/* Using path="*"" means "match anything", so this route + {/* Using path="*"" means "match anything", so this route acts like a catch-all for URLs that we don't have explicit routes for. */} - } /> - - }> - } /> - } /> - - }> - } /> - } /> - - - - ); + } /> + + }> + } /> + } /> + + }> + } /> + } /> + + + + ); } function Layout() { - const { t } = useTranslation(); - return ( -
- + const { t } = useTranslation(); + return ( +
+ - {/* An renders whatever child route is currently active, + {/* An renders whatever child route is currently active, so you can think about this as a placeholder for the child routes we defined above. */} - -
-
- -
+ +
+
+ +
+
+
-
-
- ); + ); } diff --git a/client-tauri/src/components/DynamicParameterFields.tsx b/client-tauri/src/components/DynamicParameterFields.tsx index 6832c6248..97437508b 100644 --- a/client-tauri/src/components/DynamicParameterFields.tsx +++ b/client-tauri/src/components/DynamicParameterFields.tsx @@ -1,7 +1,7 @@ -import Form from 'react-bootstrap/Form'; -import { useTranslation } from 'react-i18next'; -import { FieldConstraint, RecordConstraint } from '@stirling-pdf/shared-operations/src/dynamic-ui/OperatorConstraints' +import Form from "react-bootstrap/Form"; +import { useTranslation } from "react-i18next"; +import { FieldConstraint, RecordConstraint } from "@stirling-pdf/shared-operations/src/dynamic-ui/OperatorConstraints"; interface DynamicParameterFieldsProps { constraints: RecordConstraint; @@ -13,15 +13,15 @@ const DynamicParameterFields: React.FC = ({constrai return (<> {Object.entries(constraints.record).map(([fieldName, value]) => { - console.log(fieldName, value) + console.log(fieldName, value); const globallyUniqueId = joinKeyPath([...parentKeyPath, fieldName]); return
{fieldConstraintToElement(fieldName, parentKeyPath, globallyUniqueId, value)} -
+
; })} ); -} +}; function joinKeyPath(keyPath: string[]) { return keyPath.join("."); @@ -29,7 +29,7 @@ function joinKeyPath(keyPath: string[]) { function fieldConstraintToElement(fieldName: string, parentKeyPath: string[], globallyUniqueId: string, fieldConstraint: FieldConstraint) { if (Array.isArray(fieldConstraint.type)) { - if (fieldConstraint.type.every(e => typeof e == 'string' || typeof e == 'number')) { + if (fieldConstraint.type.every(e => typeof e == "string" || typeof e == "number")) { return ( @@ -37,27 +37,27 @@ function fieldConstraintToElement(fieldName: string, parentKeyPath: string[], gl ); } else { - return
Error: Field type '{fieldConstraint.type}' not supported
+ return
Error: Field type '{fieldConstraint.type}' not supported
; } - } else if (typeof fieldConstraint.type == 'string') { + } else if (typeof fieldConstraint.type == "string") { switch (fieldConstraint.type) { - case "file.pdf": - return ; - case "files.pdf": - return ; - case "string": - return ; - case "number": - return ; - default: - return
Error: Field type '{fieldConstraint.type}' not supported
+ case "file.pdf": + return ; + case "files.pdf": + return ; + case "string": + return ; + case "number": + return ; + default: + return
Error: Field type '{fieldConstraint.type}' not supported
; } } else if (fieldConstraint.type instanceof RecordConstraint) { //return - return
Error: Field type 'RecordConstraint' not supported yet!
+ return
Error: Field type 'RecordConstraint' not supported yet!
; } - return
Error: Field type '{fieldConstraint.type}' not supported
+ return
Error: Field type '{fieldConstraint.type}' not supported
; } export default DynamicParameterFields; \ No newline at end of file diff --git a/client-tauri/src/components/NavBar.tsx b/client-tauri/src/components/NavBar.tsx index 4faca2c52..91451298b 100644 --- a/client-tauri/src/components/NavBar.tsx +++ b/client-tauri/src/components/NavBar.tsx @@ -2,25 +2,25 @@ import { AiOutlineMergeCells, AiOutlineSplitCells } from "react-icons/ai"; import { BiCrop, BiSprayCan } from "react-icons/bi"; import { - BsTools, BsSortNumericDown, BsArrowClockwise, BsFileEarmarkX, BsLayoutSplit, BsPalette, BsArrowUpSquare, Bs1Square, BsFileEarmarkPdf, - BsArrowLeftRight, BsFileEarmarkImage, BsFileEarmark, BsFiletypeHtml, BsLink, BsFiletypeMd, BsFileEarmarkWord, BsFiletypePpt, BsFiletypeTxt, - BsFiletypeXml, BsLock, BsUnlock, BsShieldLock, BsDroplet, BsAward, BsEraserFill, BsCardList, BsClipboardData, BsFile, BsFileEarmarkRichtext, - BsFileZip, BsFiletypeJs, BsFonts, BsImages, BsInfoCircle, BsSearch, BsShieldCheck, BsVectorPen, BsWrench, BsArrowsCollapse, BsGrid, Bs123, - BsArrowsFullscreen + BsTools, BsSortNumericDown, BsArrowClockwise, BsFileEarmarkX, BsLayoutSplit, BsPalette, BsArrowUpSquare, Bs1Square, BsFileEarmarkPdf, + BsArrowLeftRight, BsFileEarmarkImage, BsFileEarmark, BsFiletypeHtml, BsLink, BsFiletypeMd, BsFileEarmarkWord, BsFiletypePpt, BsFiletypeTxt, + BsFiletypeXml, BsLock, BsUnlock, BsShieldLock, BsDroplet, BsAward, BsEraserFill, BsCardList, BsClipboardData, BsFile, BsFileEarmarkRichtext, + BsFileZip, BsFiletypeJs, BsFonts, BsImages, BsInfoCircle, BsSearch, BsShieldCheck, BsVectorPen, BsWrench, BsArrowsCollapse, BsGrid, Bs123, + BsArrowsFullscreen } from "react-icons/bs"; import { MdOutlineScanner, MdOutlineBalance } from "react-icons/md"; import { IconType } from "react-icons"; -import Container from 'react-bootstrap/Container'; -import Nav from 'react-bootstrap/Nav'; -import Navbar from 'react-bootstrap/Navbar'; -import NavDropdown from 'react-bootstrap/NavDropdown'; -import { LinkContainer } from 'react-router-bootstrap'; -import { useTranslation } from 'react-i18next'; +import Container from "react-bootstrap/Container"; +import Nav from "react-bootstrap/Nav"; +import Navbar from "react-bootstrap/Navbar"; +import NavDropdown from "react-bootstrap/NavDropdown"; +import { LinkContainer } from "react-router-bootstrap"; +import { useTranslation } from "react-i18next"; import LanguagePicker from "./toolbar/LanguagePicker"; -import Logo from '../../public/stirling-pdf-logo.svg' -import './NavBar.css'; +import Logo from "../../public/stirling-pdf-logo.svg"; +import "./NavBar.css"; interface NavInfoItem { displayText: string; @@ -31,143 +31,143 @@ interface NavInfoItem { interface NavInfoSublist { displayText: string; icon: IconType; - sublist: Array; + sublist: NavInfoItem[]; } function convertToNavLink(item: NavInfoItem, index: number) { - return {item.displayText}; + return {item.displayText}; } function convertToNavDropdownItem(item: NavInfoItem | null, index: number) { - if (item == null) - return ; + if (item == null) + return ; - return ( - - - - {item.displayText} - - - ); + return ( + + + + {item.displayText} + + + ); } function convertToNavDropdown(sublist: NavInfoSublist, index: number) { - var myTitle = <> - - - {sublist.displayText} - - ; + const myTitle = <> + + + {sublist.displayText} + + ; - return ( - - {sublist.sublist.map((item, i) => convertToNavDropdownItem(item, i))} - - ); + return ( + + {sublist.sublist.map((item, i) => convertToNavDropdownItem(item, i))} + + ); } function NavBar() { - const { t } = useTranslation(); + const { t } = useTranslation(); - const navInfo = [ - {displayText: t('multiTool.title'), icon: BsTools, dest: "/home", tooltip: t('home.multiTool.desc')}, - {displayText: t('navbar.pageOps'), icon: BsFileEarmarkPdf, sublist: [ - { displayText: t('home.merge.title'), icon: AiOutlineMergeCells, dest: "/dashboard", tooltip: t('home.merge.desc') }, - { displayText: t('home.split.title'), icon: AiOutlineSplitCells, dest: "/about", tooltip: t('home.split.desc') }, - { displayText: t('home.pdfOrganiser.title'), icon: BsSortNumericDown, dest: "/nothing-here", tooltip: t('home.pdfOrganiser.desc') }, - { displayText: t('home.rotate.title'), icon: BsArrowClockwise, dest: "/nothing-here", tooltip: t('home.rotate.desc') }, - { displayText: t('home.removePages.title'), icon: BsFileEarmarkX, dest: "/nothing-here", tooltip: t('home.removePages.desc') }, - { displayText: t('home.pageLayout.title'), icon: BsGrid, dest: "/page-operations/impose", tooltip: t('home.pageLayout.desc') }, - { displayText: t('home.scalePages.title'), icon: BsArrowsFullscreen, dest: "/nothing-here", tooltip: t('home.scalePages.desc') }, - { displayText: t('home.autoSplitPDF.title'), icon: BsLayoutSplit, dest: "/nothing-here", tooltip: t('home.autoSplitPDF.desc') }, - { displayText: t('home.adjust-contrast.title'), icon: BsPalette, dest: "/nothing-here", tooltip: t('home.adjust-contrast.desc') }, - { displayText: t('home.crop.title'), icon: BiCrop, dest: "/nothing-here", tooltip: t('home.crop.desc') }, - { displayText: t('home.extractPage.title'), icon: BsArrowUpSquare, dest: "/nothing-here", tooltip: t('home.extractPage.desc') }, - { displayText: t('home.PdfToSinglePage.title'), icon: Bs1Square, dest: "/nothing-here", tooltip: t('home.PdfToSinglePage.desc') }, - ]}, - {displayText: t('navbar.convert'), icon: BsArrowLeftRight, sublist: [ - { displayText: t('home.imageToPdf.title'), icon: BsFileEarmarkImage, dest: "/dashboard", tooltip: t('home.imageToPdf.desc') }, - { displayText: t('home.fileToPDF.title'), icon: BsFileEarmark, dest: "/convert/file-to-pdf", tooltip: t('home.fileToPDF.desc') }, - { displayText: t('home.HTMLToPDF.title'), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t('home.HTMLToPDF.desc') }, - { displayText: t('home.URLToPDF.title'), icon: BsLink, dest: "/nothing-here", tooltip: t('home.URLToPDF.desc') }, - { displayText: t('home.MarkdownToPDF.title'), icon: BsFiletypeMd, dest: "/nothing-here", tooltip: t('home.MarkdownToPDF.desc') }, - null, - { displayText: t('home.pdfToImage.title'), icon: BsFileEarmarkImage, dest: "/nothing-here", tooltip: t('home.pdfToImage.desc') }, - { displayText: t('home.PDFToWord.title'), icon: BsFileEarmarkWord, dest: "/nothing-here", tooltip: t('home.PDFToWord.desc') }, - { displayText: t('home.PDFToPresentation.title'), icon: BsFiletypePpt, dest: "/nothing-here", tooltip: t('home.PDFToPresentation.desc') }, - { displayText: t('home.PDFToText.title'), icon: BsFiletypeTxt, dest: "/nothing-here", tooltip: t('home.PDFToText.desc') }, - { displayText: t('home.PDFToHTML.title'), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t('home.PDFToHTML.desc') }, - { displayText: t('home.PDFToXML.title'), icon: BsFiletypeXml, dest: "/nothing-here", tooltip: t('home.PDFToXML.desc') }, - { displayText: t('home.pdfToPDFA.title'), icon: BsFileEarmarkPdf, dest: "/nothing-here", tooltip: t('home.pdfToPDFA.desc') }, - ]}, - {displayText: t('navbar.security'), icon: BsShieldCheck, sublist: [ - { displayText: t('home.addPassword.title'), icon: BsLock, dest: "/dashboard", tooltip: t('home.addPassword.desc') }, - { displayText: t('home.removePassword.title'), icon: BsUnlock, dest: "/nothing-here", tooltip: t('home.removePassword.desc') }, - { displayText: t('home.permissions.title'), icon: BsShieldLock, dest: "/nothing-here", tooltip: t('home.permissions.desc') }, - { displayText: t('home.watermark.title'), icon: BsDroplet, dest: "/nothing-here", tooltip: t('home.watermark.desc') }, - { displayText: t('home.certSign.title'), icon: BsAward, dest: "/nothing-here", tooltip: t('home.certSign.desc') }, - { displayText: t('home.sanitizePdf.title'), icon: BiSprayCan, dest: "/nothing-here", tooltip: t('home.sanitizePdf.desc') }, - { displayText: t('home.autoRedact.title'), icon: BsEraserFill, dest: "/nothing-here", tooltip: t('home.autoRedact.desc') }, - ]}, - {displayText: t('navbar.other'), icon: BsCardList, sublist: [ - { displayText: t('home.ocr.title'), icon: BsSearch, dest: "/dashboard", tooltip: t('home.ocr.desc') }, - { displayText: t('home.addImage.title'), icon: BsFileEarmarkRichtext, dest: "/nothing-here", tooltip: t('home.addImage.desc') }, - { displayText: t('home.compressPdfs.title'), icon: BsFileZip, dest: "/nothing-here", tooltip: t('home.compressPdfs.desc') }, - { displayText: t('home.extractImages.title'), icon: BsImages, dest: "/nothing-here", tooltip: t('home.extractImages.desc') }, - { displayText: t('home.changeMetadata.title'), icon: BsClipboardData, dest: "/nothing-here", tooltip: t('home.changeMetadata.desc') }, - { displayText: t('home.ScannerImageSplit.title'), icon: MdOutlineScanner, dest: "/nothing-here", tooltip: t('home.ScannerImageSplit.desc') }, - { displayText: t('home.sign.title'), icon: BsVectorPen, dest: "/nothing-here", tooltip: t('home.sign.desc') }, - { displayText: t('home.flatten.title'), icon: BsArrowsCollapse, dest: "/nothing-here", tooltip: t('home.flatten.desc') }, - { displayText: t('home.repair.title'), icon: BsWrench, dest: "/nothing-here", tooltip: t('home.repair.desc') }, - { displayText: t('home.removeBlanks.title'), icon: BsFile, dest: "/nothing-here", tooltip: t('home.removeBlanks.desc') }, - { displayText: t('home.compare.title'), icon: MdOutlineBalance, dest: "/nothing-here", tooltip: t('home.compare.desc') }, - { displayText: t('home.add-page-numbers.title'), icon: Bs123, dest: "/nothing-here", tooltip: t('home.add-page-numbers.desc') }, - { displayText: t('home.auto-rename.title'), icon: BsFonts, dest: "/nothing-here", tooltip: t('home.auto-rename.desc') }, - { displayText: t('home.getPdfInfo.title'), icon: BsInfoCircle, dest: "/nothing-here", tooltip: t('home.getPdfInfo.desc') }, - { displayText: t('home.showJS.title'), icon: BsFiletypeJs, dest: "/nothing-here", tooltip: t('home.showJS.desc') }, - ]}, - ] as Array; + const navInfo = [ + {displayText: t("multiTool.title"), icon: BsTools, dest: "/home", tooltip: t("home.multiTool.desc")}, + {displayText: t("navbar.pageOps"), icon: BsFileEarmarkPdf, sublist: [ + { displayText: t("home.merge.title"), icon: AiOutlineMergeCells, dest: "/dashboard", tooltip: t("home.merge.desc") }, + { displayText: t("home.split.title"), icon: AiOutlineSplitCells, dest: "/about", tooltip: t("home.split.desc") }, + { displayText: t("home.pdfOrganiser.title"), icon: BsSortNumericDown, dest: "/nothing-here", tooltip: t("home.pdfOrganiser.desc") }, + { displayText: t("home.rotate.title"), icon: BsArrowClockwise, dest: "/nothing-here", tooltip: t("home.rotate.desc") }, + { displayText: t("home.removePages.title"), icon: BsFileEarmarkX, dest: "/nothing-here", tooltip: t("home.removePages.desc") }, + { displayText: t("home.pageLayout.title"), icon: BsGrid, dest: "/page-operations/impose", tooltip: t("home.pageLayout.desc") }, + { displayText: t("home.scalePages.title"), icon: BsArrowsFullscreen, dest: "/nothing-here", tooltip: t("home.scalePages.desc") }, + { displayText: t("home.autoSplitPDF.title"), icon: BsLayoutSplit, dest: "/nothing-here", tooltip: t("home.autoSplitPDF.desc") }, + { displayText: t("home.adjust-contrast.title"), icon: BsPalette, dest: "/nothing-here", tooltip: t("home.adjust-contrast.desc") }, + { displayText: t("home.crop.title"), icon: BiCrop, dest: "/nothing-here", tooltip: t("home.crop.desc") }, + { displayText: t("home.extractPage.title"), icon: BsArrowUpSquare, dest: "/nothing-here", tooltip: t("home.extractPage.desc") }, + { displayText: t("home.PdfToSinglePage.title"), icon: Bs1Square, dest: "/nothing-here", tooltip: t("home.PdfToSinglePage.desc") }, + ]}, + {displayText: t("navbar.convert"), icon: BsArrowLeftRight, sublist: [ + { displayText: t("home.imageToPdf.title"), icon: BsFileEarmarkImage, dest: "/dashboard", tooltip: t("home.imageToPdf.desc") }, + { displayText: t("home.fileToPDF.title"), icon: BsFileEarmark, dest: "/convert/file-to-pdf", tooltip: t("home.fileToPDF.desc") }, + { displayText: t("home.HTMLToPDF.title"), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t("home.HTMLToPDF.desc") }, + { displayText: t("home.URLToPDF.title"), icon: BsLink, dest: "/nothing-here", tooltip: t("home.URLToPDF.desc") }, + { displayText: t("home.MarkdownToPDF.title"), icon: BsFiletypeMd, dest: "/nothing-here", tooltip: t("home.MarkdownToPDF.desc") }, + null, + { displayText: t("home.pdfToImage.title"), icon: BsFileEarmarkImage, dest: "/nothing-here", tooltip: t("home.pdfToImage.desc") }, + { displayText: t("home.PDFToWord.title"), icon: BsFileEarmarkWord, dest: "/nothing-here", tooltip: t("home.PDFToWord.desc") }, + { displayText: t("home.PDFToPresentation.title"), icon: BsFiletypePpt, dest: "/nothing-here", tooltip: t("home.PDFToPresentation.desc") }, + { displayText: t("home.PDFToText.title"), icon: BsFiletypeTxt, dest: "/nothing-here", tooltip: t("home.PDFToText.desc") }, + { displayText: t("home.PDFToHTML.title"), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t("home.PDFToHTML.desc") }, + { displayText: t("home.PDFToXML.title"), icon: BsFiletypeXml, dest: "/nothing-here", tooltip: t("home.PDFToXML.desc") }, + { displayText: t("home.pdfToPDFA.title"), icon: BsFileEarmarkPdf, dest: "/nothing-here", tooltip: t("home.pdfToPDFA.desc") }, + ]}, + {displayText: t("navbar.security"), icon: BsShieldCheck, sublist: [ + { displayText: t("home.addPassword.title"), icon: BsLock, dest: "/dashboard", tooltip: t("home.addPassword.desc") }, + { displayText: t("home.removePassword.title"), icon: BsUnlock, dest: "/nothing-here", tooltip: t("home.removePassword.desc") }, + { displayText: t("home.permissions.title"), icon: BsShieldLock, dest: "/nothing-here", tooltip: t("home.permissions.desc") }, + { displayText: t("home.watermark.title"), icon: BsDroplet, dest: "/nothing-here", tooltip: t("home.watermark.desc") }, + { displayText: t("home.certSign.title"), icon: BsAward, dest: "/nothing-here", tooltip: t("home.certSign.desc") }, + { displayText: t("home.sanitizePdf.title"), icon: BiSprayCan, dest: "/nothing-here", tooltip: t("home.sanitizePdf.desc") }, + { displayText: t("home.autoRedact.title"), icon: BsEraserFill, dest: "/nothing-here", tooltip: t("home.autoRedact.desc") }, + ]}, + {displayText: t("navbar.other"), icon: BsCardList, sublist: [ + { displayText: t("home.ocr.title"), icon: BsSearch, dest: "/dashboard", tooltip: t("home.ocr.desc") }, + { displayText: t("home.addImage.title"), icon: BsFileEarmarkRichtext, dest: "/nothing-here", tooltip: t("home.addImage.desc") }, + { displayText: t("home.compressPdfs.title"), icon: BsFileZip, dest: "/nothing-here", tooltip: t("home.compressPdfs.desc") }, + { displayText: t("home.extractImages.title"), icon: BsImages, dest: "/nothing-here", tooltip: t("home.extractImages.desc") }, + { displayText: t("home.changeMetadata.title"), icon: BsClipboardData, dest: "/nothing-here", tooltip: t("home.changeMetadata.desc") }, + { displayText: t("home.ScannerImageSplit.title"), icon: MdOutlineScanner, dest: "/nothing-here", tooltip: t("home.ScannerImageSplit.desc") }, + { displayText: t("home.sign.title"), icon: BsVectorPen, dest: "/nothing-here", tooltip: t("home.sign.desc") }, + { displayText: t("home.flatten.title"), icon: BsArrowsCollapse, dest: "/nothing-here", tooltip: t("home.flatten.desc") }, + { displayText: t("home.repair.title"), icon: BsWrench, dest: "/nothing-here", tooltip: t("home.repair.desc") }, + { displayText: t("home.removeBlanks.title"), icon: BsFile, dest: "/nothing-here", tooltip: t("home.removeBlanks.desc") }, + { displayText: t("home.compare.title"), icon: MdOutlineBalance, dest: "/nothing-here", tooltip: t("home.compare.desc") }, + { displayText: t("home.add-page-numbers.title"), icon: Bs123, dest: "/nothing-here", tooltip: t("home.add-page-numbers.desc") }, + { displayText: t("home.auto-rename.title"), icon: BsFonts, dest: "/nothing-here", tooltip: t("home.auto-rename.desc") }, + { displayText: t("home.getPdfInfo.title"), icon: BsInfoCircle, dest: "/nothing-here", tooltip: t("home.getPdfInfo.desc") }, + { displayText: t("home.showJS.title"), icon: BsFiletypeJs, dest: "/nothing-here", tooltip: t("home.showJS.desc") }, + ]}, + ] as (NavInfoItem | NavInfoSublist)[]; - return ( - - - - - Image - Stirling PDF - - - - + return ( + + + + + Image + Stirling PDF + + + + - + -
+
- + -
-
-
- ); +
+
+
+ ); } export default NavBar; \ No newline at end of file diff --git a/client-tauri/src/components/toolbar/LanguagePicker.tsx b/client-tauri/src/components/toolbar/LanguagePicker.tsx index 01ac1f0c6..16b5bb866 100644 --- a/client-tauri/src/components/toolbar/LanguagePicker.tsx +++ b/client-tauri/src/components/toolbar/LanguagePicker.tsx @@ -1,29 +1,29 @@ -import NavDropdown from 'react-bootstrap/NavDropdown'; -import { useTranslation } from 'react-i18next'; -import { BsGlobe2 } from 'react-icons/bs'; +import NavDropdown from "react-bootstrap/NavDropdown"; +import { useTranslation } from "react-i18next"; +import { BsGlobe2 } from "react-icons/bs"; function generateSublist() { - const { i18n } = useTranslation(); - const out: JSX.Element[] = []; - const languages = i18n.options.resources; - for (var key in languages) { - const lang: any = languages[key].translation; - const staticKey = key; - out.push(( - i18n.changeLanguage(staticKey)}> - {lang.language?.flag} - {lang.language?.name} - - )); - } - return <>{out}; + const { i18n } = useTranslation(); + const out: JSX.Element[] = []; + const languages = i18n.options.resources; + for (const key in languages) { + const lang: any = languages[key].translation; + const staticKey = key; + out.push(( + i18n.changeLanguage(staticKey)}> + {lang.language?.flag} + {lang.language?.name} + + )); + } + return <>{out}; } export default function LanguagePicker() { - return ( - }> - {generateSublist()} - - ); + return ( + }> + {generateSublist()} + + ); } diff --git a/client-tauri/src/declarations/shared-operations.d.ts b/client-tauri/src/declarations/shared-operations.d.ts index 0101f019e..3cee864c4 100644 --- a/client-tauri/src/declarations/shared-operations.d.ts +++ b/client-tauri/src/declarations/shared-operations.d.ts @@ -1,4 +1,4 @@ -declare module '@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js' { +declare module "@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js" { export async function oneToOne(wasmArray: any, snapshot: any): Promise; } diff --git a/client-tauri/src/main.tsx b/client-tauri/src/main.tsx index dc4b2c422..60876ead7 100644 --- a/client-tauri/src/main.tsx +++ b/client-tauri/src/main.tsx @@ -6,9 +6,9 @@ import App from "./App"; import "./index.css"; ReactDOM.createRoot(document.getElementById("root")!).render( - - - - - + + + + + ); \ No newline at end of file diff --git a/client-tauri/src/pages/About.tsx b/client-tauri/src/pages/About.tsx index c703576c7..4e102b20d 100644 --- a/client-tauri/src/pages/About.tsx +++ b/client-tauri/src/pages/About.tsx @@ -1,10 +1,10 @@ function About() { - return ( -
-

About

-
- ); + return ( +
+

About

+
+ ); } export default About; \ No newline at end of file diff --git a/client-tauri/src/pages/Dashboard.tsx b/client-tauri/src/pages/Dashboard.tsx index b2486a5f5..198c7be85 100644 --- a/client-tauri/src/pages/Dashboard.tsx +++ b/client-tauri/src/pages/Dashboard.tsx @@ -1,8 +1,8 @@ function Dashboard() { - return ( -
-

Dashboard

+ return ( +
+

Dashboard

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquet felis in ornare molestie. Quisque et dolor gravida, vulputate libero ultricies, suscipit diam. Pellentesque semper eget purus et rutrum. Duis fringilla elementum tellus, ut egestas nisi ultrices sed. Fusce id elit ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla facilisi. Duis varius, orci vel tempor cursus, elit tellus interdum sem, at vulputate lorem ex et dolor. Vestibulum purus mauris, consequat viverra gravida eget, fermentum a lacus. Phasellus eu varius dolor. Etiam a vulputate sapien. Etiam pulvinar, neque eu elementum imperdiet, nibh ex lobortis magna, ut varius lectus ante tristique massa. Nullam quis porttitor sapien. Suspendisse dictum enim vitae tristique aliquet. Nunc imperdiet pellentesque quam, sit amet luctus dui dignissim non. Vivamus eleifend sagittis mauris, at imperdiet nisl. Morbi rutrum magna ut tortor euismod efficitur. Pellentesque quis tortor consectetur, lobortis turpis eget, tincidunt turpis. Nulla consectetur massa ex. Donec lectus purus, interdum sit amet sapien eu, maximus dapibus diam. Suspendisse potenti. In lacinia augue massa, et vulputate eros convallis id. Suspendisse bibendum sagittis posuere. Integer ullamcorper odio eget risus venenatis, non mollis arcu lacinia. Vestibulum feugiat arcu elit, eu varius enim fermentum vitae. @@ -42,8 +42,8 @@ Proin faucibus efficitur sollicitudin. Curabitur pharetra lectus ut metus molest Aenean tincidunt scelerisque ante non vestibulum. Curabitur eleifend ipsum sem, elementum ornare enim ornare eu. In molestie sodales mattis. Morbi ac posuere lorem. Aliquam in nisi ac ipsum euismod bibendum eget id urna. Quisque suscipit lectus non magna varius venenatis sed sit amet lectus. Nam leo nisl, imperdiet at lorem fringilla, lacinia bibendum lacus. Nunc auctor mauris at orci condimentum venenatis at non augue. Donec iaculis aliquam risus. Suspendisse vel massa leo. Mauris sed est turpis. Nullam ut magna eu elit vehicula tempus. Sed mollis ultrices eleifend. Curabitur metus felis, sodales a turpis accumsan, ultricies feugiat arcu. Donec sit amet dui commodo, lacinia sem facilisis, lobortis urna. Donec cursus arcu ex, ac imperdiet lorem rutrum at. Curabitur faucibus erat in dolor placerat, vel blandit ligula eleifend. Morbi blandit nisl ut arcu semper consequat. Nulla malesuada convallis lectus a egestas. Sed volutpat metus vitae libero pulvinar, ut pretium magna malesuada. -
- ); +
+ ); } export default Dashboard; \ No newline at end of file diff --git a/client-tauri/src/pages/Home.tsx b/client-tauri/src/pages/Home.tsx index 6991f4b1e..e2b2e543f 100644 --- a/client-tauri/src/pages/Home.tsx +++ b/client-tauri/src/pages/Home.tsx @@ -1,9 +1,9 @@ function Home() { return ( -
-

Home

-
+
+

Home

+
); } diff --git a/client-tauri/src/pages/NoMatch.tsx b/client-tauri/src/pages/NoMatch.tsx index 1f3672aa1..6794379ce 100644 --- a/client-tauri/src/pages/NoMatch.tsx +++ b/client-tauri/src/pages/NoMatch.tsx @@ -1,14 +1,14 @@ import { Link } from "react-router-dom"; function NoMatch() { - return ( -
-

Nothing to see here!

-

- Go to the home page 3 -

-
- ); + return ( +
+

Nothing to see here!

+

+ Go to the home page 3 +

+
+ ); } export default NoMatch; \ No newline at end of file diff --git a/client-tauri/src/pages/convert/ToPdf.tsx b/client-tauri/src/pages/convert/ToPdf.tsx index 41d9e6f46..e193060de 100644 --- a/client-tauri/src/pages/convert/ToPdf.tsx +++ b/client-tauri/src/pages/convert/ToPdf.tsx @@ -2,7 +2,7 @@ import { isLibreOfficeInstalled } from "../../utils/libre-office-utils"; const hasLibreOffice = await isLibreOfficeInstalled(); -console.log(hasLibreOffice) +console.log(hasLibreOffice); function About() { return ( diff --git a/client-tauri/src/pages/page-operations/Impose.tsx b/client-tauri/src/pages/page-operations/Impose.tsx index 7957618a4..5700b427e 100644 --- a/client-tauri/src/pages/page-operations/Impose.tsx +++ b/client-tauri/src/pages/page-operations/Impose.tsx @@ -1,7 +1,7 @@ import DynamicParameterFields from "../../components/DynamicParameterFields"; import { ImposeParamConstraints } from "@stirling-pdf/shared-operations/src/functions/impose"; -import { useTranslation } from 'react-i18next'; +import { useTranslation } from "react-i18next"; function Impose() { const { t } = useTranslation(); diff --git a/client-tauri/src/utils/file-utils.ts b/client-tauri/src/utils/file-utils.ts index e369807a8..80801ccbf 100644 --- a/client-tauri/src/utils/file-utils.ts +++ b/client-tauri/src/utils/file-utils.ts @@ -1,7 +1,7 @@ export function appendToFilename(inputPath: string, toAppend: string) { - const parts = inputPath.split('.'); + const parts = inputPath.split("."); if (parts.length > 1) { parts[parts.length-2] = parts[parts.length-2] + toAppend; } diff --git a/client-tauri/src/utils/libre-office-utils.tsx b/client-tauri/src/utils/libre-office-utils.tsx index 2b7d33f4f..b8bce8002 100644 --- a/client-tauri/src/utils/libre-office-utils.tsx +++ b/client-tauri/src/utils/libre-office-utils.tsx @@ -1,7 +1,7 @@ -import { readBinaryFile, writeBinaryFile, removeDir, BaseDirectory } from '@tauri-apps/api/fs'; -import { PdfFile,RepresentationType } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile' -import { runShell, isTauriAvailable } from './tauri-wrapper'; +import { readBinaryFile, writeBinaryFile, removeDir, BaseDirectory } from "@tauri-apps/api/fs"; +import { PdfFile,RepresentationType } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"; +import { runShell, isTauriAvailable } from "./tauri-wrapper"; export async function fileToPdf(byteArray: Uint8Array, filename: string): Promise { const randUuid = crypto.randomUUID(); @@ -18,9 +18,9 @@ export async function fileToPdf(byteArray: Uint8Array, filename: string): Promis } console.debug(`${stream}, ${randUuid}: ${message}`); }); - const lastMessage = messageList[messageList.length-1] + const lastMessage = messageList[messageList.length-1]; const outputFilePath = lastMessage.split(" -> ")[1].split(".pdf")[0]+".pdf"; - const outputFilePathSplit = outputFilePath.toString().split("[\\/]") + const outputFilePathSplit = outputFilePath.toString().split("[\\/]"); const outputFileName = outputFilePathSplit[outputFilePathSplit.length-1]; const outputBytes = await readBinaryFile(outputFilePath); @@ -42,7 +42,7 @@ export async function isLibreOfficeInstalled() { } catch (error) { return false; } - console.log("messageList", messageList) + console.log("messageList", messageList); const result = messageList[0].match("LibreOffice ([0-9]+\.){4}.*"); return result ? true : false; } diff --git a/client-tauri/src/utils/pdf-operations.ts b/client-tauri/src/utils/pdf-operations.ts index 1cf6aec08..af772f2bb 100644 --- a/client-tauri/src/utils/pdf-operations.ts +++ b/client-tauri/src/utils/pdf-operations.ts @@ -1,7 +1,7 @@ -import SharedOperations, { OperationsType } from '@stirling-pdf/shared-operations/src' -import { ImposeParamsType } from '@stirling-pdf/shared-operations/src/functions/impose' -import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile" +import SharedOperations, { OperationsType } from "@stirling-pdf/shared-operations/src"; +import { ImposeParamsType } from "@stirling-pdf/shared-operations/src/functions/impose"; +import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"; // Import injected libraries here! import * as pdfcpuWrapper from "@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js"; @@ -13,5 +13,5 @@ async function impose(params: ImposeParamsType): Promise { const toExport: OperationsType = { ...SharedOperations, impose, -} +}; export default toExport; diff --git a/client-tauri/src/utils/tauri-wrapper.ts b/client-tauri/src/utils/tauri-wrapper.ts index 3f71d8378..e8a946230 100644 --- a/client-tauri/src/utils/tauri-wrapper.ts +++ b/client-tauri/src/utils/tauri-wrapper.ts @@ -1,9 +1,9 @@ -import { open, save } from '@tauri-apps/api/dialog'; -import { readBinaryFile, writeBinaryFile } from '@tauri-apps/api/fs'; -import { Command } from '@tauri-apps/api/shell' +import { open, save } from "@tauri-apps/api/dialog"; +import { readBinaryFile, writeBinaryFile } from "@tauri-apps/api/fs"; +import { Command } from "@tauri-apps/api/shell"; -export type TauriBrowserFile = { +export interface TauriBrowserFile { name: string, relativePath?: string, data: Uint8Array, @@ -29,13 +29,13 @@ export function isTauriAvailable() { } // [*] = Not available in browser -type SelectFilesDialogOptions = { +interface SelectFilesDialogOptions { defaultPath?: string, // [*] the default path to open the dialog on directory?: boolean, // should the dialog be a directory dialog - filters?: Array<{ // list of file type filters + filters?: { // list of file type filters name: string, // category name eg. 'Images' extensions: string[] // list of extensions eg ['png', 'jpeg', 'jpg'] - }>, + }[], multiple?: boolean, // allow multiple selections recursive?: boolean, // [*] If directory is true, indicates that it will be read recursively later. Defines whether subdirectories will be allowed on the scope or not. title?: string // [*] the title of the dialog @@ -43,7 +43,7 @@ type SelectFilesDialogOptions = { export function openFiles(options: SelectFilesDialogOptions): Promise { return new Promise(async (resolve) => { if (isTauriAvailable()) { - var selected = await open(options); + let selected = await open(options); if (!selected) { resolve(null); return; @@ -65,15 +65,15 @@ export function openFiles(options: SelectFilesDialogOptions): Promise f.extensions).map(ext => "."+ext).join(", ")); if (options.multiple) input.setAttribute("multiple", ""); input.onchange = async () => { if (input.files && input.files.length) { - console.log("input.files", input.files) + console.log("input.files", input.files); const files: TauriBrowserFile[] = []; for (const f of input.files) { const contents = new Uint8Array(await f.arrayBuffer()); @@ -91,8 +91,8 @@ export function openFiles(options: SelectFilesDialogOptions): Promise { - setTimeout(()=>resolve(null), 200); // the timeout is needed because 'document.body.onfocus' is called before 'input.onchange' - } + setTimeout(()=>{ resolve(null) }, 200); // the timeout is needed because 'document.body.onfocus' is called before 'input.onchange' + }; input.click(); } @@ -100,40 +100,40 @@ export function openFiles(options: SelectFilesDialogOptions): Promise, + }[], title?: string // [*] the title of the dialog } export async function downloadFile(fileData: Uint8Array, options: DownloadFilesDialogOptions): Promise { if (isTauriAvailable()) { const pathToSave = await save(options); - console.log("pathToSave", pathToSave) + console.log("pathToSave", pathToSave); if (pathToSave) { await writeBinaryFile(pathToSave, fileData); } } else { - const pdfBlob = new Blob([fileData], { type: 'application/pdf' }); + const pdfBlob = new Blob([fileData], { type: "application/pdf" }); const url = URL.createObjectURL(pdfBlob); - const downloadOption = localStorage.getItem('downloadOption'); + const downloadOption = localStorage.getItem("downloadOption"); // ensure filename is not a path const separator = options.defaultPath?.includes("\\") ? "\\" : "/"; const filename = options.defaultPath?.split(separator).pop(); - const filenameToUse = filename ? filename : 'edited.pdf'; + const filenameToUse = filename ? filename : "edited.pdf"; - if (downloadOption === 'sameWindow') { + if (downloadOption === "sameWindow") { // Open the file in the same window window.location.href = url; - } else if (downloadOption === 'newWindow') { + } else if (downloadOption === "newWindow") { // Open the file in a new window - window.open(url, '_blank'); + window.open(url, "_blank"); } else { // Download the file - const downloadLink = document.createElement('a'); + const downloadLink = document.createElement("a"); downloadLink.href = url; downloadLink.download = filenameToUse; downloadLink.click(); @@ -152,18 +152,18 @@ export function runShell(commandName: string, args: string[], callback: (message return new Promise(async (resolve, reject) => { const comm = new Command(commandName, args); - comm.on('close', data => { + comm.on("close", data => { if (data.code === 0) { resolve(); } else { reject(new Error(`Command failed with exit code ${data.code} and signal ${data.signal}`)); } }); - comm.on('error', error => callback(error, "error")); - comm.stdout.on('data', line => callback(line, "stdout")); - comm.stderr.on('data', line => callback(line, "stderr")); + comm.on("error", error => { callback(error, "error") }); + comm.stdout.on("data", line => { callback(line, "stdout") }); + comm.stderr.on("data", line => { callback(line, "stderr") }); const child = await comm.spawn(); - console.debug(`Started child process with pid: ${child.pid}`) + console.debug(`Started child process with pid: ${child.pid}`); }); } diff --git a/client-tauri/vite.config.ts b/client-tauri/vite.config.ts index 510ba1da0..d2deb7d13 100644 --- a/client-tauri/vite.config.ts +++ b/client-tauri/vite.config.ts @@ -4,26 +4,26 @@ import topLevelAwait from "vite-plugin-top-level-await"; // https://vitejs.dev/config/ export default defineConfig(async () => ({ - plugins: [ - react(), - topLevelAwait({ - // The export name of top-level await promise for each chunk module - promiseExportName: "__tla", - // The function to generate import names of top-level await promise in each chunk module - promiseImportName: i => `__tla_${i}` - }), - ], + plugins: [ + react(), + topLevelAwait({ + // The export name of top-level await promise for each chunk module + promiseExportName: "__tla", + // The function to generate import names of top-level await promise in each chunk module + promiseImportName: i => `__tla_${i}` + }), + ], - // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` - // - // 1. prevent vite from obscuring rust errors - clearScreen: false, - // 2. tauri expects a fixed port, fail if that port is not available - server: { - port: 1420, - strictPort: true, - }, - // 3. to make use of `TAURI_DEBUG` and other env variables - // https://tauri.app/v1/api/config#buildconfig.beforedevcommand - envPrefix: ["VITE_"], + // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` + // + // 1. prevent vite from obscuring rust errors + clearScreen: false, + // 2. tauri expects a fixed port, fail if that port is not available + server: { + port: 1420, + strictPort: true, + }, + // 3. to make use of `TAURI_DEBUG` and other env variables + // https://tauri.app/v1/api/config#buildconfig.beforedevcommand + envPrefix: ["VITE_"], })); diff --git a/server-node/src/index.ts b/server-node/src/index.ts index 6b60b9faf..a737da95a 100644 --- a/server-node/src/index.ts +++ b/server-node/src/index.ts @@ -1,14 +1,18 @@ import "@stirling-pdf/shared-operations/src/locales/i18next.config"; -import express from 'express'; +import express from "express"; const app = express(); const PORT = 8000; // server-node: backend api -import api from './routes/api/api-controller'; +import api from "./routes/api/api-controller"; app.use("/api", api); // serve app.listen(PORT, () => { console.log(`http://localhost:${PORT}`); -}); \ No newline at end of file +}); + +process.on('unhandledRejection', (reason, promise) => { + console.error('Unhandled Rejection at:', promise, 'reason:', reason); +}); diff --git a/server-node/src/routes/api/api-controller.ts b/server-node/src/routes/api/api-controller.ts index 4be925944..44589dd25 100644 --- a/server-node/src/routes/api/api-controller.ts +++ b/server-node/src/routes/api/api-controller.ts @@ -1,7 +1,7 @@ -import express, { Request, Response } from 'express'; +import express, { Request, Response } from "express"; -import workflow from './workflow-controller'; -import dynamicOperations from './dynamic-operations-controller'; +import workflow from "./workflow-controller"; +import dynamicOperations from "./dynamic-operations-controller"; const router = express.Router(); diff --git a/server-node/src/routes/api/dynamic-operations-controller.ts b/server-node/src/routes/api/dynamic-operations-controller.ts index 6223c7457..48a5708f7 100644 --- a/server-node/src/routes/api/dynamic-operations-controller.ts +++ b/server-node/src/routes/api/dynamic-operations-controller.ts @@ -1,26 +1,26 @@ -import express, { Request, Response } from 'express'; +import express, { Request, Response } from "express"; const router = express.Router(); -import multer from 'multer'; +import multer from "multer"; const upload = multer(); -import { getOperatorByName } from '@stirling-pdf/shared-operations/src/workflow/getOperatorByName'; -import { Operator } from '@stirling-pdf/shared-operations/src/functions'; +import { getOperatorByName } from "@stirling-pdf/shared-operations/src/workflow/getOperatorByName"; +import { Operator } from "@stirling-pdf/shared-operations/src/functions"; -import { PdfFile } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile'; -import { respondWithPdfFiles } from '../../utils/endpoint-utils'; -import { Action } from '@stirling-pdf/shared-operations/declarations/Action'; -import { JoiPDFFileSchema } from '@stirling-pdf/shared-operations/src/wrappers/PdfFileJoi'; +import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"; +import { respondWithPdfFiles } from "../../utils/endpoint-utils"; +import { Action } from "@stirling-pdf/shared-operations/declarations/Action"; +import { JoiPDFFileSchema } from "@stirling-pdf/shared-operations/src/wrappers/PdfFileJoi"; -router.post('/:func', upload.array("file"), async function(req: Request, res: Response) { +router.post("/:func", upload.array("file"), async function(req: Request, res: Response) { handleEndpoint(req, res); }); -router.post('/:dir/:func', upload.array("file"), async function(req: Request, res: Response) { +router.post("/:dir/:func", upload.array("file"), async function(req: Request, res: Response) { handleEndpoint(req, res); }); function handleEndpoint(req: Request, res: Response) { if(!req.files || req.files.length == 0) { - res.status(400).json({error: "no input file(s) were provided"}) + res.status(400).json({error: "no input file(s) were provided"}); return; } @@ -46,11 +46,11 @@ function handleEndpoint(req: Request, res: Response) { operation.run(validationResults.value.input, (progress) => {}).then(pdfFiles => { respondWithPdfFiles(res, pdfFiles, req.params.func + "_result"); - }) + }); } } else { - res.status(400).json({error: `the operator of type ${req.params.func} does not exist`}) + res.status(400).json({error: `the operator of type ${req.params.func} does not exist`}); } } diff --git a/server-node/src/routes/api/workflow-controller.ts b/server-node/src/routes/api/workflow-controller.ts index 676997cab..765339582 100644 --- a/server-node/src/routes/api/workflow-controller.ts +++ b/server-node/src/routes/api/workflow-controller.ts @@ -1,15 +1,15 @@ -import express, { Request, Response } from 'express'; -import crypto from 'crypto'; -import multer from 'multer' +import express, { Request, Response } from "express"; +import crypto from "crypto"; +import multer from "multer"; const upload = multer(); import { traverseOperations } from "@stirling-pdf/shared-operations/src/workflow/traverseOperations"; -import { PdfFile, RepresentationType } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile'; -import { respondWithPdfFiles } from '../../utils/endpoint-utils'; -import { JoiPDFFileSchema } from '@stirling-pdf/shared-operations/src/wrappers/PdfFileJoi'; +import { PdfFile, RepresentationType } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"; +import { respondWithPdfFiles } from "../../utils/endpoint-utils"; +import { JoiPDFFileSchema } from "@stirling-pdf/shared-operations/src/wrappers/PdfFileJoi"; interface Workflow { - eventStream?: express.Response>, + eventStream?: express.Response, result?: PdfFile[], finished: boolean, createdAt: EpochTimeStamp, @@ -73,19 +73,19 @@ router.post("/:workflowUuid?", [ } else { throw err; } - }) + }); } else { console.log("Start Aync Workflow"); // TODO: UUID collision checks - let workflowID = req.params.workflowUuid + let workflowID = req.params.workflowUuid; if(!workflowID) workflowID = generateWorkflowID(); activeWorkflows[workflowID] = { createdAt: Date.now(), finished: false - } + }; const activeWorkflow = activeWorkflows[workflowID]; res.status(200).json({ @@ -104,7 +104,7 @@ router.post("/:workflowUuid?", [ activeWorkflow.eventStream.write(`data: ${state}\n\n`); }).then(async (pdfResults) => { if(activeWorkflow.eventStream) { - activeWorkflow.eventStream.write(`data: processing done\n\n`); + activeWorkflow.eventStream.write("data: processing done\n\n"); activeWorkflow.eventStream.end(); } @@ -170,16 +170,16 @@ router.get("/progress-stream/:workflowUuid", (req: Request, res: Response) => { // TODO: Check if already done // Send realtime updates - res.setHeader('Cache-Control', 'no-cache'); - res.setHeader('Content-Type', 'text/event-stream'); - res.setHeader('Access-Control-Allow-Origin', '*'); - res.setHeader('Connection', 'keep-alive'); + res.setHeader("Cache-Control", "no-cache"); + res.setHeader("Content-Type", "text/event-stream"); + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Connection", "keep-alive"); res.flushHeaders(); // flush the headers to establish SSE with client const workflow = activeWorkflows[req.params.workflowUuid]; workflow.eventStream = res; - res.on('close', () => { + res.on("close", () => { res.end(); // TODO: Abort if not already done? }); @@ -203,7 +203,7 @@ router.get("/result/:workflowUuid", async (req: Request, res: Response) => { const workflow = activeWorkflows[req.params.workflowUuid]; if(!workflow.finished) { res.status(202).json({ message: "Workflow hasn't finished yet. Check progress or connect to progress-steam to get notified when its done." }); - return + return; } await respondWithPdfFiles(res, workflow.result, "workflow-results"); diff --git a/server-node/src/utils/endpoint-utils.ts b/server-node/src/utils/endpoint-utils.ts index d39c07875..68506c114 100644 --- a/server-node/src/utils/endpoint-utils.ts +++ b/server-node/src/utils/endpoint-utils.ts @@ -1,13 +1,13 @@ -import { Response } from 'express'; -import { PdfFile } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile' -import Archiver from 'archiver'; +import { Response } from "express"; +import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"; +import Archiver from "archiver"; export async function respondWithFile(res: Response, uint8Array: Uint8Array, filename: string, mimeType: string): Promise { res.writeHead(200, { - 'Content-Type': mimeType, - 'Content-disposition': `attachment; filename="${filename}"`, - 'Content-Length': uint8Array.length + "Content-Type": mimeType, + "Content-disposition": `attachment; filename="${filename}"`, + "Content-Length": uint8Array.length }); res.end(uint8Array); } @@ -23,14 +23,14 @@ export async function respondWithZip(res: Response, filename: string, files: {ui return; } - console.log(filename) + console.log(filename); res.writeHead(200, { - 'Content-Type': 'application/zip', - 'Content-disposition': `attachment; filename="${filename}.zip"`, + "Content-Type": "application/zip", + "Content-disposition": `attachment; filename="${filename}.zip"`, }); // TODO: Also allow changing the compression level - var zip = Archiver('zip'); + const zip = Archiver("zip"); // Stream the file to the user. zip.pipe(res); @@ -50,10 +50,10 @@ export async function respondWithPdfFiles(res: Response, pdfFiles: PdfFile[] | u res.status(500).json({"warning": "The workflow had no outputs."}); } else if (pdfFiles.length == 1) { - respondWithPdfFile(res, pdfFiles[0]) + respondWithPdfFile(res, pdfFiles[0]); } else { - const promises = pdfFiles.map(async (pdf) => {return{uint8Array: await pdf.uint8Array, filename: pdf.filename + ".pdf"}}) + const promises = pdfFiles.map(async (pdf) => {return{uint8Array: await pdf.uint8Array, filename: pdf.filename + ".pdf"}}); const files = await Promise.all(promises); respondWithZip(res, filename, files); } diff --git a/server-node/src/utils/libre-office-utils.ts b/server-node/src/utils/libre-office-utils.ts index 3608d1b65..60d51b50d 100644 --- a/server-node/src/utils/libre-office-utils.ts +++ b/server-node/src/utils/libre-office-utils.ts @@ -1,9 +1,9 @@ -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import { exec, spawn } from 'child_process' -import { PdfFile, RepresentationType } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile' +import fs from "fs"; +import os from "os"; +import path from "path"; +import { exec, spawn } from "child_process"; +import { PdfFile, RepresentationType } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"; export async function fileToPdf(byteArray: Uint8Array, filename: string): Promise { const parentDir = path.join(os.tmpdir(), "StirlingPDF"); @@ -46,14 +46,14 @@ export function isLibreOfficeInstalled() { const result = stdout.match("LibreOffice ([0-9]+\.){4}.*"); resolve(result ? true : false); }); - }) + }); } function writeBytesToFile(filePath: string, bytes: Uint8Array): Promise { return new Promise((resolve, reject) => { fs.writeFile(filePath, bytes, function(err) { if(err) { - reject(err) + reject(err); return; } resolve(); @@ -80,17 +80,17 @@ function runLibreOfficeCommand(idKey: string, args: string[]): Promise const process = spawn("libreoffice", args); - process.stdout.on('data', (data) => { + process.stdout.on("data", (data) => { const dataStr = data.toString(); console.log(`Progress ${idKey}:`, dataStr); messageList.push(dataStr); }); - process.stderr.on('data', (data) => { + process.stderr.on("data", (data) => { console.error(`stderr ${idKey}:`, data.toString()); }); - process.on('exit', (code) => { + process.on("exit", (code) => { if (code === 0) { resolve(messageList); } else { @@ -98,7 +98,7 @@ function runLibreOfficeCommand(idKey: string, args: string[]): Promise } }); - process.on('error', (err) => { + process.on("error", (err) => { reject(err); }); diff --git a/shared-operations/declarations/pdfcpu.d.ts b/shared-operations/declarations/pdfcpu.d.ts index a444033a5..845c548a3 100644 --- a/shared-operations/declarations/pdfcpu.d.ts +++ b/shared-operations/declarations/pdfcpu.d.ts @@ -1,3 +1,3 @@ -declare module '#pdfcpu' { +declare module "#pdfcpu" { export function oneToOne(wasmArray: string[], snapshot: Uint8Array): Promise; } \ No newline at end of file diff --git a/shared-operations/src/functions/arrangePages.ts b/shared-operations/src/functions/arrangePages.ts index 15c00260c..9ad75b3c8 100644 --- a/shared-operations/src/functions/arrangePages.ts +++ b/shared-operations/src/functions/arrangePages.ts @@ -1,10 +1,10 @@ -import { PdfFile } from '../wrappers/PdfFile.js'; -import { Sorts } from './common/pageIndexesSorting.js'; -import { getPages } from './common/getPagesByIndex.js'; -import { parsePageIndexSpecification } from './common/pageIndexesUtils.js'; +import { PdfFile } from "../wrappers/PdfFile.js"; +import { Sorts } from "./common/pageIndexesSorting.js"; +import { getPages } from "./common/getPagesByIndex.js"; +import { parsePageIndexSpecification } from "./common/pageIndexesUtils.js"; -export type ArrangePagesParamsType = { +export interface ArrangePagesParamsType { file: PdfFile; arrangementConfig: string; // a member of Sorts, or a page index specification } @@ -22,6 +22,6 @@ export async function arrangePages(params: ArrangePagesParamsType) { } const newFile = await getPages(file, sortIndexes); - newFile.filename += "arrangedPages" + newFile.filename += "arrangedPages"; return newFile; } diff --git a/shared-operations/src/functions/common/detectEmptyPages.ts b/shared-operations/src/functions/common/detectEmptyPages.ts index 73284c685..27c9e0b4b 100644 --- a/shared-operations/src/functions/common/detectEmptyPages.ts +++ b/shared-operations/src/functions/common/detectEmptyPages.ts @@ -1,7 +1,7 @@ -import { PdfFile } from '../../wrappers/PdfFile'; +import { PdfFile } from "../../wrappers/PdfFile"; import { PDFPageProxy } from "pdfjs-dist/types/src/display/api.js"; -import { Image, ImageKind } from 'image-js'; +import { Image, ImageKind } from "image-js"; import { getImagesOnPage, PDFJSImage } from "./getImagesOnPage.js"; @@ -45,8 +45,8 @@ async function areImagesBlank(page: PDFPageProxy, threshold: number): Promise { - var img = new Image(image.width, image.height, image.data, { kind: "RGB" as ImageKind }); // TODO: Maybe respect image.kind and convert accordingly, needs to be tested with a pdf with alpha-image - var grey = img.grey(); - var mean = grey.getMean(); + const img = new Image(image.width, image.height, image.data, { kind: "RGB" as ImageKind }); // TODO: Maybe respect image.kind and convert accordingly, needs to be tested with a pdf with alpha-image + const grey = img.grey(); + const mean = grey.getMean(); return mean[0] <= threshold; } \ No newline at end of file diff --git a/shared-operations/src/functions/common/detectQRCodePages.ts b/shared-operations/src/functions/common/detectQRCodePages.ts index 0f086494f..7db13382d 100644 --- a/shared-operations/src/functions/common/detectQRCodePages.ts +++ b/shared-operations/src/functions/common/detectQRCodePages.ts @@ -1,7 +1,7 @@ import jsQR from "jsqr"; -import { PdfFile } from '../../wrappers/PdfFile.js'; +import { PdfFile } from "../../wrappers/PdfFile.js"; import { getImagesOnPage, PDFJSImage } from "./getImagesOnPage.js"; export async function detectQRCodePages(file: PdfFile) { @@ -24,7 +24,7 @@ export async function detectQRCodePages(file: PdfFile) { } } if(pagesWithQR.length == 0) { - console.warn("Could not find any QR Codes in the provided PDF.") + console.warn("Could not find any QR Codes in the provided PDF."); } return pagesWithQR; } diff --git a/shared-operations/src/functions/common/getImagesOnPage.ts b/shared-operations/src/functions/common/getImagesOnPage.ts index 6c53c353d..39d251243 100644 --- a/shared-operations/src/functions/common/getImagesOnPage.ts +++ b/shared-operations/src/functions/common/getImagesOnPage.ts @@ -1,20 +1,20 @@ import { PDFPageProxy } from "pdfjs-dist/types/src/display/api.js"; -import * as PDFJS from 'pdfjs-dist'; +import * as PDFJS from "pdfjs-dist"; -export type PDFJSImage = { +export interface PDFJSImage { width: number; height: number; interpolate?: any; kind: number; // TODO: Document what this is, maybe hasAlpha? data: Uint8ClampedArray; -}; +} export async function getImagesOnPage(page: PDFPageProxy): Promise { const ops = await page.getOperatorList(); const images: PDFJSImage[] = []; - for (var j=0; j < ops.fnArray.length; j++) { + for (let j=0; j < ops.fnArray.length; j++) { if (ops.fnArray[j] == PDFJS.OPS.paintImageXObject) { const image = page.objs.get(ops.argsArray[j][0]) as PDFJSImage; images.push(image); diff --git a/shared-operations/src/functions/common/getPagesByIndex.ts b/shared-operations/src/functions/common/getPagesByIndex.ts index d7498d8fb..5290106a4 100644 --- a/shared-operations/src/functions/common/getPagesByIndex.ts +++ b/shared-operations/src/functions/common/getPagesByIndex.ts @@ -1,6 +1,6 @@ -import { PdfFile, RepresentationType } from '../../wrappers/PdfFile.js'; -import { PDFDocument } from 'pdf-lib'; +import { PdfFile, RepresentationType } from "../../wrappers/PdfFile.js"; +import { PDFDocument } from "pdf-lib"; export async function getPages(file: PdfFile, pageIndexes: number[]): Promise { const pdfLibDocument = await file.pdfLibDocument; diff --git a/shared-operations/src/functions/common/pageIndexesSorting.ts b/shared-operations/src/functions/common/pageIndexesSorting.ts index e4522a74c..22226e12c 100644 --- a/shared-operations/src/functions/common/pageIndexesSorting.ts +++ b/shared-operations/src/functions/common/pageIndexesSorting.ts @@ -55,11 +55,11 @@ function bookletSort(totalPages: number): number[] { 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)); + 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; } @@ -72,10 +72,10 @@ function sideStitchBooklet(totalPages: number): number[] { function oddEvenSplit(totalPages: number): number[] { const newPageOrder: number[] = []; for (let i = 1; i <= totalPages; i += 2) { - newPageOrder.push(i - 1); + newPageOrder.push(i - 1); } for (let i = 2; i <= totalPages; i += 2) { - newPageOrder.push(i - 1); + newPageOrder.push(i - 1); } return newPageOrder; } @@ -108,9 +108,7 @@ function removeFirstAndLast(totalPages: number): number[] { } export type SortFunction = (totalPages: number) => number[]; -type Sorts = { - [key: string]: SortFunction; -}; +type Sorts = Record; export const Sorts: Sorts = Object.freeze({ "REVERSE_ORDER": reverseSort, "DUPLEX_SORT": duplexSort, diff --git a/shared-operations/src/functions/common/pageIndexesUtils.ts b/shared-operations/src/functions/common/pageIndexesUtils.ts index 32d3da20a..0b25f3391 100644 --- a/shared-operations/src/functions/common/pageIndexesUtils.ts +++ b/shared-operations/src/functions/common/pageIndexesUtils.ts @@ -18,7 +18,7 @@ export function invertSelection(selection: number[], pages: number|number[]): nu */ export function parsePageIndexSpecification(specification: string, totalPages: number): number[] { // Translated to JS from the original Java function - const pageOrderArr = specification.split(",") + const pageOrderArr = specification.split(","); const newPageOrder: number[] = []; // loop through the page order array @@ -32,13 +32,13 @@ export function parsePageIndexSpecification(specification: string, totalPages: n } 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; + let coefficient = 0; + let constant = 0; + let coefficientExists = false; + let constantExists = false; if (element.includes("n")) { - var parts = element.split("n"); + const parts = element.split("n"); if (!parts[0]) { coefficient = parseInt(parts[0]); coefficientExists = true; @@ -53,7 +53,7 @@ export function parsePageIndexSpecification(specification: string, totalPages: n } for (var i = 1; i <= totalPages; i++) { - var pageNum = coefficientExists ? coefficient * i : i; + let pageNum = coefficientExists ? coefficient * i : i; pageNum += constantExists ? constant : 0; if (pageNum <= totalPages && pageNum > 0) { @@ -64,13 +64,13 @@ export function parsePageIndexSpecification(specification: string, totalPages: n // split the range into start and end page const range = element.split("-"); const start = parseInt(range[0]); - var end = parseInt(range[1]); + let 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++) { + for (let j = start; j <= end; j++) { // print the current index newPageOrder.push(j - 1); } diff --git a/shared-operations/src/functions/common/sortPdfArray.ts b/shared-operations/src/functions/common/sortPdfArray.ts index d082bf429..70e10d16a 100644 --- a/shared-operations/src/functions/common/sortPdfArray.ts +++ b/shared-operations/src/functions/common/sortPdfArray.ts @@ -1,46 +1,46 @@ -import { PdfFile } from '../../wrappers/PdfFile'; +import { PdfFile } from "../../wrappers/PdfFile"; export async function sortPdfArray( - files: PdfFile[], - sortType: "orderProvided"|"byFileName"|"byDateModified"|"byDateCreated"|"byPDFTitle" = "orderProvided" - ): Promise { + files: PdfFile[], + sortType: "orderProvided"|"byFileName"|"byDateModified"|"byDateCreated"|"byPDFTitle" = "orderProvided" +): Promise { const docCache = await PdfFile.cacheAsPdfLibDocuments(files); switch(sortType) { - case "byFileName": - files.sort((a, b) => { - if (!a || !b) return 0; - const ad = a.filename, bd = b.filename; - if (!ad || !bd) return 0; - return ad.localeCompare(bd); - }); - break; - case "byDateModified": - files.sort((a, b) => { - const ad = docCache.get(a)?.getModificationDate()?.getTime(); - const bd = docCache.get(b)?.getModificationDate()?.getTime(); - if (!ad || !bd) return 0; - return ad > bd ? 1 : -1 - }); - break; - case "byDateCreated": - files.sort((a, b) => { - const ad = docCache.get(a)?.getCreationDate()?.getTime(); - const bd = docCache.get(b)?.getCreationDate()?.getTime(); - if (!ad || !bd) return 0; - return ad > bd ? 1 : -1 - }); - break; - case "byPDFTitle": - files.sort((a, b) => { - const ad = docCache.get(a)?.getTitle(); - const bd = docCache.get(b)?.getTitle(); - if (!ad || !bd) return 0; - return ad.localeCompare(bd); - }); - break; + case "byFileName": + files.sort((a, b) => { + if (!a || !b) return 0; + const ad = a.filename, bd = b.filename; + if (!ad || !bd) return 0; + return ad.localeCompare(bd); + }); + break; + case "byDateModified": + files.sort((a, b) => { + const ad = docCache.get(a).getModificationDate().getTime(); + const bd = docCache.get(b).getModificationDate().getTime(); + if (!ad || !bd) return 0; + return ad > bd ? 1 : -1; + }); + break; + case "byDateCreated": + files.sort((a, b) => { + const ad = docCache.get(a).getCreationDate().getTime(); + const bd = docCache.get(b).getCreationDate().getTime(); + if (!ad || !bd) return 0; + return ad > bd ? 1 : -1; + }); + break; + case "byPDFTitle": + files.sort((a, b) => { + const ad = docCache.get(a).getTitle(); + const bd = docCache.get(b).getTitle(); + if (!ad || !bd) return 0; + return ad.localeCompare(bd); + }); + break; } return files; diff --git a/shared-operations/src/functions/common/splitPagesByIndex.ts b/shared-operations/src/functions/common/splitPagesByIndex.ts index 036212981..7612c9c17 100644 --- a/shared-operations/src/functions/common/splitPagesByIndex.ts +++ b/shared-operations/src/functions/common/splitPagesByIndex.ts @@ -1,5 +1,5 @@ -import { PdfFile } from '../../wrappers/PdfFile.js'; +import { PdfFile } from "../../wrappers/PdfFile.js"; import { getPages } from "./getPagesByIndex"; export async function splitPagesByIndex(file: PdfFile, splitAfterPageIndexes: number[]): Promise { @@ -22,4 +22,4 @@ export async function splitPagesByIndex(file: PdfFile, splitAfterPageIndexes: nu pagesArray = []; return subDocuments; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/shared-operations/src/functions/extractPages.ts b/shared-operations/src/functions/extractPages.ts index c1206f965..c3f727600 100644 --- a/shared-operations/src/functions/extractPages.ts +++ b/shared-operations/src/functions/extractPages.ts @@ -1,9 +1,9 @@ -import { PdfFile } from '../wrappers/PdfFile.js'; -import { getPages } from './common/getPagesByIndex.js'; -import { parsePageIndexSpecification } from './common/pageIndexesUtils' +import { PdfFile } from "../wrappers/PdfFile.js"; +import { getPages } from "./common/getPagesByIndex.js"; +import { parsePageIndexSpecification } from "./common/pageIndexesUtils"; -export type ExtractPagesParamsType = { +export interface ExtractPagesParamsType { file: PdfFile; pageIndexes: string | number[]; } @@ -11,13 +11,13 @@ export async function extractPages(params: ExtractPagesParamsType): Promise { if (err) throw err; }); +import i18next from "i18next"; +i18next.loadNamespaces("impose", (err, t) => { if (err) throw err; }); export class Impose extends Operator { - static type: string = "impose"; + static type = "impose"; /** * Validation & Localisation */ - protected static inputSchema = JoiPDFFileSchema.label(i18next.t('inputs.pdffile.name')).description(i18next.t('inputs.pdffile.description')); + protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")); protected static valueSchema = Joi.object({ nup: Joi.number().integer().valid(2, 3, 4, 8, 9, 12, 16).required() - .label(i18next.t('values.nup.friendlyName', { ns: 'impose' })).description(i18next.t('values.nup.description', { ns: 'impose' })) + .label(i18next.t("values.nup.friendlyName", { ns: "impose" })).description(i18next.t("values.nup.description", { ns: "impose" })) .example("3").example("4"), format: Joi.string().valid(...[ // ISO 216:1975 A @@ -62,16 +62,16 @@ export class Impose extends Operator { "JIS-B7", "JIS-B8", "JIS-B9", "JIS-B10", "JIS-B11", "JIS-B12", "Shirokuban4", "Shirokuban5", "Shirokuban6", "Kiku4", "Kiku5", "AB", "B40", "Shikisen" ].flatMap(size => [size, size + "P", size + "L"])).required() - .label(i18next.t('values.format.friendlyName', { ns: 'impose' })).description(i18next.t('values.format.description', { ns: 'impose' })) + .label(i18next.t("values.format.friendlyName", { ns: "impose" })).description(i18next.t("values.format.description", { ns: "impose" })) .example("A4").example("A3L") }); - protected static outputSchema = JoiPDFFileSchema.label(i18next.t('outputs.pdffile.name')).description(i18next.t('outputs.pdffile.description')); + protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description")); static schema = Joi.object({ input: Impose.inputSchema, values: Impose.valueSchema.required(), output: Impose.outputSchema - }).label(i18next.t('friendlyName', { ns: 'impose' })).description(i18next.t('description', { ns: 'impose' })); + }).label(i18next.t("friendlyName", { ns: "impose" })).description(i18next.t("description", { ns: "impose" })); /** @@ -89,7 +89,7 @@ export class Impose extends Operator { "nup", "-c", "disable", - 'f:' + this.actionValues.format, + "f:" + this.actionValues.format, "/output.pdf", String(this.actionValues.nup), "input.pdf", @@ -104,10 +104,10 @@ export class Impose extends Operator { input.filename + "_imposed" ); - progressCallback({ curFileProgress: 1, operationProgress: index/max }) + progressCallback({ curFileProgress: 1, operationProgress: index/max }); console.log("ImposeResult: ", result); return result; - }) + }); } } diff --git a/shared-operations/src/functions/index.ts b/shared-operations/src/functions/index.ts index 709b7c7bf..96444e912 100644 --- a/shared-operations/src/functions/index.ts +++ b/shared-operations/src/functions/index.ts @@ -45,7 +45,7 @@ export async function nToOne (inputs: I[], callback: (input: I[]) => Promi /** This function should be used if the Operation takes one file as input and may output multiple files */ export async function oneToN (inputs: I[], callback: (input: I, index: number, max: number) => Promise): Promise { - let output: O[] = [] + let output: O[] = []; for (let i = 0; i < inputs.length; i++) { output = output.concat(await callback(inputs[i], i, inputs.length)); } @@ -55,6 +55,6 @@ export async function oneToN (inputs: I[], callback: (input: I, index: num /** This function should be used if the Operation takes one file as input and outputs only one file */ export async function oneToOne (inputs: I[], callback: (input: I, index: number, max: number) => Promise): Promise { return oneToN(inputs, async (input, index, max) => { - return [await callback(input, index, max)] + return [await callback(input, index, max)]; }); } \ No newline at end of file diff --git a/shared-operations/src/functions/mergePDFs.ts b/shared-operations/src/functions/mergePDFs.ts index ebde95b50..d46511e99 100644 --- a/shared-operations/src/functions/mergePDFs.ts +++ b/shared-operations/src/functions/mergePDFs.ts @@ -1,8 +1,8 @@ -import { PDFDocument } from 'pdf-lib'; -import { PdfFile, RepresentationType } from '../wrappers/PdfFile'; +import { PDFDocument } from "pdf-lib"; +import { PdfFile, RepresentationType } from "../wrappers/PdfFile"; -export type MergeParamsType = { +export interface MergeParamsType { files: PdfFile[]; } @@ -15,6 +15,6 @@ export async function mergePDFs(params: MergeParamsType): Promise { copiedPages.forEach((page) => mergedPdf.addPage(page)); } - const newName = "("+params.files.map(input => input.filename).join("_and_") + ")_merged" + const newName = "("+params.files.map(input => input.filename).join("_and_") + ")_merged"; return new PdfFile("mergedPDF", mergedPdf, RepresentationType.PDFLibDocument, newName); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/shared-operations/src/functions/removeBlankPages.ts b/shared-operations/src/functions/removeBlankPages.ts index 433df5c15..86b42c7ca 100644 --- a/shared-operations/src/functions/removeBlankPages.ts +++ b/shared-operations/src/functions/removeBlankPages.ts @@ -1,10 +1,10 @@ -import { PdfFile } from '../wrappers/PdfFile.js'; -import { detectEmptyPages } from './common/detectEmptyPages.js'; -import { getPages } from './common/getPagesByIndex.js'; -import { invertSelection } from './common/pageIndexesUtils.js'; +import { PdfFile } from "../wrappers/PdfFile.js"; +import { detectEmptyPages } from "./common/detectEmptyPages.js"; +import { getPages } from "./common/getPagesByIndex.js"; +import { invertSelection } from "./common/pageIndexesUtils.js"; -export type RemoveBlankPagesParamsType = { +export interface RemoveBlankPagesParamsType { file: PdfFile; whiteThreashold: number; } @@ -15,9 +15,9 @@ export async function removeBlankPages(params: RemoveBlankPagesParamsType) { const emptyPages = await detectEmptyPages(file, whiteThreashold); console.debug("Empty Pages: ", emptyPages); - const pagesToKeep = invertSelection(emptyPages, pageCount) + const pagesToKeep = invertSelection(emptyPages, pageCount); const newFile = await getPages(file, pagesToKeep); - newFile.filename += "_removedBlanks" + newFile.filename += "_removedBlanks"; return newFile; } \ No newline at end of file diff --git a/shared-operations/src/functions/removePages.ts b/shared-operations/src/functions/removePages.ts index 6174e12c0..e5d56aa26 100644 --- a/shared-operations/src/functions/removePages.ts +++ b/shared-operations/src/functions/removePages.ts @@ -1,9 +1,9 @@ -import { PdfFile } from '../wrappers/PdfFile.js'; -import { getPages } from './common/getPagesByIndex.js'; -import { invertSelection, parsePageIndexSpecification } from './common/pageIndexesUtils.js'; +import { PdfFile } from "../wrappers/PdfFile.js"; +import { getPages } from "./common/getPagesByIndex.js"; +import { invertSelection, parsePageIndexSpecification } from "./common/pageIndexesUtils.js"; -export type RemovePagesParamsType = { +export interface RemovePagesParamsType { file: PdfFile; pageSelector: string; } @@ -16,6 +16,6 @@ export async function removePages(params: RemovePagesParamsType) { const pagesToKeep = invertSelection(pageSelection, pageCount); const newFile = await getPages(file, pagesToKeep); - newFile.filename += "_removedPages" + newFile.filename += "_removedPages"; return newFile; } \ No newline at end of file diff --git a/shared-operations/src/functions/rotatePages.ts b/shared-operations/src/functions/rotatePages.ts index d78f73070..09218ec63 100644 --- a/shared-operations/src/functions/rotatePages.ts +++ b/shared-operations/src/functions/rotatePages.ts @@ -1,8 +1,8 @@ -import { degrees } from 'pdf-lib'; -import { PdfFile, RepresentationType } from '../wrappers/PdfFile'; +import { degrees } from "pdf-lib"; +import { PdfFile, RepresentationType } from "../wrappers/PdfFile"; -export type RotateParamsType = { +export interface RotateParamsType { file: PdfFile; rotation: number|number[]; } @@ -15,19 +15,19 @@ export async function rotatePages(params: RotateParamsType): Promise { if (Array.isArray(rotation)) { if (rotation.length != pages.length) { - throw new Error(`Number of given rotations '${rotation.length}' is not the same as the number of pages '${pages.length}'`) + throw new Error(`Number of given rotations '${rotation.length}' is not the same as the number of pages '${pages.length}'`); } for (let i=0; i { // Change page size - const oldRotation = page.getRotation().angle - page.setRotation(degrees(oldRotation + rotation)) + const oldRotation = page.getRotation().angle; + page.setRotation(degrees(oldRotation + rotation)); }); } return new PdfFile(file.originalFilename, pdfDoc, RepresentationType.PDFLibDocument, file.filename+"_rotated"); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/shared-operations/src/functions/scaleContent.ts b/shared-operations/src/functions/scaleContent.ts index e28c8a272..6a97ee748 100644 --- a/shared-operations/src/functions/scaleContent.ts +++ b/shared-operations/src/functions/scaleContent.ts @@ -1,8 +1,8 @@ -import { PDFPage } from 'pdf-lib'; -import { PdfFile, RepresentationType } from '../wrappers/PdfFile'; +import { PDFPage } from "pdf-lib"; +import { PdfFile, RepresentationType } from "../wrappers/PdfFile"; -export type ScaleContentParamsType = { +export interface ScaleContentParamsType { file: PdfFile; scaleFactor: number|number[]; } @@ -15,17 +15,17 @@ export async function scaleContent(params: ScaleContentParamsType): Promise scalePage(page, scaleFactor)); + pages.forEach(page => { scalePage(page, scaleFactor) }); } return new PdfFile(file.originalFilename, pdfDoc, RepresentationType.PDFLibDocument, file.filename+"_scaledContent"); -}; +} function scalePage(page: PDFPage, scaleFactor: number) { const width = page.getWidth(); diff --git a/shared-operations/src/functions/scalePage.ts b/shared-operations/src/functions/scalePage.ts index f04c3f19d..b582f9a78 100644 --- a/shared-operations/src/functions/scalePage.ts +++ b/shared-operations/src/functions/scalePage.ts @@ -1,24 +1,24 @@ -import Joi from 'joi'; -import { PDFPage } from 'pdf-lib'; -import { PdfFile, RepresentationType, JoiPDFFileSchema } from '../wrappers/PdfFileJoi'; +import Joi from "joi"; +import { PDFPage } from "pdf-lib"; +import { PdfFile, RepresentationType, JoiPDFFileSchema } from "../wrappers/PdfFileJoi"; const whSchema = Joi.string().custom((value, helpers) => { - console.log("value.pageSize", typeof value) + console.log("value.pageSize", typeof value); try { const obj = JSON.parse(value); if (!obj.width && !obj.height) { - return helpers.error('any.required', { message: 'At least one of width/height must be present' }); + return helpers.error("any.required", { message: "At least one of width/height must be present" }); } - if (typeof obj.width != 'number' && typeof obj.width != 'undefined') { - return helpers.error('any.invalid', { message: 'Width must be a number if present' }); + if (typeof obj.width != "number" && typeof obj.width != "undefined") { + return helpers.error("any.invalid", { message: "Width must be a number if present" }); } - if (typeof obj.height != 'number' && typeof obj.height != 'undefined') { - return helpers.error('any.invalid', { message: 'Height must be a number if present' }); + if (typeof obj.height != "number" && typeof obj.height != "undefined") { + return helpers.error("any.invalid", { message: "Height must be a number if present" }); } return obj; } catch (error) { - return helpers.error('any.invalid', { message: 'Value must be a valid JSON' }); + return helpers.error("any.invalid", { message: "Value must be a valid JSON" }); } }); @@ -28,7 +28,7 @@ export const ScalePageSchema = Joi.object({ }); -export type ScalePageParamsType = { +export interface ScalePageParamsType { file: PdfFile; pageSize: { width?:number,height?:number }|{ width?:number,height?:number }[]; } @@ -41,17 +41,17 @@ export async function scalePage(params: ScalePageParamsType): Promise { if (Array.isArray(pageSize)) { if (pageSize.length != pages.length) { - throw new Error(`Number of given sizes '${pageSize.length}' is not the same as the number of pages '${pages.length}'`) + throw new Error(`Number of given sizes '${pageSize.length}' is not the same as the number of pages '${pages.length}'`); } for (let i=0; i resize(page, pageSize)); + pages.forEach(page => { resize(page, pageSize) }); } return new PdfFile(file.originalFilename, pdfDoc, RepresentationType.PDFLibDocument, file.filename+"_scaledPages"); -}; +} function resize(page: PDFPage, newSize: {width?:number,height?:number}) { const calculatedSize = calculateSize(page, newSize); @@ -74,7 +74,7 @@ function calculateSize(page: PDFPage, newSize: {width?:number,height?:number}): const ratio = oldSize.height / oldSize.width; return { width: newSize.width, height: newSize.width * ratio }; } - return { width: newSize.width!, height: newSize.height! }; + return { width: newSize.width, height: newSize.height }; } export const PageSize = Object.freeze({ diff --git a/shared-operations/src/functions/splitPagesByPreset.ts b/shared-operations/src/functions/splitPagesByPreset.ts index 5d96d6479..617827ce4 100644 --- a/shared-operations/src/functions/splitPagesByPreset.ts +++ b/shared-operations/src/functions/splitPagesByPreset.ts @@ -1,10 +1,10 @@ -import { PdfFile } from '../wrappers/PdfFile.js'; +import { PdfFile } from "../wrappers/PdfFile.js"; import { splitPagesByIndex } from "./common/splitPagesByIndex.js"; import { detectEmptyPages } from "./common/detectEmptyPages.js"; import { detectQRCodePages } from "./common/detectQRCodePages.js"; -export type SplitPageByPresetParamsType = { +export interface SplitPageByPresetParamsType { file: PdfFile; type: "BAR_CODE"|"QR_CODE"|"BLANK_PAGE"; whiteThreashold?: number; @@ -16,22 +16,22 @@ export async function splitPagesByPreset(params: SplitPageByPresetParamsType): P let splitAtPages: number[]; switch (type) { - case "BAR_CODE": - // TODO: Implement - throw new Error("This split-type has not been implemented yet"); + case "BAR_CODE": + // TODO: Implement + throw new Error("This split-type has not been implemented yet"); - case "QR_CODE": - splitAtPages = await detectQRCodePages(file); - break; + case "QR_CODE": + splitAtPages = await detectQRCodePages(file); + break; - case "BLANK_PAGE": - if (!whiteThreashold) - throw new Error("White threshold not provided"); - splitAtPages = await detectEmptyPages(file, whiteThreashold); - break; + case "BLANK_PAGE": + if (!whiteThreashold) + throw new Error("White threshold not provided"); + splitAtPages = await detectEmptyPages(file, whiteThreashold); + break; - default: - throw new Error("An invalid split-type was provided."); + default: + throw new Error("An invalid split-type was provided."); } console.debug("Split At Pages: ", splitAtPages); @@ -41,4 +41,4 @@ export async function splitPagesByPreset(params: SplitPageByPresetParamsType): P newFiles[i].filename += "_split-"+i; } return newFiles; -}; +} diff --git a/shared-operations/src/functions/splitPdfByIndex.ts b/shared-operations/src/functions/splitPdfByIndex.ts index 89aec4092..edbe5cdaf 100644 --- a/shared-operations/src/functions/splitPdfByIndex.ts +++ b/shared-operations/src/functions/splitPdfByIndex.ts @@ -1,9 +1,9 @@ -import { PdfFile } from '../wrappers/PdfFile.js'; -import { parsePageIndexSpecification } from './common/pageIndexesUtils' -import { splitPagesByIndex } from './common/splitPagesByIndex.js'; +import { PdfFile } from "../wrappers/PdfFile.js"; +import { parsePageIndexSpecification } from "./common/pageIndexesUtils"; +import { splitPagesByIndex } from "./common/splitPagesByIndex.js"; -export type SplitPdfByIndexParamsType = { +export interface SplitPdfByIndexParamsType { file: PdfFile; pageIndexes: string | number[]; } @@ -11,7 +11,7 @@ export async function splitPdfByIndex(params: SplitPdfByIndexParamsType): Promis const { file, pageIndexes } = params; const pdfLibDocument = await file.pdfLibDocument; - var indexes = pageIndexes; + let indexes = pageIndexes; if (!Array.isArray(indexes)) { indexes = parsePageIndexSpecification(indexes, pdfLibDocument.getPageCount()); diff --git a/shared-operations/src/functions/updateMetadata.ts b/shared-operations/src/functions/updateMetadata.ts index 1b6c5d916..39aa52923 100644 --- a/shared-operations/src/functions/updateMetadata.ts +++ b/shared-operations/src/functions/updateMetadata.ts @@ -1,7 +1,7 @@ -import { PdfFile } from '../wrappers/PdfFile'; +import { PdfFile } from "../wrappers/PdfFile"; -export type UpdateMetadataParams = { +export interface UpdateMetadataParams { file: PdfFile, deleteAll?: boolean, // Delete all metadata if set to true author?: string, // The author of the document @@ -21,34 +21,34 @@ export async function updateMetadata(params: UpdateMetadataParams): Promise import(`./${namespace}/${language}.json`))) .init({ // debug: true, - ns: ['common'], // Preload this namespace, no need to add the others - defaultNS: 'common', - fallbackLng: 'en', + ns: ["common"], // Preload this namespace, no need to add the others + defaultNS: "common", + fallbackLng: "en", interpolation: { escapeValue: false, } diff --git a/shared-operations/src/workflow/getOperatorByName.ts b/shared-operations/src/workflow/getOperatorByName.ts index 1c41a1d2e..30fa9f3f5 100644 --- a/shared-operations/src/workflow/getOperatorByName.ts +++ b/shared-operations/src/workflow/getOperatorByName.ts @@ -4,7 +4,7 @@ import { Operator } from "../functions"; import { Impose } from "../functions/impose"; export const Operators = { Impose: Impose -} +}; // TODO: Convert this to a map or similar export function getOperatorByName(name: string): typeof Operator | undefined { @@ -13,7 +13,7 @@ export function getOperatorByName(name: string): typeof Operator | undefined { // Loop over each default export Object.entries(Operators).some(([className, exportedClass]) => { // Check if the exported item is a class - if (typeof exportedClass === 'function' && exportedClass.prototype) { + if (typeof exportedClass === "function" && exportedClass.prototype) { if (exportedClass.type === name) { foundClass = exportedClass; return true; // Stop the iteration @@ -28,4 +28,4 @@ export function getOperatorByName(name: string): typeof Operator | undefined { export function listOperatorNames(): string[] { // TODO: Implement this return []; -} \ No newline at end of file +} diff --git a/shared-operations/src/workflow/organizeWaitOperations.ts b/shared-operations/src/workflow/organizeWaitOperations.ts index aa3325904..3fe9b519e 100644 --- a/shared-operations/src/workflow/organizeWaitOperations.ts +++ b/shared-operations/src/workflow/organizeWaitOperations.ts @@ -4,8 +4,8 @@ import { PdfFile } from "../wrappers/PdfFile"; export function organizeWaitOperations(actions: Action[]) { // Initialize an object to store the counts and associated "done" operations - const waitCounts: {[key: string]: number} = {}; - const doneOperations: {[key: string]: Action} = {}; + const waitCounts: Record = {}; + const doneOperations: Record = {}; // Function to count "type: wait" operations and associate "done" operations per id function countWaitOperationsAndDone(actions: Action[]) { @@ -43,10 +43,8 @@ export function organizeWaitOperations(actions: Action[]) { return result; } -export type ResultType = { - [key: string]: { +export type ResultType = Record; \ No newline at end of file diff --git a/shared-operations/src/workflow/traverseOperations.ts b/shared-operations/src/workflow/traverseOperations.ts index a2f3e50cd..4dd684aca 100644 --- a/shared-operations/src/workflow/traverseOperations.ts +++ b/shared-operations/src/workflow/traverseOperations.ts @@ -34,27 +34,27 @@ export async function traverseOperations(operations: Action[], input: PdfFile[], async function computeOperation(action: Action, input: PdfFile[], progressCallback: (state: Progress) => void): Promise { console.log("Input: ", input); switch (action.type) { - case "done": // Skip this, because it is a valid node. - break; - case "wait": - const waitOperation = waitOperations[(action as WaitAction).values.id]; + case "done": // Skip this, because it is a valid node. + break; + case "wait": + const waitOperation = waitOperations[(action as WaitAction).values.id]; - waitOperation.input.concat(input); // TODO: May have unexpected concequences. Needs further testing! + waitOperation.input.concat(input); // TODO: May have unexpected concequences. Needs further testing! - waitOperation.waitCount--; - if(waitOperation.waitCount == 0 && waitOperation.doneOperation.actions) { - await nextOperation(waitOperation.doneOperation.actions, waitOperation.input, progressCallback); - } - break; - default: - const operator = getOperatorByName(action.type); - if(operator) { - let operation = new operator(action); - input = await operation.run(input, progressCallback); - await nextOperation(action.actions, input, progressCallback); - } - else - throw new Error(`${action.type} not implemented yet.`); + waitOperation.waitCount--; + if(waitOperation.waitCount == 0 && waitOperation.doneOperation.actions) { + await nextOperation(waitOperation.doneOperation.actions, waitOperation.input, progressCallback); + } + break; + default: + const operator = getOperatorByName(action.type); + if(operator) { + const operation = new operator(action); + input = await operation.run(input, progressCallback); + await nextOperation(action.actions, input, progressCallback); + } + else + throw new Error(`${action.type} not implemented yet.`); } } } \ No newline at end of file diff --git a/shared-operations/src/workflow/validateOperations.ts b/shared-operations/src/workflow/validateOperations.ts index e0d3dbb44..66de33812 100644 --- a/shared-operations/src/workflow/validateOperations.ts +++ b/shared-operations/src/workflow/validateOperations.ts @@ -17,7 +17,7 @@ export function validateOperations(actions: Action[]): { valid: boolean, reason? const operator = getOperatorByName(action.type); if(!operator) { - return { valid: false, reason: `action.type ${action.type} does not exist` } + return { valid: false, reason: `action.type ${action.type} does not exist` }; } const validationResult = operator.schema.validate({values: action.values}); @@ -44,7 +44,7 @@ export function validateOperations(actions: Action[]): { valid: boolean, reason? } } else if (action.type === "done") { - return { valid: false, reason: `There shouldn't be a done action here.` }; + return { valid: false, reason: "There shouldn't be a done action here." }; } else { const receivingOperator = getOperatorByName(childAction.type); diff --git a/shared-operations/src/wrappers/PdfFile.ts b/shared-operations/src/wrappers/PdfFile.ts index da5cef77a..2c9273a0f 100644 --- a/shared-operations/src/wrappers/PdfFile.ts +++ b/shared-operations/src/wrappers/PdfFile.ts @@ -1,7 +1,7 @@ -import * as PDFJS from 'pdfjs-dist'; -import type { PDFDocumentProxy as PDFJSDocument } from 'pdfjs-dist/types/src/display/api'; -import { PDFDocument as PDFLibDocument } from 'pdf-lib'; -import Joi from 'joi'; +import * as PDFJS from "pdfjs-dist"; +import type { PDFDocumentProxy as PDFJSDocument } from "pdfjs-dist/types/src/display/api"; +import { PDFDocument as PDFLibDocument } from "pdf-lib"; +import Joi from "joi"; export enum RepresentationType { Uint8Array, @@ -17,25 +17,25 @@ export class PdfFile { get uint8Array() : Promise { switch (this.representationType) { - case RepresentationType.Uint8Array: - return new Promise((resolve) => { - resolve(this.representation as Uint8Array); - }); - case RepresentationType.PDFLibDocument: - return new Promise(async (resolve) => { - var uint8Array = await (this.representation as PDFLibDocument).save(); - this.uint8Array = uint8Array; - resolve(uint8Array); - }); - case RepresentationType.PDFJSDocument: - return new Promise(async (resolve) => { - var uint8Array = await (this.representation as PDFJSDocument).getData(); - this.uint8Array = uint8Array; - resolve(uint8Array); - }); - default: - console.error("unhandeled PDF type: " + typeof this.representation as string); - throw Error("unhandeled PDF type"); + case RepresentationType.Uint8Array: + return new Promise((resolve) => { + resolve(this.representation as Uint8Array); + }); + case RepresentationType.PDFLibDocument: + return new Promise(async (resolve) => { + const uint8Array = await (this.representation as PDFLibDocument).save(); + this.uint8Array = uint8Array; + resolve(uint8Array); + }); + case RepresentationType.PDFJSDocument: + return new Promise(async (resolve) => { + const uint8Array = await (this.representation as PDFJSDocument).getData(); + this.uint8Array = uint8Array; + resolve(uint8Array); + }); + default: + console.error("unhandeled PDF type: " + typeof this.representation ); + throw Error("unhandeled PDF type"); } } set uint8Array(value: Uint8Array) { @@ -45,19 +45,19 @@ export class PdfFile { get pdfLibDocument() : Promise { switch (this.representationType) { - case RepresentationType.PDFLibDocument: - return new Promise((resolve) => { - resolve(this.representation as PDFLibDocument); - }); - default: - return new Promise(async (resolve) => { - var uint8Array = await this.uint8Array; - var pdfLibDoc = await PDFLibDocument.load(uint8Array, { - updateMetadata: false, - }); - this.pdfLibDocument = pdfLibDoc; - resolve(pdfLibDoc); + case RepresentationType.PDFLibDocument: + return new Promise((resolve) => { + resolve(this.representation as PDFLibDocument); + }); + default: + return new Promise(async (resolve) => { + const uint8Array = await this.uint8Array; + const pdfLibDoc = await PDFLibDocument.load(uint8Array, { + updateMetadata: false, }); + this.pdfLibDocument = pdfLibDoc; + resolve(pdfLibDoc); + }); } } set pdfLibDocument(value: PDFLibDocument) { @@ -67,16 +67,16 @@ export class PdfFile { get pdfJsDocument() : Promise { switch (this.representationType) { - case RepresentationType.PDFJSDocument: - return new Promise((resolve) => { - resolve(this.representation as PDFJSDocument); - }); - default: - return new Promise(async (resolve) => { - const pdfjsDoc = await PDFJS.getDocument(await this.uint8Array).promise; - this.pdfJsDocument = pdfjsDoc; - resolve(pdfjsDoc); - }); + case RepresentationType.PDFJSDocument: + return new Promise((resolve) => { + resolve(this.representation as PDFJSDocument); + }); + default: + return new Promise(async (resolve) => { + const pdfjsDoc = await PDFJS.getDocument(await this.uint8Array).promise; + this.pdfJsDocument = pdfjsDoc; + resolve(pdfjsDoc); + }); } } set pdfJsDocument(value: PDFJSDocument) { diff --git a/shared-operations/src/wrappers/PdfFileJoi.ts b/shared-operations/src/wrappers/PdfFileJoi.ts index 6ecf94e5a..9955f238a 100644 --- a/shared-operations/src/wrappers/PdfFileJoi.ts +++ b/shared-operations/src/wrappers/PdfFileJoi.ts @@ -23,5 +23,5 @@ export const JoiPDFFileSchema = Joi.custom((value: Express.Multer.File[] /* <- a }, "pdffile validation"); function isPdfFileArray(value: any[]): value is PdfFile[] { // "is" is a ts-typeguard - https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates - return value.every((e) => e instanceof PdfFile) + return value.every((e) => e instanceof PdfFile); } \ No newline at end of file