diff options
Diffstat (limited to 'packages/cli/src/ui/utils/MarkdownDisplay.tsx')
| -rw-r--r-- | packages/cli/src/ui/utils/MarkdownDisplay.tsx | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/packages/cli/src/ui/utils/MarkdownDisplay.tsx b/packages/cli/src/ui/utils/MarkdownDisplay.tsx index 572ae12e..eb5dc453 100644 --- a/packages/cli/src/ui/utils/MarkdownDisplay.tsx +++ b/packages/cli/src/ui/utils/MarkdownDisplay.tsx @@ -21,7 +21,7 @@ interface MarkdownDisplayProps { // Constants for Markdown parsing and rendering const EMPTY_LINE_HEIGHT = 1; -const CODE_BLOCK_PADDING = 1; +const CODE_BLOCK_PREFIX_PADDING = 1; const LIST_ITEM_PREFIX_PADDING = 1; const LIST_ITEM_TEXT_FLEX_GROW = 1; @@ -44,6 +44,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ const contentBlocks: React.ReactNode[] = []; let inCodeBlock = false; + let lastLineEmpty = true; let codeBlockContent: string[] = []; let codeBlockLang: string | null = null; let codeBlockFence = ''; @@ -51,6 +52,13 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ let tableRows: string[][] = []; let tableHeaders: string[] = []; + function addContentBlock(block: React.ReactNode) { + if (block) { + contentBlocks.push(block); + lastLineEmpty = false; + } + } + lines.forEach((line, index) => { const key = `line-${index}`; @@ -61,7 +69,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ fenceMatch[1].startsWith(codeBlockFence[0]) && fenceMatch[1].length >= codeBlockFence.length ) { - contentBlocks.push( + addContentBlock( <RenderCodeBlock key={key} content={codeBlockContent} @@ -104,7 +112,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ tableRows = []; } else { // Not a table, treat as regular text - contentBlocks.push( + addContentBlock( <Box key={key}> <Text wrap="wrap"> <RenderInline text={line} /> @@ -128,7 +136,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ } else if (inTable && !tableRowMatch) { // End of table if (tableHeaders.length > 0 && tableRows.length > 0) { - contentBlocks.push( + addContentBlock( <RenderTable key={`table-${contentBlocks.length}`} headers={tableHeaders} @@ -143,7 +151,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ // Process current line as normal if (line.trim().length > 0) { - contentBlocks.push( + addContentBlock( <Box key={key}> <Text wrap="wrap"> <RenderInline text={line} /> @@ -152,7 +160,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ ); } } else if (hrMatch) { - contentBlocks.push( + addContentBlock( <Box key={key}> <Text dimColor>---</Text> </Box>, @@ -198,12 +206,12 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ ); break; } - if (headerNode) contentBlocks.push(<Box key={key}>{headerNode}</Box>); + if (headerNode) addContentBlock(<Box key={key}>{headerNode}</Box>); } else if (ulMatch) { const leadingWhitespace = ulMatch[1]; const marker = ulMatch[2]; const itemText = ulMatch[3]; - contentBlocks.push( + addContentBlock( <RenderListItem key={key} itemText={itemText} @@ -216,7 +224,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ const leadingWhitespace = olMatch[1]; const marker = olMatch[2]; const itemText = olMatch[3]; - contentBlocks.push( + addContentBlock( <RenderListItem key={key} itemText={itemText} @@ -226,12 +234,15 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ />, ); } else { - if (line.trim().length === 0) { - if (contentBlocks.length > 0 && !inCodeBlock) { - contentBlocks.push(<Box key={key} height={EMPTY_LINE_HEIGHT} />); + if (line.trim().length === 0 && !inCodeBlock) { + if (!lastLineEmpty) { + contentBlocks.push( + <Box key={`spacer-${index}`} height={EMPTY_LINE_HEIGHT} />, + ); + lastLineEmpty = true; } } else { - contentBlocks.push( + addContentBlock( <Box key={key}> <Text wrap="wrap"> <RenderInline text={line} /> @@ -243,7 +254,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ }); if (inCodeBlock) { - contentBlocks.push( + addContentBlock( <RenderCodeBlock key="line-eof" content={codeBlockContent} @@ -257,7 +268,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ // Handle table at end of content if (inTable && tableHeaders.length > 0 && tableRows.length > 0) { - contentBlocks.push( + addContentBlock( <RenderTable key={`table-${contentBlocks.length}`} headers={tableHeaders} @@ -293,14 +304,14 @@ const RenderCodeBlockInternal: React.FC<RenderCodeBlockProps> = ({ if (isPending && availableTerminalHeight !== undefined) { const MAX_CODE_LINES_WHEN_PENDING = Math.max( 0, - availableTerminalHeight - CODE_BLOCK_PADDING * 2 - RESERVED_LINES, + availableTerminalHeight - RESERVED_LINES, ); if (content.length > MAX_CODE_LINES_WHEN_PENDING) { if (MAX_CODE_LINES_WHEN_PENDING < MIN_LINES_FOR_MESSAGE) { // Not enough space to even show the message meaningfully return ( - <Box padding={CODE_BLOCK_PADDING}> + <Box paddingLeft={CODE_BLOCK_PREFIX_PADDING}> <Text color={Colors.Gray}>... code is being written ...</Text> </Box> ); @@ -310,10 +321,10 @@ const RenderCodeBlockInternal: React.FC<RenderCodeBlockProps> = ({ truncatedContent.join('\n'), lang, availableTerminalHeight, - terminalWidth - CODE_BLOCK_PADDING * 2, + terminalWidth - CODE_BLOCK_PREFIX_PADDING, ); return ( - <Box flexDirection="column" padding={CODE_BLOCK_PADDING}> + <Box paddingLeft={CODE_BLOCK_PREFIX_PADDING} flexDirection="column"> {colorizedTruncatedCode} <Text color={Colors.Gray}>... generating more ...</Text> </Box> @@ -326,13 +337,13 @@ const RenderCodeBlockInternal: React.FC<RenderCodeBlockProps> = ({ fullContent, lang, availableTerminalHeight, - terminalWidth - CODE_BLOCK_PADDING * 2, + terminalWidth - CODE_BLOCK_PREFIX_PADDING, ); return ( <Box + paddingLeft={CODE_BLOCK_PREFIX_PADDING} flexDirection="column" - padding={CODE_BLOCK_PADDING} width={terminalWidth} flexShrink={0} > |
