mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-10-25 11:17:28 +02:00 
			
		
		
		
	node based backend
This commit is contained in:
		
							parent
							
								
									542d74b9cc
								
							
						
					
					
						commit
						76e37354e1
					
				| @ -12,6 +12,19 @@ | ||||
| </head> | ||||
| <body> | ||||
|     <input type="file" id="pdfFile" accept=".pdf"> | ||||
|     <a id="downloadLink" style="display: none;" download="modified.pdf">Download Modified PDF</a> | ||||
| 
 | ||||
|     <ul id="operations"> | ||||
| 
 | ||||
|     </ul> | ||||
| 
 | ||||
|     <select id="pdfOptions"> | ||||
|         <option value="scaleContent">Scale Content</option> | ||||
|         <option value="changePageSize">Change Page Size</option> | ||||
|         <option value="mergePDFs">Merge PDFs</option> | ||||
|         <option value="splitPDFs">Split PDFs</option> | ||||
|     </select> | ||||
|     <button id="addButton">Add</button> | ||||
| 
 | ||||
|     <button id="doneButton">Done</button> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										194
									
								
								public/index.js
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								public/index.js
									
									
									
									
									
								
							| @ -1,16 +1,192 @@ | ||||
| import { scaleContent } from "./functions/scaleContent.js"; | ||||
| import { scalePage, PageSize } from "./functions/scalePage.js"; | ||||
| import { organizeWaitOperations } from "./organizeWaitOperations.js"; | ||||
| import { testWorkflow } from "./testWorkflow.js"; | ||||
| 
 | ||||
