mirror of
https://github.com/C4illin/ConvertX.git
synced 2026-09-12 09:57:46 +02:00
feat(pdftops): added pdftops converter (#611)
This commit is contained in:
@@ -47,6 +47,7 @@ A self-hosted online file converter. Supports over a thousand different formats.
|
||||
| [Potrace](https://potrace.sourceforge.net/) | Raster to vector | 4 | 11 |
|
||||
| [VTracer](https://github.com/visioncortex/vtracer) | Raster to vector | 8 | 1 |
|
||||
| [Markitdown](https://github.com/microsoft/markitdown) | Documents | 6 | 1 |
|
||||
| [pdftops](https://poppler.freedesktop.org/) | Documents | 1 | 2 |
|
||||
|
||||
<!-- many ffmpeg fileformats are duplicates -->
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import { convert as convertLibjxl, properties as propertiesLibjxl } from "./libj
|
||||
import { convert as convertLibreOffice, properties as propertiesLibreOffice } from "./libreoffice";
|
||||
import { convert as convertMsgconvert, properties as propertiesMsgconvert } from "./msgconvert";
|
||||
import { convert as convertPandoc, properties as propertiesPandoc } from "./pandoc";
|
||||
import { convert as convertPdftops, properties as propertiesPdftops } from "./pdftops";
|
||||
import { convert as convertPotrace, properties as propertiesPotrace } from "./potrace";
|
||||
import { convert as convertresvg, properties as propertiesresvg } from "./resvg";
|
||||
import { convert as convertImage, properties as propertiesImage } from "./vips";
|
||||
@@ -137,6 +138,10 @@ const properties: Record<
|
||||
properties: propertiesMarkitdown,
|
||||
converter: convertMarkitdown,
|
||||
},
|
||||
pdftops: {
|
||||
properties: propertiesPdftops,
|
||||
converter: convertPdftops,
|
||||
},
|
||||
};
|
||||
|
||||
function chunks<T>(arr: T[], size: number): T[][] {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { execFile as execFileOriginal } from "node:child_process";
|
||||
import { ExecFileFn } from "./types";
|
||||
|
||||
export const properties = {
|
||||
from: {
|
||||
document: ["pdf"],
|
||||
},
|
||||
to: {
|
||||
document: ["eps", "ps"],
|
||||
},
|
||||
};
|
||||
|
||||
export async function convert(
|
||||
filePath: string,
|
||||
fileType: string,
|
||||
convertTo: string,
|
||||
targetPath: string,
|
||||
options?: unknown,
|
||||
execFile: ExecFileFn = execFileOriginal, // to make it mockable
|
||||
): Promise<string> {
|
||||
const args: string[] = [];
|
||||
|
||||
if (convertTo === "eps") {
|
||||
args.push("-eps");
|
||||
}
|
||||
|
||||
args.push(filePath, targetPath);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
execFile("pdftops", args, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`error: ${error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stdout) {
|
||||
console.log(`stdout: ${stdout}`);
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
console.error(`stderr: ${stderr}`);
|
||||
}
|
||||
|
||||
resolve("Done");
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { beforeEach, expect, test } from "bun:test";
|
||||
import { convert } from "../../src/converters/pdftops";
|
||||
import { runCommonTests } from "./helpers/commonTests";
|
||||
|
||||
runCommonTests(convert);
|
||||
|
||||
let calls: string[][] = [];
|
||||
|
||||
function mockExecFile(
|
||||
_cmd: string,
|
||||
args: string[],
|
||||
callback: (err: Error | null, stdout: string, stderr: string) => void,
|
||||
) {
|
||||
calls.push(args);
|
||||
if (args.includes("fail.pdf")) {
|
||||
callback(new Error("mock failure"), "", "Fake stderr: fail");
|
||||
} else {
|
||||
callback(null, "Fake stdout", "");
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
calls = [];
|
||||
});
|
||||
|
||||
test("converts a normal file to ps", async () => {
|
||||
const originalConsoleLog = console.log;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.log = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
const result = await convert("in.pdf", "pdf", "ps", "out.ps", undefined, mockExecFile);
|
||||
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
expect(result).toBe("Done");
|
||||
expect(calls[0]).toEqual(["in.pdf", "out.ps"]);
|
||||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
});
|
||||
|
||||
test("adds -eps flag for eps output", async () => {
|
||||
const result = await convert("in.pdf", "pdf", "eps", "out.eps", undefined, mockExecFile);
|
||||
|
||||
expect(result).toBe("Done");
|
||||
expect(calls[0]).toEqual(["-eps", "in.pdf", "out.eps"]);
|
||||
});
|
||||
|
||||
test("fails on exec error", async () => {
|
||||
expect(convert("fail.pdf", "pdf", "ps", "output.ps", undefined, mockExecFile)).rejects.toMatch(
|
||||
/error: Error: mock failure/,
|
||||
);
|
||||
});
|
||||
|
||||
test("logs stderr when execFile returns only stderr and no error", async () => {
|
||||
const originalConsoleError = console.error;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.error = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
const mockExecFileStderrOnly = (
|
||||
_cmd: string,
|
||||
_args: string[],
|
||||
callback: (err: Error | null, stdout: string, stderr: string) => void,
|
||||
) => {
|
||||
callback(null, "", "Only stderr output");
|
||||
};
|
||||
|
||||
await convert("input.pdf", "pdf", "ps", "output.ps", undefined, mockExecFileStderrOnly);
|
||||
|
||||
console.error = originalConsoleError;
|
||||
|
||||
expect(loggedMessage).toBe("stderr: Only stderr output");
|
||||
});
|
||||
Reference in New Issue
Block a user