microsoft / microsoft/simplechat
V2 chat shows TeX, Mermaid diagrams and chart payloads as raw text
- 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
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