mirror of
https://github.com/prdlk/cv.git
synced 2026-08-02 17:31:41 +00:00
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import { execFile } from "node:child_process";
|
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { promisify } from "node:util";
|
|
import type { Plugin } from "vite";
|
|
|
|
const run = promisify(execFile);
|
|
|
|
/**
|
|
* Dev-only PDF compiler. Uses the same local TeX Live toolchain as the
|
|
* repository Makefile, so dev output is byte-identical to `make`.
|
|
* In production the client falls back to the Worker's /api/pdf route.
|
|
*/
|
|
export function latexDev(): Plugin {
|
|
return {
|
|
name: "latex-dev-compiler",
|
|
apply: "serve",
|
|
configureServer(server) {
|
|
server.middlewares.use("/local/compile", (req, res) => {
|
|
if (req.method !== "POST") {
|
|
res.statusCode = 405;
|
|
res.end();
|
|
return;
|
|
}
|
|
const chunks: Buffer[] = [];
|
|
req.on("data", (c: Buffer) => chunks.push(c));
|
|
req.on("end", () => {
|
|
void (async () => {
|
|
let dir: string | undefined;
|
|
try {
|
|
const { latex } = JSON.parse(Buffer.concat(chunks).toString("utf8")) as {
|
|
latex: string;
|
|
};
|
|
dir = await mkdtemp(join(tmpdir(), "cvtex-"));
|
|
await writeFile(join(dir, "main.tex"), latex, "utf8");
|
|
await run("pdflatex", ["-interaction=nonstopmode", "-halt-on-error", "main.tex"], {
|
|
cwd: dir,
|
|
timeout: 30_000,
|
|
});
|
|
const pdf = await readFile(join(dir, "main.pdf"));
|
|
res.setHeader("Content-Type", "application/pdf");
|
|
res.end(pdf);
|
|
} catch (err) {
|
|
let log = err instanceof Error ? err.message : String(err);
|
|
if (dir) {
|
|
try {
|
|
log = (await readFile(join(dir, "main.log"), "utf8")).slice(-4000);
|
|
} catch {
|
|
/* no log written */
|
|
}
|
|
}
|
|
res.statusCode = 422;
|
|
res.setHeader("Content-Type", "application/json");
|
|
res.end(JSON.stringify({ error: "pdflatex failed", log }));
|
|
} finally {
|
|
if (dir) void rm(dir, { recursive: true, force: true });
|
|
}
|
|
})();
|
|
});
|
|
});
|
|
},
|
|
};
|
|
}
|