@opentui/core 0.0.0-20251128-0889a764 → 0.0.0-20251202-71dcabc4

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
@@ -9,9 +9,7 @@ import {
9
9
  ConsolePosition,
10
10
  DataPathsManager,
11
11
  DebugOverlayCorner,
12
- Edge,
13
12
  ExtmarksController,
14
- Gutter,
15
13
  InternalKeyHandler,
16
14
  KeyEvent,
17
15
  KeyHandler,
@@ -19,7 +17,6 @@ import {
19
17
  LinearScrollAccel,
20
18
  LogLevel,
21
19
  MacOSScrollAccel,
22
- MeasureMode,
23
20
  MouseButton,
24
21
  MouseEvent,
25
22
  MouseParser,
@@ -38,6 +35,7 @@ import {
38
35
  TextAttributes,
39
36
  TextBuffer,
40
37
  TreeSitterClient,
38
+ __toESM,
41
39
  addDefaultParsers,
42
40
  bg,
43
41
  bgBlack,
@@ -74,7 +72,6 @@ import {
74
72
  dim,
75
73
  env,
76
74
  envRegistry,
77
- exports_src,
78
75
  extToFiletype,
79
76
  fg,
80
77
  fonts,
@@ -123,6 +120,7 @@ import {
123
120
  red,
124
121
  registerEnvVar,
125
122
  renderFontToFrameBuffer,
123
+ require_dist,
126
124
  resolveRenderLib,
127
125
  reverse,
128
126
  rgbToHex,
@@ -137,7 +135,7 @@ import {
137
135
  white,
138
136
  wrapWithDelegates,
139
137
  yellow
140
- } from "./index-rhx7c7kj.js";
138
+ } from "./index-r6acnfwr.js";
141
139
  // src/text-buffer-view.ts
142
140
  class TextBufferView {
143
141
  lib;
@@ -198,6 +196,10 @@ class TextBufferView {
198
196
  this.guard();
199
197
  this.lib.textBufferViewSetViewportSize(this.viewPtr, width, height);
200
198
  }
199
+ setViewport(x, y, width, height) {
200
+ this.guard();
201
+ this.lib.textBufferViewSetViewport(this.viewPtr, x, y, width, height);
202
+ }
201
203
  get lineInfo() {
202
204
  this.guard();
203
205
  return this.lib.textBufferViewGetLineInfo(this.viewPtr);
@@ -239,6 +241,10 @@ class TextBufferView {
239
241
  this.guard();
240
242
  return this.lib.textBufferViewMeasureForDimensions(this.viewPtr, width, height);
241
243
  }
244
+ getVirtualLineCount() {
245
+ this.guard();
246
+ return this.lib.textBufferViewGetVirtualLineCount(this.viewPtr);
247
+ }
242
248
  destroy() {
243
249
  if (this._destroyed)
244
250
  return;
@@ -2193,6 +2199,7 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
2193
2199
  }
2194
2200
  }
2195
2201
  // src/renderables/Box.ts
2202
+ var import_bun_yoga = __toESM(require_dist(), 1);
2196
2203
  function isGapType(value) {
2197
2204
  if (value === undefined) {
2198
2205
  return true;
@@ -2371,44 +2378,45 @@ class BoxRenderable extends Renderable {
2371
2378
  }
2372
2379
  applyYogaBorders() {
2373
2380
  const node = this.yogaNode;
2374
- node.setBorder(Edge.Left, this.borderSides.left ? 1 : 0);
2375
- node.setBorder(Edge.Right, this.borderSides.right ? 1 : 0);
2376
- node.setBorder(Edge.Top, this.borderSides.top ? 1 : 0);
2377
- node.setBorder(Edge.Bottom, this.borderSides.bottom ? 1 : 0);
2381
+ node.setBorder(import_bun_yoga.Edge.Left, this.borderSides.left ? 1 : 0);
2382
+ node.setBorder(import_bun_yoga.Edge.Right, this.borderSides.right ? 1 : 0);
2383
+ node.setBorder(import_bun_yoga.Edge.Top, this.borderSides.top ? 1 : 0);
2384
+ node.setBorder(import_bun_yoga.Edge.Bottom, this.borderSides.bottom ? 1 : 0);
2378
2385
  this.requestRender();
2379
2386
  }
2380
2387
  applyYogaGap(options) {
2381
2388
  const node = this.yogaNode;
2382
2389
  if (isGapType(options.gap)) {
2383
- node.setGap(Gutter.All, options.gap);
2390
+ node.setGap(import_bun_yoga.Gutter.All, options.gap);
2384
2391
  }
2385
2392
  if (isGapType(options.rowGap)) {
2386
- node.setGap(Gutter.Row, options.rowGap);
2393
+ node.setGap(import_bun_yoga.Gutter.Row, options.rowGap);
2387
2394
  }
2388
2395
  if (isGapType(options.columnGap)) {
2389
- node.setGap(Gutter.Column, options.columnGap);
2396
+ node.setGap(import_bun_yoga.Gutter.Column, options.columnGap);
2390
2397
  }
2391
2398
  }
2392
2399
  set gap(gap) {
2393
2400
  if (isGapType(gap)) {
2394
- this.yogaNode.setGap(Gutter.All, gap);
2401
+ this.yogaNode.setGap(import_bun_yoga.Gutter.All, gap);
2395
2402
  this.requestRender();
2396
2403
  }
2397
2404
  }
2398
2405
  set rowGap(rowGap) {
2399
2406
  if (isGapType(rowGap)) {
2400
- this.yogaNode.setGap(Gutter.Row, rowGap);
2407
+ this.yogaNode.setGap(import_bun_yoga.Gutter.Row, rowGap);
2401
2408
  this.requestRender();
2402
2409
  }
2403
2410
  }
2404
2411
  set columnGap(columnGap) {
2405
2412
  if (isGapType(columnGap)) {
2406
- this.yogaNode.setGap(Gutter.Column, columnGap);
2413
+ this.yogaNode.setGap(import_bun_yoga.Gutter.Column, columnGap);
2407
2414
  this.requestRender();
2408
2415
  }
2409
2416
  }
2410
2417
  }
2411
2418
  // src/renderables/TextBufferRenderable.ts
2419
+ var import_bun_yoga2 = __toESM(require_dist(), 1);
2412
2420
  class TextBufferRenderable extends Renderable {
2413
2421
  selectable = true;
2414
2422
  _defaultFg;
@@ -2420,6 +2428,8 @@ class TextBufferRenderable extends Renderable {
2420
2428
  lastLocalSelection = null;
2421
2429
  _tabIndicator;
2422
2430
  _tabIndicatorColor;
2431
+ _scrollX = 0;
2432
+ _scrollY = 0;
2423
2433
  textBuffer;
2424
2434
  textBufferView;
2425
2435
  _defaultOptions = {
@@ -2462,16 +2472,82 @@ class TextBufferRenderable extends Renderable {
2462
2472
  if (this._wrapMode !== "none" && this.width > 0) {
2463
2473
  this.textBufferView.setWrapWidth(this.width);
2464
2474
  }
2475
+ if (this.width > 0 && this.height > 0) {
2476
+ this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
2477
+ }
2465
2478
  this.updateTextInfo();
2466
2479
  }
2480
+ onMouseEvent(event) {
2481
+ if (event.type === "scroll") {
2482
+ this.handleScroll(event);
2483
+ }
2484
+ }
2485
+ handleScroll(event) {
2486
+ if (!event.scroll)
2487
+ return;
2488
+ const { direction, delta } = event.scroll;
2489
+ if (direction === "up") {
2490
+ this.scrollY -= delta;
2491
+ } else if (direction === "down") {
2492
+ this.scrollY += delta;
2493
+ }
2494
+ if (this._wrapMode === "none") {
2495
+ if (direction === "left") {
2496
+ this.scrollX -= delta;
2497
+ } else if (direction === "right") {
2498
+ this.scrollX += delta;
2499
+ }
2500
+ }
2501
+ }
2467
2502
  get lineInfo() {
2468
2503
  return this.textBufferView.logicalLineInfo;
2469
2504
  }
2470
2505
  get lineCount() {
2471
2506
  return this.textBuffer.getLineCount();
2472
2507
  }
2508
+ get virtualLineCount() {
2509
+ return this.textBufferView.getVirtualLineCount();
2510
+ }
2473
2511
  get scrollY() {
2474
- return 0;
2512
+ return this._scrollY;
2513
+ }
2514
+ set scrollY(value) {
2515
+ const maxScrollY = Math.max(0, this.scrollHeight - this.height);
2516
+ const clamped = Math.max(0, Math.min(value, maxScrollY));
2517
+ if (this._scrollY !== clamped) {
2518
+ this._scrollY = clamped;
2519
+ this.updateViewportOffset();
2520
+ this.requestRender();
2521
+ }
2522
+ }
2523
+ get scrollX() {
2524
+ return this._scrollX;
2525
+ }
2526
+ set scrollX(value) {
2527
+ const maxScrollX = Math.max(0, this.scrollWidth - this.width);
2528
+ const clamped = Math.max(0, Math.min(value, maxScrollX));
2529
+ if (this._scrollX !== clamped) {
2530
+ this._scrollX = clamped;
2531
+ this.updateViewportOffset();
2532
+ this.requestRender();
2533
+ }
2534
+ }
2535
+ get scrollWidth() {
2536
+ return this.lineInfo.maxLineWidth;
2537
+ }
2538
+ get scrollHeight() {
2539
+ return this.lineInfo.lineStarts.length;
2540
+ }
2541
+ get maxScrollY() {
2542
+ return Math.max(0, this.scrollHeight - this.height);
2543
+ }
2544
+ get maxScrollX() {
2545
+ return Math.max(0, this.scrollWidth - this.width);
2546
+ }
2547
+ updateViewportOffset() {
2548
+ if (this.width > 0 && this.height > 0) {
2549
+ this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
2550
+ }
2475
2551
  }
2476
2552
  get plainText() {
2477
2553
  return this.textBuffer.getPlainText();
@@ -2580,7 +2656,8 @@ class TextBufferRenderable extends Renderable {
2580
2656
  }
2581
2657
  }
2582
2658
  onResize(width, height) {
2583
- this.textBufferView.setViewportSize(width, height);
2659
+ this.textBufferView.setViewport(this._scrollX, this._scrollY, width, height);
2660
+ this.updateTextInfo();
2584
2661
  if (this.lastLocalSelection) {
2585
2662
  const changed = this.updateLocalSelection(this.lastLocalSelection);
2586
2663
  if (changed) {
@@ -2612,7 +2689,7 @@ class TextBufferRenderable extends Renderable {
2612
2689
  setupMeasureFunc() {
2613
2690
  const measureFunc = (width, widthMode, height, heightMode) => {
2614
2691
  let effectiveWidth;
2615
- if (widthMode === MeasureMode.Undefined || isNaN(width)) {
2692
+ if (widthMode === import_bun_yoga2.MeasureMode.Undefined || isNaN(width)) {
2616
2693
  effectiveWidth = 0;
2617
2694
  } else {
2618
2695
  effectiveWidth = width;
@@ -2621,7 +2698,7 @@ class TextBufferRenderable extends Renderable {
2621
2698
  const measureResult = this.textBufferView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
2622
2699
  const measuredWidth = measureResult ? Math.max(1, measureResult.maxWidth) : 1;
2623
2700
  const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
2624
- if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
2701
+ if (widthMode === import_bun_yoga2.MeasureMode.AtMost && this._positionType !== "absolute") {
2625
2702
  return {
2626
2703
  width: Math.min(effectiveWidth, measuredWidth),
2627
2704
  height: Math.min(effectiveHeight, measuredHeight)
@@ -3249,12 +3326,12 @@ class GutterRenderable extends Renderable {
3249
3326
  this._lineNumberOffset = options.lineNumberOffset;
3250
3327
  this._hideLineNumbers = options.hideLineNumbers;
3251
3328
  this._lineNumbers = options.lineNumbers ?? new Map;
3252
- this._lastKnownLineCount = this.target.lineCount;
3329
+ this._lastKnownLineCount = this.target.virtualLineCount;
3253
3330
  this._lastKnownScrollY = this.target.scrollY;
3254
3331
  this.calculateSignWidths();
3255
3332
  this.setupMeasureFunc();
3256
3333
  this.onLifecyclePass = () => {
3257
- const currentLineCount = this.target.lineCount;
3334
+ const currentLineCount = this.target.virtualLineCount;
3258
3335
  if (currentLineCount !== this._lastKnownLineCount) {
3259
3336
  this._lastKnownLineCount = currentLineCount;
3260
3337
  this.yogaNode.markDirty();
@@ -3265,7 +3342,7 @@ class GutterRenderable extends Renderable {
3265
3342
  setupMeasureFunc() {
3266
3343
  const measureFunc = (width, widthMode, height, heightMode) => {
3267
3344
  const gutterWidth = this.calculateWidth();
3268
- const gutterHeight = this.target.lineCount;
3345
+ const gutterHeight = this.target.virtualLineCount;
3269
3346
  return {
3270
3347
  width: gutterWidth,
3271
3348
  height: gutterHeight
@@ -3276,6 +3353,23 @@ class GutterRenderable extends Renderable {
3276
3353
  remeasure() {
3277
3354
  this.yogaNode.markDirty();
3278
3355
  }
3356
+ setLineNumberOffset(offset) {
3357
+ if (this._lineNumberOffset !== offset) {
3358
+ this._lineNumberOffset = offset;
3359
+ this.yogaNode.markDirty();
3360
+ this.requestRender();
3361
+ }
3362
+ }
3363
+ setHideLineNumbers(hideLineNumbers) {
3364
+ this._hideLineNumbers = hideLineNumbers;
3365
+ this.yogaNode.markDirty();
3366
+ this.requestRender();
3367
+ }
3368
+ setLineNumbers(lineNumbers) {
3369
+ this._lineNumbers = lineNumbers;
3370
+ this.yogaNode.markDirty();
3371
+ this.requestRender();
3372
+ }
3279
3373
  calculateSignWidths() {
3280
3374
  this._maxBeforeWidth = 0;
3281
3375
  this._maxAfterWidth = 0;
@@ -3291,7 +3385,7 @@ class GutterRenderable extends Renderable {
3291
3385
  }
3292
3386
  }
3293
3387
  calculateWidth() {
3294
- const totalLines = this.target.lineCount;
3388
+ const totalLines = this.target.virtualLineCount;
3295
3389
  let maxLineNumber = totalLines + this._lineNumberOffset;
3296
3390
  if (this._lineNumbers.size > 0) {
3297
3391
  for (const customLineNum of this._lineNumbers.values()) {
@@ -3495,7 +3589,7 @@ class LineNumberRenderable extends Renderable {
3495
3589
  super.add(this.target);
3496
3590
  }
3497
3591
  add(child) {
3498
- if (!this.target && "lineInfo" in child && "lineCount" in child && "scrollY" in child) {
3592
+ if (!this.target && "lineInfo" in child && "lineCount" in child && "virtualLineCount" in child && "scrollY" in child) {
3499
3593
  this.setTarget(child);
3500
3594
  return this.getChildrenCount() - 1;
3501
3595
  }
@@ -3634,13 +3728,8 @@ class LineNumberRenderable extends Renderable {
3634
3728
  set lineNumberOffset(value) {
3635
3729
  if (this._lineNumberOffset !== value) {
3636
3730
  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);
3731
+ if (this.gutter) {
3732
+ this.gutter.setLineNumberOffset(value);
3644
3733
  }
3645
3734
  }
3646
3735
  }
@@ -3649,13 +3738,8 @@ class LineNumberRenderable extends Renderable {
3649
3738
  }
3650
3739
  setHideLineNumbers(hideLineNumbers) {
3651
3740
  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);
3741
+ if (this.gutter) {
3742
+ this.gutter.setHideLineNumbers(hideLineNumbers);
3659
3743
  }
3660
3744
  }
3661
3745
  getHideLineNumbers() {
@@ -3663,13 +3747,8 @@ class LineNumberRenderable extends Renderable {
3663
3747
  }
3664
3748
  setLineNumbers(lineNumbers) {
3665
3749
  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);
3750
+ if (this.gutter) {
3751
+ this.gutter.setLineNumbers(lineNumbers);
3673
3752
  }
3674
3753
  }
3675
3754
  getLineNumbers() {
@@ -4392,22 +4471,128 @@ function parsePatch(uniDiff) {
4392
4471
  return list;
4393
4472
  }
4394
4473
 
4474
+ // src/renderables/Text.ts
4475
+ class TextRenderable extends TextBufferRenderable {
4476
+ _text;
4477
+ _hasManualStyledText = false;
4478
+ rootTextNode;
4479
+ _contentDefaultOptions = {
4480
+ content: ""
4481
+ };
4482
+ constructor(ctx, options) {
4483
+ super(ctx, options);
4484
+ const content = options.content ?? this._contentDefaultOptions.content;
4485
+ const styledText = typeof content === "string" ? stringToStyledText(content) : content;
4486
+ this._text = styledText;
4487
+ this._hasManualStyledText = options.content !== undefined && content !== "";
4488
+ this.rootTextNode = new RootTextNodeRenderable(ctx, {
4489
+ id: `${this.id}-root`,
4490
+ fg: this._defaultFg,
4491
+ bg: this._defaultBg,
4492
+ attributes: this._defaultAttributes
4493
+ }, this);
4494
+ this.updateTextBuffer(styledText);
4495
+ }
4496
+ updateTextBuffer(styledText) {
4497
+ this.textBuffer.setStyledText(styledText);
4498
+ this.clearChunks(styledText);
4499
+ }
4500
+ clearChunks(styledText) {}
4501
+ get content() {
4502
+ return this._text;
4503
+ }
4504
+ get chunks() {
4505
+ return this._text.chunks;
4506
+ }
4507
+ get textNode() {
4508
+ return this.rootTextNode;
4509
+ }
4510
+ set content(value) {
4511
+ this._hasManualStyledText = true;
4512
+ const styledText = typeof value === "string" ? stringToStyledText(value) : value;
4513
+ if (this._text !== styledText) {
4514
+ this._text = styledText;
4515
+ this.updateTextBuffer(styledText);
4516
+ this.updateTextInfo();
4517
+ }
4518
+ }
4519
+ updateTextFromNodes() {
4520
+ if (this.rootTextNode.isDirty && !this._hasManualStyledText) {
4521
+ const chunks = this.rootTextNode.gatherWithInheritedStyle({
4522
+ fg: this._defaultFg,
4523
+ bg: this._defaultBg,
4524
+ attributes: this._defaultAttributes
4525
+ });
4526
+ this.textBuffer.setStyledText(new StyledText(chunks));
4527
+ this.refreshLocalSelection();
4528
+ this.yogaNode.markDirty();
4529
+ }
4530
+ }
4531
+ add(obj, index) {
4532
+ return this.rootTextNode.add(obj, index);
4533
+ }
4534
+ remove(id) {
4535
+ this.rootTextNode.remove(id);
4536
+ }
4537
+ insertBefore(obj, anchor) {
4538
+ this.rootTextNode.insertBefore(obj, anchor);
4539
+ return this.rootTextNode.children.indexOf(obj);
4540
+ }
4541
+ getTextChildren() {
4542
+ return this.rootTextNode.getChildren();
4543
+ }
4544
+ clear() {
4545
+ this.rootTextNode.clear();
4546
+ const emptyStyledText = stringToStyledText("");
4547
+ this._text = emptyStyledText;
4548
+ this.updateTextBuffer(emptyStyledText);
4549
+ this.updateTextInfo();
4550
+ this.requestRender();
4551
+ }
4552
+ onLifecyclePass = () => {
4553
+ this.updateTextFromNodes();
4554
+ };
4555
+ onFgChanged(newColor) {
4556
+ this.rootTextNode.fg = newColor;
4557
+ }
4558
+ onBgChanged(newColor) {
4559
+ this.rootTextNode.bg = newColor;
4560
+ }
4561
+ onAttributesChanged(newAttributes) {
4562
+ this.rootTextNode.attributes = newAttributes;
4563
+ }
4564
+ destroy() {
4565
+ this.rootTextNode.children.length = 0;
4566
+ super.destroy();
4567
+ }
4568
+ }
4569
+
4395
4570
  // src/renderables/Diff.ts
4396
4571
  class DiffRenderable extends Renderable {
4397
4572
  _diff;
4398
4573
  _view;
4399
4574
  _parsedDiff = null;
4575
+ _parseError = null;
4400
4576
  _filetype;
4401
4577
  _syntaxStyle;
4402
4578
  _wrapMode;
4403
4579
  _conceal;
4580
+ _selectionBg;
4581
+ _selectionFg;
4582
+ _treeSitterClient;
4404
4583
  _showLineNumbers;
4405
4584
  _lineNumberFg;
4406
4585
  _lineNumberBg;
4407
4586
  _addedBg;
4408
4587
  _removedBg;
4588
+ _contextBg;
4589
+ _addedContentBg;
4590
+ _removedContentBg;
4591
+ _contextContentBg;
4409
4592
  _addedSignColor;
4410
4593
  _removedSignColor;
4594
+ _addedLineNumberBg;
4595
+ _removedLineNumberBg;
4411
4596
  leftSide = null;
4412
4597
  rightSide = null;
4413
4598
  leftSideAdded = false;
@@ -4415,6 +4600,9 @@ class DiffRenderable extends Renderable {
4415
4600
  leftCodeRenderable = null;
4416
4601
  rightCodeRenderable = null;
4417
4602
  pendingRebuild = false;
4603
+ _lastWidth = 0;
4604
+ errorTextRenderable = null;
4605
+ errorCodeRenderable = null;
4418
4606
  constructor(ctx, options) {
4419
4607
  super(ctx, {
4420
4608
  ...options,
@@ -4425,14 +4613,23 @@ class DiffRenderable extends Renderable {
4425
4613
  this._filetype = options.filetype;
4426
4614
  this._syntaxStyle = options.syntaxStyle;
4427
4615
  this._wrapMode = options.wrapMode;
4428
- this._conceal = options.conceal ?? true;
4616
+ this._conceal = options.conceal ?? false;
4617
+ this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : undefined;
4618
+ this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : undefined;
4619
+ this._treeSitterClient = options.treeSitterClient;
4429
4620
  this._showLineNumbers = options.showLineNumbers ?? true;
4430
4621
  this._lineNumberFg = parseColor(options.lineNumberFg ?? "#888888");
4431
4622
  this._lineNumberBg = parseColor(options.lineNumberBg ?? "transparent");
4432
4623
  this._addedBg = parseColor(options.addedBg ?? "#1a4d1a");
4433
4624
  this._removedBg = parseColor(options.removedBg ?? "#4d1a1a");
4625
+ this._contextBg = parseColor(options.contextBg ?? "transparent");
4626
+ this._addedContentBg = options.addedContentBg ? parseColor(options.addedContentBg) : null;
4627
+ this._removedContentBg = options.removedContentBg ? parseColor(options.removedContentBg) : null;
4628
+ this._contextContentBg = options.contextContentBg ? parseColor(options.contextContentBg) : null;
4434
4629
  this._addedSignColor = parseColor(options.addedSignColor ?? "#22c55e");
4435
4630
  this._removedSignColor = parseColor(options.removedSignColor ?? "#ef4444");
4631
+ this._addedLineNumberBg = parseColor(options.addedLineNumberBg ?? "transparent");
4632
+ this._removedLineNumberBg = parseColor(options.removedLineNumberBg ?? "transparent");
4436
4633
  if (this._diff) {
4437
4634
  this.parseDiff();
4438
4635
  this.buildView();
@@ -4441,16 +4638,28 @@ class DiffRenderable extends Renderable {
4441
4638
  parseDiff() {
4442
4639
  if (!this._diff) {
4443
4640
  this._parsedDiff = null;
4641
+ this._parseError = null;
4444
4642
  return;
4445
4643
  }
4446
- const patches = parsePatch(this._diff);
4447
- if (patches.length === 0) {
4644
+ try {
4645
+ const patches = parsePatch(this._diff);
4646
+ if (patches.length === 0) {
4647
+ this._parsedDiff = null;
4648
+ this._parseError = null;
4649
+ return;
4650
+ }
4651
+ this._parsedDiff = patches[0];
4652
+ this._parseError = null;
4653
+ } catch (error) {
4448
4654
  this._parsedDiff = null;
4449
- return;
4655
+ this._parseError = error instanceof Error ? error : new Error(String(error));
4450
4656
  }
4451
- this._parsedDiff = patches[0];
4452
4657
  }
4453
4658
  buildView() {
4659
+ if (this._parseError) {
4660
+ this.buildErrorView();
4661
+ return;
4662
+ }
4454
4663
  if (!this._parsedDiff || this._parsedDiff.hunks.length === 0) {
4455
4664
  return;
4456
4665
  }
@@ -4463,7 +4672,10 @@ class DiffRenderable extends Renderable {
4463
4672
  onResize(width, height) {
4464
4673
  super.onResize(width, height);
4465
4674
  if (this._view === "split" && this._wrapMode !== "none" && this._wrapMode !== undefined) {
4466
- this.requestRebuild();
4675
+ if (this._lastWidth !== width) {
4676
+ this._lastWidth = width;
4677
+ this.requestRebuild();
4678
+ }
4467
4679
  }
4468
4680
  }
4469
4681
  requestRebuild() {
@@ -4479,15 +4691,177 @@ class DiffRenderable extends Renderable {
4479
4691
  }
4480
4692
  });
4481
4693
  }
4694
+ rebuildView() {
4695
+ if (this._view === "split") {
4696
+ this.requestRebuild();
4697
+ } else {
4698
+ this.buildView();
4699
+ }
4700
+ }
4482
4701
  destroyRecursively() {
4483
4702
  this.pendingRebuild = false;
4484
4703
  this.leftSideAdded = false;
4485
4704
  this.rightSideAdded = false;
4486
4705
  super.destroyRecursively();
4487
4706
  }
4707
+ buildErrorView() {
4708
+ this.flexDirection = "column";
4709
+ if (this.leftSide && this.leftSideAdded) {
4710
+ super.remove(this.leftSide.id);
4711
+ this.leftSideAdded = false;
4712
+ }
4713
+ if (this.rightSide && this.rightSideAdded) {
4714
+ super.remove(this.rightSide.id);
4715
+ this.rightSideAdded = false;
4716
+ }
4717
+ const errorMessage = `Error parsing diff: ${this._parseError?.message || "Unknown error"}
4718
+ `;
4719
+ if (!this.errorTextRenderable) {
4720
+ this.errorTextRenderable = new TextRenderable(this.ctx, {
4721
+ id: this.id ? `${this.id}-error-text` : undefined,
4722
+ content: errorMessage,
4723
+ fg: "#ef4444",
4724
+ width: "100%",
4725
+ flexShrink: 0
4726
+ });
4727
+ super.add(this.errorTextRenderable);
4728
+ } else {
4729
+ this.errorTextRenderable.content = errorMessage;
4730
+ const errorTextIndex = this.getChildren().indexOf(this.errorTextRenderable);
4731
+ if (errorTextIndex === -1) {
4732
+ super.add(this.errorTextRenderable);
4733
+ }
4734
+ }
4735
+ if (!this.errorCodeRenderable) {
4736
+ this.errorCodeRenderable = new CodeRenderable(this.ctx, {
4737
+ id: this.id ? `${this.id}-error-code` : undefined,
4738
+ content: this._diff,
4739
+ filetype: "diff",
4740
+ syntaxStyle: this._syntaxStyle ?? SyntaxStyle.create(),
4741
+ wrapMode: this._wrapMode,
4742
+ conceal: this._conceal,
4743
+ width: "100%",
4744
+ flexGrow: 1,
4745
+ flexShrink: 1,
4746
+ ...this._treeSitterClient !== undefined && { treeSitterClient: this._treeSitterClient }
4747
+ });
4748
+ super.add(this.errorCodeRenderable);
4749
+ } else {
4750
+ this.errorCodeRenderable.content = this._diff;
4751
+ this.errorCodeRenderable.wrapMode = this._wrapMode ?? "none";
4752
+ if (this._syntaxStyle) {
4753
+ this.errorCodeRenderable.syntaxStyle = this._syntaxStyle;
4754
+ }
4755
+ const errorCodeIndex = this.getChildren().indexOf(this.errorCodeRenderable);
4756
+ if (errorCodeIndex === -1) {
4757
+ super.add(this.errorCodeRenderable);
4758
+ }
4759
+ }
4760
+ }
4761
+ createOrUpdateCodeRenderable(side, content, wrapMode, drawUnstyledText) {
4762
+ const existingRenderable = side === "left" ? this.leftCodeRenderable : this.rightCodeRenderable;
4763
+ if (!existingRenderable) {
4764
+ const codeOptions = {
4765
+ id: this.id ? `${this.id}-${side}-code` : undefined,
4766
+ content,
4767
+ filetype: this._filetype,
4768
+ wrapMode,
4769
+ conceal: this._conceal,
4770
+ syntaxStyle: this._syntaxStyle ?? SyntaxStyle.create(),
4771
+ width: "100%",
4772
+ height: "100%",
4773
+ ...drawUnstyledText !== undefined && { drawUnstyledText },
4774
+ ...this._selectionBg !== undefined && { selectionBg: this._selectionBg },
4775
+ ...this._selectionFg !== undefined && { selectionFg: this._selectionFg },
4776
+ ...this._treeSitterClient !== undefined && { treeSitterClient: this._treeSitterClient }
4777
+ };
4778
+ const newRenderable = new CodeRenderable(this.ctx, codeOptions);
4779
+ if (side === "left") {
4780
+ this.leftCodeRenderable = newRenderable;
4781
+ } else {
4782
+ this.rightCodeRenderable = newRenderable;
4783
+ }
4784
+ return newRenderable;
4785
+ } else {
4786
+ existingRenderable.content = content;
4787
+ existingRenderable.wrapMode = wrapMode ?? "none";
4788
+ existingRenderable.conceal = this._conceal;
4789
+ if (drawUnstyledText !== undefined) {
4790
+ existingRenderable.drawUnstyledText = drawUnstyledText;
4791
+ }
4792
+ if (this._filetype !== undefined) {
4793
+ existingRenderable.filetype = this._filetype;
4794
+ }
4795
+ if (this._syntaxStyle !== undefined) {
4796
+ existingRenderable.syntaxStyle = this._syntaxStyle;
4797
+ }
4798
+ if (this._selectionBg !== undefined) {
4799
+ existingRenderable.selectionBg = this._selectionBg;
4800
+ }
4801
+ if (this._selectionFg !== undefined) {
4802
+ existingRenderable.selectionFg = this._selectionFg;
4803
+ }
4804
+ return existingRenderable;
4805
+ }
4806
+ }
4807
+ createOrUpdateSide(side, target, lineColors, lineSigns, lineNumbers, hideLineNumbers, width) {
4808
+ const sideRef = side === "left" ? this.leftSide : this.rightSide;
4809
+ const addedFlag = side === "left" ? this.leftSideAdded : this.rightSideAdded;
4810
+ if (!sideRef) {
4811
+ const newSide = new LineNumberRenderable(this.ctx, {
4812
+ id: this.id ? `${this.id}-${side}` : undefined,
4813
+ target,
4814
+ fg: this._lineNumberFg,
4815
+ bg: this._lineNumberBg,
4816
+ lineColors,
4817
+ lineSigns,
4818
+ lineNumbers,
4819
+ lineNumberOffset: 0,
4820
+ hideLineNumbers,
4821
+ width,
4822
+ height: "100%"
4823
+ });
4824
+ newSide.showLineNumbers = this._showLineNumbers;
4825
+ super.add(newSide);
4826
+ if (side === "left") {
4827
+ this.leftSide = newSide;
4828
+ this.leftSideAdded = true;
4829
+ } else {
4830
+ this.rightSide = newSide;
4831
+ this.rightSideAdded = true;
4832
+ }
4833
+ } else {
4834
+ sideRef.width = width;
4835
+ sideRef.setLineColors(lineColors);
4836
+ sideRef.setLineSigns(lineSigns);
4837
+ sideRef.setLineNumbers(lineNumbers);
4838
+ sideRef.setHideLineNumbers(hideLineNumbers);
4839
+ if (!addedFlag) {
4840
+ super.add(sideRef);
4841
+ if (side === "left") {
4842
+ this.leftSideAdded = true;
4843
+ } else {
4844
+ this.rightSideAdded = true;
4845
+ }
4846
+ }
4847
+ }
4848
+ }
4488
4849
  buildUnifiedView() {
4489
4850
  if (!this._parsedDiff)
4490
4851
  return;
4852
+ this.flexDirection = "column";
4853
+ if (this.errorTextRenderable) {
4854
+ const errorTextIndex = this.getChildren().indexOf(this.errorTextRenderable);
4855
+ if (errorTextIndex !== -1) {
4856
+ super.remove(this.errorTextRenderable.id);
4857
+ }
4858
+ }
4859
+ if (this.errorCodeRenderable) {
4860
+ const errorCodeIndex = this.getChildren().indexOf(this.errorCodeRenderable);
4861
+ if (errorCodeIndex !== -1) {
4862
+ super.remove(this.errorCodeRenderable.id);
4863
+ }
4864
+ }
4491
4865
  const contentLines = [];
4492
4866
  const lineColors = new Map;
4493
4867
  const lineSigns = new Map;
@@ -4501,7 +4875,15 @@ class DiffRenderable extends Renderable {
4501
4875
  const content2 = line.slice(1);
4502
4876
  if (firstChar === "+") {
4503
4877
  contentLines.push(content2);
4504
- lineColors.set(lineIndex, this._addedBg);
4878
+ const config = {
4879
+ gutter: this._addedLineNumberBg
4880
+ };
4881
+ if (this._addedContentBg) {
4882
+ config.content = this._addedContentBg;
4883
+ } else {
4884
+ config.content = this._addedBg;
4885
+ }
4886
+ lineColors.set(lineIndex, config);
4505
4887
  lineSigns.set(lineIndex, {
4506
4888
  after: " +",
4507
4889
  afterColor: this._addedSignColor
@@ -4511,7 +4893,15 @@ class DiffRenderable extends Renderable {
4511
4893
  lineIndex++;
4512
4894
  } else if (firstChar === "-") {
4513
4895
  contentLines.push(content2);
4514
- lineColors.set(lineIndex, this._removedBg);
4896
+ const config = {
4897
+ gutter: this._removedLineNumberBg
4898
+ };
4899
+ if (this._removedContentBg) {
4900
+ config.content = this._removedContentBg;
4901
+ } else {
4902
+ config.content = this._removedBg;
4903
+ }
4904
+ lineColors.set(lineIndex, config);
4515
4905
  lineSigns.set(lineIndex, {
4516
4906
  after: " -",
4517
4907
  afterColor: this._removedSignColor
@@ -4521,6 +4911,15 @@ class DiffRenderable extends Renderable {
4521
4911
  lineIndex++;
4522
4912
  } else if (firstChar === " ") {
4523
4913
  contentLines.push(content2);
4914
+ const config = {
4915
+ gutter: this._lineNumberBg
4916
+ };
4917
+ if (this._contextContentBg) {
4918
+ config.content = this._contextContentBg;
4919
+ } else {
4920
+ config.content = this._contextBg;
4921
+ }
4922
+ lineColors.set(lineIndex, config);
4524
4923
  lineNumbers.set(lineIndex, newLineNum);
4525
4924
  oldLineNum++;
4526
4925
  newLineNum++;
@@ -4530,58 +4929,8 @@ class DiffRenderable extends Renderable {
4530
4929
  }
4531
4930
  const content = contentLines.join(`
4532
4931
  `);
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
- }
4932
+ const codeRenderable = this.createOrUpdateCodeRenderable("left", content, this._wrapMode);
4933
+ this.createOrUpdateSide("left", codeRenderable, lineColors, lineSigns, lineNumbers, new Set, "100%");
4585
4934
  if (this.rightSide && this.rightSideAdded) {
4586
4935
  super.remove(this.rightSide.id);
4587
4936
  this.rightSideAdded = false;
@@ -4590,6 +4939,19 @@ class DiffRenderable extends Renderable {
4590
4939
  buildSplitView() {
4591
4940
  if (!this._parsedDiff)
4592
4941
  return;
4942
+ this.flexDirection = "row";
4943
+ if (this.errorTextRenderable) {
4944
+ const errorTextIndex = this.getChildren().indexOf(this.errorTextRenderable);
4945
+ if (errorTextIndex !== -1) {
4946
+ super.remove(this.errorTextRenderable.id);
4947
+ }
4948
+ }
4949
+ if (this.errorCodeRenderable) {
4950
+ const errorCodeIndex = this.getChildren().indexOf(this.errorCodeRenderable);
4951
+ if (errorCodeIndex !== -1) {
4952
+ super.remove(this.errorCodeRenderable.id);
4953
+ }
4954
+ }
4593
4955
  const leftLogicalLines = [];
4594
4956
  const rightLogicalLines = [];
4595
4957
  for (const hunk of this._parsedDiff.hunks) {
@@ -4604,11 +4966,13 @@ class DiffRenderable extends Renderable {
4604
4966
  leftLogicalLines.push({
4605
4967
  content,
4606
4968
  lineNum: oldLineNum,
4969
+ color: this._contextBg,
4607
4970
  type: "context"
4608
4971
  });
4609
4972
  rightLogicalLines.push({
4610
4973
  content,
4611
4974
  lineNum: newLineNum,
4975
+ color: this._contextBg,
4612
4976
  type: "context"
4613
4977
  });
4614
4978
  oldLineNum++;
@@ -4682,64 +5046,15 @@ class DiffRenderable extends Renderable {
4682
5046
  `);
4683
5047
  const preRightContent = rightLogicalLines.map((l) => l.content).join(`
4684
5048
  `);
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
- }
5049
+ const needsConsistentConcealing = (this._wrapMode === "word" || this._wrapMode === "char") && this._conceal && this._filetype;
5050
+ const drawUnstyledText = !needsConsistentConcealing;
5051
+ const leftCodeRenderable = this.createOrUpdateCodeRenderable("left", preLeftContent, this._wrapMode, drawUnstyledText);
5052
+ const rightCodeRenderable = this.createOrUpdateCodeRenderable("right", preRightContent, this._wrapMode, drawUnstyledText);
4738
5053
  let finalLeftLines;
4739
5054
  let finalRightLines;
4740
5055
  if (canDoWrapAlignment) {
4741
- const leftLineInfo = this.leftCodeRenderable.lineInfo;
4742
- const rightLineInfo = this.rightCodeRenderable.lineInfo;
5056
+ const leftLineInfo = leftCodeRenderable.lineInfo;
5057
+ const rightLineInfo = rightCodeRenderable.lineInfo;
4743
5058
  const leftSources = leftLineInfo.lineSources || [];
4744
5059
  const rightSources = rightLineInfo.lineSources || [];
4745
5060
  const leftVisualCounts = new Map;
@@ -4807,8 +5122,26 @@ class DiffRenderable extends Renderable {
4807
5122
  if (line.hideLineNumber) {
4808
5123
  leftHideLineNumbers.add(index);
4809
5124
  }
4810
- if (line.color) {
4811
- leftLineColors.set(index, line.color);
5125
+ if (line.type === "remove") {
5126
+ const config = {
5127
+ gutter: this._removedLineNumberBg
5128
+ };
5129
+ if (this._removedContentBg) {
5130
+ config.content = this._removedContentBg;
5131
+ } else {
5132
+ config.content = this._removedBg;
5133
+ }
5134
+ leftLineColors.set(index, config);
5135
+ } else if (line.type === "context") {
5136
+ const config = {
5137
+ gutter: this._lineNumberBg
5138
+ };
5139
+ if (this._contextContentBg) {
5140
+ config.content = this._contextContentBg;
5141
+ } else {
5142
+ config.content = this._contextBg;
5143
+ }
5144
+ leftLineColors.set(index, config);
4812
5145
  }
4813
5146
  if (line.sign) {
4814
5147
  leftLineSigns.set(index, line.sign);
@@ -4821,8 +5154,26 @@ class DiffRenderable extends Renderable {
4821
5154
  if (line.hideLineNumber) {
4822
5155
  rightHideLineNumbers.add(index);
4823
5156
  }
4824
- if (line.color) {
4825
- rightLineColors.set(index, line.color);
5157
+ if (line.type === "add") {
5158
+ const config = {
5159
+ gutter: this._addedLineNumberBg
5160
+ };
5161
+ if (this._addedContentBg) {
5162
+ config.content = this._addedContentBg;
5163
+ } else {
5164
+ config.content = this._addedBg;
5165
+ }
5166
+ rightLineColors.set(index, config);
5167
+ } else if (line.type === "context") {
5168
+ const config = {
5169
+ gutter: this._lineNumberBg
5170
+ };
5171
+ if (this._contextContentBg) {
5172
+ config.content = this._contextContentBg;
5173
+ } else {
5174
+ config.content = this._contextBg;
5175
+ }
5176
+ rightLineColors.set(index, config);
4826
5177
  }
4827
5178
  if (line.sign) {
4828
5179
  rightLineSigns.set(index, line.sign);
@@ -4832,63 +5183,10 @@ class DiffRenderable extends Renderable {
4832
5183
  `);
4833
5184
  const rightContentFinal = finalRightLines.map((l) => l.content).join(`
4834
5185
  `);
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
- }
5186
+ leftCodeRenderable.content = leftContentFinal;
5187
+ rightCodeRenderable.content = rightContentFinal;
5188
+ this.createOrUpdateSide("left", leftCodeRenderable, leftLineColors, leftLineSigns, leftLineNumbers, leftHideLineNumbers, "50%");
5189
+ this.createOrUpdateSide("right", rightCodeRenderable, rightLineColors, rightLineSigns, rightLineNumbers, rightHideLineNumbers, "50%");
4892
5190
  }
4893
5191
  get diff() {
4894
5192
  return this._diff;
@@ -4897,11 +5195,7 @@ class DiffRenderable extends Renderable {
4897
5195
  if (this._diff !== value) {
4898
5196
  this._diff = value;
4899
5197
  this.parseDiff();
4900
- if (this._view === "split") {
4901
- this.requestRebuild();
4902
- } else {
4903
- this.buildView();
4904
- }
5198
+ this.rebuildView();
4905
5199
  }
4906
5200
  }
4907
5201
  get view() {
@@ -4920,11 +5214,7 @@ class DiffRenderable extends Renderable {
4920
5214
  set filetype(value) {
4921
5215
  if (this._filetype !== value) {
4922
5216
  this._filetype = value;
4923
- if (this._view === "split") {
4924
- this.requestRebuild();
4925
- } else {
4926
- this.buildView();
4927
- }
5217
+ this.rebuildView();
4928
5218
  }
4929
5219
  }
4930
5220
  get syntaxStyle() {
@@ -4933,11 +5223,7 @@ class DiffRenderable extends Renderable {
4933
5223
  set syntaxStyle(value) {
4934
5224
  if (this._syntaxStyle !== value) {
4935
5225
  this._syntaxStyle = value;
4936
- if (this._view === "split") {
4937
- this.requestRebuild();
4938
- } else {
4939
- this.buildView();
4940
- }
5226
+ this.rebuildView();
4941
5227
  }
4942
5228
  }
4943
5229
  get wrapMode() {
@@ -4967,6 +5253,165 @@ class DiffRenderable extends Renderable {
4967
5253
  }
4968
5254
  }
4969
5255
  }
5256
+ get addedBg() {
5257
+ return this._addedBg;
5258
+ }
5259
+ set addedBg(value) {
5260
+ const parsed = parseColor(value);
5261
+ if (this._addedBg !== parsed) {
5262
+ this._addedBg = parsed;
5263
+ this.rebuildView();
5264
+ }
5265
+ }
5266
+ get removedBg() {
5267
+ return this._removedBg;
5268
+ }
5269
+ set removedBg(value) {
5270
+ const parsed = parseColor(value);
5271
+ if (this._removedBg !== parsed) {
5272
+ this._removedBg = parsed;
5273
+ this.rebuildView();
5274
+ }
5275
+ }
5276
+ get contextBg() {
5277
+ return this._contextBg;
5278
+ }
5279
+ set contextBg(value) {
5280
+ const parsed = parseColor(value);
5281
+ if (this._contextBg !== parsed) {
5282
+ this._contextBg = parsed;
5283
+ this.rebuildView();
5284
+ }
5285
+ }
5286
+ get addedSignColor() {
5287
+ return this._addedSignColor;
5288
+ }
5289
+ set addedSignColor(value) {
5290
+ const parsed = parseColor(value);
5291
+ if (this._addedSignColor !== parsed) {
5292
+ this._addedSignColor = parsed;
5293
+ this.rebuildView();
5294
+ }
5295
+ }
5296
+ get removedSignColor() {
5297
+ return this._removedSignColor;
5298
+ }
5299
+ set removedSignColor(value) {
5300
+ const parsed = parseColor(value);
5301
+ if (this._removedSignColor !== parsed) {
5302
+ this._removedSignColor = parsed;
5303
+ this.rebuildView();
5304
+ }
5305
+ }
5306
+ get addedLineNumberBg() {
5307
+ return this._addedLineNumberBg;
5308
+ }
5309
+ set addedLineNumberBg(value) {
5310
+ const parsed = parseColor(value);
5311
+ if (this._addedLineNumberBg !== parsed) {
5312
+ this._addedLineNumberBg = parsed;
5313
+ this.rebuildView();
5314
+ }
5315
+ }
5316
+ get removedLineNumberBg() {
5317
+ return this._removedLineNumberBg;
5318
+ }
5319
+ set removedLineNumberBg(value) {
5320
+ const parsed = parseColor(value);
5321
+ if (this._removedLineNumberBg !== parsed) {
5322
+ this._removedLineNumberBg = parsed;
5323
+ this.rebuildView();
5324
+ }
5325
+ }
5326
+ get lineNumberFg() {
5327
+ return this._lineNumberFg;
5328
+ }
5329
+ set lineNumberFg(value) {
5330
+ const parsed = parseColor(value);
5331
+ if (this._lineNumberFg !== parsed) {
5332
+ this._lineNumberFg = parsed;
5333
+ this.rebuildView();
5334
+ }
5335
+ }
5336
+ get lineNumberBg() {
5337
+ return this._lineNumberBg;
5338
+ }
5339
+ set lineNumberBg(value) {
5340
+ const parsed = parseColor(value);
5341
+ if (this._lineNumberBg !== parsed) {
5342
+ this._lineNumberBg = parsed;
5343
+ this.rebuildView();
5344
+ }
5345
+ }
5346
+ get addedContentBg() {
5347
+ return this._addedContentBg;
5348
+ }
5349
+ set addedContentBg(value) {
5350
+ const parsed = value ? parseColor(value) : null;
5351
+ if (this._addedContentBg !== parsed) {
5352
+ this._addedContentBg = parsed;
5353
+ this.rebuildView();
5354
+ }
5355
+ }
5356
+ get removedContentBg() {
5357
+ return this._removedContentBg;
5358
+ }
5359
+ set removedContentBg(value) {
5360
+ const parsed = value ? parseColor(value) : null;
5361
+ if (this._removedContentBg !== parsed) {
5362
+ this._removedContentBg = parsed;
5363
+ this.rebuildView();
5364
+ }
5365
+ }
5366
+ get contextContentBg() {
5367
+ return this._contextContentBg;
5368
+ }
5369
+ set contextContentBg(value) {
5370
+ const parsed = value ? parseColor(value) : null;
5371
+ if (this._contextContentBg !== parsed) {
5372
+ this._contextContentBg = parsed;
5373
+ this.rebuildView();
5374
+ }
5375
+ }
5376
+ get selectionBg() {
5377
+ return this._selectionBg;
5378
+ }
5379
+ set selectionBg(value) {
5380
+ const parsed = value ? parseColor(value) : undefined;
5381
+ if (this._selectionBg !== parsed) {
5382
+ this._selectionBg = parsed;
5383
+ if (this.leftCodeRenderable) {
5384
+ this.leftCodeRenderable.selectionBg = parsed;
5385
+ }
5386
+ if (this.rightCodeRenderable) {
5387
+ this.rightCodeRenderable.selectionBg = parsed;
5388
+ }
5389
+ }
5390
+ }
5391
+ get selectionFg() {
5392
+ return this._selectionFg;
5393
+ }
5394
+ set selectionFg(value) {
5395
+ const parsed = value ? parseColor(value) : undefined;
5396
+ if (this._selectionFg !== parsed) {
5397
+ this._selectionFg = parsed;
5398
+ if (this.leftCodeRenderable) {
5399
+ this.leftCodeRenderable.selectionFg = parsed;
5400
+ }
5401
+ if (this.rightCodeRenderable) {
5402
+ this.rightCodeRenderable.selectionFg = parsed;
5403
+ }
5404
+ }
5405
+ }
5406
+ get conceal() {
5407
+ return this._conceal;
5408
+ }
5409
+ set conceal(value) {
5410
+ if (this._conceal !== value) {
5411
+ this._conceal = value;
5412
+ this.rebuildView();
5413
+ }
5414
+ }
4970
5415
  }
4971
5416
  // src/renderables/Input.ts
4972
5417
  var InputRenderableEvents;
@@ -6813,10 +7258,12 @@ class TabSelectRenderable extends Renderable {
6813
7258
  }
6814
7259
  }
6815
7260
  refreshFrameBuffer() {
6816
- if (!this.frameBuffer || this._options.length === 0)
7261
+ if (!this.frameBuffer)
6817
7262
  return;
6818
7263
  const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
6819
7264
  this.frameBuffer.clear(bgColor);
7265
+ if (this._options.length === 0)
7266
+ return;
6820
7267
  const contentX = 0;
6821
7268
  const contentY = 0;
6822
7269
  const contentWidth = this.width;
@@ -7051,102 +7498,9 @@ class TabSelectRenderable extends Renderable {
7051
7498
  this.requestRender();
7052
7499
  }
7053
7500
  }
7054
- // src/renderables/Text.ts
7055
- class TextRenderable extends TextBufferRenderable {
7056
- _text;
7057
- _hasManualStyledText = false;
7058
- rootTextNode;
7059
- _contentDefaultOptions = {
7060
- content: ""
7061
- };
7062
- constructor(ctx, options) {
7063
- super(ctx, options);
7064
- const content = options.content ?? this._contentDefaultOptions.content;
7065
- const styledText = typeof content === "string" ? stringToStyledText(content) : content;
7066
- this._text = styledText;
7067
- this._hasManualStyledText = options.content !== undefined && content !== "";
7068
- this.rootTextNode = new RootTextNodeRenderable(ctx, {
7069
- id: `${this.id}-root`,
7070
- fg: this._defaultFg,
7071
- bg: this._defaultBg,
7072
- attributes: this._defaultAttributes
7073
- }, this);
7074
- this.updateTextBuffer(styledText);
7075
- }
7076
- updateTextBuffer(styledText) {
7077
- this.textBuffer.setStyledText(styledText);
7078
- this.clearChunks(styledText);
7079
- }
7080
- clearChunks(styledText) {}
7081
- get content() {
7082
- return this._text;
7083
- }
7084
- get chunks() {
7085
- return this._text.chunks;
7086
- }
7087
- get textNode() {
7088
- return this.rootTextNode;
7089
- }
7090
- set content(value) {
7091
- this._hasManualStyledText = true;
7092
- const styledText = typeof value === "string" ? stringToStyledText(value) : value;
7093
- if (this._text !== styledText) {
7094
- this._text = styledText;
7095
- this.updateTextBuffer(styledText);
7096
- this.updateTextInfo();
7097
- }
7098
- }
7099
- updateTextFromNodes() {
7100
- if (this.rootTextNode.isDirty && !this._hasManualStyledText) {
7101
- const chunks = this.rootTextNode.gatherWithInheritedStyle({
7102
- fg: this._defaultFg,
7103
- bg: this._defaultBg,
7104
- attributes: this._defaultAttributes
7105
- });
7106
- this.textBuffer.setStyledText(new StyledText(chunks));
7107
- this.refreshLocalSelection();
7108
- this.yogaNode.markDirty();
7109
- }
7110
- }
7111
- add(obj, index) {
7112
- return this.rootTextNode.add(obj, index);
7113
- }
7114
- remove(id) {
7115
- this.rootTextNode.remove(id);
7116
- }
7117
- insertBefore(obj, anchor) {
7118
- this.rootTextNode.insertBefore(obj, anchor);
7119
- return this.rootTextNode.children.indexOf(obj);
7120
- }
7121
- getTextChildren() {
7122
- return this.rootTextNode.getChildren();
7123
- }
7124
- clear() {
7125
- this.rootTextNode.clear();
7126
- const emptyStyledText = stringToStyledText("");
7127
- this._text = emptyStyledText;
7128
- this.updateTextBuffer(emptyStyledText);
7129
- this.updateTextInfo();
7130
- this.requestRender();
7131
- }
7132
- onLifecyclePass = () => {
7133
- this.updateTextFromNodes();
7134
- };
7135
- onFgChanged(newColor) {
7136
- this.rootTextNode.fg = newColor;
7137
- }
7138
- onBgChanged(newColor) {
7139
- this.rootTextNode.bg = newColor;
7140
- }
7141
- onAttributesChanged(newAttributes) {
7142
- this.rootTextNode.attributes = newAttributes;
7143
- }
7144
- destroy() {
7145
- this.rootTextNode.children.length = 0;
7146
- super.destroy();
7147
- }
7148
- }
7149
7501
  // src/renderables/EditBufferRenderable.ts
7502
+ var import_bun_yoga3 = __toESM(require_dist(), 1);
7503
+
7150
7504
  class EditBufferRenderable extends Renderable {
7151
7505
  _focusable = true;
7152
7506
  selectable = true;
@@ -7247,6 +7601,9 @@ class EditBufferRenderable extends Renderable {
7247
7601
  get lineCount() {
7248
7602
  return this.editBuffer.getLineCount();
7249
7603
  }
7604
+ get virtualLineCount() {
7605
+ return this.editorView.getVirtualLineCount();
7606
+ }
7250
7607
  get scrollY() {
7251
7608
  return this.editorView.getViewport().offsetY;
7252
7609
  }
@@ -7443,7 +7800,7 @@ class EditBufferRenderable extends Renderable {
7443
7800
  setupMeasureFunc() {
7444
7801
  const measureFunc = (width, widthMode, height, heightMode) => {
7445
7802
  let effectiveWidth;
7446
- if (widthMode === MeasureMode.Undefined || isNaN(width)) {
7803
+ if (widthMode === import_bun_yoga3.MeasureMode.Undefined || isNaN(width)) {
7447
7804
  effectiveWidth = 0;
7448
7805
  } else {
7449
7806
  effectiveWidth = width;
@@ -7452,7 +7809,7 @@ class EditBufferRenderable extends Renderable {
7452
7809
  const measureResult = this.editorView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
7453
7810
  const measuredWidth = measureResult ? Math.max(1, measureResult.maxWidth) : 1;
7454
7811
  const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
7455
- if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
7812
+ if (widthMode === import_bun_yoga3.MeasureMode.AtMost && this._positionType !== "absolute") {
7456
7813
  return {
7457
7814
  width: Math.min(effectiveWidth, measuredWidth),
7458
7815
  height: Math.min(effectiveHeight, measuredHeight)
@@ -7505,12 +7862,15 @@ class EditBufferRenderable extends Renderable {
7505
7862
  }
7506
7863
  }
7507
7864
  destroy() {
7865
+ if (this.isDestroyed)
7866
+ return;
7508
7867
  if (this._focused) {
7509
7868
  this._ctx.setCursorPosition(0, 0, false);
7869
+ this.blur();
7510
7870
  }
7511
- super.destroy();
7512
7871
  this.editorView.destroy();
7513
7872
  this.editBuffer.destroy();
7873
+ super.destroy();
7514
7874
  }
7515
7875
  set onCursorChange(handler) {
7516
7876
  this._cursorChangeListener = handler;
@@ -8037,7 +8397,9 @@ class TextareaRenderable extends EditBufferRenderable {
8037
8397
  }
8038
8398
  blur() {
8039
8399
  super.blur();
8040
- this.updateColors();
8400
+ if (!this.isDestroyed) {
8401
+ this.updateColors();
8402
+ }
8041
8403
  }
8042
8404
  get placeholder() {
8043
8405
  return this._placeholder;
@@ -8109,6 +8471,8 @@ class TextareaRenderable extends EditBufferRenderable {
8109
8471
  return this.editorView.extmarks;
8110
8472
  }
8111
8473
  }
8474
+ // src/index.ts
8475
+ var Yoga = __toESM(require_dist(), 1);
8112
8476
  export {
8113
8477
  yellow,
8114
8478
  wrapWithDelegates,
@@ -8218,7 +8582,7 @@ export {
8218
8582
  applyChromaticAberration,
8219
8583
  applyAsciiArt,
8220
8584
  addDefaultParsers,
8221
- exports_src as Yoga,
8585
+ Yoga,
8222
8586
  VignetteEffect,
8223
8587
  VRenderable,
8224
8588
  TreeSitterClient,
@@ -8296,5 +8660,5 @@ export {
8296
8660
  ASCIIFont
8297
8661
  };
8298
8662
 
8299
- //# debugId=84CD912F2F121D3E64756E2164756E21
8663
+ //# debugId=FC7E508FCF3C484F64756E2164756E21
8300
8664
  //# sourceMappingURL=index.js.map