@opentui/core 0.0.0-20251112-613689c1 → 0.0.0-20251128-0889a764

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/index.js CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  LinearScrollAccel,
20
20
  LogLevel,
21
21
  MacOSScrollAccel,
22
+ MeasureMode,
22
23
  MouseButton,
23
24
  MouseEvent,
24
25
  MouseParser,
@@ -136,7 +137,7 @@ import {
136
137
  white,
137
138
  wrapWithDelegates,
138
139
  yellow
139
- } from "./index-y49e47t2.js";
140
+ } from "./index-rhx7c7kj.js";
140
141
  // src/text-buffer-view.ts
141
142
  class TextBufferView {
142
143
  lib;
@@ -234,6 +235,10 @@ class TextBufferView {
234
235
  this.guard();
235
236
  this.lib.textBufferViewSetTabIndicatorColor(this.viewPtr, color);
236
237
  }
238
+ measureForDimensions(width, height) {
239
+ this.guard();
240
+ return this.lib.textBufferViewMeasureForDimensions(this.viewPtr, width, height);
241
+ }
237
242
  destroy() {
238
243
  if (this._destroyed)
239
244
  return;
@@ -319,6 +324,10 @@ class EditBuffer extends EventEmitter {
319
324
  const textBytes = this.lib.encoder.encode(text);
320
325
  this.lib.editBufferSetText(this.bufferPtr, textBytes, history);
321
326
  }
327
+ getLineCount() {
328
+ this.guard();
329
+ return this.lib.textBufferGetLineCount(this.textBufferPtr);
330
+ }
322
331
  getText() {
323
332
  this.guard();
324
333
  const maxSize = 1024 * 1024;
@@ -551,6 +560,7 @@ class EditorView {
551
560
  editBuffer;
552
561
  _destroyed = false;
553
562
  _extmarksController;
563
+ _textBufferViewPtr;
554
564
  constructor(lib, ptr, editBuffer) {
555
565
  this.lib = lib;
556
566
  this.viewPtr = ptr;
@@ -696,6 +706,13 @@ class EditorView {
696
706
  this.guard();
697
707
  this.lib.editorViewSetTabIndicatorColor(this.viewPtr, color);
698
708
  }
709
+ measureForDimensions(width, height) {
710
+ this.guard();
711
+ if (!this._textBufferViewPtr) {
712
+ this._textBufferViewPtr = this.lib.editorViewGetTextBufferView(this.viewPtr);
713
+ }
714
+ return this.lib.textBufferViewMeasureForDimensions(this._textBufferViewPtr, width, height);
715
+ }
699
716
  destroy() {
700
717
  if (this._destroyed)
701
718
  return;
@@ -2405,7 +2422,6 @@ class TextBufferRenderable extends Renderable {
2405
2422
  _tabIndicatorColor;
2406
2423
  textBuffer;
2407
2424
  textBufferView;
2408
- _lineInfo = { lineStarts: [], lineWidths: [], maxLineWidth: 0 };
2409
2425
  _defaultOptions = {
2410
2426
  fg: RGBA.fromValues(1, 1, 1, 1),
2411
2427
  bg: RGBA.fromValues(0, 0, 0, 0),
@@ -2444,10 +2460,19 @@ class TextBufferRenderable extends Renderable {
2444
2460
  this.textBufferView.setTabIndicatorColor(this._tabIndicatorColor);
2445
2461
  }
2446
2462
  if (this._wrapMode !== "none" && this.width > 0) {
2447
- this.updateWrapWidth(this.width);
2463
+ this.textBufferView.setWrapWidth(this.width);
2448
2464
  }
2449
2465
  this.updateTextInfo();
2450
2466
  }
2467
+ get lineInfo() {
2468
+ return this.textBufferView.logicalLineInfo;
2469
+ }
2470
+ get lineCount() {
2471
+ return this.textBuffer.getLineCount();
2472
+ }
2473
+ get scrollY() {
2474
+ return 0;
2475
+ }
2451
2476
  get plainText() {
2452
2477
  return this.textBuffer.getPlainText();
2453
2478
  }
@@ -2523,7 +2548,7 @@ class TextBufferRenderable extends Renderable {
2523
2548
  this._wrapMode = value;
2524
2549
  this.textBufferView.setWrapMode(this._wrapMode);
2525
2550
  if (value !== "none" && this.width > 0) {
2526
- this.updateWrapWidth(this.width);
2551
+ this.textBufferView.setWrapWidth(this.width);
2527
2552
  }
2528
2553
  this.yogaNode.markDirty();
2529
2554
  this.requestRender();
@@ -2582,30 +2607,29 @@ class TextBufferRenderable extends Renderable {
2582
2607
  }
2583
2608
  this.yogaNode.markDirty();
2584
2609
  this.requestRender();
2585
- }
2586
- updateLineInfo() {
2587
- const lineInfo = this.textBufferView.logicalLineInfo;
2588
- this._lineInfo.lineStarts = lineInfo.lineStarts;
2589
- this._lineInfo.lineWidths = lineInfo.lineWidths;
2590
- this._lineInfo.maxLineWidth = lineInfo.maxLineWidth;
2591
- }
2592
- updateWrapWidth(width) {
2593
- this.textBufferView.setWrapWidth(width);
2594
- this.updateLineInfo();
2610
+ this.emit("line-info-change");
2595
2611
  }
2596
2612
  setupMeasureFunc() {
2597
2613
  const measureFunc = (width, widthMode, height, heightMode) => {
2598
- const effectiveWidth = isNaN(width) ? 1 : width;
2599
- if (this._wrapMode !== "none" && this.width !== effectiveWidth) {
2600
- this.updateWrapWidth(effectiveWidth);
2614
+ let effectiveWidth;
2615
+ if (widthMode === MeasureMode.Undefined || isNaN(width)) {
2616
+ effectiveWidth = 0;
2601
2617
  } else {
2602
- this.updateLineInfo();
2618
+ effectiveWidth = width;
2619
+ }
2620
+ const effectiveHeight = isNaN(height) ? 1 : height;
2621
+ const measureResult = this.textBufferView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
2622
+ const measuredWidth = measureResult ? Math.max(1, measureResult.maxWidth) : 1;
2623
+ const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
2624
+ if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
2625
+ return {
2626
+ width: Math.min(effectiveWidth, measuredWidth),
2627
+ height: Math.min(effectiveHeight, measuredHeight)
2628
+ };
2603
2629
  }
2604
- const measuredWidth = this._lineInfo.maxLineWidth;
2605
- const measuredHeight = this._lineInfo.lineStarts.length;
2606
2630
  return {
2607
- width: Math.max(1, measuredWidth),
2608
- height: Math.max(1, measuredHeight)
2631
+ width: measuredWidth,
2632
+ height: measuredHeight
2609
2633
  };
2610
2634
  };
2611
2635
  this.yogaNode.setMeasureFunc(measureFunc);
@@ -2690,6 +2714,10 @@ class CodeRenderable extends TextBufferRenderable {
2690
2714
  this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
2691
2715
  this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText;
2692
2716
  this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
2717
+ if (this._content.length > 0 && (this._drawUnstyledText || !this._filetype)) {
2718
+ this.textBuffer.setText(this._content);
2719
+ this.updateTextInfo();
2720
+ }
2693
2721
  this._highlightsDirty = this._content.length > 0;
2694
2722
  }
2695
2723
  get content() {
@@ -2699,6 +2727,10 @@ class CodeRenderable extends TextBufferRenderable {
2699
2727
  if (this._content !== value) {
2700
2728
  this._content = value;
2701
2729
  this._highlightsDirty = true;
2730
+ if (this._drawUnstyledText || !this._filetype) {
2731
+ this.textBuffer.setText(value);
2732
+ this.updateTextInfo();
2733
+ }
2702
2734
  }
2703
2735
  }
2704
2736
  get filetype() {
@@ -3180,197 +3212,1953 @@ class VRenderable extends Renderable {
3180
3212
  }
3181
3213
  }
3182
3214
  }
3183
- // src/renderables/Input.ts
3184
- var InputRenderableEvents;
3185
- ((InputRenderableEvents2) => {
3186
- InputRenderableEvents2["INPUT"] = "input";
3187
- InputRenderableEvents2["CHANGE"] = "change";
3188
- InputRenderableEvents2["ENTER"] = "enter";
3189
- })(InputRenderableEvents ||= {});
3190
-
3191
- class InputRenderable extends Renderable {
3192
- _focusable = true;
3193
- _value = "";
3194
- _cursorPosition = 0;
3195
- _placeholder;
3196
- _backgroundColor;
3197
- _textColor;
3198
- _focusedBackgroundColor;
3199
- _focusedTextColor;
3200
- _placeholderColor;
3201
- _cursorColor;
3202
- _cursorStyle;
3203
- _maxLength;
3204
- _lastCommittedValue = "";
3205
- _defaultOptions = {
3206
- backgroundColor: "transparent",
3207
- textColor: "#FFFFFF",
3208
- focusedBackgroundColor: "#1a1a1a",
3209
- focusedTextColor: "#FFFFFF",
3210
- placeholder: "",
3211
- placeholderColor: "#666666",
3212
- cursorColor: "#FFFFFF",
3213
- cursorStyle: {
3214
- style: "block",
3215
- blinking: true
3216
- },
3217
- maxLength: 1000,
3218
- value: ""
3219
- };
3220
- constructor(ctx, options) {
3221
- super(ctx, { ...options, buffered: true });
3222
- this._backgroundColor = parseColor(options.backgroundColor || this._defaultOptions.backgroundColor);
3223
- this._textColor = parseColor(options.textColor || this._defaultOptions.textColor);
3224
- this._focusedBackgroundColor = parseColor(options.focusedBackgroundColor || options.backgroundColor || this._defaultOptions.focusedBackgroundColor);
3225
- this._focusedTextColor = parseColor(options.focusedTextColor || options.textColor || this._defaultOptions.focusedTextColor);
3226
- this._placeholder = options.placeholder || this._defaultOptions.placeholder;
3227
- this._value = options.value || this._defaultOptions.value;
3228
- this._lastCommittedValue = this._value;
3229
- this._cursorPosition = this._value.length;
3230
- this._maxLength = options.maxLength || this._defaultOptions.maxLength;
3231
- this._placeholderColor = parseColor(options.placeholderColor || this._defaultOptions.placeholderColor);
3232
- this._cursorColor = parseColor(options.cursorColor || this._defaultOptions.cursorColor);
3233
- this._cursorStyle = options.cursorStyle || this._defaultOptions.cursorStyle;
3215
+ // src/renderables/LineNumberRenderable.ts
3216
+ class GutterRenderable extends Renderable {
3217
+ target;
3218
+ _fg;
3219
+ _bg;
3220
+ _minWidth;
3221
+ _paddingRight;
3222
+ _lineColorsGutter;
3223
+ _lineColorsContent;
3224
+ _lineSigns;
3225
+ _lineNumberOffset;
3226
+ _hideLineNumbers;
3227
+ _lineNumbers;
3228
+ _maxBeforeWidth = 0;
3229
+ _maxAfterWidth = 0;
3230
+ _lastKnownLineCount = 0;
3231
+ _lastKnownScrollY = 0;
3232
+ constructor(ctx, target, options) {
3233
+ super(ctx, {
3234
+ id: options.id,
3235
+ width: "auto",
3236
+ height: "auto",
3237
+ flexGrow: 0,
3238
+ flexShrink: 0,
3239
+ buffered: options.buffered
3240
+ });
3241
+ this.target = target;
3242
+ this._fg = options.fg;
3243
+ this._bg = options.bg;
3244
+ this._minWidth = options.minWidth;
3245
+ this._paddingRight = options.paddingRight;
3246
+ this._lineColorsGutter = options.lineColorsGutter;
3247
+ this._lineColorsContent = options.lineColorsContent;
3248
+ this._lineSigns = options.lineSigns;
3249
+ this._lineNumberOffset = options.lineNumberOffset;
3250
+ this._hideLineNumbers = options.hideLineNumbers;
3251
+ this._lineNumbers = options.lineNumbers ?? new Map;
3252
+ this._lastKnownLineCount = this.target.lineCount;
3253
+ this._lastKnownScrollY = this.target.scrollY;
3254
+ this.calculateSignWidths();
3255
+ this.setupMeasureFunc();
3256
+ this.onLifecyclePass = () => {
3257
+ const currentLineCount = this.target.lineCount;
3258
+ if (currentLineCount !== this._lastKnownLineCount) {
3259
+ this._lastKnownLineCount = currentLineCount;
3260
+ this.yogaNode.markDirty();
3261
+ this.requestRender();
3262
+ }
3263
+ };
3234
3264
  }
3235
- updateCursorPosition() {
3236
- if (!this._focused)
3237
- return;
3238
- const contentX = 0;
3239
- const contentY = 0;
3240
- const contentWidth = this.width;
3241
- const maxVisibleChars = contentWidth - 1;
3242
- let displayStartIndex = 0;
3243
- if (this._cursorPosition >= maxVisibleChars) {
3244
- displayStartIndex = this._cursorPosition - maxVisibleChars + 1;
3265
+ setupMeasureFunc() {
3266
+ const measureFunc = (width, widthMode, height, heightMode) => {
3267
+ const gutterWidth = this.calculateWidth();
3268
+ const gutterHeight = this.target.lineCount;
3269
+ return {
3270
+ width: gutterWidth,
3271
+ height: gutterHeight
3272
+ };
3273
+ };
3274
+ this.yogaNode.setMeasureFunc(measureFunc);
3275
+ }
3276
+ remeasure() {
3277
+ this.yogaNode.markDirty();
3278
+ }
3279
+ calculateSignWidths() {
3280
+ this._maxBeforeWidth = 0;
3281
+ this._maxAfterWidth = 0;
3282
+ for (const sign of this._lineSigns.values()) {
3283
+ if (sign.before) {
3284
+ const width = Bun.stringWidth(sign.before);
3285
+ this._maxBeforeWidth = Math.max(this._maxBeforeWidth, width);
3286
+ }
3287
+ if (sign.after) {
3288
+ const width = Bun.stringWidth(sign.after);
3289
+ this._maxAfterWidth = Math.max(this._maxAfterWidth, width);
3290
+ }
3245
3291
  }
3246
- const cursorDisplayX = this._cursorPosition - displayStartIndex;
3247
- if (cursorDisplayX >= 0 && cursorDisplayX < contentWidth) {
3248
- const absoluteCursorX = this.x + contentX + cursorDisplayX + 1;
3249
- const absoluteCursorY = this.y + contentY + 1;
3250
- this._ctx.setCursorPosition(absoluteCursorX, absoluteCursorY, true);
3251
- this._ctx.setCursorColor(this._cursorColor);
3292
+ }
3293
+ calculateWidth() {
3294
+ const totalLines = this.target.lineCount;
3295
+ let maxLineNumber = totalLines + this._lineNumberOffset;
3296
+ if (this._lineNumbers.size > 0) {
3297
+ for (const customLineNum of this._lineNumbers.values()) {
3298
+ maxLineNumber = Math.max(maxLineNumber, customLineNum);
3299
+ }
3252
3300
  }
3301
+ const digits = maxLineNumber > 0 ? Math.floor(Math.log10(maxLineNumber)) + 1 : 1;
3302
+ const baseWidth = Math.max(this._minWidth, digits + this._paddingRight + 1);
3303
+ return baseWidth + this._maxBeforeWidth + this._maxAfterWidth;
3253
3304
  }
3254
- focus() {
3255
- super.focus();
3256
- this._ctx.setCursorStyle(this._cursorStyle.style, this._cursorStyle.blinking);
3257
- this._ctx.setCursorColor(this._cursorColor);
3258
- this.updateCursorPosition();
3305
+ setLineColors(lineColorsGutter, lineColorsContent) {
3306
+ this._lineColorsGutter = lineColorsGutter;
3307
+ this._lineColorsContent = lineColorsContent;
3308
+ this.requestRender();
3259
3309
  }
3260
- blur() {
3261
- super.blur();
3262
- this._ctx.setCursorPosition(0, 0, false);
3263
- if (this._value !== this._lastCommittedValue) {
3264
- this._lastCommittedValue = this._value;
3265
- this.emit("change" /* CHANGE */, this._value);
3310
+ getLineColors() {
3311
+ return {
3312
+ gutter: this._lineColorsGutter,
3313
+ content: this._lineColorsContent
3314
+ };
3315
+ }
3316
+ setLineSigns(lineSigns) {
3317
+ const oldMaxBefore = this._maxBeforeWidth;
3318
+ const oldMaxAfter = this._maxAfterWidth;
3319
+ this._lineSigns = lineSigns;
3320
+ this.calculateSignWidths();
3321
+ if (this._maxBeforeWidth !== oldMaxBefore || this._maxAfterWidth !== oldMaxAfter) {
3322
+ this.yogaNode.markDirty();
3266
3323
  }
3324
+ this.requestRender();
3267
3325
  }
3268
- renderSelf(buffer, deltaTime) {
3269
- if (!this.visible || !this.frameBuffer)
3326
+ getLineSigns() {
3327
+ return this._lineSigns;
3328
+ }
3329
+ renderSelf(buffer) {
3330
+ const currentScrollY = this.target.scrollY;
3331
+ const scrollChanged = currentScrollY !== this._lastKnownScrollY;
3332
+ if (this.buffered && !this.isDirty && !scrollChanged) {
3270
3333
  return;
3271
- if (this.isDirty) {
3272
- this.refreshFrameBuffer();
3273
3334
  }
3335
+ this._lastKnownScrollY = currentScrollY;
3336
+ this.refreshFrameBuffer(buffer);
3274
3337
  }
3275
- refreshFrameBuffer() {
3276
- if (!this.frameBuffer)
3338
+ refreshFrameBuffer(buffer) {
3339
+ const startX = this.buffered ? 0 : this.x;
3340
+ const startY = this.buffered ? 0 : this.y;
3341
+ if (this.buffered) {
3342
+ buffer.clear(this._bg);
3343
+ } else if (this._bg.a > 0) {
3344
+ buffer.fillRect(startX, startY, this.width, this.height, this._bg);
3345
+ }
3346
+ const lineInfo = this.target.lineInfo;
3347
+ if (!lineInfo || !lineInfo.lineSources)
3277
3348
  return;
3278
- const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
3279
- this.frameBuffer.clear(bgColor);
3280
- const contentX = 0;
3281
- const contentY = 0;
3282
- const contentWidth = this.width;
3283
- const contentHeight = this.height;
3284
- const displayText = this._value || this._placeholder;
3285
- const isPlaceholder = !this._value && this._placeholder;
3286
- const baseTextColor = this._focused ? this._focusedTextColor : this._textColor;
3287
- const textColor = isPlaceholder ? this._placeholderColor : baseTextColor;
3288
- const maxVisibleChars = contentWidth - 1;
3289
- let displayStartIndex = 0;
3290
- if (this._cursorPosition >= maxVisibleChars) {
3291
- displayStartIndex = this._cursorPosition - maxVisibleChars + 1;
3349
+ const sources = lineInfo.lineSources;
3350
+ let lastSource = -1;
3351
+ const startLine = this.target.scrollY;
3352
+ if (startLine >= sources.length)
3353
+ return;
3354
+ lastSource = startLine > 0 ? sources[startLine - 1] : -1;
3355
+ for (let i = 0;i < this.height; i++) {
3356
+ const visualLineIndex = startLine + i;
3357
+ if (visualLineIndex >= sources.length)
3358
+ break;
3359
+ const logicalLine = sources[visualLineIndex];
3360
+ const lineBg = this._lineColorsGutter.get(logicalLine) ?? this._bg;
3361
+ if (lineBg !== this._bg) {
3362
+ buffer.fillRect(startX, startY + i, this.width, 1, lineBg);
3363
+ }
3364
+ if (logicalLine === lastSource) {} else {
3365
+ let currentX = startX;
3366
+ const sign = this._lineSigns.get(logicalLine);
3367
+ if (sign?.before) {
3368
+ const beforeWidth = Bun.stringWidth(sign.before);
3369
+ const padding = this._maxBeforeWidth - beforeWidth;
3370
+ currentX += padding;
3371
+ const beforeColor = sign.beforeColor ? parseColor(sign.beforeColor) : this._fg;
3372
+ buffer.drawText(sign.before, currentX, startY + i, beforeColor, lineBg);
3373
+ currentX += beforeWidth;
3374
+ } else if (this._maxBeforeWidth > 0) {
3375
+ currentX += this._maxBeforeWidth;
3376
+ }
3377
+ if (!this._hideLineNumbers.has(logicalLine)) {
3378
+ const customLineNum = this._lineNumbers.get(logicalLine);
3379
+ const lineNum = customLineNum !== undefined ? customLineNum : logicalLine + 1 + this._lineNumberOffset;
3380
+ const lineNumStr = lineNum.toString();
3381
+ const lineNumWidth = lineNumStr.length;
3382
+ const availableSpace = this.width - this._maxBeforeWidth - this._maxAfterWidth - this._paddingRight;
3383
+ const lineNumX = startX + this._maxBeforeWidth + 1 + availableSpace - lineNumWidth - 1;
3384
+ if (lineNumX >= startX + this._maxBeforeWidth + 1) {
3385
+ buffer.drawText(lineNumStr, lineNumX, startY + i, this._fg, lineBg);
3386
+ }
3387
+ }
3388
+ if (sign?.after) {
3389
+ const afterX = startX + this.width - this._paddingRight - this._maxAfterWidth;
3390
+ const afterColor = sign.afterColor ? parseColor(sign.afterColor) : this._fg;
3391
+ buffer.drawText(sign.after, afterX, startY + i, afterColor, lineBg);
3392
+ }
3393
+ }
3394
+ lastSource = logicalLine;
3292
3395
  }
3293
- const visibleText = displayText.substring(displayStartIndex, displayStartIndex + maxVisibleChars);
3294
- if (visibleText) {
3295
- this.frameBuffer.drawText(visibleText, contentX, contentY, textColor);
3396
+ }
3397
+ }
3398
+ function darkenColor(color) {
3399
+ return RGBA.fromValues(color.r * 0.8, color.g * 0.8, color.b * 0.8, color.a);
3400
+ }
3401
+
3402
+ class LineNumberRenderable extends Renderable {
3403
+ gutter = null;
3404
+ target = null;
3405
+ _lineColorsGutter;
3406
+ _lineColorsContent;
3407
+ _lineSigns;
3408
+ _fg;
3409
+ _bg;
3410
+ _minWidth;
3411
+ _paddingRight;
3412
+ _lineNumberOffset;
3413
+ _hideLineNumbers;
3414
+ _lineNumbers;
3415
+ _isDestroying = false;
3416
+ handleLineInfoChange = () => {
3417
+ this.gutter?.remeasure();
3418
+ this.requestRender();
3419
+ };
3420
+ parseLineColor(line, color) {
3421
+ if (typeof color === "object" && "gutter" in color) {
3422
+ const config = color;
3423
+ if (config.gutter) {
3424
+ this._lineColorsGutter.set(line, parseColor(config.gutter));
3425
+ }
3426
+ if (config.content) {
3427
+ this._lineColorsContent.set(line, parseColor(config.content));
3428
+ } else if (config.gutter) {
3429
+ this._lineColorsContent.set(line, darkenColor(parseColor(config.gutter)));
3430
+ }
3431
+ } else {
3432
+ const parsedColor = parseColor(color);
3433
+ this._lineColorsGutter.set(line, parsedColor);
3434
+ this._lineColorsContent.set(line, darkenColor(parsedColor));
3296
3435
  }
3297
- if (this._focused) {
3298
- this.updateCursorPosition();
3436
+ }
3437
+ constructor(ctx, options) {
3438
+ super(ctx, {
3439
+ ...options,
3440
+ flexDirection: "row",
3441
+ height: "auto"
3442
+ });
3443
+ this._fg = parseColor(options.fg ?? "#888888");
3444
+ this._bg = parseColor(options.bg ?? "transparent");
3445
+ this._minWidth = options.minWidth ?? 3;
3446
+ this._paddingRight = options.paddingRight ?? 1;
3447
+ this._lineNumberOffset = options.lineNumberOffset ?? 0;
3448
+ this._hideLineNumbers = options.hideLineNumbers ?? new Set;
3449
+ this._lineNumbers = options.lineNumbers ?? new Map;
3450
+ this._lineColorsGutter = new Map;
3451
+ this._lineColorsContent = new Map;
3452
+ if (options.lineColors) {
3453
+ for (const [line, color] of options.lineColors) {
3454
+ this.parseLineColor(line, color);
3455
+ }
3456
+ }
3457
+ this._lineSigns = new Map;
3458
+ if (options.lineSigns) {
3459
+ for (const [line, sign] of options.lineSigns) {
3460
+ this._lineSigns.set(line, sign);
3461
+ }
3462
+ }
3463
+ if (options.target) {
3464
+ this.setTarget(options.target);
3299
3465
  }
3300
3466
  }
3301
- get value() {
3302
- return this._value;
3467
+ setTarget(target) {
3468
+ if (this.target === target)
3469
+ return;
3470
+ if (this.target) {
3471
+ this.target.off("line-info-change", this.handleLineInfoChange);
3472
+ super.remove(this.target.id);
3473
+ }
3474
+ if (this.gutter) {
3475
+ super.remove(this.gutter.id);
3476
+ this.gutter = null;
3477
+ }
3478
+ this.target = target;
3479
+ this.target.on("line-info-change", this.handleLineInfoChange);
3480
+ this.gutter = new GutterRenderable(this.ctx, this.target, {
3481
+ fg: this._fg,
3482
+ bg: this._bg,
3483
+ minWidth: this._minWidth,
3484
+ paddingRight: this._paddingRight,
3485
+ lineColorsGutter: this._lineColorsGutter,
3486
+ lineColorsContent: this._lineColorsContent,
3487
+ lineSigns: this._lineSigns,
3488
+ lineNumberOffset: this._lineNumberOffset,
3489
+ hideLineNumbers: this._hideLineNumbers,
3490
+ lineNumbers: this._lineNumbers,
3491
+ id: this.id ? `${this.id}-gutter` : undefined,
3492
+ buffered: true
3493
+ });
3494
+ super.add(this.gutter);
3495
+ super.add(this.target);
3303
3496
  }
3304
- set value(value) {
3305
- const newValue = value.substring(0, this._maxLength);
3306
- if (this._value !== newValue) {
3307
- this._value = newValue;
3308
- this._cursorPosition = Math.min(this._cursorPosition, this._value.length);
3309
- this.requestRender();
3310
- this.updateCursorPosition();
3311
- this.emit("input" /* INPUT */, this._value);
3497
+ add(child) {
3498
+ if (!this.target && "lineInfo" in child && "lineCount" in child && "scrollY" in child) {
3499
+ this.setTarget(child);
3500
+ return this.getChildrenCount() - 1;
3312
3501
  }
3502
+ return -1;
3313
3503
  }
3314
- set placeholder(placeholder) {
3315
- if (this._placeholder !== placeholder) {
3316
- this._placeholder = placeholder;
3317
- this.requestRender();
3504
+ remove(id) {
3505
+ if (this._isDestroying) {
3506
+ super.remove(id);
3507
+ return;
3508
+ }
3509
+ if (this.gutter && id === this.gutter.id) {
3510
+ throw new Error("LineNumberRenderable: Cannot remove gutter directly.");
3318
3511
  }
3512
+ if (this.target && id === this.target.id) {
3513
+ throw new Error("LineNumberRenderable: Cannot remove target directly. Use clearTarget() instead.");
3514
+ }
3515
+ super.remove(id);
3319
3516
  }
3320
- get cursorPosition() {
3321
- return this._cursorPosition;
3517
+ destroyRecursively() {
3518
+ this._isDestroying = true;
3519
+ if (this.target) {
3520
+ this.target.off("line-info-change", this.handleLineInfoChange);
3521
+ }
3522
+ super.destroyRecursively();
3523
+ this.gutter = null;
3524
+ this.target = null;
3322
3525
  }
3323
- set cursorPosition(position) {
3324
- const newPosition = Math.max(0, Math.min(position, this._value.length));
3325
- if (this._cursorPosition !== newPosition) {
3326
- this._cursorPosition = newPosition;
3327
- this.requestRender();
3328
- this.updateCursorPosition();
3526
+ clearTarget() {
3527
+ if (this.target) {
3528
+ this.target.off("line-info-change", this.handleLineInfoChange);
3529
+ super.remove(this.target.id);
3530
+ this.target = null;
3531
+ }
3532
+ if (this.gutter) {
3533
+ super.remove(this.gutter.id);
3534
+ this.gutter = null;
3329
3535
  }
3330
3536
  }
3331
- insertText(text) {
3332
- if (this._value.length + text.length > this._maxLength) {
3537
+ renderSelf(buffer) {
3538
+ if (!this.target || !this.gutter)
3333
3539
  return;
3540
+ const lineInfo = this.target.lineInfo;
3541
+ if (!lineInfo || !lineInfo.lineSources)
3542
+ return;
3543
+ const sources = lineInfo.lineSources;
3544
+ const startLine = this.target.scrollY;
3545
+ if (startLine >= sources.length)
3546
+ return;
3547
+ const gutterWidth = this.gutter.visible ? this.gutter.width : 0;
3548
+ const contentWidth = this.width - gutterWidth;
3549
+ for (let i = 0;i < this.height; i++) {
3550
+ const visualLineIndex = startLine + i;
3551
+ if (visualLineIndex >= sources.length)
3552
+ break;
3553
+ const logicalLine = sources[visualLineIndex];
3554
+ const lineBg = this._lineColorsContent.get(logicalLine);
3555
+ if (lineBg) {
3556
+ buffer.fillRect(this.x + gutterWidth, this.y + i, contentWidth, 1, lineBg);
3557
+ }
3334
3558
  }
3335
- const beforeCursor = this._value.substring(0, this._cursorPosition);
3336
- const afterCursor = this._value.substring(this._cursorPosition);
3337
- this._value = beforeCursor + text + afterCursor;
3338
- this._cursorPosition += text.length;
3339
- this.requestRender();
3340
- this.updateCursorPosition();
3341
- this.emit("input" /* INPUT */, this._value);
3342
3559
  }
3343
- deleteCharacter(direction) {
3344
- if (direction === "backward" && this._cursorPosition > 0) {
3345
- const beforeCursor = this._value.substring(0, this._cursorPosition - 1);
3346
- const afterCursor = this._value.substring(this._cursorPosition);
3347
- this._value = beforeCursor + afterCursor;
3348
- this._cursorPosition--;
3349
- this.requestRender();
3350
- this.updateCursorPosition();
3351
- this.emit("input" /* INPUT */, this._value);
3352
- } else if (direction === "forward" && this._cursorPosition < this._value.length) {
3353
- const beforeCursor = this._value.substring(0, this._cursorPosition);
3354
- const afterCursor = this._value.substring(this._cursorPosition + 1);
3355
- this._value = beforeCursor + afterCursor;
3356
- this.requestRender();
3357
- this.updateCursorPosition();
3358
- this.emit("input" /* INPUT */, this._value);
3560
+ set showLineNumbers(value) {
3561
+ if (this.gutter) {
3562
+ this.gutter.visible = value;
3359
3563
  }
3360
3564
  }
3361
- handleKeyPress(key) {
3362
- const keyName = typeof key === "string" ? key : key.name;
3363
- const keySequence = typeof key === "string" ? key : key.sequence;
3364
- switch (keyName) {
3365
- case "left":
3366
- this.cursorPosition = this._cursorPosition - 1;
3367
- return true;
3368
- case "right":
3369
- this.cursorPosition = this._cursorPosition + 1;
3370
- return true;
3371
- case "home":
3372
- this.cursorPosition = 0;
3373
- return true;
3565
+ get showLineNumbers() {
3566
+ return this.gutter?.visible ?? false;
3567
+ }
3568
+ setLineColor(line, color) {
3569
+ this.parseLineColor(line, color);
3570
+ if (this.gutter) {
3571
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
3572
+ }
3573
+ }
3574
+ clearLineColor(line) {
3575
+ this._lineColorsGutter.delete(line);
3576
+ this._lineColorsContent.delete(line);
3577
+ if (this.gutter) {
3578
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
3579
+ }
3580
+ }
3581
+ clearAllLineColors() {
3582
+ this._lineColorsGutter.clear();
3583
+ this._lineColorsContent.clear();
3584
+ if (this.gutter) {
3585
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
3586
+ }
3587
+ }
3588
+ setLineColors(lineColors) {
3589
+ this._lineColorsGutter.clear();
3590
+ this._lineColorsContent.clear();
3591
+ for (const [line, color] of lineColors) {
3592
+ this.parseLineColor(line, color);
3593
+ }
3594
+ if (this.gutter) {
3595
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
3596
+ }
3597
+ }
3598
+ getLineColors() {
3599
+ return {
3600
+ gutter: this._lineColorsGutter,
3601
+ content: this._lineColorsContent
3602
+ };
3603
+ }
3604
+ setLineSign(line, sign) {
3605
+ this._lineSigns.set(line, sign);
3606
+ if (this.gutter) {
3607
+ this.gutter.setLineSigns(this._lineSigns);
3608
+ }
3609
+ }
3610
+ clearLineSign(line) {
3611
+ this._lineSigns.delete(line);
3612
+ if (this.gutter) {
3613
+ this.gutter.setLineSigns(this._lineSigns);
3614
+ }
3615
+ }
3616
+ clearAllLineSigns() {
3617
+ this._lineSigns.clear();
3618
+ if (this.gutter) {
3619
+ this.gutter.setLineSigns(this._lineSigns);
3620
+ }
3621
+ }
3622
+ setLineSigns(lineSigns) {
3623
+ this._lineSigns.clear();
3624
+ for (const [line, sign] of lineSigns) {
3625
+ this._lineSigns.set(line, sign);
3626
+ }
3627
+ if (this.gutter) {
3628
+ this.gutter.setLineSigns(this._lineSigns);
3629
+ }
3630
+ }
3631
+ getLineSigns() {
3632
+ return this._lineSigns;
3633
+ }
3634
+ set lineNumberOffset(value) {
3635
+ if (this._lineNumberOffset !== value) {
3636
+ this._lineNumberOffset = value;
3637
+ if (this.gutter && this.target) {
3638
+ const target = this.target;
3639
+ super.remove(this.gutter.id);
3640
+ super.remove(this.target.id);
3641
+ this.gutter = null;
3642
+ this.target = null;
3643
+ this.setTarget(target);
3644
+ }
3645
+ }
3646
+ }
3647
+ get lineNumberOffset() {
3648
+ return this._lineNumberOffset;
3649
+ }
3650
+ setHideLineNumbers(hideLineNumbers) {
3651
+ this._hideLineNumbers = hideLineNumbers;
3652
+ if (this.gutter && this.target) {
3653
+ const target = this.target;
3654
+ super.remove(this.gutter.id);
3655
+ super.remove(this.target.id);
3656
+ this.gutter = null;
3657
+ this.target = null;
3658
+ this.setTarget(target);
3659
+ }
3660
+ }
3661
+ getHideLineNumbers() {
3662
+ return this._hideLineNumbers;
3663
+ }
3664
+ setLineNumbers(lineNumbers) {
3665
+ this._lineNumbers = lineNumbers;
3666
+ if (this.gutter && this.target) {
3667
+ const target = this.target;
3668
+ super.remove(this.gutter.id);
3669
+ super.remove(this.target.id);
3670
+ this.gutter = null;
3671
+ this.target = null;
3672
+ this.setTarget(target);
3673
+ }
3674
+ }
3675
+ getLineNumbers() {
3676
+ return this._lineNumbers;
3677
+ }
3678
+ }
3679
+
3680
+ // ../../node_modules/diff/libesm/diff/base.js
3681
+ class Diff {
3682
+ diff(oldStr, newStr, options = {}) {
3683
+ let callback;
3684
+ if (typeof options === "function") {
3685
+ callback = options;
3686
+ options = {};
3687
+ } else if ("callback" in options) {
3688
+ callback = options.callback;
3689
+ }
3690
+ const oldString = this.castInput(oldStr, options);
3691
+ const newString = this.castInput(newStr, options);
3692
+ const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
3693
+ const newTokens = this.removeEmpty(this.tokenize(newString, options));
3694
+ return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
3695
+ }
3696
+ diffWithOptionsObj(oldTokens, newTokens, options, callback) {
3697
+ var _a;
3698
+ const done = (value) => {
3699
+ value = this.postProcess(value, options);
3700
+ if (callback) {
3701
+ setTimeout(function() {
3702
+ callback(value);
3703
+ }, 0);
3704
+ return;
3705
+ } else {
3706
+ return value;
3707
+ }
3708
+ };
3709
+ const newLen = newTokens.length, oldLen = oldTokens.length;
3710
+ let editLength = 1;
3711
+ let maxEditLength = newLen + oldLen;
3712
+ if (options.maxEditLength != null) {
3713
+ maxEditLength = Math.min(maxEditLength, options.maxEditLength);
3714
+ }
3715
+ const maxExecutionTime = (_a = options.timeout) !== null && _a !== undefined ? _a : Infinity;
3716
+ const abortAfterTimestamp = Date.now() + maxExecutionTime;
3717
+ const bestPath = [{ oldPos: -1, lastComponent: undefined }];
3718
+ let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
3719
+ if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
3720
+ return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
3721
+ }
3722
+ let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
3723
+ const execEditLength = () => {
3724
+ for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength);diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
3725
+ let basePath;
3726
+ const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
3727
+ if (removePath) {
3728
+ bestPath[diagonalPath - 1] = undefined;
3729
+ }
3730
+ let canAdd = false;
3731
+ if (addPath) {
3732
+ const addPathNewPos = addPath.oldPos - diagonalPath;
3733
+ canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
3734
+ }
3735
+ const canRemove = removePath && removePath.oldPos + 1 < oldLen;
3736
+ if (!canAdd && !canRemove) {
3737
+ bestPath[diagonalPath] = undefined;
3738
+ continue;
3739
+ }
3740
+ if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
3741
+ basePath = this.addToPath(addPath, true, false, 0, options);
3742
+ } else {
3743
+ basePath = this.addToPath(removePath, false, true, 1, options);
3744
+ }
3745
+ newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
3746
+ if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
3747
+ return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
3748
+ } else {
3749
+ bestPath[diagonalPath] = basePath;
3750
+ if (basePath.oldPos + 1 >= oldLen) {
3751
+ maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
3752
+ }
3753
+ if (newPos + 1 >= newLen) {
3754
+ minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
3755
+ }
3756
+ }
3757
+ }
3758
+ editLength++;
3759
+ };
3760
+ if (callback) {
3761
+ (function exec() {
3762
+ setTimeout(function() {
3763
+ if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
3764
+ return callback(undefined);
3765
+ }
3766
+ if (!execEditLength()) {
3767
+ exec();
3768
+ }
3769
+ }, 0);
3770
+ })();
3771
+ } else {
3772
+ while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
3773
+ const ret = execEditLength();
3774
+ if (ret) {
3775
+ return ret;
3776
+ }
3777
+ }
3778
+ }
3779
+ }
3780
+ addToPath(path, added, removed, oldPosInc, options) {
3781
+ const last = path.lastComponent;
3782
+ if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
3783
+ return {
3784
+ oldPos: path.oldPos + oldPosInc,
3785
+ lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
3786
+ };
3787
+ } else {
3788
+ return {
3789
+ oldPos: path.oldPos + oldPosInc,
3790
+ lastComponent: { count: 1, added, removed, previousComponent: last }
3791
+ };
3792
+ }
3793
+ }
3794
+ extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
3795
+ const newLen = newTokens.length, oldLen = oldTokens.length;
3796
+ let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
3797
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
3798
+ newPos++;
3799
+ oldPos++;
3800
+ commonCount++;
3801
+ if (options.oneChangePerToken) {
3802
+ basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
3803
+ }
3804
+ }
3805
+ if (commonCount && !options.oneChangePerToken) {
3806
+ basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
3807
+ }
3808
+ basePath.oldPos = oldPos;
3809
+ return newPos;
3810
+ }
3811
+ equals(left, right, options) {
3812
+ if (options.comparator) {
3813
+ return options.comparator(left, right);
3814
+ } else {
3815
+ return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
3816
+ }
3817
+ }
3818
+ removeEmpty(array) {
3819
+ const ret = [];
3820
+ for (let i = 0;i < array.length; i++) {
3821
+ if (array[i]) {
3822
+ ret.push(array[i]);
3823
+ }
3824
+ }
3825
+ return ret;
3826
+ }
3827
+ castInput(value, options) {
3828
+ return value;
3829
+ }
3830
+ tokenize(value, options) {
3831
+ return Array.from(value);
3832
+ }
3833
+ join(chars) {
3834
+ return chars.join("");
3835
+ }
3836
+ postProcess(changeObjects, options) {
3837
+ return changeObjects;
3838
+ }
3839
+ get useLongestToken() {
3840
+ return false;
3841
+ }
3842
+ buildValues(lastComponent, newTokens, oldTokens) {
3843
+ const components = [];
3844
+ let nextComponent;
3845
+ while (lastComponent) {
3846
+ components.push(lastComponent);
3847
+ nextComponent = lastComponent.previousComponent;
3848
+ delete lastComponent.previousComponent;
3849
+ lastComponent = nextComponent;
3850
+ }
3851
+ components.reverse();
3852
+ const componentLen = components.length;
3853
+ let componentPos = 0, newPos = 0, oldPos = 0;
3854
+ for (;componentPos < componentLen; componentPos++) {
3855
+ const component = components[componentPos];
3856
+ if (!component.removed) {
3857
+ if (!component.added && this.useLongestToken) {
3858
+ let value = newTokens.slice(newPos, newPos + component.count);
3859
+ value = value.map(function(value2, i) {
3860
+ const oldValue = oldTokens[oldPos + i];
3861
+ return oldValue.length > value2.length ? oldValue : value2;
3862
+ });
3863
+ component.value = this.join(value);
3864
+ } else {
3865
+ component.value = this.join(newTokens.slice(newPos, newPos + component.count));
3866
+ }
3867
+ newPos += component.count;
3868
+ if (!component.added) {
3869
+ oldPos += component.count;
3870
+ }
3871
+ } else {
3872
+ component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
3873
+ oldPos += component.count;
3874
+ }
3875
+ }
3876
+ return components;
3877
+ }
3878
+ }
3879
+
3880
+ // ../../node_modules/diff/libesm/diff/character.js
3881
+ class CharacterDiff extends Diff {
3882
+ }
3883
+ var characterDiff = new CharacterDiff;
3884
+
3885
+ // ../../node_modules/diff/libesm/util/string.js
3886
+ function longestCommonPrefix(str1, str2) {
3887
+ let i;
3888
+ for (i = 0;i < str1.length && i < str2.length; i++) {
3889
+ if (str1[i] != str2[i]) {
3890
+ return str1.slice(0, i);
3891
+ }
3892
+ }
3893
+ return str1.slice(0, i);
3894
+ }
3895
+ function longestCommonSuffix(str1, str2) {
3896
+ let i;
3897
+ if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) {
3898
+ return "";
3899
+ }
3900
+ for (i = 0;i < str1.length && i < str2.length; i++) {
3901
+ if (str1[str1.length - (i + 1)] != str2[str2.length - (i + 1)]) {
3902
+ return str1.slice(-i);
3903
+ }
3904
+ }
3905
+ return str1.slice(-i);
3906
+ }
3907
+ function replacePrefix(string, oldPrefix, newPrefix) {
3908
+ if (string.slice(0, oldPrefix.length) != oldPrefix) {
3909
+ throw Error(`string ${JSON.stringify(string)} doesn't start with prefix ${JSON.stringify(oldPrefix)}; this is a bug`);
3910
+ }
3911
+ return newPrefix + string.slice(oldPrefix.length);
3912
+ }
3913
+ function replaceSuffix(string, oldSuffix, newSuffix) {
3914
+ if (!oldSuffix) {
3915
+ return string + newSuffix;
3916
+ }
3917
+ if (string.slice(-oldSuffix.length) != oldSuffix) {
3918
+ throw Error(`string ${JSON.stringify(string)} doesn't end with suffix ${JSON.stringify(oldSuffix)}; this is a bug`);
3919
+ }
3920
+ return string.slice(0, -oldSuffix.length) + newSuffix;
3921
+ }
3922
+ function removePrefix(string, oldPrefix) {
3923
+ return replacePrefix(string, oldPrefix, "");
3924
+ }
3925
+ function removeSuffix(string, oldSuffix) {
3926
+ return replaceSuffix(string, oldSuffix, "");
3927
+ }
3928
+ function maximumOverlap(string1, string2) {
3929
+ return string2.slice(0, overlapCount(string1, string2));
3930
+ }
3931
+ function overlapCount(a, b) {
3932
+ let startA = 0;
3933
+ if (a.length > b.length) {
3934
+ startA = a.length - b.length;
3935
+ }
3936
+ let endB = b.length;
3937
+ if (a.length < b.length) {
3938
+ endB = a.length;
3939
+ }
3940
+ const map = Array(endB);
3941
+ let k = 0;
3942
+ map[0] = 0;
3943
+ for (let j = 1;j < endB; j++) {
3944
+ if (b[j] == b[k]) {
3945
+ map[j] = map[k];
3946
+ } else {
3947
+ map[j] = k;
3948
+ }
3949
+ while (k > 0 && b[j] != b[k]) {
3950
+ k = map[k];
3951
+ }
3952
+ if (b[j] == b[k]) {
3953
+ k++;
3954
+ }
3955
+ }
3956
+ k = 0;
3957
+ for (let i = startA;i < a.length; i++) {
3958
+ while (k > 0 && a[i] != b[k]) {
3959
+ k = map[k];
3960
+ }
3961
+ if (a[i] == b[k]) {
3962
+ k++;
3963
+ }
3964
+ }
3965
+ return k;
3966
+ }
3967
+ function trailingWs(string) {
3968
+ let i;
3969
+ for (i = string.length - 1;i >= 0; i--) {
3970
+ if (!string[i].match(/\s/)) {
3971
+ break;
3972
+ }
3973
+ }
3974
+ return string.substring(i + 1);
3975
+ }
3976
+ function leadingWs(string) {
3977
+ const match = string.match(/^\s*/);
3978
+ return match ? match[0] : "";
3979
+ }
3980
+
3981
+ // ../../node_modules/diff/libesm/diff/word.js
3982
+ var extendedWordChars = "a-zA-Z0-9_\\u{C0}-\\u{FF}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";
3983
+ var tokenizeIncludingWhitespace = new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`, "ug");
3984
+
3985
+ class WordDiff extends Diff {
3986
+ equals(left, right, options) {
3987
+ if (options.ignoreCase) {
3988
+ left = left.toLowerCase();
3989
+ right = right.toLowerCase();
3990
+ }
3991
+ return left.trim() === right.trim();
3992
+ }
3993
+ tokenize(value, options = {}) {
3994
+ let parts;
3995
+ if (options.intlSegmenter) {
3996
+ const segmenter = options.intlSegmenter;
3997
+ if (segmenter.resolvedOptions().granularity != "word") {
3998
+ throw new Error('The segmenter passed must have a granularity of "word"');
3999
+ }
4000
+ parts = Array.from(segmenter.segment(value), (segment) => segment.segment);
4001
+ } else {
4002
+ parts = value.match(tokenizeIncludingWhitespace) || [];
4003
+ }
4004
+ const tokens = [];
4005
+ let prevPart = null;
4006
+ parts.forEach((part) => {
4007
+ if (/\s/.test(part)) {
4008
+ if (prevPart == null) {
4009
+ tokens.push(part);
4010
+ } else {
4011
+ tokens.push(tokens.pop() + part);
4012
+ }
4013
+ } else if (prevPart != null && /\s/.test(prevPart)) {
4014
+ if (tokens[tokens.length - 1] == prevPart) {
4015
+ tokens.push(tokens.pop() + part);
4016
+ } else {
4017
+ tokens.push(prevPart + part);
4018
+ }
4019
+ } else {
4020
+ tokens.push(part);
4021
+ }
4022
+ prevPart = part;
4023
+ });
4024
+ return tokens;
4025
+ }
4026
+ join(tokens) {
4027
+ return tokens.map((token, i) => {
4028
+ if (i == 0) {
4029
+ return token;
4030
+ } else {
4031
+ return token.replace(/^\s+/, "");
4032
+ }
4033
+ }).join("");
4034
+ }
4035
+ postProcess(changes, options) {
4036
+ if (!changes || options.oneChangePerToken) {
4037
+ return changes;
4038
+ }
4039
+ let lastKeep = null;
4040
+ let insertion = null;
4041
+ let deletion = null;
4042
+ changes.forEach((change) => {
4043
+ if (change.added) {
4044
+ insertion = change;
4045
+ } else if (change.removed) {
4046
+ deletion = change;
4047
+ } else {
4048
+ if (insertion || deletion) {
4049
+ dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, change);
4050
+ }
4051
+ lastKeep = change;
4052
+ insertion = null;
4053
+ deletion = null;
4054
+ }
4055
+ });
4056
+ if (insertion || deletion) {
4057
+ dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, null);
4058
+ }
4059
+ return changes;
4060
+ }
4061
+ }
4062
+ var wordDiff = new WordDiff;
4063
+ function dedupeWhitespaceInChangeObjects(startKeep, deletion, insertion, endKeep) {
4064
+ if (deletion && insertion) {
4065
+ const oldWsPrefix = leadingWs(deletion.value);
4066
+ const oldWsSuffix = trailingWs(deletion.value);
4067
+ const newWsPrefix = leadingWs(insertion.value);
4068
+ const newWsSuffix = trailingWs(insertion.value);
4069
+ if (startKeep) {
4070
+ const commonWsPrefix = longestCommonPrefix(oldWsPrefix, newWsPrefix);
4071
+ startKeep.value = replaceSuffix(startKeep.value, newWsPrefix, commonWsPrefix);
4072
+ deletion.value = removePrefix(deletion.value, commonWsPrefix);
4073
+ insertion.value = removePrefix(insertion.value, commonWsPrefix);
4074
+ }
4075
+ if (endKeep) {
4076
+ const commonWsSuffix = longestCommonSuffix(oldWsSuffix, newWsSuffix);
4077
+ endKeep.value = replacePrefix(endKeep.value, newWsSuffix, commonWsSuffix);
4078
+ deletion.value = removeSuffix(deletion.value, commonWsSuffix);
4079
+ insertion.value = removeSuffix(insertion.value, commonWsSuffix);
4080
+ }
4081
+ } else if (insertion) {
4082
+ if (startKeep) {
4083
+ const ws = leadingWs(insertion.value);
4084
+ insertion.value = insertion.value.substring(ws.length);
4085
+ }
4086
+ if (endKeep) {
4087
+ const ws = leadingWs(endKeep.value);
4088
+ endKeep.value = endKeep.value.substring(ws.length);
4089
+ }
4090
+ } else if (startKeep && endKeep) {
4091
+ const newWsFull = leadingWs(endKeep.value), delWsStart = leadingWs(deletion.value), delWsEnd = trailingWs(deletion.value);
4092
+ const newWsStart = longestCommonPrefix(newWsFull, delWsStart);
4093
+ deletion.value = removePrefix(deletion.value, newWsStart);
4094
+ const newWsEnd = longestCommonSuffix(removePrefix(newWsFull, newWsStart), delWsEnd);
4095
+ deletion.value = removeSuffix(deletion.value, newWsEnd);
4096
+ endKeep.value = replacePrefix(endKeep.value, newWsFull, newWsEnd);
4097
+ startKeep.value = replaceSuffix(startKeep.value, newWsFull, newWsFull.slice(0, newWsFull.length - newWsEnd.length));
4098
+ } else if (endKeep) {
4099
+ const endKeepWsPrefix = leadingWs(endKeep.value);
4100
+ const deletionWsSuffix = trailingWs(deletion.value);
4101
+ const overlap = maximumOverlap(deletionWsSuffix, endKeepWsPrefix);
4102
+ deletion.value = removeSuffix(deletion.value, overlap);
4103
+ } else if (startKeep) {
4104
+ const startKeepWsSuffix = trailingWs(startKeep.value);
4105
+ const deletionWsPrefix = leadingWs(deletion.value);
4106
+ const overlap = maximumOverlap(startKeepWsSuffix, deletionWsPrefix);
4107
+ deletion.value = removePrefix(deletion.value, overlap);
4108
+ }
4109
+ }
4110
+
4111
+ class WordsWithSpaceDiff extends Diff {
4112
+ tokenize(value) {
4113
+ const regex = new RegExp(`(\\r?\\n)|[${extendedWordChars}]+|[^\\S\\n\\r]+|[^${extendedWordChars}]`, "ug");
4114
+ return value.match(regex) || [];
4115
+ }
4116
+ }
4117
+ var wordsWithSpaceDiff = new WordsWithSpaceDiff;
4118
+
4119
+ // ../../node_modules/diff/libesm/diff/line.js
4120
+ class LineDiff extends Diff {
4121
+ constructor() {
4122
+ super(...arguments);
4123
+ this.tokenize = tokenize;
4124
+ }
4125
+ equals(left, right, options) {
4126
+ if (options.ignoreWhitespace) {
4127
+ if (!options.newlineIsToken || !left.includes(`
4128
+ `)) {
4129
+ left = left.trim();
4130
+ }
4131
+ if (!options.newlineIsToken || !right.includes(`
4132
+ `)) {
4133
+ right = right.trim();
4134
+ }
4135
+ } else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
4136
+ if (left.endsWith(`
4137
+ `)) {
4138
+ left = left.slice(0, -1);
4139
+ }
4140
+ if (right.endsWith(`
4141
+ `)) {
4142
+ right = right.slice(0, -1);
4143
+ }
4144
+ }
4145
+ return super.equals(left, right, options);
4146
+ }
4147
+ }
4148
+ var lineDiff = new LineDiff;
4149
+ function tokenize(value, options) {
4150
+ if (options.stripTrailingCr) {
4151
+ value = value.replace(/\r\n/g, `
4152
+ `);
4153
+ }
4154
+ const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
4155
+ if (!linesAndNewlines[linesAndNewlines.length - 1]) {
4156
+ linesAndNewlines.pop();
4157
+ }
4158
+ for (let i = 0;i < linesAndNewlines.length; i++) {
4159
+ const line = linesAndNewlines[i];
4160
+ if (i % 2 && !options.newlineIsToken) {
4161
+ retLines[retLines.length - 1] += line;
4162
+ } else {
4163
+ retLines.push(line);
4164
+ }
4165
+ }
4166
+ return retLines;
4167
+ }
4168
+
4169
+ // ../../node_modules/diff/libesm/diff/sentence.js
4170
+ function isSentenceEndPunct(char) {
4171
+ return char == "." || char == "!" || char == "?";
4172
+ }
4173
+
4174
+ class SentenceDiff extends Diff {
4175
+ tokenize(value) {
4176
+ var _a;
4177
+ const result = [];
4178
+ let tokenStartI = 0;
4179
+ for (let i = 0;i < value.length; i++) {
4180
+ if (i == value.length - 1) {
4181
+ result.push(value.slice(tokenStartI));
4182
+ break;
4183
+ }
4184
+ if (isSentenceEndPunct(value[i]) && value[i + 1].match(/\s/)) {
4185
+ result.push(value.slice(tokenStartI, i + 1));
4186
+ i = tokenStartI = i + 1;
4187
+ while ((_a = value[i + 1]) === null || _a === undefined ? undefined : _a.match(/\s/)) {
4188
+ i++;
4189
+ }
4190
+ result.push(value.slice(tokenStartI, i + 1));
4191
+ tokenStartI = i + 1;
4192
+ }
4193
+ }
4194
+ return result;
4195
+ }
4196
+ }
4197
+ var sentenceDiff = new SentenceDiff;
4198
+
4199
+ // ../../node_modules/diff/libesm/diff/css.js
4200
+ class CssDiff extends Diff {
4201
+ tokenize(value) {
4202
+ return value.split(/([{}:;,]|\s+)/);
4203
+ }
4204
+ }
4205
+ var cssDiff = new CssDiff;
4206
+
4207
+ // ../../node_modules/diff/libesm/diff/json.js
4208
+ class JsonDiff extends Diff {
4209
+ constructor() {
4210
+ super(...arguments);
4211
+ this.tokenize = tokenize;
4212
+ }
4213
+ get useLongestToken() {
4214
+ return true;
4215
+ }
4216
+ castInput(value, options) {
4217
+ const { undefinedReplacement, stringifyReplacer = (k, v) => typeof v === "undefined" ? undefinedReplacement : v } = options;
4218
+ return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), null, " ");
4219
+ }
4220
+ equals(left, right, options) {
4221
+ return super.equals(left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"), options);
4222
+ }
4223
+ }
4224
+ var jsonDiff = new JsonDiff;
4225
+ function canonicalize(obj, stack, replacementStack, replacer, key) {
4226
+ stack = stack || [];
4227
+ replacementStack = replacementStack || [];
4228
+ if (replacer) {
4229
+ obj = replacer(key === undefined ? "" : key, obj);
4230
+ }
4231
+ let i;
4232
+ for (i = 0;i < stack.length; i += 1) {
4233
+ if (stack[i] === obj) {
4234
+ return replacementStack[i];
4235
+ }
4236
+ }
4237
+ let canonicalizedObj;
4238
+ if (Object.prototype.toString.call(obj) === "[object Array]") {
4239
+ stack.push(obj);
4240
+ canonicalizedObj = new Array(obj.length);
4241
+ replacementStack.push(canonicalizedObj);
4242
+ for (i = 0;i < obj.length; i += 1) {
4243
+ canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, String(i));
4244
+ }
4245
+ stack.pop();
4246
+ replacementStack.pop();
4247
+ return canonicalizedObj;
4248
+ }
4249
+ if (obj && obj.toJSON) {
4250
+ obj = obj.toJSON();
4251
+ }
4252
+ if (typeof obj === "object" && obj !== null) {
4253
+ stack.push(obj);
4254
+ canonicalizedObj = {};
4255
+ replacementStack.push(canonicalizedObj);
4256
+ const sortedKeys = [];
4257
+ let key2;
4258
+ for (key2 in obj) {
4259
+ if (Object.prototype.hasOwnProperty.call(obj, key2)) {
4260
+ sortedKeys.push(key2);
4261
+ }
4262
+ }
4263
+ sortedKeys.sort();
4264
+ for (i = 0;i < sortedKeys.length; i += 1) {
4265
+ key2 = sortedKeys[i];
4266
+ canonicalizedObj[key2] = canonicalize(obj[key2], stack, replacementStack, replacer, key2);
4267
+ }
4268
+ stack.pop();
4269
+ replacementStack.pop();
4270
+ } else {
4271
+ canonicalizedObj = obj;
4272
+ }
4273
+ return canonicalizedObj;
4274
+ }
4275
+
4276
+ // ../../node_modules/diff/libesm/diff/array.js
4277
+ class ArrayDiff extends Diff {
4278
+ tokenize(value) {
4279
+ return value.slice();
4280
+ }
4281
+ join(value) {
4282
+ return value;
4283
+ }
4284
+ removeEmpty(value) {
4285
+ return value;
4286
+ }
4287
+ }
4288
+ var arrayDiff = new ArrayDiff;
4289
+
4290
+ // ../../node_modules/diff/libesm/patch/parse.js
4291
+ function parsePatch(uniDiff) {
4292
+ const diffstr = uniDiff.split(/\n/), list = [];
4293
+ let i = 0;
4294
+ function parseIndex() {
4295
+ const index = {};
4296
+ list.push(index);
4297
+ while (i < diffstr.length) {
4298
+ const line = diffstr[i];
4299
+ if (/^(---|\+\+\+|@@)\s/.test(line)) {
4300
+ break;
4301
+ }
4302
+ const header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
4303
+ if (header) {
4304
+ index.index = header[1];
4305
+ }
4306
+ i++;
4307
+ }
4308
+ parseFileHeader(index);
4309
+ parseFileHeader(index);
4310
+ index.hunks = [];
4311
+ while (i < diffstr.length) {
4312
+ const line = diffstr[i];
4313
+ if (/^(Index:\s|diff\s|---\s|\+\+\+\s|===================================================================)/.test(line)) {
4314
+ break;
4315
+ } else if (/^@@/.test(line)) {
4316
+ index.hunks.push(parseHunk());
4317
+ } else if (line) {
4318
+ throw new Error("Unknown line " + (i + 1) + " " + JSON.stringify(line));
4319
+ } else {
4320
+ i++;
4321
+ }
4322
+ }
4323
+ }
4324
+ function parseFileHeader(index) {
4325
+ const fileHeader = /^(---|\+\+\+)\s+(.*)\r?$/.exec(diffstr[i]);
4326
+ if (fileHeader) {
4327
+ const data = fileHeader[2].split("\t", 2), header = (data[1] || "").trim();
4328
+ let fileName = data[0].replace(/\\\\/g, "\\");
4329
+ if (/^".*"$/.test(fileName)) {
4330
+ fileName = fileName.substr(1, fileName.length - 2);
4331
+ }
4332
+ if (fileHeader[1] === "---") {
4333
+ index.oldFileName = fileName;
4334
+ index.oldHeader = header;
4335
+ } else {
4336
+ index.newFileName = fileName;
4337
+ index.newHeader = header;
4338
+ }
4339
+ i++;
4340
+ }
4341
+ }
4342
+ function parseHunk() {
4343
+ var _a;
4344
+ const chunkHeaderIndex = i, chunkHeaderLine = diffstr[i++], chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
4345
+ const hunk = {
4346
+ oldStart: +chunkHeader[1],
4347
+ oldLines: typeof chunkHeader[2] === "undefined" ? 1 : +chunkHeader[2],
4348
+ newStart: +chunkHeader[3],
4349
+ newLines: typeof chunkHeader[4] === "undefined" ? 1 : +chunkHeader[4],
4350
+ lines: []
4351
+ };
4352
+ if (hunk.oldLines === 0) {
4353
+ hunk.oldStart += 1;
4354
+ }
4355
+ if (hunk.newLines === 0) {
4356
+ hunk.newStart += 1;
4357
+ }
4358
+ let addCount = 0, removeCount = 0;
4359
+ for (;i < diffstr.length && (removeCount < hunk.oldLines || addCount < hunk.newLines || ((_a = diffstr[i]) === null || _a === undefined ? undefined : _a.startsWith("\\"))); i++) {
4360
+ const operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? " " : diffstr[i][0];
4361
+ if (operation === "+" || operation === "-" || operation === " " || operation === "\\") {
4362
+ hunk.lines.push(diffstr[i]);
4363
+ if (operation === "+") {
4364
+ addCount++;
4365
+ } else if (operation === "-") {
4366
+ removeCount++;
4367
+ } else if (operation === " ") {
4368
+ addCount++;
4369
+ removeCount++;
4370
+ }
4371
+ } else {
4372
+ throw new Error(`Hunk at line ${chunkHeaderIndex + 1} contained invalid line ${diffstr[i]}`);
4373
+ }
4374
+ }
4375
+ if (!addCount && hunk.newLines === 1) {
4376
+ hunk.newLines = 0;
4377
+ }
4378
+ if (!removeCount && hunk.oldLines === 1) {
4379
+ hunk.oldLines = 0;
4380
+ }
4381
+ if (addCount !== hunk.newLines) {
4382
+ throw new Error("Added line count did not match for hunk at line " + (chunkHeaderIndex + 1));
4383
+ }
4384
+ if (removeCount !== hunk.oldLines) {
4385
+ throw new Error("Removed line count did not match for hunk at line " + (chunkHeaderIndex + 1));
4386
+ }
4387
+ return hunk;
4388
+ }
4389
+ while (i < diffstr.length) {
4390
+ parseIndex();
4391
+ }
4392
+ return list;
4393
+ }
4394
+
4395
+ // src/renderables/Diff.ts
4396
+ class DiffRenderable extends Renderable {
4397
+ _diff;
4398
+ _view;
4399
+ _parsedDiff = null;
4400
+ _filetype;
4401
+ _syntaxStyle;
4402
+ _wrapMode;
4403
+ _conceal;
4404
+ _showLineNumbers;
4405
+ _lineNumberFg;
4406
+ _lineNumberBg;
4407
+ _addedBg;
4408
+ _removedBg;
4409
+ _addedSignColor;
4410
+ _removedSignColor;
4411
+ leftSide = null;
4412
+ rightSide = null;
4413
+ leftSideAdded = false;
4414
+ rightSideAdded = false;
4415
+ leftCodeRenderable = null;
4416
+ rightCodeRenderable = null;
4417
+ pendingRebuild = false;
4418
+ constructor(ctx, options) {
4419
+ super(ctx, {
4420
+ ...options,
4421
+ flexDirection: options.view === "split" ? "row" : "column"
4422
+ });
4423
+ this._diff = options.diff ?? "";
4424
+ this._view = options.view ?? "unified";
4425
+ this._filetype = options.filetype;
4426
+ this._syntaxStyle = options.syntaxStyle;
4427
+ this._wrapMode = options.wrapMode;
4428
+ this._conceal = options.conceal ?? true;
4429
+ this._showLineNumbers = options.showLineNumbers ?? true;
4430
+ this._lineNumberFg = parseColor(options.lineNumberFg ?? "#888888");
4431
+ this._lineNumberBg = parseColor(options.lineNumberBg ?? "transparent");
4432
+ this._addedBg = parseColor(options.addedBg ?? "#1a4d1a");
4433
+ this._removedBg = parseColor(options.removedBg ?? "#4d1a1a");
4434
+ this._addedSignColor = parseColor(options.addedSignColor ?? "#22c55e");
4435
+ this._removedSignColor = parseColor(options.removedSignColor ?? "#ef4444");
4436
+ if (this._diff) {
4437
+ this.parseDiff();
4438
+ this.buildView();
4439
+ }
4440
+ }
4441
+ parseDiff() {
4442
+ if (!this._diff) {
4443
+ this._parsedDiff = null;
4444
+ return;
4445
+ }
4446
+ const patches = parsePatch(this._diff);
4447
+ if (patches.length === 0) {
4448
+ this._parsedDiff = null;
4449
+ return;
4450
+ }
4451
+ this._parsedDiff = patches[0];
4452
+ }
4453
+ buildView() {
4454
+ if (!this._parsedDiff || this._parsedDiff.hunks.length === 0) {
4455
+ return;
4456
+ }
4457
+ if (this._view === "unified") {
4458
+ this.buildUnifiedView();
4459
+ } else {
4460
+ this.buildSplitView();
4461
+ }
4462
+ }
4463
+ onResize(width, height) {
4464
+ super.onResize(width, height);
4465
+ if (this._view === "split" && this._wrapMode !== "none" && this._wrapMode !== undefined) {
4466
+ this.requestRebuild();
4467
+ }
4468
+ }
4469
+ requestRebuild() {
4470
+ if (this.pendingRebuild) {
4471
+ return;
4472
+ }
4473
+ this.pendingRebuild = true;
4474
+ queueMicrotask(() => {
4475
+ if (!this.isDestroyed && this.pendingRebuild) {
4476
+ this.pendingRebuild = false;
4477
+ this.buildView();
4478
+ this.requestRender();
4479
+ }
4480
+ });
4481
+ }
4482
+ destroyRecursively() {
4483
+ this.pendingRebuild = false;
4484
+ this.leftSideAdded = false;
4485
+ this.rightSideAdded = false;
4486
+ super.destroyRecursively();
4487
+ }
4488
+ buildUnifiedView() {
4489
+ if (!this._parsedDiff)
4490
+ return;
4491
+ const contentLines = [];
4492
+ const lineColors = new Map;
4493
+ const lineSigns = new Map;
4494
+ const lineNumbers = new Map;
4495
+ let lineIndex = 0;
4496
+ for (const hunk of this._parsedDiff.hunks) {
4497
+ let oldLineNum = hunk.oldStart;
4498
+ let newLineNum = hunk.newStart;
4499
+ for (const line of hunk.lines) {
4500
+ const firstChar = line[0];
4501
+ const content2 = line.slice(1);
4502
+ if (firstChar === "+") {
4503
+ contentLines.push(content2);
4504
+ lineColors.set(lineIndex, this._addedBg);
4505
+ lineSigns.set(lineIndex, {
4506
+ after: " +",
4507
+ afterColor: this._addedSignColor
4508
+ });
4509
+ lineNumbers.set(lineIndex, newLineNum);
4510
+ newLineNum++;
4511
+ lineIndex++;
4512
+ } else if (firstChar === "-") {
4513
+ contentLines.push(content2);
4514
+ lineColors.set(lineIndex, this._removedBg);
4515
+ lineSigns.set(lineIndex, {
4516
+ after: " -",
4517
+ afterColor: this._removedSignColor
4518
+ });
4519
+ lineNumbers.set(lineIndex, oldLineNum);
4520
+ oldLineNum++;
4521
+ lineIndex++;
4522
+ } else if (firstChar === " ") {
4523
+ contentLines.push(content2);
4524
+ lineNumbers.set(lineIndex, newLineNum);
4525
+ oldLineNum++;
4526
+ newLineNum++;
4527
+ lineIndex++;
4528
+ }
4529
+ }
4530
+ }
4531
+ const content = contentLines.join(`
4532
+ `);
4533
+ if (!this.leftCodeRenderable) {
4534
+ const codeOptions = {
4535
+ id: this.id ? `${this.id}-left-code` : undefined,
4536
+ content,
4537
+ filetype: this._filetype,
4538
+ wrapMode: this._wrapMode,
4539
+ conceal: this._conceal,
4540
+ width: "100%",
4541
+ height: "100%"
4542
+ };
4543
+ if (this._syntaxStyle) {
4544
+ codeOptions.syntaxStyle = this._syntaxStyle;
4545
+ }
4546
+ this.leftCodeRenderable = new CodeRenderable(this.ctx, codeOptions);
4547
+ } else {
4548
+ this.leftCodeRenderable.content = content;
4549
+ if (this._filetype !== undefined) {
4550
+ this.leftCodeRenderable.filetype = this._filetype;
4551
+ }
4552
+ if (this._syntaxStyle !== undefined) {
4553
+ this.leftCodeRenderable.syntaxStyle = this._syntaxStyle;
4554
+ }
4555
+ this.leftCodeRenderable.wrapMode = this._wrapMode ?? "none";
4556
+ }
4557
+ if (!this.leftSide) {
4558
+ this.leftSide = new LineNumberRenderable(this.ctx, {
4559
+ id: this.id ? `${this.id}-left` : undefined,
4560
+ target: this.leftCodeRenderable,
4561
+ fg: this._lineNumberFg,
4562
+ bg: this._lineNumberBg,
4563
+ lineColors,
4564
+ lineSigns,
4565
+ lineNumbers,
4566
+ lineNumberOffset: 0,
4567
+ hideLineNumbers: new Set,
4568
+ width: "100%",
4569
+ height: "100%"
4570
+ });
4571
+ this.leftSide.showLineNumbers = this._showLineNumbers;
4572
+ super.add(this.leftSide);
4573
+ this.leftSideAdded = true;
4574
+ } else {
4575
+ this.leftSide.setLineColors(lineColors);
4576
+ this.leftSide.setLineSigns(lineSigns);
4577
+ this.leftSide.setLineNumbers(lineNumbers);
4578
+ this.leftSide.setHideLineNumbers(new Set);
4579
+ this.leftSide.width = "100%";
4580
+ if (!this.leftSideAdded) {
4581
+ super.add(this.leftSide);
4582
+ this.leftSideAdded = true;
4583
+ }
4584
+ }
4585
+ if (this.rightSide && this.rightSideAdded) {
4586
+ super.remove(this.rightSide.id);
4587
+ this.rightSideAdded = false;
4588
+ }
4589
+ }
4590
+ buildSplitView() {
4591
+ if (!this._parsedDiff)
4592
+ return;
4593
+ const leftLogicalLines = [];
4594
+ const rightLogicalLines = [];
4595
+ for (const hunk of this._parsedDiff.hunks) {
4596
+ let oldLineNum = hunk.oldStart;
4597
+ let newLineNum = hunk.newStart;
4598
+ let i = 0;
4599
+ while (i < hunk.lines.length) {
4600
+ const line = hunk.lines[i];
4601
+ const firstChar = line[0];
4602
+ if (firstChar === " ") {
4603
+ const content = line.slice(1);
4604
+ leftLogicalLines.push({
4605
+ content,
4606
+ lineNum: oldLineNum,
4607
+ type: "context"
4608
+ });
4609
+ rightLogicalLines.push({
4610
+ content,
4611
+ lineNum: newLineNum,
4612
+ type: "context"
4613
+ });
4614
+ oldLineNum++;
4615
+ newLineNum++;
4616
+ i++;
4617
+ } else if (firstChar === "\\") {
4618
+ i++;
4619
+ } else {
4620
+ const removes = [];
4621
+ const adds = [];
4622
+ while (i < hunk.lines.length) {
4623
+ const currentLine = hunk.lines[i];
4624
+ const currentChar = currentLine[0];
4625
+ if (currentChar === " " || currentChar === "\\") {
4626
+ break;
4627
+ }
4628
+ const content = currentLine.slice(1);
4629
+ if (currentChar === "-") {
4630
+ removes.push({ content, lineNum: oldLineNum });
4631
+ oldLineNum++;
4632
+ } else if (currentChar === "+") {
4633
+ adds.push({ content, lineNum: newLineNum });
4634
+ newLineNum++;
4635
+ }
4636
+ i++;
4637
+ }
4638
+ const maxLength = Math.max(removes.length, adds.length);
4639
+ for (let j = 0;j < maxLength; j++) {
4640
+ if (j < removes.length) {
4641
+ leftLogicalLines.push({
4642
+ content: removes[j].content,
4643
+ lineNum: removes[j].lineNum,
4644
+ color: this._removedBg,
4645
+ sign: {
4646
+ after: " -",
4647
+ afterColor: this._removedSignColor
4648
+ },
4649
+ type: "remove"
4650
+ });
4651
+ } else {
4652
+ leftLogicalLines.push({
4653
+ content: "",
4654
+ hideLineNumber: true,
4655
+ type: "empty"
4656
+ });
4657
+ }
4658
+ if (j < adds.length) {
4659
+ rightLogicalLines.push({
4660
+ content: adds[j].content,
4661
+ lineNum: adds[j].lineNum,
4662
+ color: this._addedBg,
4663
+ sign: {
4664
+ after: " +",
4665
+ afterColor: this._addedSignColor
4666
+ },
4667
+ type: "add"
4668
+ });
4669
+ } else {
4670
+ rightLogicalLines.push({
4671
+ content: "",
4672
+ hideLineNumber: true,
4673
+ type: "empty"
4674
+ });
4675
+ }
4676
+ }
4677
+ }
4678
+ }
4679
+ }
4680
+ const canDoWrapAlignment = this.width > 0 && (this._wrapMode === "word" || this._wrapMode === "char");
4681
+ const preLeftContent = leftLogicalLines.map((l) => l.content).join(`
4682
+ `);
4683
+ const preRightContent = rightLogicalLines.map((l) => l.content).join(`
4684
+ `);
4685
+ const effectiveWrapMode = canDoWrapAlignment ? this._wrapMode : "none";
4686
+ if (!this.leftCodeRenderable) {
4687
+ const leftCodeOptions = {
4688
+ id: this.id ? `${this.id}-left-code` : undefined,
4689
+ content: preLeftContent,
4690
+ filetype: this._filetype,
4691
+ wrapMode: effectiveWrapMode,
4692
+ conceal: this._conceal,
4693
+ drawUnstyledText: true,
4694
+ width: "100%",
4695
+ height: "100%"
4696
+ };
4697
+ if (this._syntaxStyle) {
4698
+ leftCodeOptions.syntaxStyle = this._syntaxStyle;
4699
+ }
4700
+ this.leftCodeRenderable = new CodeRenderable(this.ctx, leftCodeOptions);
4701
+ } else {
4702
+ this.leftCodeRenderable.content = preLeftContent;
4703
+ this.leftCodeRenderable.wrapMode = effectiveWrapMode;
4704
+ this.leftCodeRenderable.drawUnstyledText = true;
4705
+ if (this._filetype !== undefined) {
4706
+ this.leftCodeRenderable.filetype = this._filetype;
4707
+ }
4708
+ if (this._syntaxStyle !== undefined) {
4709
+ this.leftCodeRenderable.syntaxStyle = this._syntaxStyle;
4710
+ }
4711
+ }
4712
+ if (!this.rightCodeRenderable) {
4713
+ const rightCodeOptions = {
4714
+ id: this.id ? `${this.id}-right-code` : undefined,
4715
+ content: preRightContent,
4716
+ filetype: this._filetype,
4717
+ wrapMode: effectiveWrapMode,
4718
+ conceal: this._conceal,
4719
+ drawUnstyledText: true,
4720
+ width: "100%",
4721
+ height: "100%"
4722
+ };
4723
+ if (this._syntaxStyle) {
4724
+ rightCodeOptions.syntaxStyle = this._syntaxStyle;
4725
+ }
4726
+ this.rightCodeRenderable = new CodeRenderable(this.ctx, rightCodeOptions);
4727
+ } else {
4728
+ this.rightCodeRenderable.content = preRightContent;
4729
+ this.rightCodeRenderable.wrapMode = effectiveWrapMode;
4730
+ this.rightCodeRenderable.drawUnstyledText = true;
4731
+ if (this._filetype !== undefined) {
4732
+ this.rightCodeRenderable.filetype = this._filetype;
4733
+ }
4734
+ if (this._syntaxStyle !== undefined) {
4735
+ this.rightCodeRenderable.syntaxStyle = this._syntaxStyle;
4736
+ }
4737
+ }
4738
+ let finalLeftLines;
4739
+ let finalRightLines;
4740
+ if (canDoWrapAlignment) {
4741
+ const leftLineInfo = this.leftCodeRenderable.lineInfo;
4742
+ const rightLineInfo = this.rightCodeRenderable.lineInfo;
4743
+ const leftSources = leftLineInfo.lineSources || [];
4744
+ const rightSources = rightLineInfo.lineSources || [];
4745
+ const leftVisualCounts = new Map;
4746
+ const rightVisualCounts = new Map;
4747
+ for (const logicalLine of leftSources) {
4748
+ leftVisualCounts.set(logicalLine, (leftVisualCounts.get(logicalLine) || 0) + 1);
4749
+ }
4750
+ for (const logicalLine of rightSources) {
4751
+ rightVisualCounts.set(logicalLine, (rightVisualCounts.get(logicalLine) || 0) + 1);
4752
+ }
4753
+ finalLeftLines = [];
4754
+ finalRightLines = [];
4755
+ let leftVisualPos = 0;
4756
+ let rightVisualPos = 0;
4757
+ for (let i = 0;i < leftLogicalLines.length; i++) {
4758
+ const leftLine = leftLogicalLines[i];
4759
+ const rightLine = rightLogicalLines[i];
4760
+ const leftVisualCount = leftVisualCounts.get(i) || 1;
4761
+ const rightVisualCount = rightVisualCounts.get(i) || 1;
4762
+ if (leftVisualPos < rightVisualPos) {
4763
+ const pad = rightVisualPos - leftVisualPos;
4764
+ for (let p = 0;p < pad; p++) {
4765
+ finalLeftLines.push({ content: "", hideLineNumber: true, type: "empty" });
4766
+ }
4767
+ leftVisualPos += pad;
4768
+ } else if (rightVisualPos < leftVisualPos) {
4769
+ const pad = leftVisualPos - rightVisualPos;
4770
+ for (let p = 0;p < pad; p++) {
4771
+ finalRightLines.push({ content: "", hideLineNumber: true, type: "empty" });
4772
+ }
4773
+ rightVisualPos += pad;
4774
+ }
4775
+ finalLeftLines.push(leftLine);
4776
+ finalRightLines.push(rightLine);
4777
+ leftVisualPos += leftVisualCount;
4778
+ rightVisualPos += rightVisualCount;
4779
+ }
4780
+ if (leftVisualPos < rightVisualPos) {
4781
+ const pad = rightVisualPos - leftVisualPos;
4782
+ for (let p = 0;p < pad; p++) {
4783
+ finalLeftLines.push({ content: "", hideLineNumber: true, type: "empty" });
4784
+ }
4785
+ } else if (rightVisualPos < leftVisualPos) {
4786
+ const pad = leftVisualPos - rightVisualPos;
4787
+ for (let p = 0;p < pad; p++) {
4788
+ finalRightLines.push({ content: "", hideLineNumber: true, type: "empty" });
4789
+ }
4790
+ }
4791
+ } else {
4792
+ finalLeftLines = leftLogicalLines;
4793
+ finalRightLines = rightLogicalLines;
4794
+ }
4795
+ const leftLineColors = new Map;
4796
+ const rightLineColors = new Map;
4797
+ const leftLineSigns = new Map;
4798
+ const rightLineSigns = new Map;
4799
+ const leftHideLineNumbers = new Set;
4800
+ const rightHideLineNumbers = new Set;
4801
+ const leftLineNumbers = new Map;
4802
+ const rightLineNumbers = new Map;
4803
+ finalLeftLines.forEach((line, index) => {
4804
+ if (line.lineNum !== undefined) {
4805
+ leftLineNumbers.set(index, line.lineNum);
4806
+ }
4807
+ if (line.hideLineNumber) {
4808
+ leftHideLineNumbers.add(index);
4809
+ }
4810
+ if (line.color) {
4811
+ leftLineColors.set(index, line.color);
4812
+ }
4813
+ if (line.sign) {
4814
+ leftLineSigns.set(index, line.sign);
4815
+ }
4816
+ });
4817
+ finalRightLines.forEach((line, index) => {
4818
+ if (line.lineNum !== undefined) {
4819
+ rightLineNumbers.set(index, line.lineNum);
4820
+ }
4821
+ if (line.hideLineNumber) {
4822
+ rightHideLineNumbers.add(index);
4823
+ }
4824
+ if (line.color) {
4825
+ rightLineColors.set(index, line.color);
4826
+ }
4827
+ if (line.sign) {
4828
+ rightLineSigns.set(index, line.sign);
4829
+ }
4830
+ });
4831
+ const leftContentFinal = finalLeftLines.map((l) => l.content).join(`
4832
+ `);
4833
+ const rightContentFinal = finalRightLines.map((l) => l.content).join(`
4834
+ `);
4835
+ this.leftCodeRenderable.content = leftContentFinal;
4836
+ this.rightCodeRenderable.content = rightContentFinal;
4837
+ if (!this.leftSide) {
4838
+ this.leftSide = new LineNumberRenderable(this.ctx, {
4839
+ id: this.id ? `${this.id}-left` : undefined,
4840
+ target: this.leftCodeRenderable,
4841
+ fg: this._lineNumberFg,
4842
+ bg: this._lineNumberBg,
4843
+ lineColors: leftLineColors,
4844
+ lineSigns: leftLineSigns,
4845
+ lineNumbers: leftLineNumbers,
4846
+ lineNumberOffset: 0,
4847
+ hideLineNumbers: leftHideLineNumbers,
4848
+ width: "50%",
4849
+ height: "100%"
4850
+ });
4851
+ this.leftSide.showLineNumbers = this._showLineNumbers;
4852
+ super.add(this.leftSide);
4853
+ this.leftSideAdded = true;
4854
+ } else {
4855
+ this.leftSide.width = "50%";
4856
+ this.leftSide.setLineColors(leftLineColors);
4857
+ this.leftSide.setLineSigns(leftLineSigns);
4858
+ this.leftSide.setLineNumbers(leftLineNumbers);
4859
+ this.leftSide.setHideLineNumbers(leftHideLineNumbers);
4860
+ if (!this.leftSideAdded) {
4861
+ super.add(this.leftSide);
4862
+ this.leftSideAdded = true;
4863
+ }
4864
+ }
4865
+ if (!this.rightSide) {
4866
+ this.rightSide = new LineNumberRenderable(this.ctx, {
4867
+ id: this.id ? `${this.id}-right` : undefined,
4868
+ target: this.rightCodeRenderable,
4869
+ fg: this._lineNumberFg,
4870
+ bg: this._lineNumberBg,
4871
+ lineColors: rightLineColors,
4872
+ lineSigns: rightLineSigns,
4873
+ lineNumbers: rightLineNumbers,
4874
+ lineNumberOffset: 0,
4875
+ hideLineNumbers: rightHideLineNumbers,
4876
+ width: "50%",
4877
+ height: "100%"
4878
+ });
4879
+ this.rightSide.showLineNumbers = this._showLineNumbers;
4880
+ super.add(this.rightSide);
4881
+ this.rightSideAdded = true;
4882
+ } else {
4883
+ this.rightSide.setLineColors(rightLineColors);
4884
+ this.rightSide.setLineSigns(rightLineSigns);
4885
+ this.rightSide.setLineNumbers(rightLineNumbers);
4886
+ this.rightSide.setHideLineNumbers(rightHideLineNumbers);
4887
+ if (!this.rightSideAdded) {
4888
+ super.add(this.rightSide);
4889
+ this.rightSideAdded = true;
4890
+ }
4891
+ }
4892
+ }
4893
+ get diff() {
4894
+ return this._diff;
4895
+ }
4896
+ set diff(value) {
4897
+ if (this._diff !== value) {
4898
+ this._diff = value;
4899
+ this.parseDiff();
4900
+ if (this._view === "split") {
4901
+ this.requestRebuild();
4902
+ } else {
4903
+ this.buildView();
4904
+ }
4905
+ }
4906
+ }
4907
+ get view() {
4908
+ return this._view;
4909
+ }
4910
+ set view(value) {
4911
+ if (this._view !== value) {
4912
+ this._view = value;
4913
+ this.flexDirection = value === "split" ? "row" : "column";
4914
+ this.buildView();
4915
+ }
4916
+ }
4917
+ get filetype() {
4918
+ return this._filetype;
4919
+ }
4920
+ set filetype(value) {
4921
+ if (this._filetype !== value) {
4922
+ this._filetype = value;
4923
+ if (this._view === "split") {
4924
+ this.requestRebuild();
4925
+ } else {
4926
+ this.buildView();
4927
+ }
4928
+ }
4929
+ }
4930
+ get syntaxStyle() {
4931
+ return this._syntaxStyle;
4932
+ }
4933
+ set syntaxStyle(value) {
4934
+ if (this._syntaxStyle !== value) {
4935
+ this._syntaxStyle = value;
4936
+ if (this._view === "split") {
4937
+ this.requestRebuild();
4938
+ } else {
4939
+ this.buildView();
4940
+ }
4941
+ }
4942
+ }
4943
+ get wrapMode() {
4944
+ return this._wrapMode;
4945
+ }
4946
+ set wrapMode(value) {
4947
+ if (this._wrapMode !== value) {
4948
+ this._wrapMode = value;
4949
+ if (this._view === "unified" && this.leftCodeRenderable) {
4950
+ this.leftCodeRenderable.wrapMode = value ?? "none";
4951
+ } else if (this._view === "split") {
4952
+ this.requestRebuild();
4953
+ }
4954
+ }
4955
+ }
4956
+ get showLineNumbers() {
4957
+ return this._showLineNumbers;
4958
+ }
4959
+ set showLineNumbers(value) {
4960
+ if (this._showLineNumbers !== value) {
4961
+ this._showLineNumbers = value;
4962
+ if (this.leftSide) {
4963
+ this.leftSide.showLineNumbers = value;
4964
+ }
4965
+ if (this.rightSide) {
4966
+ this.rightSide.showLineNumbers = value;
4967
+ }
4968
+ }
4969
+ }
4970
+ }
4971
+ // src/renderables/Input.ts
4972
+ var InputRenderableEvents;
4973
+ ((InputRenderableEvents2) => {
4974
+ InputRenderableEvents2["INPUT"] = "input";
4975
+ InputRenderableEvents2["CHANGE"] = "change";
4976
+ InputRenderableEvents2["ENTER"] = "enter";
4977
+ })(InputRenderableEvents ||= {});
4978
+
4979
+ class InputRenderable extends Renderable {
4980
+ _focusable = true;
4981
+ _value = "";
4982
+ _cursorPosition = 0;
4983
+ _placeholder;
4984
+ _backgroundColor;
4985
+ _textColor;
4986
+ _focusedBackgroundColor;
4987
+ _focusedTextColor;
4988
+ _placeholderColor;
4989
+ _cursorColor;
4990
+ _cursorStyle;
4991
+ _maxLength;
4992
+ _lastCommittedValue = "";
4993
+ _defaultOptions = {
4994
+ backgroundColor: "transparent",
4995
+ textColor: "#FFFFFF",
4996
+ focusedBackgroundColor: "#1a1a1a",
4997
+ focusedTextColor: "#FFFFFF",
4998
+ placeholder: "",
4999
+ placeholderColor: "#666666",
5000
+ cursorColor: "#FFFFFF",
5001
+ cursorStyle: {
5002
+ style: "block",
5003
+ blinking: true
5004
+ },
5005
+ maxLength: 1000,
5006
+ value: ""
5007
+ };
5008
+ constructor(ctx, options) {
5009
+ super(ctx, { ...options, buffered: true });
5010
+ this._backgroundColor = parseColor(options.backgroundColor || this._defaultOptions.backgroundColor);
5011
+ this._textColor = parseColor(options.textColor || this._defaultOptions.textColor);
5012
+ this._focusedBackgroundColor = parseColor(options.focusedBackgroundColor || options.backgroundColor || this._defaultOptions.focusedBackgroundColor);
5013
+ this._focusedTextColor = parseColor(options.focusedTextColor || options.textColor || this._defaultOptions.focusedTextColor);
5014
+ this._placeholder = options.placeholder || this._defaultOptions.placeholder;
5015
+ this._value = options.value || this._defaultOptions.value;
5016
+ this._lastCommittedValue = this._value;
5017
+ this._cursorPosition = this._value.length;
5018
+ this._maxLength = options.maxLength || this._defaultOptions.maxLength;
5019
+ this._placeholderColor = parseColor(options.placeholderColor || this._defaultOptions.placeholderColor);
5020
+ this._cursorColor = parseColor(options.cursorColor || this._defaultOptions.cursorColor);
5021
+ this._cursorStyle = options.cursorStyle || this._defaultOptions.cursorStyle;
5022
+ }
5023
+ updateCursorPosition() {
5024
+ if (!this._focused)
5025
+ return;
5026
+ const contentX = 0;
5027
+ const contentY = 0;
5028
+ const contentWidth = this.width;
5029
+ const maxVisibleChars = contentWidth - 1;
5030
+ let displayStartIndex = 0;
5031
+ if (this._cursorPosition >= maxVisibleChars) {
5032
+ displayStartIndex = this._cursorPosition - maxVisibleChars + 1;
5033
+ }
5034
+ const cursorDisplayX = this._cursorPosition - displayStartIndex;
5035
+ if (cursorDisplayX >= 0 && cursorDisplayX < contentWidth) {
5036
+ const absoluteCursorX = this.x + contentX + cursorDisplayX + 1;
5037
+ const absoluteCursorY = this.y + contentY + 1;
5038
+ this._ctx.setCursorPosition(absoluteCursorX, absoluteCursorY, true);
5039
+ this._ctx.setCursorColor(this._cursorColor);
5040
+ }
5041
+ }
5042
+ focus() {
5043
+ super.focus();
5044
+ this._ctx.setCursorStyle(this._cursorStyle.style, this._cursorStyle.blinking);
5045
+ this._ctx.setCursorColor(this._cursorColor);
5046
+ this.updateCursorPosition();
5047
+ }
5048
+ blur() {
5049
+ super.blur();
5050
+ this._ctx.setCursorPosition(0, 0, false);
5051
+ if (this._value !== this._lastCommittedValue) {
5052
+ this._lastCommittedValue = this._value;
5053
+ this.emit("change" /* CHANGE */, this._value);
5054
+ }
5055
+ }
5056
+ renderSelf(buffer, deltaTime) {
5057
+ if (!this.visible || !this.frameBuffer)
5058
+ return;
5059
+ if (this.isDirty) {
5060
+ this.refreshFrameBuffer();
5061
+ }
5062
+ }
5063
+ refreshFrameBuffer() {
5064
+ if (!this.frameBuffer)
5065
+ return;
5066
+ const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
5067
+ this.frameBuffer.clear(bgColor);
5068
+ const contentX = 0;
5069
+ const contentY = 0;
5070
+ const contentWidth = this.width;
5071
+ const contentHeight = this.height;
5072
+ const displayText = this._value || this._placeholder;
5073
+ const isPlaceholder = !this._value && this._placeholder;
5074
+ const baseTextColor = this._focused ? this._focusedTextColor : this._textColor;
5075
+ const textColor = isPlaceholder ? this._placeholderColor : baseTextColor;
5076
+ const maxVisibleChars = contentWidth - 1;
5077
+ let displayStartIndex = 0;
5078
+ if (this._cursorPosition >= maxVisibleChars) {
5079
+ displayStartIndex = this._cursorPosition - maxVisibleChars + 1;
5080
+ }
5081
+ const visibleText = displayText.substring(displayStartIndex, displayStartIndex + maxVisibleChars);
5082
+ if (visibleText) {
5083
+ this.frameBuffer.drawText(visibleText, contentX, contentY, textColor);
5084
+ }
5085
+ if (this._focused) {
5086
+ this.updateCursorPosition();
5087
+ }
5088
+ }
5089
+ get value() {
5090
+ return this._value;
5091
+ }
5092
+ set value(value) {
5093
+ const newValue = value.substring(0, this._maxLength);
5094
+ if (this._value !== newValue) {
5095
+ this._value = newValue;
5096
+ this._cursorPosition = Math.min(this._cursorPosition, this._value.length);
5097
+ this.requestRender();
5098
+ this.updateCursorPosition();
5099
+ this.emit("input" /* INPUT */, this._value);
5100
+ }
5101
+ }
5102
+ set placeholder(placeholder) {
5103
+ if (this._placeholder !== placeholder) {
5104
+ this._placeholder = placeholder;
5105
+ this.requestRender();
5106
+ }
5107
+ }
5108
+ get cursorPosition() {
5109
+ return this._cursorPosition;
5110
+ }
5111
+ set cursorPosition(position) {
5112
+ const newPosition = Math.max(0, Math.min(position, this._value.length));
5113
+ if (this._cursorPosition !== newPosition) {
5114
+ this._cursorPosition = newPosition;
5115
+ this.requestRender();
5116
+ this.updateCursorPosition();
5117
+ }
5118
+ }
5119
+ insertText(text) {
5120
+ if (this._value.length + text.length > this._maxLength) {
5121
+ return;
5122
+ }
5123
+ const beforeCursor = this._value.substring(0, this._cursorPosition);
5124
+ const afterCursor = this._value.substring(this._cursorPosition);
5125
+ this._value = beforeCursor + text + afterCursor;
5126
+ this._cursorPosition += text.length;
5127
+ this.requestRender();
5128
+ this.updateCursorPosition();
5129
+ this.emit("input" /* INPUT */, this._value);
5130
+ }
5131
+ deleteCharacter(direction) {
5132
+ if (direction === "backward" && this._cursorPosition > 0) {
5133
+ const beforeCursor = this._value.substring(0, this._cursorPosition - 1);
5134
+ const afterCursor = this._value.substring(this._cursorPosition);
5135
+ this._value = beforeCursor + afterCursor;
5136
+ this._cursorPosition--;
5137
+ this.requestRender();
5138
+ this.updateCursorPosition();
5139
+ this.emit("input" /* INPUT */, this._value);
5140
+ } else if (direction === "forward" && this._cursorPosition < this._value.length) {
5141
+ const beforeCursor = this._value.substring(0, this._cursorPosition);
5142
+ const afterCursor = this._value.substring(this._cursorPosition + 1);
5143
+ this._value = beforeCursor + afterCursor;
5144
+ this.requestRender();
5145
+ this.updateCursorPosition();
5146
+ this.emit("input" /* INPUT */, this._value);
5147
+ }
5148
+ }
5149
+ handleKeyPress(key) {
5150
+ const keyName = typeof key === "string" ? key : key.name;
5151
+ const keySequence = typeof key === "string" ? key : key.sequence;
5152
+ switch (keyName) {
5153
+ case "left":
5154
+ this.cursorPosition = this._cursorPosition - 1;
5155
+ return true;
5156
+ case "right":
5157
+ this.cursorPosition = this._cursorPosition + 1;
5158
+ return true;
5159
+ case "home":
5160
+ this.cursorPosition = 0;
5161
+ return true;
3374
5162
  case "end":
3375
5163
  this.cursorPosition = this._value.length;
3376
5164
  return true;
@@ -4100,6 +5888,8 @@ class ScrollBoxRenderable extends BoxRenderable {
4100
5888
  cachedAutoScrollSpeed = 3;
4101
5889
  autoScrollAccumulatorX = 0;
4102
5890
  autoScrollAccumulatorY = 0;
5891
+ scrollAccumulatorX = 0;
5892
+ scrollAccumulatorY = 0;
4103
5893
  _stickyScroll;
4104
5894
  _stickyScrollTop = false;
4105
5895
  _stickyScrollBottom = false;
@@ -4375,14 +6165,35 @@ class ScrollBoxRenderable extends BoxRenderable {
4375
6165
  const baseDelta = event.scroll?.delta ?? 0;
4376
6166
  const now = Date.now();
4377
6167
  const multiplier = this.scrollAccel.tick(now);
6168
+ const scrollAmount = baseDelta * multiplier;
4378
6169
  if (dir === "up") {
4379
- this.scrollTop -= baseDelta * multiplier;
6170
+ this.scrollAccumulatorY -= scrollAmount;
6171
+ const integerScroll = Math.trunc(this.scrollAccumulatorY);
6172
+ if (integerScroll !== 0) {
6173
+ this.scrollTop += integerScroll;
6174
+ this.scrollAccumulatorY -= integerScroll;
6175
+ }
4380
6176
  } else if (dir === "down") {
4381
- this.scrollTop += baseDelta * multiplier;
6177
+ this.scrollAccumulatorY += scrollAmount;
6178
+ const integerScroll = Math.trunc(this.scrollAccumulatorY);
6179
+ if (integerScroll !== 0) {
6180
+ this.scrollTop += integerScroll;
6181
+ this.scrollAccumulatorY -= integerScroll;
6182
+ }
4382
6183
  } else if (dir === "left") {
4383
- this.scrollLeft -= baseDelta * multiplier;
6184
+ this.scrollAccumulatorX -= scrollAmount;
6185
+ const integerScroll = Math.trunc(this.scrollAccumulatorX);
6186
+ if (integerScroll !== 0) {
6187
+ this.scrollLeft += integerScroll;
6188
+ this.scrollAccumulatorX -= integerScroll;
6189
+ }
4384
6190
  } else if (dir === "right") {
4385
- this.scrollLeft += baseDelta * multiplier;
6191
+ this.scrollAccumulatorX += scrollAmount;
6192
+ const integerScroll = Math.trunc(this.scrollAccumulatorX);
6193
+ if (integerScroll !== 0) {
6194
+ this.scrollLeft += integerScroll;
6195
+ this.scrollAccumulatorX -= integerScroll;
6196
+ }
4386
6197
  }
4387
6198
  const maxScrollTop = Math.max(0, this.scrollHeight - this.viewport.height);
4388
6199
  const maxScrollLeft = Math.max(0, this.scrollWidth - this.viewport.width);
@@ -4400,15 +6211,21 @@ class ScrollBoxRenderable extends BoxRenderable {
4400
6211
  if (this.verticalScrollBar.handleKeyPress(key)) {
4401
6212
  this._hasManualScroll = true;
4402
6213
  this.scrollAccel.reset();
6214
+ this.resetScrollAccumulators();
4403
6215
  return true;
4404
6216
  }
4405
6217
  if (this.horizontalScrollBar.handleKeyPress(key)) {
4406
6218
  this._hasManualScroll = true;
4407
6219
  this.scrollAccel.reset();
6220
+ this.resetScrollAccumulators();
4408
6221
  return true;
4409
6222
  }
4410
6223
  return false;
4411
6224
  }
6225
+ resetScrollAccumulators() {
6226
+ this.scrollAccumulatorX = 0;
6227
+ this.scrollAccumulatorY = 0;
6228
+ }
4412
6229
  startAutoScroll(mouseX, mouseY) {
4413
6230
  this.stopAutoScroll();
4414
6231
  this.autoScrollMouseX = mouseX;
@@ -4715,7 +6532,6 @@ class SelectRenderable extends Renderable {
4715
6532
  }
4716
6533
  if (this._showDescription && itemY + this.fontHeight < contentY + contentHeight) {
4717
6534
  const descColor = isSelected ? this._selectedDescriptionColor : this._descriptionColor;
4718
- const descBg = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
4719
6535
  this.frameBuffer.drawText(option.description, descX, itemY + this.fontHeight, descColor);
4720
6536
  }
4721
6537
  }
@@ -5347,6 +7163,7 @@ class EditBufferRenderable extends Renderable {
5347
7163
  lastLocalSelection = null;
5348
7164
  _tabIndicator;
5349
7165
  _tabIndicatorColor;
7166
+ _selectionAnchorState = null;
5350
7167
  _cursorChangeListener = undefined;
5351
7168
  _contentChangeListener = undefined;
5352
7169
  editBuffer;
@@ -5403,6 +7220,9 @@ class EditBufferRenderable extends Renderable {
5403
7220
  this.setupMeasureFunc();
5404
7221
  this.setupEventListeners(options);
5405
7222
  }
7223
+ get lineInfo() {
7224
+ return this.editorView.getLogicalLineInfo();
7225
+ }
5406
7226
  setupEventListeners(options) {
5407
7227
  this._cursorChangeListener = options.onCursorChange;
5408
7228
  this._contentChangeListener = options.onContentChange;
@@ -5418,11 +7238,18 @@ class EditBufferRenderable extends Renderable {
5418
7238
  this.editBuffer.on("content-changed", () => {
5419
7239
  this.yogaNode.markDirty();
5420
7240
  this.requestRender();
7241
+ this.emit("line-info-change");
5421
7242
  if (this._contentChangeListener) {
5422
7243
  this._contentChangeListener({});
5423
7244
  }
5424
7245
  });
5425
7246
  }
7247
+ get lineCount() {
7248
+ return this.editBuffer.getLineCount();
7249
+ }
7250
+ get scrollY() {
7251
+ return this.editorView.getViewport().offsetY;
7252
+ }
5426
7253
  get plainText() {
5427
7254
  return this.editBuffer.getText();
5428
7255
  }
@@ -5615,19 +7442,25 @@ class EditBufferRenderable extends Renderable {
5615
7442
  }
5616
7443
  setupMeasureFunc() {
5617
7444
  const measureFunc = (width, widthMode, height, heightMode) => {
5618
- const effectiveHeight = isNaN(height) ? 1 : height;
5619
- const effectiveWidth = isNaN(width) ? 1 : width;
5620
- if (this._wrapMode !== "none" && this.width !== effectiveWidth) {
5621
- this.editorView.setViewportSize(effectiveWidth, effectiveHeight);
7445
+ let effectiveWidth;
7446
+ if (widthMode === MeasureMode.Undefined || isNaN(width)) {
7447
+ effectiveWidth = 0;
5622
7448
  } else {
5623
- this.editorView.setViewportSize(effectiveWidth, effectiveHeight);
7449
+ effectiveWidth = width;
7450
+ }
7451
+ const effectiveHeight = isNaN(height) ? 1 : height;
7452
+ const measureResult = this.editorView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
7453
+ const measuredWidth = measureResult ? Math.max(1, measureResult.maxWidth) : 1;
7454
+ const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
7455
+ if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
7456
+ return {
7457
+ width: Math.min(effectiveWidth, measuredWidth),
7458
+ height: Math.min(effectiveHeight, measuredHeight)
7459
+ };
5624
7460
  }
5625
- const lineInfo = this.editorView.getLogicalLineInfo();
5626
- const measuredWidth = lineInfo.maxLineWidth;
5627
- const measuredHeight = lineInfo.lineStarts.length;
5628
7461
  return {
5629
- width: Math.max(1, measuredWidth),
5630
- height: Math.max(1, measuredHeight)
7462
+ width: measuredWidth,
7463
+ height: measuredHeight
5631
7464
  };
5632
7465
  };
5633
7466
  this.yogaNode.setMeasureFunc(measureFunc);
@@ -5748,6 +7581,55 @@ class EditBufferRenderable extends Renderable {
5748
7581
  getTextRangeByCoords(startRow, startCol, endRow, endCol) {
5749
7582
  return this.editBuffer.getTextRangeByCoords(startRow, startCol, endRow, endCol);
5750
7583
  }
7584
+ updateSelectionForMovement(shiftPressed, isBeforeMovement) {
7585
+ if (!this.selectable)
7586
+ return;
7587
+ if (!shiftPressed) {
7588
+ this._ctx.clearSelection();
7589
+ this._selectionAnchorState = null;
7590
+ return;
7591
+ }
7592
+ const visualCursor = this.editorView.getVisualCursor();
7593
+ const viewport = this.editorView.getViewport();
7594
+ const cursorX = this.x + visualCursor.visualCol;
7595
+ const cursorY = this.y + visualCursor.visualRow;
7596
+ if (isBeforeMovement) {
7597
+ if (!this._ctx.hasSelection) {
7598
+ this._ctx.startSelection(this, cursorX, cursorY);
7599
+ this._selectionAnchorState = {
7600
+ screenX: cursorX,
7601
+ screenY: cursorY,
7602
+ viewportX: viewport.offsetX,
7603
+ viewportY: viewport.offsetY
7604
+ };
7605
+ } else if (!this._selectionAnchorState) {
7606
+ const selection = this._ctx.getSelection();
7607
+ if (selection && selection.isActive) {
7608
+ this._selectionAnchorState = {
7609
+ screenX: selection.anchor.x,
7610
+ screenY: selection.anchor.y,
7611
+ viewportX: viewport.offsetX,
7612
+ viewportY: viewport.offsetY
7613
+ };
7614
+ }
7615
+ }
7616
+ } else {
7617
+ if (this._selectionAnchorState) {
7618
+ const deltaY = viewport.offsetY - this._selectionAnchorState.viewportY;
7619
+ const deltaX = viewport.offsetX - this._selectionAnchorState.viewportX;
7620
+ if (deltaY !== 0 || deltaX !== 0) {
7621
+ const newAnchorX = this._selectionAnchorState.screenX - deltaX;
7622
+ const newAnchorY = this._selectionAnchorState.screenY - deltaY;
7623
+ this._ctx.startSelection(this, newAnchorX, newAnchorY);
7624
+ this._ctx.updateSelection(this, cursorX, cursorY);
7625
+ } else {
7626
+ this._ctx.updateSelection(this, cursorX, cursorY);
7627
+ }
7628
+ } else {
7629
+ this._ctx.updateSelection(this, cursorX, cursorY);
7630
+ }
7631
+ }
7632
+ }
5751
7633
  }
5752
7634
 
5753
7635
  // src/lib/keymapping.ts
@@ -5785,12 +7667,12 @@ var defaultTextareaKeybindings = [
5785
7667
  { name: "right", shift: true, action: "select-right" },
5786
7668
  { name: "up", shift: true, action: "select-up" },
5787
7669
  { name: "down", shift: true, action: "select-down" },
5788
- { name: "home", action: "line-home" },
5789
- { name: "end", action: "line-end" },
5790
- { name: "home", shift: true, action: "select-line-home" },
5791
- { name: "end", shift: true, action: "select-line-end" },
5792
- { name: "a", ctrl: true, action: "buffer-home" },
5793
- { name: "e", ctrl: true, action: "buffer-end" },
7670
+ { name: "home", action: "buffer-home" },
7671
+ { name: "end", action: "buffer-end" },
7672
+ { name: "home", shift: true, action: "select-buffer-home" },
7673
+ { name: "end", shift: true, action: "select-buffer-end" },
7674
+ { name: "a", ctrl: true, action: "line-home" },
7675
+ { name: "e", ctrl: true, action: "line-end" },
5794
7676
  { name: "f", ctrl: true, action: "move-right" },
5795
7677
  { name: "b", ctrl: true, action: "move-left" },
5796
7678
  { name: "d", ctrl: true, action: "delete-word-forward" },
@@ -5888,6 +7770,8 @@ class TextareaRenderable extends EditBufferRenderable {
5888
7770
  ["line-end", () => this.gotoLineEnd()],
5889
7771
  ["select-line-home", () => this.gotoLineHome({ select: true })],
5890
7772
  ["select-line-end", () => this.gotoLineEnd({ select: true })],
7773
+ ["select-buffer-home", () => this.gotoBufferHome({ select: true })],
7774
+ ["select-buffer-end", () => this.gotoBufferEnd({ select: true })],
5891
7775
  ["buffer-home", () => this.gotoBufferHome()],
5892
7776
  ["buffer-end", () => this.gotoBufferEnd()],
5893
7777
  ["delete-line", () => this.deleteLine()],
@@ -6004,33 +7888,33 @@ class TextareaRenderable extends EditBufferRenderable {
6004
7888
  }
6005
7889
  moveCursorLeft(options) {
6006
7890
  const select = options?.select ?? false;
6007
- this.handleShiftSelection(select, true);
7891
+ this.updateSelectionForMovement(select, true);
6008
7892
  this.editBuffer.moveCursorLeft();
6009
- this.handleShiftSelection(select, false);
7893
+ this.updateSelectionForMovement(select, false);
6010
7894
  this.requestRender();
6011
7895
  return true;
6012
7896
  }
6013
7897
  moveCursorRight(options) {
6014
7898
  const select = options?.select ?? false;
6015
- this.handleShiftSelection(select, true);
7899
+ this.updateSelectionForMovement(select, true);
6016
7900
  this.editBuffer.moveCursorRight();
6017
- this.handleShiftSelection(select, false);
7901
+ this.updateSelectionForMovement(select, false);
6018
7902
  this.requestRender();
6019
7903
  return true;
6020
7904
  }
6021
7905
  moveCursorUp(options) {
6022
7906
  const select = options?.select ?? false;
6023
- this.handleShiftSelection(select, true);
7907
+ this.updateSelectionForMovement(select, true);
6024
7908
  this.editorView.moveUpVisual();
6025
- this.handleShiftSelection(select, false);
7909
+ this.updateSelectionForMovement(select, false);
6026
7910
  this.requestRender();
6027
7911
  return true;
6028
7912
  }
6029
7913
  moveCursorDown(options) {
6030
7914
  const select = options?.select ?? false;
6031
- this.handleShiftSelection(select, true);
7915
+ this.updateSelectionForMovement(select, true);
6032
7916
  this.editorView.moveDownVisual();
6033
- this.handleShiftSelection(select, false);
7917
+ this.updateSelectionForMovement(select, false);
6034
7918
  this.requestRender();
6035
7919
  return true;
6036
7920
  }
@@ -6040,29 +7924,35 @@ class TextareaRenderable extends EditBufferRenderable {
6040
7924
  }
6041
7925
  gotoLineHome(options) {
6042
7926
  const select = options?.select ?? false;
6043
- this.handleShiftSelection(select, true);
7927
+ this.updateSelectionForMovement(select, true);
6044
7928
  const cursor = this.editorView.getCursor();
6045
7929
  this.editBuffer.setCursor(cursor.row, 0);
6046
- this.handleShiftSelection(select, false);
7930
+ this.updateSelectionForMovement(select, false);
6047
7931
  this.requestRender();
6048
7932
  return true;
6049
7933
  }
6050
7934
  gotoLineEnd(options) {
6051
7935
  const select = options?.select ?? false;
6052
- this.handleShiftSelection(select, true);
7936
+ this.updateSelectionForMovement(select, true);
6053
7937
  const eol = this.editBuffer.getEOL();
6054
7938
  this.editBuffer.setCursor(eol.row, eol.col);
6055
- this.handleShiftSelection(select, false);
7939
+ this.updateSelectionForMovement(select, false);
6056
7940
  this.requestRender();
6057
7941
  return true;
6058
7942
  }
6059
- gotoBufferHome() {
7943
+ gotoBufferHome(options) {
7944
+ const select = options?.select ?? false;
7945
+ this.updateSelectionForMovement(select, true);
6060
7946
  this.editBuffer.setCursor(0, 0);
7947
+ this.updateSelectionForMovement(select, false);
6061
7948
  this.requestRender();
6062
7949
  return true;
6063
7950
  }
6064
- gotoBufferEnd() {
7951
+ gotoBufferEnd(options) {
7952
+ const select = options?.select ?? false;
7953
+ this.updateSelectionForMovement(select, true);
6065
7954
  this.editBuffer.gotoLine(999999);
7955
+ this.updateSelectionForMovement(select, false);
6066
7956
  this.requestRender();
6067
7957
  return true;
6068
7958
  }
@@ -6097,19 +7987,19 @@ class TextareaRenderable extends EditBufferRenderable {
6097
7987
  }
6098
7988
  moveWordForward(options) {
6099
7989
  const select = options?.select ?? false;
6100
- this.handleShiftSelection(select, true);
7990
+ this.updateSelectionForMovement(select, true);
6101
7991
  const nextWord = this.editBuffer.getNextWordBoundary();
6102
7992
  this.editBuffer.setCursorByOffset(nextWord.offset);
6103
- this.handleShiftSelection(select, false);
7993
+ this.updateSelectionForMovement(select, false);
6104
7994
  this.requestRender();
6105
7995
  return true;
6106
7996
  }
6107
7997
  moveWordBackward(options) {
6108
7998
  const select = options?.select ?? false;
6109
- this.handleShiftSelection(select, true);
7999
+ this.updateSelectionForMovement(select, true);
6110
8000
  const prevWord = this.editBuffer.getPrevWordBoundary();
6111
8001
  this.editBuffer.setCursorByOffset(prevWord.offset);
6112
- this.handleShiftSelection(select, false);
8002
+ this.updateSelectionForMovement(select, false);
6113
8003
  this.requestRender();
6114
8004
  return true;
6115
8005
  }
@@ -6141,25 +8031,6 @@ class TextareaRenderable extends EditBufferRenderable {
6141
8031
  this.requestRender();
6142
8032
  return true;
6143
8033
  }
6144
- handleShiftSelection(shiftPressed, isBeforeMovement) {
6145
- if (!this.selectable)
6146
- return;
6147
- if (!shiftPressed) {
6148
- this._ctx.clearSelection();
6149
- return;
6150
- }
6151
- const visualCursor = this.editorView.getVisualCursor();
6152
- const viewport = this.editorView.getViewport();
6153
- const cursorX = this.x + visualCursor.visualCol;
6154
- const cursorY = this.y + (visualCursor.visualRow - viewport.offsetY);
6155
- if (isBeforeMovement) {
6156
- if (!this._ctx.hasSelection) {
6157
- this._ctx.startSelection(this, cursorX, cursorY);
6158
- }
6159
- } else {
6160
- this._ctx.updateSelection(this, cursorX, cursorY);
6161
- }
6162
- }
6163
8034
  focus() {
6164
8035
  super.focus();
6165
8036
  this.updateColors();
@@ -6389,6 +8260,7 @@ export {
6389
8260
  MacOSScrollAccel,
6390
8261
  LogLevel,
6391
8262
  LinearScrollAccel,
8263
+ LineNumberRenderable,
6392
8264
  LayoutEvents,
6393
8265
  KeyHandler,
6394
8266
  KeyEvent,
@@ -6403,6 +8275,7 @@ export {
6403
8275
  EditorView,
6404
8276
  EditBuffer,
6405
8277
  DistortionEffect,
8278
+ DiffRenderable,
6406
8279
  DebugOverlayCorner,
6407
8280
  DataPathsManager,
6408
8281
  ConsolePosition,
@@ -6423,5 +8296,5 @@ export {
6423
8296
  ASCIIFont
6424
8297
  };
6425
8298
 
6426
- //# debugId=B9B7175D268B0B9C64756E2164756E21
8299
+ //# debugId=84CD912F2F121D3E64756E2164756E21
6427
8300
  //# sourceMappingURL=index.js.map