@jrichman/ink 6.5.1-beta.2 → 6.5.1-beta.5
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/build/colorize.d.ts +2 -0
- package/build/colorize.js +24 -0
- package/build/colorize.js.map +1 -1
- package/build/components/Static.js +2 -1
- package/build/components/Static.js.map +1 -1
- package/build/components/Text.js +8 -8
- package/build/components/Text.js.map +1 -1
- package/build/debug-log.js +3 -2
- package/build/debug-log.js.map +1 -1
- package/build/dom.js +3 -5
- package/build/dom.js.map +1 -1
- package/build/index.d.ts +2 -2
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/ink.d.ts +2 -2
- package/build/ink.js +3 -0
- package/build/ink.js.map +1 -1
- package/build/measure-element.js +3 -3
- package/build/measure-element.js.map +1 -1
- package/build/measure-text.d.ts +14 -1
- package/build/measure-text.js +46 -38
- package/build/measure-text.js.map +1 -1
- package/build/output.d.ts +6 -0
- package/build/output.js +26 -18
- package/build/output.js.map +1 -1
- package/build/render-background.js +16 -4
- package/build/render-background.js.map +1 -1
- package/build/render-cached.d.ts +2 -2
- package/build/render-cached.js +7 -6
- package/build/render-cached.js.map +1 -1
- package/build/render-container.d.ts +2 -2
- package/build/render-node-to-output.d.ts +3 -3
- package/build/render-node-to-output.js +2 -0
- package/build/render-node-to-output.js.map +1 -1
- package/build/render-scrollbar.d.ts +1 -2
- package/build/render-scrollbar.js +14 -28
- package/build/render-scrollbar.js.map +1 -1
- package/build/render-sticky.d.ts +3 -3
- package/build/render-text-node.d.ts +2 -2
- package/build/render-text-node.js +47 -43
- package/build/render-text-node.js.map +1 -1
- package/build/render.d.ts +2 -2
- package/build/renderer.d.ts +2 -2
- package/build/renderer.js +2 -1
- package/build/renderer.js.map +1 -1
- package/build/replay.js +4 -4
- package/build/replay.js.map +1 -1
- package/build/selection.d.ts +2 -3
- package/build/selection.js +35 -57
- package/build/selection.js.map +1 -1
- package/build/serialization.js +2 -0
- package/build/serialization.js.map +1 -1
- package/build/styled-line.d.ts +18 -33
- package/build/styled-line.js +373 -156
- package/build/styled-line.js.map +1 -1
- package/build/text-wrap.d.ts +5 -0
- package/build/text-wrap.js +78 -79
- package/build/text-wrap.js.map +1 -1
- package/build/tokenize.d.ts +1 -1
- package/build/tokenize.js +2 -2
- package/build/tokenize.js.map +1 -1
- package/build/worker/canvas.d.ts +13 -1
- package/build/worker/canvas.js +16 -5
- package/build/worker/canvas.js.map +1 -1
- package/build/worker/compositor.js +9 -23
- package/build/worker/compositor.js.map +1 -1
- package/build/worker/render-worker.js +2 -2
- package/build/worker/render-worker.js.map +1 -1
- package/build/worker/terminal-writer.js +1 -1
- package/build/worker/terminal-writer.js.map +1 -1
- package/package.json +2 -2
- package/build/render-worker.d.ts +0 -25
- package/build/render-worker.js +0 -370
- package/build/render-worker.js.map +0 -1
- package/build/styled-lines.d.ts +0 -29
- package/build/styled-lines.js +0 -110
- package/build/styled-lines.js.map +0 -1
- package/build/terminal-writer.d.ts +0 -69
- package/build/terminal-writer.js +0 -546
- package/build/terminal-writer.js.map +0 -1
- package/build/web/ansi-to-css.d.ts +0 -16
- package/build/web/ansi-to-css.js +0 -147
- package/build/web/ansi-to-css.js.map +0 -1
- package/build/web/client.d.ts +0 -51
- package/build/web/client.js +0 -315
- package/build/web/client.js.map +0 -1
- package/build/web/server.d.ts +0 -1
- package/build/web/server.js +0 -179
- package/build/web/server.js.map +0 -1
- package/build/worker/dump-replay.d.ts +0 -1
- package/build/worker/dump-replay.js +0 -15
- package/build/worker/dump-replay.js.map +0 -1
- package/build/worker/replay.d.ts +0 -55
- package/build/worker/replay.js +0 -133
- package/build/worker/replay.js.map +0 -1
- package/build/wrap-text.d.ts +0 -6
- package/build/wrap-text.js +0 -120
- package/build/wrap-text.js.map +0 -1
package/build/styled-line.js
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { FULL_WIDTH_MASK, INVERSE_MASK } from './tokenize.js';
|
|
7
|
+
const MAX_SAFE_OFFSET = 0x7f_ff;
|
|
2
8
|
export class StyledLine {
|
|
3
9
|
static empty(length) {
|
|
10
|
+
const safeLength = Math.min(length, MAX_SAFE_OFFSET);
|
|
11
|
+
if (safeLength <= 0) {
|
|
12
|
+
return new StyledLine();
|
|
13
|
+
}
|
|
14
|
+
const cached = StyledLine.emptyCache.get(safeLength);
|
|
15
|
+
if (cached) {
|
|
16
|
+
return cached.clone();
|
|
17
|
+
}
|
|
4
18
|
const line = new StyledLine();
|
|
5
|
-
line.length =
|
|
6
|
-
line.text = ' '.repeat(
|
|
7
|
-
line.charData = new Uint16Array(Math.max(
|
|
8
|
-
for (let i = 0; i <
|
|
19
|
+
line.length = safeLength;
|
|
20
|
+
line.text = ' '.repeat(safeLength);
|
|
21
|
+
line.charData = new Uint16Array(Math.max(safeLength, 16));
|
|
22
|
+
for (let i = 0; i < safeLength; i++) {
|
|
9
23
|
line.charData[i] = i;
|
|
10
24
|
}
|
|
11
|
-
line.spans =
|
|
25
|
+
line.spans = [{ length: safeLength, formatFlags: 0 }];
|
|
26
|
+
if (StyledLine.emptyCache.size > 100) {
|
|
27
|
+
StyledLine.emptyCache.clear();
|
|
28
|
+
}
|
|
29
|
+
Object.freeze(line.spans[0]);
|
|
30
|
+
Object.freeze(line.spans);
|
|
31
|
+
Object.freeze(line);
|
|
32
|
+
StyledLine.emptyCache.set(safeLength, line);
|
|
33
|
+
return line.clone();
|
|
34
|
+
}
|
|
35
|
+
static legacyCreateStyledLine(values = [], spans = []) {
|
|
36
|
+
const line = new StyledLine();
|
|
37
|
+
line.applyValuesAndSpans(values, spans);
|
|
12
38
|
return line;
|
|
13
39
|
}
|
|
40
|
+
static emptyCache = new Map();
|
|
14
41
|
length;
|
|
15
42
|
text;
|
|
16
43
|
charData;
|
|
17
44
|
spans;
|
|
18
|
-
constructor(
|
|
19
|
-
this.length =
|
|
20
|
-
this.text = values.join('');
|
|
21
|
-
this.charData = new Uint16Array(Math.max(this.length, 16));
|
|
22
|
-
let currentOffset = 0;
|
|
23
|
-
let spanIdx = 0;
|
|
24
|
-
let spanPos = 0;
|
|
25
|
-
for (let i = 0; i < this.length; i++) {
|
|
26
|
-
const val = values[i];
|
|
27
|
-
let isFullWidth = false;
|
|
28
|
-
if (spans.length > 0 && spanIdx < spans.length) {
|
|
29
|
-
const span = spans[spanIdx];
|
|
30
|
-
if ((span.formatFlags & FULL_WIDTH_MASK) !== 0) {
|
|
31
|
-
isFullWidth = true;
|
|
32
|
-
}
|
|
33
|
-
spanPos++;
|
|
34
|
-
if (spanPos >= span.length) {
|
|
35
|
-
spanIdx++;
|
|
36
|
-
spanPos = 0;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
this.charData[i] = currentOffset | (isFullWidth ? 0x80_00 : 0);
|
|
40
|
-
currentOffset += val.length;
|
|
41
|
-
}
|
|
42
|
-
this.spans = spans.map(s => ({
|
|
43
|
-
...s,
|
|
44
|
-
formatFlags: s.formatFlags & ~FULL_WIDTH_MASK,
|
|
45
|
-
}));
|
|
46
|
-
this.mergeSpans();
|
|
45
|
+
constructor() {
|
|
46
|
+
this.length = 0;
|
|
47
47
|
}
|
|
48
48
|
getValue(index) {
|
|
49
|
-
if (index < 0 || index >= this.length)
|
|
49
|
+
if (this.text === undefined || index < 0 || index >= this.length)
|
|
50
50
|
return '';
|
|
51
51
|
const start = this.charData[index] & 0x7f_ff;
|
|
52
52
|
const end = index + 1 < this.length
|
|
@@ -55,7 +55,7 @@ export class StyledLine {
|
|
|
55
55
|
return this.text.slice(start, end);
|
|
56
56
|
}
|
|
57
57
|
getSpan(index) {
|
|
58
|
-
if (index < 0 || index >= this.length)
|
|
58
|
+
if (this.spans === undefined || index < 0 || index >= this.length)
|
|
59
59
|
return undefined;
|
|
60
60
|
let current = 0;
|
|
61
61
|
for (const span of this.spans) {
|
|
@@ -66,7 +66,7 @@ export class StyledLine {
|
|
|
66
66
|
return undefined;
|
|
67
67
|
}
|
|
68
68
|
getFullWidth(index) {
|
|
69
|
-
if (index < 0 || index >= this.length)
|
|
69
|
+
if (this.charData === undefined || index < 0 || index >= this.length)
|
|
70
70
|
return false;
|
|
71
71
|
return (this.charData[index] & 0x80_00) !== 0;
|
|
72
72
|
}
|
|
@@ -95,10 +95,64 @@ export class StyledLine {
|
|
|
95
95
|
getLink(index) {
|
|
96
96
|
return this.getSpan(index)?.link;
|
|
97
97
|
}
|
|
98
|
+
setInverted(index, inverted) {
|
|
99
|
+
if (index < 0 || index >= this.length)
|
|
100
|
+
return;
|
|
101
|
+
this.ensureInitialized();
|
|
102
|
+
this.splitSpansAt(index);
|
|
103
|
+
this.splitSpansAt(index + 1);
|
|
104
|
+
let current = 0;
|
|
105
|
+
for (const span of this.spans) {
|
|
106
|
+
if (current === index && span.length === 1) {
|
|
107
|
+
if (inverted) {
|
|
108
|
+
span.formatFlags |= INVERSE_MASK;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
span.formatFlags &= ~INVERSE_MASK;
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
current += span.length;
|
|
116
|
+
}
|
|
117
|
+
this.mergeSpans();
|
|
118
|
+
}
|
|
119
|
+
setBackgroundColor(index, color) {
|
|
120
|
+
if (index < 0 || index >= this.length)
|
|
121
|
+
return;
|
|
122
|
+
this.ensureInitialized();
|
|
123
|
+
this.splitSpansAt(index);
|
|
124
|
+
this.splitSpansAt(index + 1);
|
|
125
|
+
let current = 0;
|
|
126
|
+
for (const span of this.spans) {
|
|
127
|
+
if (current === index && span.length === 1) {
|
|
128
|
+
span.bgColor = color;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
current += span.length;
|
|
132
|
+
}
|
|
133
|
+
this.mergeSpans();
|
|
134
|
+
}
|
|
135
|
+
setForegroundColor(index, color) {
|
|
136
|
+
if (index < 0 || index >= this.length)
|
|
137
|
+
return;
|
|
138
|
+
this.ensureInitialized();
|
|
139
|
+
this.splitSpansAt(index);
|
|
140
|
+
this.splitSpansAt(index + 1);
|
|
141
|
+
let current = 0;
|
|
142
|
+
for (const span of this.spans) {
|
|
143
|
+
if (current === index && span.length === 1) {
|
|
144
|
+
span.fgColor = color;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
current += span.length;
|
|
148
|
+
}
|
|
149
|
+
this.mergeSpans();
|
|
150
|
+
}
|
|
98
151
|
// eslint-disable-next-line max-params
|
|
99
152
|
setChar(index, value, formatFlags, fgColor, bgColor, link) {
|
|
100
153
|
if (index < 0 || index >= this.length)
|
|
101
154
|
return;
|
|
155
|
+
this.ensureInitialized();
|
|
102
156
|
const isFullWidth = (formatFlags & FULL_WIDTH_MASK) !== 0;
|
|
103
157
|
const cleanFormatFlags = formatFlags & ~FULL_WIDTH_MASK;
|
|
104
158
|
const start = this.charData[index] & 0x7f_ff;
|
|
@@ -106,12 +160,16 @@ export class StyledLine {
|
|
|
106
160
|
? this.charData[index + 1] & 0x7f_ff
|
|
107
161
|
: this.text.length;
|
|
108
162
|
const oldLen = end - start;
|
|
109
|
-
|
|
163
|
+
let newValue = value;
|
|
164
|
+
if (this.text.length - oldLen + value.length > MAX_SAFE_OFFSET) {
|
|
165
|
+
newValue = value.slice(0, Math.max(0, MAX_SAFE_OFFSET - (this.text.length - oldLen)));
|
|
166
|
+
}
|
|
167
|
+
const newLen = newValue.length;
|
|
110
168
|
if (oldLen === newLen) {
|
|
111
|
-
this.text = this.text.slice(0, start) +
|
|
169
|
+
this.text = this.text.slice(0, start) + newValue + this.text.slice(end);
|
|
112
170
|
}
|
|
113
171
|
else {
|
|
114
|
-
this.text = this.text.slice(0, start) +
|
|
172
|
+
this.text = this.text.slice(0, start) + newValue + this.text.slice(end);
|
|
115
173
|
const diff = newLen - oldLen;
|
|
116
174
|
for (let i = index + 1; i < this.length; i++) {
|
|
117
175
|
const data = this.charData[i];
|
|
@@ -142,9 +200,19 @@ export class StyledLine {
|
|
|
142
200
|
}
|
|
143
201
|
// eslint-disable-next-line max-params
|
|
144
202
|
pushChar(value, formatFlags, fgColor, bgColor, link) {
|
|
203
|
+
this.ensureInitialized();
|
|
145
204
|
const isFullWidth = (formatFlags & FULL_WIDTH_MASK) !== 0;
|
|
146
205
|
const cleanFormatFlags = formatFlags & ~FULL_WIDTH_MASK;
|
|
147
206
|
const offset = this.text.length;
|
|
207
|
+
if (value !== '…' && offset + value.length > MAX_SAFE_OFFSET - 1) {
|
|
208
|
+
if (offset < MAX_SAFE_OFFSET && !this.text.endsWith('…')) {
|
|
209
|
+
this.pushChar('…', formatFlags, fgColor, bgColor, link);
|
|
210
|
+
}
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (offset + value.length > MAX_SAFE_OFFSET) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
148
216
|
this.text += value;
|
|
149
217
|
if (this.length >= this.charData.length) {
|
|
150
218
|
const newData = new Uint16Array(this.charData.length * 2 || 16);
|
|
@@ -171,11 +239,26 @@ export class StyledLine {
|
|
|
171
239
|
}
|
|
172
240
|
this.length++;
|
|
173
241
|
}
|
|
242
|
+
clone() {
|
|
243
|
+
if (this.charData === undefined)
|
|
244
|
+
return new StyledLine();
|
|
245
|
+
const result = new StyledLine();
|
|
246
|
+
result.length = this.length;
|
|
247
|
+
result.text = this.text;
|
|
248
|
+
result.charData = this.charData.slice(0, Math.max(this.length, 16));
|
|
249
|
+
result.spans = this.spans.map(span => ({ ...span }));
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
174
252
|
slice(start, end) {
|
|
253
|
+
if (this.charData === undefined)
|
|
254
|
+
return new StyledLine();
|
|
175
255
|
const actualStart = Math.max(0, start);
|
|
176
256
|
const actualEnd = end === undefined ? this.length : Math.min(this.length, end);
|
|
177
257
|
if (actualStart >= actualEnd)
|
|
178
|
-
return new StyledLine(
|
|
258
|
+
return new StyledLine();
|
|
259
|
+
if (actualStart === 0 && actualEnd === this.length) {
|
|
260
|
+
return this.clone();
|
|
261
|
+
}
|
|
179
262
|
const result = new StyledLine();
|
|
180
263
|
result.length = actualEnd - actualStart;
|
|
181
264
|
result.charData = new Uint16Array(Math.max(result.length, 16));
|
|
@@ -211,65 +294,143 @@ export class StyledLine {
|
|
|
211
294
|
result.mergeSpans();
|
|
212
295
|
return result;
|
|
213
296
|
}
|
|
214
|
-
|
|
297
|
+
combine(...others) {
|
|
298
|
+
if (others.length === 0)
|
|
299
|
+
return this.clone();
|
|
300
|
+
const allLines = [this, ...others].filter(l => l.length > 0);
|
|
301
|
+
if (allLines.length === 0)
|
|
302
|
+
return new StyledLine();
|
|
303
|
+
if (allLines.length === 1)
|
|
304
|
+
return allLines[0].clone();
|
|
305
|
+
let totalTextLen = 0;
|
|
306
|
+
let totalChars = 0;
|
|
307
|
+
for (const line of allLines) {
|
|
308
|
+
totalTextLen += line.getText().length;
|
|
309
|
+
totalChars += line.length;
|
|
310
|
+
}
|
|
311
|
+
if (totalTextLen > MAX_SAFE_OFFSET) {
|
|
312
|
+
let result = this.clone();
|
|
313
|
+
for (const other of others) {
|
|
314
|
+
result = result.instanceConcat(other);
|
|
315
|
+
}
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
215
318
|
const result = new StyledLine();
|
|
216
|
-
result.length =
|
|
217
|
-
result.text =
|
|
218
|
-
result.charData = new Uint16Array(Math.max(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
for (
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
319
|
+
result.length = totalChars;
|
|
320
|
+
result.text = allLines.map(l => l.getText()).join('');
|
|
321
|
+
result.charData = new Uint16Array(Math.max(totalChars, 16));
|
|
322
|
+
let currentChar = 0;
|
|
323
|
+
let currentOffset = 0;
|
|
324
|
+
for (const line of allLines) {
|
|
325
|
+
const lineCharData = line.charData;
|
|
326
|
+
const lineText = line.getText();
|
|
327
|
+
if (lineCharData) {
|
|
328
|
+
for (let i = 0; i < line.length; i++) {
|
|
329
|
+
const data = lineCharData[i];
|
|
330
|
+
const offset = data & 0x7f_ff;
|
|
331
|
+
const fw = data & 0x80_00;
|
|
332
|
+
result.charData[currentChar + i] = (currentOffset + offset) | fw;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
for (let i = 0; i < line.length; i++) {
|
|
337
|
+
result.charData[currentChar + i] = currentOffset + i;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
currentChar += line.length;
|
|
341
|
+
currentOffset += lineText.length;
|
|
226
342
|
}
|
|
227
|
-
result.spans =
|
|
343
|
+
result.spans = allLines.flatMap(l => l.getSpans().map(s => ({ ...s })));
|
|
228
344
|
result.mergeSpans();
|
|
229
345
|
return result;
|
|
230
346
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
347
|
+
getTrimmedLength() {
|
|
348
|
+
if (this.length === 0)
|
|
349
|
+
return 0;
|
|
350
|
+
if (this.text === undefined || this.charData === undefined)
|
|
351
|
+
return 0;
|
|
352
|
+
let currentIdx = this.length - 1;
|
|
353
|
+
if (this.spans) {
|
|
354
|
+
for (let s = this.spans.length - 1; s >= 0; s--) {
|
|
355
|
+
const span = this.spans[s];
|
|
356
|
+
const hasStyles = (span.formatFlags & ~FULL_WIDTH_MASK) !== 0 ||
|
|
357
|
+
span.fgColor !== undefined ||
|
|
358
|
+
span.bgColor !== undefined ||
|
|
359
|
+
span.link !== undefined;
|
|
360
|
+
if (hasStyles) {
|
|
361
|
+
return currentIdx + 1;
|
|
362
|
+
}
|
|
363
|
+
for (let i = 0; i < span.length; i++) {
|
|
364
|
+
const start = this.charData[currentIdx] & 0x7f_ff;
|
|
365
|
+
const end = currentIdx + 1 < this.length
|
|
366
|
+
? this.charData[currentIdx + 1] & 0x7f_ff
|
|
367
|
+
: this.text.length;
|
|
368
|
+
if (end - start !== 1 || this.text[start] !== ' ') {
|
|
369
|
+
return currentIdx + 1;
|
|
370
|
+
}
|
|
371
|
+
currentIdx--;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
235
374
|
}
|
|
236
|
-
return
|
|
375
|
+
return 0;
|
|
376
|
+
}
|
|
377
|
+
trimEnd() {
|
|
378
|
+
const trimmedLength = this.getTrimmedLength();
|
|
379
|
+
if (trimmedLength === this.length)
|
|
380
|
+
return this;
|
|
381
|
+
if (trimmedLength === 0)
|
|
382
|
+
return new StyledLine();
|
|
383
|
+
return this.slice(0, trimmedLength);
|
|
237
384
|
}
|
|
238
385
|
equals(other) {
|
|
239
386
|
if (this.length !== other.length)
|
|
240
387
|
return false;
|
|
241
|
-
if (this.
|
|
388
|
+
if (this.length === 0)
|
|
389
|
+
return true;
|
|
390
|
+
if (this.getText() !== other.getText())
|
|
242
391
|
return false;
|
|
243
|
-
|
|
392
|
+
const s1 = this.getSpans();
|
|
393
|
+
const s2 = other.getSpans();
|
|
394
|
+
if (s1.length !== s2.length)
|
|
244
395
|
return false;
|
|
245
|
-
for (let i = 0; i <
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
396
|
+
for (let i = 0; i < s1.length; i++) {
|
|
397
|
+
const sp1 = s1[i];
|
|
398
|
+
const sp2 = s2[i];
|
|
399
|
+
if (sp1.length !== sp2.length ||
|
|
400
|
+
sp1.formatFlags !== sp2.formatFlags ||
|
|
401
|
+
sp1.fgColor !== sp2.fgColor ||
|
|
402
|
+
sp1.bgColor !== sp2.bgColor ||
|
|
403
|
+
sp1.link !== sp2.link) {
|
|
253
404
|
return false;
|
|
254
405
|
}
|
|
255
406
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
407
|
+
const thisCharData = this.charData;
|
|
408
|
+
const otherCharData = other.charData;
|
|
409
|
+
if (thisCharData && otherCharData) {
|
|
410
|
+
for (let i = 0; i < this.length; i++) {
|
|
411
|
+
if (thisCharData[i] !== otherCharData[i])
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
259
414
|
}
|
|
260
415
|
return true;
|
|
261
416
|
}
|
|
417
|
+
getText() {
|
|
418
|
+
return this.text ?? '';
|
|
419
|
+
}
|
|
262
420
|
getSpans() {
|
|
263
|
-
return this.spans;
|
|
421
|
+
return this.spans ?? [];
|
|
264
422
|
}
|
|
265
423
|
getValues() {
|
|
266
424
|
return Array.from({ length: this.length }, (_, i) => this.getValue(i));
|
|
267
425
|
}
|
|
268
426
|
*[Symbol.iterator]() {
|
|
427
|
+
if (this.length === 0)
|
|
428
|
+
return;
|
|
269
429
|
let currentSpanIdx = 0;
|
|
270
430
|
let currentSpanPos = 0;
|
|
431
|
+
const spans = this.getSpans();
|
|
271
432
|
for (let i = 0; i < this.length; i++) {
|
|
272
|
-
const span =
|
|
433
|
+
const span = spans[currentSpanIdx];
|
|
273
434
|
const formatFlags = span ? span.formatFlags : 0;
|
|
274
435
|
const isFullWidth = this.getFullWidth(i);
|
|
275
436
|
yield {
|
|
@@ -293,8 +454,143 @@ export class StyledLine {
|
|
|
293
454
|
}
|
|
294
455
|
}
|
|
295
456
|
}
|
|
457
|
+
ensureInitialized(initialCapacity = 16) {
|
|
458
|
+
if (this.charData === undefined) {
|
|
459
|
+
this.text = '';
|
|
460
|
+
this.charData = new Uint16Array(Math.max(this.length, initialCapacity));
|
|
461
|
+
this.spans =
|
|
462
|
+
this.length > 0 ? [{ length: this.length, formatFlags: 0 }] : [];
|
|
463
|
+
if (this.length > 0 && this.text.length === 0) {
|
|
464
|
+
this.text = ' '.repeat(this.length);
|
|
465
|
+
for (let i = 0; i < this.length; i++) {
|
|
466
|
+
this.charData[i] = i;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
applyValuesAndSpans(values, spans) {
|
|
472
|
+
let totalTextLen = 0;
|
|
473
|
+
let visibleChars = 0;
|
|
474
|
+
for (const val of values) {
|
|
475
|
+
if (totalTextLen + val.length > MAX_SAFE_OFFSET - 1) {
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
totalTextLen += val.length;
|
|
479
|
+
visibleChars++;
|
|
480
|
+
}
|
|
481
|
+
const truncated = visibleChars < values.length;
|
|
482
|
+
this.length = visibleChars + (truncated ? 1 : 0);
|
|
483
|
+
this.text = values.slice(0, visibleChars).join('') + (truncated ? '…' : '');
|
|
484
|
+
this.charData = new Uint16Array(Math.max(this.length, 16));
|
|
485
|
+
let currentOffset = 0;
|
|
486
|
+
let spanIdx = 0;
|
|
487
|
+
let spanPos = 0;
|
|
488
|
+
for (let i = 0; i < visibleChars; i++) {
|
|
489
|
+
const val = values[i];
|
|
490
|
+
let isFullWidth = false;
|
|
491
|
+
if (spans.length > 0 && spanIdx < spans.length) {
|
|
492
|
+
const span = spans[spanIdx];
|
|
493
|
+
if ((span.formatFlags & FULL_WIDTH_MASK) !== 0) {
|
|
494
|
+
isFullWidth = true;
|
|
495
|
+
}
|
|
496
|
+
spanPos++;
|
|
497
|
+
if (spanPos >= span.length) {
|
|
498
|
+
spanIdx++;
|
|
499
|
+
spanPos = 0;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
this.charData[i] = currentOffset | (isFullWidth ? 0x80_00 : 0);
|
|
503
|
+
currentOffset += val.length;
|
|
504
|
+
}
|
|
505
|
+
if (truncated) {
|
|
506
|
+
this.charData[visibleChars] = currentOffset;
|
|
507
|
+
}
|
|
508
|
+
if (truncated) {
|
|
509
|
+
const newSpans = [];
|
|
510
|
+
let remaining = visibleChars;
|
|
511
|
+
let sIdx = 0;
|
|
512
|
+
while (remaining > 0 && sIdx < spans.length) {
|
|
513
|
+
const span = spans[sIdx];
|
|
514
|
+
const take = Math.min(remaining, span.length);
|
|
515
|
+
newSpans.push({ ...span, length: take });
|
|
516
|
+
remaining -= take;
|
|
517
|
+
sIdx++;
|
|
518
|
+
}
|
|
519
|
+
newSpans.push({ length: 1, formatFlags: 0 });
|
|
520
|
+
this.spans = newSpans;
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
this.spans = spans.map(s => ({
|
|
524
|
+
...s,
|
|
525
|
+
formatFlags: s.formatFlags & ~FULL_WIDTH_MASK,
|
|
526
|
+
}));
|
|
527
|
+
}
|
|
528
|
+
this.mergeSpans();
|
|
529
|
+
}
|
|
530
|
+
instanceConcat(other) {
|
|
531
|
+
const spaceForOther = MAX_SAFE_OFFSET - 1 - this.getText().length;
|
|
532
|
+
if (spaceForOther <= 0) {
|
|
533
|
+
if (this.getText().length < MAX_SAFE_OFFSET &&
|
|
534
|
+
!this.getText().endsWith('…')) {
|
|
535
|
+
const result = this.clone();
|
|
536
|
+
result.pushChar('…', 0);
|
|
537
|
+
return result;
|
|
538
|
+
}
|
|
539
|
+
return this.clone();
|
|
540
|
+
}
|
|
541
|
+
let otherTextLenToTake = 0;
|
|
542
|
+
let otherCharsToTake = 0;
|
|
543
|
+
for (let i = 0; i < other.length; i++) {
|
|
544
|
+
const val = other.getValue(i);
|
|
545
|
+
if (otherTextLenToTake + val.length > spaceForOther) {
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
otherTextLenToTake += val.length;
|
|
549
|
+
otherCharsToTake++;
|
|
550
|
+
}
|
|
551
|
+
const truncated = otherCharsToTake < other.length;
|
|
552
|
+
const result = new StyledLine();
|
|
553
|
+
result.length = this.length + otherCharsToTake + (truncated ? 1 : 0);
|
|
554
|
+
result.text =
|
|
555
|
+
this.getText() +
|
|
556
|
+
other.getText().slice(0, otherTextLenToTake) +
|
|
557
|
+
(truncated ? '…' : '');
|
|
558
|
+
result.charData = new Uint16Array(Math.max(result.length, 16));
|
|
559
|
+
if (this.charData) {
|
|
560
|
+
result.charData.set(this.charData.subarray(0, this.length), 0);
|
|
561
|
+
}
|
|
562
|
+
const textOffset = this.getText().length;
|
|
563
|
+
const otherCharData = other.charData;
|
|
564
|
+
if (otherCharData) {
|
|
565
|
+
for (let i = 0; i < otherCharsToTake; i++) {
|
|
566
|
+
const oldData = otherCharData[i];
|
|
567
|
+
const oldOffset = oldData & 0x7f_ff;
|
|
568
|
+
const fw = oldData & 0x80_00;
|
|
569
|
+
result.charData[this.length + i] = (oldOffset + textOffset) | fw;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (truncated) {
|
|
573
|
+
result.charData[this.length + otherCharsToTake] =
|
|
574
|
+
this.getText().length + otherTextLenToTake;
|
|
575
|
+
}
|
|
576
|
+
const otherSpans = [];
|
|
577
|
+
let remaining = otherCharsToTake;
|
|
578
|
+
for (const span of other.getSpans()) {
|
|
579
|
+
if (remaining <= 0)
|
|
580
|
+
break;
|
|
581
|
+
const take = Math.min(remaining, span.length);
|
|
582
|
+
otherSpans.push({ ...span, length: take });
|
|
583
|
+
remaining -= take;
|
|
584
|
+
}
|
|
585
|
+
result.spans = [...this.getSpans(), ...otherSpans];
|
|
586
|
+
if (truncated) {
|
|
587
|
+
result.spans.push({ length: 1, formatFlags: 0 });
|
|
588
|
+
}
|
|
589
|
+
result.mergeSpans();
|
|
590
|
+
return result;
|
|
591
|
+
}
|
|
296
592
|
splitSpansAt(index) {
|
|
297
|
-
if (index <= 0 || index >= this.length)
|
|
593
|
+
if (this.spans === undefined || index <= 0 || index >= this.length)
|
|
298
594
|
return;
|
|
299
595
|
let current = 0;
|
|
300
596
|
for (let i = 0; i < this.spans.length; i++) {
|
|
@@ -309,6 +605,8 @@ export class StyledLine {
|
|
|
309
605
|
}
|
|
310
606
|
}
|
|
311
607
|
mergeSpans() {
|
|
608
|
+
if (this.spans === undefined)
|
|
609
|
+
return;
|
|
312
610
|
const newSpans = [];
|
|
313
611
|
for (const span of this.spans) {
|
|
314
612
|
if (span.length === 0)
|
|
@@ -328,85 +626,4 @@ export class StyledLine {
|
|
|
328
626
|
this.spans = newSpans;
|
|
329
627
|
}
|
|
330
628
|
}
|
|
331
|
-
export class StyledChar {
|
|
332
|
-
_value;
|
|
333
|
-
_formatFlags;
|
|
334
|
-
_fgColor;
|
|
335
|
-
_bgColor;
|
|
336
|
-
_link;
|
|
337
|
-
// eslint-disable-next-line max-params
|
|
338
|
-
constructor(_value, _formatFlags, _fgColor, _bgColor, _link) {
|
|
339
|
-
this._value = _value;
|
|
340
|
-
this._formatFlags = _formatFlags;
|
|
341
|
-
this._fgColor = _fgColor;
|
|
342
|
-
this._bgColor = _bgColor;
|
|
343
|
-
this._link = _link;
|
|
344
|
-
}
|
|
345
|
-
getValue() {
|
|
346
|
-
return this._value;
|
|
347
|
-
}
|
|
348
|
-
getFullWidth() {
|
|
349
|
-
return (this._formatFlags & FULL_WIDTH_MASK) !== 0;
|
|
350
|
-
}
|
|
351
|
-
getForegroundColor() {
|
|
352
|
-
return this._fgColor;
|
|
353
|
-
}
|
|
354
|
-
getBackgroundColor() {
|
|
355
|
-
return this._bgColor;
|
|
356
|
-
}
|
|
357
|
-
getBold() {
|
|
358
|
-
return (this._formatFlags & BOLD_MASK) !== 0;
|
|
359
|
-
}
|
|
360
|
-
getDim() {
|
|
361
|
-
return (this._formatFlags & DIM_MASK) !== 0;
|
|
362
|
-
}
|
|
363
|
-
getItalic() {
|
|
364
|
-
return (this._formatFlags & ITALIC_MASK) !== 0;
|
|
365
|
-
}
|
|
366
|
-
getUnderline() {
|
|
367
|
-
return (this._formatFlags & UNDERLINE_MASK) !== 0;
|
|
368
|
-
}
|
|
369
|
-
getStrikethrough() {
|
|
370
|
-
return (this._formatFlags & STRIKETHROUGH_MASK) !== 0;
|
|
371
|
-
}
|
|
372
|
-
getInverse() {
|
|
373
|
-
return (this._formatFlags & INVERSE_MASK) !== 0;
|
|
374
|
-
}
|
|
375
|
-
getHidden() {
|
|
376
|
-
return (this._formatFlags & HIDDEN_MASK) !== 0;
|
|
377
|
-
}
|
|
378
|
-
getLink() {
|
|
379
|
-
return this._link;
|
|
380
|
-
}
|
|
381
|
-
get formatFlags() {
|
|
382
|
-
return this._formatFlags;
|
|
383
|
-
}
|
|
384
|
-
get fgColor() {
|
|
385
|
-
return this._fgColor;
|
|
386
|
-
}
|
|
387
|
-
get bgColor() {
|
|
388
|
-
return this._bgColor;
|
|
389
|
-
}
|
|
390
|
-
get link() {
|
|
391
|
-
return this._link;
|
|
392
|
-
}
|
|
393
|
-
setFormatFlag(mask) {
|
|
394
|
-
this._formatFlags |= mask;
|
|
395
|
-
}
|
|
396
|
-
clearFormatFlag(mask) {
|
|
397
|
-
this._formatFlags &= ~mask;
|
|
398
|
-
}
|
|
399
|
-
setBackgroundColor(color) {
|
|
400
|
-
this._bgColor = color;
|
|
401
|
-
}
|
|
402
|
-
hasStyles() {
|
|
403
|
-
return ((this._formatFlags & ~FULL_WIDTH_MASK) !== 0 ||
|
|
404
|
-
this._fgColor !== undefined ||
|
|
405
|
-
this._bgColor !== undefined ||
|
|
406
|
-
this._link !== undefined);
|
|
407
|
-
}
|
|
408
|
-
copyWith(overrides) {
|
|
409
|
-
return new StyledChar(overrides.value ?? this._value, this._formatFlags, this._fgColor, this._bgColor, this._link);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
629
|
//# sourceMappingURL=styled-line.js.map
|