perf(mothership): restore static markdown parse for settled chat messages#5751
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryLow Risk Overview Streamdown Syntax highlighting: Code blocks go through a module-scoped bounded LRU cache (512 entries) for Prism output, since row virtualization remounts rows and component Reviewed by Cursor Bugbot for commit 76892a3. Configure here. |
Greptile SummaryThis PR improves rendering performance for virtualized chat messages. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "fix(mothership): don't cache fallback-hi..." | Re-trigger Greptile |
…ages Settled/reloaded chat messages rendered through Streamdown's streaming parser (remend + incomplete-markdown repair + per-block re-parse, running the rehype raw/sanitize/harden chain once per block). Because rows are virtualized, every up/down scroll remounted the messages crossing the overscan boundary and re-paid that N-block cost — the scroll lag. - Render never-streamed mounts (reloaded history, or an in-session message scrolled out of the virtualized window and back) with mode='static': one whole-document parse instead of streaming's per-block re-parse. In-session streaming keeps the streaming parser for its mount life (no drain flash). - Cache Prism highlight output in a module-level bounded LRU so a code block re-highlights at most once across the unmount/remount virtualization does on scroll (a component useMemo would not survive the unmount).
4d39557 to
b79985a
Compare
An unregistered language highlighted via the JavaScript fallback was cached under its own name, so if that Prism grammar registered later in the session a remount would keep serving the stale fallback render. Resolve the grammar inside the highlight helper and skip the cache entirely on the fallback path.
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 76892a3. Configure here.

Summary
mode='static'from the chat markdown renderer. Every message then rendered through Streamdown's streaming parser — remend + incomplete-markdown repair + per-block re-parse, running the rehype raw/sanitize/harden chain once per block.mode='static'for never-streamed mounts (reloaded history, or an in-session message scrolled out of the virtualized window and back): one whole-document parse instead of streaming's per-block re-parse. A completed message needs no incomplete-markdown repair, so static is the correct — and much cheaper — mode.useMemowould not survive the unmount.Root cause
Verified by commit archaeology + reading
streamdown@2.5.0's compiled parser:mode: 'static'renders the whole message in oneReactMarkdownpass and skipsparseIncompleteMarkdown;mode: 'streaming'splits into N blocks and renders each as its ownReactMarkdownsubtree, running the expensiverehype-rawchain per block.Type of Change
Testing
tscclean (0 errors), biome clean, 108/108 message-content tests pass./cleanup(8 parallel quality passes: effects, state, memo, callback, react-query, url-state, emcn, comments) returned zero findings.Checklist