mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-04-19 19:21:18 +00:00
Moved to use npm workspaces. updated imports
This commit is contained in:
parent
989a5e02b9
commit
19f4f7febb
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
*/node_modules/
|
||||
node_modules/
|
||||
*.code-workspace
|
||||
|
22
CONTRIBUTE.md
Normal file
22
CONTRIBUTE.md
Normal 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
|
@ -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",
|
||||
|
@ -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
10137
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
package.json
Normal file
13
package.json
Normal 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"
|
||||
}
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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"
|
||||
}
|
||||
|
@ -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');
|
||||
|
@ -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);
|
||||
}
|
@ -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) {
|
||||
|
@ -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 = {};
|
||||
|
115
shared-operations/functions/organizePages.js
Normal file
115
shared-operations/functions/organizePages.js
Normal 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
13
shared-operations/package-lock.json
generated
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
@ -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": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user