Co-authored-by: matt korwel <matt.korwel@gmail.com>
This commit is contained in:
Jacob Richman
2026-03-31 21:50:12 -07:00
committed by GitHub
parent 7c5cd693ce
commit 9f76f34049
42 changed files with 679 additions and 390 deletions
+20 -20
View File
@@ -5,16 +5,16 @@
*/
import React, { useMemo } from 'react';
import { styledCharsToString } from '@alcalzone/ansi-tokenize';
import {
Text,
Box,
type StyledChar,
StyledLine,
toStyledCharacters,
styledCharsWidth,
wordBreakStyledChars,
wrapStyledChars,
widestLineFromStyledChars,
styledCharsWidth,
styledCharsToString,
} from 'ink';
import { theme } from '../semantic-colors.js';
import { parseMarkdownToANSI } from './markdownParsingUtils.js';
@@ -31,22 +31,22 @@ const COLUMN_PADDING = 2;
const TABLE_MARGIN = 2;
/**
* Parses markdown to StyledChar array by first converting to ANSI.
* Parses markdown to StyledLine by first converting to ANSI.
* This ensures character counts are accurate (markdown markers are removed
* and styles are applied to the character's internal style object).
*/
const parseMarkdownToStyledChars = (
const parseMarkdownToStyledLine = (
text: string,
defaultColor?: string,
): StyledChar[] => {
): StyledLine => {
const ansi = parseMarkdownToANSI(text, defaultColor);
return toStyledCharacters(ansi);
};
const calculateWidths = (styledChars: StyledChar[]) => {
const contentWidth = styledCharsWidth(styledChars);
const calculateWidths = (styledLine: StyledLine) => {
const contentWidth = styledCharsWidth(styledLine);
const words: StyledChar[][] = wordBreakStyledChars(styledChars);
const words: StyledLine[] = wordBreakStyledChars(styledLine);
const maxWordWidth = widestLineFromStyledChars(words);
return { contentWidth, maxWordWidth };
@@ -67,10 +67,10 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
rows,
terminalWidth,
}) => {
const styledHeaders = useMemo(
const styledHeaders = useMemo<StyledLine[]>(
() =>
headers.map((header) =>
parseMarkdownToStyledChars(
parseMarkdownToStyledLine(
stripUnsafeCharacters(header),
theme.text.link,
),
@@ -78,11 +78,11 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
[headers],
);
const styledRows = useMemo(
const styledRows = useMemo<StyledLine[][]>(
() =>
rows.map((row) =>
row.map((cell) =>
parseMarkdownToStyledChars(
parseMarkdownToStyledLine(
stripUnsafeCharacters(cell),
theme.text.primary,
),
@@ -100,14 +100,14 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
// --- Define Constraints per Column ---
const constraints = Array.from({ length: numColumns }).map(
(_, colIndex) => {
const headerStyledChars = styledHeaders[colIndex] || [];
const headerStyledLine = styledHeaders[colIndex] || StyledLine.empty(0);
let { contentWidth: maxContentWidth, maxWordWidth } =
calculateWidths(headerStyledChars);
calculateWidths(headerStyledLine);
styledRows.forEach((row) => {
const cellStyledChars = row[colIndex] || [];
const cellStyledLine = row[colIndex] || StyledLine.empty(0);
const { contentWidth: cellWidth, maxWordWidth: cellWordWidth } =
calculateWidths(cellStyledChars);
calculateWidths(cellStyledLine);
maxContentWidth = Math.max(maxContentWidth, cellWidth);
maxWordWidth = Math.max(maxWordWidth, cellWordWidth);
@@ -176,16 +176,16 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
// --- Pre-wrap and Optimize Widths ---
const actualColumnWidths = new Array(numColumns).fill(0);
const wrapAndProcessRow = (row: StyledChar[][]) => {
const wrapAndProcessRow = (row: StyledLine[]) => {
const rowResult: ProcessedLine[][] = [];
// Ensure we iterate up to numColumns, filling with empty cells if needed
for (let colIndex = 0; colIndex < numColumns; colIndex++) {
const cellStyledChars = row[colIndex] || [];
const cellStyledLine = row[colIndex] || StyledLine.empty(0);
const allocatedWidth = finalContentWidths[colIndex];
const contentWidth = Math.max(1, allocatedWidth);
const wrappedStyledLines = wrapStyledChars(
cellStyledChars,
cellStyledLine,
contentWidth,
);