@fairyhunter13/opentui-core 0.1.129 → 0.1.131

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.
@@ -6,18 +6,18 @@ import {
6
6
  BaseRenderable,
7
7
  BorderCharArrays,
8
8
  BorderChars,
9
+ BoxRenderable,
9
10
  CliRenderEvents,
10
11
  CliRenderer,
12
+ CodeRenderable,
11
13
  ConsolePosition,
12
14
  DataPathsManager,
13
15
  DebugOverlayCorner,
14
- Edge,
15
16
  EditBuffer,
16
17
  EditBufferRenderable,
17
18
  EditBufferRenderableEvents,
18
19
  EditorView,
19
20
  ExtmarksController,
20
- Gutter,
21
21
  InternalKeyHandler,
22
22
  KeyEvent,
23
23
  KeyHandler,
@@ -36,16 +36,22 @@ import {
36
36
  RenderableEvents,
37
37
  RendererControlState,
38
38
  RootRenderable,
39
+ RootTextNodeRenderable,
39
40
  Selection,
40
41
  SpanInfoStruct,
41
42
  StdinParser,
42
43
  StyledText,
44
+ SyntaxStyle,
43
45
  SystemClock,
44
46
  TargetChannel,
45
47
  TerminalConsole,
46
48
  TerminalPalette,
47
49
  TextAttributes,
48
50
  TextBuffer,
51
+ TextBufferRenderable,
52
+ TextBufferView,
53
+ TextNodeRenderable,
54
+ TextRenderable,
49
55
  TreeSitterClient,
50
56
  __export,
51
57
  addDefaultParsers,
@@ -78,6 +84,7 @@ import {
78
84
  capture,
79
85
  clearEnvCache,
80
86
  convertGlobalToLocalSelection,
87
+ convertThemeToStyles,
81
88
  coordinateToCharacterIndex,
82
89
  createCliRenderer,
83
90
  createExtmarksController,
@@ -117,9 +124,9 @@ import {
117
124
  isEditBufferRenderable,
118
125
  isRenderable,
119
126
  isStyledText,
127
+ isTextNodeRenderable,
120
128
  isVNode,
121
129
  isValidBorderStyle,
122
- isValidPercentage,
123
130
  italic,
124
131
  link,
125
132
  magenta,
@@ -167,7 +174,7 @@ import {
167
174
  white,
168
175
  wrapWithDelegates,
169
176
  yellow
170
- } from "./index-w7h7gtsh.js";
177
+ } from "./index-t3rrpex7.js";
171
178
 
172
179
  // src/index.ts
173
180
  var exports_src2 = {};
@@ -408,320 +415,6 @@ __export(exports_src2, {
408
415
  ACHROMATOPSIA_MATRIX: () => ACHROMATOPSIA_MATRIX
409
416
  });
410
417
 
411
- // src/text-buffer-view.ts
412
- class TextBufferView {
413
- lib;
414
- viewPtr;
415
- textBuffer;
416
- _destroyed = false;
417
- constructor(lib, ptr, textBuffer) {
418
- this.lib = lib;
419
- this.viewPtr = ptr;
420
- this.textBuffer = textBuffer;
421
- }
422
- static create(textBuffer) {
423
- const lib = resolveRenderLib();
424
- const viewPtr = lib.createTextBufferView(textBuffer.ptr);
425
- return new TextBufferView(lib, viewPtr, textBuffer);
426
- }
427
- guard() {
428
- if (this._destroyed)
429
- throw new Error("TextBufferView is destroyed");
430
- }
431
- get ptr() {
432
- this.guard();
433
- return this.viewPtr;
434
- }
435
- setSelection(start, end, bgColor, fgColor) {
436
- this.guard();
437
- this.lib.textBufferViewSetSelection(this.viewPtr, start, end, bgColor || null, fgColor || null);
438
- }
439
- updateSelection(end, bgColor, fgColor) {
440
- this.guard();
441
- this.lib.textBufferViewUpdateSelection(this.viewPtr, end, bgColor || null, fgColor || null);
442
- }
443
- resetSelection() {
444
- this.guard();
445
- this.lib.textBufferViewResetSelection(this.viewPtr);
446
- }
447
- getSelection() {
448
- this.guard();
449
- return this.lib.textBufferViewGetSelection(this.viewPtr);
450
- }
451
- hasSelection() {
452
- this.guard();
453
- return this.getSelection() !== null;
454
- }
455
- setLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
456
- this.guard();
457
- return this.lib.textBufferViewSetLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
458
- }
459
- updateLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
460
- this.guard();
461
- return this.lib.textBufferViewUpdateLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
462
- }
463
- resetLocalSelection() {
464
- this.guard();
465
- this.lib.textBufferViewResetLocalSelection(this.viewPtr);
466
- }
467
- setWrapWidth(width) {
468
- this.guard();
469
- this.lib.textBufferViewSetWrapWidth(this.viewPtr, width ?? 0);
470
- }
471
- setWrapMode(mode) {
472
- this.guard();
473
- this.lib.textBufferViewSetWrapMode(this.viewPtr, mode);
474
- }
475
- setViewportSize(width, height) {
476
- this.guard();
477
- this.lib.textBufferViewSetViewportSize(this.viewPtr, width, height);
478
- }
479
- setViewport(x, y, width, height) {
480
- this.guard();
481
- this.lib.textBufferViewSetViewport(this.viewPtr, x, y, width, height);
482
- }
483
- get lineInfo() {
484
- this.guard();
485
- return this.lib.textBufferViewGetLineInfo(this.viewPtr);
486
- }
487
- get logicalLineInfo() {
488
- this.guard();
489
- return this.lib.textBufferViewGetLogicalLineInfo(this.viewPtr);
490
- }
491
- getSelectedText() {
492
- this.guard();
493
- const byteSize = this.textBuffer.byteSize;
494
- if (byteSize === 0)
495
- return "";
496
- const selectedBytes = this.lib.textBufferViewGetSelectedTextBytes(this.viewPtr, byteSize);
497
- if (!selectedBytes)
498
- return "";
499
- return this.lib.decoder.decode(selectedBytes);
500
- }
501
- getPlainText() {
502
- this.guard();
503
- const byteSize = this.textBuffer.byteSize;
504
- if (byteSize === 0)
505
- return "";
506
- const plainBytes = this.lib.textBufferViewGetPlainTextBytes(this.viewPtr, byteSize);
507
- if (!plainBytes)
508
- return "";
509
- return this.lib.decoder.decode(plainBytes);
510
- }
511
- setTabIndicator(indicator) {
512
- this.guard();
513
- const codePoint = typeof indicator === "string" ? indicator.codePointAt(0) ?? 0 : indicator;
514
- this.lib.textBufferViewSetTabIndicator(this.viewPtr, codePoint);
515
- }
516
- setTabIndicatorColor(color) {
517
- this.guard();
518
- this.lib.textBufferViewSetTabIndicatorColor(this.viewPtr, color);
519
- }
520
- setTruncate(truncate) {
521
- this.guard();
522
- this.lib.textBufferViewSetTruncate(this.viewPtr, truncate);
523
- }
524
- measureForDimensions(width, height) {
525
- this.guard();
526
- return this.lib.textBufferViewMeasureForDimensions(this.viewPtr, width, height);
527
- }
528
- getVirtualLineCount() {
529
- this.guard();
530
- return this.lib.textBufferViewGetVirtualLineCount(this.viewPtr);
531
- }
532
- destroy() {
533
- if (this._destroyed)
534
- return;
535
- this._destroyed = true;
536
- this.lib.destroyTextBufferView(this.viewPtr);
537
- }
538
- }
539
- // src/syntax-style.ts
540
- function convertThemeToStyles(theme) {
541
- const flatStyles = {};
542
- for (const tokenStyle of theme) {
543
- const styleDefinition = {};
544
- if (tokenStyle.style.foreground) {
545
- styleDefinition.fg = parseColor(tokenStyle.style.foreground);
546
- }
547
- if (tokenStyle.style.background) {
548
- styleDefinition.bg = parseColor(tokenStyle.style.background);
549
- }
550
- if (tokenStyle.style.bold !== undefined) {
551
- styleDefinition.bold = tokenStyle.style.bold;
552
- }
553
- if (tokenStyle.style.italic !== undefined) {
554
- styleDefinition.italic = tokenStyle.style.italic;
555
- }
556
- if (tokenStyle.style.underline !== undefined) {
557
- styleDefinition.underline = tokenStyle.style.underline;
558
- }
559
- if (tokenStyle.style.dim !== undefined) {
560
- styleDefinition.dim = tokenStyle.style.dim;
561
- }
562
- for (const scope of tokenStyle.scope) {
563
- flatStyles[scope] = styleDefinition;
564
- }
565
- }
566
- return flatStyles;
567
- }
568
-
569
- class SyntaxStyle {
570
- lib;
571
- stylePtr;
572
- _destroyed = false;
573
- nameCache = new Map;
574
- styleDefs = new Map;
575
- mergedCache = new Map;
576
- constructor(lib, ptr) {
577
- this.lib = lib;
578
- this.stylePtr = ptr;
579
- }
580
- static create() {
581
- const lib = resolveRenderLib();
582
- const ptr = lib.createSyntaxStyle();
583
- return new SyntaxStyle(lib, ptr);
584
- }
585
- static fromTheme(theme) {
586
- const style = SyntaxStyle.create();
587
- const flatStyles = convertThemeToStyles(theme);
588
- for (const [name, styleDef] of Object.entries(flatStyles)) {
589
- style.registerStyle(name, styleDef);
590
- }
591
- return style;
592
- }
593
- static fromStyles(styles) {
594
- const style = SyntaxStyle.create();
595
- for (const [name, styleDef] of Object.entries(styles)) {
596
- style.registerStyle(name, styleDef);
597
- }
598
- return style;
599
- }
600
- guard() {
601
- if (this._destroyed)
602
- throw new Error("NativeSyntaxStyle is destroyed");
603
- }
604
- registerStyle(name, style) {
605
- this.guard();
606
- const attributes = createTextAttributes({
607
- bold: style.bold,
608
- italic: style.italic,
609
- underline: style.underline,
610
- dim: style.dim
611
- });
612
- const id = this.lib.syntaxStyleRegister(this.stylePtr, name, style.fg || null, style.bg || null, attributes);
613
- this.nameCache.set(name, id);
614
- this.styleDefs.set(name, style);
615
- return id;
616
- }
617
- resolveStyleId(name) {
618
- this.guard();
619
- const cached = this.nameCache.get(name);
620
- if (cached !== undefined)
621
- return cached;
622
- const id = this.lib.syntaxStyleResolveByName(this.stylePtr, name);
623
- if (id !== null) {
624
- this.nameCache.set(name, id);
625
- }
626
- return id;
627
- }
628
- getStyleId(name) {
629
- this.guard();
630
- const id = this.resolveStyleId(name);
631
- if (id !== null)
632
- return id;
633
- if (name.includes(".")) {
634
- const baseName = name.split(".")[0];
635
- return this.resolveStyleId(baseName);
636
- }
637
- return null;
638
- }
639
- get ptr() {
640
- this.guard();
641
- return this.stylePtr;
642
- }
643
- getStyleCount() {
644
- this.guard();
645
- return this.lib.syntaxStyleGetStyleCount(this.stylePtr);
646
- }
647
- clearNameCache() {
648
- this.nameCache.clear();
649
- }
650
- getStyle(name) {
651
- this.guard();
652
- const style = this.styleDefs.get(name);
653
- if (style)
654
- return style;
655
- if (name.includes(".")) {
656
- const baseName = name.split(".")[0];
657
- return this.styleDefs.get(baseName);
658
- }
659
- return;
660
- }
661
- mergeStyles(...styleNames) {
662
- this.guard();
663
- const cacheKey = styleNames.join(":");
664
- const cached = this.mergedCache.get(cacheKey);
665
- if (cached)
666
- return cached;
667
- const styleDefinition = {};
668
- for (const name of styleNames) {
669
- const style = this.getStyle(name);
670
- if (!style)
671
- continue;
672
- if (style.fg)
673
- styleDefinition.fg = style.fg;
674
- if (style.bg)
675
- styleDefinition.bg = style.bg;
676
- if (style.bold !== undefined)
677
- styleDefinition.bold = style.bold;
678
- if (style.italic !== undefined)
679
- styleDefinition.italic = style.italic;
680
- if (style.underline !== undefined)
681
- styleDefinition.underline = style.underline;
682
- if (style.dim !== undefined)
683
- styleDefinition.dim = style.dim;
684
- }
685
- const attributes = createTextAttributes({
686
- bold: styleDefinition.bold,
687
- italic: styleDefinition.italic,
688
- underline: styleDefinition.underline,
689
- dim: styleDefinition.dim
690
- });
691
- const merged = {
692
- fg: styleDefinition.fg,
693
- bg: styleDefinition.bg,
694
- attributes
695
- };
696
- this.mergedCache.set(cacheKey, merged);
697
- return merged;
698
- }
699
- clearCache() {
700
- this.guard();
701
- this.mergedCache.clear();
702
- }
703
- getCacheSize() {
704
- this.guard();
705
- return this.mergedCache.size;
706
- }
707
- getAllStyles() {
708
- this.guard();
709
- return new Map(this.styleDefs);
710
- }
711
- getRegisteredNames() {
712
- this.guard();
713
- return Array.from(this.styleDefs.keys());
714
- }
715
- destroy() {
716
- if (this._destroyed)
717
- return;
718
- this._destroyed = true;
719
- this.nameCache.clear();
720
- this.styleDefs.clear();
721
- this.mergedCache.clear();
722
- this.lib.destroySyntaxStyle(this.stylePtr);
723
- }
724
- }
725
418
  // src/post/effects.ts
726
419
  class DistortionEffect {
727
420
  glitchChancePerSecond = 0.5;
@@ -3381,1262 +3074,122 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
3381
3074
  this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : undefined;
3382
3075
  this.selectable = options.selectable ?? true;
3383
3076
  this.selectionHelper = new ASCIIFontSelectionHelper(() => this._text, () => this._font);
3384
- this.renderFontToBuffer();
3385
- }
3386
- get text() {
3387
- return this._text;
3388
- }
3389
- set text(value) {
3390
- this._text = value;
3391
- this.updateDimensions();
3392
- if (this.lastLocalSelection) {
3393
- this.selectionHelper.onLocalSelectionChanged(this.lastLocalSelection, this.width, this.height);
3394
- }
3395
- this.renderFontToBuffer();
3396
- this.requestRender();
3397
- }
3398
- get font() {
3399
- return this._font;
3400
- }
3401
- set font(value) {
3402
- this._font = value;
3403
- this.updateDimensions();
3404
- if (this.lastLocalSelection) {
3405
- this.selectionHelper.onLocalSelectionChanged(this.lastLocalSelection, this.width, this.height);
3406
- }
3407
- this.renderFontToBuffer();
3408
- this.requestRender();
3409
- }
3410
- get color() {
3411
- return this._color;
3412
- }
3413
- set color(value) {
3414
- this._color = value;
3415
- this.renderFontToBuffer();
3416
- this.requestRender();
3417
- }
3418
- get backgroundColor() {
3419
- return this._backgroundColor;
3420
- }
3421
- set backgroundColor(value) {
3422
- this._backgroundColor = value;
3423
- this.renderFontToBuffer();
3424
- this.requestRender();
3425
- }
3426
- updateDimensions() {
3427
- const measurements = measureText({ text: this._text, font: this._font });
3428
- this.width = measurements.width;
3429
- this.height = measurements.height;
3430
- }
3431
- shouldStartSelection(x, y) {
3432
- const localX = x - this.x;
3433
- const localY = y - this.y;
3434
- return this.selectionHelper.shouldStartSelection(localX, localY, this.width, this.height);
3435
- }
3436
- onSelectionChanged(selection) {
3437
- const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
3438
- this.lastLocalSelection = localSelection;
3439
- const changed = this.selectionHelper.onLocalSelectionChanged(localSelection, this.width, this.height);
3440
- if (changed) {
3441
- this.renderFontToBuffer();
3442
- this.requestRender();
3443
- }
3444
- return changed;
3445
- }
3446
- getSelectedText() {
3447
- const selection = this.selectionHelper.getSelection();
3448
- if (!selection)
3449
- return "";
3450
- return this._text.slice(selection.start, selection.end);
3451
- }
3452
- hasSelection() {
3453
- return this.selectionHelper.hasSelection();
3454
- }
3455
- onResize(width, height) {
3456
- super.onResize(width, height);
3457
- this.renderFontToBuffer();
3458
- }
3459
- renderFontToBuffer() {
3460
- if (this.isDestroyed)
3461
- return;
3462
- this.frameBuffer.clear(parseColor(this._backgroundColor));
3463
- renderFontToFrameBuffer(this.frameBuffer, {
3464
- text: this._text,
3465
- x: 0,
3466
- y: 0,
3467
- color: this.color,
3468
- backgroundColor: this._backgroundColor,
3469
- font: this._font
3470
- });
3471
- const selection = this.selectionHelper.getSelection();
3472
- if (selection && (this._selectionBg || this._selectionFg)) {
3473
- this.renderSelectionHighlight(selection);
3474
- }
3475
- }
3476
- renderSelectionHighlight(selection) {
3477
- if (!this._selectionBg && !this._selectionFg)
3478
- return;
3479
- const selectedText = this._text.slice(selection.start, selection.end);
3480
- if (!selectedText)
3481
- return;
3482
- const positions = getCharacterPositions(this._text, this._font);
3483
- const startX = positions[selection.start] || 0;
3484
- const endX = selection.end < positions.length ? positions[selection.end] : measureText({ text: this._text, font: this._font }).width;
3485
- if (this._selectionBg) {
3486
- this.frameBuffer.fillRect(startX, 0, endX - startX, this.height, parseColor(this._selectionBg));
3487
- }
3488
- if (this._selectionFg || this._selectionBg) {
3489
- renderFontToFrameBuffer(this.frameBuffer, {
3490
- text: selectedText,
3491
- x: startX,
3492
- y: 0,
3493
- color: this._selectionFg ? this._selectionFg : this._color,
3494
- backgroundColor: this._selectionBg ? this._selectionBg : this._backgroundColor,
3495
- font: this._font
3496
- });
3497
- }
3498
- }
3499
- }
3500
- // src/renderables/Box.ts
3501
- function isGapType(value) {
3502
- if (value === undefined) {
3503
- return true;
3504
- }
3505
- if (typeof value === "number" && !Number.isNaN(value)) {
3506
- return true;
3507
- }
3508
- return isValidPercentage(value);
3509
- }
3510
-
3511
- class BoxRenderable extends Renderable {
3512
- _backgroundColor;
3513
- _border;
3514
- _borderStyle;
3515
- _borderColor;
3516
- _focusedBorderColor;
3517
- _customBorderCharsObj;
3518
- _customBorderChars;
3519
- borderSides;
3520
- shouldFill;
3521
- _title;
3522
- _titleAlignment;
3523
- _bottomTitle;
3524
- _bottomTitleAlignment;
3525
- _defaultOptions = {
3526
- backgroundColor: "transparent",
3527
- borderStyle: "single",
3528
- border: false,
3529
- borderColor: "#FFFFFF",
3530
- shouldFill: true,
3531
- titleAlignment: "left",
3532
- bottomTitleAlignment: "left",
3533
- focusedBorderColor: "#00AAFF"
3534
- };
3535
- constructor(ctx, options) {
3536
- super(ctx, options);
3537
- if (options.focusable === true) {
3538
- this._focusable = true;
3539
- }
3540
- this._backgroundColor = parseColor(options.backgroundColor || this._defaultOptions.backgroundColor);
3541
- this._border = options.border ?? this._defaultOptions.border;
3542
- if (!options.border && (options.borderStyle || options.borderColor || options.focusedBorderColor || options.customBorderChars)) {
3543
- this._border = true;
3544
- }
3545
- this._borderStyle = parseBorderStyle(options.borderStyle, this._defaultOptions.borderStyle);
3546
- this._borderColor = parseColor(options.borderColor || this._defaultOptions.borderColor);
3547
- this._focusedBorderColor = parseColor(options.focusedBorderColor || this._defaultOptions.focusedBorderColor);
3548
- this._customBorderCharsObj = options.customBorderChars;
3549
- this._customBorderChars = this._customBorderCharsObj ? borderCharsToArray(this._customBorderCharsObj) : undefined;
3550
- this.borderSides = getBorderSides(this._border);
3551
- this.shouldFill = options.shouldFill ?? this._defaultOptions.shouldFill;
3552
- this._title = options.title;
3553
- this._titleAlignment = options.titleAlignment || this._defaultOptions.titleAlignment;
3554
- this._bottomTitle = options.bottomTitle;
3555
- this._bottomTitleAlignment = options.bottomTitleAlignment || this._defaultOptions.bottomTitleAlignment;
3556
- this.applyYogaBorders();
3557
- const hasInitialGapProps = options.gap !== undefined || options.rowGap !== undefined || options.columnGap !== undefined;
3558
- if (hasInitialGapProps) {
3559
- this.applyYogaGap(options);
3560
- }
3561
- }
3562
- initializeBorder() {
3563
- if (this._border === false) {
3564
- this._border = true;
3565
- this.borderSides = getBorderSides(this._border);
3566
- this.applyYogaBorders();
3567
- }
3568
- }
3569
- get customBorderChars() {
3570
- return this._customBorderCharsObj;
3571
- }
3572
- set customBorderChars(value) {
3573
- this._customBorderCharsObj = value;
3574
- this._customBorderChars = value ? borderCharsToArray(value) : undefined;
3575
- this.requestRender();
3576
- }
3577
- get backgroundColor() {
3578
- return this._backgroundColor;
3579
- }
3580
- set backgroundColor(value) {
3581
- const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
3582
- if (this._backgroundColor !== newColor) {
3583
- this._backgroundColor = newColor;
3584
- this.requestRender();
3585
- }
3586
- }
3587
- get border() {
3588
- return this._border;
3589
- }
3590
- set border(value) {
3591
- if (this._border !== value) {
3592
- this._border = value;
3593
- this.borderSides = getBorderSides(value);
3594
- this.applyYogaBorders();
3595
- this.requestRender();
3596
- }
3597
- }
3598
- get borderStyle() {
3599
- return this._borderStyle;
3600
- }
3601
- set borderStyle(value) {
3602
- const _value = parseBorderStyle(value, this._defaultOptions.borderStyle);
3603
- if (this._borderStyle !== _value || !this._border) {
3604
- this._borderStyle = _value;
3605
- this._customBorderChars = undefined;
3606
- this.initializeBorder();
3607
- this.requestRender();
3608
- }
3609
- }
3610
- get borderColor() {
3611
- return this._borderColor;
3612
- }
3613
- set borderColor(value) {
3614
- const newColor = parseColor(value ?? this._defaultOptions.borderColor);
3615
- if (this._borderColor !== newColor) {
3616
- this._borderColor = newColor;
3617
- this.initializeBorder();
3618
- this.requestRender();
3619
- }
3620
- }
3621
- get focusedBorderColor() {
3622
- return this._focusedBorderColor;
3623
- }
3624
- set focusedBorderColor(value) {
3625
- const newColor = parseColor(value ?? this._defaultOptions.focusedBorderColor);
3626
- if (this._focusedBorderColor !== newColor) {
3627
- this._focusedBorderColor = newColor;
3628
- this.initializeBorder();
3629
- if (this._focused) {
3630
- this.requestRender();
3631
- }
3632
- }
3633
- }
3634
- get title() {
3635
- return this._title;
3636
- }
3637
- set title(value) {
3638
- if (this._title !== value) {
3639
- this._title = value;
3640
- this.requestRender();
3641
- }
3642
- }
3643
- get titleAlignment() {
3644
- return this._titleAlignment;
3645
- }
3646
- set titleAlignment(value) {
3647
- if (this._titleAlignment !== value) {
3648
- this._titleAlignment = value;
3649
- this.requestRender();
3650
- }
3651
- }
3652
- get bottomTitle() {
3653
- return this._bottomTitle;
3654
- }
3655
- set bottomTitle(value) {
3656
- if (this._bottomTitle !== value) {
3657
- this._bottomTitle = value;
3658
- this.requestRender();
3659
- }
3660
- }
3661
- get bottomTitleAlignment() {
3662
- return this._bottomTitleAlignment;
3663
- }
3664
- set bottomTitleAlignment(value) {
3665
- if (this._bottomTitleAlignment !== value) {
3666
- this._bottomTitleAlignment = value;
3667
- this.requestRender();
3668
- }
3669
- }
3670
- renderSelf(buffer) {
3671
- const hasBorder = this.borderSides.top || this.borderSides.right || this.borderSides.bottom || this.borderSides.left;
3672
- const hasVisibleFill = this.shouldFill && this._backgroundColor.a > 0;
3673
- if (!hasBorder && !hasVisibleFill) {
3674
- return;
3675
- }
3676
- const hasFocusWithin = this._focusable && (this._focused || this._hasFocusedDescendant);
3677
- const currentBorderColor = hasFocusWithin ? this._focusedBorderColor : this._borderColor;
3678
- const screenX = this._screenX;
3679
- const screenY = this._screenY;
3680
- buffer.drawBox({
3681
- x: screenX,
3682
- y: screenY,
3683
- width: this.width,
3684
- height: this.height,
3685
- borderStyle: this._borderStyle,
3686
- customBorderChars: this._customBorderChars,
3687
- border: this._border,
3688
- borderColor: currentBorderColor,
3689
- backgroundColor: this._backgroundColor,
3690
- shouldFill: this.shouldFill,
3691
- title: this._title,
3692
- titleAlignment: this._titleAlignment,
3693
- bottomTitle: this._bottomTitle,
3694
- bottomTitleAlignment: this._bottomTitleAlignment
3695
- });
3696
- }
3697
- getScissorRect() {
3698
- const baseRect = super.getScissorRect();
3699
- if (!this.borderSides.top && !this.borderSides.right && !this.borderSides.bottom && !this.borderSides.left) {
3700
- return baseRect;
3701
- }
3702
- const leftInset = this.borderSides.left ? 1 : 0;
3703
- const rightInset = this.borderSides.right ? 1 : 0;
3704
- const topInset = this.borderSides.top ? 1 : 0;
3705
- const bottomInset = this.borderSides.bottom ? 1 : 0;
3706
- return {
3707
- x: baseRect.x + leftInset,
3708
- y: baseRect.y + topInset,
3709
- width: Math.max(0, baseRect.width - leftInset - rightInset),
3710
- height: Math.max(0, baseRect.height - topInset - bottomInset)
3711
- };
3712
- }
3713
- applyYogaBorders() {
3714
- const node = this.yogaNode;
3715
- node.setBorder(Edge.Left, this.borderSides.left ? 1 : 0);
3716
- node.setBorder(Edge.Right, this.borderSides.right ? 1 : 0);
3717
- node.setBorder(Edge.Top, this.borderSides.top ? 1 : 0);
3718
- node.setBorder(Edge.Bottom, this.borderSides.bottom ? 1 : 0);
3719
- this.requestRender();
3720
- }
3721
- applyYogaGap(options) {
3722
- const node = this.yogaNode;
3723
- if (isGapType(options.gap)) {
3724
- node.setGap(Gutter.All, options.gap);
3725
- }
3726
- if (isGapType(options.rowGap)) {
3727
- node.setGap(Gutter.Row, options.rowGap);
3728
- }
3729
- if (isGapType(options.columnGap)) {
3730
- node.setGap(Gutter.Column, options.columnGap);
3731
- }
3732
- }
3733
- set gap(gap) {
3734
- if (isGapType(gap)) {
3735
- this.yogaNode.setGap(Gutter.All, gap);
3736
- this.requestRender();
3737
- }
3738
- }
3739
- set rowGap(rowGap) {
3740
- if (isGapType(rowGap)) {
3741
- this.yogaNode.setGap(Gutter.Row, rowGap);
3742
- this.requestRender();
3743
- }
3744
- }
3745
- set columnGap(columnGap) {
3746
- if (isGapType(columnGap)) {
3747
- this.yogaNode.setGap(Gutter.Column, columnGap);
3748
- this.requestRender();
3749
- }
3750
- }
3751
- }
3752
- // src/renderables/TextBufferRenderable.ts
3753
- class TextBufferRenderable extends Renderable {
3754
- selectable = true;
3755
- _defaultFg;
3756
- _defaultBg;
3757
- _defaultAttributes;
3758
- _selectionBg;
3759
- _selectionFg;
3760
- _wrapMode = "word";
3761
- lastLocalSelection = null;
3762
- _tabIndicator;
3763
- _tabIndicatorColor;
3764
- _scrollX = 0;
3765
- _scrollY = 0;
3766
- _truncate = false;
3767
- textBuffer;
3768
- textBufferView;
3769
- _textBufferSyntaxStyle;
3770
- _defaultOptions = {
3771
- fg: RGBA.fromValues(1, 1, 1, 1),
3772
- bg: RGBA.fromValues(0, 0, 0, 0),
3773
- selectionBg: undefined,
3774
- selectionFg: undefined,
3775
- selectable: true,
3776
- attributes: 0,
3777
- wrapMode: "word",
3778
- tabIndicator: undefined,
3779
- tabIndicatorColor: undefined,
3780
- truncate: false
3781
- };
3782
- constructor(ctx, options) {
3783
- super(ctx, options);
3784
- this._defaultFg = parseColor(options.fg ?? this._defaultOptions.fg);
3785
- this._defaultBg = parseColor(options.bg ?? this._defaultOptions.bg);
3786
- this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
3787
- this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
3788
- this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
3789
- this.selectable = options.selectable ?? this._defaultOptions.selectable;
3790
- this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
3791
- this._tabIndicator = options.tabIndicator ?? this._defaultOptions.tabIndicator;
3792
- this._tabIndicatorColor = options.tabIndicatorColor ? parseColor(options.tabIndicatorColor) : this._defaultOptions.tabIndicatorColor;
3793
- this._truncate = options.truncate ?? this._defaultOptions.truncate;
3794
- this.textBuffer = TextBuffer.create(this._ctx.widthMethod);
3795
- this.textBufferView = TextBufferView.create(this.textBuffer);
3796
- this._textBufferSyntaxStyle = SyntaxStyle.create();
3797
- this.textBuffer.setSyntaxStyle(this._textBufferSyntaxStyle);
3798
- this.textBufferView.setWrapMode(this._wrapMode);
3799
- this.setupMeasureFunc();
3800
- this.textBuffer.setDefaultFg(this._defaultFg);
3801
- this.textBuffer.setDefaultBg(this._defaultBg);
3802
- this.textBuffer.setDefaultAttributes(this._defaultAttributes);
3803
- if (this._tabIndicator !== undefined) {
3804
- this.textBufferView.setTabIndicator(this._tabIndicator);
3805
- }
3806
- if (this._tabIndicatorColor !== undefined) {
3807
- this.textBufferView.setTabIndicatorColor(this._tabIndicatorColor);
3808
- }
3809
- if (this._wrapMode !== "none" && this.width > 0) {
3810
- this.textBufferView.setWrapWidth(this.width);
3811
- }
3812
- if (this.width > 0 && this.height > 0) {
3813
- this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
3814
- }
3815
- this.textBufferView.setTruncate(this._truncate);
3816
- this.updateTextInfo();
3817
- }
3818
- onMouseEvent(event) {
3819
- if (event.type === "scroll") {
3820
- this.handleScroll(event);
3821
- }
3822
- }
3823
- handleScroll(event) {
3824
- if (!event.scroll)
3825
- return;
3826
- const { direction, delta } = event.scroll;
3827
- if (direction === "up") {
3828
- this.scrollY -= delta;
3829
- } else if (direction === "down") {
3830
- this.scrollY += delta;
3831
- }
3832
- if (this._wrapMode === "none") {
3833
- if (direction === "left") {
3834
- this.scrollX -= delta;
3835
- } else if (direction === "right") {
3836
- this.scrollX += delta;
3837
- }
3838
- }
3839
- }
3840
- get lineInfo() {
3841
- return this.textBufferView.logicalLineInfo;
3842
- }
3843
- get lineCount() {
3844
- return this.textBuffer.getLineCount();
3845
- }
3846
- get virtualLineCount() {
3847
- return this.textBufferView.getVirtualLineCount();
3848
- }
3849
- get scrollY() {
3850
- return this._scrollY;
3851
- }
3852
- set scrollY(value) {
3853
- const maxScrollY = Math.max(0, this.scrollHeight - this.height);
3854
- const clamped = Math.max(0, Math.min(value, maxScrollY));
3855
- if (this._scrollY !== clamped) {
3856
- this._scrollY = clamped;
3857
- this.updateViewportOffset();
3858
- this.requestRender();
3859
- }
3860
- }
3861
- get scrollX() {
3862
- return this._scrollX;
3863
- }
3864
- set scrollX(value) {
3865
- const maxScrollX = Math.max(0, this.scrollWidth - this.width);
3866
- const clamped = Math.max(0, Math.min(value, maxScrollX));
3867
- if (this._scrollX !== clamped) {
3868
- this._scrollX = clamped;
3869
- this.updateViewportOffset();
3870
- this.requestRender();
3871
- }
3872
- }
3873
- get scrollWidth() {
3874
- return this.lineInfo.lineWidthColsMax;
3875
- }
3876
- get scrollHeight() {
3877
- return this.lineInfo.lineStartCols.length;
3878
- }
3879
- get maxScrollY() {
3880
- return Math.max(0, this.scrollHeight - this.height);
3881
- }
3882
- get maxScrollX() {
3883
- return Math.max(0, this.scrollWidth - this.width);
3884
- }
3885
- updateViewportOffset() {
3886
- if (this.width > 0 && this.height > 0) {
3887
- this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
3888
- }
3889
- }
3890
- get plainText() {
3891
- return this.textBuffer.getPlainText();
3892
- }
3893
- get textLength() {
3894
- return this.textBuffer.length;
3895
- }
3896
- get fg() {
3897
- return this._defaultFg;
3898
- }
3899
- set fg(value) {
3900
- const newColor = parseColor(value ?? this._defaultOptions.fg);
3901
- if (this._defaultFg !== newColor) {
3902
- this._defaultFg = newColor;
3903
- this.textBuffer.setDefaultFg(this._defaultFg);
3904
- this.onFgChanged(newColor);
3905
- this.requestRender();
3906
- }
3907
- }
3908
- get selectionBg() {
3909
- return this._selectionBg;
3910
- }
3911
- set selectionBg(value) {
3912
- const newColor = value ? parseColor(value) : this._defaultOptions.selectionBg;
3913
- if (this._selectionBg !== newColor) {
3914
- this._selectionBg = newColor;
3915
- if (this.lastLocalSelection) {
3916
- this.updateLocalSelection(this.lastLocalSelection);
3917
- }
3918
- this.requestRender();
3919
- }
3920
- }
3921
- get selectionFg() {
3922
- return this._selectionFg;
3923
- }
3924
- set selectionFg(value) {
3925
- const newColor = value ? parseColor(value) : this._defaultOptions.selectionFg;
3926
- if (this._selectionFg !== newColor) {
3927
- this._selectionFg = newColor;
3928
- if (this.lastLocalSelection) {
3929
- this.updateLocalSelection(this.lastLocalSelection);
3930
- }
3931
- this.requestRender();
3932
- }
3933
- }
3934
- get bg() {
3935
- return this._defaultBg;
3936
- }
3937
- set bg(value) {
3938
- const newColor = parseColor(value ?? this._defaultOptions.bg);
3939
- if (this._defaultBg !== newColor) {
3940
- this._defaultBg = newColor;
3941
- this.textBuffer.setDefaultBg(this._defaultBg);
3942
- this.onBgChanged(newColor);
3943
- this.requestRender();
3944
- }
3945
- }
3946
- get attributes() {
3947
- return this._defaultAttributes;
3948
- }
3949
- set attributes(value) {
3950
- if (this._defaultAttributes !== value) {
3951
- this._defaultAttributes = value;
3952
- this.textBuffer.setDefaultAttributes(this._defaultAttributes);
3953
- this.onAttributesChanged(value);
3954
- this.requestRender();
3955
- }
3956
- }
3957
- get wrapMode() {
3958
- return this._wrapMode;
3959
- }
3960
- set wrapMode(value) {
3961
- if (this._wrapMode !== value) {
3962
- this._wrapMode = value;
3963
- this.textBufferView.setWrapMode(this._wrapMode);
3964
- if (value !== "none" && this.width > 0) {
3965
- this.textBufferView.setWrapWidth(this.width);
3966
- }
3967
- this.yogaNode.markDirty();
3968
- this.requestRender();
3969
- }
3970
- }
3971
- get tabIndicator() {
3972
- return this._tabIndicator;
3973
- }
3974
- set tabIndicator(value) {
3975
- if (this._tabIndicator !== value) {
3976
- this._tabIndicator = value;
3977
- if (value !== undefined) {
3978
- this.textBufferView.setTabIndicator(value);
3979
- }
3980
- this.requestRender();
3981
- }
3982
- }
3983
- get tabIndicatorColor() {
3984
- return this._tabIndicatorColor;
3985
- }
3986
- set tabIndicatorColor(value) {
3987
- const newColor = value ? parseColor(value) : undefined;
3988
- if (this._tabIndicatorColor !== newColor) {
3989
- this._tabIndicatorColor = newColor;
3990
- if (newColor !== undefined) {
3991
- this.textBufferView.setTabIndicatorColor(newColor);
3992
- }
3993
- this.requestRender();
3994
- }
3995
- }
3996
- get truncate() {
3997
- return this._truncate;
3998
- }
3999
- set truncate(value) {
4000
- if (this._truncate !== value) {
4001
- this._truncate = value;
4002
- this.textBufferView.setTruncate(value);
4003
- this.requestRender();
4004
- }
4005
- }
4006
- onResize(width, height) {
4007
- this.textBufferView.setViewport(this._scrollX, this._scrollY, width, height);
4008
- this.yogaNode.markDirty();
4009
- this.requestRender();
4010
- this.emit("line-info-change");
4011
- }
4012
- refreshLocalSelection() {
4013
- if (this.lastLocalSelection) {
4014
- return this.updateLocalSelection(this.lastLocalSelection);
4015
- }
4016
- return false;
4017
- }
4018
- updateLocalSelection(localSelection) {
4019
- if (!localSelection?.isActive) {
4020
- this.textBufferView.resetLocalSelection();
4021
- return true;
4022
- }
4023
- return this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
4024
- }
4025
- updateTextInfo() {
4026
- if (this.lastLocalSelection) {
4027
- this.updateLocalSelection(this.lastLocalSelection);
4028
- }
4029
- this.yogaNode.markDirty();
4030
- this.requestRender();
4031
- this.emit("line-info-change");
4032
- }
4033
- setupMeasureFunc() {
4034
- const measureFunc = (width, widthMode, height, heightMode) => {
4035
- let effectiveWidth;
4036
- if (widthMode === MeasureMode.Undefined || isNaN(width)) {
4037
- effectiveWidth = 0;
4038
- } else {
4039
- effectiveWidth = width;
4040
- }
4041
- const effectiveHeight = isNaN(height) ? 1 : height;
4042
- const measureResult = this.textBufferView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
4043
- const measuredWidth = measureResult ? Math.max(1, measureResult.widthColsMax) : 1;
4044
- const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
4045
- if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
4046
- return {
4047
- width: Math.min(effectiveWidth, measuredWidth),
4048
- height: Math.min(effectiveHeight, measuredHeight)
4049
- };
4050
- }
4051
- return {
4052
- width: measuredWidth,
4053
- height: measuredHeight
4054
- };
4055
- };
4056
- this.yogaNode.setMeasureFunc(measureFunc);
4057
- }
4058
- shouldStartSelection(x, y) {
4059
- if (!this.selectable)
4060
- return false;
4061
- const localX = x - this.x;
4062
- const localY = y - this.y;
4063
- return localX >= 0 && localX < this.width && localY >= 0 && localY < this.height;
4064
- }
4065
- onSelectionChanged(selection) {
4066
- const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
4067
- this.lastLocalSelection = localSelection;
4068
- let changed;
4069
- if (!localSelection?.isActive) {
4070
- this.textBufferView.resetLocalSelection();
4071
- changed = true;
4072
- } else if (selection?.isStart) {
4073
- changed = this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
4074
- } else {
4075
- changed = this.textBufferView.updateLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
4076
- }
4077
- if (changed) {
4078
- this.requestRender();
4079
- }
4080
- return this.hasSelection();
4081
- }
4082
- getSelectedText() {
4083
- return this.textBufferView.getSelectedText();
4084
- }
4085
- hasSelection() {
4086
- return this.textBufferView.hasSelection();
4087
- }
4088
- getSelection() {
4089
- return this.textBufferView.getSelection();
4090
- }
4091
- render(buffer, deltaTime) {
4092
- if (!this.visible)
4093
- return;
4094
- const screenX = this._screenX;
4095
- const screenY = this._screenY;
4096
- this.markClean();
4097
- this._ctx.addToHitGrid(screenX, screenY, this.width, this.height, this.num);
4098
- this.renderSelf(buffer);
4099
- if (this.buffered && this.frameBuffer) {
4100
- buffer.drawFrameBuffer(screenX, screenY, this.frameBuffer);
4101
- }
4102
- }
4103
- renderSelf(buffer) {
4104
- if (this.textBuffer.ptr) {
4105
- buffer.drawTextBuffer(this.textBufferView, this._screenX, this._screenY);
4106
- }
4107
- }
4108
- destroy() {
4109
- if (this.isDestroyed)
4110
- return;
4111
- this.textBuffer.setSyntaxStyle(null);
4112
- this._textBufferSyntaxStyle.destroy();
4113
- this.textBufferView.destroy();
4114
- this.textBuffer.destroy();
4115
- super.destroy();
4116
- }
4117
- onFgChanged(newColor) {}
4118
- onBgChanged(newColor) {}
4119
- onAttributesChanged(newAttributes) {}
4120
- }
4121
-
4122
- // src/renderables/Code.ts
4123
- class CodeRenderable extends TextBufferRenderable {
4124
- _content;
4125
- _filetype;
4126
- _syntaxStyle;
4127
- _isHighlighting = false;
4128
- _treeSitterClient;
4129
- _highlightsDirty = false;
4130
- _highlightSnapshotId = 0;
4131
- _conceal;
4132
- _drawUnstyledText;
4133
- _shouldRenderTextBuffer = true;
4134
- _streaming;
4135
- _hadInitialContent = false;
4136
- _lastHighlights = [];
4137
- _onHighlight;
4138
- _onChunks;
4139
- _highlightingPromise = Promise.resolve();
4140
- _contentDefaultOptions = {
4141
- content: "",
4142
- conceal: true,
4143
- drawUnstyledText: true,
4144
- streaming: false
4145
- };
4146
- constructor(ctx, options) {
4147
- super(ctx, options);
4148
- this._content = options.content ?? this._contentDefaultOptions.content;
4149
- this._filetype = options.filetype;
4150
- this._syntaxStyle = options.syntaxStyle;
4151
- this._treeSitterClient = options.treeSitterClient ?? getTreeSitterClient();
4152
- this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
4153
- this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText;
4154
- this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
4155
- this._onHighlight = options.onHighlight;
4156
- this._onChunks = options.onChunks;
4157
- if (this._content.length > 0) {
4158
- this.textBuffer.setText(this._content);
4159
- this.updateTextInfo();
4160
- this._shouldRenderTextBuffer = this._drawUnstyledText || !this._filetype;
4161
- }
4162
- this._highlightsDirty = this._content.length > 0;
4163
- }
4164
- get content() {
4165
- return this._content;
4166
- }
4167
- set content(value) {
4168
- if (this._content !== value) {
4169
- this._content = value;
4170
- this._highlightsDirty = true;
4171
- this._highlightSnapshotId++;
4172
- if (this._streaming && !this._drawUnstyledText && this._filetype) {
4173
- return;
4174
- }
4175
- this.textBuffer.setText(value);
4176
- this.updateTextInfo();
4177
- }
4178
- }
4179
- get filetype() {
4180
- return this._filetype;
4181
- }
4182
- set filetype(value) {
4183
- if (this._filetype !== value) {
4184
- this._filetype = value;
4185
- this._highlightsDirty = true;
4186
- }
4187
- }
4188
- get syntaxStyle() {
4189
- return this._syntaxStyle;
4190
- }
4191
- set syntaxStyle(value) {
4192
- if (this._syntaxStyle !== value) {
4193
- this._syntaxStyle = value;
4194
- this._highlightsDirty = true;
4195
- }
4196
- }
4197
- get conceal() {
4198
- return this._conceal;
4199
- }
4200
- set conceal(value) {
4201
- if (this._conceal !== value) {
4202
- this._conceal = value;
4203
- this._highlightsDirty = true;
4204
- }
4205
- }
4206
- get drawUnstyledText() {
4207
- return this._drawUnstyledText;
4208
- }
4209
- set drawUnstyledText(value) {
4210
- if (this._drawUnstyledText !== value) {
4211
- this._drawUnstyledText = value;
4212
- this._highlightsDirty = true;
4213
- }
4214
- }
4215
- get streaming() {
4216
- return this._streaming;
4217
- }
4218
- set streaming(value) {
4219
- if (this._streaming !== value) {
4220
- this._streaming = value;
4221
- this._hadInitialContent = false;
4222
- this._lastHighlights = [];
4223
- this._highlightsDirty = true;
4224
- }
4225
- }
4226
- get treeSitterClient() {
4227
- return this._treeSitterClient;
4228
- }
4229
- set treeSitterClient(value) {
4230
- if (this._treeSitterClient !== value) {
4231
- this._treeSitterClient = value;
4232
- this._highlightsDirty = true;
4233
- }
4234
- }
4235
- get onHighlight() {
4236
- return this._onHighlight;
4237
- }
4238
- set onHighlight(value) {
4239
- if (this._onHighlight !== value) {
4240
- this._onHighlight = value;
4241
- this._highlightsDirty = true;
4242
- }
4243
- }
4244
- get onChunks() {
4245
- return this._onChunks;
4246
- }
4247
- set onChunks(value) {
4248
- if (this._onChunks !== value) {
4249
- this._onChunks = value;
4250
- this._highlightsDirty = true;
4251
- }
4252
- }
4253
- get isHighlighting() {
4254
- return this._isHighlighting;
4255
- }
4256
- get highlightingDone() {
4257
- return this._highlightingPromise;
4258
- }
4259
- async transformChunks(chunks, context) {
4260
- if (!this._onChunks)
4261
- return chunks;
4262
- const modified = await this._onChunks(chunks, context);
4263
- return modified ?? chunks;
4264
- }
4265
- ensureVisibleTextBeforeHighlight() {
4266
- if (this.isDestroyed)
4267
- return;
4268
- const content = this._content;
4269
- if (!this._filetype) {
4270
- this._shouldRenderTextBuffer = true;
4271
- return;
4272
- }
4273
- const isInitialContent = this._streaming && !this._hadInitialContent;
4274
- const shouldDrawUnstyledNow = this._streaming ? isInitialContent && this._drawUnstyledText : this._drawUnstyledText;
4275
- if (this._streaming && !isInitialContent) {
4276
- this._shouldRenderTextBuffer = true;
4277
- } else if (shouldDrawUnstyledNow) {
4278
- this.textBuffer.setText(content);
4279
- this._shouldRenderTextBuffer = true;
4280
- } else {
4281
- this._shouldRenderTextBuffer = false;
4282
- }
4283
- }
4284
- async startHighlight() {
4285
- const content = this._content;
4286
- const filetype = this._filetype;
4287
- const snapshotId = ++this._highlightSnapshotId;
4288
- if (!filetype)
4289
- return;
4290
- const isInitialContent = this._streaming && !this._hadInitialContent;
4291
- if (isInitialContent) {
4292
- this._hadInitialContent = true;
4293
- }
4294
- this._isHighlighting = true;
4295
- try {
4296
- const result = await this._treeSitterClient.highlightOnce(content, filetype);
4297
- if (snapshotId !== this._highlightSnapshotId) {
4298
- return;
4299
- }
4300
- if (this.isDestroyed)
4301
- return;
4302
- let highlights = result.highlights ?? [];
4303
- if (this._onHighlight && highlights.length >= 0) {
4304
- const context = {
4305
- content,
4306
- filetype,
4307
- syntaxStyle: this._syntaxStyle
4308
- };
4309
- const modified = await this._onHighlight(highlights, context);
4310
- if (modified !== undefined) {
4311
- highlights = modified;
4312
- }
4313
- }
4314
- if (snapshotId !== this._highlightSnapshotId) {
4315
- return;
4316
- }
4317
- if (this.isDestroyed)
4318
- return;
4319
- if (highlights.length > 0) {
4320
- if (this._streaming) {
4321
- this._lastHighlights = highlights;
4322
- }
4323
- }
4324
- if (highlights.length > 0 || this._onChunks) {
4325
- const context = {
4326
- content,
4327
- filetype,
4328
- syntaxStyle: this._syntaxStyle,
4329
- highlights
4330
- };
4331
- let chunks = treeSitterToTextChunks(content, highlights, this._syntaxStyle, {
4332
- enabled: this._conceal
4333
- });
4334
- chunks = await this.transformChunks(chunks, context);
4335
- if (snapshotId !== this._highlightSnapshotId) {
4336
- return;
4337
- }
4338
- if (this.isDestroyed)
4339
- return;
4340
- const styledText = new StyledText(chunks);
4341
- this.textBuffer.setStyledText(styledText);
4342
- } else {
4343
- this.textBuffer.setText(content);
4344
- }
4345
- this._shouldRenderTextBuffer = true;
4346
- this._isHighlighting = false;
4347
- this._highlightsDirty = false;
4348
- this.updateTextInfo();
4349
- this.requestRender();
4350
- } catch (error) {
4351
- if (snapshotId !== this._highlightSnapshotId) {
4352
- return;
4353
- }
4354
- console.warn("Code highlighting failed, falling back to plain text:", error);
4355
- if (this.isDestroyed)
4356
- return;
4357
- this.textBuffer.setText(content);
4358
- this._shouldRenderTextBuffer = true;
4359
- this._isHighlighting = false;
4360
- this._highlightsDirty = false;
4361
- this.updateTextInfo();
4362
- this.requestRender();
4363
- }
4364
- }
4365
- getLineHighlights(lineIdx) {
4366
- return this.textBuffer.getLineHighlights(lineIdx);
4367
- }
4368
- renderSelf(buffer) {
4369
- if (this._highlightsDirty) {
4370
- if (this.isDestroyed)
4371
- return;
4372
- if (this._content.length === 0) {
4373
- this._shouldRenderTextBuffer = false;
4374
- this._highlightsDirty = false;
4375
- } else if (!this._filetype) {
4376
- this._shouldRenderTextBuffer = true;
4377
- this._highlightsDirty = false;
4378
- } else {
4379
- this.ensureVisibleTextBeforeHighlight();
4380
- this._highlightsDirty = false;
4381
- this._highlightingPromise = this.startHighlight();
4382
- }
4383
- }
4384
- if (!this._shouldRenderTextBuffer)
4385
- return;
4386
- super.renderSelf(buffer);
4387
- }
4388
- }
4389
- // src/renderables/TextNode.ts
4390
- var BrandedTextNodeRenderable = Symbol.for("@opentui/core/TextNodeRenderable");
4391
- function isTextNodeRenderable(obj) {
4392
- return !!obj?.[BrandedTextNodeRenderable];
4393
- }
4394
- function styledTextToTextNodes(styledText) {
4395
- return styledText.chunks.map((chunk) => {
4396
- const node = new TextNodeRenderable({
4397
- fg: chunk.fg,
4398
- bg: chunk.bg,
4399
- attributes: chunk.attributes,
4400
- link: chunk.link
4401
- });
4402
- node.add(chunk.text);
4403
- return node;
4404
- });
4405
- }
4406
-
4407
- class TextNodeRenderable extends BaseRenderable {
4408
- [BrandedTextNodeRenderable] = true;
4409
- _fg;
4410
- _bg;
4411
- _attributes;
4412
- _link;
4413
- _children = [];
4414
- parent = null;
4415
- constructor(options) {
4416
- super(options);
4417
- this._fg = options.fg ? parseColor(options.fg) : undefined;
4418
- this._bg = options.bg ? parseColor(options.bg) : undefined;
4419
- this._attributes = options.attributes ?? 0;
4420
- this._link = options.link;
4421
- }
4422
- get children() {
4423
- return this._children;
4424
- }
4425
- set children(children) {
4426
- this._children = children;
4427
- this.requestRender();
4428
- }
4429
- requestRender() {
4430
- this.markDirty();
4431
- this.parent?.requestRender();
4432
- }
4433
- add(obj, index) {
4434
- if (typeof obj === "string") {
4435
- if (index !== undefined) {
4436
- this._children.splice(index, 0, obj);
4437
- this.requestRender();
4438
- return index;
4439
- }
4440
- const insertIndex = this._children.length;
4441
- this._children.push(obj);
4442
- this.requestRender();
4443
- return insertIndex;
4444
- }
4445
- if (isTextNodeRenderable(obj)) {
4446
- if (index !== undefined) {
4447
- this._children.splice(index, 0, obj);
4448
- obj.parent = this;
4449
- this.requestRender();
4450
- return index;
4451
- }
4452
- const insertIndex = this._children.length;
4453
- this._children.push(obj);
4454
- obj.parent = this;
4455
- this.requestRender();
4456
- return insertIndex;
4457
- }
4458
- if (isStyledText(obj)) {
4459
- const textNodes = styledTextToTextNodes(obj);
4460
- if (index !== undefined) {
4461
- this._children.splice(index, 0, ...textNodes);
4462
- textNodes.forEach((node) => node.parent = this);
4463
- this.requestRender();
4464
- return index;
4465
- }
4466
- const insertIndex = this._children.length;
4467
- this._children.push(...textNodes);
4468
- textNodes.forEach((node) => node.parent = this);
4469
- this.requestRender();
4470
- return insertIndex;
4471
- }
4472
- throw new Error("TextNodeRenderable only accepts strings, TextNodeRenderable instances, or StyledText instances");
3077
+ this.renderFontToBuffer();
4473
3078
  }
4474
- replace(obj, index) {
4475
- this._children[index] = obj;
4476
- if (typeof obj !== "string") {
4477
- obj.parent = this;
4478
- }
4479
- this.requestRender();
3079
+ get text() {
3080
+ return this._text;
4480
3081
  }
4481
- insertBefore(child, anchorNode) {
4482
- if (!anchorNode || !isTextNodeRenderable(anchorNode)) {
4483
- throw new Error("Anchor must be a TextNodeRenderable");
4484
- }
4485
- const anchorIndex = this._children.indexOf(anchorNode);
4486
- if (anchorIndex === -1) {
4487
- throw new Error("Anchor node not found in children");
4488
- }
4489
- if (typeof child === "string") {
4490
- this._children.splice(anchorIndex, 0, child);
4491
- } else if (isTextNodeRenderable(child)) {
4492
- this._children.splice(anchorIndex, 0, child);
4493
- child.parent = this;
4494
- } else if (child instanceof StyledText) {
4495
- const textNodes = styledTextToTextNodes(child);
4496
- this._children.splice(anchorIndex, 0, ...textNodes);
4497
- textNodes.forEach((node) => node.parent = this);
4498
- } else {
4499
- throw new Error("Child must be a string, TextNodeRenderable, or StyledText instance");
3082
+ set text(value) {
3083
+ this._text = value;
3084
+ this.updateDimensions();
3085
+ if (this.lastLocalSelection) {
3086
+ this.selectionHelper.onLocalSelectionChanged(this.lastLocalSelection, this.width, this.height);
4500
3087
  }
3088
+ this.renderFontToBuffer();
4501
3089
  this.requestRender();
4502
- return this;
4503
3090
  }
4504
- remove(id) {
4505
- const childIndex = this.getRenderableIndex(id);
4506
- if (childIndex === -1) {
4507
- throw new Error("Child not found in children");
4508
- }
4509
- const child = this._children[childIndex];
4510
- this._children.splice(childIndex, 1);
4511
- child.parent = null;
4512
- this.requestRender();
4513
- return this;
3091
+ get font() {
3092
+ return this._font;
4514
3093
  }
4515
- clear() {
4516
- this._children = [];
3094
+ set font(value) {
3095
+ this._font = value;
3096
+ this.updateDimensions();
3097
+ if (this.lastLocalSelection) {
3098
+ this.selectionHelper.onLocalSelectionChanged(this.lastLocalSelection, this.width, this.height);
3099
+ }
3100
+ this.renderFontToBuffer();
4517
3101
  this.requestRender();
4518
3102
  }
4519
- mergeStyles(parentStyle) {
4520
- return {
4521
- fg: this._fg ?? parentStyle.fg,
4522
- bg: this._bg ?? parentStyle.bg,
4523
- attributes: this._attributes | parentStyle.attributes,
4524
- link: this._link ?? parentStyle.link
4525
- };
3103
+ get color() {
3104
+ return this._color;
4526
3105
  }
4527
- gatherWithInheritedStyle(parentStyle = {
4528
- fg: undefined,
4529
- bg: undefined,
4530
- attributes: 0
4531
- }) {
4532
- const currentStyle = this.mergeStyles(parentStyle);
4533
- const chunks = [];
4534
- for (const child of this._children) {
4535
- if (typeof child === "string") {
4536
- chunks.push({
4537
- __isChunk: true,
4538
- text: child,
4539
- fg: currentStyle.fg,
4540
- bg: currentStyle.bg,
4541
- attributes: currentStyle.attributes,
4542
- link: currentStyle.link
4543
- });
4544
- } else {
4545
- const childChunks = child.gatherWithInheritedStyle(currentStyle);
4546
- chunks.push(...childChunks);
4547
- }
4548
- }
4549
- this.markClean();
4550
- return chunks;
3106
+ set color(value) {
3107
+ this._color = value;
3108
+ this.renderFontToBuffer();
3109
+ this.requestRender();
4551
3110
  }
4552
- static fromString(text, options = {}) {
4553
- const node = new TextNodeRenderable(options);
4554
- node.add(text);
4555
- return node;
3111
+ get backgroundColor() {
3112
+ return this._backgroundColor;
4556
3113
  }
4557
- static fromNodes(nodes, options = {}) {
4558
- const node = new TextNodeRenderable(options);
4559
- for (const childNode of nodes) {
4560
- node.add(childNode);
4561
- }
4562
- return node;
3114
+ set backgroundColor(value) {
3115
+ this._backgroundColor = value;
3116
+ this.renderFontToBuffer();
3117
+ this.requestRender();
4563
3118
  }
4564
- toChunks(parentStyle = {
4565
- fg: undefined,
4566
- bg: undefined,
4567
- attributes: 0
4568
- }) {
4569
- return this.gatherWithInheritedStyle(parentStyle);
3119
+ updateDimensions() {
3120
+ const measurements = measureText({ text: this._text, font: this._font });
3121
+ this.width = measurements.width;
3122
+ this.height = measurements.height;
4570
3123
  }
4571
- getChildren() {
4572
- return this._children.filter((child) => typeof child !== "string");
3124
+ shouldStartSelection(x, y) {
3125
+ const localX = x - this.x;
3126
+ const localY = y - this.y;
3127
+ return this.selectionHelper.shouldStartSelection(localX, localY, this.width, this.height);
4573
3128
  }
4574
- getChildrenCount() {
4575
- return this._children.length;
3129
+ onSelectionChanged(selection) {
3130
+ const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
3131
+ this.lastLocalSelection = localSelection;
3132
+ const changed = this.selectionHelper.onLocalSelectionChanged(localSelection, this.width, this.height);
3133
+ if (changed) {
3134
+ this.renderFontToBuffer();
3135
+ this.requestRender();
3136
+ }
3137
+ return changed;
4576
3138
  }
4577
- getRenderable(id) {
4578
- return this._children.find((child) => typeof child !== "string" && child.id === id);
3139
+ getSelectedText() {
3140
+ const selection = this.selectionHelper.getSelection();
3141
+ if (!selection)
3142
+ return "";
3143
+ return this._text.slice(selection.start, selection.end);
4579
3144
  }
4580
- getRenderableIndex(id) {
4581
- return this._children.findIndex((child) => isTextNodeRenderable(child) && child.id === id);
3145
+ hasSelection() {
3146
+ return this.selectionHelper.hasSelection();
4582
3147
  }
4583
- get fg() {
4584
- return this._fg;
3148
+ onResize(width, height) {
3149
+ super.onResize(width, height);
3150
+ this.renderFontToBuffer();
4585
3151
  }
4586
- set fg(fg2) {
4587
- if (!fg2) {
4588
- this._fg = undefined;
4589
- this.requestRender();
3152
+ renderFontToBuffer() {
3153
+ if (this.isDestroyed)
4590
3154
  return;
3155
+ this.frameBuffer.clear(parseColor(this._backgroundColor));
3156
+ renderFontToFrameBuffer(this.frameBuffer, {
3157
+ text: this._text,
3158
+ x: 0,
3159
+ y: 0,
3160
+ color: this.color,
3161
+ backgroundColor: this._backgroundColor,
3162
+ font: this._font
3163
+ });
3164
+ const selection = this.selectionHelper.getSelection();
3165
+ if (selection && (this._selectionBg || this._selectionFg)) {
3166
+ this.renderSelectionHighlight(selection);
4591
3167
  }
4592
- this._fg = parseColor(fg2);
4593
- this.requestRender();
4594
3168
  }
4595
- set bg(bg2) {
4596
- if (!bg2) {
4597
- this._bg = undefined;
4598
- this.requestRender();
3169
+ renderSelectionHighlight(selection) {
3170
+ if (!this._selectionBg && !this._selectionFg)
4599
3171
  return;
3172
+ const selectedText = this._text.slice(selection.start, selection.end);
3173
+ if (!selectedText)
3174
+ return;
3175
+ const positions = getCharacterPositions(this._text, this._font);
3176
+ const startX = positions[selection.start] || 0;
3177
+ const endX = selection.end < positions.length ? positions[selection.end] : measureText({ text: this._text, font: this._font }).width;
3178
+ if (this._selectionBg) {
3179
+ this.frameBuffer.fillRect(startX, 0, endX - startX, this.height, parseColor(this._selectionBg));
3180
+ }
3181
+ if (this._selectionFg || this._selectionBg) {
3182
+ renderFontToFrameBuffer(this.frameBuffer, {
3183
+ text: selectedText,
3184
+ x: startX,
3185
+ y: 0,
3186
+ color: this._selectionFg ? this._selectionFg : this._color,
3187
+ backgroundColor: this._selectionBg ? this._selectionBg : this._backgroundColor,
3188
+ font: this._font
3189
+ });
4600
3190
  }
4601
- this._bg = parseColor(bg2);
4602
- this.requestRender();
4603
- }
4604
- get bg() {
4605
- return this._bg;
4606
- }
4607
- set attributes(attributes) {
4608
- this._attributes = attributes;
4609
- this.requestRender();
4610
- }
4611
- get attributes() {
4612
- return this._attributes;
4613
- }
4614
- set link(link2) {
4615
- this._link = link2;
4616
- this.requestRender();
4617
- }
4618
- get link() {
4619
- return this._link;
4620
- }
4621
- findDescendantById(id) {
4622
- return;
4623
- }
4624
- }
4625
-
4626
- class RootTextNodeRenderable extends TextNodeRenderable {
4627
- ctx;
4628
- textParent;
4629
- constructor(ctx, options, textParent) {
4630
- super(options);
4631
- this.ctx = ctx;
4632
- this.textParent = textParent;
4633
- }
4634
- requestRender() {
4635
- this.markDirty();
4636
- this.ctx.requestRender();
4637
3191
  }
4638
3192
  }
4639
-
4640
3193
  // src/renderables/composition/constructs.ts
4641
3194
  function Generic(props, ...children) {
4642
3195
  return h(VRenderable, props || {}, ...children);
@@ -5340,103 +3893,6 @@ function parsePatch(uniDiff) {
5340
3893
  }
5341
3894
  return list;
5342
3895
  }
5343
- // src/renderables/Text.ts
5344
- class TextRenderable extends TextBufferRenderable {
5345
- _text;
5346
- _hasManualStyledText = false;
5347
- rootTextNode;
5348
- _contentDefaultOptions = {
5349
- content: ""
5350
- };
5351
- constructor(ctx, options) {
5352
- super(ctx, options);
5353
- const content = options.content ?? this._contentDefaultOptions.content;
5354
- const styledText = typeof content === "string" ? stringToStyledText(content) : content;
5355
- this._text = styledText;
5356
- this._hasManualStyledText = options.content !== undefined && content !== "";
5357
- this.rootTextNode = new RootTextNodeRenderable(ctx, {
5358
- id: `${this.id}-root`,
5359
- fg: this._defaultFg,
5360
- bg: this._defaultBg,
5361
- attributes: this._defaultAttributes
5362
- }, this);
5363
- this.updateTextBuffer(styledText);
5364
- }
5365
- updateTextBuffer(styledText) {
5366
- this.textBuffer.setStyledText(styledText);
5367
- this.clearChunks(styledText);
5368
- }
5369
- clearChunks(styledText) {}
5370
- get content() {
5371
- return this._text;
5372
- }
5373
- get chunks() {
5374
- return this._text.chunks;
5375
- }
5376
- get textNode() {
5377
- return this.rootTextNode;
5378
- }
5379
- set content(value) {
5380
- this._hasManualStyledText = true;
5381
- const styledText = typeof value === "string" ? stringToStyledText(value) : value;
5382
- if (this._text !== styledText) {
5383
- this._text = styledText;
5384
- this.updateTextBuffer(styledText);
5385
- this.updateTextInfo();
5386
- }
5387
- }
5388
- updateTextFromNodes() {
5389
- if (this.rootTextNode.isDirty && !this._hasManualStyledText) {
5390
- const chunks = this.rootTextNode.gatherWithInheritedStyle({
5391
- fg: this._defaultFg,
5392
- bg: this._defaultBg,
5393
- attributes: this._defaultAttributes,
5394
- link: undefined
5395
- });
5396
- this.textBuffer.setStyledText(new StyledText(chunks));
5397
- this.refreshLocalSelection();
5398
- this.yogaNode.markDirty();
5399
- }
5400
- }
5401
- add(obj, index) {
5402
- return this.rootTextNode.add(obj, index);
5403
- }
5404
- remove(id) {
5405
- this.rootTextNode.remove(id);
5406
- }
5407
- insertBefore(obj, anchor) {
5408
- this.rootTextNode.insertBefore(obj, anchor);
5409
- return this.rootTextNode.children.indexOf(obj);
5410
- }
5411
- getTextChildren() {
5412
- return this.rootTextNode.getChildren();
5413
- }
5414
- clear() {
5415
- this.rootTextNode.clear();
5416
- const emptyStyledText = stringToStyledText("");
5417
- this._text = emptyStyledText;
5418
- this.updateTextBuffer(emptyStyledText);
5419
- this.updateTextInfo();
5420
- this.requestRender();
5421
- }
5422
- onLifecyclePass = () => {
5423
- this.updateTextFromNodes();
5424
- };
5425
- onFgChanged(newColor) {
5426
- this.rootTextNode.fg = newColor;
5427
- }
5428
- onBgChanged(newColor) {
5429
- this.rootTextNode.bg = newColor;
5430
- }
5431
- onAttributesChanged(newAttributes) {
5432
- this.rootTextNode.attributes = newAttributes;
5433
- }
5434
- destroy() {
5435
- this.rootTextNode.children.length = 0;
5436
- super.destroy();
5437
- }
5438
- }
5439
-
5440
3896
  // src/renderables/Diff.ts
5441
3897
  class DiffRenderable extends Renderable {
5442
3898
  _diff;
@@ -6889,6 +5345,7 @@ class TextTableRenderable extends Renderable {
6889
5345
  _columnWidthMode;
6890
5346
  _columnFitter;
6891
5347
  _cellPadding;
5348
+ _columnGap;
6892
5349
  _showBorders;
6893
5350
  _border;
6894
5351
  _outerBorder;
@@ -6919,6 +5376,7 @@ class TextTableRenderable extends Renderable {
6919
5376
  columnWidthMode: "full",
6920
5377
  columnFitter: "proportional",
6921
5378
  cellPadding: 0,
5379
+ columnGap: 0,
6922
5380
  showBorders: true,
6923
5381
  border: true,
6924
5382
  outerBorder: true,
@@ -6940,6 +5398,7 @@ class TextTableRenderable extends Renderable {
6940
5398
  this._columnWidthMode = options.columnWidthMode ?? this._defaultOptions.columnWidthMode;
6941
5399
  this._columnFitter = this.resolveColumnFitter(options.columnFitter);
6942
5400
  this._cellPadding = this.resolveCellPadding(options.cellPadding);
5401
+ this._columnGap = this.resolveColumnGap(options.columnGap);
6943
5402
  this._showBorders = options.showBorders ?? this._defaultOptions.showBorders;
6944
5403
  this._border = options.border ?? this._defaultOptions.border;
6945
5404
  this._hasExplicitOuterBorder = options.outerBorder !== undefined;
@@ -7007,6 +5466,16 @@ class TextTableRenderable extends Renderable {
7007
5466
  this._cellPadding = next;
7008
5467
  this.invalidateLayoutAndRaster();
7009
5468
  }
5469
+ get columnGap() {
5470
+ return this._columnGap;
5471
+ }
5472
+ set columnGap(value) {
5473
+ const next = this.resolveColumnGap(value);
5474
+ if (this._columnGap === next)
5475
+ return;
5476
+ this._columnGap = next;
5477
+ this.invalidateLayoutAndRaster();
5478
+ }
7010
5479
  get showBorders() {
7011
5480
  return this._showBorders;
7012
5481
  }
@@ -7320,7 +5789,7 @@ class TextTableRenderable extends Renderable {
7320
5789
  const borderLayout = this.resolveBorderLayout();
7321
5790
  const columnWidths = this.computeColumnWidths(maxTableWidth, borderLayout);
7322
5791
  const rowHeights = this.computeRowHeights(columnWidths);
7323
- const columnOffsets = this.computeOffsets(columnWidths, borderLayout.left, borderLayout.right, borderLayout.innerVertical);
5792
+ const columnOffsets = this.computeOffsets(columnWidths, borderLayout.left, borderLayout.right, borderLayout.innerVertical, this.getInterColumnGap(borderLayout));
7324
5793
  const rowOffsets = this.computeOffsets(rowHeights, borderLayout.top, borderLayout.bottom, borderLayout.innerHorizontal);
7325
5794
  return {
7326
5795
  columnWidths,
@@ -7352,7 +5821,7 @@ class TextTableRenderable extends Renderable {
7352
5821
  if (maxTableWidth === undefined || !Number.isFinite(maxTableWidth) || maxTableWidth <= 0) {
7353
5822
  return intrinsicWidths;
7354
5823
  }
7355
- const maxContentWidth = Math.max(1, Math.floor(maxTableWidth) - this.getVerticalBorderCount(borderLayout));
5824
+ const maxContentWidth = Math.max(1, Math.floor(maxTableWidth) - this.getVerticalBorderCount(borderLayout) - this.getTotalInterColumnGap(borderLayout));
7356
5825
  const currentWidth = intrinsicWidths.reduce((sum, width) => sum + width, 0);
7357
5826
  if (currentWidth === maxContentWidth) {
7358
5827
  return intrinsicWidths;
@@ -7535,17 +6004,26 @@ class TextTableRenderable extends Renderable {
7535
6004
  }
7536
6005
  return rowHeights;
7537
6006
  }
7538
- computeOffsets(parts, startBoundary, endBoundary, includeInnerBoundaries) {
6007
+ computeOffsets(parts, startBoundary, endBoundary, includeInnerBoundaries, innerGap = 0) {
7539
6008
  const offsets = [startBoundary ? 0 : -1];
7540
6009
  let cursor = offsets[0] ?? 0;
7541
6010
  for (let idx = 0;idx < parts.length; idx++) {
7542
6011
  const size = parts[idx] ?? 1;
7543
- const hasBoundaryAfter = idx < parts.length - 1 ? includeInnerBoundaries : endBoundary;
7544
- cursor += size + (hasBoundaryAfter ? 1 : 0);
6012
+ const separatorAfter = idx < parts.length - 1 ? includeInnerBoundaries ? 1 : innerGap : endBoundary ? 1 : 0;
6013
+ cursor += size + separatorAfter;
7545
6014
  offsets.push(cursor);
7546
6015
  }
7547
6016
  return offsets;
7548
6017
  }
6018
+ getInterColumnGap(borderLayout) {
6019
+ if (borderLayout.innerVertical) {
6020
+ return 0;
6021
+ }
6022
+ return this._columnGap;
6023
+ }
6024
+ getTotalInterColumnGap(borderLayout) {
6025
+ return Math.max(0, this._columnCount - 1) * this.getInterColumnGap(borderLayout);
6026
+ }
7549
6027
  applyLayoutToViews(layout) {
7550
6028
  const horizontalPadding = this.getHorizontalCellPadding();
7551
6029
  const verticalPadding = this.getVerticalCellPadding();
@@ -7864,6 +6342,12 @@ class TextTableRenderable extends Renderable {
7864
6342
  }
7865
6343
  return Math.max(0, Math.floor(value));
7866
6344
  }
6345
+ resolveColumnGap(value) {
6346
+ if (value === undefined || !Number.isFinite(value)) {
6347
+ return this._defaultOptions.columnGap;
6348
+ }
6349
+ return Math.max(0, Math.floor(value));
6350
+ }
7867
6351
  invalidateLayoutAndRaster(markYogaDirty = true) {
7868
6352
  this._layoutDirty = true;
7869
6353
  this._rasterDirty = true;
@@ -9150,9 +7634,13 @@ function parseMarkdownIncremental(newContent, prevState, trailingUnstable = 2) {
9150
7634
  if (!prevState || prevState.tokens.length === 0) {
9151
7635
  try {
9152
7636
  const tokens = x.lex(newContent, { gfm: true });
9153
- return { content: newContent, tokens };
7637
+ return {
7638
+ content: newContent,
7639
+ tokens,
7640
+ stableTokenCount: Math.max(0, tokens.length - trailingUnstable)
7641
+ };
9154
7642
  } catch {
9155
- return { content: newContent, tokens: [] };
7643
+ return { content: newContent, tokens: [], stableTokenCount: 0 };
9156
7644
  }
9157
7645
  }
9158
7646
  let offset = 0;
@@ -9174,23 +7662,32 @@ function parseMarkdownIncremental(newContent, prevState, trailingUnstable = 2) {
9174
7662
  const stableTokens = prevState.tokens.slice(0, reuseCount);
9175
7663
  const remainingContent = newContent.slice(offset);
9176
7664
  if (!remainingContent) {
9177
- return { content: newContent, tokens: stableTokens };
7665
+ return {
7666
+ content: newContent,
7667
+ tokens: stableTokens,
7668
+ stableTokenCount: stableTokens.length
7669
+ };
9178
7670
  }
9179
7671
  try {
9180
7672
  const newTokens = x.lex(remainingContent, { gfm: true });
9181
- return { content: newContent, tokens: [...stableTokens, ...newTokens] };
7673
+ return {
7674
+ content: newContent,
7675
+ tokens: [...stableTokens, ...newTokens],
7676
+ stableTokenCount: trailingUnstable === 0 ? stableTokens.length + newTokens.length : stableTokens.length
7677
+ };
9182
7678
  } catch {
9183
7679
  try {
9184
7680
  const fullTokens = x.lex(newContent, { gfm: true });
9185
- return { content: newContent, tokens: fullTokens };
7681
+ return { content: newContent, tokens: fullTokens, stableTokenCount: 0 };
9186
7682
  } catch {
9187
- return { content: newContent, tokens: [] };
7683
+ return { content: newContent, tokens: [], stableTokenCount: 0 };
9188
7684
  }
9189
7685
  }
9190
7686
  }
9191
7687
 
9192
7688
  // src/renderables/Markdown.ts
9193
7689
  var TRAILING_MARKDOWN_BLOCK_BREAKS_RE = /(?:\r?\n)+$/;
7690
+ var TRAILING_MARKDOWN_BLOCK_NEWLINES_RE = /(?:\r?\n)+$/;
9194
7691
  function colorsEqual(left, right) {
9195
7692
  if (!left || !right)
9196
7693
  return left === right;
@@ -9207,9 +7704,11 @@ class MarkdownRenderable extends Renderable {
9207
7704
  _treeSitterClient;
9208
7705
  _tableOptions;
9209
7706
  _renderNode;
7707
+ _internalBlockMode;
9210
7708
  _parseState = null;
9211
7709
  _streaming = false;
9212
7710
  _blockStates = [];
7711
+ _stableBlockCount = 0;
9213
7712
  _styleDirty = false;
9214
7713
  _linkifyMarkdownChunks = (chunks, context) => detectLinks(chunks, {
9215
7714
  content: context.content,
@@ -9222,7 +7721,8 @@ class MarkdownRenderable extends Renderable {
9222
7721
  content: "",
9223
7722
  conceal: true,
9224
7723
  concealCode: false,
9225
- streaming: false
7724
+ streaming: false,
7725
+ internalBlockMode: "coalesced"
9226
7726
  };
9227
7727
  constructor(ctx, options) {
9228
7728
  super(ctx, {
@@ -9240,6 +7740,7 @@ class MarkdownRenderable extends Renderable {
9240
7740
  this._tableOptions = options.tableOptions;
9241
7741
  this._renderNode = options.renderNode;
9242
7742
  this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
7743
+ this._internalBlockMode = options.internalBlockMode ?? this._contentDefaultOptions.internalBlockMode;
9243
7744
  this.updateBlocks();
9244
7745
  }
9245
7746
  get content() {
@@ -9471,6 +7972,10 @@ class MarkdownRenderable extends Renderable {
9471
7972
  break;
9472
7973
  }
9473
7974
  }
7975
+ applyMargins(renderable, marginTop, marginBottom) {
7976
+ renderable.marginTop = marginTop;
7977
+ renderable.marginBottom = marginBottom;
7978
+ }
9474
7979
  buildInlineConcealChunks(chunks, context) {
9475
7980
  const result = [];
9476
7981
  try {
@@ -9775,6 +8280,9 @@ class MarkdownRenderable extends Renderable {
9775
8280
  normalizeMarkdownBlockRaw(raw) {
9776
8281
  return raw.replace(TRAILING_MARKDOWN_BLOCK_BREAKS_RE, "");
9777
8282
  }
8283
+ normalizeScrollbackMarkdownBlockRaw(raw) {
8284
+ return raw.replace(TRAILING_MARKDOWN_BLOCK_NEWLINES_RE, "");
8285
+ }
9778
8286
  buildRenderableTokens(tokens) {
9779
8287
  if (this._renderNode) {
9780
8288
  return tokens.filter((token) => token.type !== "space");
@@ -9816,6 +8324,26 @@ class MarkdownRenderable extends Renderable {
9816
8324
  flushMarkdownRaw();
9817
8325
  return renderTokens;
9818
8326
  }
8327
+ buildTopLevelRenderBlocks(tokens) {
8328
+ const blocks = [];
8329
+ let gapBefore = "";
8330
+ for (let i = 0;i < tokens.length; i += 1) {
8331
+ const token = tokens[i];
8332
+ if (token.type === "space") {
8333
+ gapBefore += token.raw;
8334
+ continue;
8335
+ }
8336
+ const prev = blocks[blocks.length - 1];
8337
+ const marginTop = prev && (this.shouldRenderSeparately(prev.token) || TRAILING_MARKDOWN_BLOCK_BREAKS_RE.test(prev.token.raw + gapBefore)) ? 1 : 0;
8338
+ blocks.push({
8339
+ token,
8340
+ sourceTokenEnd: i + 1,
8341
+ marginTop
8342
+ });
8343
+ gapBefore = "";
8344
+ }
8345
+ return blocks;
8346
+ }
9819
8347
  getTableRowsToRender(table) {
9820
8348
  return table.rows;
9821
8349
  }
@@ -9937,13 +8465,29 @@ class MarkdownRenderable extends Renderable {
9937
8465
  changed
9938
8466
  };
9939
8467
  }
8468
+ resolveTableStyle(options = this._tableOptions) {
8469
+ if (options?.style === "columns") {
8470
+ return "columns";
8471
+ }
8472
+ if (options?.style === "grid") {
8473
+ return "grid";
8474
+ }
8475
+ return this._internalBlockMode === "top-level" ? "columns" : "grid";
8476
+ }
8477
+ usesBorderlessColumnSpacing(options = this._tableOptions) {
8478
+ const style = this.resolveTableStyle(options);
8479
+ const borders = options?.borders ?? style === "grid";
8480
+ return style === "columns" && !borders;
8481
+ }
9940
8482
  resolveTableRenderableOptions() {
9941
- const borders = this._tableOptions?.borders ?? true;
8483
+ const style = this.resolveTableStyle();
8484
+ const borders = this._tableOptions?.borders ?? style === "grid";
9942
8485
  return {
9943
- columnWidthMode: this._tableOptions?.widthMode ?? "full",
8486
+ columnWidthMode: this._tableOptions?.widthMode ?? (style === "columns" ? "content" : "full"),
9944
8487
  columnFitter: this._tableOptions?.columnFitter ?? "proportional",
9945
8488
  wrapMode: this._tableOptions?.wrapMode ?? "word",
9946
8489
  cellPadding: this._tableOptions?.cellPadding ?? 0,
8490
+ columnGap: this.usesBorderlessColumnSpacing() ? 2 : 0,
9947
8491
  border: borders,
9948
8492
  outerBorder: this._tableOptions?.outerBorder ?? borders,
9949
8493
  showBorders: borders,
@@ -9957,6 +8501,7 @@ class MarkdownRenderable extends Renderable {
9957
8501
  tableRenderable.columnFitter = options.columnFitter;
9958
8502
  tableRenderable.wrapMode = options.wrapMode;
9959
8503
  tableRenderable.cellPadding = options.cellPadding;
8504
+ tableRenderable.columnGap = options.columnGap;
9960
8505
  tableRenderable.border = options.border;
9961
8506
  tableRenderable.outerBorder = options.outerBorder;
9962
8507
  tableRenderable.showBorders = options.showBorders;
@@ -9988,6 +8533,7 @@ class MarkdownRenderable extends Renderable {
9988
8533
  columnFitter: options.columnFitter,
9989
8534
  wrapMode: options.wrapMode,
9990
8535
  cellPadding: options.cellPadding,
8536
+ columnGap: options.columnGap,
9991
8537
  border: options.border,
9992
8538
  outerBorder: options.outerBorder,
9993
8539
  showBorders: options.showBorders,
@@ -10008,6 +8554,75 @@ class MarkdownRenderable extends Renderable {
10008
8554
  tableContentCache: cache
10009
8555
  };
10010
8556
  }
8557
+ getStableBlockCount(blocks, stableTokenCount) {
8558
+ if (this._internalBlockMode !== "top-level") {
8559
+ return 0;
8560
+ }
8561
+ let stableBlockCount = 0;
8562
+ for (const block of blocks) {
8563
+ if (block.sourceTokenEnd <= stableTokenCount) {
8564
+ stableBlockCount += 1;
8565
+ continue;
8566
+ }
8567
+ break;
8568
+ }
8569
+ return stableBlockCount;
8570
+ }
8571
+ syncTopLevelBlockState(state, block, tableContentCache = state.tableContentCache) {
8572
+ state.token = block.token;
8573
+ state.tokenRaw = block.token.raw;
8574
+ state.marginTop = block.marginTop;
8575
+ state.tableContentCache = tableContentCache;
8576
+ }
8577
+ getTopLevelBlockRaw(token) {
8578
+ if (!token.raw) {
8579
+ return;
8580
+ }
8581
+ return this.shouldRenderSeparately(token) ? token.raw : this.normalizeScrollbackMarkdownBlockRaw(token.raw);
8582
+ }
8583
+ createTopLevelDefaultRenderable(block, index) {
8584
+ const { token, marginTop } = block;
8585
+ const id = `${this.id}-block-${index}`;
8586
+ if (token.type === "code") {
8587
+ const renderable2 = this.createCodeRenderable(token, id);
8588
+ renderable2.marginTop = marginTop;
8589
+ return { renderable: renderable2 };
8590
+ }
8591
+ if (token.type === "table") {
8592
+ const next = this.createTableBlock(token, id);
8593
+ next.renderable.marginTop = marginTop;
8594
+ return next;
8595
+ }
8596
+ const markdownRaw = this.getTopLevelBlockRaw(token);
8597
+ if (!markdownRaw) {
8598
+ return { renderable: undefined };
8599
+ }
8600
+ const renderable = this.createMarkdownCodeRenderable(markdownRaw, id);
8601
+ renderable.marginTop = marginTop;
8602
+ return { renderable };
8603
+ }
8604
+ createTopLevelRenderable(block, index) {
8605
+ if (!this._renderNode) {
8606
+ return this.createTopLevelDefaultRenderable(block, index);
8607
+ }
8608
+ let next;
8609
+ const context = {
8610
+ syntaxStyle: this._syntaxStyle,
8611
+ conceal: this._conceal,
8612
+ concealCode: this._concealCode,
8613
+ treeSitterClient: this._treeSitterClient,
8614
+ defaultRender: () => {
8615
+ next = this.createTopLevelDefaultRenderable(block, index);
8616
+ return next.renderable ?? null;
8617
+ }
8618
+ };
8619
+ const custom = this._renderNode(block.token, context);
8620
+ if (custom) {
8621
+ this.applyMargins(custom, block.marginTop, 0);
8622
+ return { renderable: custom };
8623
+ }
8624
+ return next ?? this.createTopLevelDefaultRenderable(block, index);
8625
+ }
10011
8626
  createDefaultRenderable(token, index, hasNextToken = false) {
10012
8627
  const id = `${this.id}-block-${index}`;
10013
8628
  const marginBottom = this.getInterBlockMargin(token, hasNextToken);
@@ -10072,12 +8687,57 @@ class MarkdownRenderable extends Renderable {
10072
8687
  this.add(markdownRenderable);
10073
8688
  state.renderable = markdownRenderable;
10074
8689
  }
8690
+ updateTopLevelBlocks(tokens, forceTableRefresh) {
8691
+ const blocks = this.buildTopLevelRenderBlocks(tokens);
8692
+ this._stableBlockCount = this.getStableBlockCount(blocks, this._parseState?.stableTokenCount ?? 0);
8693
+ let blockIndex = 0;
8694
+ for (let i = 0;i < blocks.length; i += 1) {
8695
+ const block = blocks[i];
8696
+ const existing = this._blockStates[blockIndex];
8697
+ if (existing && existing.token === block.token && !forceTableRefresh) {
8698
+ if (existing.marginTop !== block.marginTop) {
8699
+ this.applyMargins(existing.renderable, block.marginTop, 0);
8700
+ }
8701
+ this.syncTopLevelBlockState(existing, block);
8702
+ blockIndex++;
8703
+ continue;
8704
+ }
8705
+ if (existing && existing.tokenRaw === block.token.raw && existing.token.type === block.token.type && !forceTableRefresh) {
8706
+ if (existing.marginTop !== block.marginTop) {
8707
+ this.applyMargins(existing.renderable, block.marginTop, 0);
8708
+ }
8709
+ this.syncTopLevelBlockState(existing, block);
8710
+ blockIndex++;
8711
+ continue;
8712
+ }
8713
+ if (existing) {
8714
+ existing.renderable.destroyRecursively();
8715
+ }
8716
+ const next = this.createTopLevelRenderable(block, blockIndex);
8717
+ if (next.renderable) {
8718
+ this.add(next.renderable);
8719
+ this._blockStates[blockIndex] = {
8720
+ token: block.token,
8721
+ tokenRaw: block.token.raw,
8722
+ marginTop: block.marginTop,
8723
+ renderable: next.renderable,
8724
+ tableContentCache: next.tableContentCache
8725
+ };
8726
+ }
8727
+ blockIndex++;
8728
+ }
8729
+ while (this._blockStates.length > blockIndex) {
8730
+ const removed = this._blockStates.pop();
8731
+ removed.renderable.destroyRecursively();
8732
+ }
8733
+ }
10075
8734
  updateBlocks(forceTableRefresh = false) {
10076
8735
  if (this.isDestroyed)
10077
8736
  return;
10078
8737
  if (!this._content) {
10079
8738
  this.clearBlockStates();
10080
8739
  this._parseState = null;
8740
+ this._stableBlockCount = 0;
10081
8741
  return;
10082
8742
  }
10083
8743
  const trailingUnstable = this._streaming ? 2 : 0;
@@ -10085,17 +8745,24 @@ class MarkdownRenderable extends Renderable {
10085
8745
  const tokens = this._parseState.tokens;
10086
8746
  if (tokens.length === 0 && this._content.length > 0) {
10087
8747
  this.clearBlockStates();
8748
+ this._stableBlockCount = 0;
10088
8749
  const fallback = this.createMarkdownCodeRenderable(this._content, `${this.id}-fallback`);
10089
8750
  this.add(fallback);
10090
8751
  this._blockStates = [
10091
8752
  {
10092
8753
  token: { type: "text", raw: this._content, text: this._content },
10093
8754
  tokenRaw: this._content,
8755
+ marginTop: 0,
10094
8756
  renderable: fallback
10095
8757
  }
10096
8758
  ];
10097
8759
  return;
10098
8760
  }
8761
+ if (this._internalBlockMode === "top-level") {
8762
+ this.updateTopLevelBlocks(tokens, forceTableRefresh);
8763
+ return;
8764
+ }
8765
+ this._stableBlockCount = 0;
10099
8766
  const blockTokens = this.buildRenderableTokens(tokens);
10100
8767
  const lastBlockIndex = blockTokens.length - 1;
10101
8768
  let blockIndex = 0;
@@ -10180,8 +8847,13 @@ class MarkdownRenderable extends Renderable {
10180
8847
  state.renderable.destroyRecursively();
10181
8848
  }
10182
8849
  this._blockStates = [];
8850
+ this._stableBlockCount = 0;
10183
8851
  }
10184
8852
  rerenderBlocks() {
8853
+ if (this._internalBlockMode === "top-level") {
8854
+ this.updateBlocks(true);
8855
+ return;
8856
+ }
10185
8857
  for (let i = 0;i < this._blockStates.length; i++) {
10186
8858
  const state = this._blockStates[i];
10187
8859
  const hasNextToken = i < this._blockStates.length - 1;
@@ -12287,7 +10959,7 @@ class TimeToFirstDrawRenderable extends Renderable {
12287
10959
  return Math.max(0, Math.floor(value));
12288
10960
  }
12289
10961
  }
12290
- export { TextBufferView, convertThemeToStyles, SyntaxStyle, DistortionEffect, VignetteEffect, CloudsEffect, FlamesEffect, CRTRollingBarEffect, RainbowTextEffect, applyScanlines, applyInvert, applyNoise, applyChromaticAberration, applyAsciiArt, applyBrightness, applyGain, applySaturation, BloomEffect, SEPIA_MATRIX, PROTANOPIA_SIM_MATRIX, DEUTERANOPIA_SIM_MATRIX, TRITANOPIA_SIM_MATRIX, ACHROMATOPSIA_MATRIX, PROTANOPIA_COMP_MATRIX, DEUTERANOPIA_COMP_MATRIX, TRITANOPIA_COMP_MATRIX, TECHNICOLOR_MATRIX, SOLARIZATION_MATRIX, SYNTHWAVE_MATRIX, GREENSCALE_MATRIX, GRAYSCALE_MATRIX, INVERT_MATRIX, Timeline, engine, createTimeline, SlotRegistry, createSlotRegistry, createCoreSlotRegistry, registerCorePlugin, resolveCoreSlot, SlotRenderable, NativeSpanFeed, FrameBufferRenderable, ASCIIFontRenderable, BoxRenderable, TextBufferRenderable, CodeRenderable, isTextNodeRenderable, TextNodeRenderable, RootTextNodeRenderable, Generic, Box, Text, ASCIIFont, Input, Select, TabSelect, FrameBuffer, Code, ScrollBox, vstyles, VRenderable, LineNumberRenderable, TextRenderable, DiffRenderable, TextareaRenderable, InputRenderableEvents, InputRenderable, TextTableRenderable, MarkdownRenderable, SliderRenderable, ScrollBarRenderable, ArrowRenderable, ScrollBoxRenderable, SelectRenderableEvents, SelectRenderable, TabSelectRenderableEvents, TabSelectRenderable, TimeToFirstDrawRenderable, exports_src2 as exports_src };
10962
+ export { DistortionEffect, VignetteEffect, CloudsEffect, FlamesEffect, CRTRollingBarEffect, RainbowTextEffect, applyScanlines, applyInvert, applyNoise, applyChromaticAberration, applyAsciiArt, applyBrightness, applyGain, applySaturation, BloomEffect, SEPIA_MATRIX, PROTANOPIA_SIM_MATRIX, DEUTERANOPIA_SIM_MATRIX, TRITANOPIA_SIM_MATRIX, ACHROMATOPSIA_MATRIX, PROTANOPIA_COMP_MATRIX, DEUTERANOPIA_COMP_MATRIX, TRITANOPIA_COMP_MATRIX, TECHNICOLOR_MATRIX, SOLARIZATION_MATRIX, SYNTHWAVE_MATRIX, GREENSCALE_MATRIX, GRAYSCALE_MATRIX, INVERT_MATRIX, Timeline, engine, createTimeline, SlotRegistry, createSlotRegistry, createCoreSlotRegistry, registerCorePlugin, resolveCoreSlot, SlotRenderable, NativeSpanFeed, FrameBufferRenderable, ASCIIFontRenderable, Generic, Box, Text, ASCIIFont, Input, Select, TabSelect, FrameBuffer, Code, ScrollBox, vstyles, VRenderable, LineNumberRenderable, DiffRenderable, TextareaRenderable, InputRenderableEvents, InputRenderable, TextTableRenderable, MarkdownRenderable, SliderRenderable, ScrollBarRenderable, ArrowRenderable, ScrollBoxRenderable, SelectRenderableEvents, SelectRenderable, TabSelectRenderableEvents, TabSelectRenderable, TimeToFirstDrawRenderable, exports_src2 as exports_src };
12291
10963
 
12292
- //# debugId=1D1B6F62C2F2A1BF64756E2164756E21
12293
- //# sourceMappingURL=index-kwnan0ww.js.map
10964
+ //# debugId=76D5B28EFB1D404464756E2164756E21
10965
+ //# sourceMappingURL=index-gwfqqvw5.js.map