Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/project/print_to_pdf.ts
1447 views
1
/*
2
* This file is part of CoCalc: Copyright © 2023 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
//##############################################
7
// Printing an individual file to pdf
8
//##############################################
9
10
import { unlink, writeFile } from "node:fs/promises";
11
import { path as temp_path } from "temp";
12
13
import { executeCode } from "@cocalc/backend/execute-code";
14
import { CoCalcSocket } from "@cocalc/backend/tcp/enable-messaging-protocol";
15
import * as message from "@cocalc/util/message";
16
import { defaults, filename_extension, required } from "@cocalc/util/misc";
17
18
interface SagewsPrintOpts {
19
path: string;
20
outfile: string;
21
title: string;
22
author: string;
23
date: string;
24
contents: string;
25
subdir: string;
26
base_url?: string;
27
extra_data?: string;
28
timeout?: number;
29
}
30
31
export async function printSageWS(opts: SagewsPrintOpts) {
32
opts = defaults(opts, {
33
path: required,
34
outfile: required,
35
title: required,
36
author: required,
37
date: required,
38
contents: required,
39
subdir: required, // 'true' or 'false', if true, then workdir is a generated subdirectory which will retain the temporary tex files
40
base_url: undefined, // the base_url for downloading blobs/images
41
extra_data: undefined, // extra data that is useful for displaying certain things in the worksheet.
42
timeout: 90,
43
});
44
45
let extra_data_file: string | undefined = undefined;
46
let args = [
47
opts.path,
48
"--outfile",
49
opts.outfile,
50
"--title",
51
opts.title,
52
"--author",
53
opts.author,
54
"--date",
55
opts.date,
56
"--subdir",
57
opts.subdir,
58
"--contents",
59
opts.contents,
60
];
61
if (opts.base_url) {
62
args = args.concat(["--base_url", opts.base_url]);
63
}
64
65
try {
66
if (opts.extra_data != null) {
67
extra_data_file = temp_path() + ".json";
68
args.push("--extra_data_file");
69
args.push(extra_data_file);
70
// NOTE: extra_data is a string that is *already* in JSON format.
71
await writeFile(extra_data_file, opts.extra_data);
72
}
73
74
// run the converter script
75
await executeCode({
76
command: "smc-sagews2pdf",
77
args,
78
err_on_exit: true,
79
bash: false,
80
timeout: opts.timeout,
81
});
82
} finally {
83
if (extra_data_file != null) {
84
unlink(extra_data_file); // no need to wait
85
}
86
}
87
}
88
89
export async function print_to_pdf(socket: CoCalcSocket, mesg) {
90
let pdf;
91
const ext = filename_extension(mesg.path);
92
if (ext) {
93
pdf = `${mesg.path.slice(0, mesg.path.length - ext.length)}pdf`;
94
} else {
95
pdf = mesg.path + ".pdf";
96
}
97
98
try {
99
switch (ext) {
100
case "sagews":
101
await printSageWS({
102
path: mesg.path,
103
outfile: pdf,
104
title: mesg.options.title,
105
author: mesg.options.author,
106
date: mesg.options.date,
107
contents: mesg.options.contents,
108
subdir: mesg.options.subdir,
109
extra_data: mesg.options.extra_data,
110
timeout: mesg.options.timeout,
111
});
112
break;
113
114
default:
115
throw new Error(`unable to print file of type '${ext}'`);
116
}
117
118
// all good
119
return socket.write_mesg(
120
"json",
121
message.printed_to_pdf({ id: mesg.id, path: pdf }),
122
);
123
} catch (err) {
124
return socket.write_mesg(
125
"json",
126
message.error({ id: mesg.id, error: err }),
127
);
128
}
129
}
130
131