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 { TerminalBlock, TerminalLayout } from "./TerminalLayout.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 {
private tools: Map<string, ITool> = new Map();
@ -15,19 +25,18 @@ export class PdfToolsCli {
help: ["-h", "--help"],
});
async importTools(tools?: string) {
tools = tools?.replace(/\/$/, "").replace(/^\.?\//, "") || "tools";
for (const toolfile of Deno.readDirSync(tools)) {
if (toolfile.isFile) {
const tool = await import(
Deno.cwd() + "/" + tools + "/" + toolfile.name
);
if (tool.default) {
async importTools() {
for (const [name, toolfile] of toolRegistry) {
const t = await toolfile;
try {
if (t.default) {
this.tools.set(
toCase(toolfile.name.replace(".ts", ""), "title"),
tool.default,
toCase(name, "title"),
t.default,
);
}
} catch (e) {
cliLog(e + "\n", this.terminalLayout.getBlock("body"));
}
}
}
@ -50,6 +59,7 @@ export class PdfToolsCli {
public async run() {
try {
await this.importTools();
const titleBlock = new TerminalBlock();
this.terminalLayout.register("title", titleBlock);
const bodyBlock = new TerminalBlock();
@ -59,10 +69,8 @@ export class PdfToolsCli {
return;
} else if (this.args.nonFlags.length === 0 || !this.args.task) {
this.embiggenHeader();
await this.importTools();
await this.toolMenu();
} else {
await this.importTools();
const task = this.args.task;
await this.runTool(toCase(task, "title"));
}

View File

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

View File

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

7
deno.lock generated
View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@ 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";

View File

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

View File

@ -1,3 +1,5 @@
import type { ToolFunc } from "../types.ts";
type transformer = (arg: string) => any;
interface IConfig {
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) {
const pdfDoc = await loadPdf(path);
@ -13,6 +13,11 @@ export async function loadPdf(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();
if (Deno.env.get("DRYRUN") || path.includes("dryrun")) return;
await Deno.writeFile(path, pdfBytes);