* fix(mobile): render Mermaid diagrams in MobileMarkdown (#11141)
Co-Authored-By: Grok Companion <noreply@x.ai>
* fix(mobile): keep streaming mermaid fences as raw code until the fence closes
* perf(mobile): memoize MermaidDiagram and add a CDN load watchdog
* fix(mobile): escape mermaid source before embedding in WebView script
JSON.stringify leaves </script>, &, and U+2028/U+2029 raw, so a diagram
source containing </script> broke out of the inline script and ran
arbitrary WebView JS. Diagram source is untrusted (agent output, PR/chat
content), and this component now renders from chat and markdown preview,
not just the PR sidebar. Escape those chars to \uXXXX; the literal still
parses back to the exact source. Adds an adversarial buildHtml test.
* fix(mobile): embed the mermaid engine instead of fetching it from a CDN
The diagram WebView loaded mermaid from jsdelivr at runtime: offline and
constrained-network renders always fell back, the stalled-load watchdog
existed only to paper over that, and an unpinned floating-major CDN script
with no integrity check ran inside the WebView. Embed the lockfile-pinned
package's prebuilt bundle via a postinstall generator (same mechanism as
the terminal WebView engine) so the document loads nothing external; the
watchdog is removed as obsolete and a no-external-URL gate pins it.
* chore(deps): align mermaid at 11.16.0 across desktop and mobile
Desktop floated ^11.15.0 while the mobile embedded engine resolved 11.16.0.
Raise the desktop floor so both lockfiles resolve the same version, and pin
mobile exact: the generated WebView engine embeds the package bytes, so an
implicit range bump would silently change what ships.
* fix(mobile): block Mermaid diagram network requests
Mermaid image-node URLs can initiate subresource requests even with the engine embedded. Keep the WebView offline by restricting resource types through its document CSP.
* style(mobile): format Mermaid routing test
* fix(mobile): use stable keys for Mermaid diagrams
* fix(mobile): keep duplicate Mermaid keys distinct
Combine each diagram source with its sibling occurrence so identical diagrams remain unique while source edits still remount the WebView and later streaming prose does not.
* fix(mobile): keep Mermaid transitive within release-age policy
---------
Co-authored-by: Grok Companion <noreply@x.ai>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* fix(mobile): bundle terminal engine and show load errors instead of a blank pane
The mobile terminal WebView loaded xterm.js from cdn.jsdelivr.net at
runtime; old WebViews (< Chrome 85) fail to parse the modern bundle and
blocked-CDN networks fail to fetch it, and the resulting error was
silently dropped, leaving the pane permanently blank (#7030).
Bundle the engine into the app via exact-pinned npm deps + a postinstall
esbuild step (chrome74 target, guarded WeakRef/structuredClone/
replaceChildren shims) emitting a gitignored generated module, inline it
into the terminal document, and surface fatal engine failures as a
visible overlay with diagnostics and a Reload wired into the existing
resubscribe path. Non-fatal errors log without covering a live terminal.
Co-authored-by: Orca <help@stably.ai>
* fix(mobile): add a native watchdog so a dead terminal document can't stay silently blank
CodeRabbit round: if the webview document dies before the glue can post
anything (or the RN message bridge never comes up), no error message and
no native handler fires. Arm a 15s foreground-gated watchdog per document
generation that paints the fatal overlay when web-ready never arrives;
first fatal diagnostics win over later cascades. Extract the watchdog and
the public contract types to keep TerminalWebView under the line cap, and
document the SVG xmlns percent-encoding transform.
Co-authored-by: Orca <help@stably.ai>
* test(mobile): unmount TerminalWebView renderers so watchdog timers can't leak across tests
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>