@nuvin/ink 6.6.7 → 7.0.0-alpha

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 (149) hide show
  1. package/build/ansi-tokenizer.d.ts +38 -0
  2. package/build/ansi-tokenizer.js +316 -0
  3. package/build/ansi-tokenizer.js.map +1 -0
  4. package/build/components/AnimationContext.d.ts +9 -0
  5. package/build/components/AnimationContext.js +13 -0
  6. package/build/components/AnimationContext.js.map +1 -0
  7. package/build/components/App.d.ts +11 -49
  8. package/build/components/App.js +412 -227
  9. package/build/components/App.js.map +1 -1
  10. package/build/components/AppContext.d.ts +33 -3
  11. package/build/components/AppContext.js +2 -1
  12. package/build/components/AppContext.js.map +1 -1
  13. package/build/components/Box.d.ts +15 -8
  14. package/build/components/Box.js +12 -10
  15. package/build/components/Box.js.map +1 -1
  16. package/build/components/CursorContext.d.ts +11 -0
  17. package/build/components/CursorContext.js +8 -0
  18. package/build/components/CursorContext.js.map +1 -0
  19. package/build/components/ErrorBoundary.d.ts +18 -0
  20. package/build/components/ErrorBoundary.js +23 -0
  21. package/build/components/ErrorBoundary.js.map +1 -0
  22. package/build/components/ErrorOverview.js +6 -6
  23. package/build/components/ErrorOverview.js.map +1 -1
  24. package/build/components/Static.js.map +1 -1
  25. package/build/components/StdinContext.d.ts +7 -1
  26. package/build/components/StdinContext.js +1 -0
  27. package/build/components/StdinContext.js.map +1 -1
  28. package/build/components/Text.d.ts +1 -1
  29. package/build/components/Text.js +1 -1
  30. package/build/components/Text.js.map +1 -1
  31. package/build/components/Transform.d.ts +1 -1
  32. package/build/cursor-helpers.d.ts +38 -0
  33. package/build/cursor-helpers.js +56 -0
  34. package/build/cursor-helpers.js.map +1 -0
  35. package/build/devtools-window-polyfill.js +7 -4
  36. package/build/devtools-window-polyfill.js.map +1 -1
  37. package/build/devtools.js +31 -6
  38. package/build/devtools.js.map +1 -1
  39. package/build/dom.d.ts +5 -1
  40. package/build/dom.js +20 -1
  41. package/build/dom.js.map +1 -1
  42. package/build/hooks/use-animation.d.ts +49 -0
  43. package/build/hooks/use-animation.js +87 -0
  44. package/build/hooks/use-animation.js.map +1 -0
  45. package/build/hooks/use-app.d.ts +5 -2
  46. package/build/hooks/use-app.js +1 -1
  47. package/build/hooks/use-box-metrics.d.ts +59 -0
  48. package/build/hooks/use-box-metrics.js +88 -0
  49. package/build/hooks/use-box-metrics.js.map +1 -0
  50. package/build/hooks/use-cursor.d.ts +12 -0
  51. package/build/hooks/use-cursor.js +29 -0
  52. package/build/hooks/use-cursor.js.map +1 -0
  53. package/build/hooks/use-focus-manager.d.ts +17 -2
  54. package/build/hooks/use-focus-manager.js +2 -1
  55. package/build/hooks/use-focus-manager.js.map +1 -1
  56. package/build/hooks/use-focus.d.ts +2 -1
  57. package/build/hooks/use-focus.js +5 -4
  58. package/build/hooks/use-focus.js.map +1 -1
  59. package/build/hooks/use-input.d.ts +40 -1
  60. package/build/hooks/use-input.js +84 -51
  61. package/build/hooks/use-input.js.map +1 -1
  62. package/build/hooks/use-is-screen-reader-enabled.d.ts +2 -1
  63. package/build/hooks/use-is-screen-reader-enabled.js +2 -1
  64. package/build/hooks/use-is-screen-reader-enabled.js.map +1 -1
  65. package/build/hooks/use-paste.d.ts +35 -0
  66. package/build/hooks/use-paste.js +62 -0
  67. package/build/hooks/use-paste.js.map +1 -0
  68. package/build/hooks/use-stderr.d.ts +1 -1
  69. package/build/hooks/use-stderr.js +1 -1
  70. package/build/hooks/use-stdin.d.ts +4 -2
  71. package/build/hooks/use-stdin.js +2 -1
  72. package/build/hooks/use-stdin.js.map +1 -1
  73. package/build/hooks/use-stdout.d.ts +1 -1
  74. package/build/hooks/use-stdout.js +1 -1
  75. package/build/hooks/use-window-size.d.ts +18 -0
  76. package/build/hooks/use-window-size.js +22 -0
  77. package/build/hooks/use-window-size.js.map +1 -0
  78. package/build/index.d.ts +14 -1
  79. package/build/index.js +7 -0
  80. package/build/index.js.map +1 -1
  81. package/build/ink.d.ts +86 -5
  82. package/build/ink.js +581 -80
  83. package/build/ink.js.map +1 -1
  84. package/build/input-parser.d.ts +10 -0
  85. package/build/input-parser.js +194 -0
  86. package/build/input-parser.js.map +1 -0
  87. package/build/kitty-keyboard.d.ts +23 -0
  88. package/build/kitty-keyboard.js +32 -0
  89. package/build/kitty-keyboard.js.map +1 -0
  90. package/build/log-update.d.ts +7 -1
  91. package/build/log-update.js +181 -56
  92. package/build/log-update.js.map +1 -1
  93. package/build/measure-element.d.ts +4 -0
  94. package/build/measure-element.js +4 -0
  95. package/build/measure-element.js.map +1 -1
  96. package/build/measure-text.js +3 -11
  97. package/build/measure-text.js.map +1 -1
  98. package/build/output.d.ts +2 -1
  99. package/build/output.js +62 -58
  100. package/build/output.js.map +1 -1
  101. package/build/parse-keypress.d.ts +9 -3
  102. package/build/parse-keypress.js +283 -13
  103. package/build/parse-keypress.js.map +1 -1
  104. package/build/reconciler.js +57 -37
  105. package/build/reconciler.js.map +1 -1
  106. package/build/render-background.js +2 -0
  107. package/build/render-background.js.map +1 -1
  108. package/build/render-border.d.ts +1 -1
  109. package/build/render-border.js +35 -24
  110. package/build/render-border.js.map +1 -1
  111. package/build/render-node-to-output.d.ts +1 -1
  112. package/build/render-node-to-output.js +35 -18
  113. package/build/render-node-to-output.js.map +1 -1
  114. package/build/render-to-string.d.ts +38 -0
  115. package/build/render-to-string.js +116 -0
  116. package/build/render-to-string.js.map +1 -0
  117. package/build/render.d.ts +91 -3
  118. package/build/render.js +17 -5
  119. package/build/render.js.map +1 -1
  120. package/build/sanitize-ansi.d.ts +2 -0
  121. package/build/sanitize-ansi.js +27 -0
  122. package/build/sanitize-ansi.js.map +1 -0
  123. package/build/squash-text-nodes.js +2 -1
  124. package/build/squash-text-nodes.js.map +1 -1
  125. package/build/styles.d.ts +75 -37
  126. package/build/styles.js +87 -44
  127. package/build/styles.js.map +1 -1
  128. package/build/utils.d.ts +9 -2
  129. package/build/utils.js +18 -3
  130. package/build/utils.js.map +1 -1
  131. package/build/wrap-text.js +7 -14
  132. package/build/wrap-text.js.map +1 -1
  133. package/build/write-synchronized.d.ts +4 -0
  134. package/build/write-synchronized.js +9 -0
  135. package/build/write-synchronized.js.map +1 -0
  136. package/package.json +45 -105
  137. package/readme.md +850 -64
  138. package/build/components/FixedLayout.d.ts +0 -12
  139. package/build/components/FixedLayout.js +0 -19
  140. package/build/components/FixedLayout.js.map +0 -1
  141. package/build/components/VirtualizedList.d.ts +0 -21
  142. package/build/components/VirtualizedList.js +0 -55
  143. package/build/components/VirtualizedList.js.map +0 -1
  144. package/build/hooks/use-mouse.d.ts +0 -15
  145. package/build/hooks/use-mouse.js +0 -121
  146. package/build/hooks/use-mouse.js.map +0 -1
  147. package/build/hooks/use-virtualization.d.ts +0 -19
  148. package/build/hooks/use-virtualization.js +0 -56
  149. package/build/hooks/use-virtualization.js.map +0 -1
