texlite 0.7.3 → 0.7.5

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.
Files changed (26) hide show
  1. package/README.md +1 -6
  2. package/README.zh-CN.md +1 -6
  3. package/dist/client/assets/{BinaryModule-Aj1vLnwf-_qIOaefD.js → BinaryModule-Aj1vLnwf-CKY6Y_Pt.js} +1 -1
  4. package/dist/client/assets/{GitDialog-BmRzMv-C.js → GitDialog-pn8n5Afm.js} +1 -1
  5. package/dist/client/assets/{HistoryDialog-V0IkSDtJ.js → HistoryDialog-BpWEZrYf.js} +1 -1
  6. package/dist/client/assets/{LatexEditor-CokkLLxi.js → LatexEditor-DNAmNvHu.js} +1 -1
  7. package/dist/client/assets/{PdfPreview-Cs1WYPsC.js → PdfPreview-BVaG7TtG.js} +1 -1
  8. package/dist/client/assets/{ProjectNavigationDialogs-BVQb4qdD.js → ProjectNavigationDialogs-CaovMu4V.js} +1 -1
  9. package/dist/client/assets/{SystemMetricsDialog-DBrendnp.js → SystemMetricsDialog-D8jj7epG.js} +1 -1
  10. package/dist/client/assets/binary-BoldOm0z.js +1 -0
  11. package/dist/client/assets/index-BQCB3z5H.js +64 -0
  12. package/dist/client/assets/index-BnvpaWsa.css +1 -0
  13. package/dist/client/assets/{index-QyVe7I1s.js → index-Byn2Miy9.js} +1 -1
  14. package/dist/client/assets/{minus-yEV4SLvG.js → minus-K-5IK4nL.js} +1 -1
  15. package/dist/client/assets/pdf-BB1XvBIF.js +55 -0
  16. package/dist/client/assets/{spellCheck-OZGa6ljx.js → spellCheck-C32VQVUE.js} +3 -3
  17. package/dist/client/assets/texFmtRuntime-EYyQNUnJ.js +2 -0
  18. package/dist/client/assets/tex_fmt_bg-VEAUIuFz.wasm +0 -0
  19. package/dist/client/index.html +2 -2
  20. package/dist/server/app.js +0 -40
  21. package/package.json +3 -1
  22. package/dist/client/assets/binary-BQKEW09b.js +0 -1
  23. package/dist/client/assets/index-BS1IMOaB.js +0 -62
  24. package/dist/client/assets/index-Lw53KTaT.css +0 -1
  25. package/dist/client/assets/pdf-DPnwNQHb.js +0 -55
  26. package/dist/server/latexFormatter.js +0 -118
