tasmota-esp-web-tools 12.0.0 → 12.1.1

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.
@@ -1159,9 +1159,6 @@ export class EwtInstallDialog extends LitElement {
1159
1159
  name="password"
1160
1160
  type="password"
1161
1161
  ></ew-filled-text-field>
1162
- <ew-text-button slot="actions" @click=${this._doProvision}
1163
- >Connect</ew-text-button
1164
- >
1165
1162
  <ew-text-button
1166
1163
  slot="actions"
1167
1164
  @click=${async () => {
@@ -1185,6 +1182,9 @@ export class EwtInstallDialog extends LitElement {
1185
1182
  ? "Skip"
1186
1183
  : "Back"}</ew-text-button
1187
1184
  >
1185
+ <ew-text-button slot="actions" @click=${this._doProvision}
1186
+ >Connect</ew-text-button
1187
+ >
1188
1188
  `;
1189
1189
  }
1190
1190
  return [heading, content, hideActions];
@@ -1203,17 +1203,17 @@ export class EwtInstallDialog extends LitElement {
1203
1203
  <ew-text-button
1204
1204
  slot="actions"
1205
1205
  @click=${() => {
1206
- const checkbox = this.shadowRoot.querySelector("ew-checkbox");
1207
- this._startInstall(checkbox.checked);
1206
+ this._state = "DASHBOARD";
1208
1207
  }}
1209
- >Next</ew-text-button
1208
+ >Back</ew-text-button
1210
1209
  >
1211
1210
  <ew-text-button
1212
1211
  slot="actions"
1213
1212
  @click=${() => {
1214
- this._state = "DASHBOARD";
1213
+ const checkbox = this.shadowRoot.querySelector("ew-checkbox");
1214
+ this._startInstall(checkbox.checked);
1215
1215
  }}
1216
- >Back</ew-text-button
1216
+ >Next</ew-text-button
1217
1217
  >
1218
1218
  `;
1219
1219
  return [heading, content];
@@ -1229,6 +1229,13 @@ export class EwtInstallDialog extends LitElement {
1229
1229
  content = html `
1230
1230
  Do you want to reset your device and erase all user data from your
1231
1231
  device?
1232
+ <ew-text-button
1233
+ slot="actions"
1234
+ @click=${() => {
1235
+ this._state = "DASHBOARD";
1236
+ }}
1237
+ >Back</ew-text-button
1238
+ >
1232
1239
  <ew-text-button
1233
1240
  class="danger"
1234
1241
  slot="actions"
@@ -1250,9 +1257,6 @@ export class EwtInstallDialog extends LitElement {
1250
1257
  ${this._installErase
1251
1258
  ? html `<br /><br />All data on the device will be erased.`
1252
1259
  : ""}
1253
- <ew-text-button slot="actions" @click=${this._confirmInstall}
1254
- >Install</ew-text-button
1255
- >
1256
1260
  <ew-text-button
1257
1261
  slot="actions"
1258
1262
  @click=${() => {
@@ -1260,6 +1264,9 @@ export class EwtInstallDialog extends LitElement {
1260
1264
  }}
1261
1265
  >Back</ew-text-button
1262
1266
  >
1267
+ <ew-text-button slot="actions" @click=${this._confirmInstall}
1268
+ >Install</ew-text-button
1269
+ >
1263
1270
  `;
1264
1271
  }
1265
1272
  else if (!this._installState ||
@@ -5,6 +5,10 @@ interface ConsoleState {
5
5
  strikethrough: boolean;
6
6
  foregroundColor: string | null;
7
7
  backgroundColor: string | null;
8
+ fgRgb: string | null;
9
+ bgRgb: string | null;
10
+ dim: boolean;
11
+ reverse: boolean;
8
12
  carriageReturn: boolean;
9
13
  lines: string[];
10
14
  secret: boolean;
@@ -31,5 +35,5 @@ export declare class ColoredConsole {
31
35
  processLines(): void;
32
36
  addLine(line: string): void;
33
37
  }
34
- export declare const coloredConsoleStyles = "\n .log {\n flex: 1;\n background-color: #1c1c1c;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, Courier,\n monospace;\n font-size: 12px;\n padding: 16px;\n overflow: auto;\n line-height: 1.45;\n border-radius: 3px;\n white-space: pre-wrap;\n overflow-wrap: break-word;\n color: #ddd;\n }\n\n .log-bold { font-weight: bold; }\n .log-italic { font-style: italic; }\n .log-underline { text-decoration: underline; }\n .log-strikethrough { text-decoration: line-through; }\n .log-underline.log-strikethrough { text-decoration: underline line-through; }\n .log-blink { animation: blink 1s step-end infinite; }\n .log-rapid-blink { animation: blink 0.4s step-end infinite; }\n @keyframes blink { 50% { opacity: 0; } }\n .log-secret {\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n }\n .log-secret-redacted { opacity: 0; width: 1px; font-size: 1px; }\n .log-fg-black { color: rgb(128, 128, 128); }\n .log-fg-red { color: rgb(255, 0, 0); }\n .log-fg-green { color: rgb(0, 255, 0); }\n .log-fg-yellow { color: rgb(255, 255, 0); }\n .log-fg-blue { color: rgb(0, 0, 255); }\n .log-fg-magenta { color: rgb(255, 0, 255); }\n .log-fg-cyan { color: rgb(0, 255, 255); }\n .log-fg-white { color: rgb(187, 187, 187); }\n .log-bg-black { background-color: rgb(0, 0, 0); }\n .log-bg-red { background-color: rgb(255, 0, 0); }\n .log-bg-green { background-color: rgb(0, 255, 0); }\n .log-bg-yellow { background-color: rgb(255, 255, 0); }\n .log-bg-blue { background-color: rgb(0, 0, 255); }\n .log-bg-magenta { background-color: rgb(255, 0, 255); }\n .log-bg-cyan { background-color: rgb(0, 255, 255); }\n .log-bg-white { background-color: rgb(255, 255, 255); }\n";
38
+ export declare const coloredConsoleStyles = "\n .log {\n flex: 1;\n background-color: #1c1c1c;\n font-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, Courier,\n monospace;\n font-size: 12px;\n padding: 16px;\n overflow: auto;\n line-height: 1.45;\n border-radius: 3px;\n white-space: pre-wrap;\n overflow-wrap: break-word;\n color: #ddd;\n }\n\n .log-bold { font-weight: bold; }\n .log-dim { opacity: 0.5; }\n .log-italic { font-style: italic; }\n .log-underline { text-decoration: underline; }\n .log-strikethrough { text-decoration: line-through; }\n .log-underline.log-strikethrough { text-decoration: underline line-through; }\n .log-blink { animation: blink 1s step-end infinite; }\n .log-rapid-blink { animation: blink 0.4s step-end infinite; }\n @keyframes blink { 50% { opacity: 0; } }\n .log-secret {\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n }\n .log-secret-redacted { opacity: 0; width: 1px; font-size: 1px; }\n .log-reverse { background: #ddd; color: #1c1c1c; }\n .log-fg-black { color: rgb(128, 128, 128); }\n .log-fg-red { color: rgb(255, 0, 0); }\n .log-fg-green { color: rgb(0, 255, 0); }\n .log-fg-yellow { color: rgb(255, 255, 0); }\n .log-fg-blue { color: rgb(0, 0, 255); }\n .log-fg-magenta { color: rgb(255, 0, 255); }\n .log-fg-cyan { color: rgb(0, 255, 255); }\n .log-fg-white { color: rgb(187, 187, 187); }\n .log-bg-black { background-color: rgb(0, 0, 0); }\n .log-bg-red { background-color: rgb(255, 0, 0); }\n .log-bg-green { background-color: rgb(0, 255, 0); }\n .log-bg-yellow { background-color: rgb(255, 255, 0); }\n .log-bg-blue { background-color: rgb(0, 0, 255); }\n .log-bg-magenta { background-color: rgb(255, 0, 255); }\n .log-bg-cyan { background-color: rgb(0, 255, 255); }\n .log-bg-white { background-color: rgb(255, 255, 255); }\n";
35
39
  export {};
@@ -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
  const MAX_LINES = 2000;
2
55
  export class ColoredConsole {
3
56
  constructor(targetElement) {
@@ -9,6 +62,10 @@ export class ColoredConsole {
9
62
  strikethrough: false,
10
63
  foregroundColor: null,
11
64
  backgroundColor: null,
65
+ fgRgb: null,
66
+ bgRgb: null,
67
+ dim: false,
68
+ reverse: false,
12
69
  carriageReturn: false,
13
70
  lines: [],
14
71
  secret: false,
@@ -114,7 +171,7 @@ export class ColoredConsole {
114
171
  }
115
172
  }
116
173
  processLine(line) {
117
- const re = /(?:\x1B|\\x1B)(?:\[(.*?)[@-~]|\].*?(?:\x07|\x1B\\))/g;
174
+ const re = /(?:\x1B|\\x1B)(?:\[(.*?)([@-~])|\].*?(?:\x07|\x1B\\))/g;
118
175
  let i = 0;
119
176
  const lineSpan = document.createElement("span");
120
177
  lineSpan.classList.add("line");
@@ -131,6 +188,8 @@ export class ColoredConsole {
131
188
  const span = document.createElement("span");
132
189
  if (this.state.bold)
133
190
  span.classList.add("log-bold");
191
+ if (this.state.dim)
192
+ span.classList.add("log-dim");
134
193
  if (this.state.italic)
135
194
  span.classList.add("log-italic");
136
195
  if (this.state.underline)
@@ -141,10 +200,39 @@ export class ColoredConsole {
141
200
  span.classList.add("log-blink");
142
201
  if (this.state.rapidBlink)
143
202
  span.classList.add("log-rapid-blink");
144
- if (this.state.foregroundColor !== null)
145
- span.classList.add(`log-fg-${this.state.foregroundColor}`);
146
- if (this.state.backgroundColor !== null)
147
- span.classList.add(`log-bg-${this.state.backgroundColor}`);
203
+ // Resolve colors with reverse-video support
204
+ let fgRgb = this.state.fgRgb;
205
+ let bgRgb = this.state.bgRgb;
206
+ let fg = this.state.foregroundColor;
207
+ let bg = this.state.backgroundColor;
208
+ if (this.state.reverse) {
209
+ fgRgb = this.state.bgRgb;
210
+ bgRgb = this.state.fgRgb;
211
+ fg = this.state.backgroundColor;
212
+ bg = this.state.foregroundColor;
213
+ if (!fgRgb && !fg && !bgRgb && !bg) {
214
+ span.classList.add("log-reverse");
215
+ }
216
+ else {
217
+ if (!fgRgb && !fg)
218
+ fgRgb = "rgb(28,28,28)";
219
+ if (!bgRgb && !bg)
220
+ bgRgb = "rgb(221,221,221)";
221
+ }
222
+ }
223
+ // Inline rgb() style takes priority over CSS class
224
+ if (fgRgb) {
225
+ span.style.color = fgRgb;
226
+ }
227
+ else if (fg !== null) {
228
+ span.classList.add(`log-fg-${fg}`);
229
+ }
230
+ if (bgRgb) {
231
+ span.style.backgroundColor = bgRgb;
232
+ }
233
+ else if (bg !== null) {
234
+ span.classList.add(`log-bg-${bg}`);
235
+ }
148
236
  span.appendChild(document.createTextNode(content));
149
237
  lineSpan.appendChild(span);
150
238
  };
@@ -155,17 +243,39 @@ export class ColoredConsole {
155
243
  const j = match.index;
156
244
  addSpan(line.substring(i, j));
157
245
  i = j + match[0].length;
158
- if (match[1] === undefined)
246
+ // Only process SGR sequences (final byte 'm'); skip cursor, erase, etc.
247
+ if (match[1] === undefined || match[2] !== "m")
159
248
  continue;
160
- for (const colorCode of match[1].split(";")) {
161
- switch (parseInt(colorCode)) {
249
+ const rawCodes = match[1] === "" ? [""] : match[1].split(";");
250
+ const codes = [];
251
+ let invalidSgr = false;
252
+ for (const rawCode of rawCodes) {
253
+ if (rawCode === "") {
254
+ codes.push(0);
255
+ continue;
256
+ }
257
+ if (!/^\d+$/.test(rawCode)) {
258
+ invalidSgr = true;
259
+ break;
260
+ }
261
+ codes.push(Number(rawCode));
262
+ }
263
+ if (invalidSgr)
264
+ continue;
265
+ for (let ci = 0; ci < codes.length; ci++) {
266
+ const code = codes[ci];
267
+ switch (code) {
162
268
  case 0:
163
269
  this.state.bold = false;
270
+ this.state.dim = false;
164
271
  this.state.italic = false;
165
272
  this.state.underline = false;
166
273
  this.state.strikethrough = false;
167
274
  this.state.foregroundColor = null;
168
275
  this.state.backgroundColor = null;
276
+ this.state.fgRgb = null;
277
+ this.state.bgRgb = null;
278
+ this.state.reverse = false;
169
279
  this.state.secret = false;
170
280
  this.state.blink = false;
171
281
  this.state.rapidBlink = false;
@@ -173,6 +283,9 @@ export class ColoredConsole {
173
283
  case 1:
174
284
  this.state.bold = true;
175
285
  break;
286
+ case 2:
287
+ this.state.dim = true;
288
+ break;
176
289
  case 3:
177
290
  this.state.italic = true;
178
291
  break;
@@ -181,9 +294,14 @@ export class ColoredConsole {
181
294
  break;
182
295
  case 5:
183
296
  this.state.blink = true;
297
+ this.state.rapidBlink = false;
184
298
  break;
185
299
  case 6:
186
300
  this.state.rapidBlink = true;
301
+ this.state.blink = false;
302
+ break;
303
+ case 7:
304
+ this.state.reverse = true;
187
305
  break;
188
306
  case 8:
189
307
  this.state.secret = true;
@@ -193,6 +311,7 @@ export class ColoredConsole {
193
311
  break;
194
312
  case 22:
195
313
  this.state.bold = false;
314
+ this.state.dim = false;
196
315
  break;
197
316
  case 23:
198
317
  this.state.italic = false;
@@ -204,6 +323,9 @@ export class ColoredConsole {
204
323
  this.state.blink = false;
205
324
  this.state.rapidBlink = false;
206
325
  break;
326
+ case 27:
327
+ this.state.reverse = false;
328
+ break;
207
329
  case 28:
208
330
  this.state.secret = false;
209
331
  break;
@@ -212,57 +334,211 @@ export class ColoredConsole {
212
334
  break;
213
335
  case 30:
214
336
  this.state.foregroundColor = "black";
337
+ this.state.fgRgb = null;
215
338
  break;
216
339
  case 31:
217
340
  this.state.foregroundColor = "red";
341
+ this.state.fgRgb = null;
218
342
  break;
219
343
  case 32:
220
344
  this.state.foregroundColor = "green";
345
+ this.state.fgRgb = null;
221
346
  break;
222
347
  case 33:
223
348
  this.state.foregroundColor = "yellow";
349
+ this.state.fgRgb = null;
224
350
  break;
225
351
  case 34:
226
352
  this.state.foregroundColor = "blue";
353
+ this.state.fgRgb = null;
227
354
  break;
228
355
  case 35:
229
356
  this.state.foregroundColor = "magenta";
357
+ this.state.fgRgb = null;
230
358
  break;
231
359
  case 36:
232
360
  this.state.foregroundColor = "cyan";
361
+ this.state.fgRgb = null;
233
362
  break;
234
363
  case 37:
235
364
  this.state.foregroundColor = "white";
365
+ this.state.fgRgb = null;
366
+ break;
367
+ case 38:
368
+ // Extended foreground: 38;5;n (256-color) or 38;2;r;g;b (true-color)
369
+ if (ci + 1 < codes.length) {
370
+ if (codes[ci + 1] === 5) {
371
+ if (ci + 2 < codes.length) {
372
+ const idx = codes[ci + 2];
373
+ if (idx >= 0 && idx <= 7 && ANSI_NAMED[idx]) {
374
+ this.state.foregroundColor = ANSI_NAMED[idx];
375
+ this.state.fgRgb = null;
376
+ }
377
+ else if (idx >= 0 && idx <= 255 && ANSI_256[idx]) {
378
+ this.state.foregroundColor = null;
379
+ this.state.fgRgb = ANSI_256[idx];
380
+ }
381
+ ci += 2;
382
+ }
383
+ else {
384
+ ci += 1;
385
+ }
386
+ }
387
+ else if (codes[ci + 1] === 2) {
388
+ if (ci + 4 < codes.length) {
389
+ this.state.foregroundColor = null;
390
+ const r = Math.max(0, Math.min(255, codes[ci + 2]));
391
+ const g = Math.max(0, Math.min(255, codes[ci + 3]));
392
+ const b = Math.max(0, Math.min(255, codes[ci + 4]));
393
+ this.state.fgRgb = "rgb(" + r + "," + g + "," + b + ")";
394
+ ci += 4;
395
+ }
396
+ else {
397
+ ci = codes.length - 1;
398
+ }
399
+ }
400
+ }
236
401
  break;
237
402
  case 39:
238
403
  this.state.foregroundColor = null;
404
+ this.state.fgRgb = null;
239
405
  break;
240
406
  case 40:
241
407
  this.state.backgroundColor = "black";
408
+ this.state.bgRgb = null;
242
409
  break;
243
410
  case 41:
244
411
  this.state.backgroundColor = "red";
412
+ this.state.bgRgb = null;
245
413
  break;
246
414
  case 42:
247
415
  this.state.backgroundColor = "green";
416
+ this.state.bgRgb = null;
248
417
  break;
249
418
  case 43:
250
419
  this.state.backgroundColor = "yellow";
420
+ this.state.bgRgb = null;
251
421
  break;
252
422
  case 44:
253
423
  this.state.backgroundColor = "blue";
424
+ this.state.bgRgb = null;
254
425
  break;
255
426
  case 45:
256
427
  this.state.backgroundColor = "magenta";
428
+ this.state.bgRgb = null;
257
429
  break;
258
430
  case 46:
259
431
  this.state.backgroundColor = "cyan";
432
+ this.state.bgRgb = null;
260
433
  break;
261
434
  case 47:
262
435
  this.state.backgroundColor = "white";
436
+ this.state.bgRgb = null;
437
+ break;
438
+ case 48:
439
+ // Extended background: 48;5;n (256-color) or 48;2;r;g;b (true-color)
440
+ if (ci + 1 < codes.length) {
441
+ if (codes[ci + 1] === 5) {
442
+ if (ci + 2 < codes.length) {
443
+ const idx = codes[ci + 2];
444
+ if (idx >= 0 && idx <= 7 && ANSI_NAMED[idx]) {
445
+ this.state.backgroundColor = ANSI_NAMED[idx];
446
+ this.state.bgRgb = null;
447
+ }
448
+ else if (idx >= 0 && idx <= 255 && ANSI_256[idx]) {
449
+ this.state.backgroundColor = null;
450
+ this.state.bgRgb = ANSI_256[idx];
451
+ }
452
+ ci += 2;
453
+ }
454
+ else {
455
+ ci += 1;
456
+ }
457
+ }
458
+ else if (codes[ci + 1] === 2) {
459
+ if (ci + 4 < codes.length) {
460
+ this.state.backgroundColor = null;
461
+ const r = Math.max(0, Math.min(255, codes[ci + 2]));
462
+ const g = Math.max(0, Math.min(255, codes[ci + 3]));
463
+ const b = Math.max(0, Math.min(255, codes[ci + 4]));
464
+ this.state.bgRgb = "rgb(" + r + "," + g + "," + b + ")";
465
+ ci += 4;
466
+ }
467
+ else {
468
+ ci = codes.length - 1;
469
+ }
470
+ }
471
+ }
263
472
  break;
264
473
  case 49:
265
474
  this.state.backgroundColor = null;
475
+ this.state.bgRgb = null;
476
+ break;
477
+ // Bright foreground colors
478
+ case 90:
479
+ this.state.foregroundColor = null;
480
+ this.state.fgRgb = ANSI_256[8];
481
+ break;
482
+ case 91:
483
+ this.state.foregroundColor = null;
484
+ this.state.fgRgb = ANSI_256[9];
485
+ break;
486
+ case 92:
487
+ this.state.foregroundColor = null;
488
+ this.state.fgRgb = ANSI_256[10];
489
+ break;
490
+ case 93:
491
+ this.state.foregroundColor = null;
492
+ this.state.fgRgb = ANSI_256[11];
493
+ break;
494
+ case 94:
495
+ this.state.foregroundColor = null;
496
+ this.state.fgRgb = ANSI_256[12];
497
+ break;
498
+ case 95:
499
+ this.state.foregroundColor = null;
500
+ this.state.fgRgb = ANSI_256[13];
501
+ break;
502
+ case 96:
503
+ this.state.foregroundColor = null;
504
+ this.state.fgRgb = ANSI_256[14];
505
+ break;
506
+ case 97:
507
+ this.state.foregroundColor = null;
508
+ this.state.fgRgb = ANSI_256[15];
509
+ break;
510
+ // Bright background colors
511
+ case 100:
512
+ this.state.backgroundColor = null;
513
+ this.state.bgRgb = ANSI_256[8];
514
+ break;
515
+ case 101:
516
+ this.state.backgroundColor = null;
517
+ this.state.bgRgb = ANSI_256[9];
518
+ break;
519
+ case 102:
520
+ this.state.backgroundColor = null;
521
+ this.state.bgRgb = ANSI_256[10];
522
+ break;
523
+ case 103:
524
+ this.state.backgroundColor = null;
525
+ this.state.bgRgb = ANSI_256[11];
526
+ break;
527
+ case 104:
528
+ this.state.backgroundColor = null;
529
+ this.state.bgRgb = ANSI_256[12];
530
+ break;
531
+ case 105:
532
+ this.state.backgroundColor = null;
533
+ this.state.bgRgb = ANSI_256[13];
534
+ break;
535
+ case 106:
536
+ this.state.backgroundColor = null;
537
+ this.state.bgRgb = ANSI_256[14];
538
+ break;
539
+ case 107:
540
+ this.state.backgroundColor = null;
541
+ this.state.bgRgb = ANSI_256[15];
266
542
  break;
267
543
  }
268
544
  }
@@ -360,6 +636,7 @@ export const coloredConsoleStyles = `
360
636
  }
361
637
 
362
638
  .log-bold { font-weight: bold; }
639
+ .log-dim { opacity: 0.5; }
363
640
  .log-italic { font-style: italic; }
364
641
  .log-underline { text-decoration: underline; }
365
642
  .log-strikethrough { text-decoration: line-through; }
@@ -374,6 +651,7 @@ export const coloredConsoleStyles = `
374
651
  user-select: none;
375
652
  }
376
653
  .log-secret-redacted { opacity: 0; width: 1px; font-size: 1px; }
654
+ .log-reverse { background: #ddd; color: #1c1c1c; }
377
655
  .log-fg-black { color: rgb(128, 128, 128); }
378
656
  .log-fg-red { color: rgb(255, 0, 0); }
379
657
  .log-fg-green { color: rgb(0, 255, 0); }
@@ -1,3 +1,5 @@
1
1
  export declare class TimestampTransformer implements Transformer<string, string> {
2
+ private deviceHasTimestamps;
2
3
  transform(chunk: string, controller: TransformStreamDefaultController<string>): void;
4
+ reset(): void;
3
5
  }
@@ -1,25 +1,27 @@
1
- // Matches lines that already carry a wall-clock or tick timestamp so we don't
2
- // add a redundant one. Does NOT match bare log-level prefixes like ESPHome's
3
- // [I][tag:line]: those have no time information.
4
- //
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
5
  // Covered formats:
6
- // (123456) FreeRTOS ms-tick e.g. "(12345) "
7
6
  // [HH:MM:SS] wall-clock bracket
8
7
  // [HH:MM:SS.mmm] wall-clock bracket with millis
9
- // I (1234) tag: ESP-IDF log level + tick e.g. "I (1234) wifi: ..."
10
8
  // HH:MM:SS.mmm plain wall-clock
11
- const DEVICE_TIMESTAMP_RE = /^\s*(?:\(\d+\)\s|\[\d{2}:\d{2}:\d{2}(?:\.\d+)?\]|[DIWEACV] \(\d+\) \w|(?:\d{2}:){2}\d{2}\.\d)/;
9
+ const DEVICE_TIMESTAMP_RE = /^\s*(?:\[\d{2}:\d{2}:\d{2}(?:\.\d+)?\]|(?:\d{2}:){2}\d{2}\.\d)/;
12
10
  export class TimestampTransformer {
11
+ constructor() {
12
+ this.deviceHasTimestamps = false;
13
+ }
13
14
  transform(chunk, controller) {
14
- // Pass through pure newline (blank-line sentinel) and empty chunks unchanged
15
- // so that carriage-return overwrite logic in console-color.ts can still
16
- // detect them via line !== "\n".
15
+ // Pass through pure newline / empty sentinel unchanged so that
16
+ // carriage-return overwrite logic in console-color.ts still works.
17
17
  if (chunk === "" || chunk === "\n" || chunk === "\r") {
18
18
  controller.enqueue(chunk);
19
19
  return;
20
20
  }
21
- // Skip prefixing if the line already starts with a timestamp
22
- if (DEVICE_TIMESTAMP_RE.test(chunk)) {
21
+ if (!this.deviceHasTimestamps && DEVICE_TIMESTAMP_RE.test(chunk)) {
22
+ this.deviceHasTimestamps = true;
23
+ }
24
+ if (this.deviceHasTimestamps) {
23
25
  controller.enqueue(chunk);
24
26
  return;
25
27
  }
@@ -27,6 +29,9 @@ export class TimestampTransformer {
27
29
  const h = date.getHours().toString().padStart(2, "0");
28
30
  const m = date.getMinutes().toString().padStart(2, "0");
29
31
  const s = date.getSeconds().toString().padStart(2, "0");
30
- controller.enqueue(`[${h}:${m}:${s}]${chunk}`);
32
+ controller.enqueue(`[${h}:${m}:${s}] ${chunk}`);
33
+ }
34
+ reset() {
35
+ this.deviceHasTimestamps = false;
31
36
  }
32
37
  }