@opentui/core 0.1.81 → 0.1.82

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
@@ -153,7 +153,7 @@ import {
153
153
  white,
154
154
  wrapWithDelegates,
155
155
  yellow
156
- } from "./index-ve2seej0.js";
156
+ } from "./index-fv58mb45.js";
157
157
  // src/text-buffer-view.ts
158
158
  class TextBufferView {
159
159
  lib;
@@ -2748,6 +2748,7 @@ class TextBufferRenderable extends Renderable {
2748
2748
  _truncate = false;
2749
2749
  textBuffer;
2750
2750
  textBufferView;
2751
+ _textBufferSyntaxStyle;
2751
2752
  _defaultOptions = {
2752
2753
  fg: RGBA.fromValues(1, 1, 1, 1),
2753
2754
  bg: RGBA.fromValues(0, 0, 0, 0),
@@ -2774,8 +2775,8 @@ class TextBufferRenderable extends Renderable {
2774
2775
  this._truncate = options.truncate ?? this._defaultOptions.truncate;
2775
2776
  this.textBuffer = TextBuffer.create(this._ctx.widthMethod);
2776
2777
  this.textBufferView = TextBufferView.create(this.textBuffer);
2777
- const style = SyntaxStyle.create();
2778
- this.textBuffer.setSyntaxStyle(style);
2778
+ this._textBufferSyntaxStyle = SyntaxStyle.create();
2779
+ this.textBuffer.setSyntaxStyle(this._textBufferSyntaxStyle);
2779
2780
  this.textBufferView.setWrapMode(this._wrapMode);
2780
2781
  this.setupMeasureFunc();
2781
2782
  this.textBuffer.setDefaultFg(this._defaultFg);
@@ -3085,6 +3086,10 @@ class TextBufferRenderable extends Renderable {
3085
3086
  }
3086
3087
  }
3087
3088
  destroy() {
3089
+ if (this.isDestroyed)
3090
+ return;
3091
+ this.textBuffer.setSyntaxStyle(null);
3092
+ this._textBufferSyntaxStyle.destroy();
3088
3093
  this.textBufferView.destroy();
3089
3094
  this.textBuffer.destroy();
3090
3095
  super.destroy();
@@ -7159,6 +7164,840 @@ class InputRenderable extends TextareaRenderable {
7159
7164
  }
7160
7165
  set initialValue(value) {}
7161
7166
  }
7167
+ // src/renderables/TextTable.ts
7168
+ var MEASURE_HEIGHT = 1e4;
7169
+
7170
+ class TextTableRenderable extends Renderable {
7171
+ _content;
7172
+ _wrapMode;
7173
+ _columnWidthMode;
7174
+ _cellPadding;
7175
+ _showBorders;
7176
+ _border;
7177
+ _outerBorder;
7178
+ _hasExplicitOuterBorder;
7179
+ _borderStyle;
7180
+ _borderColor;
7181
+ _borderBackgroundColor;
7182
+ _backgroundColor;
7183
+ _defaultFg;
7184
+ _defaultBg;
7185
+ _defaultAttributes;
7186
+ _selectionBg;
7187
+ _selectionFg;
7188
+ _lastLocalSelection = null;
7189
+ _cells = [];
7190
+ _prevCellContent = [];
7191
+ _rowCount = 0;
7192
+ _columnCount = 0;
7193
+ _layout = this.createEmptyLayout();
7194
+ _layoutDirty = true;
7195
+ _rasterDirty = true;
7196
+ _cachedMeasureLayout = null;
7197
+ _cachedMeasureWidth = undefined;
7198
+ _defaultOptions = {
7199
+ content: [],
7200
+ wrapMode: "none",
7201
+ columnWidthMode: "content",
7202
+ cellPadding: 0,
7203
+ showBorders: true,
7204
+ border: true,
7205
+ outerBorder: true,
7206
+ selectable: true,
7207
+ selectionBg: undefined,
7208
+ selectionFg: undefined,
7209
+ borderStyle: "single",
7210
+ borderColor: "#FFFFFF",
7211
+ borderBackgroundColor: "transparent",
7212
+ backgroundColor: "transparent",
7213
+ fg: "#FFFFFF",
7214
+ bg: "transparent",
7215
+ attributes: 0
7216
+ };
7217
+ constructor(ctx, options = {}) {
7218
+ super(ctx, { ...options, buffered: true });
7219
+ this._content = options.content ?? this._defaultOptions.content;
7220
+ this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
7221
+ this._columnWidthMode = options.columnWidthMode ?? this._defaultOptions.columnWidthMode;
7222
+ this._cellPadding = this.resolveCellPadding(options.cellPadding);
7223
+ this._showBorders = options.showBorders ?? this._defaultOptions.showBorders;
7224
+ this._border = options.border ?? this._defaultOptions.border;
7225
+ this._hasExplicitOuterBorder = options.outerBorder !== undefined;
7226
+ this._outerBorder = options.outerBorder ?? this._border;
7227
+ this.selectable = options.selectable ?? this._defaultOptions.selectable;
7228
+ this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : undefined;
7229
+ this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : undefined;
7230
+ this._borderStyle = parseBorderStyle(options.borderStyle, this._defaultOptions.borderStyle);
7231
+ this._borderColor = parseColor(options.borderColor ?? this._defaultOptions.borderColor);
7232
+ this._borderBackgroundColor = parseColor(options.borderBackgroundColor ?? this._defaultOptions.borderBackgroundColor);
7233
+ this._backgroundColor = parseColor(options.backgroundColor ?? this._defaultOptions.backgroundColor);
7234
+ this._defaultFg = parseColor(options.fg ?? this._defaultOptions.fg);
7235
+ this._defaultBg = parseColor(options.bg ?? this._defaultOptions.bg);
7236
+ this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
7237
+ this.setupMeasureFunc();
7238
+ this.rebuildCells();
7239
+ }
7240
+ get content() {
7241
+ return this._content;
7242
+ }
7243
+ set content(value) {
7244
+ this._content = value ?? [];
7245
+ this.rebuildCells();
7246
+ }
7247
+ get wrapMode() {
7248
+ return this._wrapMode;
7249
+ }
7250
+ set wrapMode(value) {
7251
+ if (this._wrapMode === value)
7252
+ return;
7253
+ this._wrapMode = value;
7254
+ for (const row of this._cells) {
7255
+ for (const cell of row) {
7256
+ cell.textBufferView.setWrapMode(value);
7257
+ }
7258
+ }
7259
+ this.invalidateLayoutAndRaster();
7260
+ }
7261
+ get columnWidthMode() {
7262
+ return this._columnWidthMode;
7263
+ }
7264
+ set columnWidthMode(value) {
7265
+ if (this._columnWidthMode === value)
7266
+ return;
7267
+ this._columnWidthMode = value;
7268
+ this.invalidateLayoutAndRaster();
7269
+ }
7270
+ get cellPadding() {
7271
+ return this._cellPadding;
7272
+ }
7273
+ set cellPadding(value) {
7274
+ const next = this.resolveCellPadding(value);
7275
+ if (this._cellPadding === next)
7276
+ return;
7277
+ this._cellPadding = next;
7278
+ this.invalidateLayoutAndRaster();
7279
+ }
7280
+ get showBorders() {
7281
+ return this._showBorders;
7282
+ }
7283
+ set showBorders(value) {
7284
+ if (this._showBorders === value)
7285
+ return;
7286
+ this._showBorders = value;
7287
+ this.invalidateRasterOnly();
7288
+ }
7289
+ get outerBorder() {
7290
+ return this._outerBorder;
7291
+ }
7292
+ set outerBorder(value) {
7293
+ if (this._outerBorder === value)
7294
+ return;
7295
+ this._hasExplicitOuterBorder = true;
7296
+ this._outerBorder = value;
7297
+ this.invalidateLayoutAndRaster();
7298
+ }
7299
+ get border() {
7300
+ return this._border;
7301
+ }
7302
+ set border(value) {
7303
+ if (this._border === value)
7304
+ return;
7305
+ this._border = value;
7306
+ if (!this._hasExplicitOuterBorder) {
7307
+ this._outerBorder = value;
7308
+ }
7309
+ this.invalidateLayoutAndRaster();
7310
+ }
7311
+ get borderStyle() {
7312
+ return this._borderStyle;
7313
+ }
7314
+ set borderStyle(value) {
7315
+ const next = parseBorderStyle(value, this._defaultOptions.borderStyle);
7316
+ if (this._borderStyle === next)
7317
+ return;
7318
+ this._borderStyle = next;
7319
+ this.invalidateRasterOnly();
7320
+ }
7321
+ get borderColor() {
7322
+ return this._borderColor;
7323
+ }
7324
+ set borderColor(value) {
7325
+ const next = parseColor(value);
7326
+ if (this._borderColor === next)
7327
+ return;
7328
+ this._borderColor = next;
7329
+ this.invalidateRasterOnly();
7330
+ }
7331
+ shouldStartSelection(x, y) {
7332
+ if (!this.selectable)
7333
+ return false;
7334
+ this.ensureLayoutReady();
7335
+ const localX = x - this.x;
7336
+ const localY = y - this.y;
7337
+ return this.getCellAtLocalPosition(localX, localY) !== null;
7338
+ }
7339
+ onSelectionChanged(selection) {
7340
+ this.ensureLayoutReady();
7341
+ const previousLocalSelection = this._lastLocalSelection;
7342
+ const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
7343
+ this._lastLocalSelection = localSelection;
7344
+ const dirtyRows = this.getDirtySelectionRowRange(previousLocalSelection, localSelection);
7345
+ if (!localSelection?.isActive) {
7346
+ this.resetCellSelections();
7347
+ } else {
7348
+ this.applySelectionToCells(localSelection, selection?.isStart ?? false);
7349
+ }
7350
+ if (dirtyRows !== null) {
7351
+ this.redrawSelectionRows(dirtyRows.firstRow, dirtyRows.lastRow);
7352
+ }
7353
+ return this.hasSelection();
7354
+ }
7355
+ hasSelection() {
7356
+ for (const row of this._cells) {
7357
+ for (const cell of row) {
7358
+ if (cell.textBufferView.hasSelection()) {
7359
+ return true;
7360
+ }
7361
+ }
7362
+ }
7363
+ return false;
7364
+ }
7365
+ getSelection() {
7366
+ for (const row of this._cells) {
7367
+ for (const cell of row) {
7368
+ const selection = cell.textBufferView.getSelection();
7369
+ if (selection) {
7370
+ return selection;
7371
+ }
7372
+ }
7373
+ }
7374
+ return null;
7375
+ }
7376
+ getSelectedText() {
7377
+ const selectedRows = [];
7378
+ for (let rowIdx = 0;rowIdx < this._rowCount; rowIdx++) {
7379
+ const rowSelections = [];
7380
+ for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7381
+ const cell = this._cells[rowIdx]?.[colIdx];
7382
+ if (!cell || !cell.textBufferView.hasSelection())
7383
+ continue;
7384
+ const selectedText = cell.textBufferView.getSelectedText();
7385
+ if (selectedText.length > 0) {
7386
+ rowSelections.push(selectedText);
7387
+ }
7388
+ }
7389
+ if (rowSelections.length > 0) {
7390
+ selectedRows.push(rowSelections.join("\t"));
7391
+ }
7392
+ }
7393
+ return selectedRows.join(`
7394
+ `);
7395
+ }
7396
+ onResize(width, height) {
7397
+ this.invalidateLayoutAndRaster(false);
7398
+ super.onResize(width, height);
7399
+ }
7400
+ renderSelf(buffer) {
7401
+ if (!this.visible || this.isDestroyed)
7402
+ return;
7403
+ if (this._layoutDirty) {
7404
+ this.rebuildLayoutForCurrentWidth();
7405
+ }
7406
+ if (!this._rasterDirty)
7407
+ return;
7408
+ buffer.clear(this._backgroundColor);
7409
+ if (this._rowCount === 0 || this._columnCount === 0) {
7410
+ this._rasterDirty = false;
7411
+ return;
7412
+ }
7413
+ this.drawBorders(buffer);
7414
+ this.drawCells(buffer);
7415
+ this._rasterDirty = false;
7416
+ }
7417
+ destroySelf() {
7418
+ this.destroyCells();
7419
+ super.destroySelf();
7420
+ }
7421
+ setupMeasureFunc() {
7422
+ const measureFunc = (width, widthMode, height, heightMode) => {
7423
+ const hasWidthConstraint = widthMode !== MeasureMode.Undefined && Number.isFinite(width);
7424
+ const rawWidthConstraint = hasWidthConstraint ? Math.max(1, Math.floor(width)) : undefined;
7425
+ const widthConstraint = this.resolveLayoutWidthConstraint(rawWidthConstraint);
7426
+ const measuredLayout = this.computeLayout(widthConstraint);
7427
+ this._cachedMeasureLayout = measuredLayout;
7428
+ this._cachedMeasureWidth = widthConstraint;
7429
+ let measuredWidth = measuredLayout.tableWidth > 0 ? measuredLayout.tableWidth : 1;
7430
+ let measuredHeight = measuredLayout.tableHeight > 0 ? measuredLayout.tableHeight : 1;
7431
+ if (widthMode === MeasureMode.AtMost && rawWidthConstraint !== undefined && this._positionType !== "absolute") {
7432
+ measuredWidth = Math.min(rawWidthConstraint, measuredWidth);
7433
+ }
7434
+ if (heightMode === MeasureMode.AtMost && Number.isFinite(height) && this._positionType !== "absolute") {
7435
+ measuredHeight = Math.min(Math.max(1, Math.floor(height)), measuredHeight);
7436
+ }
7437
+ return {
7438
+ width: measuredWidth,
7439
+ height: measuredHeight
7440
+ };
7441
+ };
7442
+ this.yogaNode.setMeasureFunc(measureFunc);
7443
+ }
7444
+ rebuildCells() {
7445
+ const newRowCount = this._content.length;
7446
+ const newColumnCount = this._content.reduce((max, row) => Math.max(max, row.length), 0);
7447
+ if (this._cells.length === 0) {
7448
+ this._rowCount = newRowCount;
7449
+ this._columnCount = newColumnCount;
7450
+ this._cells = [];
7451
+ this._prevCellContent = [];
7452
+ for (let rowIdx = 0;rowIdx < newRowCount; rowIdx++) {
7453
+ const row = this._content[rowIdx] ?? [];
7454
+ const rowCells = [];
7455
+ const rowRefs = [];
7456
+ for (let colIdx = 0;colIdx < newColumnCount; colIdx++) {
7457
+ const cellContent = row[colIdx];
7458
+ rowCells.push(this.createCell(cellContent));
7459
+ rowRefs.push(cellContent);
7460
+ }
7461
+ this._cells.push(rowCells);
7462
+ this._prevCellContent.push(rowRefs);
7463
+ }
7464
+ this.invalidateLayoutAndRaster();
7465
+ return;
7466
+ }
7467
+ this.updateCellsDiff(newRowCount, newColumnCount);
7468
+ this.invalidateLayoutAndRaster();
7469
+ }
7470
+ updateCellsDiff(newRowCount, newColumnCount) {
7471
+ const oldRowCount = this._rowCount;
7472
+ const oldColumnCount = this._columnCount;
7473
+ const keepRows = Math.min(oldRowCount, newRowCount);
7474
+ const keepCols = Math.min(oldColumnCount, newColumnCount);
7475
+ for (let rowIdx = 0;rowIdx < keepRows; rowIdx++) {
7476
+ const newRow = this._content[rowIdx] ?? [];
7477
+ const cellRow = this._cells[rowIdx];
7478
+ const refRow = this._prevCellContent[rowIdx];
7479
+ for (let colIdx = 0;colIdx < keepCols; colIdx++) {
7480
+ const cellContent = newRow[colIdx];
7481
+ if (cellContent === refRow[colIdx])
7482
+ continue;
7483
+ const oldCell = cellRow[colIdx];
7484
+ oldCell.textBufferView.destroy();
7485
+ oldCell.textBuffer.destroy();
7486
+ oldCell.syntaxStyle.destroy();
7487
+ cellRow[colIdx] = this.createCell(cellContent);
7488
+ refRow[colIdx] = cellContent;
7489
+ }
7490
+ if (newColumnCount > oldColumnCount) {
7491
+ for (let colIdx = oldColumnCount;colIdx < newColumnCount; colIdx++) {
7492
+ const cellContent = newRow[colIdx];
7493
+ cellRow.push(this.createCell(cellContent));
7494
+ refRow.push(cellContent);
7495
+ }
7496
+ } else if (newColumnCount < oldColumnCount) {
7497
+ for (let colIdx = newColumnCount;colIdx < oldColumnCount; colIdx++) {
7498
+ const cell = cellRow[colIdx];
7499
+ cell.textBufferView.destroy();
7500
+ cell.textBuffer.destroy();
7501
+ cell.syntaxStyle.destroy();
7502
+ }
7503
+ cellRow.length = newColumnCount;
7504
+ refRow.length = newColumnCount;
7505
+ }
7506
+ }
7507
+ if (newRowCount > oldRowCount) {
7508
+ for (let rowIdx = oldRowCount;rowIdx < newRowCount; rowIdx++) {
7509
+ const newRow = this._content[rowIdx] ?? [];
7510
+ const rowCells = [];
7511
+ const rowRefs = [];
7512
+ for (let colIdx = 0;colIdx < newColumnCount; colIdx++) {
7513
+ const cellContent = newRow[colIdx];
7514
+ rowCells.push(this.createCell(cellContent));
7515
+ rowRefs.push(cellContent);
7516
+ }
7517
+ this._cells.push(rowCells);
7518
+ this._prevCellContent.push(rowRefs);
7519
+ }
7520
+ } else if (newRowCount < oldRowCount) {
7521
+ for (let rowIdx = newRowCount;rowIdx < oldRowCount; rowIdx++) {
7522
+ const row = this._cells[rowIdx];
7523
+ for (const cell of row) {
7524
+ cell.textBufferView.destroy();
7525
+ cell.textBuffer.destroy();
7526
+ cell.syntaxStyle.destroy();
7527
+ }
7528
+ }
7529
+ this._cells.length = newRowCount;
7530
+ this._prevCellContent.length = newRowCount;
7531
+ }
7532
+ this._rowCount = newRowCount;
7533
+ this._columnCount = newColumnCount;
7534
+ }
7535
+ createCell(content) {
7536
+ const styledText = this.toStyledText(content);
7537
+ const textBuffer = TextBuffer.create(this._ctx.widthMethod);
7538
+ const syntaxStyle = SyntaxStyle.create();
7539
+ textBuffer.setDefaultFg(this._defaultFg);
7540
+ textBuffer.setDefaultBg(this._defaultBg);
7541
+ textBuffer.setDefaultAttributes(this._defaultAttributes);
7542
+ textBuffer.setSyntaxStyle(syntaxStyle);
7543
+ textBuffer.setStyledText(styledText);
7544
+ const textBufferView = TextBufferView.create(textBuffer);
7545
+ textBufferView.setWrapMode(this._wrapMode);
7546
+ return { textBuffer, textBufferView, syntaxStyle };
7547
+ }
7548
+ toStyledText(content) {
7549
+ if (Array.isArray(content)) {
7550
+ return new StyledText(content);
7551
+ }
7552
+ if (content === null || content === undefined) {
7553
+ return stringToStyledText("");
7554
+ }
7555
+ return stringToStyledText(String(content));
7556
+ }
7557
+ destroyCells() {
7558
+ for (const row of this._cells) {
7559
+ for (const cell of row) {
7560
+ cell.textBufferView.destroy();
7561
+ cell.textBuffer.destroy();
7562
+ cell.syntaxStyle.destroy();
7563
+ }
7564
+ }
7565
+ this._cells = [];
7566
+ this._prevCellContent = [];
7567
+ this._rowCount = 0;
7568
+ this._columnCount = 0;
7569
+ this._layout = this.createEmptyLayout();
7570
+ }
7571
+ rebuildLayoutForCurrentWidth() {
7572
+ const maxTableWidth = this.resolveLayoutWidthConstraint(this.width);
7573
+ let layout;
7574
+ if (this._cachedMeasureLayout !== null && this._cachedMeasureWidth === maxTableWidth) {
7575
+ layout = this._cachedMeasureLayout;
7576
+ } else {
7577
+ layout = this.computeLayout(maxTableWidth);
7578
+ }
7579
+ this._cachedMeasureLayout = null;
7580
+ this._cachedMeasureWidth = undefined;
7581
+ this._layout = layout;
7582
+ this.applyLayoutToViews(layout);
7583
+ this._layoutDirty = false;
7584
+ if (this._lastLocalSelection?.isActive) {
7585
+ this.applySelectionToCells(this._lastLocalSelection, true);
7586
+ }
7587
+ }
7588
+ computeLayout(maxTableWidth) {
7589
+ if (this._rowCount === 0 || this._columnCount === 0) {
7590
+ return this.createEmptyLayout();
7591
+ }
7592
+ const borderLayout = this.resolveBorderLayout();
7593
+ const columnWidths = this.computeColumnWidths(maxTableWidth, borderLayout);
7594
+ const rowHeights = this.computeRowHeights(columnWidths);
7595
+ const columnOffsets = this.computeOffsets(columnWidths, borderLayout.left, borderLayout.right, borderLayout.innerVertical);
7596
+ const rowOffsets = this.computeOffsets(rowHeights, borderLayout.top, borderLayout.bottom, borderLayout.innerHorizontal);
7597
+ return {
7598
+ columnWidths,
7599
+ rowHeights,
7600
+ columnOffsets,
7601
+ rowOffsets,
7602
+ columnOffsetsI32: new Int32Array(columnOffsets),
7603
+ rowOffsetsI32: new Int32Array(rowOffsets),
7604
+ tableWidth: (columnOffsets[columnOffsets.length - 1] ?? 0) + 1,
7605
+ tableHeight: (rowOffsets[rowOffsets.length - 1] ?? 0) + 1
7606
+ };
7607
+ }
7608
+ computeColumnWidths(maxTableWidth, borderLayout) {
7609
+ const horizontalPadding = this.getHorizontalCellPadding();
7610
+ const intrinsicWidths = new Array(this._columnCount).fill(1 + horizontalPadding);
7611
+ for (let rowIdx = 0;rowIdx < this._rowCount; rowIdx++) {
7612
+ for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7613
+ const cell = this._cells[rowIdx]?.[colIdx];
7614
+ if (!cell)
7615
+ continue;
7616
+ const measure = cell.textBufferView.measureForDimensions(0, MEASURE_HEIGHT);
7617
+ const measuredWidth = Math.max(1, measure?.maxWidth ?? 0) + horizontalPadding;
7618
+ intrinsicWidths[colIdx] = Math.max(intrinsicWidths[colIdx], measuredWidth);
7619
+ }
7620
+ }
7621
+ if (maxTableWidth === undefined || !Number.isFinite(maxTableWidth) || maxTableWidth <= 0) {
7622
+ return intrinsicWidths;
7623
+ }
7624
+ const maxContentWidth = Math.max(1, Math.floor(maxTableWidth) - this.getVerticalBorderCount(borderLayout));
7625
+ const currentWidth = intrinsicWidths.reduce((sum, width) => sum + width, 0);
7626
+ if (currentWidth === maxContentWidth) {
7627
+ return intrinsicWidths;
7628
+ }
7629
+ if (currentWidth < maxContentWidth) {
7630
+ if (this._columnWidthMode === "fill") {
7631
+ return this.expandColumnWidths(intrinsicWidths, maxContentWidth);
7632
+ }
7633
+ return intrinsicWidths;
7634
+ }
7635
+ if (this._wrapMode === "none") {
7636
+ return intrinsicWidths;
7637
+ }
7638
+ return this.fitColumnWidths(intrinsicWidths, maxContentWidth);
7639
+ }
7640
+ expandColumnWidths(widths, targetContentWidth) {
7641
+ const baseWidths = widths.map((width) => Math.max(1, Math.floor(width)));
7642
+ const totalBaseWidth = baseWidths.reduce((sum, width) => sum + width, 0);
7643
+ if (totalBaseWidth >= targetContentWidth) {
7644
+ return baseWidths;
7645
+ }
7646
+ const expanded = [...baseWidths];
7647
+ const columns = expanded.length;
7648
+ const extraWidth = targetContentWidth - totalBaseWidth;
7649
+ const sharedWidth = Math.floor(extraWidth / columns);
7650
+ const remainder = extraWidth % columns;
7651
+ for (let idx = 0;idx < columns; idx++) {
7652
+ expanded[idx] += sharedWidth;
7653
+ if (idx < remainder) {
7654
+ expanded[idx] += 1;
7655
+ }
7656
+ }
7657
+ return expanded;
7658
+ }
7659
+ fitColumnWidths(widths, targetContentWidth) {
7660
+ const minWidth = 1 + this.getHorizontalCellPadding();
7661
+ const hardMinWidths = new Array(widths.length).fill(minWidth);
7662
+ const baseWidths = widths.map((width) => Math.max(1, Math.floor(width)));
7663
+ const preferredMinWidths = baseWidths.map((width) => Math.min(width, minWidth + 1));
7664
+ const preferredMinTotal = preferredMinWidths.reduce((sum, width) => sum + width, 0);
7665
+ const floorWidths = preferredMinTotal <= targetContentWidth ? preferredMinWidths : hardMinWidths;
7666
+ const floorTotal = floorWidths.reduce((sum, width) => sum + width, 0);
7667
+ const clampedTarget = Math.max(floorTotal, targetContentWidth);
7668
+ const totalBaseWidth = baseWidths.reduce((sum, width) => sum + width, 0);
7669
+ if (totalBaseWidth <= clampedTarget) {
7670
+ return baseWidths;
7671
+ }
7672
+ const shrinkable = baseWidths.map((width, idx) => width - floorWidths[idx]);
7673
+ const totalShrinkable = shrinkable.reduce((sum, value) => sum + value, 0);
7674
+ if (totalShrinkable <= 0) {
7675
+ return [...floorWidths];
7676
+ }
7677
+ const targetShrink = totalBaseWidth - clampedTarget;
7678
+ const integerShrink = new Array(baseWidths.length).fill(0);
7679
+ const fractions = new Array(baseWidths.length).fill(0);
7680
+ let usedShrink = 0;
7681
+ for (let idx = 0;idx < baseWidths.length; idx++) {
7682
+ if (shrinkable[idx] <= 0)
7683
+ continue;
7684
+ const exact = shrinkable[idx] / totalShrinkable * targetShrink;
7685
+ const whole = Math.min(shrinkable[idx], Math.floor(exact));
7686
+ integerShrink[idx] = whole;
7687
+ fractions[idx] = exact - whole;
7688
+ usedShrink += whole;
7689
+ }
7690
+ let remainingShrink = targetShrink - usedShrink;
7691
+ while (remainingShrink > 0) {
7692
+ let bestIdx = -1;
7693
+ let bestFraction = -1;
7694
+ for (let idx = 0;idx < baseWidths.length; idx++) {
7695
+ if (shrinkable[idx] - integerShrink[idx] <= 0)
7696
+ continue;
7697
+ if (fractions[idx] > bestFraction) {
7698
+ bestFraction = fractions[idx];
7699
+ bestIdx = idx;
7700
+ }
7701
+ }
7702
+ if (bestIdx === -1)
7703
+ break;
7704
+ integerShrink[bestIdx] += 1;
7705
+ fractions[bestIdx] = 0;
7706
+ remainingShrink -= 1;
7707
+ }
7708
+ return baseWidths.map((width, idx) => Math.max(floorWidths[idx], width - integerShrink[idx]));
7709
+ }
7710
+ computeRowHeights(columnWidths) {
7711
+ const horizontalPadding = this.getHorizontalCellPadding();
7712
+ const verticalPadding = this.getVerticalCellPadding();
7713
+ const rowHeights = new Array(this._rowCount).fill(1 + verticalPadding);
7714
+ for (let rowIdx = 0;rowIdx < this._rowCount; rowIdx++) {
7715
+ for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7716
+ const cell = this._cells[rowIdx]?.[colIdx];
7717
+ if (!cell)
7718
+ continue;
7719
+ const width = Math.max(1, (columnWidths[colIdx] ?? 1) - horizontalPadding);
7720
+ const measure = cell.textBufferView.measureForDimensions(width, MEASURE_HEIGHT);
7721
+ const lineCount = Math.max(1, measure?.lineCount ?? 1);
7722
+ rowHeights[rowIdx] = Math.max(rowHeights[rowIdx], lineCount + verticalPadding);
7723
+ }
7724
+ }
7725
+ return rowHeights;
7726
+ }
7727
+ computeOffsets(parts, startBoundary, endBoundary, includeInnerBoundaries) {
7728
+ const offsets = [startBoundary ? 0 : -1];
7729
+ let cursor = offsets[0] ?? 0;
7730
+ for (let idx = 0;idx < parts.length; idx++) {
7731
+ const size = parts[idx] ?? 1;
7732
+ const hasBoundaryAfter = idx < parts.length - 1 ? includeInnerBoundaries : endBoundary;
7733
+ cursor += size + (hasBoundaryAfter ? 1 : 0);
7734
+ offsets.push(cursor);
7735
+ }
7736
+ return offsets;
7737
+ }
7738
+ applyLayoutToViews(layout) {
7739
+ const horizontalPadding = this.getHorizontalCellPadding();
7740
+ const verticalPadding = this.getVerticalCellPadding();
7741
+ for (let rowIdx = 0;rowIdx < this._rowCount; rowIdx++) {
7742
+ for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7743
+ const cell = this._cells[rowIdx]?.[colIdx];
7744
+ if (!cell)
7745
+ continue;
7746
+ const colWidth = layout.columnWidths[colIdx] ?? 1;
7747
+ const rowHeight = layout.rowHeights[rowIdx] ?? 1;
7748
+ const contentWidth = Math.max(1, colWidth - horizontalPadding);
7749
+ const contentHeight = Math.max(1, rowHeight - verticalPadding);
7750
+ if (this._wrapMode === "none") {
7751
+ cell.textBufferView.setWrapWidth(null);
7752
+ } else {
7753
+ cell.textBufferView.setWrapWidth(contentWidth);
7754
+ }
7755
+ cell.textBufferView.setViewport(0, 0, contentWidth, contentHeight);
7756
+ }
7757
+ }
7758
+ }
7759
+ resolveBorderLayout() {
7760
+ return {
7761
+ left: this._outerBorder,
7762
+ right: this._outerBorder,
7763
+ top: this._outerBorder,
7764
+ bottom: this._outerBorder,
7765
+ innerVertical: this._border && this._columnCount > 1,
7766
+ innerHorizontal: this._border && this._rowCount > 1
7767
+ };
7768
+ }
7769
+ getVerticalBorderCount(borderLayout) {
7770
+ return (borderLayout.left ? 1 : 0) + (borderLayout.right ? 1 : 0) + (borderLayout.innerVertical ? Math.max(0, this._columnCount - 1) : 0);
7771
+ }
7772
+ getHorizontalBorderCount(borderLayout) {
7773
+ return (borderLayout.top ? 1 : 0) + (borderLayout.bottom ? 1 : 0) + (borderLayout.innerHorizontal ? Math.max(0, this._rowCount - 1) : 0);
7774
+ }
7775
+ drawBorders(buffer) {
7776
+ if (!this._showBorders) {
7777
+ return;
7778
+ }
7779
+ const borderLayout = this.resolveBorderLayout();
7780
+ if (this.getVerticalBorderCount(borderLayout) === 0 && this.getHorizontalBorderCount(borderLayout) === 0) {
7781
+ return;
7782
+ }
7783
+ buffer.drawGrid({
7784
+ borderChars: BorderCharArrays[this._borderStyle],
7785
+ borderFg: this._borderColor,
7786
+ borderBg: this._borderBackgroundColor,
7787
+ columnOffsets: this._layout.columnOffsetsI32,
7788
+ rowOffsets: this._layout.rowOffsetsI32,
7789
+ drawInner: this._border,
7790
+ drawOuter: this._outerBorder
7791
+ });
7792
+ }
7793
+ drawCells(buffer) {
7794
+ this.drawCellRange(buffer, 0, this._rowCount - 1);
7795
+ }
7796
+ drawCellRange(buffer, firstRow, lastRow) {
7797
+ const colOffsets = this._layout.columnOffsets;
7798
+ const rowOffsets = this._layout.rowOffsets;
7799
+ const cellPadding = this._cellPadding;
7800
+ for (let rowIdx = firstRow;rowIdx <= lastRow; rowIdx++) {
7801
+ const cellY = (rowOffsets[rowIdx] ?? 0) + 1 + cellPadding;
7802
+ for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7803
+ const cell = this._cells[rowIdx]?.[colIdx];
7804
+ if (!cell)
7805
+ continue;
7806
+ buffer.drawTextBuffer(cell.textBufferView, (colOffsets[colIdx] ?? 0) + 1 + cellPadding, cellY);
7807
+ }
7808
+ }
7809
+ }
7810
+ redrawSelectionRows(firstRow, lastRow) {
7811
+ if (firstRow > lastRow)
7812
+ return;
7813
+ if (this._backgroundColor.a < 1) {
7814
+ this.invalidateRasterOnly();
7815
+ return;
7816
+ }
7817
+ const buffer = this.frameBuffer;
7818
+ if (!buffer)
7819
+ return;
7820
+ this.clearCellRange(buffer, firstRow, lastRow);
7821
+ this.drawCellRange(buffer, firstRow, lastRow);
7822
+ this.requestRender();
7823
+ }
7824
+ clearCellRange(buffer, firstRow, lastRow) {
7825
+ const colWidths = this._layout.columnWidths;
7826
+ const rowHeights = this._layout.rowHeights;
7827
+ const colOffsets = this._layout.columnOffsets;
7828
+ const rowOffsets = this._layout.rowOffsets;
7829
+ for (let rowIdx = firstRow;rowIdx <= lastRow; rowIdx++) {
7830
+ const cellY = (rowOffsets[rowIdx] ?? 0) + 1;
7831
+ const rowHeight = rowHeights[rowIdx] ?? 1;
7832
+ for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7833
+ const cellX = (colOffsets[colIdx] ?? 0) + 1;
7834
+ const colWidth = colWidths[colIdx] ?? 1;
7835
+ buffer.fillRect(cellX, cellY, colWidth, rowHeight, this._backgroundColor);
7836
+ }
7837
+ }
7838
+ }
7839
+ ensureLayoutReady() {
7840
+ if (!this._layoutDirty)
7841
+ return;
7842
+ this.rebuildLayoutForCurrentWidth();
7843
+ }
7844
+ getCellAtLocalPosition(localX, localY) {
7845
+ if (this._rowCount === 0 || this._columnCount === 0)
7846
+ return null;
7847
+ if (localX < 0 || localY < 0 || localX >= this._layout.tableWidth || localY >= this._layout.tableHeight) {
7848
+ return null;
7849
+ }
7850
+ let rowIdx = -1;
7851
+ for (let idx = 0;idx < this._rowCount; idx++) {
7852
+ const top = (this._layout.rowOffsets[idx] ?? 0) + 1;
7853
+ const bottom = top + (this._layout.rowHeights[idx] ?? 1) - 1;
7854
+ if (localY >= top && localY <= bottom) {
7855
+ rowIdx = idx;
7856
+ break;
7857
+ }
7858
+ }
7859
+ if (rowIdx < 0)
7860
+ return null;
7861
+ let colIdx = -1;
7862
+ for (let idx = 0;idx < this._columnCount; idx++) {
7863
+ const left = (this._layout.columnOffsets[idx] ?? 0) + 1;
7864
+ const right = left + (this._layout.columnWidths[idx] ?? 1) - 1;
7865
+ if (localX >= left && localX <= right) {
7866
+ colIdx = idx;
7867
+ break;
7868
+ }
7869
+ }
7870
+ if (colIdx < 0)
7871
+ return null;
7872
+ return { rowIdx, colIdx };
7873
+ }
7874
+ applySelectionToCells(localSelection, isStart) {
7875
+ const minSelY = Math.min(localSelection.anchorY, localSelection.focusY);
7876
+ const maxSelY = Math.max(localSelection.anchorY, localSelection.focusY);
7877
+ const firstRow = this.findRowForLocalY(minSelY);
7878
+ const lastRow = this.findRowForLocalY(maxSelY);
7879
+ for (let rowIdx = 0;rowIdx < this._rowCount; rowIdx++) {
7880
+ if (rowIdx < firstRow || rowIdx > lastRow) {
7881
+ this.resetRowSelection(rowIdx);
7882
+ continue;
7883
+ }
7884
+ const cellTop = (this._layout.rowOffsets[rowIdx] ?? 0) + 1 + this._cellPadding;
7885
+ for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7886
+ const cell = this._cells[rowIdx]?.[colIdx];
7887
+ if (!cell)
7888
+ continue;
7889
+ const cellLeft = (this._layout.columnOffsets[colIdx] ?? 0) + 1 + this._cellPadding;
7890
+ const anchorX = localSelection.anchorX - cellLeft;
7891
+ const anchorY = localSelection.anchorY - cellTop;
7892
+ const focusX = localSelection.focusX - cellLeft;
7893
+ const focusY = localSelection.focusY - cellTop;
7894
+ if (isStart) {
7895
+ cell.textBufferView.setLocalSelection(anchorX, anchorY, focusX, focusY, this._selectionBg, this._selectionFg);
7896
+ } else {
7897
+ cell.textBufferView.updateLocalSelection(anchorX, anchorY, focusX, focusY, this._selectionBg, this._selectionFg);
7898
+ }
7899
+ }
7900
+ }
7901
+ }
7902
+ findRowForLocalY(localY) {
7903
+ if (this._rowCount === 0)
7904
+ return 0;
7905
+ if (localY < 0)
7906
+ return 0;
7907
+ for (let rowIdx = 0;rowIdx < this._rowCount; rowIdx++) {
7908
+ const rowStart = (this._layout.rowOffsets[rowIdx] ?? 0) + 1;
7909
+ const rowEnd = rowStart + (this._layout.rowHeights[rowIdx] ?? 1) - 1;
7910
+ if (localY <= rowEnd)
7911
+ return rowIdx;
7912
+ }
7913
+ return this._rowCount - 1;
7914
+ }
7915
+ getSelectionRowRange(selection) {
7916
+ if (!selection?.isActive || this._rowCount === 0)
7917
+ return null;
7918
+ const minSelY = Math.min(selection.anchorY, selection.focusY);
7919
+ const maxSelY = Math.max(selection.anchorY, selection.focusY);
7920
+ return {
7921
+ firstRow: this.findRowForLocalY(minSelY),
7922
+ lastRow: this.findRowForLocalY(maxSelY)
7923
+ };
7924
+ }
7925
+ getDirtySelectionRowRange(previousSelection, currentSelection) {
7926
+ const previousRange = this.getSelectionRowRange(previousSelection);
7927
+ const currentRange = this.getSelectionRowRange(currentSelection);
7928
+ if (previousRange === null)
7929
+ return currentRange;
7930
+ if (currentRange === null)
7931
+ return previousRange;
7932
+ return {
7933
+ firstRow: Math.min(previousRange.firstRow, currentRange.firstRow),
7934
+ lastRow: Math.max(previousRange.lastRow, currentRange.lastRow)
7935
+ };
7936
+ }
7937
+ resetRowSelection(rowIdx) {
7938
+ const row = this._cells[rowIdx];
7939
+ if (!row)
7940
+ return;
7941
+ for (const cell of row) {
7942
+ if (!cell.textBufferView.hasSelection())
7943
+ continue;
7944
+ cell.textBufferView.resetLocalSelection();
7945
+ }
7946
+ }
7947
+ resetCellSelections() {
7948
+ for (let rowIdx = 0;rowIdx < this._rowCount; rowIdx++) {
7949
+ this.resetRowSelection(rowIdx);
7950
+ }
7951
+ }
7952
+ createEmptyLayout() {
7953
+ return {
7954
+ columnWidths: [],
7955
+ rowHeights: [],
7956
+ columnOffsets: [0],
7957
+ rowOffsets: [0],
7958
+ columnOffsetsI32: new Int32Array([0]),
7959
+ rowOffsetsI32: new Int32Array([0]),
7960
+ tableWidth: 0,
7961
+ tableHeight: 0
7962
+ };
7963
+ }
7964
+ resolveLayoutWidthConstraint(width) {
7965
+ if (width === undefined || !Number.isFinite(width) || width <= 0) {
7966
+ return;
7967
+ }
7968
+ if (this._wrapMode !== "none" || this._columnWidthMode === "fill") {
7969
+ return Math.max(1, Math.floor(width));
7970
+ }
7971
+ return;
7972
+ }
7973
+ getHorizontalCellPadding() {
7974
+ return this._cellPadding * 2;
7975
+ }
7976
+ getVerticalCellPadding() {
7977
+ return this._cellPadding * 2;
7978
+ }
7979
+ resolveCellPadding(value) {
7980
+ if (value === undefined || !Number.isFinite(value)) {
7981
+ return this._defaultOptions.cellPadding;
7982
+ }
7983
+ return Math.max(0, Math.floor(value));
7984
+ }
7985
+ invalidateLayoutAndRaster(markYogaDirty = true) {
7986
+ this._layoutDirty = true;
7987
+ this._rasterDirty = true;
7988
+ this._cachedMeasureLayout = null;
7989
+ this._cachedMeasureWidth = undefined;
7990
+ if (markYogaDirty) {
7991
+ this.yogaNode.markDirty();
7992
+ }
7993
+ this.requestRender();
7994
+ }
7995
+ invalidateRasterOnly() {
7996
+ this._rasterDirty = true;
7997
+ this.requestRender();
7998
+ }
7999
+ }
8000
+
7162
8001
  // ../../node_modules/.bun/marked@17.0.1/node_modules/marked/lib/marked.esm.js