@@ -1,121 +1,246 @@
1
1
  import ansiEscapes from 'ansi-escapes';
2
2
  import cliCursor from 'cli-cursor';
3
+ import { cursorPositionChanged, buildCursorSuffix, buildCursorOnlySequence, buildReturnToBottomPrefix, hideCursorEscape, } from './cursor-helpers.js';
4
+ // Count visible lines in a string, ignoring the trailing empty element
5
+ // that `split('\n')` produces when the string ends with '\n'.
6
+ const visibleLineCount = (lines, str) => str.endsWith('\n') ? lines.length - 1 : lines.length;
3
7
  const createStandard = (stream, { showCursor = false } = {}) => {
4
8
  let previousLineCount = 0;
5
9
  let previousOutput = '';
6
10
  let hasHiddenCursor = false;
11
+ let cursorPosition;
12
+ let cursorDirty = false;
13
+ let previousCursorPosition;
14
+ let cursorWasShown = false;
15
+ const getActiveCursor = () => (cursorDirty ? cursorPosition : undefined);
16
+ const hasChanges = (str, activeCursor) => {
17
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
18
+ return str !== previousOutput || cursorChanged;
19
+ };
7
20
  const render = (str) => {
8
21
  if (!showCursor && !hasHiddenCursor) {
9
- cliCursor.hide();
22
+ cliCursor.hide(stream);
10
23
  hasHiddenCursor = true;
11
24
  }
12
- const output = str;
13
- if (output === previousOutput) {
14
- return;
25
+ // Only use cursor if setCursorPosition was called since last render.
26
+ // This ensures stale positions don't persist after component unmount.
27
+ const activeCursor = getActiveCursor();
28
+ cursorDirty = false;
29
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
30
+ if (!hasChanges(str, activeCursor)) {
31
+ return false;
32
+ }
33
+ const lines = str.split('\n');
34
+ const visibleCount = visibleLineCount(lines, str);
35
+ const cursorSuffix = buildCursorSuffix(visibleCount, activeCursor);
36
+ if (str === previousOutput && cursorChanged) {
37
+ stream.write(buildCursorOnlySequence({
38
+ cursorWasShown,
39
+ previousLineCount,
40
+ previousCursorPosition,
41
+ visibleLineCount: visibleCount,
42
+ cursorPosition: activeCursor,
43
+ }));
44
+ }
45
+ else {
46
+ previousOutput = str;
47
+ const returnPrefix = buildReturnToBottomPrefix(cursorWasShown, previousLineCount, previousCursorPosition);
48
+ stream.write(returnPrefix +
49
+ ansiEscapes.eraseLines(previousLineCount) +
50
+ str +
51
+ cursorSuffix);
52
+ previousLineCount = lines.length;
15
53
  }
16
- previousOutput = output;
17
- stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
18
- previousLineCount = output.split('\n').length;
54
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
55
+ cursorWasShown = activeCursor !== undefined;
56
+ return true;
19
57
  };
20
58
  render.clear = () => {
21
- stream.write(ansiEscapes.eraseLines(previousLineCount));
59
+ const prefix = buildReturnToBottomPrefix(cursorWasShown, previousLineCount, previousCursorPosition);
60
+ stream.write(prefix + ansiEscapes.eraseLines(previousLineCount));
22
61
  previousOutput = '';
23
62
  previousLineCount = 0;
63
+ previousCursorPosition = undefined;
64
+ cursorWasShown = false;
24
65
  };
25
66
  render.done = () => {
26
- // On exit, we write a finally newline to restore the terminal prompt properly,
27
- // unless the output was empty.
28
- if (previousOutput.length > 0) {
29
- stream.write('\n');
30
- }
31
67
  previousOutput = '';
32
68
  previousLineCount = 0;
69
+ previousCursorPosition = undefined;
70
+ cursorWasShown = false;
33
71
  if (!showCursor) {
34
- cliCursor.show();
72
+ cliCursor.show(stream);
35
73
  hasHiddenCursor = false;
36
74
  }
37
75
  };
76
+ render.reset = () => {
77
+ previousOutput = '';
78
+ previousLineCount = 0;
79
+ previousCursorPosition = undefined;
80
+ cursorWasShown = false;
81
+ };
38
82
  render.sync = (str) => {
39
- const output = str;
40
- previousOutput = output;
41
- previousLineCount = output.split('\n').length;
83
+ const activeCursor = cursorDirty ? cursorPosition : undefined;
84
+ cursorDirty = false;
85
+ const lines = str.split('\n');
86
+ previousOutput = str;
87
+ previousLineCount = lines.length;
88
+ if (!activeCursor && cursorWasShown) {
89
+ stream.write(hideCursorEscape);
90
+ }
91
+ if (activeCursor) {
92
+ stream.write(buildCursorSuffix(visibleLineCount(lines, str), activeCursor));
93
+ }
94
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
95
+ cursorWasShown = activeCursor !== undefined;
96
+ };
97
+ render.setCursorPosition = (position) => {
98
+ cursorPosition = position;
99
+ cursorDirty = true;
42
100
  };
101
+ render.isCursorDirty = () => cursorDirty;
102
+ render.willRender = (str) => hasChanges(str, getActiveCursor());
43
103
  return render;
44
104
  };
45
105
  const createIncremental = (stream, { showCursor = false } = {}) => {
46
106
  let previousLines = [];
47
107
  let previousOutput = '';
48
108
  let hasHiddenCursor = false;
109
+ let cursorPosition;
110
+ let cursorDirty = false;
111
+ let previousCursorPosition;
112
+ let cursorWasShown = false;
113
+ const getActiveCursor = () => (cursorDirty ? cursorPosition : undefined);
114
+ const hasChanges = (str, activeCursor) => {
115
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
116
+ return str !== previousOutput || cursorChanged;
117
+ };
49
118
  const render = (str) => {
50
119
  if (!showCursor && !hasHiddenCursor) {
51
- cliCursor.hide();
120
+ cliCursor.hide(stream);
52
121
  hasHiddenCursor = true;
53
122
  }
54
- const output = str;
55
- if (output === previousOutput) {
56
- return;
57
- }
58
- const previousCount = previousLines.length;
59
- const nextLines = output.split('\n');
60
- const nextCount = nextLines.length;
61
- const visibleCount = nextCount;
62
- if (output === '' || previousOutput.length === 0) {
63
- stream.write(ansiEscapes.eraseLines(previousCount) + output);
64
- previousOutput = output;
123
+ // Only use cursor if setCursorPosition was called since last render.
124
+ // This ensures stale positions don't persist after component unmount.
125
+ const activeCursor = getActiveCursor();
126
+ cursorDirty = false;
127
+ const cursorChanged = cursorPositionChanged(activeCursor, previousCursorPosition);
128
+ if (!hasChanges(str, activeCursor)) {
129
+ return false;
130
+ }
131
+ const nextLines = str.split('\n');
132
+ const visibleCount = visibleLineCount(nextLines, str);
133
+ const previousVisible = visibleLineCount(previousLines, previousOutput);
134
+ if (str === previousOutput && cursorChanged) {
135
+ stream.write(buildCursorOnlySequence({
136
+ cursorWasShown,
137
+ previousLineCount: previousLines.length,
138
+ previousCursorPosition,
139
+ visibleLineCount: visibleCount,
140
+ cursorPosition: activeCursor,
141
+ }));
142
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
143
+ cursorWasShown = activeCursor !== undefined;
144
+ return true;
145
+ }
146
+ const returnPrefix = buildReturnToBottomPrefix(cursorWasShown, previousLines.length, previousCursorPosition);
147
+ if (str === '\n' || previousOutput.length === 0) {
148
+ const cursorSuffix = buildCursorSuffix(visibleCount, activeCursor);
149
+ stream.write(returnPrefix +
150
+ ansiEscapes.eraseLines(previousLines.length) +
151
+ str +
152
+ cursorSuffix);
153
+ cursorWasShown = activeCursor !== undefined;
154
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
155
+ previousOutput = str;
65
156
  previousLines = nextLines;
66
- return;
157
+ return true;
67
158
  }
159
+ const hasTrailingNewline = str.endsWith('\n');
68
160
  // We aggregate all chunks for incremental rendering into a buffer, and then write them to stdout at the end.
69
161
  const buffer = [];
162
+ buffer.push(returnPrefix);
70
163
  // Clear extra lines if the current content's line count is lower than the previous.
71
- if (nextCount < previousCount) {
72
- buffer.push(
73
- // Erases the trailing lines.
74
- ansiEscapes.eraseLines(previousCount - nextCount),
75
- // Positions cursor to the top of the rendered output.
76
- ansiEscapes.cursorUp(nextCount));
164
+ if (visibleCount < previousVisible) {
165
+ const previousHadTrailingNewline = previousOutput.endsWith('\n');
166
+ const extraSlot = previousHadTrailingNewline ? 1 : 0;
167
+ buffer.push(ansiEscapes.eraseLines(previousVisible - visibleCount + extraSlot), ansiEscapes.cursorUp(visibleCount));
77
168
  }
78
169
  else {
79
- buffer.push(ansiEscapes.cursorUp(previousCount - 1), ansiEscapes.cursorLeft);
170
+ buffer.push(ansiEscapes.cursorUp(previousLines.length - 1));
80
171
  }
81
172
  for (let i = 0; i < visibleCount; i++) {
82
- // We skip writing lines if the contents are the same to prevent flickering.
83
- // However, we must still handle cursor positioning.
84
- const contentChanged = nextLines[i] !== previousLines[i];
85
- if (contentChanged) {
86
- // Erase and write the changed line
87
- buffer.push(ansiEscapes.eraseLine, nextLines[i] ?? '');
88
- }
89
- // Move to next line, except for the last line
90
- if (i < visibleCount - 1) {
91
- buffer.push(contentChanged ? '\n' : ansiEscapes.cursorNextLine);
173
+ const isLastLine = i === visibleCount - 1;
174
+ // We do not write lines if the contents are the same. This prevents flickering during renders.
175
+ if (nextLines[i] === previousLines[i]) {
176
+ // Don't move past the last line when there's no trailing newline,
177
+ // otherwise the cursor overshoots the rendered block.
178
+ if (!isLastLine || hasTrailingNewline) {
179
+ buffer.push(ansiEscapes.cursorNextLine);
180
+ }
181
+ continue;
92
182
  }
183
+ buffer.push(ansiEscapes.cursorTo(0) +
184
+ nextLines[i] +
185
+ ansiEscapes.eraseEndLine +
186
+ // Don't append newline after the last line when the input
187
+ // has no trailing newline (fullscreen mode).
188
+ (isLastLine && !hasTrailingNewline ? '' : '\n'));
93
189
  }
190
+ const cursorSuffix = buildCursorSuffix(visibleCount, activeCursor);
191
+ buffer.push(cursorSuffix);
94
192
  stream.write(buffer.join(''));
95
- previousOutput = output;
193
+ cursorWasShown = activeCursor !== undefined;
194
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
195
+ previousOutput = str;
96
196
  previousLines = nextLines;
197
+ return true;
97
198
  };
98
199
  render.clear = () => {
99
- stream.write(ansiEscapes.eraseLines(previousLines.length));
200
+ const prefix = buildReturnToBottomPrefix(cursorWasShown, previousLines.length, previousCursorPosition);
201
+ stream.write(prefix + ansiEscapes.eraseLines(previousLines.length));
100
202
  previousOutput = '';
101
203
  previousLines = [];
204
+ previousCursorPosition = undefined;
205
+ cursorWasShown = false;
102
206
  };
103
207
  render.done = () => {
104
- if (previousOutput.length > 0) {
105
- stream.write('\n');
106
- }
107
208
  previousOutput = '';
108
209
  previousLines = [];
210
+ previousCursorPosition = undefined;
211
+ cursorWasShown = false;
109
212
  if (!showCursor) {
110
- cliCursor.show();
213
+ cliCursor.show(stream);
111
214
  hasHiddenCursor = false;
112
215
  }
113
216
  };
217
+ render.reset = () => {
218
+ previousOutput = '';
219
+ previousLines = [];
220
+ previousCursorPosition = undefined;
221
+ cursorWasShown = false;
222
+ };
114
223
  render.sync = (str) => {
115
- const output = str;
116
- previousOutput = output;
117
- previousLines = output.split('\n');
224
+ const activeCursor = cursorDirty ? cursorPosition : undefined;
225
+ cursorDirty = false;
226
+ const lines = str.split('\n');
227
+ previousOutput = str;
228
+ previousLines = lines;
229
+ if (!activeCursor && cursorWasShown) {
230
+ stream.write(hideCursorEscape);
231
+ }
232
+ if (activeCursor) {
233
+ stream.write(buildCursorSuffix(visibleLineCount(lines, str), activeCursor));
234
+ }
235
+ previousCursorPosition = activeCursor ? { ...activeCursor } : undefined;
236
+ cursorWasShown = activeCursor !== undefined;
237
+ };
238
+ render.setCursorPosition = (position) => {
239
+ cursorPosition = position;
240
+ cursorDirty = true;
118
241
  };
242
+ render.isCursorDirty = () => cursorDirty;
243
+ render.willRender = (str) => hasChanges(str, getActiveCursor());
119
244
  return render;
120
245
  };
121
246
  const create = (stream, { showCursor = false, incremental = false } = {}) => {
@@ -1 +1 @@
1
- {"version":3,"file":"log-update.js","sourceRoot":"","sources":["../src/log-update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"log-update.js","sourceRoot":"","sources":["../src/log-update.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,10 @@ type Output = {
11
11
  };
12
12
  /**
13
13
  Measure the dimensions of a particular `<Box>` element.
14
+ Returns an object with `width` and `height` properties.
15
+ This function is useful when your component needs to know the amount of available space it has. You can use it when you need to change the layout based on the length of its content.
16
+
17
+ Note: `measureElement()` returns `{width: 0, height: 0}` when called during render (before layout is calculated). Call it from post-render code, such as `useEffect`, `useLayoutEffect`, input handlers, or timer callbacks. When content changes, pass the relevant dependency to your effect so it re-measures after each update.
14
18
  */
15
19
  declare const measureElement: (node: DOMElement) => Output;
16
20
  export default measureElement;
@@ -1,5 +1,9 @@
1
1
  /**
2
2
  Measure the dimensions of a particular `<Box>` element.
3
+ Returns an object with `width` and `height` properties.
4
+ This function is useful when your component needs to know the amount of available space it has. You can use it when you need to change the layout based on the length of its content.
5
+
6
+ Note: `measureElement()` returns `{width: 0, height: 0}` when called during render (before layout is calculated). Call it from post-render code, such as `useEffect`, `useLayoutEffect`, input handlers, or timer callbacks. When content changes, pass the relevant dependency to your effect so it re-measures after each update.
3
7
  */
4
8
  const measureElement = (node) => ({
5
9
  width: node.yogaNode?.getComputedWidth() ?? 0,
@@ -1 +1 @@
1
- {"version":3,"file":"measure-element.js","sourceRoot":"","sources":["../src/measure-element.ts"],"names":[],"mappings":"AAcA;;EAEE;AACF,MAAM,cAAc,GAAG,CAAC,IAAgB,EAAU,EAAE,CAAC,CAAC;IACrD,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,CAAC;IAC7C,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,CAAC;CAC/C,CAAC,CAAC;AAEH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"measure-element.js","sourceRoot":"","sources":["../src/measure-element.ts"],"names":[],"mappings":"AAcA;;;;;;EAME;AACF,MAAM,cAAc,GAAG,CAAC,IAAgB,EAAU,EAAE,CAAC,CAAC;IACrD,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,CAAC;IAC7C,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,CAAC;CAC/C,CAAC,CAAC;AAEH,eAAe,cAAc,CAAC"}
@@ -1,6 +1,5 @@
1
- import stringWidth from 'string-width';
1
+ import widestLine from 'widest-line';
2
2
  const cache = new Map();
3
- const TAB_SPACES = ' '; // 2 spaces per tab
4
3
  const measureText = (text) => {
5
4
  if (text.length === 0) {
6
5
  return {
@@ -12,15 +11,8 @@ const measureText = (text) => {
12
11
  if (cachedDimensions) {
13
12
  return cachedDimensions;
14
13
  }
15
- const lines = text.split('\n');
16
- let width = Math.max(0, ...lines.map(line => stringWidth(line.includes('\t') ? line.replaceAll('\t', TAB_SPACES) : line)));
17
- // If width is > 0, add a tiny epsilon to prevent Yoga from wrapping
18
- // items with exact integer width (like 1) in some flexbox configurations.
19
- // This fixes a layout regression where items would wrap unexpectedly.
20
- if (width > 0) {
21
- width += 0.01;
22
- }
23
- const height = lines.length;
14
+ const width = widestLine(text);
15
+ const height = text.split('\n').length;
24
16
  const dimensions = { width, height };
25
17
  cache.set(text, dimensions);
26
18
  return dimensions;
@@ -1 +1 @@
1
- {"version":3,"file":"measure-text.js","sourceRoot":"","sources":["../src/measure-text.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,mBAAmB;AAO5C,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE;IAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACN,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;SACT,CAAC;IACH,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,gBAAgB,EAAE,CAAC;QACtB,OAAO,gBAAgB,CAAC;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CACnB,CAAC,EACD,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACnB,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAC3E,CACD,CAAC;IAEF,oEAAoE;IACpE,0EAA0E;IAC1E,sEAAsE;IACtE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACf,KAAK,IAAI,IAAI,CAAC;IACf,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,MAAM,UAAU,GAAG,EAAC,KAAK,EAAE,MAAM,EAAC,CAAC;IACnC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAE5B,OAAO,UAAU,CAAC;AACnB,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"measure-text.js","sourceRoot":"","sources":["../src/measure-text.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAC;AAErC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAOxC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE;IAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACN,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;SACT,CAAC;IACH,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,gBAAgB,EAAE,CAAC;QACtB,OAAO,gBAAgB,CAAC;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACvC,MAAM,UAAU,GAAG,EAAC,KAAK,EAAE,MAAM,EAAC,CAAC;IACnC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAE5B,OAAO,UAAU,CAAC;AACnB,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
package/build/output.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { OutputTransformer } from './render-node-to-output.js';
1
+ import { type OutputTransformer } from './render-node-to-output.js';
2
2
  /**
3
3
  "Virtual" output class
4
4
 
@@ -20,6 +20,7 @@ export default class Output {
20
20
  width: number;
21
21
  height: number;
22
22
  private readonly operations;
23
+ private readonly caches;
23
24
  constructor(options: Options);
24
25
  write(x: number, y: number, text: string, options: {
25
26
  transformers: OutputTransformer[];
package/build/output.js CHANGED
@@ -1,36 +1,44 @@
1
1
  import sliceAnsi from 'slice-ansi';
2
2
  import stringWidth from 'string-width';
3
3
  import { styledCharsFromTokens, styledCharsToString, tokenize, } from '@alcalzone/ansi-tokenize';
4
- const TAB_SPACES = ' '; // 2 spaces per tab
5
- const expandTabs = (text) => text.includes('\t') ? text.replaceAll('\t', TAB_SPACES) : text;
6
- const intersectClips = (clips) => {
7
- if (clips.length === 0) {
8
- return undefined;
9
- }
10
- let x1;
11
- let x2;
12
- let y1;
13
- let y2;
14
- for (const c of clips) {
15
- if (c.x1 !== undefined) {
16
- x1 = x1 === undefined ? c.x1 : Math.max(x1, c.x1);
17
- }
18
- if (c.x2 !== undefined) {
19
- x2 = x2 === undefined ? c.x2 : Math.min(x2, c.x2);
4
+ class OutputCaches {
5
+ widths = new Map();
6
+ blockWidths = new Map();
7
+ styledChars = new Map();
8
+ getStyledChars(line) {
9
+ let cached = this.styledChars.get(line);
10
+ if (cached === undefined) {
11
+ cached = styledCharsFromTokens(tokenize(line));
12
+ this.styledChars.set(line, cached);
20
13
  }
21
- if (c.y1 !== undefined) {
22
- y1 = y1 === undefined ? c.y1 : Math.max(y1, c.y1);
14
+ return cached;
15
+ }
16
+ getStringWidth(text) {
17
+ let cached = this.widths.get(text);
18
+ if (cached === undefined) {
19
+ cached = stringWidth(text);
20
+ this.widths.set(text, cached);
23
21
  }
24
- if (c.y2 !== undefined) {
25
- y2 = y2 === undefined ? c.y2 : Math.min(y2, c.y2);
22
+ return cached;
23
+ }
24
+ getWidestLine(text) {
25
+ let cached = this.blockWidths.get(text);
26
+ if (cached === undefined) {
27
+ let lineWidth = 0;
28
+ for (const line of text.split('\n')) {
29
+ lineWidth = Math.max(lineWidth, this.getStringWidth(line));
30
+ }
31
+ cached = lineWidth;
32
+ this.blockWidths.set(text, cached);
26
33
  }
34
+ return cached;
27
35
  }
28
- return { x1, x2, y1, y2 };
29
- };
36
+ }
30
37
  export default class Output {
31
38
  width;
32
39
  height;
33
40
  operations = [];
41
+ caches = new OutputCaches();
34
42
  constructor(options) {
35
43
  const { width, height } = options;
36
44
  this.width = width;
@@ -45,7 +53,7 @@ export default class Output {
45
53
  type: 'write',
46
54
  x,
47
55
  y,
48
- text: expandTabs(text),
56
+ text,
49
57
  transformers,
50
58
  });
51
59
  }
@@ -87,14 +95,14 @@ export default class Output {
87
95
  const { text, transformers } = operation;
88
96
  let { x, y } = operation;
89
97
  let lines = text.split('\n');
90
- const clip = intersectClips(clips);
98
+ const clip = clips.at(-1);
91
99
  if (clip) {
92
100
  const clipHorizontally = typeof clip?.x1 === 'number' && typeof clip?.x2 === 'number';
93
101
  const clipVertically = typeof clip?.y1 === 'number' && typeof clip?.y2 === 'number';
94
102
  // If text is positioned outside of clipping area altogether,
95
103
  // skip to the next operation to avoid unnecessary calculations
96
104
  if (clipHorizontally) {
97
- const width = Math.max(0, ...lines.map(line => stringWidth(line)));
105
+ const width = this.caches.getWidestLine(text);
98
106
  if (x + width < clip.x1 || x > clip.x2) {
99
107
  continue;
100
108
  }
@@ -108,7 +116,7 @@ export default class Output {
108
116
  if (clipHorizontally) {
109
117
  lines = lines.map(line => {
110
118
  const from = x < clip.x1 ? clip.x1 - x : 0;
111
- const width = stringWidth(line);
119
+ const width = this.caches.getStringWidth(line);
112
120
  const to = x + width > clip.x2 ? clip.x2 - x : width;
113
121
  return sliceAnsi(line, from, to);
114
122
  });
@@ -136,41 +144,34 @@ export default class Output {
136
144
  for (const transformer of transformers) {
137
145
  line = transformer(line, index);
138
146
  }
139
- const characters = styledCharsFromTokens(tokenize(line));
147
+ const characters = this.caches.getStyledChars(line);
140
148
  let offsetX = x;
149
+ // Nothing to write (e.g. line was clipped away).
150
+ if (characters.length === 0) {
151
+ offsetY++;
152
+ continue;
153
+ }
154
+ const spaceCell = {
155
+ type: 'char',
156
+ value: ' ',
157
+ fullWidth: false,
158
+ styles: [],
159
+ };
160
+ // Wide characters (e.g. CJK) occupy two cells: a leading
161
+ // cell with the character and a trailing placeholder with
162
+ // value ''. When an overlapping write lands in the middle
163
+ // of a wide character, the boundary cells need cleanup so
164
+ // the terminal never renders a half-visible wide character.
165
+ if (currentLine[offsetX]?.value === '' &&
166
+ offsetX > 0 &&
167
+ this.caches.getStringWidth(currentLine[offsetX - 1]?.value ?? '') >
168
+ 1) {
169
+ currentLine[offsetX - 1] = spaceCell;
170
+ }
141
171
  for (const character of characters) {
142
- // Check if this is a zero-width character (like U+FE0F emoji variation selector)
143
- const rawWidth = stringWidth(character.value);
144
- if (rawWidth === 0) {
145
- // Zero-width characters (like variation selectors) should be appended
146
- // to the previous cell rather than taking up their own space
147
- const previousCell = currentLine[offsetX - 1];
148
- if (previousCell?.value) {
149
- // Measure width before and after appending to detect width changes
150
- // This handles cases like ⏭ (width 1) + ️ (VS16) = ⏭️ (width 2)
151
- const prevWidth = stringWidth(previousCell.value);
152
- previousCell.value += character.value;
153
- const newWidth = stringWidth(previousCell.value);
154
- // If combining increased the display width, add placeholder cells
155
- const extraWidth = newWidth - prevWidth;
156
- if (extraWidth > 0) {
157
- for (let i = 0; i < extraWidth; i++) {
158
- currentLine[offsetX + i] = {
159
- type: 'char',
160
- value: '',
161
- fullWidth: false,
162
- styles: previousCell.styles,
163
- };
164
- }
165
- offsetX += extraWidth;
166
- }
167
- }
168
- // Don't advance offsetX for zero-width characters (already handled above if width changed)
169
- continue;
170
- }
171
172
  currentLine[offsetX] = character;
172
- // Determine printed width using string-width
173
- const characterWidth = Math.max(1, rawWidth);
173
+ // Determine printed width using string-width to align with measurement
174
+ const characterWidth = Math.max(1, this.caches.getStringWidth(character.value));
174
175
  // For multi-column characters, clear following cells to avoid stray spaces/artifacts
175
176
  if (characterWidth > 1) {
176
177
  for (let index = 1; index < characterWidth; index++) {
@@ -184,6 +185,9 @@ export default class Output {
184
185
  }
185
186
  offsetX += characterWidth;
186
187
  }
188
+ if (currentLine[offsetX]?.value === '') {
189
+ currentLine[offsetX] = spaceCell;
190
+ }
187
191
  offsetY++;
188
192
  }
189
193
  }