committing for push
This commit is contained in:
parent
597c52eefe
commit
08bba857db
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
|||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
|
.env
|
47
call.ts
Normal file
47
call.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
type transformer = (arg: string) => any;
|
||||||
|
interface IConfig {
|
||||||
|
multiTransform?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function call<T extends unknown[]>(tool: Tool<T>, conf?: transformer | IConfig, ...transforms: transformer[]) {
|
||||||
|
const config: IConfig = {}
|
||||||
|
|
||||||
|
if (typeof conf === 'object') {
|
||||||
|
Object.assign(config, conf)
|
||||||
|
} else {
|
||||||
|
transforms.unshift(conf as transformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
const args = Deno.args;
|
||||||
|
const shouldPair = transforms.length === args.length;
|
||||||
|
const multiTransform = config.multiTransform || !shouldPair && transforms.length > 1;
|
||||||
|
|
||||||
|
const transformedArgs = args.map((arg, i) => {
|
||||||
|
if (shouldPair) return transforms[i](arg);
|
||||||
|
if (multiTransform) return transforms.reduce((a, b) => b(a), arg)
|
||||||
|
return transforms[0] ? transforms[0](arg) : arg
|
||||||
|
})
|
||||||
|
|
||||||
|
await tool(...transformedArgs as T)
|
||||||
|
}
|
||||||
|
|
||||||
|
type prompt = [string, (v?: string) => boolean] | string
|
||||||
|
|
||||||
|
export async function callWithArgPrompt<T extends unknown[]>(tool: Tool<T>, prompts: prompt[]) {
|
||||||
|
function buildPromptTransform(p: prompt): transformer {
|
||||||
|
let validation = (v?: string) => !!v;
|
||||||
|
let pText = p as string;
|
||||||
|
|
||||||
|
if (Array.isArray(p)) {
|
||||||
|
[pText, validation] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (a: string) => {
|
||||||
|
while (!validation(a)) {
|
||||||
|
a = prompt(pText) || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await call(tool, ...prompts.map(buildPromptTransform))
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"name": "@bearmetal/pdf-tools",
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"dev": "deno run -A --watch main.ts",
|
"dev": "deno run -A --watch dev.ts",
|
||||||
"compile": "deno compile -o compare-form-fields.exe --target x86_64-pc-windows-msvc -R ./main.ts",
|
"compile": "deno compile -o compare-form-fields.exe --target x86_64-pc-windows-msvc -R ./main.ts",
|
||||||
"install": "deno install -fgq --import-map ./deno.json -n checkfields -R ./main.ts"
|
"install": "deno install -fgq --import-map ./deno.json -n checkfields -R ./main.ts"
|
||||||
},
|
},
|
||||||
|
82
fieldRename.ts
Normal file
82
fieldRename.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { PDFAcroField, PDFHexString, PDFName, PDFString, toHexString } from "pdf-lib";
|
||||||
|
import { loadPdfForm, savePdf } from "./saveLoadPdf.ts";
|
||||||
|
import { PDFDocument } from "pdf-lib";
|
||||||
|
import { call, callWithArgPrompt } from "./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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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:"
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
21
main.ts
21
main.ts
@ -1,25 +1,22 @@
|
|||||||
import {PDFDocument} from "pdf-lib";
|
import { PDFDocument } from "pdf-lib";
|
||||||
|
import { loadPdfForm } from "./saveLoadPdf.ts";
|
||||||
|
|
||||||
let [pdfPath, csPath] = Deno.args;
|
let [pdfPath, csPath] = Deno.args;
|
||||||
|
|
||||||
while (!pdfPath || !pdfPath.endsWith('.pdf')) pdfPath = prompt("Please provide path to PDF file:") || "";
|
while (!pdfPath || !pdfPath.endsWith('.pdf')) pdfPath = prompt("Please provide path to PDF file:") || "";
|
||||||
while (!csPath || !csPath.endsWith('.cs')) csPath = prompt("Please provide path to CS class file:") || "";
|
while (!csPath || !csPath.endsWith('.cs')) csPath = prompt("Please provide path to CS class file:") || "";
|
||||||
|
|
||||||
const pdfBytes = await Deno.readFile(pdfPath);
|
const form = await loadPdfForm(pdfPath);
|
||||||
|
|
||||||
const pdfDoc = await PDFDocument.load(pdfBytes);
|
|
||||||
|
|
||||||
const form = pdfDoc.getForm();
|
|
||||||
|
|
||||||
const fields = form.getFields();
|
const fields = form.getFields();
|
||||||
const csFiles = await Promise.all(csPath.split(",").map(c => Deno.readTextFile(c.trim())));
|
const csFiles = await Promise.all(csPath.split(",").map(c => Deno.readTextFile(c.trim())));
|
||||||
|
|
||||||
const fieldNames:string[] = fields.map(f => f.getName())
|
const fieldNames: string[] = fields.map(f => f.getName())
|
||||||
.filter(f => {
|
.filter(f => {
|
||||||
const rx = new RegExp(`(?<!//\s?)case ?"${f}"`)
|
const rx = new RegExp(`(?<!//\s?)case ?"${f.replace(/\[\d\]/, '\\[\\?\\]')}"`)
|
||||||
return !csFiles.some(c => rx.test(c))
|
return !csFiles.some(c => rx.test(c))
|
||||||
})
|
})
|
||||||
.filter(f => !f.toLowerCase().includes("signature"));
|
.filter(f => !f.toLowerCase().includes("signature"));
|
||||||
|
|
||||||
if (fieldNames.length) {
|
if (fieldNames.length) {
|
||||||
console.log("%cThe following field names are not present in the CS code", "color: red")
|
console.log("%cThe following field names are not present in the CS code", "color: red")
|
||||||
@ -29,3 +26,5 @@ if (fieldNames.length) {
|
|||||||
console.log("%cAll form fields present", 'color: lime')
|
console.log("%cAll form fields present", 'color: lime')
|
||||||
alert("Ok!")
|
alert("Ok!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/additionalAdviser.personalInfo.npn\[\?\]/
|
16
saveLoadPdf.ts
Normal file
16
saveLoadPdf.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { PDFDocument } from "pdf-lib";
|
||||||
|
|
||||||
|
export async function loadPdfForm(path: string) {
|
||||||
|
const pdfBytes = await Deno.readFile(path);
|
||||||
|
|
||||||
|
const pdfDoc = await PDFDocument.load(pdfBytes);
|
||||||
|
|
||||||
|
const form = pdfDoc.getForm()
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function savePdf(doc: PDFDocument, path: string) {
|
||||||
|
const pdfBytes = await doc.save();
|
||||||
|
if (Deno.env.get("DRYRUN")) return
|
||||||
|
await Deno.writeFile(path, pdfBytes);
|
||||||
|
}
|
BIN
testing/test.pdf
Normal file
BIN
testing/test.pdf
Normal file
Binary file not shown.
0
testing/test.ts
Normal file
0
testing/test.ts
Normal file
Loading…
x
Reference in New Issue
Block a user