@@ -1,118 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { detachedProcessGroup, killProcessGroup } from "./processTree.js";
3
- const DEFAULT_COMMAND = "tex-fmt";
4
- const FORMAT_TIMEOUT_MS = 30_000;
5
- const MAX_DIAGNOSTIC_BYTES = 16 * 1024;
6
- /**
7
- * Invokes the optional host formatter without involving a shell. Keeping
8
- * this in the server means project-level tex-fmt.toml files are discovered
9
- * from the project's source directory and the browser never needs a native
10
- * executable.
11
- */
12
- export class LatexFormatterService {
13
- command;
14
- constructor(command = process.env.TEXLITE_TEX_FMT?.trim() || DEFAULT_COMMAND) {
15
- this.command = command;
16
- }
17
- async format(source, cwd) {
18
- const result = await runCommand(this.command, ["--stdin"], source, cwd, FORMAT_TIMEOUT_MS);
19
- // tex-fmt is optional like Git, but formatting must never silently switch
20
- // algorithms: users should know when the host formatter is unavailable.
21
- if (result.error?.code === "ENOENT")
22
- throw formatterUnavailable(this.command);
23
- if (result.error)
24
- throw formatterError(`无法运行 tex-fmt:${result.error.message}`);
25
- if (result.status !== 0) {
26
- const detail = result.stderr.trim() || `退出码 ${result.status ?? "unknown"}`;
27
- throw formatterError(`tex-fmt 格式化失败:${truncate(detail)}`);
28
- }
29
- if (source.trim() && !result.stdout.trim())
30
- throw formatterError("tex-fmt 未返回格式化后的源码");
31
- return { formatter: "tex-fmt", formatted: result.stdout };
32
- }
33
- }
34
- function formatterError(message) {
35
- return Object.assign(new Error(message), { code: "FORMAT_FAILED", statusCode: 422 });
36
- }
37
- function formatterUnavailable(command) {
38
- return Object.assign(new Error(`tex-fmt is not installed or cannot be found as "${command}". Install it from https://github.com/wgunderwood/tex-fmt and restart TexLite.`), { code: "FORMATTER_UNAVAILABLE", statusCode: 503 });
39
- }
40
- function truncate(value) {
41
- const bytes = Buffer.byteLength(value, "utf8");
42
- if (bytes <= MAX_DIAGNOSTIC_BYTES)
43
- return value;
44
- return `${Buffer.from(value, "utf8").subarray(0, MAX_DIAGNOSTIC_BYTES).toString("utf8")}…`;
45
- }
46
- function runCommand(command, args, input, cwd, timeoutMs) {
47
- return new Promise((resolve) => {
48
- let child;
49
- try {
50
- child = spawn(command, args, {
51
- cwd,
52
- env: { ...process.env, LC_ALL: "C" },
53
- shell: false,
54
- detached: detachedProcessGroup(),
55
- stdio: ["pipe", "pipe", "pipe"]
56
- });
57
- }
58
- catch (error) {
59
- resolve({
60
- status: null,
61
- stdout: "",
62
- stderr: "",
63
- error: error instanceof Error ? Object.assign(error, { code: error.code }) : new Error(String(error))
64
- });
65
- return;
66
- }
67
- const stdout = [];
68
- const stderr = [];
69
- let stdoutBytes = 0;
70
- let stderrBytes = 0;
71
- let settled = false;
72
- let timedOut = false;
73
- let outputTooLarge = false;
74
- const finish = (result) => {
75
- if (settled)
76
- return;
77
- settled = true;
78
- clearTimeout(timer);
79
- resolve({
80
- ...result,
81
- stdout: Buffer.concat(stdout).toString("utf8"),
82
- stderr: Buffer.concat(stderr).toString("utf8")
83
- });
84
- };
85
- const timer = setTimeout(() => {
86
- timedOut = true;
87
- killProcessGroup(child);
88
- }, timeoutMs);
89
- child.stdout.on("data", (chunk) => {
90
- if (outputTooLarge || stdoutBytes >= 64 * 1024 * 1024)
91
- return;
92
- const remaining = 64 * 1024 * 1024 - stdoutBytes;
93
- const bytes = chunk.byteLength > remaining ? chunk.subarray(0, remaining) : chunk;
94
- stdout.push(bytes);
95
- stdoutBytes += bytes.byteLength;
96
- if (chunk.byteLength > remaining) {
97
- outputTooLarge = true;
98
- killProcessGroup(child);
99
- }
100
- });
101
- child.stderr.on("data", (chunk) => {
102
- if (stderrBytes >= MAX_DIAGNOSTIC_BYTES)
103
- return;
104
- const remaining = MAX_DIAGNOSTIC_BYTES - stderrBytes;
105
- const bytes = chunk.byteLength > remaining ? chunk.subarray(0, remaining) : chunk;
106
- stderr.push(bytes);
107
- stderrBytes += bytes.byteLength;
108
- });
109
- child.once("error", (error) => finish({ status: null, error }));
110
- child.once("close", (status) => {
111
- finish({
112
- status,
113
- error: timedOut ? new Error(`命令超时(${timeoutMs}ms)`) : outputTooLarge ? new Error("tex-fmt 输出过大") : null
114
- });
115
- });
116
- child.stdin.end(input, "utf8");
117
- });
118
- }