@f5xc-salesdemos/pi-tui 18.40.2 → 18.41.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.
Files changed (2) hide show
  1. package/package.json +3 -3
  2. package/src/tui.ts +10 -31
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5xc-salesdemos/pi-tui",
4
- "version": "18.40.2",
4
+ "version": "18.41.1",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://github.com/f5xc-salesdemos/xcsh",
7
7
  "author": "Can Boluk",
@@ -37,8 +37,8 @@
37
37
  "fmt": "biome format --write ."
38
38
  },
39
39
  "dependencies": {
40
- "@f5xc-salesdemos/pi-natives": "18.40.2",
41
- "@f5xc-salesdemos/pi-utils": "18.40.2",
40
+ "@f5xc-salesdemos/pi-natives": "18.41.1",
41
+ "@f5xc-salesdemos/pi-utils": "18.41.1",
42
42
  "marked": "^17.0"
43
43
  },
44
44
  "devDependencies": {
package/src/tui.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import * as fs from "node:fs";
5
5
  import * as path from "node:path";
6
- import { $flag, getCrashLogPath, getDebugLogPath } from "@f5xc-salesdemos/pi-utils";
6
+ import { $flag, getDebugLogPath } from "@f5xc-salesdemos/pi-utils";
7
7
  import { isKeyRelease, matchesKey } from "./keys";
8
8
  import type { Terminal } from "./terminal";
9
9
  import { ImageProtocol, setCellDimensions, setTerminalImageProtocol, TERMINAL } from "./terminal-capabilities";
@@ -996,6 +996,14 @@ export class TUI extends Container {
996
996
  // Render all components to get new lines
997
997
  let newLines = this.render(width);
998
998
 
999
+ // Clamp any oversized lines before dirty-checking so the truncated form
1000
+ // matches what we store in #previousLines, preventing perpetual repaints.
1001
+ for (let i = 0; i < newLines.length; i++) {
1002
+ if (!TERMINAL.isImageLine(newLines[i]) && visibleWidth(newLines[i]) > width) {
1003
+ newLines[i] = sliceByColumn(newLines[i], 0, width, true);
1004
+ }
1005
+ }
1006
+
999
1007
  // Composite overlays into the rendered lines (before differential compare)
1000
1008
  if (this.overlayStack.length > 0) {
1001
1009
  newLines = this.#compositeOverlays(newLines, width, height);
@@ -1195,36 +1203,7 @@ export class TUI extends Container {
1195
1203
  if (i > firstChanged) buffer += "\r\n";
1196
1204
  buffer += "\x1b[2K"; // Clear current line
1197
1205
  const line = newLines[i];
1198
- const isImage = TERMINAL.isImageLine(line);
1199
- if (!isImage && visibleWidth(line) > width) {
1200
- // Log all lines to crash file for debugging
1201
- const crashLogPath = getCrashLogPath();
1202
- const crashData = [
1203
- `Crash at ${new Date().toISOString()}`,
1204
- `Terminal width: ${width}`,
1205
- `Line ${i} visible width: ${visibleWidth(line)}`,
1206
- "",
1207
- "=== All rendered lines ===",
1208
- ...newLines.map((l, idx) => `[${idx}] (w=${visibleWidth(l)}) ${l}`),
1209
- "",
1210
- ].join("\n");
1211
- fs.mkdirSync(path.dirname(crashLogPath), { recursive: true });
1212
- fs.writeFileSync(crashLogPath, crashData);
1213
-
1214
- // Clean up terminal state before throwing
1215
- this.stop();
1216
-
1217
- const errorMsg = [
1218
- `Rendered line ${i} exceeds terminal width (${visibleWidth(line)} > ${width}).`,
1219
- "",
1220
- "This is likely caused by a custom TUI component not truncating its output.",
1221
- "Use visibleWidth() to measure and truncateToWidth() to truncate lines.",
1222
- "",
1223
- `Debug log written to: ${crashLogPath}`,
1224
- ].join("\n");
1225
- throw new Error(errorMsg);
1226
- }
1227
- buffer += isImage ? line : line + SEGMENT_RESET;
1206
+ buffer += TERMINAL.isImageLine(line) ? line : line + SEGMENT_RESET;
1228
1207
  }
1229
1208
 
1230
1209
  // Track where cursor ended up after rendering