7163
8002
  function L() {
7164
8003
  return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
@@ -8437,10 +9276,10 @@ function parseMarkdownIncremental(newContent, prevState, trailingUnstable = 2) {
8437
9276
  let offset = 0;
8438
9277
  let reuseCount = 0;
8439
9278
  for (const token of prevState.tokens) {
8440
- const tokenEnd = offset + token.raw.length;
8441
- if (tokenEnd <= newContent.length && newContent.slice(offset, tokenEnd) === token.raw) {
9279
+ const tokenLength = token.raw.length;
9280
+ if (offset + tokenLength <= newContent.length && newContent.startsWith(token.raw, offset)) {
8442
9281
  reuseCount++;
8443
- offset = tokenEnd;
9282
+ offset += tokenLength;
8444
9283
  } else {
8445
9284
  break;
8446
9285
  }
@@ -8784,159 +9623,152 @@ class MarkdownRenderable extends Renderable {
8784
9623
  marginBottom
8785
9624
  });
8786
9625
  }
8787
- updateTableRenderable(tableBox, table, marginBottom) {
8788
- tableBox.marginBottom = marginBottom;
8789
- const borderColor = this.getStyle("conceal")?.fg ?? "#888888";
9626
+ getTableRowsToRender(table) {
9627
+ return this._streaming && table.rows.length > 0 ? table.rows.slice(0, -1) : table.rows;
9628
+ }
9629
+ hashString(value, seed) {
9630
+ let hash = seed >>> 0;
9631
+ for (let i = 0;i < value.length; i += 1) {
9632
+ hash ^= value.charCodeAt(i);
9633
+ hash = Math.imul(hash, 16777619);
9634
+ }
9635
+ return hash >>> 0;
9636
+ }
9637
+ hashTableToken(token, seed, depth = 0) {
9638
+ let hash = this.hashString(token.type, seed);
9639
+ if ("raw" in token && typeof token.raw === "string") {
9640
+ return this.hashString(token.raw, hash);
9641
+ }
9642
+ if ("text" in token && typeof token.text === "string") {
9643
+ hash = this.hashString(token.text, hash);
9644
+ }
9645
+ if (depth < 2 && "tokens" in token && Array.isArray(token.tokens)) {
9646
+ for (const child of token.tokens) {
9647
+ hash = this.hashTableToken(child, hash, depth + 1);
9648
+ }
9649
+ }
9650
+ return hash >>> 0;
9651
+ }
9652
+ getTableCellKey(cell, isHeader) {
9653
+ const seed = isHeader ? 2902232141 : 1371922141;
9654
+ if (!cell) {
9655
+ return seed;
9656
+ }
9657
+ if (typeof cell.text === "string") {
9658
+ return this.hashString(cell.text, seed);
9659
+ }
9660
+ if (Array.isArray(cell.tokens) && cell.tokens.length > 0) {
9661
+ let hash = seed ^ cell.tokens.length;
9662
+ for (const token of cell.tokens) {
9663
+ hash = this.hashTableToken(token, hash);
9664
+ }
9665
+ return hash >>> 0;
9666
+ }
9667
+ return (seed ^ 2654435769) >>> 0;
9668
+ }
9669
+ createTableDataCellChunks(cell) {
9670
+ const chunks = [];
9671
+ if (cell) {
9672
+ this.renderInlineContent(cell.tokens, chunks);
9673
+ }
9674
+ return chunks.length > 0 ? chunks : [this.createDefaultChunk(" ")];
9675
+ }
9676
+ createTableHeaderCellChunks(cell) {
9677
+ const chunks = [];
9678
+ this.renderInlineContent(cell.tokens, chunks);
9679
+ const baseChunks = chunks.length > 0 ? chunks : [this.createDefaultChunk(" ")];
8790
9680
  const headingStyle = this.getStyle("markup.heading") || this.getStyle("default");
8791
- const rowsToRender = this._streaming && table.rows.length > 0 ? table.rows.slice(0, -1) : table.rows;
9681
+ if (!headingStyle) {
9682
+ return baseChunks;
9683
+ }
9684
+ const headingAttributes = createTextAttributes({
9685
+ bold: headingStyle.bold,
9686
+ italic: headingStyle.italic,
9687
+ underline: headingStyle.underline,
9688
+ dim: headingStyle.dim
9689
+ });
9690
+ return baseChunks.map((chunk) => ({
9691
+ ...chunk,
9692
+ fg: headingStyle.fg ?? chunk.fg,
9693
+ bg: headingStyle.bg ?? chunk.bg,
9694
+ attributes: headingAttributes
9695
+ }));
9696
+ }
9697
+ buildTableContentCache(table, previous, forceRegenerate = false) {
8792
9698
  const colCount = table.header.length;
8793
- const columns = tableBox._childrenInLayoutOrder;
8794
- for (let col = 0;col < colCount; col++) {
8795
- const columnBox = columns[col];
8796
- if (!columnBox)
8797
- continue;
8798
- if (columnBox instanceof BoxRenderable) {
8799
- columnBox.borderColor = borderColor;
8800
- }
8801
- const columnChildren = columnBox._childrenInLayoutOrder;
8802
- const headerBox = columnChildren[0];
8803
- if (headerBox instanceof BoxRenderable) {
8804
- headerBox.borderColor = borderColor;
8805
- const headerChildren = headerBox._childrenInLayoutOrder;
8806
- const headerText = headerChildren[0];
8807
- if (headerText instanceof TextRenderable) {
8808
- const headerCell = table.header[col];
8809
- const headerChunks = [];
8810
- this.renderInlineContent(headerCell.tokens, headerChunks);
8811
- const styledHeaderChunks = headerChunks.map((chunk) => ({
8812
- ...chunk,
8813
- fg: headingStyle?.fg ?? chunk.fg,
8814
- bg: headingStyle?.bg ?? chunk.bg,
8815
- attributes: headingStyle ? createTextAttributes({
8816
- bold: headingStyle.bold,
8817
- italic: headingStyle.italic,
8818
- underline: headingStyle.underline,
8819
- dim: headingStyle.dim
8820
- }) : chunk.attributes
8821
- }));
8822
- headerText.content = new StyledText(styledHeaderChunks);
8823
- }
8824
- }
8825
- for (let row = 0;row < rowsToRender.length; row++) {
8826
- const childIndex = row + 1;
8827
- const cellContainer = columnChildren[childIndex];
8828
- let cellText;
8829
- if (cellContainer instanceof BoxRenderable) {
8830
- cellContainer.borderColor = borderColor;
8831
- const cellChildren = cellContainer._childrenInLayoutOrder;
8832
- cellText = cellChildren[0];
8833
- } else if (cellContainer instanceof TextRenderable) {
8834
- cellText = cellContainer;
8835
- }
8836
- if (cellText) {
8837
- const cell = rowsToRender[row][col];
8838
- const cellChunks = [];
8839
- if (cell) {
8840
- this.renderInlineContent(cell.tokens, cellChunks);
9699
+ const rowsToRender = this.getTableRowsToRender(table);
9700
+ if (colCount === 0 || rowsToRender.length === 0) {
9701
+ return { cache: null, changed: previous !== undefined };
9702
+ }
9703
+ const content = [];
9704
+ const cellKeys = [];
9705
+ const totalRows = rowsToRender.length + 1;
9706
+ let changed = forceRegenerate || !previous;
9707
+ for (let rowIndex = 0;rowIndex < totalRows; rowIndex += 1) {
9708
+ const rowContent = [];
9709
+ const rowKeys = new Uint32Array(colCount);
9710
+ for (let colIndex = 0;colIndex < colCount; colIndex += 1) {
9711
+ const isHeader = rowIndex === 0;
9712
+ const cell = isHeader ? table.header[colIndex] : rowsToRender[rowIndex - 1]?.[colIndex];
9713
+ const cellKey = this.getTableCellKey(cell, isHeader);
9714
+ rowKeys[colIndex] = cellKey;
9715
+ const previousCellKey = previous?.cellKeys[rowIndex]?.[colIndex];
9716
+ const previousCellContent = previous?.content[rowIndex]?.[colIndex];
9717
+ if (!forceRegenerate && previousCellKey === cellKey && Array.isArray(previousCellContent)) {
9718
+ rowContent.push(previousCellContent);
9719
+ continue;
9720
+ }
9721
+ changed = true;
9722
+ rowContent.push(isHeader ? this.createTableHeaderCellChunks(table.header[colIndex]) : this.createTableDataCellChunks(cell));
9723
+ }
9724
+ content.push(rowContent);
9725
+ cellKeys.push(rowKeys);
9726
+ }
9727
+ if (previous && !changed) {
9728
+ if (previous.content.length !== content.length) {
9729
+ changed = true;
9730
+ } else {
9731
+ for (let rowIndex = 0;rowIndex < content.length; rowIndex += 1) {
9732
+ if ((previous.content[rowIndex]?.length ?? 0) !== content[rowIndex].length) {
9733
+ changed = true;
9734
+ break;
8841
9735
  }
8842
- cellText.content = new StyledText(cellChunks.length > 0 ? cellChunks : [this.createDefaultChunk(" ")]);
8843
9736
  }
8844
9737
  }
8845
9738
  }
9739
+ return {
9740
+ cache: {
9741
+ content,
9742
+ cellKeys
9743
+ },
9744
+ changed
9745
+ };
8846
9746
  }
8847
- createTableRenderable(table, id, marginBottom = 0) {
8848
- const colCount = table.header.length;
8849
- const rowsToRender = this._streaming && table.rows.length > 0 ? table.rows.slice(0, -1) : table.rows;
8850
- if (colCount === 0 || rowsToRender.length === 0) {
8851
- return this.createTextRenderable([this.createDefaultChunk(table.raw)], id, marginBottom);
8852
- }
8853
- const tableBox = new BoxRenderable(this.ctx, {
9747
+ createTextTableRenderable(content, id, marginBottom = 0) {
9748
+ return new TextTableRenderable(this.ctx, {
8854
9749
  id,
8855
- flexDirection: "row",
8856
- marginBottom
9750
+ content,
9751
+ width: "100%",
9752
+ marginBottom,
9753
+ border: true,
9754
+ outerBorder: true,
9755
+ showBorders: true,
9756
+ borderStyle: "single",
9757
+ borderColor: this.getStyle("conceal")?.fg ?? "#888888",
9758
+ selectable: false
8857
9759
  });
8858
- const borderColor = this.getStyle("conceal")?.fg ?? "#888888";
8859
- for (let col = 0;col < colCount; col++) {
8860
- const isFirstCol = col === 0;
8861
- const isLastCol = col === colCount - 1;
8862
- const columnBox = new BoxRenderable(this.ctx, {
8863
- id: `${id}-col-${col}`,
8864
- flexDirection: "column",
8865
- border: isLastCol ? true : ["top", "bottom", "left"],
8866
- borderColor,
8867
- customBorderChars: isFirstCol ? undefined : {
8868
- topLeft: "\u252C",
8869
- topRight: "\u2510",
8870
- bottomLeft: "\u2534",
8871
- bottomRight: "\u2518",
8872
- horizontal: "\u2500",
8873
- vertical: "\u2502",
8874
- topT: "\u252C",
8875
- bottomT: "\u2534",
8876
- leftT: "\u251C",
8877
- rightT: "\u2524",
8878
- cross: "\u253C"
8879
- }
8880
- });
8881
- const headerCell = table.header[col];
8882
- const headerChunks = [];
8883
- this.renderInlineContent(headerCell.tokens, headerChunks);
8884
- const headingStyle = this.getStyle("markup.heading") || this.getStyle("default");
8885
- const styledHeaderChunks = headerChunks.map((chunk) => ({
8886
- ...chunk,
8887
- fg: headingStyle?.fg ?? chunk.fg,
8888
- bg: headingStyle?.bg ?? chunk.bg,
8889
- attributes: headingStyle ? createTextAttributes({
8890
- bold: headingStyle.bold,
8891
- italic: headingStyle.italic,
8892
- underline: headingStyle.underline,
8893
- dim: headingStyle.dim
8894
- }) : chunk.attributes
8895
- }));
8896
- const headerBox = new BoxRenderable(this.ctx, {
8897
- id: `${id}-col-${col}-header-box`,
8898
- border: ["bottom"],
8899
- borderColor
8900
- });
8901
- headerBox.add(new TextRenderable(this.ctx, {
8902
- id: `${id}-col-${col}-header`,
8903
- content: new StyledText(styledHeaderChunks),
8904
- height: 1,
8905
- overflow: "hidden",
8906
- paddingLeft: 1,
8907
- paddingRight: 1
8908
- }));
8909
- columnBox.add(headerBox);
8910
- for (let row = 0;row < rowsToRender.length; row++) {
8911
- const cell = rowsToRender[row][col];
8912
- const cellChunks = [];
8913
- if (cell) {
8914
- this.renderInlineContent(cell.tokens, cellChunks);
8915
- }
8916
- const isLastRow = row === rowsToRender.length - 1;
8917
- const cellText = new TextRenderable(this.ctx, {
8918
- id: `${id}-col-${col}-row-${row}`,
8919
- content: new StyledText(cellChunks.length > 0 ? cellChunks : [this.createDefaultChunk(" ")]),
8920
- height: 1,
8921
- overflow: "hidden",
8922
- paddingLeft: 1,
8923
- paddingRight: 1
8924
- });
8925
- if (isLastRow) {
8926
- columnBox.add(cellText);
8927
- } else {
8928
- const cellBox = new BoxRenderable(this.ctx, {
8929
- id: `${id}-col-${col}-row-${row}-box`,
8930
- border: ["bottom"],
8931
- borderColor
8932
- });
8933
- cellBox.add(cellText);
8934
- columnBox.add(cellBox);
8935
- }
8936
- }
8937
- tableBox.add(columnBox);
9760
+ }
9761
+ createTableBlock(table, id, marginBottom = 0, previousCache, forceRegenerate = false) {
9762
+ const { cache } = this.buildTableContentCache(table, previousCache, forceRegenerate);
9763
+ if (!cache) {
9764
+ return {
9765
+ renderable: this.createTextRenderable([this.createDefaultChunk(table.raw)], id, marginBottom)
9766
+ };
8938
9767
  }
8939
- return tableBox;
9768
+ return {
9769
+ renderable: this.createTextTableRenderable(cache.content, id, marginBottom),
9770
+ tableContentCache: cache
9771
+ };
8940
9772
  }
8941
9773
  createDefaultRenderable(token, index, hasNextToken = false) {
8942
9774
  const id = `${this.id}-block-${index}`;
@@ -8945,7 +9777,7 @@ class MarkdownRenderable extends Renderable {
8945
9777
  return this.createCodeRenderable(token, id, marginBottom);
8946
9778
  }
8947
9779
  if (token.type === "table") {
8948
- return this.createTableRenderable(token, id, marginBottom);
9780
+ return this.createTableBlock(token, id, marginBottom).renderable;
8949
9781
  }
8950
9782
  if (token.type === "space") {
8951
9783
  return null;
@@ -8969,26 +9801,39 @@ class MarkdownRenderable extends Renderable {
8969
9801
  return;
8970
9802
  }
8971
9803
  if (token.type === "table") {
8972
- const prevTable = state.token;
8973
- const newTable = token;
8974
- if (this._streaming) {
8975
- const prevCompleteRows = Math.max(0, prevTable.rows.length - 1);
8976
- const newCompleteRows = Math.max(0, newTable.rows.length - 1);
8977
- const prevIsRawFallback = prevTable.header.length === 0 || prevCompleteRows === 0;
8978
- const newIsRawFallback = newTable.header.length === 0 || newCompleteRows === 0;
8979
- if (prevCompleteRows === newCompleteRows && prevTable.header.length === newTable.header.length) {
8980
- if (prevIsRawFallback && newIsRawFallback && prevTable.raw !== newTable.raw) {
8981
- const textRenderable2 = state.renderable;
8982
- textRenderable2.content = new StyledText([this.createDefaultChunk(newTable.raw)]);
8983
- textRenderable2.marginBottom = marginBottom;
9804
+ const tableToken = token;
9805
+ const { cache, changed } = this.buildTableContentCache(tableToken, state.tableContentCache);
9806
+ if (!cache) {
9807
+ const fallbackChunks = [this.createDefaultChunk(tableToken.raw)];
9808
+ if (state.renderable instanceof TextRenderable) {
9809
+ if (state.tokenRaw !== tableToken.raw) {
9810
+ state.renderable.content = new StyledText(fallbackChunks);
8984
9811
  }
9812
+ state.renderable.marginBottom = marginBottom;
9813
+ state.tableContentCache = undefined;
8985
9814
  return;
8986
9815
  }
9816
+ state.renderable.destroyRecursively();
9817
+ const fallbackRenderable = this.createTextRenderable(fallbackChunks, `${this.id}-block-${index}`, marginBottom);
9818
+ this.add(fallbackRenderable);
9819
+ state.renderable = fallbackRenderable;
9820
+ state.tableContentCache = undefined;
9821
+ return;
8987
9822
  }
8988
- this.remove(state.renderable.id);
8989
- const newRenderable = this.createTableRenderable(newTable, `${this.id}-block-${index}`, marginBottom);
8990
- this.add(newRenderable);
8991
- state.renderable = newRenderable;
9823
+ if (state.renderable instanceof TextTableRenderable) {
9824
+ if (changed) {
9825
+ state.renderable.content = cache.content;
9826
+ }
9827
+ state.renderable.borderColor = this.getStyle("conceal")?.fg ?? "#888888";
9828
+ state.renderable.marginBottom = marginBottom;
9829
+ state.tableContentCache = cache;
9830
+ return;
9831
+ }
9832
+ state.renderable.destroyRecursively();
9833
+ const tableRenderable = this.createTextTableRenderable(cache.content, `${this.id}-block-${index}`, marginBottom);
9834
+ this.add(tableRenderable);
9835
+ state.renderable = tableRenderable;
9836
+ state.tableContentCache = cache;
8992
9837
  return;
8993
9838
  }
8994
9839
  const textRenderable = state.renderable;
@@ -8998,10 +9843,7 @@ class MarkdownRenderable extends Renderable {
8998
9843
  }
8999
9844
  updateBlocks() {
9000
9845
  if (!this._content) {
9001
- for (const state of this._blockStates) {
9002
- this.remove(state.renderable.id);
9003
- }
9004
- this._blockStates = [];
9846
+ this.clearBlockStates();
9005
9847
  this._parseState = null;
9006
9848
  return;
9007
9849
  }
@@ -9009,9 +9851,7 @@ class MarkdownRenderable extends Renderable {
9009
9851
  this._parseState = parseMarkdownIncremental(this._content, this._parseState, trailingUnstable);
9010
9852
  const tokens = this._parseState.tokens;
9011
9853
  if (tokens.length === 0 && this._content.length > 0) {
9012
- for (const state of this._blockStates) {
9013
- this.remove(state.renderable.id);
9014
- }
9854
+ this.clearBlockStates();
9015
9855
  const text = this.createTextRenderable([this.createDefaultChunk(this._content)], `${this.id}-fallback`);
9016
9856
  this.add(text);
9017
9857
  this._blockStates = [
@@ -9052,9 +9892,10 @@ class MarkdownRenderable extends Renderable {
9052
9892
  continue;
9053
9893
  }
9054
9894
  if (existing) {
9055
- this.remove(existing.renderable.id);
9895
+ existing.renderable.destroyRecursively();
9056
9896
  }
9057
9897
  let renderable;
9898
+ let tableContentCache;
9058
9899
  if (this._renderNode) {
9059
9900
  const context = {
9060
9901
  syntaxStyle: this._syntaxStyle,
@@ -9068,26 +9909,37 @@ class MarkdownRenderable extends Renderable {
9068
9909
  }
9069
9910
  }
9070
9911
  if (!renderable) {
9071
- renderable = this.createDefaultRenderable(token, blockIndex, hasNextToken) ?? undefined;
9912
+ if (token.type === "table") {
9913
+ const tableBlock = this.createTableBlock(token, `${this.id}-block-${blockIndex}`, hasNextToken ? 1 : 0);
9914
+ renderable = tableBlock.renderable;
9915
+ tableContentCache = tableBlock.tableContentCache;
9916
+ } else {
9917
+ renderable = this.createDefaultRenderable(token, blockIndex, hasNextToken) ?? undefined;
9918
+ }
9919
+ }
9920
+ if (token.type === "table" && !tableContentCache && renderable instanceof TextTableRenderable) {
9921
+ const { cache } = this.buildTableContentCache(token);
9922
+ tableContentCache = cache ?? undefined;
9072
9923
  }
9073
9924
  if (renderable) {
9074
9925
  this.add(renderable);
9075
9926
  this._blockStates[blockIndex] = {
9076
9927
  token,
9077
9928
  tokenRaw: token.raw,
9078
- renderable
9929
+ renderable,
9930
+ tableContentCache
9079
9931
  };
9080
9932
  }
9081
9933
  blockIndex++;
9082
9934
  }
9083
9935
  while (this._blockStates.length > blockIndex) {
9084
9936
  const removed = this._blockStates.pop();
9085
- this.remove(removed.renderable.id);
9937
+ removed.renderable.destroyRecursively();
9086
9938
  }
9087
9939
  }
9088
9940
  clearBlockStates() {
9089
9941
  for (const state of this._blockStates) {
9090
- this.remove(state.renderable.id);
9942
+ state.renderable.destroyRecursively();
9091
9943
  }
9092
9944
  this._blockStates = [];
9093
9945
  }
@@ -9100,8 +9952,32 @@ class MarkdownRenderable extends Renderable {
9100
9952
  codeRenderable.syntaxStyle = this._syntaxStyle;
9101
9953
  codeRenderable.conceal = this._conceal;
9102
9954
  } else if (state.token.type === "table") {
9955
+ const tableToken = state.token;
9103
9956
  const marginBottom = hasNextToken ? 1 : 0;
9104
- this.updateTableRenderable(state.renderable, state.token, marginBottom);
9957
+ const { cache } = this.buildTableContentCache(tableToken, state.tableContentCache, true);
9958
+ if (!cache) {
9959
+ if (state.renderable instanceof TextRenderable) {
9960
+ state.renderable.content = new StyledText([this.createDefaultChunk(tableToken.raw)]);
9961
+ state.renderable.marginBottom = marginBottom;
9962
+ } else {
9963
+ state.renderable.destroyRecursively();
9964
+ const fallbackRenderable = this.createTextRenderable([this.createDefaultChunk(tableToken.raw)], `${this.id}-block-${i}`, marginBottom);
9965
+ this.add(fallbackRenderable);
9966
+ state.renderable = fallbackRenderable;
9967
+ }
9968
+ state.tableContentCache = undefined;
9969
+ } else if (state.renderable instanceof TextTableRenderable) {
9970
+ state.renderable.content = cache.content;
9971
+ state.renderable.borderColor = this.getStyle("conceal")?.fg ?? "#888888";
9972
+ state.renderable.marginBottom = marginBottom;
9973
+ state.tableContentCache = cache;
9974
+ } else {
9975
+ state.renderable.destroyRecursively();
9976
+ const tableRenderable = this.createTextTableRenderable(cache.content, `${this.id}-block-${i}`, marginBottom);
9977
+ this.add(tableRenderable);
9978
+ state.renderable = tableRenderable;
9979
+ state.tableContentCache = cache;
9980
+ }
9105
9981
  } else {
9106
9982
  const textRenderable = state.renderable;
9107
9983
  const chunks = this.renderTokenToChunks(state.token);
@@ -9117,6 +9993,11 @@ class MarkdownRenderable extends Renderable {
9117
9993
  this.updateBlocks();
9118
9994
  this.requestRender();
9119
9995
  }
9996
+ refreshStyles() {
9997
+ this._styleDirty = false;
9998
+ this.rerenderBlocks();
9999
+ this.requestRender();
10000
+ }
9120
10001
  renderSelf(buffer, deltaTime) {
9121
10002
  if (this._styleDirty) {
9122
10003
  this._styleDirty = false;
@@ -11128,6 +12009,7 @@ export {
11128
12009
  TreeSitterClient,
11129
12010
  Timeline,
11130
12011
  TextareaRenderable,
12012
+ TextTableRenderable,
11131
12013
  TextRenderable,
11132
12014
  TextNodeRenderable,
11133
12015
  TextBufferView,
@@ -11206,5 +12088,5 @@ export {
11206
12088
  ASCIIFont
11207
12089
  };
11208
12090
 
11209
- //# debugId=B77F27E92D33B1E964756E2164756E21
12091
+ //# debugId=115C19DFB6D5E10364756E2164756E21
11210
12092
  //# sourceMappingURL=index.js.map