UNPKG

buroventures-harald-code

Version:

Harald Code - AI-powered coding assistant CLI

84 lines 4.47 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import React from 'react'; import { Text, Box } from 'ink'; import { Colors } from '../colors.js'; import { RenderInline, getPlainTextLength } from './InlineMarkdownRenderer.js'; /** * Custom table renderer for markdown tables * We implement our own instead of using ink-table due to module compatibility issues */ export const TableRenderer = ({ headers, rows, terminalWidth, }) => { // Calculate column widths using actual display width after markdown processing const columnWidths = headers.map((header, index) => { const headerWidth = getPlainTextLength(header); const maxRowWidth = Math.max(...rows.map((row) => getPlainTextLength(row[index] || ''))); return Math.max(headerWidth, maxRowWidth) + 2; // Add padding }); // Ensure table fits within terminal width const totalWidth = columnWidths.reduce((sum, width) => sum + width + 1, 1); const scaleFactor = totalWidth > terminalWidth ? terminalWidth / totalWidth : 1; const adjustedWidths = columnWidths.map((width) => Math.floor(width * scaleFactor)); // Helper function to render a cell with proper width const renderCell = (content, width, isHeader = false) => { const contentWidth = Math.max(0, width - 2); const displayWidth = getPlainTextLength(content); let cellContent = content; if (displayWidth > contentWidth) { if (contentWidth <= 3) { // Just truncate by character count cellContent = content.substring(0, Math.min(content.length, contentWidth)); } else { // Truncate preserving markdown formatting using binary search let left = 0; let right = content.length; let bestTruncated = content; // Binary search to find the optimal truncation point while (left <= right) { const mid = Math.floor((left + right) / 2); const candidate = content.substring(0, mid); const candidateWidth = getPlainTextLength(candidate); if (candidateWidth <= contentWidth - 3) { bestTruncated = candidate; left = mid + 1; } else { right = mid - 1; } } cellContent = bestTruncated + '...'; } } // Calculate exact padding needed const actualDisplayWidth = getPlainTextLength(cellContent); const paddingNeeded = Math.max(0, contentWidth - actualDisplayWidth); return (_jsxs(Text, { children: [isHeader ? (_jsx(Text, { bold: true, color: Colors.AccentCyan, children: _jsx(RenderInline, { text: cellContent }) })) : (_jsx(RenderInline, { text: cellContent })), ' '.repeat(paddingNeeded)] })); }; // Helper function to render border const renderBorder = (type) => { const chars = { top: { left: '┌', middle: '┬', right: '┐', horizontal: '─' }, middle: { left: '├', middle: '┼', right: '┤', horizontal: '─' }, bottom: { left: '└', middle: '┴', right: '┘', horizontal: '─' }, }; const char = chars[type]; const borderParts = adjustedWidths.map((w) => char.horizontal.repeat(w)); const border = char.left + borderParts.join(char.middle) + char.right; return _jsx(Text, { children: border }); }; // Helper function to render a table row const renderRow = (cells, isHeader = false) => { const renderedCells = cells.map((cell, index) => { const width = adjustedWidths[index] || 0; return renderCell(cell || '', width, isHeader); }); return (_jsxs(Text, { children: ["\u2502", ' ', renderedCells.map((cell, index) => (_jsxs(React.Fragment, { children: [cell, index < renderedCells.length - 1 ? ' │ ' : ''] }, index))), ' ', "\u2502"] })); }; return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [renderBorder('top'), renderRow(headers, true), renderBorder('middle'), rows.map((row, index) => (_jsx(React.Fragment, { children: renderRow(row) }, index))), renderBorder('bottom')] })); }; //# sourceMappingURL=TableRenderer.js.map