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> | </head> | ||||||
| <body> | <body> | ||||||
|     <input type="file" id="pdfFile" accept=".pdf"> |     <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> | </body> | ||||||
| </html> | </html> | ||||||
							
								
								
									
										194
									
								
								public/index.js
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								public/index.js
									
									
									
									
									
								
							| @ -1,16 +1,192 @@ | |||||||
| import { scaleContent } from "./functions/scaleContent.js"; | import { scaleContent } from "./functions/scaleContent.js"; | ||||||
| import { scalePage, PageSize } from "./functions/scalePage.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 pdfFileInput = document.getElementById('pdfFile'); | ||||||
|  |     const doneButton = document.getElementById("doneButton"); | ||||||
| 
 | 
 | ||||||
|     pdfFileInput.addEventListener('change', async (e) => { |     doneButton.addEventListener('click', async (e) => { | ||||||
|         const file = e.target.files[0]; |         const files = Array.from(pdfFileInput.files); | ||||||
|         if (file) { |         console.log(files); | ||||||
|             let pdfBuffer = new Uint8Array(await file.arrayBuffer()); |         const pdfBuffers = await Promise.all(files.map(async file => { | ||||||
|             pdfBuffer = await scaleContent(pdfBuffer, 2); |             return { | ||||||
|             pdfBuffer = await scalePage(pdfBuffer, PageSize.letter); |                 originalFileName: file.name.replace(/\.[^/.]+$/, ""), | ||||||
|             download(pdfBuffer, "pdf-lib_creation_example.pdf", "application/pdf"); |                 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