Implement StreamingProse component with markdown rendering #8310

Closed
opened 2026-02-16 18:09:39 -05:00 by yindo · 2 comments
Owner

Originally created by @randomm on GitHub (Feb 2, 2026).

Originally assigned to: @thdxr on GitHub.

Parent Epic

Part of #11762 (Ink-based TUI Rewrite)

Objective

Create component that renders streaming markdown text, handling incremental updates smoothly.

Current Implementation

The existing markdown.ts (174 lines) works well. We should reuse the markdown rendering logic but wrap it in an Ink component.

Component Design

interface StreamingProseProps {
  text: string
  isStreaming: boolean
}

const StreamingProse: React.FC<StreamingProseProps> = ({ text, isStreaming }) => {
  const rendered = useMarkdown(text)
  return (
    <Box flexDirection="column">
      <Text>{rendered}</Text>
      {isStreaming && <Text dimColor>...</Text>}
    </Box>
  )
}

Tasks

  • Create src/cli/ink/components/StreamingProse.tsx
  • Create src/cli/ink/hooks/useMarkdown.ts - wraps existing markdown logic
  • Handle terminal width for proper wrapping
  • Support streaming mode (partial text with cursor indicator)
  • Support completed mode (full text, no cursor)
  • Test with various markdown content:
    • Code blocks
    • Lists
    • Headers
    • Inline code
    • Links

Acceptance Criteria

  • Markdown renders correctly in terminal
  • Streaming text updates smoothly without flicker
  • Terminal width is respected
  • Code blocks have proper syntax highlighting (if supported)

Estimated Effort

2 days

Risk

Medium - Markdown rendering can be complex, but we're reusing existing logic

Dependencies

Originally created by @randomm on GitHub (Feb 2, 2026). Originally assigned to: @thdxr on GitHub. ## Parent Epic Part of #11762 (Ink-based TUI Rewrite) ## Objective Create component that renders streaming markdown text, handling incremental updates smoothly. ## Current Implementation The existing `markdown.ts` (174 lines) works well. We should reuse the markdown rendering logic but wrap it in an Ink component. ## Component Design ```tsx interface StreamingProseProps { text: string isStreaming: boolean } const StreamingProse: React.FC<StreamingProseProps> = ({ text, isStreaming }) => { const rendered = useMarkdown(text) return ( <Box flexDirection="column"> <Text>{rendered}</Text> {isStreaming && <Text dimColor>...</Text>} </Box> ) } ``` ## Tasks - [ ] Create `src/cli/ink/components/StreamingProse.tsx` - [ ] Create `src/cli/ink/hooks/useMarkdown.ts` - wraps existing markdown logic - [ ] Handle terminal width for proper wrapping - [ ] Support streaming mode (partial text with cursor indicator) - [ ] Support completed mode (full text, no cursor) - [ ] Test with various markdown content: - Code blocks - Lists - Headers - Inline code - Links ## Acceptance Criteria - [ ] Markdown renders correctly in terminal - [ ] Streaming text updates smoothly without flicker - [ ] Terminal width is respected - [ ] Code blocks have proper syntax highlighting (if supported) ## Estimated Effort 2 days ## Risk Medium - Markdown rendering can be complex, but we're reusing existing logic ## Dependencies - #11763 (Setup Ink dependencies) - #11764 (App component)
yindo added the opentui label 2026-02-16 18:09:39 -05:00
yindo closed this issue 2026-02-16 18:09:39 -05:00
Author
Owner

@randomm commented on GitHub (Feb 2, 2026):

Research Finding

Current implementation uses @opentui/core Code component - this is SolidJS-based and won't work with Ink/React.

Need React-compatible alternative:

  • ink-markdown - Ink-native markdown component
  • marked + chalk - Parse markdown, colorize output
  • marked-terminal - Terminal-friendly markdown renderer

Will research and select appropriate solution for Ink.

@randomm commented on GitHub (Feb 2, 2026): ## Research Finding **Current implementation** uses `@opentui/core` Code component - this is SolidJS-based and won't work with Ink/React. **Need React-compatible alternative:** - `ink-markdown` - Ink-native markdown component - `marked` + `chalk` - Parse markdown, colorize output - `marked-terminal` - Terminal-friendly markdown renderer Will research and select appropriate solution for Ink.
Author
Owner

@randomm commented on GitHub (Feb 2, 2026):

Markdown Library Decision

Selected: markdansi (Jan 2026, Node 22+)

Reasons:

  • Streaming-first design with hybrid blocks mode
  • Buffers multi-line constructs (code blocks, tables) until complete
  • Pluggable syntax highlighting via highlighter(code, lang)
  • OSC-8 hyperlinks, GFM tables
  • 70KB lightweight

Installation: bun add markdansi

Usage pattern:

import { render } from 'markdansi'

<Text>{render(markdown, { width, highlighter })}</Text>

Alternative ink-markdown exists but uses marked-terminal (batch only, not streaming-optimized).

@randomm commented on GitHub (Feb 2, 2026): ## Markdown Library Decision **Selected: `markdansi`** (Jan 2026, Node 22+) **Reasons:** - Streaming-first design with hybrid blocks mode - Buffers multi-line constructs (code blocks, tables) until complete - Pluggable syntax highlighting via `highlighter(code, lang)` - OSC-8 hyperlinks, GFM tables - 70KB lightweight **Installation:** `bun add markdansi` **Usage pattern:** ```tsx import { render } from 'markdansi' <Text>{render(markdown, { width, highlighter })}</Text> ``` Alternative `ink-markdown` exists but uses marked-terminal (batch only, not streaming-optimized).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#8310