Files
AgenticCode/openspec/specs/rich-text-display/spec.md
local 7a5c22593a feat: enable rich text display for assistant messages
Add markdown-to-HTML rendering for assistant messages using Markdig with
HTML sanitization. Includes cached rendering to avoid lag during streaming,
styled markdown elements (code blocks, tables, lists, blockquotes) within
chat bubbles, and 18 unit tests covering rendering and XSS prevention.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:29:58 +01:00

96 lines
3.9 KiB
Markdown

## Purpose
Define rich text rendering for assistant messages — markdown-to-HTML conversion, sanitization, styling, and streaming compatibility.
## Requirements
### Requirement: Markdown rendering for assistant messages
The system SHALL convert assistant message content from markdown to formatted HTML using Markdig, displaying headings, bold, italic, code blocks, lists, tables, links, and blockquotes with proper visual formatting.
#### Scenario: Markdown bold and italic rendered
- **WHEN** an assistant message contains `**bold**` or `*italic*` text
- **THEN** the text is displayed with bold or italic formatting respectively
#### Scenario: Code block rendered
- **WHEN** an assistant message contains a fenced code block (triple backticks)
- **THEN** the code is displayed in a monospace font within a visually distinct block
#### Scenario: Inline code rendered
- **WHEN** an assistant message contains inline code (single backticks)
- **THEN** the code is displayed in a monospace font with a subtle background
#### Scenario: List rendered
- **WHEN** an assistant message contains a markdown list (ordered or unordered)
- **THEN** the list is displayed with proper indentation and bullet/number markers
#### Scenario: Heading rendered
- **WHEN** an assistant message contains markdown headings (# through ######)
- **THEN** the headings are displayed with appropriate size and weight
#### Scenario: Link rendered
- **WHEN** an assistant message contains a markdown link `[text](url)`
- **THEN** the link is displayed as a clickable hyperlink opening in a new tab
#### Scenario: Table rendered
- **WHEN** an assistant message contains a markdown table
- **THEN** the table is displayed with borders, header row styling, and proper alignment
### Requirement: HTML sanitization
The system SHALL sanitize all HTML output from the markdown renderer to prevent cross-site scripting (XSS) attacks from LLM-generated content.
#### Scenario: Script tags stripped
- **WHEN** assistant message content contains `<script>` tags
- **THEN** the script tags and their content are removed from the rendered output
#### Scenario: Event handlers stripped
- **WHEN** assistant message content contains HTML attributes like `onclick` or `onerror`
- **THEN** the attributes are removed from the rendered output
#### Scenario: Safe tags preserved
- **WHEN** assistant message content contains allowed structural HTML (p, strong, em, code, pre, ul, ol, li, a, table elements, blockquote, br, h1-h6)
- **THEN** the tags are preserved in the rendered output
### Requirement: Markdown styling within chat bubbles
The system SHALL style rendered markdown elements to be visually consistent with the MudBlazor chat bubble theme.
#### Scenario: Code block styled in bubble
- **WHEN** a code block is rendered inside an assistant chat bubble
- **THEN** it has a distinct background color, padding, border-radius, and does not overflow the bubble width (horizontal scroll if needed)
#### Scenario: Paragraph spacing in bubble
- **WHEN** multiple paragraphs are rendered inside an assistant chat bubble
- **THEN** paragraphs have appropriate spacing without excessive gaps
### Requirement: Streaming compatibility
The system SHALL re-render markdown as new tokens arrive during streaming without visual glitches.
#### Scenario: Partial markdown rendered during streaming
- **WHEN** tokens are arriving and the current content contains incomplete markdown (e.g., a code block not yet closed)
- **THEN** the content is rendered with best-effort formatting and updates smoothly as more tokens complete the markdown structure
### Requirement: User messages remain plain text
The system SHALL continue to render user messages as plain text without markdown processing.
#### Scenario: User message not processed as markdown
- **WHEN** a user message contains markdown syntax like `**bold**`
- **THEN** the raw text `**bold**` is displayed, not formatted bold text