@oh-my-pi/pi-tui 9.1.0 → 9.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-tui",
3
- "version": "9.1.0",
3
+ "version": "9.1.1",
4
4
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -47,7 +47,7 @@
47
47
  "bun": ">=1.3.7"
48
48
  },
49
49
  "dependencies": {
50
- "@oh-my-pi/pi-natives": "9.1.0",
50
+ "@oh-my-pi/pi-natives": "9.1.1",
51
51
  "@types/mime-types": "^3.0.1",
52
52
  "chalk": "^5.6.2",
53
53
  "marked": "^17.0.1",
@@ -1,6 +1,13 @@
1
1
  import type { Component } from "../tui";
2
2
  import { applyBackgroundToLine, visibleWidth } from "../utils";
3
3
 
4
+ type Cache = {
5
+ key: string[];
6
+ width: number;
7
+ bgSample: string | undefined;
8
+ result: string[];
9
+ };
10
+
4
11
  /**
5
12
  * Box component - a container that applies padding and background to all children
6
13
  */
@@ -11,10 +18,7 @@ export class Box implements Component {
11
18
  private bgFn?: (text: string) => string;
12
19
 
13
20
  // Cache for rendered output
14
- private cachedWidth?: number;
15
- private cachedChildLines?: string;
16
- private cachedBgSample?: string;
17
- private cachedLines?: string[];
21
+ private cached?: Cache;
18
22
 
19
23
  constructor(paddingX = 1, paddingY = 1, bgFn?: (text: string) => string) {
20
24
  this.paddingX = paddingX;
@@ -46,10 +50,18 @@ export class Box implements Component {
46
50
  }
47
51
 
48
52
  private invalidateCache(): void {
49
- this.cachedWidth = undefined;
50
- this.cachedChildLines = undefined;
51
- this.cachedBgSample = undefined;
52
- this.cachedLines = undefined;
53
+ this.cached = undefined;
54
+ }
55
+
56
+ private matchCache(width: number, childLines: string[], bgSample: string | undefined): boolean {
57
+ const cache = this.cached;
58
+ return (
59
+ !!cache &&
60
+ cache.width === width &&
61
+ cache.bgSample === bgSample &&
62
+ cache.key.length === childLines.length &&
63
+ cache.key.every((key, index) => key === childLines[index])
64
+ );
53
65
  }
54
66
 
55
67
  invalidate(): void {
@@ -84,14 +96,8 @@ export class Box implements Component {
84
96
  const bgSample = this.bgFn ? this.bgFn("test") : undefined;
85
97
 
86
98
  // Check cache validity
87
- const childLinesKey = childLines.join("\n");
88
- if (
89
- this.cachedLines &&
90
- this.cachedWidth === width &&
91
- this.cachedChildLines === childLinesKey &&
92
- this.cachedBgSample === bgSample
93
- ) {
94
- return this.cachedLines;
99
+ if (this.matchCache(width, childLines, bgSample)) {
100
+ return this.cached!.result;
95
101
  }
96
102
 
97
103
  // Apply background and padding
@@ -113,10 +119,7 @@ export class Box implements Component {
113
119
  }
114
120
 
115
121
  // Update cache
116
- this.cachedWidth = width;
117
- this.cachedChildLines = childLinesKey;
118
- this.cachedBgSample = bgSample;
119
- this.cachedLines = result;
122
+ this.cached = { key: childLines, width, bgSample, result };
120
123
 
121
124
  return result;
122
125
  }
@@ -134,7 +134,7 @@ export class Markdown implements Component {
134
134
  const wrappedLines: string[] = [];
135
135
  for (const line of renderedLines) {
136
136
  // Skip wrapping for image protocol lines (would corrupt escape sequences)
137
- if (this.containsImage(line)) {
137
+ if (TERMINAL_INFO.isImageLine(line)) {
138
138
  wrappedLines.push(line);
139
139
  } else {
140
140
  wrappedLines.push(...wrapTextWithAnsi(line, contentWidth));
@@ -149,7 +149,7 @@ export class Markdown implements Component {
149
149
 
150
150
  for (const line of wrappedLines) {
151
151
  // Image lines must be output raw - no margins or background
152
- if (this.containsImage(line)) {
152
+ if (TERMINAL_INFO.isImageLine(line)) {
153
153
  contentLines.push(line);
154
154
  continue;
155
155
  }
@@ -761,10 +761,6 @@ export class Markdown implements Component {
761
761
  return lines;
762
762
  }
763
763
 
764
- private containsImage(line: string): boolean {
765
- return line.includes("\x1b_G") || line.includes("\x1b]1337;File=");
766
- }
767
-
768
764
  /**
769
765
  * Render a mermaid image using terminal graphics protocol.
770
766
  * Returns array of lines (image placeholder rows) or null if rendering fails.
@@ -14,7 +14,7 @@ export class TerminalInfo {
14
14
  ) {}
15
15
 
16
16
  isImageLine(line: string): boolean {
17
- return !!this.imageProtocol && line.trimStart().startsWith(this.imageProtocol);
17
+ return !!this.imageProtocol && line.startsWith(this.imageProtocol);
18
18
  }
19
19
  }
20
20
 
package/src/tui.ts CHANGED
@@ -541,10 +541,6 @@ export class TUI extends Container {
541
541
  return result;
542
542
  }
543
543
 
544
- static containsImage(line: string): boolean {
545
- return TERMINAL_INFO.isImageLine(line);
546
- }
547
-
548
544
  /**
549
545
  * Resolve overlay layout from options.
550
546
  * Returns { width, row, col, maxHeight } for rendering.
@@ -766,7 +762,7 @@ export class TUI extends Container {
766
762
  const reset = TUI.SEGMENT_RESET;
767
763
  for (let i = 0; i < lines.length; i++) {
768
764
  const line = lines[i];
769
- if (!TUI.containsImage(line)) {
765
+ if (!TERMINAL_INFO.isImageLine(line)) {
770
766
  lines[i] = line + reset;
771
767
  }
772
768
  }
@@ -845,7 +841,7 @@ export class TUI extends Container {
845
841
  overlayWidth: number,
846
842
  totalWidth: number,
847
843
  ): string {
848
- if (TUI.containsImage(baseLine)) return baseLine;
844
+ if (TERMINAL_INFO.isImageLine(baseLine)) return baseLine;
849
845
 
850
846
  // Single pass through baseLine extracts both before and after segments
851
847
  const afterStart = startCol + overlayWidth;
@@ -1087,7 +1083,7 @@ export class TUI extends Container {
1087
1083
  if (i > firstChanged) buffer += "\r\n";
1088
1084
  buffer += "\x1b[2K"; // Clear current line
1089
1085
  const line = newLines[i];
1090
- const isImageLine = TUI.containsImage(line);
1086
+ const isImageLine = TERMINAL_INFO.isImageLine(line);
1091
1087
  if (!isImageLine && visibleWidth(line) > width) {
1092
1088
  // Log all lines to crash file for debugging
1093
1089
  const crashLogPath = path.join(os.homedir(), ".omp", "agent", "omp-crash.log");