| (async () => { | ||||
| (async (workflow) => { | ||||
|     const pdfFileInput = document.getElementById('pdfFile'); | ||||
|     const doneButton = document.getElementById("doneButton"); | ||||
| 
 | ||||
|     pdfFileInput.addEventListener('change', async (e) => { | ||||
|         const file = e.target.files[0]; | ||||
|         if (file) { | ||||
|             let pdfBuffer = new Uint8Array(await file.arrayBuffer()); | ||||
|             pdfBuffer = await scaleContent(pdfBuffer, 2); | ||||
|             pdfBuffer = await scalePage(pdfBuffer, PageSize.letter); | ||||
|             download(pdfBuffer, "pdf-lib_creation_example.pdf", "application/pdf"); | ||||
|     doneButton.addEventListener('click', async (e) => { | ||||
|         const files = Array.from(pdfFileInput.files); | ||||
|         console.log(files); | ||||
|         const pdfBuffers = await Promise.all(files.map(async file => { | ||||
|             return { | ||||
|                 originalFileName: file.name.replace(/\.[^/.]+$/, ""), | ||||
|                 fileName: file.name.replace(/\.[^/.]+$/, ""), | ||||
|                 buffer: new Uint8Array(await file.arrayBuffer()) | ||||
|             } | ||||
|         })); | ||||
|         console.log(pdfBuffers); | ||||
| 
 | ||||
|         const waitOperations = organizeWaitOperations(workflow.operations); | ||||
| 
 | ||||
|         nextOperation(workflow.operations, pdfBuffers); | ||||
| 
 | ||||
|         async function nextOperation(operations, input) { | ||||
|             if(Array.isArray(operations) && operations.length == 0) { // isEmpty
 | ||||
|                 console.log("operation done: " + input.fileName); | ||||
|                 //TODO: Download Restult
 | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             for (let i = 0; i < operations.length; i++) { | ||||
|                 console.warn(input); | ||||
|                 await computeOperation(operations[i], structuredClone(input)); // break references
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         async function computeOperation(operation, input) { | ||||
|             switch (operation.type) { | ||||
|                 case "done": | ||||
|                     console.log("Done operation will get called if all waits are done. Skipping for now.") | ||||
|                     break; | ||||
|                 case "wait": | ||||
|                     const waitOperation = waitOperations[operation.values.id]; | ||||
|                     waitOperation.input.push(input); | ||||
|                     waitOperation.waitCount--; | ||||
|                     if(waitOperation.waitCount == 0) { | ||||
|                         await nextOperation(waitOperation.doneOperation.operations, waitOperation.input); | ||||
|                     } | ||||
|                     break; | ||||
|                 case "removeObjects": | ||||
|                     if(Array.isArray(input)) { | ||||
|                         for (let i = 0; i < input.length; i++) { | ||||
|                             // TODO: modfiy input
 | ||||
|                             input[i].fileName += "_removedObjects"; | ||||
|                             await nextOperation(operation.operations, input[i]); | ||||
|                         } | ||||
|                     } | ||||
|                     else { | ||||
|                         // TODO: modfiy input
 | ||||
|                         input.fileName += "_removedObjects"; | ||||
|                         await nextOperation(operation.operations, input); | ||||
|                     } | ||||
|                     break; | ||||
|                 case "extract": | ||||
|                     if(Array.isArray(input)) { | ||||
|                         for (let i = 0; i < input.length; i++) { | ||||
|                             // TODO: modfiy input
 | ||||
|                             input[i].fileName += "_extractedPages"; | ||||
|                             await nextOperation(operation.operations, input[i]); | ||||
|                         } | ||||
|                     } | ||||
|                     else { | ||||
|                         // TODO: modfiy input
 | ||||
|                         input.fileName += "_extractedPages"; | ||||
|                         await nextOperation(operation.operations, input); | ||||
|                     } | ||||
|                     break; | ||||
|                 case "fillField": | ||||
|                     if(Array.isArray(input)) { | ||||
|                         for (let i = 0; i < input.length; i++) { | ||||
|                             // TODO: modfiy input
 | ||||
|                             input[i].fileName += "_filledField"; | ||||
|                             await nextOperation(operation.operations, input[i]); | ||||
|                         } | ||||
|                     } | ||||
|                     else { | ||||
|                         // TODO: modfiy input
 | ||||
|                         input.fileName += "_filledField"; | ||||
|                         await nextOperation(operation.operations, input); | ||||
|                     } | ||||
|                     break; | ||||
|                 case "extractImages": | ||||
|                     if(Array.isArray(input)) { | ||||
|                         for (let i = 0; i < input.length; i++) { | ||||
|                             // TODO: modfiy input
 | ||||
|                             input[i].fileName += "_extractedImages"; | ||||
|                             await nextOperation(operation.operations, input[i]); | ||||
|                         } | ||||
|                     } | ||||
|                     else { | ||||
|                         // TODO: modfiy input
 | ||||
|                         input.fileName += "_extractedImages"; | ||||
|                         await nextOperation(operation.operations, input); | ||||
|                     } | ||||
|                     break; | ||||
|                 case "merge": | ||||
|                     if(Array.isArray(input)) { | ||||
|                         input = { | ||||
|                             originalFileName: input.map(input => input.originalFileName).join("_and_"), | ||||
|                             fileName: input.map(input => input.fileName).join("_and_") + "_merged", | ||||
|                             buffer: input[0].buffer // TODO: merge inputs
 | ||||
|                         } | ||||
|                     } | ||||
|                     else { | ||||
|                         // TODO: modfiy input
 | ||||
|                         input.fileName += "_merged"; | ||||
|                     } | ||||
|                     await nextOperation(operation.operations, input); | ||||
|                     break; | ||||
|                 case "transform": { | ||||
|                     if(Array.isArray(input)) { | ||||
|                         for (let i = 0; i < input.length; i++) { | ||||
|                             // TODO: modfiy input
 | ||||
|                             input[i].fileName += "_transformed"; | ||||
|                             await nextOperation(operation.operations, input[i]); | ||||
|                         } | ||||
|                     } | ||||
|                     else { | ||||
|                         // TODO: modfiy input
 | ||||
|                         input.fileName += "_transformed"; | ||||
|                         await nextOperation(operation.operations, input); | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|                 default: | ||||
|                     console.log("operation type unknown: ", operation.type); | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         // if(selectedElementsList[0].textContent == "mergePDFs") {
 | ||||
| 
 | ||||
|         // }
 | ||||
| 
 | ||||
|         // // TODO: This can also be run serverside
 | ||||
|         // if(files.length > 1) {
 | ||||
|         //     files.forEach(file => {
 | ||||
|                  | ||||
|         //     });
 | ||||
|         // }
 | ||||
|         // else {
 | ||||
|         //     const file = files[0];
 | ||||
|         //     let pdfBuffer = new Uint8Array(await file.arrayBuffer());
 | ||||
|         //     if (file) {
 | ||||
|         //         for (let i = 0; i < selectedElementsList.length; i++) {
 | ||||
|         //           const selectedOption = selectedElementsList[i];
 | ||||
|                | ||||
|         //           // Perform actions based on the selected option using the switch statement
 | ||||
|         //           switch (selectedOption.textContent) {
 | ||||
|         //             case "scaleContent":
 | ||||
|         //                 pdfBuffer = await scaleContent(pdfBuffer, 2);
 | ||||
|         //                 break;
 | ||||
|         //             case "changePageSize":
 | ||||
|         //                 pdfBuffer = await scalePage(pdfBuffer, PageSize.letter);
 | ||||
|         //                 break;
 | ||||
|         //             default:
 | ||||
|         //                 // Handle any other actions or errors here
 | ||||
|         //                 throw new Error(`This action ${selectedOption.value} has not been implemented.`);
 | ||||
|         //             }
 | ||||
|         //         }
 | ||||
|         //         download(pdfBuffer, file.name.replace(/\.[^/.]+$/, "") + "_mod.pdf", "application/pdf");
 | ||||
|         //     }
 | ||||
|         // }
 | ||||
|     }); | ||||
| })(); | ||||
| 
 | ||||
|     // document.getElementById("addButton").addEventListener("click", function() {
 | ||||
|     //     const selectedOption = document.getElementById("pdfOptions").value;
 | ||||
|     //     const operations = document.getElementById("operations");
 | ||||
|        | ||||
|     //     if (selectedOption) {
 | ||||
|     //         const listItem = document.createElement("li");
 | ||||
|     //         listItem.textContent = selectedOption;
 | ||||
|     //         operations.appendChild(listItem);
 | ||||
|     //     }
 | ||||
|     // });
 | ||||
| })(testWorkflow); | ||||
|  | ||||
							
								
								
									
										43
									
								
								public/organizeWaitOperations.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								public/organizeWaitOperations.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| 
 | ||||
| export function organizeWaitOperations(operations) { | ||||
| 
 | ||||
|     // Initialize an object to store the counts and associated "done" operations
 | ||||
|     const waitCounts = {}; | ||||
|     const doneOperations = {}; | ||||
| 
 | ||||
|     // Function to count "type: wait" operations and associate "done" operations per id
 | ||||
|     function countWaitOperationsAndDone(operations) { | ||||
|         for (const operation of operations) { | ||||
|             if (operation.type === "wait") { | ||||
|                 const id = operation.values.id; | ||||
|                 if (id in waitCounts) { | ||||
|                     waitCounts[id]++; | ||||
|                 } else { | ||||
|                     waitCounts[id] = 1; | ||||
|                 } | ||||
|             } | ||||
|             if (operation.type === "done") { | ||||
|                 const id = operation.values.id; | ||||
|                 doneOperations[id] = operation; | ||||
|             } | ||||
|             if (operation.operations) { | ||||
|                 countWaitOperationsAndDone(operation.operations); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Start counting and associating from the root operations
 | ||||
|     countWaitOperationsAndDone(operations); | ||||
| 
 | ||||
|     // Combine counts and associated "done" operations
 | ||||
|     const result = {}; | ||||
|     for (const id in waitCounts) { | ||||
|         result[id] = { | ||||
|             waitCount: waitCounts[id], | ||||
|             doneOperation: doneOperations[id], | ||||
|             input: [] | ||||
|         }; | ||||
|     } | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										71
									
								
								public/testWorkflow.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								public/testWorkflow.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | ||||
| // JSON Representation of this Node Tree:
 | ||||
| // https://discord.com/channels/1068636748814483718/1099390571493195898/1118192754103693483
 | ||||
| // https://cdn.discordapp.com/attachments/1099390571493195898/1118192753759764520/image.png?ex=6537dba7&is=652566a7&hm=dc46820ef7c34bc37424794966c5f66f93ba0e15a740742c364d47d31ea119a9&
 | ||||
| 
 | ||||
| export const testWorkflow = { | ||||
|     outputOptions: { | ||||
|         zip: false, | ||||
|         awaitAllDone: true | ||||
|     }, | ||||
|     operations: [ | ||||
|         { | ||||
|             type: "extract", | ||||
|             values: { "index": "1" }, | ||||
|             operations: [ | ||||
|                 { | ||||
|                     type: "removeObjects", | ||||
|                     values: { "objectNames": "photo, josh" }, | ||||
|                     operations: [ | ||||
|                         { | ||||
|                             type: "wait", | ||||
|                             values: { "id": 1 } | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|             type: "extract", | ||||
|             values: { "index": "2-5" }, | ||||
|             operations: [  | ||||
|                 { | ||||
|                     type: "fillField", | ||||
|                     values: { "objectName": "name", "inputValue": "Josh" }, | ||||
|                     operations: [ | ||||
|                         { | ||||
|                             type: "wait", | ||||
|                             values: { "id": 1 } | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|             type: "done", // This gets called when the other merge-ops with the same id finish.
 | ||||
|             values: { "id": 1 }, | ||||
|             operations: [ | ||||
|                 { | ||||
|                     type: "merge", // This gets called when the other merge-ops with the same id finish.
 | ||||
|                     values: {}, | ||||
|                     operations: [] | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|             type: "extractImages", | ||||
|             values: {}, | ||||
|             operations: [] | ||||
|         }, | ||||
|         { | ||||
|             type: "merge", // This gets called when the other merge-ops with the same id finish.
 | ||||
|             values: {}, | ||||
|             operations: [ | ||||
|                 { | ||||
|                     type: "transform", | ||||
|                     values: { "scale": "2x", "rotation": "90deg" }, | ||||
|                     operations: [] | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|     ] | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user