MoonshotAI / MoonshotAI/kimi-code
web: Long mermaid labels overflow their node boxes and overlap
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
Problem
In the web UI, mermaid diagrams with long labels (very common with CJK text, ~12+ Chinese characters) render with the label text overflowing its node box on both sides, and adjacent nodes' labels overlap each other:
The node rect is sized for the wrapped label, but the text renders as one long single line centered on the node.
Root cause
- mermaid (11.15,
securityLevel: loose→ htmlLabels on) wraps long labels via CSS soft wrap inside a<foreignObject>(max-width: 200px, no<br>in the DOM) and sizes the node rect from the wrapped measurement (~200px + padding). - Before inserting the SVG, markstream-vue runs it through stream-markdown-parser's
toSafeSvgElement, whosereplaceForeignObjectLabelsreplaces every<foreignObject>with a single-line SVG<text>— it only splits lines on literal<br>, so the CSS soft-wrap structure is lost. - The full-width single-line text is then rendered centered (
text-anchor="middle") on a rect sized for 200px → symmetric overflow on both sides; dagre laid the nodes out for the small measured width, so neighbors' labels overlap.
Measured with the same dependency versions (mermaid 11.15.0 + stream-markdown-parser 1.1.7): a 35-char CJK label yields a 260px node rect but 576px of rendered text (~158px overflow per side).
Notes
- App-side CSS is not the cause: after sanitization there is no
foreignObjectleft in the DOM for any selector to reach, and mermaid injects its own font styles into the SVG before measuring. - A fix PR is on the way: it injects
%%{init: {"htmlLabels": false}}%%into mermaid fences so mermaid lays out native SVG text with real width-based line breaking, leaving the sanitizer nothing to flatten. (flowchart.htmlLabelsis deprecated and silently shadowed by the global default in mermaid 11.15 — only the global key actually takes effect.)
Environment
- kimi-web (web UI) with markstream-vue 1.0.9-beta.1, stream-markdown-parser 1.1.7, mermaid 11.15.0
- Reproduces in Chrome; mechanism is platform-independent.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue in the web UI with mermaid 11.15.0 and a long CJK label, then trace the mermaid fence through markstream-vue and stream-markdown-parser 1.1.7, especially foreignObject label sanitization. Done means long labels wrap within their node boxes and adjacent node labels no longer overlap, with the behavior verified in Chrome.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100