microsoft / microsoft/simplechat

V2 chat shows TeX, Mermaid diagrams and chart payloads as raw text

Open
#1,376 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
152
Forks
116
Avg merge
7h 7m
Merged PRs (30d)
122

Description

## Problem

Three kinds of block that SimpleChat already produces are rendered as raw text in the V2 React chat (`application/v2_ui`).

### 1. Mermaid diagrams

This is the least obvious and arguably the most impactful. Azure Content Understanding already extracts document figures as Mermaid and writes them into page content as fenced blocks:

```python
# application/single_app/functions_content_understanding.py:330
if figure_kind == 'mermaid' and isinstance(figure_content, str) and figure_content.strip():
diagram_block = f"```mermaid\n{figure_content.strip()}\n```"
```

So a user who uploads a document containing a flowchart and asks about it gets diagram *source* pasted into the middle of the answer. Nothing renders it in either interface.

### 2. TeX

Models emit `\( ... \)`, `\[ ... \]` and `$$ ... $$`. None of it renders, so any answer involving mathematics arrives as unreadable markup.

### 3. SimpleChart

The built-in chart action emits ` ```simplechart ` fences (`functions_chart_operations.py:191`). The classic interface renders these via `static/js/chat/chat-inline-charts.js`; V2 shows the raw JSON payload — often several kilobytes of it — in the middle of the reply.

## Scope

V2 React UI only. The classic interface is unchanged.

## Constraints

- **No new remote browser code.** Third-party browser libraries must be downloaded and committed to the repository so the bytes the browser executes are pinned and any change to them is a reviewable commit rather than a silent substitution. This rules out resolving them from npm at build time as well as loading them from a CDN at run time.
- The `Content-Security-Policy` in `config.py` (`default-src 'self'`, `script-src 'self'`, `font-src 'self'`) must not be relaxed.
- Diagram and equation source is untrusted model output, so anything rendered from it needs an explicit sanitizer boundary — V2 currently uses `dangerouslySetInnerHTML` nowhere.
- A single `$...$` must **not** be treated as inline maths, or ordinary prose about money ("costs $5 to $10 per user") renders as an equation.

## Acceptance criteria

- [ ] `$$...$$`, `\[...\]` and `\(...\)` render as maths; a lone `$` does not
- [ ] ` ```mermaid ` fences render as diagrams
- [ ] ` ```simplechart ` fences render as charts, with the underlying data reachable and an image download
- [ ] Fenced and inline code containing these delimiters is left untouched
- [ ] A reply that is still streaming does not repeatedly hand the renderer a half-written fence
- [ ] Diagrams and charts follow the light/dark theme
- [ ] Copying a message does not paste a raw chart payload
- [ ] All third-party browser code is committed under version control, with licences and pinned versions
- [ ] The CSP is unchanged

## Resolution

Implemented in **v0.261.019**.

- Libraries vendored under `application/v2_ui/public/vendor/-/`: KaTeX 0.18.4, Mermaid 11.17.2, Chart.js 4.5.1, DOMPurify 3.4.14. All files verified against the registry's published SHA-256, licences preserved, and loaded on demand so a conversation with no maths, diagram or chart downloads none of them. **No npm dependencies were added.**
- `remark-math` was deliberately not used: CommonMark treats a backslash before ASCII punctuation as an escape, so `\(x\)` is already the literal text `(x)` by the time an mdast node exists and a post-parse plugin cannot see the delimiters. Maths instead reuses the placeholder mechanism the renderer already has for citations and masks.
- KaTeX runs with `trust: false`; Mermaid with `securityLevel: 'strict'`, `htmlLabels: false`, no autostart and no icon packs. Both pass through DOMPurify before injection — the only two `dangerouslySetInnerHTML` sites in the SPA, enforced by test.
- The markdown renderer moved from `MessageList.tsx` into its own `AssistantMarkdown.tsx`.

Verified in a real browser across light and dark themes. Covered by `functional_tests/test_v2_rich_rendering.py`; the full V2 suite (18 files) passes.

Documentation: `docs/explanation/features/REACT_V2_UI.md`, `docs/explanation/release_notes.md`.

Contributor guide

Open the contributing guide

Research direction

Start in application/v2_ui, especially the markdown rendering moved into AssistantMarkdown.tsx, and review functional_tests/test_v2_rich_rendering.py. Compare the implementation with the listed acceptance criteria, including fenced-content handling, sanitization, theme behavior, streaming, copying, vendored libraries, and the unchanged CSP.

Written by the indexing model from the issue text.

Assessment

Tech stack
chart.js, python, react, typescript
Domain
frontend, security, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.