terminal-png 0.1.1 → 0.1.3
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/ansi-parser.d.ts +2 -0
- package/dist/ansi-parser.js +179 -26
- package/dist/font.js +2 -2
- package/dist/index.js +23 -2
- package/dist/svg-renderer.js +45 -7
- package/package.json +3 -2
package/dist/ansi-parser.d.ts
CHANGED
package/dist/ansi-parser.js
CHANGED
|
@@ -7,7 +7,9 @@ function createDefaultStyle() {
|
|
|
7
7
|
italic: false,
|
|
8
8
|
underline: false,
|
|
9
9
|
strikethrough: false,
|
|
10
|
-
dim: false
|
|
10
|
+
dim: false,
|
|
11
|
+
inverse: false,
|
|
12
|
+
conceal: false
|
|
11
13
|
};
|
|
12
14
|
}
|
|
13
15
|
function cloneStyle(style) {
|
|
@@ -19,6 +21,8 @@ function stylesEqual(left, right) {
|
|
|
19
21
|
left.underline === right.underline &&
|
|
20
22
|
left.strikethrough === right.strikethrough &&
|
|
21
23
|
left.dim === right.dim &&
|
|
24
|
+
left.inverse === right.inverse &&
|
|
25
|
+
left.conceal === right.conceal &&
|
|
22
26
|
colorsEqual(left.fg, right.fg) &&
|
|
23
27
|
colorsEqual(left.bg, right.bg));
|
|
24
28
|
}
|
|
@@ -54,18 +58,20 @@ function pushRun(runs, style, text) {
|
|
|
54
58
|
italic: style.italic,
|
|
55
59
|
underline: style.underline,
|
|
56
60
|
strikethrough: style.strikethrough,
|
|
57
|
-
dim: style.dim
|
|
61
|
+
dim: style.dim,
|
|
62
|
+
inverse: style.inverse,
|
|
63
|
+
conceal: style.conceal
|
|
58
64
|
});
|
|
59
65
|
}
|
|
60
|
-
function parseCsi(input, start) {
|
|
61
|
-
let index = start +
|
|
66
|
+
function parseCsi(input, start, prefixLength) {
|
|
67
|
+
let index = start + prefixLength;
|
|
62
68
|
while (index < input.length) {
|
|
63
69
|
const code = input.charCodeAt(index);
|
|
64
70
|
if (code >= 0x40 && code <= 0x7e) {
|
|
65
71
|
return {
|
|
66
72
|
end: index + 1,
|
|
67
73
|
final: input[index],
|
|
68
|
-
params: input.slice(start +
|
|
74
|
+
params: input.slice(start + prefixLength, index)
|
|
69
75
|
};
|
|
70
76
|
}
|
|
71
77
|
index += 1;
|
|
@@ -73,7 +79,7 @@ function parseCsi(input, start) {
|
|
|
73
79
|
return {
|
|
74
80
|
end: input.length,
|
|
75
81
|
final: null,
|
|
76
|
-
params: input.slice(start +
|
|
82
|
+
params: input.slice(start + prefixLength)
|
|
77
83
|
};
|
|
78
84
|
}
|
|
79
85
|
function toInteger(value) {
|
|
@@ -125,16 +131,24 @@ function applyExtendedColor(params, start) {
|
|
|
125
131
|
function applySgr(style, paramsText) {
|
|
126
132
|
const nextStyle = cloneStyle(style);
|
|
127
133
|
const rawParams = paramsText.length === 0 ? ["0"] : paramsText.split(";");
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
134
|
+
for (let index = 0; index < rawParams.length; index += 1) {
|
|
135
|
+
const rawParam = rawParams[index] ?? "";
|
|
136
|
+
const colonColor = applyColonExtendedColor(rawParam);
|
|
137
|
+
if (colonColor !== undefined) {
|
|
138
|
+
if (colonColor !== null) {
|
|
139
|
+
if (colonColor.target === 38) {
|
|
140
|
+
nextStyle.fg = colonColor.color;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
nextStyle.bg = colonColor.color;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const value = rawParam.length === 0 ? 0 : toInteger(rawParam);
|
|
131
149
|
if (value === null) {
|
|
132
150
|
return nextStyle;
|
|
133
151
|
}
|
|
134
|
-
params.push(value);
|
|
135
|
-
}
|
|
136
|
-
for (let index = 0; index < params.length; index += 1) {
|
|
137
|
-
const value = params[index];
|
|
138
152
|
if (value === 0) {
|
|
139
153
|
Object.assign(nextStyle, createDefaultStyle());
|
|
140
154
|
continue;
|
|
@@ -176,6 +190,22 @@ function applySgr(style, paramsText) {
|
|
|
176
190
|
nextStyle.strikethrough = false;
|
|
177
191
|
continue;
|
|
178
192
|
}
|
|
193
|
+
if (value === 7) {
|
|
194
|
+
nextStyle.inverse = true;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (value === 27) {
|
|
198
|
+
nextStyle.inverse = false;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (value === 8) {
|
|
202
|
+
nextStyle.conceal = true;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (value === 28) {
|
|
206
|
+
nextStyle.conceal = false;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
179
209
|
if (value === 39) {
|
|
180
210
|
nextStyle.fg = null;
|
|
181
211
|
continue;
|
|
@@ -201,8 +231,14 @@ function applySgr(style, paramsText) {
|
|
|
201
231
|
continue;
|
|
202
232
|
}
|
|
203
233
|
if (value === 38 || value === 48) {
|
|
204
|
-
const
|
|
234
|
+
const params = rawParams.map((param) => toInteger(param));
|
|
235
|
+
const extended = params.every((param) => param !== null)
|
|
236
|
+
? applyExtendedColor(params, index + 1)
|
|
237
|
+
: null;
|
|
205
238
|
if (!extended) {
|
|
239
|
+
if (rawParams[index + 1] === "2" || rawParams[index + 1] === "5") {
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
206
242
|
continue;
|
|
207
243
|
}
|
|
208
244
|
if (value === 38) {
|
|
@@ -216,32 +252,149 @@ function applySgr(style, paramsText) {
|
|
|
216
252
|
}
|
|
217
253
|
return nextStyle;
|
|
218
254
|
}
|
|
219
|
-
|
|
255
|
+
function applyColonExtendedColor(rawParam) {
|
|
256
|
+
if (!rawParam.includes(":")) {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
const segments = rawParam.split(":");
|
|
260
|
+
const target = toInteger(segments[0]);
|
|
261
|
+
if (target !== 38 && target !== 48) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const mode = toInteger(segments[1]);
|
|
265
|
+
if (mode === 5) {
|
|
266
|
+
const index = toInteger(segments[2]);
|
|
267
|
+
return index === null ? null : { target, color: { type: "ansi8", index: clampByte(index) } };
|
|
268
|
+
}
|
|
269
|
+
if (mode !== 2) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
const offset = segments[2] === "" ? 3 : 2;
|
|
273
|
+
const r = toInteger(segments[offset]);
|
|
274
|
+
const g = toInteger(segments[offset + 1]);
|
|
275
|
+
const b = toInteger(segments[offset + 2]);
|
|
276
|
+
if (r === null || g === null || b === null) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
return { target, color: { type: "rgb", r: clampByte(r), g: clampByte(g), b: clampByte(b) } };
|
|
280
|
+
}
|
|
281
|
+
function parseOscEnd(input, start) {
|
|
282
|
+
let index = start + 2;
|
|
283
|
+
while (index < input.length) {
|
|
284
|
+
if (input[index] === "\u0007") {
|
|
285
|
+
return index + 1;
|
|
286
|
+
}
|
|
287
|
+
if (input[index] === ESC && input[index + 1] === "\\") {
|
|
288
|
+
return index + 2;
|
|
289
|
+
}
|
|
290
|
+
index += 1;
|
|
291
|
+
}
|
|
292
|
+
return input.length;
|
|
293
|
+
}
|
|
294
|
+
function positionParameter(params, index, fallback) {
|
|
295
|
+
const value = toInteger(params.split(";")[index]);
|
|
296
|
+
return value === null || value < 1 ? fallback : value;
|
|
297
|
+
}
|
|
298
|
+
function buildRuns(lines, lineBreakStyles) {
|
|
220
299
|
const runs = [];
|
|
300
|
+
const defaultStyle = createDefaultStyle();
|
|
301
|
+
for (let row = 0; row < lines.length; row += 1) {
|
|
302
|
+
const line = lines[row] ?? [];
|
|
303
|
+
let lastCell = line.length - 1;
|
|
304
|
+
while (lastCell >= 0 && line[lastCell] === undefined) {
|
|
305
|
+
lastCell -= 1;
|
|
306
|
+
}
|
|
307
|
+
for (let column = 0; column <= lastCell; column += 1) {
|
|
308
|
+
const cell = line[column] ?? { text: " ", style: defaultStyle };
|
|
309
|
+
pushRun(runs, cell.style, cell.text);
|
|
310
|
+
}
|
|
311
|
+
if (row < lines.length - 1) {
|
|
312
|
+
pushRun(runs, lineBreakStyles[row] ?? defaultStyle, "\n");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return runs;
|
|
316
|
+
}
|
|
317
|
+
export function parseAnsi(input) {
|
|
318
|
+
const lines = [[]];
|
|
319
|
+
const lineBreakStyles = [];
|
|
221
320
|
let style = createDefaultStyle();
|
|
222
|
-
let
|
|
321
|
+
let row = 0;
|
|
322
|
+
let column = 0;
|
|
223
323
|
let index = 0;
|
|
324
|
+
const ensureLine = () => {
|
|
325
|
+
while (lines.length <= row) {
|
|
326
|
+
lines.push([]);
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
const moveDown = (keepColumn) => {
|
|
330
|
+
lineBreakStyles[row] = cloneStyle(style);
|
|
331
|
+
row += 1;
|
|
332
|
+
if (!keepColumn) {
|
|
333
|
+
column = 0;
|
|
334
|
+
}
|
|
335
|
+
ensureLine();
|
|
336
|
+
};
|
|
224
337
|
while (index < input.length) {
|
|
225
338
|
const char = input[index];
|
|
226
339
|
if (char === "\n") {
|
|
227
|
-
|
|
228
|
-
pushRun(runs, style, "\n");
|
|
340
|
+
moveDown(false);
|
|
229
341
|
index += 1;
|
|
230
|
-
textStart = index;
|
|
231
342
|
continue;
|
|
232
343
|
}
|
|
233
|
-
if (char ===
|
|
234
|
-
|
|
235
|
-
|
|
344
|
+
if (char === "\v") {
|
|
345
|
+
moveDown(true);
|
|
346
|
+
index += 1;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
if (char === "\r") {
|
|
350
|
+
column = 0;
|
|
351
|
+
index += 1;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (char === "\b") {
|
|
355
|
+
column = Math.max(0, column - 1);
|
|
356
|
+
index += 1;
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
if (char === ESC && input[index + 1] === "]") {
|
|
360
|
+
index = parseOscEnd(input, index);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
const csiPrefixLength = char === "\u009b" ? 1 : char === ESC && input[index + 1] === "[" ? 2 : null;
|
|
364
|
+
if (csiPrefixLength !== null) {
|
|
365
|
+
const sequence = parseCsi(input, index, csiPrefixLength);
|
|
236
366
|
if (sequence.final === "m") {
|
|
237
367
|
style = applySgr(style, sequence.params);
|
|
238
368
|
}
|
|
369
|
+
else if (sequence.final === "G") {
|
|
370
|
+
column = positionParameter(sequence.params, 0, 1) - 1;
|
|
371
|
+
}
|
|
372
|
+
else if (sequence.final === "C") {
|
|
373
|
+
column += positionParameter(sequence.params, 0, 1);
|
|
374
|
+
}
|
|
375
|
+
else if (sequence.final === "D") {
|
|
376
|
+
column = Math.max(0, column - positionParameter(sequence.params, 0, 1));
|
|
377
|
+
}
|
|
378
|
+
else if (sequence.final === "A") {
|
|
379
|
+
row = Math.max(0, row - positionParameter(sequence.params, 0, 1));
|
|
380
|
+
}
|
|
381
|
+
else if (sequence.final === "B") {
|
|
382
|
+
row += positionParameter(sequence.params, 0, 1);
|
|
383
|
+
ensureLine();
|
|
384
|
+
}
|
|
385
|
+
else if (sequence.final === "H" || sequence.final === "f") {
|
|
386
|
+
row = positionParameter(sequence.params, 0, 1) - 1;
|
|
387
|
+
column = positionParameter(sequence.params, 1, 1) - 1;
|
|
388
|
+
ensureLine();
|
|
389
|
+
}
|
|
239
390
|
index = sequence.end;
|
|
240
|
-
textStart = index;
|
|
241
391
|
continue;
|
|
242
392
|
}
|
|
243
|
-
|
|
393
|
+
const codePoint = input.codePointAt(index);
|
|
394
|
+
const text = codePoint === undefined ? "" : String.fromCodePoint(codePoint);
|
|
395
|
+
lines[row][column] = { text, style: cloneStyle(style) };
|
|
396
|
+
column += 1;
|
|
397
|
+
index += text.length;
|
|
244
398
|
}
|
|
245
|
-
|
|
246
|
-
return runs;
|
|
399
|
+
return buildRuns(lines, lineBreakStyles);
|
|
247
400
|
}
|
package/dist/font.js
CHANGED
|
@@ -22,12 +22,12 @@ function createFontFace(base64, weight, style) {
|
|
|
22
22
|
}`;
|
|
23
23
|
}
|
|
24
24
|
export const JETBRAINS_MONO_BASE64 = readWebfontBase64("JetBrainsMono-Regular.woff2");
|
|
25
|
-
export const JETBRAINS_MONO_FONT_FILES = [
|
|
25
|
+
export const JETBRAINS_MONO_FONT_FILES = Object.freeze([
|
|
26
26
|
resolveAssetPath("jetbrains-mono-400-normal.ttf"),
|
|
27
27
|
resolveAssetPath("jetbrains-mono-700-normal.ttf"),
|
|
28
28
|
resolveAssetPath("jetbrains-mono-400-italic.ttf"),
|
|
29
29
|
resolveAssetPath("jetbrains-mono-700-italic.ttf")
|
|
30
|
-
];
|
|
30
|
+
]);
|
|
31
31
|
export const JETBRAINS_MONO_TTF_PATH = JETBRAINS_MONO_FONT_FILES[0];
|
|
32
32
|
export const FONT_FACE_CSS = [
|
|
33
33
|
createFontFace(JETBRAINS_MONO_BASE64, 400, "normal"),
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { rename, rm, writeFile } from "node:fs/promises";
|
|
2
3
|
import { parseAnsi } from "./ansi-parser.js";
|
|
3
4
|
import { renderPng } from "./png-renderer.js";
|
|
4
5
|
import { renderSvg } from "./svg-renderer.js";
|
|
5
6
|
export async function renderTerminalPng(ansiText, options = {}) {
|
|
7
|
+
if (options.padding !== undefined && (!Number.isInteger(options.padding) || options.padding < 0)) {
|
|
8
|
+
throw new Error("Padding must be a non-negative integer.");
|
|
9
|
+
}
|
|
6
10
|
const runs = parseAnsi(ansiText);
|
|
7
11
|
const svg = renderSvg(runs, {
|
|
8
12
|
padding: options.padding,
|
|
@@ -10,7 +14,24 @@ export async function renderTerminalPng(ansiText, options = {}) {
|
|
|
10
14
|
});
|
|
11
15
|
const png = renderPng(svg);
|
|
12
16
|
if (options.output) {
|
|
13
|
-
|
|
17
|
+
const temporaryPath = `${options.output}.${randomUUID()}.tmp`;
|
|
18
|
+
let temporaryCreated = false;
|
|
19
|
+
try {
|
|
20
|
+
await writeFile(temporaryPath, png, { flag: "wx" });
|
|
21
|
+
temporaryCreated = true;
|
|
22
|
+
await rename(temporaryPath, options.output);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (temporaryCreated) {
|
|
26
|
+
try {
|
|
27
|
+
await rm(temporaryPath, { force: true });
|
|
28
|
+
}
|
|
29
|
+
catch (cleanupError) {
|
|
30
|
+
void cleanupError;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
14
35
|
}
|
|
15
36
|
return png;
|
|
16
37
|
}
|
package/dist/svg-renderer.js
CHANGED
|
@@ -114,16 +114,30 @@ function splitIntoLines(runs) {
|
|
|
114
114
|
return lines;
|
|
115
115
|
}
|
|
116
116
|
function measureLines(lines) {
|
|
117
|
-
return Math.max(...lines.map(line => line.
|
|
117
|
+
return Math.max(...lines.map((line) => displayWidth(line.map((run) => run.text).join("")) * CHARACTER_WIDTH), 0);
|
|
118
118
|
}
|
|
119
|
-
function displayWidth(text) {
|
|
119
|
+
function displayWidth(text, startColumn = 0) {
|
|
120
120
|
const segmenter = new Intl.Segmenter();
|
|
121
|
-
let
|
|
121
|
+
let column = startColumn;
|
|
122
122
|
for (const { segment } of segmenter.segment(text)) {
|
|
123
|
+
if (segment === "\t") {
|
|
124
|
+
column += 8 - (column % 8);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
123
127
|
const cp = segment.codePointAt(0);
|
|
124
|
-
|
|
128
|
+
if (cp !== undefined && isZeroWidthCodePoint(cp)) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
column += cp !== undefined && (isWideCodePoint(cp) || isFlagSegment(segment)) ? 2 : 1;
|
|
125
132
|
}
|
|
126
|
-
return
|
|
133
|
+
return column - startColumn;
|
|
134
|
+
}
|
|
135
|
+
function isZeroWidthCodePoint(cp) {
|
|
136
|
+
return (cp >= 0x0300 && cp <= 0x036f) || (cp >= 0x1ab0 && cp <= 0x1aff) || (cp >= 0x1dc0 && cp <= 0x1dff) || (cp >= 0x20d0 && cp <= 0x20ff) || (cp >= 0xfe20 && cp <= 0xfe2f);
|
|
137
|
+
}
|
|
138
|
+
function isFlagSegment(segment) {
|
|
139
|
+
const codePoints = [...segment].map((character) => character.codePointAt(0));
|
|
140
|
+
return codePoints.length === 2 && codePoints.every((cp) => cp !== undefined && cp >= 0x1f1e6 && cp <= 0x1f1ff);
|
|
127
141
|
}
|
|
128
142
|
function isWideCodePoint(cp) {
|
|
129
143
|
return ((cp >= 0x1100 && cp <= 0x115F) || // Hangul Jamo
|
|
@@ -155,6 +169,7 @@ function renderLines(lines, textStartX, textStartY, lineHeightPx) {
|
|
|
155
169
|
return `<text x="${formatNumber(textStartX)}" y="${y}" xml:space="preserve"/>`;
|
|
156
170
|
}
|
|
157
171
|
return [
|
|
172
|
+
renderBackgrounds(line, textStartX, textStartY + (index * lineHeightPx) - lineHeightPx, lineHeightPx),
|
|
158
173
|
`<text x="${formatNumber(textStartX)}" y="${y}" xml:space="preserve">`,
|
|
159
174
|
line.map(renderRun).join(""),
|
|
160
175
|
"</text>"
|
|
@@ -162,9 +177,22 @@ function renderLines(lines, textStartX, textStartY, lineHeightPx) {
|
|
|
162
177
|
})
|
|
163
178
|
.join("");
|
|
164
179
|
}
|
|
180
|
+
function renderBackgrounds(line, startX, y, height) {
|
|
181
|
+
let column = 0;
|
|
182
|
+
const rectangles = [];
|
|
183
|
+
for (const run of line) {
|
|
184
|
+
const width = displayWidth(run.text, column);
|
|
185
|
+
const background = resolveBackgroundColor(run);
|
|
186
|
+
if (background !== BACKGROUND && width > 0) {
|
|
187
|
+
rectangles.push(`<rect x="${formatNumber(startX + (column * CHARACTER_WIDTH))}" y="${formatNumber(y)}" width="${formatNumber(width * CHARACTER_WIDTH)}" height="${formatNumber(height)}" fill="${escapeXmlAttribute(background)}" />`);
|
|
188
|
+
}
|
|
189
|
+
column += width;
|
|
190
|
+
}
|
|
191
|
+
return rectangles.join("");
|
|
192
|
+
}
|
|
165
193
|
function renderRun(run) {
|
|
166
194
|
const attributes = ['xml:space="preserve"'];
|
|
167
|
-
const color =
|
|
195
|
+
const color = resolveForegroundColor(run);
|
|
168
196
|
const textDecorations = [];
|
|
169
197
|
if (color !== DEFAULT_FOREGROUND) {
|
|
170
198
|
attributes.push(`fill="${escapeXmlAttribute(color)}"`);
|
|
@@ -187,7 +215,8 @@ function renderRun(run) {
|
|
|
187
215
|
if (run.dim) {
|
|
188
216
|
attributes.push('opacity="0.7"');
|
|
189
217
|
}
|
|
190
|
-
|
|
218
|
+
const text = run.conceal ? " ".repeat(displayWidth(run.text)) : run.text;
|
|
219
|
+
return `<tspan ${attributes.join(" ")}>${escapeXmlText(text)}</tspan>`;
|
|
191
220
|
}
|
|
192
221
|
function renderWindowControls() {
|
|
193
222
|
return [
|
|
@@ -211,6 +240,15 @@ function resolveColor(color) {
|
|
|
211
240
|
}
|
|
212
241
|
return `rgb(${color.r},${color.g},${color.b})`;
|
|
213
242
|
}
|
|
243
|
+
function resolveForegroundColor(run) {
|
|
244
|
+
return run.inverse ? resolveColorOrDefault(run.bg, BACKGROUND) : resolveColor(run.fg);
|
|
245
|
+
}
|
|
246
|
+
function resolveBackgroundColor(run) {
|
|
247
|
+
return run.inverse ? resolveColor(run.fg) : resolveColorOrDefault(run.bg, BACKGROUND);
|
|
248
|
+
}
|
|
249
|
+
function resolveColorOrDefault(color, defaultColor) {
|
|
250
|
+
return color === null ? defaultColor : resolveColor(color);
|
|
251
|
+
}
|
|
214
252
|
function escapeXmlText(value) {
|
|
215
253
|
return value
|
|
216
254
|
.replaceAll("&", "&")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminal-png",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Render PNG images from ANSI terminal output.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"terminal-png": "./bin/terminal-png"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "tsc -p tsconfig.build.json",
|
|
13
|
+
"build": "node ../../scripts/guard-package-dist.mjs && tsc -p tsconfig.build.json",
|
|
14
|
+
"prepack": "node ../../scripts/set-bin-executable.mjs",
|
|
14
15
|
"compare": "tsx scripts/compare.ts"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|