Moved to use npm workspaces. updated imports

This commit is contained in:
Saud Fatayerji 2023-10-26 15:42:18 +03:00
parent 989a5e02b9
commit 19f4f7febb
16 changed files with 10347 additions and 124 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
*/node_modules/
node_modules/
*.code-workspace

22
CONTRIBUTE.md Normal file
View File

@ -0,0 +1,22 @@
# Contribute
This file should introduce you with the concepts and tools used in this project.
## PDF Library Docs
- [pdf-lib](https://pdf-lib.js.org) - js
- [pdfcpu](https://pdfcpu.io) - go-wasm
## Adding a PDF Operation
StirlingPDF aims to support as many types of operations as possible, including some that cannot be executed in the client. Because of this, we have decided to move some of the shared functionality into it's own node module so that it can be shared by both client and server.
### Adding a shared (server + client) operation
1. Add the code for the operation to a new file in the [functions folder](/shared-operations/functions/).
> **NOTE:** all functions in these files use **dependency injection** (see existing functions for examples).
>
> **Explanation:** Because the server and client import libraries in different ways, we import the library as needed in the wrapper module, then pass into the a operation function as a parameter.
2. Now that we have the function code, we need to tell the other modules that it exists. Edit the [server operations](/server-node/public/pdf-operations.js) and the [client operations](/client-ionic/src/utils/pdf-operations.js) files to add your new operation! (Try to follow existing patterns where possible, keep the added operations in alphabetical order in the files).
### Adding a server only operation
> WIP

View File

@ -1,5 +1,5 @@
{
"name": "ionic-app-base",
"name": "@stirling-pdf/client-ionic",
"private": true,
"version": "0.0.0",
"type": "module",
@ -24,7 +24,7 @@
"react-dom": "^18.2.0",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4",
"shared-operations": "file:../shared-operations"
"@stirling-pdf/shared-operations": "*"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",

View File

@ -1,14 +1,19 @@
// PDFLib gets importet via index.html script-tag
import * as pdfcpuWraopper from "../../../server-node/public/wasm/pdfcpu-wrapper-browser.js";
import { extractPages as dependantExtractPages } from "../../../shared-operations/functions/extractPages.js";
import { impose as dependantImpose } from '../../../shared-operations/functions/impose.js';
import { mergePDFs as dependantMergePDFs } from '../../../shared-operations/functions/mergePDFs.js';
import { rotatePages as dependantRotatePages } from '../../../shared-operations/functions/rotatePages.js';
import { scaleContent as dependantScaleContent} from '../../../shared-operations/functions/scaleContent.js';
import { scalePage as dependantScalePage } from '../../../shared-operations/functions/scalePage.js';
import { splitPDF as dependantSplitPDF } from '../../../shared-operations/functions/splitPDF.js';
import { editMetadata as dependantEditMetadata} from "../../../shared-operations/functions/editMetadata.js";
import { editMetadata as dependantEditMetadata} from "@stirling-pdf/shared-operations/functions/editMetadata.js";
import { extractPages as dependantExtractPages } from "@stirling-pdf/shared-operations/functions/extractPages.js";
import { impose as dependantImpose } from '@stirling-pdf/shared-operations/functions/impose.js';
import { mergePDFs as dependantMergePDFs } from '@stirling-pdf/shared-operations/functions/mergePDFs.js';
import { organizePages as dependantOrganizePages } from '@stirling-pdf/shared-operations/functions/organizePages.js';
import { rotatePages as dependantRotatePages } from '@stirling-pdf/shared-operations/functions/rotatePages.js';
import { scaleContent as dependantScaleContent} from '@stirling-pdf/shared-operations/functions/scaleContent.js';
import { scalePage as dependantScalePage } from '@stirling-pdf/shared-operations/functions/scalePage.js';
import { splitPDF as dependantSplitPDF } from '@stirling-pdf/shared-operations/functions/splitPDF.js';
export async function editMetadata(snapshot, metadata) {
return dependantEditMetadata(snapshot, metadata, PDFLib);
}
export async function extractPages(snapshot, pagesToExtractArray) {
return dependantExtractPages(snapshot, pagesToExtractArray, PDFLib);
@ -22,6 +27,10 @@ export async function mergePDFs(snapshots) {
return dependantMergePDFs(snapshots, PDFLib);
}
export async function organizePages(snapshot, operation, customOrderString) {
return dependantOrganizePages(snapshot, operation, customOrderString, PDFLib);
}
export async function rotatePages(snapshot, rotation) {
return dependantRotatePages(snapshot, rotation, PDFLib);
}
@ -37,7 +46,3 @@ export async function scalePage(snapshot, pageSize) {
export async function splitPDF(snapshot, splitAfterPageArray) {
return dependantSplitPDF(snapshot, splitAfterPageArray, PDFLib);
}
export async function editMetadata(snapshot, metadata) {
return dependantEditMetadata(snapshot, metadata, PDFLib);
}

10137
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

13
package.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "stirling-pdf",
"private":"true",
"workspaces":[
"client-ionic",
"server-node",
"shared-operations"
],
"scripts": {
"node-server-dev": "node ./server-node/index.js",
"client-ionic-dev": "node ./server-node/index.js"
}
}

View File

@ -1,32 +0,0 @@
# Contribute
This file should introduce you with the concepts and tools used in this project.
## PDF Library Docs
- [pdf-lib](https://pdf-lib.js.org) - js
- [pdfcpu](https://pdfcpu.io) - go-wasm
## Adding a PDF Function
In order to add a PDF-Function there are several files that need to be changed. If the function is on the backend only, or on only on the frontend, you just need to add it to one of the locations. If it is available on both, you need to update both locations.
Dependency Injection is used to accomodate for different imports across platforms.
Backend functions can have different implementations than their frontend counterparts if neccesary. Otherwise they can just link to their frontend implementation.
Registering functions will also pass them their dependencies for the specific target platform (Node, Browser)
[Traverse Operations](/public/traverseOperations.js)\
### Backend
[Register Functions](/functions.js)\
[Functions Folder](/functions/)
Examples that go in the node-functions folder: server-side-only functions, different implementation for backend
### Frontend
[Register Functions](/public/functions.js)\
[Functions Folder](/public/functions/)
Examples that go in the browser-functions folder: client-side-only functions, shared functions

View File

@ -1,48 +0,0 @@
import PDFLib from 'pdf-lib';
import * as pdfcpuWraopper from "./public/wasm/pdfcpu-wrapper-node.js";
import { extractPages as dependantExtractPages } from "./public/functions/extractPages.js";
import { impose as dependantImpose } from './public/functions/impose.js';
import { mergePDFs as dependantMergePDFs } from './public/functions/mergePDFs.js';
import { rotatePages as dependantRotatePages } from './public/functions/rotatePages.js';
import { scaleContent as dependantScaleContent} from './public/functions/scaleContent.js';
import { scalePage as dependantScalePage } from './public/functions/scalePage.js';
import { splitPDF as dependantSplitPDF } from './public/functions/splitPDF.js';
import { editMetadata as dependantEditMetadata } from './public/functions/editMetadata.js';
import { organizePages as dependantOrganizePages } from './public/functions/organizePages.js';
export async function extractPages(snapshot, pagesToExtractArray) {
return dependantExtractPages(snapshot, pagesToExtractArray, PDFLib);
}
export async function impose(snapshot, nup, format) {
return dependantImpose(snapshot, nup, format, pdfcpuWraopper);
}
export async function mergePDFs(snapshots) {
return dependantMergePDFs(snapshots, PDFLib);
}
export async function rotatePages(snapshot, rotation) {
return dependantRotatePages(snapshot, rotation, PDFLib);
}
export async function scaleContent(snapshot, scaleFactor) {
return dependantScaleContent(snapshot, scaleFactor, PDFLib);
}
export async function scalePage(snapshot, pageSize) {
return dependantScalePage(snapshot, pageSize, PDFLib);
}
export async function splitPDF(snapshot, splitAfterPageArray) {
return dependantSplitPDF(snapshot, splitAfterPageArray, PDFLib);
}
export async function editMetadata(snapshot, metadata) {
return dependantEditMetadata(snapshot, metadata, PDFLib);
}
export async function organizePages(snapshot, operation, customOrderString) {
return dependantOrganizePages(snapshot, operation, customOrderString, PDFLib);
}

View File

@ -1,7 +1,6 @@
{
"name": "pdfjs",
"version": "1.0.0",
"description": "",
"name": "@stirling-pdf/server-node",
"version": "0.0.0",
"main": "index.js",
"scripts": {
"test": "node ."
@ -14,7 +13,7 @@
"express": "^4.18.2",
"express-fileupload": "^1.4.1",
"pdf-lib": "^1.17.1",
"shared-operations": "file:../shared-operations"
"@stirling-pdf/shared-operations": "*"
},
"type": "module"
}

View File

@ -2,7 +2,7 @@ import { scaleContent } from "./functions/scaleContent.js";
import { scalePage, PageSize } from "./functions/scalePage.js";
import * as exampleWorkflows from "./exampleWorkflows.js";
import { traverseOperations } from "./traverseOperations.js";
import * as Functions from "./functions.js";
import * as Functions from "./pdf-operations.js";
(async (workflow) => {
const pdfFileInput = document.getElementById('pdfFile');

View File

@ -1,15 +1,19 @@
// PDFLib gets importet via index.html script-tag
import * as pdfcpuWraopper from "./wasm/pdfcpu-wrapper-browser.js";
import PDFLib from 'pdf-lib';
import * as pdfcpuWraopper from "./wasm/pdfcpu-wrapper-node.js";
import { extractPages as dependantExtractPages } from "shared-operations/functions/extractPages.js";
import { impose as dependantImpose } from 'shared-operations/functions/impose.js';
import { mergePDFs as dependantMergePDFs } from 'shared-operations/functions/mergePDFs.js';
import { rotatePages as dependantRotatePages } from 'shared-operations/functions/rotatePages.js';
import { scaleContent as dependantScaleContent} from 'shared-operations/functions/scaleContent.js';
import { scalePage as dependantScalePage } from 'shared-operations/functions/scalePage.js';
import { splitPDF as dependantSplitPDF } from 'shared-operations/functions/splitPDF.js';
import { editMetadata as dependantEditMetadata} from "shared-operations/functions/editMetadata.js";
import { organizePages as dependantOrganizePages} from "shared-operations/functions/organizePages.js";
import { editMetadata as dependantEditMetadata } from '@stirling-pdf/shared-operations/functions/editMetadata.js';
import { extractPages as dependantExtractPages } from '@stirling-pdf/shared-operations/functions/extractPages.js';
import { impose as dependantImpose } from '@stirling-pdf/shared-operations/functions/impose.js';
import { mergePDFs as dependantMergePDFs } from '@stirling-pdf/shared-operations/functions/mergePDFs.js';
import { organizePages as dependantOrganizePages } from '@stirling-pdf/shared-operations/functions/organizePages.js';
import { rotatePages as dependantRotatePages } from '@stirling-pdf/shared-operations/functions/rotatePages.js';
import { scaleContent as dependantScaleContent} from '@stirling-pdf/shared-operations/functions/scaleContent.js';
import { scalePage as dependantScalePage } from '@stirling-pdf/shared-operations/functions/scalePage.js';
import { splitPDF as dependantSplitPDF } from '@stirling-pdf/shared-operations/functions/splitPDF.js';
export async function editMetadata(snapshot, metadata) {
return dependantEditMetadata(snapshot, metadata, PDFLib);
}
export async function extractPages(snapshot, pagesToExtractArray) {
return dependantExtractPages(snapshot, pagesToExtractArray, PDFLib);
@ -23,6 +27,10 @@ export async function mergePDFs(snapshots) {
return dependantMergePDFs(snapshots, PDFLib);
}
export async function organizePages(snapshot, operation, customOrderString) {
return dependantOrganizePages(snapshot, operation, customOrderString, PDFLib);
}
export async function rotatePages(snapshot, rotation) {
return dependantRotatePages(snapshot, rotation, PDFLib);
}
@ -38,11 +46,3 @@ export async function scalePage(snapshot, pageSize) {
export async function splitPDF(snapshot, splitAfterPageArray) {
return dependantSplitPDF(snapshot, splitAfterPageArray, PDFLib);
}
export async function editMetadata(snapshot, metadata) {
return dependantEditMetadata(snapshot, metadata, PDFLib);
}
export async function organizePages(snapshot, operation, customOrderString) {
return dependantOrganizePages(snapshot, operation, customOrderString, PDFLib);
}

View File

@ -4,7 +4,7 @@ import { organizeWaitOperations } from "./organizeWaitOperations.js";
*
* @param {*} operations
* @param {*} input
* @param {import('./functions.js')} Functions
* @param {import('./pdf-operations.js')} Functions
* @returns
*/
export async function * traverseOperations(operations, input, Functions) {

View File

@ -3,7 +3,7 @@ import crypto from 'crypto';
import stream from "stream";
import Archiver from 'archiver';
import * as Functions from "../../functions.js";
import * as Functions from "../../public/pdf-operations.js";
import { traverseOperations } from "../../public/traverseOperations.js";
const activeWorkflows = {};

View File

@ -0,0 +1,115 @@
/**
* @typedef {"CUSTOM_PAGE_ORDER"|"REVERSE_ORDER"|"DUPLEX_SORT"|"BOOKLET_SORT"|"ODD_EVEN_SPLIT"|"REMOVE_FIRST"|"REMOVE_LAST"|"REMOVE_FIRST_AND_LAST"} OrderOperation
*/
/**
*
* @param {Uint16Array} snapshot
* @param {OrderOperation} operation
* @param {string} customOrderString
* @param {import('pdf-lib')} PDFLib
* @returns
*/
export async function organizePages(snapshot, operation, customOrderString, PDFLib) {
const pdfDoc = await PDFLib.PDFDocument.load(snapshot);
let subDocument = await PDFLib.PDFDocument.create();
const copiedPages = await subDocument.copyPages(pdfDoc, pdfDoc.getPageIndices());
const pageCount = pdfDoc.getPages().length;
switch (operation) {
case "CUSTOM_PAGE_ORDER":
console.log("Custom Order");
const pageOrderArray = parseCustomPageOrder(customOrderString, pageCount);
console.log(pageOrderArray);
const customOrderedPages = pageOrderArray.map((pageIndex) => copiedPages[pageIndex]);
customOrderedPages.forEach((page) => subDocument.addPage(page));
break;
case "REVERSE_ORDER":
const reversedPages = [];
for (let i = pageCount - 1; i >= 0; i--) {
reversedPages.push(copiedPages[i]);
}
reversedPages.forEach((page) => subDocument.addPage(page));
break;
case 'DUPLEX_SORT': //TODO: Needs to be checked by someone who knows more about duplex printing.
const duplexPages = [];
const half = (pageCount + 1) / 2
for (let i = 1; i <= half; i++) {
duplexPages.push(copiedPages[i - 1]);
if (i <= pageCount - half) {
duplexPages.push(copiedPages[pageCount - i]);
}
}
duplexPages.forEach((page) => subDocument.addPage(page));
break;
case 'BOOKLET_SORT':
const bookletPages = [];
for (let i = 0; i < pageCount / 2; i++) {
bookletPages.push(copiedPages[i]);
bookletPages.push(copiedPages[pageCount - i - 1]);
}
bookletPages.forEach((page) => subDocument.addPage(page));
break;
case 'ODD_EVEN_SPLIT':
const oddPages = [];
const evenPages = [];
for (let i = 0; i < pageCount; i++) {
if (i % 2 === 0) {
evenPages.push(copiedPages[i]);
} else {
oddPages.push(copiedPages[i]);
}
}
oddPages.forEach((page) => subDocument.addPage(page));
evenPages.forEach((page) => subDocument.addPage(page));
break;
case 'REMOVE_FIRST':
pdfDoc.removePage(0);
subDocument = pdfDoc;
break;
case 'REMOVE_LAST':
pdfDoc.removePage(pageCount - 1);
subDocument = pdfDoc;
break;
case 'REMOVE_FIRST_AND_LAST':
pdfDoc.removePage(0);
pdfDoc.removePage(pageCount - 2);
subDocument = pdfDoc;
break;
default:
throw new Error("Operation not supported");
break;
}
return subDocument.save();
};
function parseCustomPageOrder(customOrder, pageCount) {
const pageOrderArray = [];
const ranges = customOrder.split(',');
ranges.forEach((range) => {
if (range.includes('-')) {
const [start, end] = range.split('-').map(Number);
for (let i = start; i <= end; i++) {
pageOrderArray.push(i - 1);
}
} else if (range.includes('n')) {
const [even, odd] = range.split('n').map(Number);
for (let i = 1; i <= pageCount; i++) {
if (i % 2 === 0) {
pageOrderArray.push((i * even) - 1);
} else {
pageOrderArray.push((i * odd) - 1);
}
}
} else {
pageOrderArray.push(Number(range) - 1);
}
});
return pageOrderArray;
}

13
shared-operations/package-lock.json generated Normal file
View File

@ -0,0 +1,13 @@
{
"name": "@stirling-pdf/shared-operations",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@stirling-pdf/shared-operations",
"version": "0.0.0",
"license": "ISC"
}
}
}

View File

@ -1,7 +1,6 @@
{
"name": "shared-operations",
"version": "1.0.0",
"description": "",
"name": "@stirling-pdf/shared-operations",
"version": "0.0.0",
"main": "index.js",
"type": "module",
"scripts": {