diff options
Diffstat (limited to 'packages/cli/src/ui/utils/MarkdownDisplay.tsx')
| -rw-r--r-- | packages/cli/src/ui/utils/MarkdownDisplay.tsx | 144 |
1 files changed, 1 insertions, 143 deletions
diff --git a/packages/cli/src/ui/utils/MarkdownDisplay.tsx b/packages/cli/src/ui/utils/MarkdownDisplay.tsx index 55f1ce57..572ae12e 100644 --- a/packages/cli/src/ui/utils/MarkdownDisplay.tsx +++ b/packages/cli/src/ui/utils/MarkdownDisplay.tsx @@ -9,6 +9,7 @@ import { Text, Box } from 'ink'; import { Colors } from '../colors.js'; import { colorizeCode } from './CodeColorizer.js'; import { TableRenderer } from './TableRenderer.js'; +import { RenderInline } from './InlineMarkdownRenderer.js'; interface MarkdownDisplayProps { text: string; @@ -18,12 +19,6 @@ interface MarkdownDisplayProps { } // Constants for Markdown parsing and rendering -const BOLD_MARKER_LENGTH = 2; // For "**" -const ITALIC_MARKER_LENGTH = 1; // For "*" or "_" -const STRIKETHROUGH_MARKER_LENGTH = 2; // For "~~" -const INLINE_CODE_MARKER_LENGTH = 1; // For "`" -const UNDERLINE_TAG_START_LENGTH = 3; // For "<u>" -const UNDERLINE_TAG_END_LENGTH = 4; // For "</u>" const EMPTY_LINE_HEIGHT = 1; const CODE_BLOCK_PADDING = 1; @@ -277,143 +272,6 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ // Helper functions (adapted from static methods of MarkdownRenderer) -interface RenderInlineProps { - text: string; -} - -const RenderInlineInternal: React.FC<RenderInlineProps> = ({ text }) => { - const nodes: React.ReactNode[] = []; - let lastIndex = 0; - const inlineRegex = - /(\*\*.*?\*\*|\*.*?\*|_.*?_|~~.*?~~|\[.*?\]\(.*?\)|`+.+?`+|<u>.*?<\/u>)/g; - let match; - - while ((match = inlineRegex.exec(text)) !== null) { - if (match.index > lastIndex) { - nodes.push( - <Text key={`t-${lastIndex}`}> - {text.slice(lastIndex, match.index)} - </Text>, - ); - } - - const fullMatch = match[0]; - let renderedNode: React.ReactNode = null; - const key = `m-${match.index}`; - - try { - if ( - fullMatch.startsWith('**') && - fullMatch.endsWith('**') && - fullMatch.length > BOLD_MARKER_LENGTH * 2 - ) { - renderedNode = ( - <Text key={key} bold> - {fullMatch.slice(BOLD_MARKER_LENGTH, -BOLD_MARKER_LENGTH)} - </Text> - ); - } else if ( - fullMatch.length > ITALIC_MARKER_LENGTH * 2 && - ((fullMatch.startsWith('*') && fullMatch.endsWith('*')) || - (fullMatch.startsWith('_') && fullMatch.endsWith('_'))) && - !/\w/.test(text.substring(match.index - 1, match.index)) && - !/\w/.test( - text.substring(inlineRegex.lastIndex, inlineRegex.lastIndex + 1), - ) && - !/\S[./\\]/.test(text.substring(match.index - 2, match.index)) && - !/[./\\]\S/.test( - text.substring(inlineRegex.lastIndex, inlineRegex.lastIndex + 2), - ) - ) { - renderedNode = ( - <Text key={key} italic> - {fullMatch.slice(ITALIC_MARKER_LENGTH, -ITALIC_MARKER_LENGTH)} - </Text> - ); - } else if ( - fullMatch.startsWith('~~') && - fullMatch.endsWith('~~') && - fullMatch.length > STRIKETHROUGH_MARKER_LENGTH * 2 - ) { - renderedNode = ( - <Text key={key} strikethrough> - {fullMatch.slice( - STRIKETHROUGH_MARKER_LENGTH, - -STRIKETHROUGH_MARKER_LENGTH, - )} - </Text> - ); - } else if ( - fullMatch.startsWith('`') && - fullMatch.endsWith('`') && - fullMatch.length > INLINE_CODE_MARKER_LENGTH - ) { - const codeMatch = fullMatch.match(/^(`+)(.+?)\1$/s); - if (codeMatch && codeMatch[2]) { - renderedNode = ( - <Text key={key} color={Colors.AccentPurple}> - {codeMatch[2]} - </Text> - ); - } else { - renderedNode = ( - <Text key={key} color={Colors.AccentPurple}> - {fullMatch.slice( - INLINE_CODE_MARKER_LENGTH, - -INLINE_CODE_MARKER_LENGTH, - )} - </Text> - ); - } - } else if ( - fullMatch.startsWith('[') && - fullMatch.includes('](') && - fullMatch.endsWith(')') - ) { - const linkMatch = fullMatch.match(/\[(.*?)\]\((.*?)\)/); - if (linkMatch) { - const linkText = linkMatch[1]; - const url = linkMatch[2]; - renderedNode = ( - <Text key={key}> - {linkText} - <Text color={Colors.AccentBlue}> ({url})</Text> - </Text> - ); - } - } else if ( - fullMatch.startsWith('<u>') && - fullMatch.endsWith('</u>') && - fullMatch.length > - UNDERLINE_TAG_START_LENGTH + UNDERLINE_TAG_END_LENGTH - 1 // -1 because length is compared to combined length of start and end tags - ) { - renderedNode = ( - <Text key={key} underline> - {fullMatch.slice( - UNDERLINE_TAG_START_LENGTH, - -UNDERLINE_TAG_END_LENGTH, - )} - </Text> - ); - } - } catch (e) { - console.error('Error parsing inline markdown part:', fullMatch, e); - renderedNode = null; - } - - nodes.push(renderedNode ?? <Text key={key}>{fullMatch}</Text>); - lastIndex = inlineRegex.lastIndex; - } - - if (lastIndex < text.length) { - nodes.push(<Text key={`t-${lastIndex}`}>{text.slice(lastIndex)}</Text>); - } - - return <>{nodes.filter((node) => node !== null)}</>; -}; - -const RenderInline = React.memo(RenderInlineInternal); - interface RenderCodeBlockProps { content: string[]; lang: string | null; |
