esp32tool 1.6.4 → 1.6.6
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/apple-touch-icon.png +0 -0
- package/dist/console.d.ts +4 -0
- package/dist/console.js +54 -2
- package/dist/util/console-color.d.ts +10 -1
- package/dist/util/console-color.js +369 -30
- package/dist/util/line-break-transformer.js +18 -4
- package/dist/util/timestamp-transformer.d.ts +5 -0
- package/dist/util/timestamp-transformer.js +37 -0
- package/icons/icon-128.png +0 -0
- package/icons/icon-144.png +0 -0
- package/icons/icon-152.png +0 -0
- package/icons/icon-192.png +0 -0
- package/icons/icon-384.png +0 -0
- package/icons/icon-512.png +0 -0
- package/icons/icon-72.png +0 -0
- package/icons/icon-96.png +0 -0
- package/js/console.js +52 -3
- package/js/util/console-color.js +513 -211
- package/js/util/line-break-transformer.js +29 -17
- package/js/util/timestamp-transformer.js +37 -0
- package/package.cli.json +1 -1
- package/package.json +13 -12
- package/screenshots/desktop.png +0 -0
- package/screenshots/mobile.png +0 -0
- package/src/console.ts +57 -2
- package/src/util/console-color.ts +373 -32
- package/src/util/line-break-transformer.ts +18 -4
- package/src/util/timestamp-transformer.ts +45 -0
- package/sw.js +1 -1
- package/tsconfig.util.json +9 -0
|
@@ -1,3 +1,56 @@
|
|
|
1
|
+
const ANSI_256 = (() => {
|
|
2
|
+
const t = [];
|
|
3
|
+
// Standard colors 0-7
|
|
4
|
+
t[0] = "rgb(0,0,0)";
|
|
5
|
+
t[1] = "rgb(128,0,0)";
|
|
6
|
+
t[2] = "rgb(0,128,0)";
|
|
7
|
+
t[3] = "rgb(128,128,0)";
|
|
8
|
+
t[4] = "rgb(0,0,128)";
|
|
9
|
+
t[5] = "rgb(128,0,128)";
|
|
10
|
+
t[6] = "rgb(0,128,128)";
|
|
11
|
+
t[7] = "rgb(192,192,192)";
|
|
12
|
+
// Bright colors 8-15
|
|
13
|
+
t[8] = "rgb(128,128,128)";
|
|
14
|
+
t[9] = "rgb(255,0,0)";
|
|
15
|
+
t[10] = "rgb(0,255,0)";
|
|
16
|
+
t[11] = "rgb(255,255,0)";
|
|
17
|
+
t[12] = "rgb(99,153,255)";
|
|
18
|
+
t[13] = "rgb(255,0,255)";
|
|
19
|
+
t[14] = "rgb(0,255,255)";
|
|
20
|
+
t[15] = "rgb(255,255,255)";
|
|
21
|
+
// 6x6x6 color cube 16-231
|
|
22
|
+
for (let i = 0; i < 216; i++) {
|
|
23
|
+
const r = Math.floor(i / 36);
|
|
24
|
+
const g = Math.floor((i % 36) / 6);
|
|
25
|
+
const b = i % 6;
|
|
26
|
+
t[16 + i] =
|
|
27
|
+
"rgb(" +
|
|
28
|
+
(r ? r * 40 + 55 : 0) +
|
|
29
|
+
"," +
|
|
30
|
+
(g ? g * 40 + 55 : 0) +
|
|
31
|
+
"," +
|
|
32
|
+
(b ? b * 40 + 55 : 0) +
|
|
33
|
+
")";
|
|
34
|
+
}
|
|
35
|
+
// Grayscale ramp 232-255
|
|
36
|
+
for (let i = 0; i < 24; i++) {
|
|
37
|
+
const v = i * 10 + 8;
|
|
38
|
+
t[232 + i] = "rgb(" + v + "," + v + "," + v + ")";
|
|
39
|
+
}
|
|
40
|
+
return t;
|
|
41
|
+
})();
|
|
42
|
+
// Maps 256-color indices 0–7 to the named CSS class tokens so that
|
|
43
|
+
// \x1b[38;5;1m renders the same red as \x1b[31m.
|
|
44
|
+
const ANSI_NAMED = [
|
|
45
|
+
"black",
|
|
46
|
+
"red",
|
|
47
|
+
"green",
|
|
48
|
+
"yellow",
|
|
49
|
+
"blue",
|
|
50
|
+
"magenta",
|
|
51
|
+
"cyan",
|
|
52
|
+
"white",
|
|
53
|
+
];
|
|
1
54
|
export class ColoredConsole {
|
|
2
55
|
constructor(targetElement) {
|
|
3
56
|
this.targetElement = targetElement;
|
|
@@ -8,40 +61,38 @@ export class ColoredConsole {
|
|
|
8
61
|
strikethrough: false,
|
|
9
62
|
foregroundColor: null,
|
|
10
63
|
backgroundColor: null,
|
|
64
|
+
fgRgb: null,
|
|
65
|
+
bgRgb: null,
|
|
66
|
+
dim: false,
|
|
67
|
+
reverse: false,
|
|
11
68
|
carriageReturn: false,
|
|
69
|
+
lines: [],
|
|
12
70
|
secret: false,
|
|
71
|
+
blink: false,
|
|
72
|
+
rapidBlink: false,
|
|
13
73
|
};
|
|
14
74
|
}
|
|
15
75
|
logs() {
|
|
76
|
+
if (this.state.lines.length > 0) {
|
|
77
|
+
this.processLines();
|
|
78
|
+
}
|
|
16
79
|
return this.targetElement.innerText;
|
|
17
80
|
}
|
|
18
|
-
|
|
81
|
+
processLine(line) {
|
|
19
82
|
// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequences
|
|
20
83
|
// eslint-disable-next-line no-control-regex
|
|
21
|
-
const re = /(?:\x1B|\\x1B)(?:\[(.*?)[@-~]|\].*?(?:\x07|\x1B\\))/g;
|
|
84
|
+
const re = /(?:\x1B|\\x1B)(?:\[(.*?)([@-~])|\].*?(?:\x07|\x1B\\))/g;
|
|
22
85
|
let i = 0;
|
|
23
|
-
if (this.state.carriageReturn) {
|
|
24
|
-
if (line !== "\n") {
|
|
25
|
-
// don't remove if \r\n
|
|
26
|
-
if (this.targetElement.lastChild) {
|
|
27
|
-
this.targetElement.removeChild(this.targetElement.lastChild);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
this.state.carriageReturn = false;
|
|
31
|
-
}
|
|
32
|
-
const hasBareCR = line.endsWith("\r") && !line.endsWith("\r\n");
|
|
33
|
-
if (hasBareCR) {
|
|
34
|
-
this.state.carriageReturn = true;
|
|
35
|
-
}
|
|
36
86
|
const lineSpan = document.createElement("span");
|
|
37
87
|
lineSpan.classList.add("line");
|
|
38
|
-
this.targetElement.appendChild(lineSpan);
|
|
39
88
|
const addSpan = (content) => {
|
|
40
89
|
if (content === "")
|
|
41
90
|
return;
|
|
42
91
|
const span = document.createElement("span");
|
|
43
92
|
if (this.state.bold)
|
|
44
93
|
span.classList.add("log-bold");
|
|
94
|
+
if (this.state.dim)
|
|
95
|
+
span.classList.add("log-dim");
|
|
45
96
|
if (this.state.italic)
|
|
46
97
|
span.classList.add("log-italic");
|
|
47
98
|
if (this.state.underline)
|
|
@@ -50,10 +101,45 @@ export class ColoredConsole {
|
|
|
50
101
|
span.classList.add("log-strikethrough");
|
|
51
102
|
if (this.state.secret)
|
|
52
103
|
span.classList.add("log-secret");
|
|
53
|
-
if (this.state.
|
|
54
|
-
span.classList.add(
|
|
55
|
-
if (this.state.
|
|
56
|
-
span.classList.add(
|
|
104
|
+
if (this.state.blink)
|
|
105
|
+
span.classList.add("log-blink");
|
|
106
|
+
if (this.state.rapidBlink)
|
|
107
|
+
span.classList.add("log-rapid-blink");
|
|
108
|
+
// Resolve colors with reverse-video support
|
|
109
|
+
let fgRgb = this.state.fgRgb;
|
|
110
|
+
let bgRgb = this.state.bgRgb;
|
|
111
|
+
let fg = this.state.foregroundColor;
|
|
112
|
+
let bg = this.state.backgroundColor;
|
|
113
|
+
if (this.state.reverse) {
|
|
114
|
+
fgRgb = this.state.bgRgb;
|
|
115
|
+
bgRgb = this.state.fgRgb;
|
|
116
|
+
fg = this.state.backgroundColor;
|
|
117
|
+
bg = this.state.foregroundColor;
|
|
118
|
+
// When one side is unset, fill in the terminal defaults so the
|
|
119
|
+
// swap is always visible (fg default=#ddd, bg default=#1c1c1c).
|
|
120
|
+
if (!fgRgb && !fg && !bgRgb && !bg) {
|
|
121
|
+
span.classList.add("log-reverse");
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
if (!fgRgb && !fg)
|
|
125
|
+
fgRgb = "rgb(28,28,28)";
|
|
126
|
+
if (!bgRgb && !bg)
|
|
127
|
+
bgRgb = "rgb(221,221,221)";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Inline rgb() style takes priority over CSS class
|
|
131
|
+
if (fgRgb) {
|
|
132
|
+
span.style.color = fgRgb;
|
|
133
|
+
}
|
|
134
|
+
else if (fg !== null) {
|
|
135
|
+
span.classList.add(`log-fg-${fg}`);
|
|
136
|
+
}
|
|
137
|
+
if (bgRgb) {
|
|
138
|
+
span.style.backgroundColor = bgRgb;
|
|
139
|
+
}
|
|
140
|
+
else if (bg !== null) {
|
|
141
|
+
span.classList.add(`log-bg-${bg}`);
|
|
142
|
+
}
|
|
57
143
|
span.appendChild(document.createTextNode(content));
|
|
58
144
|
lineSpan.appendChild(span);
|
|
59
145
|
if (this.state.secret) {
|
|
@@ -70,23 +156,49 @@ export class ColoredConsole {
|
|
|
70
156
|
const j = match.index;
|
|
71
157
|
addSpan(line.substring(i, j));
|
|
72
158
|
i = j + match[0].length;
|
|
73
|
-
|
|
159
|
+
// Only process SGR sequences (final byte 'm'); skip cursor, erase, etc.
|
|
160
|
+
if (match[1] === undefined || match[2] !== "m")
|
|
74
161
|
continue;
|
|
75
|
-
|
|
76
|
-
|
|
162
|
+
const rawCodes = match[1] === "" ? [""] : match[1].split(";");
|
|
163
|
+
const codes = [];
|
|
164
|
+
let invalidSgr = false;
|
|
165
|
+
for (const rawCode of rawCodes) {
|
|
166
|
+
if (rawCode === "") {
|
|
167
|
+
codes.push(0);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (!/^\d+$/.test(rawCode)) {
|
|
171
|
+
invalidSgr = true;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
codes.push(Number(rawCode));
|
|
175
|
+
}
|
|
176
|
+
if (invalidSgr)
|
|
177
|
+
continue;
|
|
178
|
+
for (let ci = 0; ci < codes.length; ci++) {
|
|
179
|
+
const code = codes[ci];
|
|
180
|
+
switch (code) {
|
|
77
181
|
case 0:
|
|
78
|
-
// reset
|
|
79
182
|
this.state.bold = false;
|
|
183
|
+
this.state.dim = false;
|
|
80
184
|
this.state.italic = false;
|
|
81
185
|
this.state.underline = false;
|
|
82
186
|
this.state.strikethrough = false;
|
|
83
187
|
this.state.foregroundColor = null;
|
|
84
188
|
this.state.backgroundColor = null;
|
|
189
|
+
this.state.fgRgb = null;
|
|
190
|
+
this.state.bgRgb = null;
|
|
191
|
+
this.state.reverse = false;
|
|
85
192
|
this.state.secret = false;
|
|
193
|
+
this.state.blink = false;
|
|
194
|
+
this.state.rapidBlink = false;
|
|
86
195
|
break;
|
|
87
196
|
case 1:
|
|
88
197
|
this.state.bold = true;
|
|
89
198
|
break;
|
|
199
|
+
case 2:
|
|
200
|
+
this.state.dim = true;
|
|
201
|
+
break;
|
|
90
202
|
case 3:
|
|
91
203
|
this.state.italic = true;
|
|
92
204
|
break;
|
|
@@ -94,16 +206,25 @@ export class ColoredConsole {
|
|
|
94
206
|
this.state.underline = true;
|
|
95
207
|
break;
|
|
96
208
|
case 5:
|
|
97
|
-
this.state.
|
|
209
|
+
this.state.blink = true;
|
|
210
|
+
this.state.rapidBlink = false;
|
|
98
211
|
break;
|
|
99
212
|
case 6:
|
|
100
|
-
this.state.
|
|
213
|
+
this.state.rapidBlink = true;
|
|
214
|
+
this.state.blink = false;
|
|
215
|
+
break;
|
|
216
|
+
case 7:
|
|
217
|
+
this.state.reverse = true;
|
|
218
|
+
break;
|
|
219
|
+
case 8:
|
|
220
|
+
this.state.secret = true;
|
|
101
221
|
break;
|
|
102
222
|
case 9:
|
|
103
223
|
this.state.strikethrough = true;
|
|
104
224
|
break;
|
|
105
225
|
case 22:
|
|
106
226
|
this.state.bold = false;
|
|
227
|
+
this.state.dim = false;
|
|
107
228
|
break;
|
|
108
229
|
case 23:
|
|
109
230
|
this.state.italic = false;
|
|
@@ -111,74 +232,274 @@ export class ColoredConsole {
|
|
|
111
232
|
case 24:
|
|
112
233
|
this.state.underline = false;
|
|
113
234
|
break;
|
|
235
|
+
case 25:
|
|
236
|
+
this.state.blink = false;
|
|
237
|
+
this.state.rapidBlink = false;
|
|
238
|
+
break;
|
|
239
|
+
case 27:
|
|
240
|
+
this.state.reverse = false;
|
|
241
|
+
break;
|
|
242
|
+
case 28:
|
|
243
|
+
this.state.secret = false;
|
|
244
|
+
break;
|
|
114
245
|
case 29:
|
|
115
246
|
this.state.strikethrough = false;
|
|
116
247
|
break;
|
|
117
248
|
case 30:
|
|
118
249
|
this.state.foregroundColor = "black";
|
|
250
|
+
this.state.fgRgb = null;
|
|
119
251
|
break;
|
|
120
252
|
case 31:
|
|
121
253
|
this.state.foregroundColor = "red";
|
|
254
|
+
this.state.fgRgb = null;
|
|
122
255
|
break;
|
|
123
256
|
case 32:
|
|
124
257
|
this.state.foregroundColor = "green";
|
|
258
|
+
this.state.fgRgb = null;
|
|
125
259
|
break;
|
|
126
260
|
case 33:
|
|
127
261
|
this.state.foregroundColor = "yellow";
|
|
262
|
+
this.state.fgRgb = null;
|
|
128
263
|
break;
|
|
129
264
|
case 34:
|
|
130
265
|
this.state.foregroundColor = "blue";
|
|
266
|
+
this.state.fgRgb = null;
|
|
131
267
|
break;
|
|
132
268
|
case 35:
|
|
133
269
|
this.state.foregroundColor = "magenta";
|
|
270
|
+
this.state.fgRgb = null;
|
|
134
271
|
break;
|
|
135
272
|
case 36:
|
|
136
273
|
this.state.foregroundColor = "cyan";
|
|
274
|
+
this.state.fgRgb = null;
|
|
137
275
|
break;
|
|
138
276
|
case 37:
|
|
139
277
|
this.state.foregroundColor = "white";
|
|
278
|
+
this.state.fgRgb = null;
|
|
279
|
+
break;
|
|
280
|
+
case 38:
|
|
281
|
+
// Extended foreground: 38;5;n (256-color) or 38;2;r;g;b (true-color)
|
|
282
|
+
if (ci + 1 < codes.length) {
|
|
283
|
+
if (codes[ci + 1] === 5) {
|
|
284
|
+
if (ci + 2 < codes.length) {
|
|
285
|
+
const idx = codes[ci + 2];
|
|
286
|
+
if (idx >= 0 && idx <= 7 && ANSI_NAMED[idx]) {
|
|
287
|
+
this.state.foregroundColor = ANSI_NAMED[idx];
|
|
288
|
+
this.state.fgRgb = null;
|
|
289
|
+
}
|
|
290
|
+
else if (idx >= 0 && idx <= 255 && ANSI_256[idx]) {
|
|
291
|
+
this.state.foregroundColor = null;
|
|
292
|
+
this.state.fgRgb = ANSI_256[idx];
|
|
293
|
+
}
|
|
294
|
+
ci += 2;
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
ci += 1;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else if (codes[ci + 1] === 2) {
|
|
301
|
+
if (ci + 4 < codes.length) {
|
|
302
|
+
this.state.foregroundColor = null;
|
|
303
|
+
const r = Math.max(0, Math.min(255, codes[ci + 2]));
|
|
304
|
+
const g = Math.max(0, Math.min(255, codes[ci + 3]));
|
|
305
|
+
const b = Math.max(0, Math.min(255, codes[ci + 4]));
|
|
306
|
+
this.state.fgRgb = "rgb(" + r + "," + g + "," + b + ")";
|
|
307
|
+
ci += 4;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
ci = codes.length - 1;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
140
314
|
break;
|
|
141
315
|
case 39:
|
|
142
316
|
this.state.foregroundColor = null;
|
|
317
|
+
this.state.fgRgb = null;
|
|
318
|
+
break;
|
|
319
|
+
case 40:
|
|
320
|
+
this.state.backgroundColor = "black";
|
|
321
|
+
this.state.bgRgb = null;
|
|
143
322
|
break;
|
|
144
323
|
case 41:
|
|
145
324
|
this.state.backgroundColor = "red";
|
|
325
|
+
this.state.bgRgb = null;
|
|
146
326
|
break;
|
|
147
327
|
case 42:
|
|
148
328
|
this.state.backgroundColor = "green";
|
|
329
|
+
this.state.bgRgb = null;
|
|
149
330
|
break;
|
|
150
331
|
case 43:
|
|
151
332
|
this.state.backgroundColor = "yellow";
|
|
333
|
+
this.state.bgRgb = null;
|
|
152
334
|
break;
|
|
153
335
|
case 44:
|
|
154
336
|
this.state.backgroundColor = "blue";
|
|
337
|
+
this.state.bgRgb = null;
|
|
155
338
|
break;
|
|
156
339
|
case 45:
|
|
157
340
|
this.state.backgroundColor = "magenta";
|
|
341
|
+
this.state.bgRgb = null;
|
|
158
342
|
break;
|
|
159
343
|
case 46:
|
|
160
344
|
this.state.backgroundColor = "cyan";
|
|
345
|
+
this.state.bgRgb = null;
|
|
161
346
|
break;
|
|
162
347
|
case 47:
|
|
163
348
|
this.state.backgroundColor = "white";
|
|
349
|
+
this.state.bgRgb = null;
|
|
164
350
|
break;
|
|
165
|
-
case
|
|
166
|
-
|
|
351
|
+
case 48:
|
|
352
|
+
// Extended background: 48;5;n (256-color) or 48;2;r;g;b (true-color)
|
|
353
|
+
if (ci + 1 < codes.length) {
|
|
354
|
+
if (codes[ci + 1] === 5) {
|
|
355
|
+
if (ci + 2 < codes.length) {
|
|
356
|
+
const idx = codes[ci + 2];
|
|
357
|
+
if (idx >= 0 && idx <= 7 && ANSI_NAMED[idx]) {
|
|
358
|
+
this.state.backgroundColor = ANSI_NAMED[idx];
|
|
359
|
+
this.state.bgRgb = null;
|
|
360
|
+
}
|
|
361
|
+
else if (idx >= 0 && idx <= 255 && ANSI_256[idx]) {
|
|
362
|
+
this.state.backgroundColor = null;
|
|
363
|
+
this.state.bgRgb = ANSI_256[idx];
|
|
364
|
+
}
|
|
365
|
+
ci += 2;
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
ci += 1;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
else if (codes[ci + 1] === 2) {
|
|
372
|
+
if (ci + 4 < codes.length) {
|
|
373
|
+
this.state.backgroundColor = null;
|
|
374
|
+
const r = Math.max(0, Math.min(255, codes[ci + 2]));
|
|
375
|
+
const g = Math.max(0, Math.min(255, codes[ci + 3]));
|
|
376
|
+
const b = Math.max(0, Math.min(255, codes[ci + 4]));
|
|
377
|
+
this.state.bgRgb = "rgb(" + r + "," + g + "," + b + ")";
|
|
378
|
+
ci += 4;
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
ci = codes.length - 1;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
167
385
|
break;
|
|
168
386
|
case 49:
|
|
169
387
|
this.state.backgroundColor = null;
|
|
388
|
+
this.state.bgRgb = null;
|
|
389
|
+
break;
|
|
390
|
+
// Bright foreground colors
|
|
391
|
+
case 90:
|
|
392
|
+
this.state.foregroundColor = null;
|
|
393
|
+
this.state.fgRgb = ANSI_256[8];
|
|
394
|
+
break;
|
|
395
|
+
case 91:
|
|
396
|
+
this.state.foregroundColor = null;
|
|
397
|
+
this.state.fgRgb = ANSI_256[9];
|
|
398
|
+
break;
|
|
399
|
+
case 92:
|
|
400
|
+
this.state.foregroundColor = null;
|
|
401
|
+
this.state.fgRgb = ANSI_256[10];
|
|
402
|
+
break;
|
|
403
|
+
case 93:
|
|
404
|
+
this.state.foregroundColor = null;
|
|
405
|
+
this.state.fgRgb = ANSI_256[11];
|
|
406
|
+
break;
|
|
407
|
+
case 94:
|
|
408
|
+
this.state.foregroundColor = null;
|
|
409
|
+
this.state.fgRgb = ANSI_256[12];
|
|
410
|
+
break;
|
|
411
|
+
case 95:
|
|
412
|
+
this.state.foregroundColor = null;
|
|
413
|
+
this.state.fgRgb = ANSI_256[13];
|
|
414
|
+
break;
|
|
415
|
+
case 96:
|
|
416
|
+
this.state.foregroundColor = null;
|
|
417
|
+
this.state.fgRgb = ANSI_256[14];
|
|
418
|
+
break;
|
|
419
|
+
case 97:
|
|
420
|
+
this.state.foregroundColor = null;
|
|
421
|
+
this.state.fgRgb = ANSI_256[15];
|
|
422
|
+
break;
|
|
423
|
+
// Bright background colors
|
|
424
|
+
case 100:
|
|
425
|
+
this.state.backgroundColor = null;
|
|
426
|
+
this.state.bgRgb = ANSI_256[8];
|
|
427
|
+
break;
|
|
428
|
+
case 101:
|
|
429
|
+
this.state.backgroundColor = null;
|
|
430
|
+
this.state.bgRgb = ANSI_256[9];
|
|
431
|
+
break;
|
|
432
|
+
case 102:
|
|
433
|
+
this.state.backgroundColor = null;
|
|
434
|
+
this.state.bgRgb = ANSI_256[10];
|
|
435
|
+
break;
|
|
436
|
+
case 103:
|
|
437
|
+
this.state.backgroundColor = null;
|
|
438
|
+
this.state.bgRgb = ANSI_256[11];
|
|
439
|
+
break;
|
|
440
|
+
case 104:
|
|
441
|
+
this.state.backgroundColor = null;
|
|
442
|
+
this.state.bgRgb = ANSI_256[12];
|
|
443
|
+
break;
|
|
444
|
+
case 105:
|
|
445
|
+
this.state.backgroundColor = null;
|
|
446
|
+
this.state.bgRgb = ANSI_256[13];
|
|
447
|
+
break;
|
|
448
|
+
case 106:
|
|
449
|
+
this.state.backgroundColor = null;
|
|
450
|
+
this.state.bgRgb = ANSI_256[14];
|
|
451
|
+
break;
|
|
452
|
+
case 107:
|
|
453
|
+
this.state.backgroundColor = null;
|
|
454
|
+
this.state.bgRgb = ANSI_256[15];
|
|
170
455
|
break;
|
|
171
456
|
}
|
|
172
457
|
}
|
|
173
458
|
}
|
|
459
|
+
addSpan(line.substring(i));
|
|
460
|
+
return lineSpan;
|
|
461
|
+
}
|
|
462
|
+
processLines() {
|
|
174
463
|
const atBottom = this.targetElement.scrollTop >
|
|
175
464
|
this.targetElement.scrollHeight - this.targetElement.offsetHeight - 50;
|
|
176
|
-
|
|
177
|
-
|
|
465
|
+
const prevCarriageReturn = this.state.carriageReturn;
|
|
466
|
+
const fragment = document.createDocumentFragment();
|
|
467
|
+
if (this.state.lines.length === 0) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
for (const line of this.state.lines) {
|
|
471
|
+
if (line === "\r") {
|
|
472
|
+
this.state.carriageReturn = true;
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
if (this.state.carriageReturn && line !== "\n") {
|
|
476
|
+
if (fragment.childElementCount) {
|
|
477
|
+
fragment.removeChild(fragment.lastChild);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
const hadCarriageReturn = line.endsWith("\r");
|
|
481
|
+
fragment.appendChild(this.processLine(line.replace(/\r/g, "")));
|
|
482
|
+
this.state.carriageReturn = hadCarriageReturn;
|
|
483
|
+
}
|
|
484
|
+
if (prevCarriageReturn &&
|
|
485
|
+
fragment.childElementCount > 0 &&
|
|
486
|
+
this.targetElement.lastChild) {
|
|
487
|
+
this.targetElement.replaceChild(fragment, this.targetElement.lastChild);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
this.targetElement.appendChild(fragment);
|
|
491
|
+
}
|
|
492
|
+
this.state.lines = [];
|
|
178
493
|
if (atBottom) {
|
|
179
494
|
this.targetElement.scrollTop = this.targetElement.scrollHeight;
|
|
180
495
|
}
|
|
181
496
|
}
|
|
497
|
+
addLine(line) {
|
|
498
|
+
if (this.state.lines.length === 0) {
|
|
499
|
+
setTimeout(() => this.processLines(), 0);
|
|
500
|
+
}
|
|
501
|
+
this.state.lines.push(line);
|
|
502
|
+
}
|
|
182
503
|
}
|
|
183
504
|
export const coloredConsoleStyles = `
|
|
184
505
|
.log {
|
|
@@ -199,6 +520,9 @@ export const coloredConsoleStyles = `
|
|
|
199
520
|
.log-bold {
|
|
200
521
|
font-weight: bold;
|
|
201
522
|
}
|
|
523
|
+
.log-dim {
|
|
524
|
+
opacity: 0.5;
|
|
525
|
+
}
|
|
202
526
|
.log-italic {
|
|
203
527
|
font-style: italic;
|
|
204
528
|
}
|
|
@@ -211,6 +535,17 @@ export const coloredConsoleStyles = `
|
|
|
211
535
|
.log-underline.log-strikethrough {
|
|
212
536
|
text-decoration: underline line-through;
|
|
213
537
|
}
|
|
538
|
+
.log-blink {
|
|
539
|
+
animation: blink 1s step-end infinite;
|
|
540
|
+
}
|
|
541
|
+
.log-rapid-blink {
|
|
542
|
+
animation: blink 0.4s step-end infinite;
|
|
543
|
+
}
|
|
544
|
+
@keyframes blink {
|
|
545
|
+
50% {
|
|
546
|
+
opacity: 0;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
214
549
|
.log-secret {
|
|
215
550
|
-webkit-user-select: none;
|
|
216
551
|
-moz-user-select: none;
|
|
@@ -222,6 +557,10 @@ export const coloredConsoleStyles = `
|
|
|
222
557
|
width: 1px;
|
|
223
558
|
font-size: 1px;
|
|
224
559
|
}
|
|
560
|
+
.log-reverse {
|
|
561
|
+
background: #ddd;
|
|
562
|
+
color: #1c1c1c;
|
|
563
|
+
}
|
|
225
564
|
.log-fg-black {
|
|
226
565
|
color: rgb(128, 128, 128);
|
|
227
566
|
}
|
|
@@ -5,10 +5,24 @@ export class LineBreakTransformer {
|
|
|
5
5
|
transform(chunk, controller) {
|
|
6
6
|
// Append new chunks to existing chunks.
|
|
7
7
|
this.chunks += chunk;
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
// Split on \r\n, lone \r, or lone \n — capturing the separator so we can
|
|
9
|
+
// distinguish a lone \r (overwrite intent) from a normal newline.
|
|
10
|
+
const re = /\r\n|\r|\n/g;
|
|
11
|
+
let lastIndex = 0;
|
|
12
|
+
let match;
|
|
13
|
+
while ((match = re.exec(this.chunks)) !== null) {
|
|
14
|
+
// If this is a lone \r at the very end of the buffer, leave it so it can
|
|
15
|
+
// be combined with a possible following \n in the next chunk.
|
|
16
|
+
if (match[0] === "\r" && match.index === this.chunks.length - 1) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
const line = this.chunks.substring(lastIndex, match.index);
|
|
20
|
+
// Emit with \r suffix only for lone \r (overwrite), \n for everything else.
|
|
21
|
+
const suffix = match[0] === "\r" ? "\r" : "\n";
|
|
22
|
+
controller.enqueue(line + suffix);
|
|
23
|
+
lastIndex = re.lastIndex;
|
|
24
|
+
}
|
|
25
|
+
this.chunks = this.chunks.substring(lastIndex);
|
|
12
26
|
}
|
|
13
27
|
flush(controller) {
|
|
14
28
|
// When the stream is closed, flush any remaining chunks out.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Matches lines that already carry a wall-clock timestamp so we don't add a
|
|
2
|
+
// redundant one. Only real wall-clock formats are matched — tick-based
|
|
3
|
+
// formats like FreeRTOS "(12345)" or ESP-IDF "I (15) boot:" are NOT matched
|
|
4
|
+
// because they don't carry time-of-day information
|
|
5
|
+
// Covered formats:
|
|
6
|
+
// [HH:MM:SS] wall-clock bracket
|
|
7
|
+
// [HH:MM:SS.mmm] wall-clock bracket with millis
|
|
8
|
+
// HH:MM:SS.mmm plain wall-clock
|
|
9
|
+
const DEVICE_TIMESTAMP_RE = /^\s*(?:\[\d{2}:\d{2}:\d{2}(?:\.\d+)?\]|(?:\d{2}:){2}\d{2}\.\d)/;
|
|
10
|
+
export class TimestampTransformer {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.deviceHasTimestamps = false;
|
|
13
|
+
}
|
|
14
|
+
transform(chunk, controller) {
|
|
15
|
+
// Pass through pure newline / empty sentinel unchanged so that
|
|
16
|
+
// carriage-return overwrite logic in console-color.ts still works.
|
|
17
|
+
if (chunk === "" || chunk === "\n" || chunk === "\r") {
|
|
18
|
+
controller.enqueue(chunk);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!this.deviceHasTimestamps && DEVICE_TIMESTAMP_RE.test(chunk)) {
|
|
22
|
+
this.deviceHasTimestamps = true;
|
|
23
|
+
}
|
|
24
|
+
if (this.deviceHasTimestamps) {
|
|
25
|
+
controller.enqueue(chunk);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const date = new Date();
|
|
29
|
+
const h = date.getHours().toString().padStart(2, "0");
|
|
30
|
+
const m = date.getMinutes().toString().padStart(2, "0");
|
|
31
|
+
const s = date.getSeconds().toString().padStart(2, "0");
|
|
32
|
+
controller.enqueue(`[${h}:${m}:${s}] ${chunk}`);
|
|
33
|
+
}
|
|
34
|
+
reset() {
|
|
35
|
+
this.deviceHasTimestamps = false;
|
|
36
|
+
}
|
|
37
|
+
}
|
package/icons/icon-128.png
CHANGED
|
Binary file
|
package/icons/icon-144.png
CHANGED
|
Binary file
|
package/icons/icon-152.png
CHANGED
|
Binary file
|
package/icons/icon-192.png
CHANGED
|
Binary file
|
package/icons/icon-384.png
CHANGED
|
Binary file
|
package/icons/icon-512.png
CHANGED
|
Binary file
|
package/icons/icon-72.png
CHANGED
|
Binary file
|
package/icons/icon-96.png
CHANGED
|
Binary file
|