Skip to content

Commit 50e6ef3

Browse files
authored
Merge pull request #13702 from quarto-dev/fix/mermaid-svg-beamer-13661
2 parents c9008d7 + a008226 commit 50e6ef3

File tree

22 files changed

+492
-33
lines changed

22 files changed

+492
-33
lines changed

.github/workflows/test-smokes.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ jobs:
139139
sudo apt-get install -y libharfbuzz-dev libfribidi-dev
140140
sudo apt-get install -y poppler-utils
141141
142+
- name: Install rsvg-convert for SVG conversion tests
143+
# Only do it on linux runner, and only if we are running the relevant tests
144+
if: runner.os == 'Linux' && contains(inputs.buckets, 'render-pdf-svg-conversion')
145+
run: |
146+
sudo apt-get update -y
147+
sudo apt-get install -y librsvg2-bin
148+
142149
- name: Restore R packages
143150
working-directory: tests
144151
run: |

news/changelog-1.9.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ All changes included in 1.9:
4141
### `pdf`
4242

4343
- ([#10291](https://github.com/quarto-dev/quarto-cli/issues/10291)): Fix detection of babel hyphenation warnings with straight-quote format instead of backtick-quote format.
44+
- ([#13661](https://github.com/quarto-dev/quarto-cli/issues/13661)): Fix LaTeX compilation errors when using `mermaid-format: svg` with PDF/LaTeX output. SVG diagrams are now written directly without HTML script tags. Note: `mermaid-format: png` is recommended for best compatibility. SVG format requires `rsvg-convert` (or Inkscape with `use-rsvg-convert: false`) in PATH for conversion to PDF, and may experience text clipping in diagrams with multi-line labels.
4445
- ([rstudio/tinytex-releases#49](https://github.com/rstudio/tinytex-releases/issues/49)): Fix detection of LuaTeX-ja missing file errors by matching both "File" and "file" in error messages.
4546
- ([#13667](https://github.com/quarto-dev/quarto-cli/issues/13667)): Fix LaTeX compilation error with Python error output containing caret characters.
4647

src/core/handlers/mermaid.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { convertFromYaml } from "../lib/yaml-schema/from-yaml.ts";
3939
import { readYamlFromString } from "../yaml.ts";
4040
import { pandocHtmlBlock, pandocRawStr } from "../pandoc/codegen.ts";
4141
import { LocalizedError } from "../lib/located-error.ts";
42-
import { warning } from "../../deno_ral/log.ts";
42+
import { info, warning } from "../../deno_ral/log.ts";
4343
import { FormatDependency } from "../../config/types.ts";
4444
import { mappedDiff } from "../mapped-text.ts";
4545
import { escape } from "../../core/lodash.ts";
@@ -228,7 +228,7 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
228228
?.[kFigResponsive];
229229

230230
const makeSvg = async () => {
231-
setupMermaidSvgJsRuntime();
231+
// Extract and process SVG
232232
let svg = asMappedString(
233233
(await handlerContext.extractHtml({
234234
html: content,
@@ -306,7 +306,29 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
306306
svg = mappedDiff(svg, oldSvgSrc);
307307
}
308308

309-
if (isMarkdownOutput(handlerContext.options.format, ["gfm"])) {
309+
// For formats that don't support JavaScript runtime (LaTeX/PDF, DOCX, Typst, etc.),
310+
// write SVG file directly without postprocess script. This avoids LaTeX compilation
311+
// errors from HTML script tags but may result in text clipping in diagrams with
312+
// multi-line labels (see https://github.com/quarto-dev/quarto-cli/issues/1622).
313+
if (
314+
isMarkdownOutput(handlerContext.options.format, ["gfm"]) ||
315+
!isJavascriptCompatible(handlerContext.options.format)
316+
) {
317+
// Emit info message for non-JS formats (excluding GFM which doesn't have the issue)
318+
if (!isMarkdownOutput(handlerContext.options.format, ["gfm"])) {
319+
let warning = `Using mermaid-format: svg with ${
320+
handlerContext.options.format.pandoc.to ?? "non-HTML"
321+
} format. Note: diagrams with multi-line text labels may experience clipping`;
322+
323+
// LaTeX-based formats also require external tooling
324+
if (isLatexOutput(handlerContext.options.format.pandoc)) {
325+
warning += " and requires external tooling (rsvg-convert or Inkscape)";
326+
}
327+
328+
warning += ". Consider using mermaid-format: png if issues occur.";
329+
330+
info(warning);
331+
}
310332
const { sourceName, fullName } = handlerContext
311333
.uniqueFigureName(
312334
"mermaid-figure-",
@@ -323,6 +345,8 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
323345
makeFigLink(sourceName, widthInInches, heightInInches, true),
324346
);
325347
} else {
348+
// For JavaScript-compatible formats, use runtime postprocessing
349+
setupMermaidSvgJsRuntime();
326350
return this.build(
327351
handlerContext,
328352
cell,

src/resources/filters/quarto-post/pdf-images.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ local function convert_svg(image)
3636
local stem = pandoc.path.split_extension(image.src)
3737
local output = stem .. '.pdf'
3838
if not _quarto.file.exists(output) then
39-
warn("Skipping SVG conversion for " .. path .. " because use-rsvg-convert is false, but required PDF file does not exist: " .. output)
39+
warn("Skipping SVG conversion for " .. image.src .. " because use-rsvg-convert is false, but required PDF file does not exist: " .. output)
40+
return nil
4041
else
4142
image.src = output
4243
return image

tests/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,30 @@ $env:QUARTO_TESTS_NO_CONFIG=$true
120120

121121
`docs/smoke-all/` is a specific folder to run some tests written directly within `.qmd`, `.md` or `.ipynb` files (but files starting with `_` will be ignored). They are run through the `smoke/smoke-all.tests.ts` script. To ease running smoke-all tests, `run-tests.sh` has a special behavior where it will run `./smoke/smoke-all.tests.ts` when passed a `.qmd`, `.md` or `.ipynb` file, not starting with `_`.
122122

123+
##### Controlling test execution with metadata
124+
125+
Smoke-all tests support metadata in the `_quarto` key to control when tests are run:
126+
127+
**Skip tests on CI:**
128+
129+
```yaml
130+
_quarto:
131+
tests-on-ci: false
132+
```
133+
134+
**Skip tests on specific operating systems:**
135+
136+
```yaml
137+
_quarto:
138+
skip-on-os: linux # Skip only on Linux
139+
skip-on-os: [linux, darwin] # Skip on Linux and macOS
140+
skip-on-os: windows # Skip only on Windows
141+
```
142+
143+
Valid OS values are: `linux`, `darwin` (macOS), `windows`
144+
145+
This is useful when tests require platform-specific dependencies or have known platform-specific issues that need separate investigation.
146+
123147
```bash
124148
# run tests for all documents in docs/smoke-all/
125149
./run-tests.sh smoke/smoke-all.tests.ts
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
---
2+
title: "Manual Test: Mermaid SVG with PDF - External Tooling"
3+
format:
4+
pdf:
5+
mermaid-format: svg
6+
keep-tex: true
7+
---
8+
9+
## Purpose
10+
11+
This document is for **manual testing** of mermaid-format:svg with PDF output,
12+
specifically to verify behavior with different external tooling configurations.
13+
14+
**Why manual?** Automated CI tests cannot easily verify:
15+
- Actual PDF generation with rsvg-convert
16+
- Inkscape fallback behavior
17+
- Platform-specific tooling issues (especially Windows)
18+
- Full conversion pipeline end-to-end
19+
20+
## Simple Diagram
21+
22+
```{mermaid}
23+
graph TD
24+
A[Start] --> B{Decision}
25+
B -->|Yes| C[Good]
26+
B -->|No| D[Bad]
27+
C --> E[End]
28+
D --> E
29+
```
30+
31+
## Multi-line Labels (Clipping Test)
32+
33+
This tests potential text clipping issues with multi-line labels:
34+
35+
```{mermaid}
36+
graph TD
37+
A["Line 1<br/>Line 2<br/>Line 3"] --> B["Another<br/>Multi<br/>Line<br/>Label"]
38+
B --> C["Final<br/>Node"]
39+
```
40+
41+
## Manual Testing Checklist
42+
43+
### Test 1: With rsvg-convert (Default)
44+
- [ ] Ensure `rsvg-convert` is on PATH
45+
- [ ] Run: `quarto render mermaid-svg-pdf-tooling.qmd`
46+
- [ ] Verify: INFO message includes "requires external tooling"
47+
- [ ] Verify: PDF generates successfully
48+
- [ ] Check `.tex` file for `\includesvg` commands
49+
- [ ] Verify: No script tags in LaTeX output
50+
- [ ] Open PDF: Diagrams render correctly
51+
52+
### Test 2: Without rsvg-convert
53+
- [ ] Remove rsvg-convert from PATH or rename binary temporarily
54+
- [ ] Run: `quarto render mermaid-svg-pdf-tooling.qmd`
55+
- [ ] Verify: INFO message about tooling requirement
56+
- [ ] Verify: Error about missing rsvg-convert
57+
- [ ] Expected behavior: Render fails with clear error
58+
59+
### Test 3: Inkscape Fallback (use-rsvg-convert: false)
60+
Create variant document with:
61+
```yaml
62+
format:
63+
pdf:
64+
mermaid-format: svg
65+
use-rsvg-convert: false
66+
pdf-engine-opt: ["-shell-escape"]
67+
keep-tex: true
68+
```
69+
70+
- [ ] Ensure Inkscape is installed
71+
- [ ] Run render with above config
72+
- [ ] Verify: INFO message about tooling
73+
- [ ] Verify: PDF generates via Inkscape (check logs)
74+
- [ ] Check `.tex` file: uses `\includesvg` with Inkscape
75+
- [ ] Open PDF: Diagrams render correctly
76+
77+
### Test 4: Windows-Specific
78+
- [ ] Test on Windows with rsvg-convert (if available via Scoop/other)
79+
- [ ] Test on Windows without rsvg-convert
80+
- [ ] Test Inkscape fallback on Windows
81+
- [ ] Document any Windows-specific issues
82+
83+
### Test 5: Comparison with PNG (Control)
84+
Create variant with `mermaid-format: png`:
85+
86+
- [ ] Run: `quarto render` with png format
87+
- [ ] Verify: NO warning about external tooling
88+
- [ ] Verify: PDF generates successfully
89+
- [ ] Quality comparison: SVG vs PNG in final PDF
90+
91+
## Expected Results Summary
92+
93+
| Scenario | Warning | PDF Generation | Notes |
94+
|----------|---------|----------------|-------|
95+
| rsvg-convert available | ✅ Yes | ✅ Success | Default path |
96+
| No rsvg-convert | ✅ Yes | ❌ Error | Clear error message |
97+
| Inkscape + shell-escape | ✅ Yes | ✅ Success | Fallback works |
98+
| PNG format | ❌ No | ✅ Success | No tooling needed |
99+
100+
## Platform-Specific Notes
101+
102+
### Linux/Mac
103+
- rsvg-convert typically available via package managers
104+
- `librsvg` package usually includes rsvg-convert
105+
- Inkscape widely available
106+
107+
### Windows
108+
- rsvg-convert NOT easily available (complex setup)
109+
- Can use Scoop: `scoop install rsvg-convert` (if r-bucket configured)
110+
- Inkscape available but requires shell-escape configuration
111+
- Most users should prefer PNG format on Windows
112+
113+
## Recording Results
114+
115+
After completing manual tests, document results in the beads issue notes field
116+
for quarto-cli-idi. Include:
117+
118+
- Platforms tested (OS, versions)
119+
- Which scenarios passed/failed
120+
- Any unexpected behavior
121+
- Screenshots if helpful
122+
- Recommendations for users
123+
124+
## See Also
125+
126+
- Automated test: `tests/docs/smoke-all/2025/11/10/13661.qmd`
127+
- DOCX test: `tests/docs/smoke-all/2025/11/14/mermaid-svg-docx.qmd`
128+
- Beads issue: quarto-cli-idi
129+
- GitHub issue: #13661

tests/docs/smoke-all/2024/01/26/issue-8299-1.qmd

Lines changed: 0 additions & 11 deletions
This file was deleted.

tests/docs/smoke-all/2024/01/26/issue-8299-2.qmd

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
title: "Mermaid SVG format with LaTeX - No script tags (#13661)"
3+
# Test strategy: Use format:latex with use-rsvg-convert:false to:
4+
# - Test mermaid-format:svg (the actual bug scenario)
5+
# - Generate .tex file without compiling PDF (avoids needing rsvg-convert/Inkscape in CI)
6+
# - Verify warning message about clipping + external tooling
7+
# - Verify LaTeX uses \includesvg (not \includegraphics)
8+
# - Verify NO HTML <script> tags in LaTeX output (the original bug)
9+
format:
10+
latex:
11+
mermaid-format: svg
12+
use-rsvg-convert: false
13+
_quarto:
14+
skip-on-os: linux
15+
tests:
16+
latex:
17+
printsMessage:
18+
level: INFO
19+
regex: 'multi-line text labels may experience clipping.*requires external tooling'
20+
ensureFileRegexMatches:
21+
- ["\\\\includesvg(\\[.*?\\])?\\{[^}]*mermaid-figure-[^}]*\\}"]
22+
- ["<script[^>]*>", "mermaid-postprocess-shim"]
23+
---
24+
25+
## Test Diagram
26+
27+
Simple mermaid diagram to test SVG format with LaTeX output.
28+
29+
**What this tests:**
30+
- Bug fix: HTML script tags should NOT appear in LaTeX output
31+
- Warning: Should emit INFO about clipping AND requiring external tooling
32+
- LaTeX structure: Should use `\includesvg` command for SVG files
33+
34+
```{mermaid}
35+
graph TD
36+
A[Start] --> B{Decision}
37+
B -->|Yes| C[Good]
38+
B -->|No| D[Bad]
39+
C --> E[End]
40+
D --> E
41+
```
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: "Mermaid SVG with DOCX - Clipping warning expected (#13661)"
3+
format:
4+
docx:
5+
mermaid-format: svg
6+
_quarto:
7+
skip-on-os: linux
8+
tests:
9+
docx:
10+
printsMessage:
11+
level: INFO
12+
regex: 'multi-line text labels may experience clipping'
13+
---
14+
15+
## Test Diagram
16+
17+
This tests that DOCX format with mermaid-format:svg emits a warning about
18+
potential text clipping issues (but NOT about external tooling requirements).
19+
20+
```{mermaid}
21+
graph TD
22+
A[Start] --> B{Decision}
23+
B -->|Yes| C[Good]
24+
B -->|No| D[Bad]
25+
C --> E[End]
26+
D --> E
27+
```
28+
29+
Expected: Warning about text clipping in multi-line labels.
30+
NOT expected: Warning about rsvg-convert/Inkscape (DOCX doesn't strictly require it).

0 commit comments

Comments
 (0)