terminal-pilot 0.0.6 → 0.0.8
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/cli.js +5663 -1269
- package/dist/cli.js.map +4 -4
- package/dist/commands/close-session.js +268 -87
- package/dist/commands/close-session.js.map +4 -4
- package/dist/commands/create-session.js +268 -87
- package/dist/commands/create-session.js.map +4 -4
- package/dist/commands/fill.js +268 -87
- package/dist/commands/fill.js.map +4 -4
- package/dist/commands/get-session.js +268 -87
- package/dist/commands/get-session.js.map +4 -4
- package/dist/commands/index.js +2404 -279
- package/dist/commands/index.js.map +4 -4
- package/dist/commands/install.js +1372 -14
- package/dist/commands/install.js.map +4 -4
- package/dist/commands/installer.js +178 -15
- package/dist/commands/installer.js.map +4 -4
- package/dist/commands/list-sessions.js +268 -87
- package/dist/commands/list-sessions.js.map +4 -4
- package/dist/commands/press-key.js +268 -87
- package/dist/commands/press-key.js.map +4 -4
- package/dist/commands/read-history.js +268 -87
- package/dist/commands/read-history.js.map +4 -4
- package/dist/commands/read-screen.js +268 -87
- package/dist/commands/read-screen.js.map +4 -4
- package/dist/commands/resize.js +268 -87
- package/dist/commands/resize.js.map +4 -4
- package/dist/commands/runtime.js +27 -85
- package/dist/commands/runtime.js.map +4 -4
- package/dist/commands/screenshot.js +1033 -91
- package/dist/commands/screenshot.js.map +4 -4
- package/dist/commands/send-signal.js +268 -87
- package/dist/commands/send-signal.js.map +4 -4
- package/dist/commands/type.js +268 -87
- package/dist/commands/type.js.map +4 -4
- package/dist/commands/uninstall.js +419 -17
- package/dist/commands/uninstall.js.map +4 -4
- package/dist/commands/wait-for-exit.js +268 -87
- package/dist/commands/wait-for-exit.js.map +4 -4
- package/dist/commands/wait-for.js +268 -87
- package/dist/commands/wait-for.js.map +4 -4
- package/dist/index.js +19 -83
- package/dist/index.js.map +3 -3
- package/dist/terminal-pilot.js +19 -83
- package/dist/terminal-pilot.js.map +3 -3
- package/dist/terminal-session.js +19 -83
- package/dist/terminal-session.js.map +3 -3
- package/dist/testing/cli-repl.js +5598 -1203
- package/dist/testing/cli-repl.js.map +4 -4
- package/dist/testing/qa-cli.js +5601 -1206
- package/dist/testing/qa-cli.js.map +4 -4
- package/package.json +17 -8
|
@@ -1,20 +1,1028 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import {
|
|
3
|
-
import { renderTerminalPng } from "terminal-png";
|
|
1
|
+
// ../cmdkit/src/index.ts
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
4
3
|
|
|
5
|
-
// src/
|
|
6
|
-
|
|
4
|
+
// ../cmdkit-schema/src/index.ts
|
|
5
|
+
function assertValidEnumValues(values) {
|
|
6
|
+
if (values.length === 0) {
|
|
7
|
+
throw new Error("Enum schema requires at least one value");
|
|
8
|
+
}
|
|
9
|
+
const uniqueValues = new Set(values);
|
|
10
|
+
if (uniqueValues.size !== values.length) {
|
|
11
|
+
throw new Error("Enum schema values must be unique");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
var S = {
|
|
15
|
+
String(options = {}) {
|
|
16
|
+
return {
|
|
17
|
+
kind: "string",
|
|
18
|
+
...options
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
Number(options = {}) {
|
|
22
|
+
return {
|
|
23
|
+
kind: "number",
|
|
24
|
+
...options
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
Boolean(options = {}) {
|
|
28
|
+
return {
|
|
29
|
+
kind: "boolean",
|
|
30
|
+
...options
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
Enum(values, options = {}) {
|
|
34
|
+
assertValidEnumValues(values);
|
|
35
|
+
return {
|
|
36
|
+
kind: "enum",
|
|
37
|
+
values,
|
|
38
|
+
...options
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
Array(item, options = {}) {
|
|
42
|
+
return {
|
|
43
|
+
kind: "array",
|
|
44
|
+
item,
|
|
45
|
+
...options
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
Object(shape) {
|
|
49
|
+
return {
|
|
50
|
+
kind: "object",
|
|
51
|
+
shape
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
Optional(inner) {
|
|
55
|
+
return {
|
|
56
|
+
kind: "optional",
|
|
57
|
+
inner
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// ../cmdkit/src/index.ts
|
|
63
|
+
var commandConfigSymbol = /* @__PURE__ */ Symbol("cmdkit.command.config");
|
|
64
|
+
var commandSourcePathSymbol = /* @__PURE__ */ Symbol("cmdkit.command.sourcePath");
|
|
65
|
+
var UserError = class extends Error {
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.name = "UserError";
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
function cloneScope(scope) {
|
|
72
|
+
return scope === void 0 ? void 0 : [...scope];
|
|
73
|
+
}
|
|
74
|
+
function cloneSecretDefinition(secret) {
|
|
75
|
+
return {
|
|
76
|
+
env: secret.env,
|
|
77
|
+
description: secret.description,
|
|
78
|
+
optional: secret.optional
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function cloneSecrets(secrets) {
|
|
82
|
+
if (secrets === void 0) {
|
|
83
|
+
return {};
|
|
84
|
+
}
|
|
85
|
+
return Object.fromEntries(
|
|
86
|
+
Object.entries(secrets).map(([key, secret]) => [key, cloneSecretDefinition(secret)])
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
function cloneRequires(requires) {
|
|
90
|
+
if (requires === void 0) {
|
|
91
|
+
return void 0;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
auth: requires.auth,
|
|
95
|
+
apiVersion: requires.apiVersion,
|
|
96
|
+
check: requires.check
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function parseStackPath(candidate) {
|
|
100
|
+
if (candidate.startsWith("file://")) {
|
|
101
|
+
try {
|
|
102
|
+
return fileURLToPath(candidate);
|
|
103
|
+
} catch {
|
|
104
|
+
return void 0;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (candidate.startsWith("/")) {
|
|
108
|
+
return candidate;
|
|
109
|
+
}
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
function extractStackPath(line) {
|
|
113
|
+
const trimmed = line.trim();
|
|
114
|
+
const fileIndex = trimmed.indexOf("file://");
|
|
115
|
+
if (fileIndex >= 0) {
|
|
116
|
+
const location2 = trimmed.slice(fileIndex);
|
|
117
|
+
const separatorIndex2 = location2.lastIndexOf(":");
|
|
118
|
+
const previousSeparatorIndex2 = separatorIndex2 >= 0 ? location2.lastIndexOf(":", separatorIndex2 - 1) : -1;
|
|
119
|
+
const candidate2 = separatorIndex2 >= 0 && previousSeparatorIndex2 >= 0 ? location2.slice(0, previousSeparatorIndex2) : location2;
|
|
120
|
+
return parseStackPath(candidate2);
|
|
121
|
+
}
|
|
122
|
+
const slashIndex = trimmed.indexOf("/");
|
|
123
|
+
if (slashIndex < 0) {
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
const location = trimmed.slice(slashIndex);
|
|
127
|
+
const separatorIndex = location.lastIndexOf(":");
|
|
128
|
+
const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(":", separatorIndex - 1) : -1;
|
|
129
|
+
const candidate = separatorIndex >= 0 && previousSeparatorIndex >= 0 ? location.slice(0, previousSeparatorIndex) : location;
|
|
130
|
+
return parseStackPath(candidate);
|
|
131
|
+
}
|
|
132
|
+
function inferCommandSourcePath() {
|
|
133
|
+
const stack = new Error().stack;
|
|
134
|
+
if (typeof stack !== "string") {
|
|
135
|
+
return void 0;
|
|
136
|
+
}
|
|
137
|
+
for (const line of stack.split("\n").slice(1)) {
|
|
138
|
+
const candidate = extractStackPath(line);
|
|
139
|
+
if (candidate === void 0) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (candidate.includes("/packages/cmdkit/src/index.ts") || candidate.includes("/packages/cmdkit/dist/index.js")) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
return candidate;
|
|
146
|
+
}
|
|
147
|
+
return void 0;
|
|
148
|
+
}
|
|
149
|
+
function composeChecks(parentCheck, childCheck) {
|
|
150
|
+
if (parentCheck === void 0) {
|
|
151
|
+
return childCheck;
|
|
152
|
+
}
|
|
153
|
+
if (childCheck === void 0) {
|
|
154
|
+
return parentCheck;
|
|
155
|
+
}
|
|
156
|
+
return async (ctx) => {
|
|
157
|
+
const parentResult = await parentCheck(ctx);
|
|
158
|
+
if (!parentResult.ok) {
|
|
159
|
+
return parentResult;
|
|
160
|
+
}
|
|
161
|
+
return childCheck(ctx);
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function mergeRequires(parent, child) {
|
|
165
|
+
if (parent === void 0 && child === void 0) {
|
|
166
|
+
return void 0;
|
|
167
|
+
}
|
|
168
|
+
const merged = {
|
|
169
|
+
auth: child?.auth ?? parent?.auth,
|
|
170
|
+
apiVersion: child?.apiVersion ?? parent?.apiVersion,
|
|
171
|
+
check: composeChecks(parent?.check, child?.check)
|
|
172
|
+
};
|
|
173
|
+
if (merged.auth === void 0 && merged.apiVersion === void 0 && merged.check === void 0) {
|
|
174
|
+
return void 0;
|
|
175
|
+
}
|
|
176
|
+
return merged;
|
|
177
|
+
}
|
|
178
|
+
function mergeSecrets(parent, child) {
|
|
179
|
+
return cloneSecrets({
|
|
180
|
+
...parent,
|
|
181
|
+
...child
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function resolveCommandScope(ownScope, inheritedScope) {
|
|
185
|
+
return cloneScope(ownScope ?? inheritedScope) ?? ["cli", "sdk"];
|
|
186
|
+
}
|
|
187
|
+
function createBaseCommand(config) {
|
|
188
|
+
const command = {
|
|
189
|
+
kind: "command",
|
|
190
|
+
name: config.name,
|
|
191
|
+
description: config.description,
|
|
192
|
+
aliases: [...config.aliases ?? []],
|
|
193
|
+
positional: [...config.positional ?? []],
|
|
194
|
+
params: config.params,
|
|
195
|
+
secrets: cloneSecrets(config.secrets),
|
|
196
|
+
scope: resolveCommandScope(config.scope, void 0),
|
|
197
|
+
confirm: config.confirm ?? false,
|
|
198
|
+
requires: cloneRequires(config.requires),
|
|
199
|
+
handler: config.handler,
|
|
200
|
+
render: config.render
|
|
201
|
+
};
|
|
202
|
+
Object.defineProperty(command, commandConfigSymbol, {
|
|
203
|
+
value: {
|
|
204
|
+
scope: cloneScope(config.scope),
|
|
205
|
+
secrets: cloneSecrets(config.secrets),
|
|
206
|
+
requires: cloneRequires(config.requires),
|
|
207
|
+
sourcePath: inferCommandSourcePath()
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
return command;
|
|
211
|
+
}
|
|
212
|
+
function getInternalCommandConfig(command) {
|
|
213
|
+
return command[commandConfigSymbol];
|
|
214
|
+
}
|
|
215
|
+
function materializeCommand(command, inherited) {
|
|
216
|
+
const internal = getInternalCommandConfig(command);
|
|
217
|
+
const materialized = {
|
|
218
|
+
kind: "command",
|
|
219
|
+
name: command.name,
|
|
220
|
+
description: command.description,
|
|
221
|
+
aliases: [...command.aliases],
|
|
222
|
+
positional: [...command.positional],
|
|
223
|
+
params: command.params,
|
|
224
|
+
secrets: mergeSecrets(inherited.secrets, internal.secrets),
|
|
225
|
+
scope: resolveCommandScope(internal.scope, inherited.scope),
|
|
226
|
+
confirm: command.confirm,
|
|
227
|
+
requires: mergeRequires(inherited.requires, internal.requires),
|
|
228
|
+
handler: command.handler,
|
|
229
|
+
render: command.render
|
|
230
|
+
};
|
|
231
|
+
Object.defineProperty(materialized, commandConfigSymbol, {
|
|
232
|
+
value: {
|
|
233
|
+
scope: cloneScope(internal.scope),
|
|
234
|
+
secrets: cloneSecrets(internal.secrets),
|
|
235
|
+
requires: cloneRequires(internal.requires),
|
|
236
|
+
sourcePath: internal.sourcePath
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
Object.defineProperty(materialized, commandSourcePathSymbol, {
|
|
240
|
+
value: internal.sourcePath
|
|
241
|
+
});
|
|
242
|
+
return materialized;
|
|
243
|
+
}
|
|
244
|
+
function defineCommand(config) {
|
|
245
|
+
return materializeCommand(createBaseCommand(config), {
|
|
246
|
+
scope: void 0,
|
|
247
|
+
secrets: {},
|
|
248
|
+
requires: void 0
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ../terminal-png/src/index.ts
|
|
253
|
+
import { writeFile } from "node:fs/promises";
|
|
254
|
+
|
|
255
|
+
// ../terminal-png/src/ansi-parser.ts
|
|
256
|
+
var ESC = "\x1B";
|
|
257
|
+
function createDefaultStyle() {
|
|
258
|
+
return {
|
|
259
|
+
fg: null,
|
|
260
|
+
bg: null,
|
|
261
|
+
bold: false,
|
|
262
|
+
italic: false,
|
|
263
|
+
underline: false,
|
|
264
|
+
strikethrough: false,
|
|
265
|
+
dim: false
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function cloneStyle(style) {
|
|
269
|
+
return { ...style };
|
|
270
|
+
}
|
|
271
|
+
function stylesEqual(left, right) {
|
|
272
|
+
return left.bold === right.bold && left.italic === right.italic && left.underline === right.underline && left.strikethrough === right.strikethrough && left.dim === right.dim && colorsEqual(left.fg, right.fg) && colorsEqual(left.bg, right.bg);
|
|
273
|
+
}
|
|
274
|
+
function colorsEqual(left, right) {
|
|
275
|
+
if (left === right) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
if (!left || !right || left.type !== right.type) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
if (left.type === "rgb" && right.type === "rgb") {
|
|
282
|
+
return left.r === right.r && left.g === right.g && left.b === right.b;
|
|
283
|
+
}
|
|
284
|
+
if ((left.type === "ansi4" || left.type === "ansi8") && left.type === right.type) {
|
|
285
|
+
return left.index === right.index;
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
function pushRun(runs, style, text) {
|
|
290
|
+
if (text.length === 0) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const previous = runs.at(-1);
|
|
294
|
+
if (previous && text !== "\n" && previous.text !== "\n" && stylesEqual(previous, style)) {
|
|
295
|
+
previous.text += text;
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
runs.push({
|
|
299
|
+
text,
|
|
300
|
+
fg: style.fg,
|
|
301
|
+
bg: style.bg,
|
|
302
|
+
bold: style.bold,
|
|
303
|
+
italic: style.italic,
|
|
304
|
+
underline: style.underline,
|
|
305
|
+
strikethrough: style.strikethrough,
|
|
306
|
+
dim: style.dim
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
function parseCsi(input, start) {
|
|
310
|
+
let index = start + 2;
|
|
311
|
+
while (index < input.length) {
|
|
312
|
+
const code = input.charCodeAt(index);
|
|
313
|
+
if (code >= 64 && code <= 126) {
|
|
314
|
+
return {
|
|
315
|
+
end: index + 1,
|
|
316
|
+
final: input[index],
|
|
317
|
+
params: input.slice(start + 2, index)
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
index += 1;
|
|
321
|
+
}
|
|
322
|
+
return {
|
|
323
|
+
end: input.length,
|
|
324
|
+
final: null,
|
|
325
|
+
params: input.slice(start + 2)
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function toInteger(value) {
|
|
329
|
+
if (!value || value.length === 0) {
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
for (const char of value) {
|
|
333
|
+
if (char < "0" || char > "9") {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return Number.parseInt(value, 10);
|
|
338
|
+
}
|
|
339
|
+
function clampByte(value) {
|
|
340
|
+
if (value < 0) {
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
if (value > 255) {
|
|
344
|
+
return 255;
|
|
345
|
+
}
|
|
346
|
+
return value;
|
|
347
|
+
}
|
|
348
|
+
function applyExtendedColor(params2, start) {
|
|
349
|
+
const mode = params2[start];
|
|
350
|
+
if (mode === 5) {
|
|
351
|
+
const index = params2[start + 1];
|
|
352
|
+
if (index === void 0) {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
color: { type: "ansi8", index: clampByte(index) },
|
|
357
|
+
consumed: 2
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
if (mode === 2) {
|
|
361
|
+
const r = params2[start + 1];
|
|
362
|
+
const g = params2[start + 2];
|
|
363
|
+
const b = params2[start + 3];
|
|
364
|
+
if (r === void 0 || g === void 0 || b === void 0) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
color: { type: "rgb", r: clampByte(r), g: clampByte(g), b: clampByte(b) },
|
|
369
|
+
consumed: 4
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
function applySgr(style, paramsText) {
|
|
375
|
+
const nextStyle = cloneStyle(style);
|
|
376
|
+
const rawParams = paramsText.length === 0 ? ["0"] : paramsText.split(";");
|
|
377
|
+
const params2 = [];
|
|
378
|
+
for (const rawParam of rawParams) {
|
|
379
|
+
const value = toInteger(rawParam);
|
|
380
|
+
if (value === null) {
|
|
381
|
+
return nextStyle;
|
|
382
|
+
}
|
|
383
|
+
params2.push(value);
|
|
384
|
+
}
|
|
385
|
+
for (let index = 0; index < params2.length; index += 1) {
|
|
386
|
+
const value = params2[index];
|
|
387
|
+
if (value === 0) {
|
|
388
|
+
Object.assign(nextStyle, createDefaultStyle());
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (value === 1) {
|
|
392
|
+
nextStyle.bold = true;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (value === 2) {
|
|
396
|
+
nextStyle.dim = true;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (value === 22) {
|
|
400
|
+
nextStyle.bold = false;
|
|
401
|
+
nextStyle.dim = false;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (value === 3) {
|
|
405
|
+
nextStyle.italic = true;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
if (value === 23) {
|
|
409
|
+
nextStyle.italic = false;
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (value === 4) {
|
|
413
|
+
nextStyle.underline = true;
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
if (value === 24) {
|
|
417
|
+
nextStyle.underline = false;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (value === 9) {
|
|
421
|
+
nextStyle.strikethrough = true;
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
if (value === 29) {
|
|
425
|
+
nextStyle.strikethrough = false;
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (value === 39) {
|
|
429
|
+
nextStyle.fg = null;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (value === 49) {
|
|
433
|
+
nextStyle.bg = null;
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
if (value >= 30 && value <= 37) {
|
|
437
|
+
nextStyle.fg = { type: "ansi4", index: value - 30 };
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
if (value >= 90 && value <= 97) {
|
|
441
|
+
nextStyle.fg = { type: "ansi4", index: value - 90 + 8 };
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
if (value >= 40 && value <= 47) {
|
|
445
|
+
nextStyle.bg = { type: "ansi4", index: value - 40 };
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
if (value >= 100 && value <= 107) {
|
|
449
|
+
nextStyle.bg = { type: "ansi4", index: value - 100 + 8 };
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (value === 38 || value === 48) {
|
|
453
|
+
const extended = applyExtendedColor(params2, index + 1);
|
|
454
|
+
if (!extended) {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (value === 38) {
|
|
458
|
+
nextStyle.fg = extended.color;
|
|
459
|
+
} else {
|
|
460
|
+
nextStyle.bg = extended.color;
|
|
461
|
+
}
|
|
462
|
+
index += extended.consumed;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return nextStyle;
|
|
466
|
+
}
|
|
467
|
+
function parseAnsi(input) {
|
|
468
|
+
const runs = [];
|
|
469
|
+
let style = createDefaultStyle();
|
|
470
|
+
let textStart = 0;
|
|
471
|
+
let index = 0;
|
|
472
|
+
while (index < input.length) {
|
|
473
|
+
const char = input[index];
|
|
474
|
+
if (char === "\n") {
|
|
475
|
+
pushRun(runs, style, input.slice(textStart, index));
|
|
476
|
+
pushRun(runs, style, "\n");
|
|
477
|
+
index += 1;
|
|
478
|
+
textStart = index;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (char === ESC && input[index + 1] === "[") {
|
|
482
|
+
pushRun(runs, style, input.slice(textStart, index));
|
|
483
|
+
const sequence = parseCsi(input, index);
|
|
484
|
+
if (sequence.final === "m") {
|
|
485
|
+
style = applySgr(style, sequence.params);
|
|
486
|
+
}
|
|
487
|
+
index = sequence.end;
|
|
488
|
+
textStart = index;
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
index += 1;
|
|
492
|
+
}
|
|
493
|
+
pushRun(runs, style, input.slice(textStart));
|
|
494
|
+
return runs;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// ../terminal-png/src/png-renderer.ts
|
|
498
|
+
import { Resvg } from "@resvg/resvg-js";
|
|
499
|
+
|
|
500
|
+
// ../terminal-png/src/font.ts
|
|
501
|
+
import { readFileSync } from "node:fs";
|
|
502
|
+
import { createRequire } from "node:module";
|
|
503
|
+
import { dirname, join } from "node:path";
|
|
504
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
505
|
+
var require2 = createRequire(import.meta.url);
|
|
506
|
+
var fontPackageRoot = dirname(require2.resolve("jetbrains-mono/package.json"));
|
|
507
|
+
var webfontRoot = join(fontPackageRoot, "fonts/webfonts");
|
|
508
|
+
function readWebfontBase64(filename) {
|
|
509
|
+
return readFileSync(join(webfontRoot, filename)).toString("base64");
|
|
510
|
+
}
|
|
511
|
+
function resolveAssetPath(filename) {
|
|
512
|
+
return fileURLToPath2(new URL(`../assets/${filename}`, import.meta.url));
|
|
513
|
+
}
|
|
514
|
+
function createFontFace(base64, weight, style) {
|
|
515
|
+
return `@font-face {
|
|
516
|
+
font-family: 'JetBrains Mono';
|
|
517
|
+
font-style: ${style};
|
|
518
|
+
font-weight: ${weight};
|
|
519
|
+
src: url('data:font/woff2;base64,${base64}') format('woff2');
|
|
520
|
+
}`;
|
|
521
|
+
}
|
|
522
|
+
var JETBRAINS_MONO_BASE64 = readWebfontBase64("JetBrainsMono-Regular.woff2");
|
|
523
|
+
var JETBRAINS_MONO_FONT_FILES = [
|
|
524
|
+
resolveAssetPath("jetbrains-mono-400-normal.ttf"),
|
|
525
|
+
resolveAssetPath("jetbrains-mono-700-normal.ttf"),
|
|
526
|
+
resolveAssetPath("jetbrains-mono-400-italic.ttf"),
|
|
527
|
+
resolveAssetPath("jetbrains-mono-700-italic.ttf")
|
|
528
|
+
];
|
|
529
|
+
var JETBRAINS_MONO_TTF_PATH = JETBRAINS_MONO_FONT_FILES[0];
|
|
530
|
+
var FONT_FACE_CSS = [
|
|
531
|
+
createFontFace(JETBRAINS_MONO_BASE64, 400, "normal"),
|
|
532
|
+
createFontFace(readWebfontBase64("JetBrainsMono-Bold.woff2"), 700, "normal"),
|
|
533
|
+
createFontFace(readWebfontBase64("JetBrainsMono-Italic.woff2"), 400, "italic"),
|
|
534
|
+
createFontFace(readWebfontBase64("JetBrainsMono-BoldItalic.woff2"), 700, "italic")
|
|
535
|
+
].join("\n");
|
|
536
|
+
|
|
537
|
+
// ../terminal-png/src/png-renderer.ts
|
|
538
|
+
function renderPng(svg) {
|
|
539
|
+
const resvg = new Resvg(svg, {
|
|
540
|
+
font: {
|
|
541
|
+
defaultFontFamily: "JetBrains Mono",
|
|
542
|
+
fontFiles: [...JETBRAINS_MONO_FONT_FILES],
|
|
543
|
+
loadSystemFonts: false,
|
|
544
|
+
monospaceFamily: "JetBrains Mono"
|
|
545
|
+
},
|
|
546
|
+
fitTo: {
|
|
547
|
+
mode: "zoom",
|
|
548
|
+
value: 4
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
const png = resvg.render();
|
|
552
|
+
return Buffer.from(png.asPng());
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// ../terminal-png/src/svg-renderer.ts
|
|
556
|
+
var ANSI_16_PALETTE = [
|
|
557
|
+
"#282a2e",
|
|
558
|
+
"#D74E6F",
|
|
559
|
+
"#31BB71",
|
|
560
|
+
"#D3E561",
|
|
561
|
+
"#8056FF",
|
|
562
|
+
"#ED61D7",
|
|
563
|
+
"#04D7D7",
|
|
564
|
+
"#C5C8C6",
|
|
565
|
+
"#4B4B4B",
|
|
566
|
+
"#FE5F86",
|
|
567
|
+
"#00D787",
|
|
568
|
+
"#EBFF71",
|
|
569
|
+
"#8F69FF",
|
|
570
|
+
"#FF7AEA",
|
|
571
|
+
"#00FEFE",
|
|
572
|
+
"#FFFFFF"
|
|
573
|
+
];
|
|
574
|
+
var XTERM_256_PALETTE = [
|
|
575
|
+
"#000000",
|
|
576
|
+
"#800000",
|
|
577
|
+
"#008000",
|
|
578
|
+
"#808000",
|
|
579
|
+
"#000080",
|
|
580
|
+
"#800080",
|
|
581
|
+
"#008080",
|
|
582
|
+
"#c0c0c0",
|
|
583
|
+
"#808080",
|
|
584
|
+
"#ff0000",
|
|
585
|
+
"#00ff00",
|
|
586
|
+
"#ffff00",
|
|
587
|
+
"#0000ff",
|
|
588
|
+
"#ff00ff",
|
|
589
|
+
"#00ffff",
|
|
590
|
+
"#ffffff",
|
|
591
|
+
"#000000",
|
|
592
|
+
"#00005f",
|
|
593
|
+
"#000087",
|
|
594
|
+
"#0000af",
|
|
595
|
+
"#0000d7",
|
|
596
|
+
"#0000ff",
|
|
597
|
+
"#005f00",
|
|
598
|
+
"#005f5f",
|
|
599
|
+
"#005f87",
|
|
600
|
+
"#005faf",
|
|
601
|
+
"#005fd7",
|
|
602
|
+
"#005fff",
|
|
603
|
+
"#008700",
|
|
604
|
+
"#00875f",
|
|
605
|
+
"#008787",
|
|
606
|
+
"#0087af",
|
|
607
|
+
"#0087d7",
|
|
608
|
+
"#0087ff",
|
|
609
|
+
"#00af00",
|
|
610
|
+
"#00af5f",
|
|
611
|
+
"#00af87",
|
|
612
|
+
"#00afaf",
|
|
613
|
+
"#00afd7",
|
|
614
|
+
"#00afff",
|
|
615
|
+
"#00d700",
|
|
616
|
+
"#00d75f",
|
|
617
|
+
"#00d787",
|
|
618
|
+
"#00d7af",
|
|
619
|
+
"#00d7d7",
|
|
620
|
+
"#00d7ff",
|
|
621
|
+
"#00ff00",
|
|
622
|
+
"#00ff5f",
|
|
623
|
+
"#00ff87",
|
|
624
|
+
"#00ffaf",
|
|
625
|
+
"#00ffd7",
|
|
626
|
+
"#00ffff",
|
|
627
|
+
"#5f0000",
|
|
628
|
+
"#5f005f",
|
|
629
|
+
"#5f0087",
|
|
630
|
+
"#5f00af",
|
|
631
|
+
"#5f00d7",
|
|
632
|
+
"#5f00ff",
|
|
633
|
+
"#5f5f00",
|
|
634
|
+
"#5f5f5f",
|
|
635
|
+
"#5f5f87",
|
|
636
|
+
"#5f5faf",
|
|
637
|
+
"#5f5fd7",
|
|
638
|
+
"#5f5fff",
|
|
639
|
+
"#5f8700",
|
|
640
|
+
"#5f875f",
|
|
641
|
+
"#5f8787",
|
|
642
|
+
"#5f87af",
|
|
643
|
+
"#5f87d7",
|
|
644
|
+
"#5f87ff",
|
|
645
|
+
"#5faf00",
|
|
646
|
+
"#5faf5f",
|
|
647
|
+
"#5faf87",
|
|
648
|
+
"#5fafaf",
|
|
649
|
+
"#5fafd7",
|
|
650
|
+
"#5fafff",
|
|
651
|
+
"#5fd700",
|
|
652
|
+
"#5fd75f",
|
|
653
|
+
"#5fd787",
|
|
654
|
+
"#5fd7af",
|
|
655
|
+
"#5fd7d7",
|
|
656
|
+
"#5fd7ff",
|
|
657
|
+
"#5fff00",
|
|
658
|
+
"#5fff5f",
|
|
659
|
+
"#5fff87",
|
|
660
|
+
"#5fffaf",
|
|
661
|
+
"#5fffd7",
|
|
662
|
+
"#5fffff",
|
|
663
|
+
"#870000",
|
|
664
|
+
"#87005f",
|
|
665
|
+
"#870087",
|
|
666
|
+
"#8700af",
|
|
667
|
+
"#8700d7",
|
|
668
|
+
"#8700ff",
|
|
669
|
+
"#875f00",
|
|
670
|
+
"#875f5f",
|
|
671
|
+
"#875f87",
|
|
672
|
+
"#875faf",
|
|
673
|
+
"#875fd7",
|
|
674
|
+
"#875fff",
|
|
675
|
+
"#878700",
|
|
676
|
+
"#87875f",
|
|
677
|
+
"#878787",
|
|
678
|
+
"#8787af",
|
|
679
|
+
"#8787d7",
|
|
680
|
+
"#8787ff",
|
|
681
|
+
"#87af00",
|
|
682
|
+
"#87af5f",
|
|
683
|
+
"#87af87",
|
|
684
|
+
"#87afaf",
|
|
685
|
+
"#87afd7",
|
|
686
|
+
"#87afff",
|
|
687
|
+
"#87d700",
|
|
688
|
+
"#87d75f",
|
|
689
|
+
"#87d787",
|
|
690
|
+
"#87d7af",
|
|
691
|
+
"#87d7d7",
|
|
692
|
+
"#87d7ff",
|
|
693
|
+
"#87ff00",
|
|
694
|
+
"#87ff5f",
|
|
695
|
+
"#87ff87",
|
|
696
|
+
"#87ffaf",
|
|
697
|
+
"#87ffd7",
|
|
698
|
+
"#87ffff",
|
|
699
|
+
"#af0000",
|
|
700
|
+
"#af005f",
|
|
701
|
+
"#af0087",
|
|
702
|
+
"#af00af",
|
|
703
|
+
"#af00d7",
|
|
704
|
+
"#af00ff",
|
|
705
|
+
"#af5f00",
|
|
706
|
+
"#af5f5f",
|
|
707
|
+
"#af5f87",
|
|
708
|
+
"#af5faf",
|
|
709
|
+
"#af5fd7",
|
|
710
|
+
"#af5fff",
|
|
711
|
+
"#af8700",
|
|
712
|
+
"#af875f",
|
|
713
|
+
"#af8787",
|
|
714
|
+
"#af87af",
|
|
715
|
+
"#af87d7",
|
|
716
|
+
"#af87ff",
|
|
717
|
+
"#afaf00",
|
|
718
|
+
"#afaf5f",
|
|
719
|
+
"#afaf87",
|
|
720
|
+
"#afafaf",
|
|
721
|
+
"#afafd7",
|
|
722
|
+
"#afafff",
|
|
723
|
+
"#afd700",
|
|
724
|
+
"#afd75f",
|
|
725
|
+
"#afd787",
|
|
726
|
+
"#afd7af",
|
|
727
|
+
"#afd7d7",
|
|
728
|
+
"#afd7ff",
|
|
729
|
+
"#afff00",
|
|
730
|
+
"#afff5f",
|
|
731
|
+
"#afff87",
|
|
732
|
+
"#afffaf",
|
|
733
|
+
"#afffd7",
|
|
734
|
+
"#afffff",
|
|
735
|
+
"#d70000",
|
|
736
|
+
"#d7005f",
|
|
737
|
+
"#d70087",
|
|
738
|
+
"#d700af",
|
|
739
|
+
"#d700d7",
|
|
740
|
+
"#d700ff",
|
|
741
|
+
"#d75f00",
|
|
742
|
+
"#d75f5f",
|
|
743
|
+
"#d75f87",
|
|
744
|
+
"#d75faf",
|
|
745
|
+
"#d75fd7",
|
|
746
|
+
"#d75fff",
|
|
747
|
+
"#d78700",
|
|
748
|
+
"#d7875f",
|
|
749
|
+
"#d78787",
|
|
750
|
+
"#d787af",
|
|
751
|
+
"#d787d7",
|
|
752
|
+
"#d787ff",
|
|
753
|
+
"#d7af00",
|
|
754
|
+
"#d7af5f",
|
|
755
|
+
"#d7af87",
|
|
756
|
+
"#d7afaf",
|
|
757
|
+
"#d7afd7",
|
|
758
|
+
"#d7afff",
|
|
759
|
+
"#d7d700",
|
|
760
|
+
"#d7d75f",
|
|
761
|
+
"#d7d787",
|
|
762
|
+
"#d7d7af",
|
|
763
|
+
"#d7d7d7",
|
|
764
|
+
"#d7d7ff",
|
|
765
|
+
"#d7ff00",
|
|
766
|
+
"#d7ff5f",
|
|
767
|
+
"#d7ff87",
|
|
768
|
+
"#d7ffaf",
|
|
769
|
+
"#d7ffd7",
|
|
770
|
+
"#d7ffff",
|
|
771
|
+
"#ff0000",
|
|
772
|
+
"#ff005f",
|
|
773
|
+
"#ff0087",
|
|
774
|
+
"#ff00af",
|
|
775
|
+
"#ff00d7",
|
|
776
|
+
"#ff00ff",
|
|
777
|
+
"#ff5f00",
|
|
778
|
+
"#ff5f5f",
|
|
779
|
+
"#ff5f87",
|
|
780
|
+
"#ff5faf",
|
|
781
|
+
"#ff5fd7",
|
|
782
|
+
"#ff5fff",
|
|
783
|
+
"#ff8700",
|
|
784
|
+
"#ff875f",
|
|
785
|
+
"#ff8787",
|
|
786
|
+
"#ff87af",
|
|
787
|
+
"#ff87d7",
|
|
788
|
+
"#ff87ff",
|
|
789
|
+
"#ffaf00",
|
|
790
|
+
"#ffaf5f",
|
|
791
|
+
"#ffaf87",
|
|
792
|
+
"#ffafaf",
|
|
793
|
+
"#ffafd7",
|
|
794
|
+
"#ffafff",
|
|
795
|
+
"#ffd700",
|
|
796
|
+
"#ffd75f",
|
|
797
|
+
"#ffd787",
|
|
798
|
+
"#ffd7af",
|
|
799
|
+
"#ffd7d7",
|
|
800
|
+
"#ffd7ff",
|
|
801
|
+
"#ffff00",
|
|
802
|
+
"#ffff5f",
|
|
803
|
+
"#ffff87",
|
|
804
|
+
"#ffffaf",
|
|
805
|
+
"#ffffd7",
|
|
806
|
+
"#ffffff",
|
|
807
|
+
"#080808",
|
|
808
|
+
"#121212",
|
|
809
|
+
"#1c1c1c",
|
|
810
|
+
"#262626",
|
|
811
|
+
"#303030",
|
|
812
|
+
"#3a3a3a",
|
|
813
|
+
"#444444",
|
|
814
|
+
"#4e4e4e",
|
|
815
|
+
"#585858",
|
|
816
|
+
"#606060",
|
|
817
|
+
"#666666",
|
|
818
|
+
"#767676",
|
|
819
|
+
"#808080",
|
|
820
|
+
"#8a8a8a",
|
|
821
|
+
"#949494",
|
|
822
|
+
"#9e9e9e",
|
|
823
|
+
"#a8a8a8",
|
|
824
|
+
"#b2b2b2",
|
|
825
|
+
"#bcbcbc",
|
|
826
|
+
"#c6c6c6",
|
|
827
|
+
"#d0d0d0",
|
|
828
|
+
"#dadada",
|
|
829
|
+
"#e4e4e4",
|
|
830
|
+
"#eeeeee"
|
|
831
|
+
];
|
|
832
|
+
var BACKGROUND = "#171717";
|
|
833
|
+
var DEFAULT_FOREGROUND = "#c4c4c4";
|
|
834
|
+
var FONT_FAMILY = "JetBrains Mono";
|
|
835
|
+
var FONT_SIZE = 14;
|
|
836
|
+
var LINE_HEIGHT = 1.2;
|
|
837
|
+
var CHARACTER_WIDTH = 8.412666666666667;
|
|
838
|
+
var TEXT_BOTTOM_PADDING = 11.6;
|
|
839
|
+
var DEFAULT_PADDING = {
|
|
840
|
+
top: 20,
|
|
841
|
+
right: 40,
|
|
842
|
+
bottom: 20,
|
|
843
|
+
left: 20
|
|
844
|
+
};
|
|
845
|
+
var WINDOW_BAR_HEIGHT = 15;
|
|
846
|
+
function renderSvg(runs, options = {}) {
|
|
847
|
+
const padding = options.padding === void 0 ? DEFAULT_PADDING : {
|
|
848
|
+
top: options.padding,
|
|
849
|
+
right: options.padding,
|
|
850
|
+
bottom: options.padding,
|
|
851
|
+
left: options.padding
|
|
852
|
+
};
|
|
853
|
+
const showWindow = options.window ?? true;
|
|
854
|
+
const titleBarHeight = showWindow ? WINDOW_BAR_HEIGHT : 0;
|
|
855
|
+
const textStartX = padding.left;
|
|
856
|
+
const lineHeightPx = FONT_SIZE * LINE_HEIGHT;
|
|
857
|
+
const textStartY = titleBarHeight + padding.top + lineHeightPx;
|
|
858
|
+
const lines = splitIntoLines(runs);
|
|
859
|
+
const contentWidth = measureLines(lines);
|
|
860
|
+
const width = padding.left + contentWidth + padding.right;
|
|
861
|
+
const height = titleBarHeight + padding.top + lines.length * lineHeightPx + padding.bottom + TEXT_BOTTOM_PADDING;
|
|
862
|
+
const svgWidth = formatNumber(width);
|
|
863
|
+
const svgHeight = formatNumber(height);
|
|
864
|
+
const viewBox = `0 0 ${svgWidth} ${svgHeight}`;
|
|
865
|
+
const textElements = renderLines(lines, textStartX, textStartY, lineHeightPx);
|
|
866
|
+
return [
|
|
867
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${svgWidth}" height="${svgHeight}" viewBox="${viewBox}">`,
|
|
868
|
+
"<defs>",
|
|
869
|
+
"<style><![CDATA[",
|
|
870
|
+
FONT_FACE_CSS,
|
|
871
|
+
"]]></style>",
|
|
872
|
+
"</defs>",
|
|
873
|
+
`<rect x="0" y="0" width="${svgWidth}" height="${svgHeight}" fill="${BACKGROUND}" />`,
|
|
874
|
+
showWindow ? renderWindowControls() : "",
|
|
875
|
+
`<g font-family="${FONT_FAMILY}" font-size="${formatNumber(FONT_SIZE)}px" fill="${DEFAULT_FOREGROUND}">`,
|
|
876
|
+
textElements,
|
|
877
|
+
"</g>",
|
|
878
|
+
"</svg>"
|
|
879
|
+
].join("");
|
|
880
|
+
}
|
|
881
|
+
function splitIntoLines(runs) {
|
|
882
|
+
const lines = [[]];
|
|
883
|
+
for (const run of runs) {
|
|
884
|
+
if (run.text === "\n") {
|
|
885
|
+
lines.push([]);
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
lines[lines.length - 1]?.push(run);
|
|
889
|
+
}
|
|
890
|
+
return lines;
|
|
891
|
+
}
|
|
892
|
+
function measureLines(lines) {
|
|
893
|
+
return Math.max(
|
|
894
|
+
...lines.map((line) => line.reduce((width, run) => width + displayWidth(run.text) * CHARACTER_WIDTH, 0)),
|
|
895
|
+
0
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
function displayWidth(text) {
|
|
899
|
+
const segmenter = new Intl.Segmenter();
|
|
900
|
+
let width = 0;
|
|
901
|
+
for (const { segment } of segmenter.segment(text)) {
|
|
902
|
+
const cp = segment.codePointAt(0);
|
|
903
|
+
width += cp !== void 0 && isWideCodePoint(cp) ? 2 : 1;
|
|
904
|
+
}
|
|
905
|
+
return width;
|
|
906
|
+
}
|
|
907
|
+
function isWideCodePoint(cp) {
|
|
908
|
+
return cp >= 4352 && cp <= 4447 || // Hangul Jamo
|
|
909
|
+
cp === 9001 || cp === 9002 || // Angle brackets
|
|
910
|
+
cp >= 11904 && cp <= 12350 || // CJK Radicals, Kangxi
|
|
911
|
+
cp >= 12353 && cp <= 13247 || // Hiragana, Katakana, CJK symbols
|
|
912
|
+
cp >= 13312 && cp <= 19903 || // CJK Extension A
|
|
913
|
+
cp >= 19968 && cp <= 42191 || // CJK Unified Ideographs
|
|
914
|
+
cp >= 43360 && cp <= 43391 || // Hangul Jamo Extended-A
|
|
915
|
+
cp >= 44032 && cp <= 55215 || // Hangul Syllables
|
|
916
|
+
cp >= 63744 && cp <= 64255 || // CJK Compatibility Ideographs
|
|
917
|
+
cp >= 65040 && cp <= 65049 || // Vertical Forms
|
|
918
|
+
cp >= 65072 && cp <= 65135 || // CJK Compatibility Forms
|
|
919
|
+
cp >= 65280 && cp <= 65376 || // Fullwidth Latin, Halfwidth Katakana
|
|
920
|
+
cp >= 65504 && cp <= 65510 || // Fullwidth Signs
|
|
921
|
+
cp >= 110592 && cp <= 110847 || // Kana Supplement
|
|
922
|
+
cp >= 126980 && cp <= 126980 || // Mahjong tile
|
|
923
|
+
cp >= 127183 && cp <= 127183 || // Playing card black joker
|
|
924
|
+
cp >= 127488 && cp <= 131069 || // Enclosed CJK + Emoji
|
|
925
|
+
cp >= 131072 && cp <= 196605 || // CJK Extension B–F
|
|
926
|
+
cp >= 196608 && cp <= 262141;
|
|
927
|
+
}
|
|
928
|
+
function renderLines(lines, textStartX, textStartY, lineHeightPx) {
|
|
929
|
+
return lines.map((line, index) => {
|
|
930
|
+
const y = formatNumber(textStartY + index * lineHeightPx);
|
|
931
|
+
if (line.length === 0) {
|
|
932
|
+
return `<text x="${formatNumber(textStartX)}" y="${y}" xml:space="preserve"/>`;
|
|
933
|
+
}
|
|
934
|
+
return [
|
|
935
|
+
`<text x="${formatNumber(textStartX)}" y="${y}" xml:space="preserve">`,
|
|
936
|
+
line.map(renderRun).join(""),
|
|
937
|
+
"</text>"
|
|
938
|
+
].join("");
|
|
939
|
+
}).join("");
|
|
940
|
+
}
|
|
941
|
+
function renderRun(run) {
|
|
942
|
+
const attributes = ['xml:space="preserve"'];
|
|
943
|
+
const color = resolveColor(run.fg);
|
|
944
|
+
const textDecorations = [];
|
|
945
|
+
if (color !== DEFAULT_FOREGROUND) {
|
|
946
|
+
attributes.push(`fill="${escapeXmlAttribute(color)}"`);
|
|
947
|
+
}
|
|
948
|
+
if (run.bold) {
|
|
949
|
+
attributes.push('font-weight="bold"');
|
|
950
|
+
}
|
|
951
|
+
if (run.italic) {
|
|
952
|
+
attributes.push('font-style="italic"');
|
|
953
|
+
}
|
|
954
|
+
if (run.underline) {
|
|
955
|
+
textDecorations.push("underline");
|
|
956
|
+
}
|
|
957
|
+
if (run.strikethrough) {
|
|
958
|
+
textDecorations.push("line-through");
|
|
959
|
+
}
|
|
960
|
+
if (textDecorations.length > 0) {
|
|
961
|
+
attributes.push(`text-decoration="${textDecorations.join(" ")}"`);
|
|
962
|
+
}
|
|
963
|
+
if (run.dim) {
|
|
964
|
+
attributes.push('opacity="0.7"');
|
|
965
|
+
}
|
|
966
|
+
return `<tspan ${attributes.join(" ")}>${escapeXmlText(run.text)}</tspan>`;
|
|
967
|
+
}
|
|
968
|
+
function renderWindowControls() {
|
|
969
|
+
return [
|
|
970
|
+
'<circle cx="13.5" cy="12" r="5.5" fill="#FF5A54" />',
|
|
971
|
+
'<circle cx="32.5" cy="12" r="5.5" fill="#E6BF29" />',
|
|
972
|
+
'<circle cx="51.5" cy="12" r="5.5" fill="#52C12B" />'
|
|
973
|
+
].join("");
|
|
974
|
+
}
|
|
975
|
+
function resolveColor(color) {
|
|
976
|
+
if (color === null) {
|
|
977
|
+
return DEFAULT_FOREGROUND;
|
|
978
|
+
}
|
|
979
|
+
if (color.type === "ansi4") {
|
|
980
|
+
return ANSI_16_PALETTE[color.index] ?? DEFAULT_FOREGROUND;
|
|
981
|
+
}
|
|
982
|
+
if (color.type === "ansi8") {
|
|
983
|
+
if (color.index < ANSI_16_PALETTE.length) {
|
|
984
|
+
return ANSI_16_PALETTE[color.index] ?? DEFAULT_FOREGROUND;
|
|
985
|
+
}
|
|
986
|
+
return XTERM_256_PALETTE[color.index] ?? DEFAULT_FOREGROUND;
|
|
987
|
+
}
|
|
988
|
+
return `rgb(${color.r},${color.g},${color.b})`;
|
|
989
|
+
}
|
|
990
|
+
function escapeXmlText(value) {
|
|
991
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
992
|
+
}
|
|
993
|
+
function escapeXmlAttribute(value) {
|
|
994
|
+
return escapeXmlText(value).replaceAll('"', """).replaceAll("'", "'");
|
|
995
|
+
}
|
|
996
|
+
function formatNumber(value) {
|
|
997
|
+
return value.toFixed(2);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
// ../terminal-png/src/index.ts
|
|
1001
|
+
async function renderTerminalPng(ansiText, options = {}) {
|
|
1002
|
+
const runs = parseAnsi(ansiText);
|
|
1003
|
+
const svg = renderSvg(runs, {
|
|
1004
|
+
padding: options.padding,
|
|
1005
|
+
window: options.window
|
|
1006
|
+
});
|
|
1007
|
+
const png = renderPng(svg);
|
|
1008
|
+
if (options.output) {
|
|
1009
|
+
await writeFile(options.output, png);
|
|
1010
|
+
}
|
|
1011
|
+
return png;
|
|
1012
|
+
}
|
|
7
1013
|
|
|
8
1014
|
// src/terminal-pilot.ts
|
|
9
1015
|
import { randomUUID } from "node:crypto";
|
|
10
1016
|
|
|
11
1017
|
// src/terminal-session.ts
|
|
12
|
-
import { spawn as spawnChildProcess } from "node:child_process";
|
|
13
1018
|
import { EventEmitter } from "node:events";
|
|
1019
|
+
import { accessSync, chmodSync, constants } from "node:fs";
|
|
1020
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
1021
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
14
1022
|
import * as nodePty from "node-pty";
|
|
15
1023
|
|
|
16
1024
|
// src/ansi.ts
|
|
17
|
-
var
|
|
1025
|
+
var ESC2 = 27;
|
|
18
1026
|
var BEL = 7;
|
|
19
1027
|
var ST = 156;
|
|
20
1028
|
var CSI = 155;
|
|
@@ -27,7 +1035,7 @@ function stripAnsi(input) {
|
|
|
27
1035
|
let output = "";
|
|
28
1036
|
for (let index = 0; index < input.length; index += 1) {
|
|
29
1037
|
const code = input.charCodeAt(index);
|
|
30
|
-
if (code ===
|
|
1038
|
+
if (code === ESC2) {
|
|
31
1039
|
const nextCode = input.charCodeAt(index + 1);
|
|
32
1040
|
if (nextCode === 91) {
|
|
33
1041
|
index = consumeCsi(input, index + 2);
|
|
@@ -78,7 +1086,7 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
|
|
|
78
1086
|
if (code === ST || allowBellTerminator && code === BEL) {
|
|
79
1087
|
return index;
|
|
80
1088
|
}
|
|
81
|
-
if (code ===
|
|
1089
|
+
if (code === ESC2 && input.charCodeAt(index + 1) === 92) {
|
|
82
1090
|
return index + 1;
|
|
83
1091
|
}
|
|
84
1092
|
index += 1;
|
|
@@ -921,93 +1929,27 @@ function createPtyProcess({
|
|
|
921
1929
|
cols,
|
|
922
1930
|
rows
|
|
923
1931
|
}) {
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
cwd,
|
|
927
|
-
env,
|
|
928
|
-
cols,
|
|
929
|
-
rows,
|
|
930
|
-
encoding: "utf8"
|
|
931
|
-
});
|
|
932
|
-
} catch {
|
|
933
|
-
return createChildProcessFallback({ command, args, cwd, env });
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
function createChildProcessFallback({
|
|
937
|
-
command,
|
|
938
|
-
args,
|
|
939
|
-
cwd,
|
|
940
|
-
env
|
|
941
|
-
}) {
|
|
942
|
-
const child = spawnChildProcess(command, args, {
|
|
1932
|
+
ensureSpawnHelperExecutable();
|
|
1933
|
+
return nodePty.spawn(command, args, {
|
|
943
1934
|
cwd,
|
|
944
1935
|
env,
|
|
945
|
-
|
|
1936
|
+
cols,
|
|
1937
|
+
rows,
|
|
1938
|
+
encoding: "utf8"
|
|
946
1939
|
});
|
|
947
|
-
return new ChildProcessFallback(child);
|
|
948
1940
|
}
|
|
949
|
-
var
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
child.stderr.on("data", this.handleData);
|
|
961
|
-
child.on("exit", (exitCode, signal) => {
|
|
962
|
-
this.exitEmitter.emit("exit", {
|
|
963
|
-
exitCode: exitCode ?? signalToExitCode(signal),
|
|
964
|
-
signal: void 0
|
|
965
|
-
});
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
write(data) {
|
|
969
|
-
this.child.stdin.write(data);
|
|
970
|
-
}
|
|
971
|
-
resize() {
|
|
972
|
-
}
|
|
973
|
-
kill(signal) {
|
|
974
|
-
this.child.kill(signal);
|
|
975
|
-
}
|
|
976
|
-
onData(listener) {
|
|
977
|
-
this.dataEmitter.on("data", listener);
|
|
978
|
-
return {
|
|
979
|
-
dispose: () => {
|
|
980
|
-
this.dataEmitter.off("data", listener);
|
|
981
|
-
}
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
onExit(listener) {
|
|
985
|
-
this.exitEmitter.on("exit", listener);
|
|
986
|
-
return {
|
|
987
|
-
dispose: () => {
|
|
988
|
-
this.exitEmitter.off("exit", listener);
|
|
989
|
-
}
|
|
990
|
-
};
|
|
991
|
-
}
|
|
992
|
-
handleData = (chunk) => {
|
|
993
|
-
this.dataEmitter.emit("data", String(chunk));
|
|
994
|
-
};
|
|
995
|
-
};
|
|
996
|
-
function signalToExitCode(signal) {
|
|
997
|
-
if (signal === null) {
|
|
998
|
-
return 0;
|
|
999
|
-
}
|
|
1000
|
-
const signalNumbers = {
|
|
1001
|
-
SIGTERM: 15,
|
|
1002
|
-
SIGINT: 2,
|
|
1003
|
-
SIGHUP: 1,
|
|
1004
|
-
SIGKILL: 9
|
|
1005
|
-
};
|
|
1006
|
-
const signalNumber = signalNumbers[signal];
|
|
1007
|
-
if (signalNumber === void 0) {
|
|
1008
|
-
return 1;
|
|
1941
|
+
var spawnHelperChecked = false;
|
|
1942
|
+
function ensureSpawnHelperExecutable() {
|
|
1943
|
+
if (spawnHelperChecked) return;
|
|
1944
|
+
spawnHelperChecked = true;
|
|
1945
|
+
const require3 = createRequire2(import.meta.url);
|
|
1946
|
+
const nodePtyDir = dirname2(require3.resolve("node-pty"));
|
|
1947
|
+
const helper = join2(nodePtyDir, "..", "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper");
|
|
1948
|
+
try {
|
|
1949
|
+
accessSync(helper, constants.X_OK);
|
|
1950
|
+
} catch {
|
|
1951
|
+
chmodSync(helper, 493);
|
|
1009
1952
|
}
|
|
1010
|
-
return 128 + signalNumber;
|
|
1011
1953
|
}
|
|
1012
1954
|
function matchPattern(buffer, pattern) {
|
|
1013
1955
|
const clean = normalizeHistoryBuffer(stripAnsi(buffer));
|