diff --git a/bun.lockb b/bun.lockb index 308e056..7be2df7 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 0cdc010..be0d7d9 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "@elysiajs/html": "^1.0.2", "@elysiajs/jwt": "^1.0.2", "@elysiajs/static": "^1.0.3", - "elysia": "^1.0.22" + "elysia": "^1.0.22", + "node-poppler": "^7.2.0" }, "module": "src/index.tsx", "bun-create": { diff --git a/src/converters/main.ts b/src/converters/main.ts index 0807b97..3b60964 100644 --- a/src/converters/main.ts +++ b/src/converters/main.ts @@ -20,6 +20,8 @@ import { properties as propertiesPdflatex, } from "./pdflatex"; +import { convert as convertPoppler, properties as propertiesPoppler } from "./poppler"; + import { normalizeFiletype } from "../helpers/normalizeFiletype"; // This should probably be reconstructed so that the functions are not imported instead the functions hook into this to make the converters more modular @@ -58,6 +60,10 @@ const properties: { properties: propertiesPdflatex, converter: convertPdflatex, }, + poppler: { + properties: propertiesPoppler, + converter: convertPoppler, + }, pandoc: { properties: propertiesPandoc, converter: convertPandoc, diff --git a/src/converters/poppler.ts b/src/converters/poppler.ts new file mode 100644 index 0000000..f6404fe --- /dev/null +++ b/src/converters/poppler.ts @@ -0,0 +1,115 @@ +const { Poppler } = require("node-poppler"); +const poppler = new Poppler(); + +export const properties = { + from: { + text: ["pdf"], + }, + to: { + text: [ + "jpeg", + "png", + "tiff", + "eps", + "icc", + "pdf", + "svg", + "ps", + "html", + "text", + ], + }, +}; + +export function convert( + filePath: string, + fileType: string, + convertTo: string, + targetPath: string, + // biome-ignore lint/suspicious/noExplicitAny: + options?: any, +): Promise { + return new Promise((resolve, reject) => { + const cairoFiles = [ + "jpeg", + "png", + "tiff", + "eps", + "icc", + "pdf", + "svg", + "ps", + ]; + + if (cairoFiles.includes(convertTo)) { + const popplerOptions: { + jpegFile?: boolean; + pngFile?: boolean; + tiffFile?: boolean; + epsFile?: boolean; + iccFile?: boolean; + pdfFile?: boolean; + svgFile?: boolean; + psFile?: boolean; + } = {}; + + switch (convertTo) { + case "jpeg": + popplerOptions.jpegFile = true; + break; + case "png": + popplerOptions.pngFile = true; + break; + case "tiff": + popplerOptions.tiffFile = true; + break; + case "eps": + popplerOptions.epsFile = true; + break; + case "icc": + popplerOptions.iccFile = true; + break; + case "pdf": + popplerOptions.pdfFile = true; + break; + case "svg": + popplerOptions.svgFile = true; + break; + case "ps": + popplerOptions.psFile = true; + break; + default: + reject(`Invalid convertTo option: ${convertTo}`); + } + + poppler + .pdfToCairo(filePath, targetPath, popplerOptions) + .then(() => { + resolve("success"); + }) + .catch((err: Error) => { + reject(err); + }); + } else if (convertTo === "html") { + poppler + .pdfToHtml(filePath, targetPath) + .then(() => { + resolve("success"); + }) + .catch((err: Error) => { + reject(err); + }); + } else if (convertTo === "text") { + poppler + .pdfToText(filePath, targetPath) + .then(() => { + resolve("success"); + }) + .catch((err: Error) => { + reject(err); + }); + } else { + reject(`Invalid convertTo option: ${convertTo}`); + } + }); +} diff --git a/src/helpers/normalizeFiletype.ts b/src/helpers/normalizeFiletype.ts index 9b4cc1d..279e64d 100644 --- a/src/helpers/normalizeFiletype.ts +++ b/src/helpers/normalizeFiletype.ts @@ -25,6 +25,8 @@ export const normalizeOutputFiletype = (filetype: string): string => { return "tex"; case "markdown": return "md"; + case "text": + return "txt"; default: return lowercaseFiletype; }