Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/project/jupyter/convert/html-to-pdf.ts
Views: 687
/*1Note that this doesn't actually use upstream nbconvert itself at all!23- pdf: takes html, then uses headless chrome via4chromium-browser or google-chrome, if installed to convert to pdf56NOTE: Firefox does *not* support printing to pdf in headless mode according to7https://stackoverflow.com/questions/48358556/firefox-headless-print-to-pdf-option8*/910import which from "which";11import { join, parse } from "path";12import { executeCode } from "@cocalc/backend/execute-code";13import { getLogger } from "@cocalc/project/logger";1415const log = getLogger("jupyter:html-to-pdf");1617// time google-chrome --headless --disable-gpu --no-sandbox --print-to-pdf=a.pdf --run-all-compositor-stages-before-draw --virtual-time-budget=10000 --disable-dev-shm-usage --disable-setuid-sandbox a.html1819export default async function htmlToPDF(20path: string,21timeout: number = 3022): Promise<string> {23const { dir, name } = parse(path);24const outfile = join(dir, name + ".pdf");2526const command = await getCommand();27const args = [28"--headless",29"--disable-gpu",30"--no-sandbox",31`--print-to-pdf=${outfile}`,32"--run-all-compositor-stages-before-draw",33// I added --disable-dev-shm-usage --disable-setuid-sandbox because printing large complicated documents was failing,34// and GPT-4 suggested these options. There are security implications, but that is OK given the application.35"--disable-dev-shm-usage",36"--disable-setuid-sandbox",37`--virtual-time-budget=${timeout * 1000}`,38path,39];40log.debug(`htmlToPDF: ${command} ${args.join(" ")}`);41const output = await executeCode({42command,43args,44err_on_exit: false,45timeout,46ulimit_timeout: true,47bash: true,48});49if (output.exit_code != 0) {50throw Error(output.stderr);51}5253return outfile;54}5556const COMMANDS = ["google-chrome", "chromium-browser"];5758let cache: string = "";59async function getCommand(): Promise<string> {60if (cache) return cache;61for (const cmd of COMMANDS) {62try {63await which(cmd);64cache = cmd;65return cmd;66} catch (_err) {}67}68throw Error(69`one of ${COMMANDS.join(" or ")} must be installed to convert to PDF`70);71}727374