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/print_to_pdf.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2023 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45//##############################################6// Printing an individual file to pdf7//##############################################89import { unlink, writeFile } from "node:fs/promises";10import { path as temp_path } from "temp";1112import { execute_code } from "@cocalc/backend/misc_node";13import { CoCalcSocket } from "@cocalc/backend/tcp/enable-messaging-protocol";14import * as message from "@cocalc/util/message";15import { defaults, filename_extension, required } from "@cocalc/util/misc";1617import { getLogger } from "@cocalc/backend/logger";18const winston = getLogger("print-to-pdf");1920interface SagewsPrintOpts {21path: string;22outfile: string;23title: string;24author: string;25date: string;26contents: string;27subdir: string;28base_url?: string;29extra_data?: string;30timeout?: number;31}3233async function print_sagews(opts: SagewsPrintOpts) {34opts = defaults(opts, {35path: required,36outfile: required,37title: required,38author: required,39date: required,40contents: required,41subdir: required, // 'true' or 'false', if true, then workdir is a generated subdirectory which will retain the temporary tex files42base_url: undefined, // the base_url for downloading blobs/images43extra_data: undefined, // extra data that is useful for displaying certain things in the worksheet.44timeout: 90,45});4647let extra_data_file: string | undefined = undefined;48let args = [49opts.path,50"--outfile",51opts.outfile,52"--title",53opts.title,54"--author",55opts.author,56"--date",57opts.date,58"--subdir",59opts.subdir,60"--contents",61opts.contents,62];63if (opts.base_url) {64args = args.concat(["--base_url", opts.base_url]);65}6667let err: Error | undefined = undefined;6869try {70if (opts.extra_data != null) {71extra_data_file = temp_path() + ".json";72args.push("--extra_data_file");73args.push(extra_data_file);74// NOTE: extra_data is a string that is *already* in JSON format.75await writeFile(extra_data_file, opts.extra_data);76}7778// run the converter script79await new Promise<void>((resolve, reject) => {80execute_code({81command: "smc-sagews2pdf",82args,83err_on_exit: true,84bash: false,85timeout: opts.timeout,86cb: (err) => {87if (err) {88winston.debug(`Issue running smc-sagews2pdf: ${err}`);89reject(err);90} else {91resolve();92}93},94});95});96} catch (err) {97err = err;98}99100if (extra_data_file != null) {101unlink(extra_data_file); // no need to wait for completion before calling opts.cb102}103104if (err) {105throw err;106}107}108109export async function print_to_pdf(socket: CoCalcSocket, mesg) {110let pdf;111const ext = filename_extension(mesg.path);112if (ext) {113pdf = `${mesg.path.slice(0, mesg.path.length - ext.length)}pdf`;114} else {115pdf = mesg.path + ".pdf";116}117118try {119switch (ext) {120case "sagews":121await print_sagews({122path: mesg.path,123outfile: pdf,124title: mesg.options.title,125author: mesg.options.author,126date: mesg.options.date,127contents: mesg.options.contents,128subdir: mesg.options.subdir,129extra_data: mesg.options.extra_data,130timeout: mesg.options.timeout,131});132break;133134default:135throw new Error(`unable to print file of type '${ext}'`);136}137138// all good139return socket.write_mesg(140"json",141message.printed_to_pdf({ id: mesg.id, path: pdf })142);143} catch (err) {144return socket.write_mesg(145"json",146message.error({ id: mesg.id, error: err })147);148}149}150151152