* test(mobile): pin escaped pipes in mobile markdown table cells
The mobile preview parser splits a table row on every pipe, so a cell
that escaped one becomes two cells and keeps the backslash.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): read table rows through the shared row splitter
The editor's markdown-table-rows already splits on unescaped pipes only
and unescapes the cell; it has no imports of its own, so owning the rule
once costs the preview parser nothing.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* test(mobile): pin escaped-pipe rows in PR comment tables
Its splitter strips the trailing pipe before walking escapes and reads
`\\|` as an escaped pipe, so a row ending in `\|` loses the pipe and a
cell holding a backslash swallows the separator after it.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): split PR comment table rows on unescaped pipes only
Its own delimiter grammar stays local: a single dash still opens a table
here, which the editor's three-dash separator would reject.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* test(config): repin the session route closure at 4,332 modules
markdown-table-rows.ts joins through the PR comment renderer. Measured on
this head: 4,332 modules / 990 local, and it is the only file under
rich-markdown/ in the closure, so nothing came with it.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* 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>