v1 ready for publish

This commit is contained in:
Emmaline Autumn 2025-05-06 17:53:17 -06:00
parent 03a1e3ed21
commit 6346b28581
11 changed files with 53 additions and 28 deletions

View File

@ -5,6 +5,16 @@ import { colorize } from "./style.ts";
import { selectMenuInteractive } from "./selectMenu.ts"; import { selectMenuInteractive } from "./selectMenu.ts";
import { TerminalBlock, TerminalLayout } from "./TerminalLayout.ts"; import { TerminalBlock, TerminalLayout } from "./TerminalLayout.ts";
import { cliAlert, cliLog } from "./prompts.ts"; import { cliAlert, cliLog } from "./prompts.ts";
import type { ITool } from "../types.ts";
import { join, toFileUrl } from "@std/path";
import { log } from "util/logfile.ts";
// Register tools here (filename, no extension)
const toolRegistry: [string, Promise<{ default: ITool }>][] = [
["checkCode", import("../tools/checkCode.ts")],
["fieldRename", import("../tools/fieldRename.ts")],
["listFormFields", import("../tools/listFormFields.ts")],
];
export class PdfToolsCli { export class PdfToolsCli {
private tools: Map<string, ITool> = new Map(); private tools: Map<string, ITool> = new Map();
@ -15,19 +25,18 @@ export class PdfToolsCli {
help: ["-h", "--help"], help: ["-h", "--help"],
}); });
async importTools(tools?: string) { async importTools() {
tools = tools?.replace(/\/$/, "").replace(/^\.?\//, "") || "tools"; for (const [name, toolfile] of toolRegistry) {
for (const toolfile of Deno.readDirSync(tools)) { const t = await toolfile;
if (toolfile.isFile) { try {
const tool = await import( if (t.default) {
Deno.cwd() + "/" + tools + "/" + toolfile.name
);
if (tool.default) {
this.tools.set( this.tools.set(
toCase(toolfile.name.replace(".ts", ""), "title"), toCase(name, "title"),
tool.default, t.default,
); );
} }
} catch (e) {
cliLog(e + "\n", this.terminalLayout.getBlock("body"));
} }
} }
} }
@ -50,6 +59,7 @@ export class PdfToolsCli {
public async run() { public async run() {
try { try {
await this.importTools();
const titleBlock = new TerminalBlock(); const titleBlock = new TerminalBlock();
this.terminalLayout.register("title", titleBlock); this.terminalLayout.register("title", titleBlock);
const bodyBlock = new TerminalBlock(); const bodyBlock = new TerminalBlock();
@ -59,10 +69,8 @@ export class PdfToolsCli {
return; return;
} else if (this.args.nonFlags.length === 0 || !this.args.task) { } else if (this.args.nonFlags.length === 0 || !this.args.task) {
this.embiggenHeader(); this.embiggenHeader();
await this.importTools();
await this.toolMenu(); await this.toolMenu();
} else { } else {
await this.importTools();
const task = this.args.task; const task = this.args.task;
await this.runTool(toCase(task, "title")); await this.runTool(toCase(task, "title"));
} }

View File

@ -1,3 +1,4 @@
import type { callback } from "../types.ts";
import { colorize } from "./style.ts"; import { colorize } from "./style.ts";
import { TerminalBlock } from "./TerminalLayout.ts"; import { TerminalBlock } from "./TerminalLayout.ts";

View File

@ -1,6 +1,7 @@
{ {
"name": "@bearmetal/pdf-tools", "name": "@bearmetal/pdf-tools",
"version": "0.0.1", "version": "0.0.6",
"license": "GPL 3.0",
"tasks": { "tasks": {
"dev": "deno run -A --env-file=.env --watch main.ts", "dev": "deno run -A --env-file=.env --watch main.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",
@ -9,6 +10,7 @@
}, },
"imports": { "imports": {
"@std/assert": "jsr:@std/assert@1", "@std/assert": "jsr:@std/assert@1",
"@std/path": "jsr:@std/path@^1.0.9",
"pdf-lib": "npm:pdf-lib@^1.17.1", "pdf-lib": "npm:pdf-lib@^1.17.1",
"util/": "./util/" "util/": "./util/"
}, },

7
deno.lock generated
View File

@ -1,8 +1,9 @@
{ {
"version": "4", "version": "5",
"specifiers": { "specifiers": {
"jsr:@std/assert@1": "1.0.12", "jsr:@std/assert@1": "1.0.12",
"jsr:@std/internal@^1.0.6": "1.0.6", "jsr:@std/internal@^1.0.6": "1.0.6",
"jsr:@std/path@^1.0.9": "1.0.9",
"npm:pdf-lib@^1.17.1": "1.17.1" "npm:pdf-lib@^1.17.1": "1.17.1"
}, },
"jsr": { "jsr": {
@ -14,6 +15,9 @@
}, },
"@std/internal@1.0.6": { "@std/internal@1.0.6": {
"integrity": "9533b128f230f73bd209408bb07a4b12f8d4255ab2a4d22a1fd6d87304aca9a4" "integrity": "9533b128f230f73bd209408bb07a4b12f8d4255ab2a4d22a1fd6d87304aca9a4"
},
"@std/path@1.0.9": {
"integrity": "260a49f11edd3db93dd38350bf9cd1b4d1366afa98e81b86167b4e3dd750129e"
} }
}, },
"npm": { "npm": {
@ -48,6 +52,7 @@
"workspace": { "workspace": {
"dependencies": [ "dependencies": [
"jsr:@std/assert@1", "jsr:@std/assert@1",
"jsr:@std/path@^1.0.9",
"npm:pdf-lib@^1.17.1" "npm:pdf-lib@^1.17.1"
] ]
} }

View File

@ -1,3 +1,4 @@
/// <reference types="./types.ts" />
import { PdfToolsCli } from "./cli/index.ts"; import { PdfToolsCli } from "./cli/index.ts";
const app = new PdfToolsCli(); const app = new PdfToolsCli();

View File

@ -2,6 +2,7 @@ import { forceArgs } from "../cli/forceArgs.ts";
import { cliAlert, cliLog } from "../cli/prompts.ts"; import { cliAlert, cliLog } from "../cli/prompts.ts";
import { colorize } from "../cli/style.ts"; import { colorize } from "../cli/style.ts";
import type { TerminalBlock } from "../cli/TerminalLayout.ts"; import type { TerminalBlock } from "../cli/TerminalLayout.ts";
import type { ITool } from "../types.ts";
import { loadPdfForm } from "../util/saveLoadPdf.ts"; import { loadPdfForm } from "../util/saveLoadPdf.ts";
function getCaseSyntaxPatternByFileExtension( function getCaseSyntaxPatternByFileExtension(
@ -33,7 +34,7 @@ class CheckCode implements ITool {
[pdfPath, codePaths] = await forceArgs([pdfPath, codePaths], [ [pdfPath, codePaths] = await forceArgs([pdfPath, codePaths], [
"Please provide path to PDF file:", "Please provide path to PDF file:",
"Please provide path(s) to code file(s) (comma separated for multiple):", "Please provide path(s) to code file(s) (comma separated for multiple):",
]); ], this.block);
const form = await loadPdfForm(pdfPath); const form = await loadPdfForm(pdfPath);

View File

@ -6,6 +6,7 @@ import { forceArgs } from "../cli/forceArgs.ts";
import { colorize } from "../cli/style.ts"; import { colorize } from "../cli/style.ts";
import { cliAlert, cliLog, cliPrompt } from "../cli/prompts.ts"; import { cliAlert, cliLog, cliPrompt } from "../cli/prompts.ts";
import { multiSelectMenuInteractive } from "../cli/selectMenu.ts"; import { multiSelectMenuInteractive } from "../cli/selectMenu.ts";
import type { callback, ITool } from "../types.ts";
async function renameFields( async function renameFields(
path: string, path: string,

View File

@ -2,6 +2,7 @@ import { forceArgs } from "../cli/forceArgs.ts";
import { cliAlert } from "../cli/prompts.ts"; import { cliAlert } from "../cli/prompts.ts";
import { TerminalBlock } from "../cli/TerminalLayout.ts"; import { TerminalBlock } from "../cli/TerminalLayout.ts";
import { loadPdfForm } from "util/saveLoadPdf.ts"; import { loadPdfForm } from "util/saveLoadPdf.ts";
import type { ITool } from "../types.ts";
export class ListFormFields implements ITool { export class ListFormFields implements ITool {
name = "listformfields"; name = "listformfields";

View File

@ -1,15 +1,13 @@
import type { TerminalBlock } from "./cli/TerminalLayout.ts"; import type { TerminalBlock } from "./cli/TerminalLayout.ts";
declare global { export type ToolFunc<T extends unknown[]> = (...args: T) => Promise<void>;
type ToolFunc<T extends unknown[]> = (...args: T) => Promise<void>; export interface ITool {
interface ITool { name: string;
name: string; description: string;
description: string; run: ToolFunc<any[]>;
run: ToolFunc<any[]>; help?: () => Promise<void> | void;
help?: () => Promise<void> | void; done?: () => Promise<void> | void;
done?: () => Promise<void> | void; setBlock?: (block: TerminalBlock) => void;
setBlock?: (block: TerminalBlock) => void;
}
type callback = (...args: any[]) => any;
} }
export type callback = (...args: any[]) => any;

View File

@ -1,3 +1,5 @@
import type { ToolFunc } from "../types.ts";
type transformer = (arg: string) => any; type transformer = (arg: string) => any;
interface IConfig { interface IConfig {
multiTransform?: boolean; multiTransform?: boolean;

View File

@ -1,4 +1,4 @@
import { PDFDocument } from "pdf-lib"; import { PDFDocument, PDFTextField } from "pdf-lib";
export async function loadPdfForm(path: string) { export async function loadPdfForm(path: string) {
const pdfDoc = await loadPdf(path); const pdfDoc = await loadPdf(path);
@ -13,6 +13,11 @@ export async function loadPdf(path: string) {
} }
export async function savePdf(doc: PDFDocument, path: string) { export async function savePdf(doc: PDFDocument, path: string) {
doc.getForm().getFields().forEach((field) => {
if (field instanceof PDFTextField) {
field.disableRichFormatting();
}
});
const pdfBytes = await doc.save(); const pdfBytes = await doc.save();
if (Deno.env.get("DRYRUN") || path.includes("dryrun")) return; if (Deno.env.get("DRYRUN") || path.includes("dryrun")) return;
await Deno.writeFile(path, pdfBytes); await Deno.writeFile(path, pdfBytes);