@danielsimonjr/mathts-plot 0.3.48 → 0.4.0

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/dist/index.js CHANGED
@@ -1117,7 +1117,7 @@ function curve3d(x, y, z, opts = {}) {
1117
1117
  }
1118
1118
 
1119
1119
  // src/index.ts
1120
- var VERSION = "0.3.48";
1120
+ var VERSION = "0.4.0";
1121
1121
  export {
1122
1122
  VERSION,
1123
1123
  area,
@@ -9,9 +9,6 @@ interface RenderOptions {
9
9
  timeoutMs?: number;
10
10
  density?: number;
11
11
  background?: string;
12
- /** Enable LaTeX \write18 shell-escape. UNSAFE for untrusted TeX — allows
13
- * arbitrary command execution during compile. Default false. */
14
- shellEscape?: boolean;
15
12
  }
16
13
  interface RunResult {
17
14
  code: number | null;
@@ -30,10 +27,9 @@ declare function hasTool(name: string): Promise<boolean>;
30
27
  * the SVG through; `.png`/`.pdf` convert via rsvg-convert (preferred) or resvg.
31
28
  * Rejects with PlotRenderError naming the tool to install if none is present. */
32
29
  declare function renderToFile(svg: string, outPath: string, opts?: RenderOptions): Promise<void>;
33
- /** Build the CLI args for a LaTeX engine. Shell-escape (\write18) is OFF unless
34
- * `shellEscape` is true — enabling it is UNSAFE for untrusted TeX (arbitrary
35
- * command execution during compile). */
36
- declare function latexArgs(engine: string, workDir: string, texPath: string, shellEscape: boolean): string[];
30
+ /** Build the CLI args for a LaTeX engine. Shell-escape (\write18) is OFF
31
+ * for security (arbitrary command execution during compile). */
32
+ declare function latexArgs(engine: string, workDir: string, texPath: string): string[];
37
33
  /** Standalone LaTeX/TikZ source → PDF via pdflatex (preferred) or tectonic.
38
34
  * Compiles in an OS temp dir and copies the resulting PDF to `outPath`.
39
35
  * Rejects with PlotRenderError naming the engine to install if none is found. */
@@ -1,7 +1,7 @@
1
1
  // src/render-file.ts
2
2
  import { spawn } from "child_process";
3
3
  import { writeFile, rm, rename, mkdtemp, readFile } from "fs/promises";
4
- import { extname, join as joinPath } from "path";
4
+ import { extname, join as joinPath, basename } from "path";
5
5
  import { tmpdir } from "os";
6
6
  var PlotRenderError = class extends Error {
7
7
  constructor(message, missingTool) {
@@ -11,8 +11,13 @@ var PlotRenderError = class extends Error {
11
11
  }
12
12
  missingTool;
13
13
  };
14
+ var ALLOWED_TOOLS = ["rsvg-convert", "resvg", "pdflatex", "xelatex", "lualatex", "tectonic"];
14
15
  function runTool(cmd, args, opts = {}) {
15
16
  return new Promise((resolve, reject) => {
17
+ if (!ALLOWED_TOOLS.includes(basename(cmd))) {
18
+ reject(new PlotRenderError(`Security Error: Execution of tool '${cmd}' is not allowed.`));
19
+ return;
20
+ }
16
21
  const child = spawn(cmd, args, { timeout: opts.timeoutMs ?? 3e4 });
17
22
  const out = [];
18
23
  let err = "";
@@ -39,6 +44,9 @@ async function hasTool(name) {
39
44
  }
40
45
  }
41
46
  async function renderToFile(svg, outPath, opts = {}) {
47
+ if (opts.tool && !ALLOWED_TOOLS.includes(basename(opts.tool))) {
48
+ throw new PlotRenderError(`Security Error: Execution of tool '${opts.tool}' is not allowed.`);
49
+ }
42
50
  const ext = extname(outPath).toLowerCase();
43
51
  if (ext === ".svg") {
44
52
  await writeFile(outPath, svg, "utf-8");
@@ -94,12 +102,12 @@ async function renderToFile(svg, outPath, opts = {}) {
94
102
  "rsvg-convert"
95
103
  );
96
104
  }
97
- function latexArgs(engine, workDir, texPath, shellEscape) {
105
+ function latexArgs(engine, workDir, texPath) {
98
106
  if (engine === "tectonic") {
99
- return [...shellEscape ? ["-Z", "shell-escape"] : [], "--outdir", workDir, texPath];
107
+ return ["--outdir", workDir, texPath];
100
108
  }
101
109
  return [
102
- shellEscape ? "-shell-escape" : "-no-shell-escape",
110
+ "-no-shell-escape",
103
111
  "-interaction=nonstopmode",
104
112
  "-halt-on-error",
105
113
  "-output-directory",
@@ -108,6 +116,9 @@ function latexArgs(engine, workDir, texPath, shellEscape) {
108
116
  ];
109
117
  }
110
118
  async function latexToPdf(texSource, outPath, opts = {}) {
119
+ if (opts.tool && !ALLOWED_TOOLS.includes(basename(opts.tool))) {
120
+ throw new PlotRenderError(`Security Error: Execution of tool '${opts.tool}' is not allowed.`);
121
+ }
111
122
  if (extname(outPath).toLowerCase() !== ".pdf") {
112
123
  throw new PlotRenderError(`latexToPdf output must be a .pdf path (got '${outPath}')`);
113
124
  }
@@ -129,7 +140,7 @@ async function latexToPdf(texSource, outPath, opts = {}) {
129
140
  try {
130
141
  const texPath = joinPath(work, "doc.tex");
131
142
  await writeFile(texPath, texSource, "utf-8");
132
- const args = latexArgs(engine, work, texPath, opts.shellEscape === true);
143
+ const args = latexArgs(engine, work, texPath);
133
144
  const r = await runTool(engine, args, { timeoutMs: opts.timeoutMs ?? 6e4 });
134
145
  const pdfPath = joinPath(work, "doc.pdf");
135
146
  let pdf;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danielsimonjr/mathts-plot",
3
- "version": "0.3.48",
3
+ "version": "0.4.0",
4
4
  "description": "Headless SVG 2D/3D plotting for MathTS — dependency-light, expression-aware, built on core/functions/expression",
5
5
  "author": "Daniel Simon Jr.",
6
6
  "license": "MIT",
@@ -34,9 +34,9 @@
34
34
  "clean": "rm -rf dist"
35
35
  },
36
36
  "dependencies": {
37
- "@danielsimonjr/mathts-core": "^0.13.1",
38
- "@danielsimonjr/mathts-functions": "^0.61.0",
39
- "@danielsimonjr/mathts-expression": "^0.6.7"
37
+ "@danielsimonjr/mathts-core": "^0.14.0",
38
+ "@danielsimonjr/mathts-functions": "^0.62.0",
39
+ "@danielsimonjr/mathts-expression": "^0.7.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^25.5.2",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "repository": {
51
51
  "type": "git",
52
- "url": "https://github.com/danielsimonjr/mathts",
52
+ "url": "git+https://github.com/danielsimonjr/MathTS.git",
53
53
  "directory": "plot"
54
54
  },
55
55
  "keywords": [