import { forceArgs } from "../cli/forceArgs.ts"; import { cliAlert } from "../cli/prompts.ts"; import { TerminalBlock } from "../cli/TerminalLayout.ts"; import { loadPdfForm } from "util/saveLoadPdf.ts"; import type { ITool } from "../types.ts"; export class ListFormFields implements ITool { name = "listformfields"; description = "Lists fields in a PDF form"; block?: TerminalBlock; async run(pdfPath: string = "") { if (!this.block) { this.block = new TerminalBlock(); } this.block.setPreserveHistory(true); [pdfPath] = await forceArgs([pdfPath], [[ "Please provide path to PDF:", (p) => !!p && p.endsWith(".pdf"), ]], this.block); const form = await loadPdfForm(pdfPath); const fields = form.getFields(); const height = this.block.getRenderHeight() - 1; const fieldNames = fields.sort((a, b) => { const aRect = a.acroField.getWidgets().find((e) => e.Rect())?.Rect() ?.asRectangle(); const bRect = b.acroField.getWidgets().find((e) => e.Rect())?.Rect() ?.asRectangle(); if (aRect && bRect) { if (aRect.x !== bRect.x) { return aRect.x - bRect.x; // Sort left to right } else { return bRect.y - aRect.y; // If x is equal, sort top to bottom } } return a.getName().localeCompare(b.getName()); }).map((f) => f.getName()); const maxLength = Math.max(...fieldNames.map((f) => f.length)) + 4; const lines = []; for (let i = 0; i < height; i++) { let line = ""; for (let j = 0; j < fieldNames.length; j += height) { const fieldName = fieldNames[i + j] ?? ""; line += fieldName.padEnd(maxLength, " "); } lines.push(line); } this.block.setLines(lines, [0, 1]); await cliAlert("", this.block); } setBlock(terminalBlock: TerminalBlock) { this.block = terminalBlock; } } export default new ListFormFields();