You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Export leaves its scratch render container in the page layout #5541
Every styled-HTML / PDF / print export appends a scratch container to document.body — a second, full-size copy of the rendered document that the engine uses to rasterise diagrams before reading the markup back. Two things are wrong with how that container is contained.
1. The rule that moves it off-screen selects a class the engine no longer emits.
packages/desktop/src/renderer/src/assets/styles/printService.css still targets the legacy muyajs class:
body .ag-render-container {
position: fixed;
left:-10000px;
right:-10000px;
max-width:100%;
}
The @muyajs/core engine tags the container mu-render-container (packages/muya/src/state/markdownToHtml.ts). The selector was never updated when the engine was swapped in for 0.20, so nothing matches and the container is laid out position: static, in the normal flow, visible, at the top of <body>.
Measured while exporting the 365 KB document from #3433, with a MutationObserver reading the container's box the moment it is inserted:
today
with the selector corrected
position
static
fixed
box
top: 21, left: 0, 1200 × 228251
top: 0, left: -10000, 1200 × 228251
document.body.scrollHeight
228 243
800
So the host page's layout grows to ~228 000 px for the duration of the export and every export pays a full reflow of the host document. It is not currently visible — the app root is a positioned element and wins the paint order, and body has overflow-y: hidden so no scrollbar appears — and the container is removed within a frame or two, so this is not user-facing today. It is one stacking-context change away from being user-facing, and the containment it is supposed to have is simply not in effect.
2. The container is only removed on the success path.
_renderMermaid / _renderDiagram contain per-diagram failures in their own try blocks, but the await loadRenderer(…) that pulls in mermaid / vega-lite / plantuml sits outside those blocks. A failed dynamic import (chunk fetch failure, a corrupted install) therefore propagates out of renderHtml, exportContainer.remove() never runs, and the container — full-size, in the normal flow, per (1) — is stranded in the page for the rest of the session. The desktop wrapper catches the rejection and shows "Failed to export document", so the user gets an error and a page that is now permanently carrying a copy of their document.
Steps to reproduce
(2) reproduces headlessly with the diagram loader mocked to reject the way a failed chunk load does:
vi.mock('../../utils/diagram',()=>({default: loadRenderer}))loadRenderer.mockRejectedValue(newError('Failed to fetch dynamically imported module'))awaitexpect(newMarkdownToHtml('```mermaid\ngraph TD; A-->B\n```\n').renderHtml()).rejects.toThrow()expect(document.querySelectorAll('.mu-render-container')).toHaveLength(0)// → AssertionError: expected …(1) to have a length of +0 but got 1
Expected behavior:
The scratch container stays out of the host document's layout while it is live, and is gone whether the render succeeds or fails.
Actual behavior:
It is laid out in the normal flow for the duration of every export, and is left behind permanently if a diagram renderer fails to load.
Activity
fix(desktop): keep the export render container out of the page layout (…
fix: keep the export render container out of the page layout (#5541) (#…