UNPKG

tasmota-esp-web-tools

Version:
60 lines (59 loc) 2.56 kB
// Matches lines that already carry a wall-clock timestamp so we don't add a // redundant one. Only real wall-clock formats are matched — tick-based // formats like FreeRTOS "(12345)" or ESP-IDF "I (15) boot:" are NOT matched // because they don't carry time-of-day information // Covered formats: // [HH:MM:SS] wall-clock bracket // [HH:MM:SS.mmm] wall-clock bracket with millis // HH:MM:SS.mmm plain wall-clock const DEVICE_TIMESTAMP_RE = /^\s*(?:\[\d{2}:\d{2}:\d{2}(?:\.\d+)?\]|(?:\d{2}:){2}\d{2}\.\d)/; // Matches leading ANSI SGR (color/style) codes at the start of a string // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequences const LEADING_ANSI_RE = /^(\x1b\[(?:\d+;)*\d*m)+/; export class TimestampTransformer { constructor() { this.deviceHasTimestamps = false; } transform(chunk, controller) { // Pass through pure newline / empty sentinel unchanged so that // carriage-return overwrite logic in console-color.ts still works. if (chunk === "" || chunk === "\n" || chunk === "\r") { controller.enqueue(chunk); return; } if (!this.deviceHasTimestamps && DEVICE_TIMESTAMP_RE.test(chunk)) { this.deviceHasTimestamps = true; } if (this.deviceHasTimestamps) { controller.enqueue(chunk); return; } // Extract leading ANSI codes to preserve them across line splits const ansiMatch = chunk.match(LEADING_ANSI_RE); const leadingAnsi = ansiMatch ? ansiMatch[0] : ""; const contentWithoutAnsi = leadingAnsi ? chunk.slice(leadingAnsi.length) : chunk; const date = new Date(); const h = date.getHours().toString().padStart(2, "0"); const m = date.getMinutes().toString().padStart(2, "0"); const s = date.getSeconds().toString().padStart(2, "0"); const timestamp = `[${h}:${m}:${s}]`; // For multi-line chunks, we need to preserve ANSI codes on each line // Split on newlines, but keep the newline characters const lines = contentWithoutAnsi.split(/(\r?\n)/); let result = ""; for (const part of lines) { if (part === "\n" || part === "\r\n") { result += part; } else if (part !== "") { result += leadingAnsi + timestamp + " " + part; } } controller.enqueue(result); } reset() { this.deviceHasTimestamps = false; } }