@tstdl/base 0.93.68 → 0.93.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/latex/render.d.ts +4 -0
- package/latex/render.js +15 -8
- package/package.json +1 -1
- package/process/spawn.d.ts +15 -4
- package/process/spawn.js +18 -0
- package/utils/try-ignore.d.ts +4 -4
package/latex/render.d.ts
CHANGED
|
@@ -9,11 +9,15 @@ export type LatexRenderOptions = {
|
|
|
9
9
|
/**
|
|
10
10
|
* Renders LaTeX source code to a PDF file.
|
|
11
11
|
*
|
|
12
|
+
* ## WARNING
|
|
13
|
+
* **This function should not be used with untrusted LaTeX source, as it can lead to arbitrary code execution on the system.**
|
|
14
|
+
*
|
|
12
15
|
* Requires latexmk and LuaTeX to be installed on the system.
|
|
13
16
|
*
|
|
14
17
|
* **Minimal recommendation:**
|
|
15
18
|
* - **Arch Linux:** texlive-binextra texlive-luatex texlive-latexrecommended texlive-fontsrecommended
|
|
16
19
|
* @param source The LaTeX source code to render
|
|
20
|
+
* @param options Rendering options
|
|
17
21
|
* @returns A TemporaryFile representing the generated PDF
|
|
18
22
|
*/
|
|
19
23
|
export declare function renderLatex(source: string, options?: LatexRenderOptions): Promise<TemporaryFile>;
|
package/latex/render.js
CHANGED
|
@@ -51,7 +51,8 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
53
|
import { TemporaryFile } from '../file/server/temporary-file.js';
|
|
54
|
-
import {
|
|
54
|
+
import { spawnWaitCommand, spawnWaitReadCommand } from '../process/spawn.js';
|
|
55
|
+
import { withTimeout } from '../utils/timing.js';
|
|
55
56
|
import { tryIgnoreAsync } from '../utils/try-ignore.js';
|
|
56
57
|
const engineMapping = {
|
|
57
58
|
pdflatex: '-pdflatex',
|
|
@@ -61,11 +62,15 @@ const engineMapping = {
|
|
|
61
62
|
/**
|
|
62
63
|
* Renders LaTeX source code to a PDF file.
|
|
63
64
|
*
|
|
65
|
+
* ## WARNING
|
|
66
|
+
* **This function should not be used with untrusted LaTeX source, as it can lead to arbitrary code execution on the system.**
|
|
67
|
+
*
|
|
64
68
|
* Requires latexmk and LuaTeX to be installed on the system.
|
|
65
69
|
*
|
|
66
70
|
* **Minimal recommendation:**
|
|
67
71
|
* - **Arch Linux:** texlive-binextra texlive-luatex texlive-latexrecommended texlive-fontsrecommended
|
|
68
72
|
* @param source The LaTeX source code to render
|
|
73
|
+
* @param options Rendering options
|
|
69
74
|
* @returns A TemporaryFile representing the generated PDF
|
|
70
75
|
*/
|
|
71
76
|
export async function renderLatex(source, options) {
|
|
@@ -73,14 +78,16 @@ export async function renderLatex(source, options) {
|
|
|
73
78
|
try {
|
|
74
79
|
const latexFile = __addDisposableResource(env_1, await TemporaryFile.from(source, '.tex'), true);
|
|
75
80
|
const engineFlag = engineMapping[options?.engine ?? 'lualatex'];
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
const { code, output, error } = await spawnWaitReadCommand('string', 'latexmk', ['-interaction=nonstopmode', engineFlag, '-cd', latexFile.path], { throwOnNonZeroExitCode: false });
|
|
82
|
+
await tryIgnoreAsync(async () => await withTimeout(1000, spawnWaitCommand('latexmk', ['-c', '-cd', engineFlag, latexFile.path])));
|
|
83
|
+
if (code !== 0) {
|
|
84
|
+
throw new Error(`
|
|
85
|
+
LaTeX compilation failed with exit code ${code}.\n
|
|
86
|
+
File: ${latexFile.path}\n
|
|
87
|
+
Output:\n${output}\n
|
|
88
|
+
Error Output:\n${error}
|
|
89
|
+
`.trim());
|
|
82
90
|
}
|
|
83
|
-
await tryIgnoreAsync(async () => await spawnWaitCommand('latexmk', ['-interaction=nonstopmode', '-pdflua', '-cd', '-c', latexFile.path]));
|
|
84
91
|
return TemporaryFile.adopt(`${latexFile.path.slice(0, -4)}.pdf`);
|
|
85
92
|
}
|
|
86
93
|
catch (e_1) {
|
package/package.json
CHANGED
package/process/spawn.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { ChildProcessWithoutNullStreams } from 'node:child_process';
|
|
2
2
|
import type { Record } from '../types/types.js';
|
|
3
|
+
type WaitReadResultFormat = 'string' | 'binary';
|
|
4
|
+
type WaitReadResultFormatType<T extends WaitReadResultFormat> = T extends 'string' ? string : Uint8Array<ArrayBuffer>;
|
|
3
5
|
export type WaitOptions = {
|
|
4
6
|
throwOnNonZeroExitCode?: boolean;
|
|
5
7
|
};
|
|
6
|
-
export type
|
|
8
|
+
export type WaitResult = {
|
|
7
9
|
code: number | null;
|
|
8
10
|
signal: string | null;
|
|
9
11
|
};
|
|
12
|
+
export type WaitReadResult<Format extends WaitReadResultFormat> = WaitResult & {
|
|
13
|
+
output: WaitReadResultFormatType<Format>;
|
|
14
|
+
error: WaitReadResultFormatType<Format>;
|
|
15
|
+
};
|
|
10
16
|
export type SpawnOptions = {
|
|
11
17
|
arguments?: string[];
|
|
12
18
|
workingDirectory?: string;
|
|
@@ -22,11 +28,16 @@ export type SpawnCommandResult = TransformStream<Uint8Array, Uint8Array> & {
|
|
|
22
28
|
readErrorBytes(): Promise<Uint8Array>;
|
|
23
29
|
readError(): Promise<string>;
|
|
24
30
|
handleNonZeroExitCode(): void;
|
|
25
|
-
wait(options?: WaitOptions): Promise<
|
|
31
|
+
wait(options?: WaitOptions): Promise<WaitResult>;
|
|
32
|
+
waitRead<F extends WaitReadResultFormat>(format: F, options?: WaitOptions): Promise<WaitReadResult<F>>;
|
|
26
33
|
};
|
|
27
34
|
/** spwans a command and waits for it to complete */
|
|
28
|
-
export declare function spawnWaitCommand(command: string, args?: string[], options?: SpawnOptions & WaitOptions): Promise<
|
|
29
|
-
export declare function spawnWaitCommand(command: string, options?: SpawnOptions & WaitOptions): Promise<
|
|
35
|
+
export declare function spawnWaitCommand(command: string, args?: string[], options?: SpawnOptions & WaitOptions): Promise<WaitResult>;
|
|
36
|
+
export declare function spawnWaitCommand(command: string, options?: SpawnOptions & WaitOptions): Promise<WaitResult>;
|
|
37
|
+
/** spwans a command, waits for it to complete and reads its output */
|
|
38
|
+
export declare function spawnWaitReadCommand<F extends WaitReadResultFormat>(format: F, command: string, args?: string[], options?: SpawnOptions & WaitOptions): Promise<WaitReadResult<F>>;
|
|
39
|
+
export declare function spawnWaitReadCommand<F extends WaitReadResultFormat>(format: F, command: string, options?: SpawnOptions & WaitOptions): Promise<WaitReadResult<F>>;
|
|
30
40
|
/** Spawns a command as a child process. */
|
|
31
41
|
export declare function spawnCommand(command: string, args?: string[], options?: SpawnOptions): Promise<SpawnCommandResult>;
|
|
32
42
|
export declare function spawnCommand(command: string, options?: SpawnOptions): Promise<SpawnCommandResult>;
|
|
43
|
+
export {};
|
package/process/spawn.js
CHANGED
|
@@ -9,6 +9,11 @@ export async function spawnWaitCommand(command, argsOrOptions, optionsOrNothing)
|
|
|
9
9
|
const process = await spawnCommand(command, args, options);
|
|
10
10
|
return await process.wait({ throwOnNonZeroExitCode: options?.throwOnNonZeroExitCode });
|
|
11
11
|
}
|
|
12
|
+
export async function spawnWaitReadCommand(format, command, argsOrOptions, optionsOrNothing) {
|
|
13
|
+
const [args, options] = isArray(argsOrOptions) ? [argsOrOptions, optionsOrNothing] : [undefined, argsOrOptions];
|
|
14
|
+
const process = await spawnCommand(command, args, options);
|
|
15
|
+
return await process.waitRead(format, { throwOnNonZeroExitCode: options?.throwOnNonZeroExitCode });
|
|
16
|
+
}
|
|
12
17
|
export async function spawnCommand(command, argsOrOptions, optionsOrNothing) {
|
|
13
18
|
const { spawn } = await dynamicImport('node:child_process');
|
|
14
19
|
const { Readable, Writable } = await dynamicImport('node:stream');
|
|
@@ -81,6 +86,18 @@ export async function spawnCommand(command, argsOrOptions, optionsOrNothing) {
|
|
|
81
86
|
}
|
|
82
87
|
return result;
|
|
83
88
|
}
|
|
89
|
+
async function waitRead(format, { throwOnNonZeroExitCode = true } = {}) {
|
|
90
|
+
const [result, output, error] = await Promise.all([
|
|
91
|
+
wait({ throwOnNonZeroExitCode }),
|
|
92
|
+
(format === 'string') ? readOutput() : readOutputBytes(),
|
|
93
|
+
(format === 'string') ? readError() : readErrorBytes(),
|
|
94
|
+
]);
|
|
95
|
+
return {
|
|
96
|
+
...result,
|
|
97
|
+
output: output,
|
|
98
|
+
error: error,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
84
101
|
return {
|
|
85
102
|
process,
|
|
86
103
|
readable,
|
|
@@ -94,5 +111,6 @@ export async function spawnCommand(command, argsOrOptions, optionsOrNothing) {
|
|
|
94
111
|
readError,
|
|
95
112
|
handleNonZeroExitCode: () => void handleNonZeroExitCode(),
|
|
96
113
|
wait,
|
|
114
|
+
waitRead,
|
|
97
115
|
};
|
|
98
116
|
}
|
package/utils/try-ignore.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Logger } from '../logger/logger.js';
|
|
2
|
-
export declare function tryIgnore<R>(fn: () => R): R;
|
|
2
|
+
export declare function tryIgnore<R>(fn: () => R): R | undefined;
|
|
3
3
|
export declare function tryIgnore<R, F>(fn: () => R, fallback: F): R | F;
|
|
4
|
-
export declare function tryIgnoreAsync<R>(fn: () => Promise<R>): Promise<R>;
|
|
4
|
+
export declare function tryIgnoreAsync<R>(fn: () => Promise<R>): Promise<R | undefined>;
|
|
5
5
|
export declare function tryIgnoreAsync<R, F>(fn: () => Promise<R>, fallback: F): Promise<F>;
|
|
6
|
-
export declare function tryIgnoreLog<R>(logger: Logger, fn: () => R): R;
|
|
6
|
+
export declare function tryIgnoreLog<R>(logger: Logger, fn: () => R): R | undefined;
|
|
7
7
|
export declare function tryIgnoreLog<R, F>(logger: Logger, fn: () => R, fallback: F): R | F;
|
|
8
|
-
export declare function tryIgnoreLogAsync<R>(logger: Logger, fn: () => Promise<R>): Promise<R>;
|
|
8
|
+
export declare function tryIgnoreLogAsync<R>(logger: Logger, fn: () => Promise<R>): Promise<R | undefined>;
|
|
9
9
|
export declare function tryIgnoreLogAsync<R, F>(logger: Logger, fn: () => Promise<R>, fallback: F): Promise<F>;
|