mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-28 20:50:05 +02:00
feat(make-pdf): diagram pre-pass — mermaid/excalidraw fences render as vector SVG; local images inline as data URIs
```mermaid / ```excalidraw fences extract to placeholder tokens, render in one diagram-render bundle tab per run (reset contract: bundle page reloads after any render error), and substitute back as accessible <figure> blocks with the raw source preserved in a comment. Render failures produce a loud red diagnostic block, never silent raw code. render=false keeps a fence as code; title="..." becomes the aria-label and caption. Local images now actually render: page.setContent loads at about:blank (tab-session.ts:194), so relative paths silently 404'd before. The pre-pass resolves them against the markdown's directory, inlines as data URIs, probes intrinsic dimensions from the bytes (pure-TS PNG/JPEG/GIF/WebP/SVG sniffing), and downscales rasters wider than 2x the content box at 300dpi. Remote URLs warn (offline posture, --allow-network exempts); missing files get a visible placeholder; --strict hard-fails both for CI pipelines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -324,6 +324,18 @@ function figureRules(): string {
|
||||
`figure { margin: 12pt 0; }`,
|
||||
`figure img { display: block; max-width: 100%; height: auto; }`,
|
||||
`figcaption { font-size: 9pt; color: #666; margin-top: 6pt; font-style: italic; }`,
|
||||
// Diagram figures (diagram-prepass): rendered mermaid/excalidraw SVG.
|
||||
// SVGs scale to the content box and never split across pages.
|
||||
`figure.diagram { break-inside: avoid; text-align: center; }`,
|
||||
`figure.diagram > svg { max-width: 100%; height: auto; }`,
|
||||
`figure.diagram .diagram-caption { text-align: center; }`,
|
||||
// Diagnostic block for a fence that failed to render — loud, boxed,
|
||||
// unmistakably an error (never silent raw code).
|
||||
`figure.diagram-error { border: 1.5pt solid #b00020; padding: 8pt 10pt; text-align: left; }`,
|
||||
`figure.diagram-error .diagram-error-title { font-weight: 700; color: #b00020; font-style: normal; margin: 0 0 6pt; }`,
|
||||
`figure.diagram-error .diagram-error-detail { font-size: 8.5pt; white-space: pre-wrap; margin: 0; }`,
|
||||
// Missing local image placeholder (non-strict mode).
|
||||
`.image-missing { display: inline-block; border: 1pt dashed #b00020; color: #b00020; padding: 4pt 8pt; font-size: 9pt; }`,
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user