import { PDFAcroField, PDFHexString, PDFName, PDFString, toHexString, } from "pdf-lib"; import { loadPdfForm, savePdf } from "util/saveLoadPdf.ts"; import { PDFDocument } from "pdf-lib"; import { call, callWithArgPrompt } from "util/call.ts"; // const thing = PDFAcroField.prototype.getFullyQualifiedName; // PDFAcroField.prototype.getFullyQualifiedName = function () { // const name = thing.call(this) // // if (name?.includes('langauge')) // console.log(name) // return name; // } // const thing = PDFHexString.prototype.copyBytesInto // PDFHexString.prototype.copyBytesInto = function (buffer: Uint8Array, offset: number) { // console.log((this as any).value) // const result = thing.call(this, buffer, offset) // return result; // } async function renameFields( path: string, pattern: string | RegExp, change: string, ) { if (typeof pattern === "string") pattern = new RegExp(pattern); const form = await loadPdfForm(path); const fields = form.getFields(); let changesMade = false; for (const field of fields) { const name = field.getName(); if (pattern.test(name)) { console.log(name + " %cfound", "color: red"); const segments = name.split("."); const matchingSegments = segments.filter((s) => pattern.test(s)); let cField: PDFAcroField | undefined = field.acroField; while (cField) { if ( cField.getPartialName() && matchingSegments.includes(cField.getPartialName()!) ) { const mName = cField.getPartialName()?.replace(pattern, change); if (mName) { changesMade = true; cField.dict.set(PDFName.of("T"), PDFString.of(mName)); // console.log(cField.getPartialName()) } } cField = cField.getParent(); // console.log(cField?.getPartialName()) } console.log(field.getName()); // const newName = name.replace(pattern, change); // console.log("Change to: %c" + newName, "color: yellow"); // if (confirm('Ok?')) { // let parent = field.acroField.getParent(); // field.acroField.setPartialName(segments.pop()) // while (parent && segments.length) { // console.log(parent.getPartialName()) // parent.setPartialName(segments.pop()) // parent = parent.getParent(); // } // changesMade = true; // console.log(field.getName()) // // dict.set(PDFName.of("T"), PDFHexString.fromText(newName)) // console.log("%cDone!", "color: lime") // } // break; } } if (changesMade) { savePdf(form.doc, path); } } class RenameFields implements ITool { name = "renamefields"; description = "Renames fields in a PDF form"; help() { console.log("Usage: renamefields "); } async run(pdfPath: string = "", pattern: string = "", change: string = "") { await callWithArgPrompt(renameFields, [ ["Please provide path to PDF:", (p) => !!p && p.endsWith(".pdf")], "Please provide search string:", "Please provide requested change:", ], [pdfPath, pattern, change]); } } export default new RenameFields(); if (import.meta.main) { // await call(renameFields) // while (!path || !path.endsWith('.pdf')) path = prompt("Please provide path to PDF:") || ''; // while (!pattern) pattern = prompt("Please provide search string:") || ''; // while (!change) change = prompt("Please provide requested change:") || ''; await callWithArgPrompt(renameFields, [ ["Please provide path to PDF:", (p) => !!p && p.endsWith(".pdf")], "Please provide search string:", "Please provide requested change:", ]); }