Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/test-smokes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ jobs:
sudo apt-get install -y libharfbuzz-dev libfribidi-dev
sudo apt-get install -y poppler-utils

- name: Install rsvg-convert for SVG conversion tests
# Only do it on linux runner, and only if we are running the relevant tests
if: runner.os == 'Linux' && contains(inputs.buckets, 'render-pdf-svg-conversion')
run: |
sudo apt-get update -y
sudo apt-get install -y librsvg2-bin

- name: Restore R packages
working-directory: tests
run: |
Expand Down
1 change: 1 addition & 0 deletions news/changelog-1.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ All changes included in 1.9:
### `pdf`

- ([#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.
- ([#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.
- ([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.

## Projects
Expand Down
30 changes: 27 additions & 3 deletions src/core/handlers/mermaid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { convertFromYaml } from "../lib/yaml-schema/from-yaml.ts";
import { readYamlFromString } from "../yaml.ts";
import { pandocHtmlBlock, pandocRawStr } from "../pandoc/codegen.ts";
import { LocalizedError } from "../lib/located-error.ts";
import { warning } from "../../deno_ral/log.ts";
import { info, warning } from "../../deno_ral/log.ts";
import { FormatDependency } from "../../config/types.ts";
import { mappedDiff } from "../mapped-text.ts";
import { escape } from "../../core/lodash.ts";
Expand Down Expand Up @@ -228,7 +228,7 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
?.[kFigResponsive];

const makeSvg = async () => {
setupMermaidSvgJsRuntime();
// Extract and process SVG
let svg = asMappedString(
(await handlerContext.extractHtml({
html: content,
Expand Down Expand Up @@ -306,7 +306,29 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
svg = mappedDiff(svg, oldSvgSrc);
}

if (isMarkdownOutput(handlerContext.options.format, ["gfm"])) {
// For formats that don't support JavaScript runtime (LaTeX/PDF, DOCX, Typst, etc.),
// write SVG file directly without postprocess script. This avoids LaTeX compilation
// errors from HTML script tags but may result in text clipping in diagrams with
// multi-line labels (see https://github.com/quarto-dev/quarto-cli/issues/1622).
if (
isMarkdownOutput(handlerContext.options.format, ["gfm"]) ||
!isJavascriptCompatible(handlerContext.options.format)
) {
// Emit info message for non-JS formats (excluding GFM which doesn't have the issue)
if (!isMarkdownOutput(handlerContext.options.format, ["gfm"])) {
let warning = `Using mermaid-format: svg with ${
handlerContext.options.format.pandoc.to ?? "non-HTML"
} format. Note: diagrams with multi-line text labels may experience clipping`;

// LaTeX-based formats also require external tooling
if (isLatexOutput(handlerContext.options.format.pandoc)) {
warning += " and requires external tooling (rsvg-convert or Inkscape)";
}

warning += ". Consider using mermaid-format: png if issues occur.";

info(warning);
}
const { sourceName, fullName } = handlerContext
.uniqueFigureName(
"mermaid-figure-",
Expand All @@ -323,6 +345,8 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
makeFigLink(sourceName, widthInInches, heightInInches, true),
);
} else {
// For JavaScript-compatible formats, use runtime postprocessing
setupMermaidSvgJsRuntime();
return this.build(
handlerContext,
cell,
Expand Down
3 changes: 2 additions & 1 deletion src/resources/filters/quarto-post/pdf-images.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ local function convert_svg(image)
local stem = pandoc.path.split_extension(image.src)
local output = stem .. '.pdf'
if not _quarto.file.exists(output) then
warn("Skipping SVG conversion for " .. path .. " because use-rsvg-convert is false, but required PDF file does not exist: " .. output)
warn("Skipping SVG conversion for " .. image.src .. " because use-rsvg-convert is false, but required PDF file does not exist: " .. output)
return nil
else
image.src = output
return image
Expand Down
24 changes: 24 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,30 @@ $env:QUARTO_TESTS_NO_CONFIG=$true

`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 `_`.

##### Controlling test execution with metadata

Smoke-all tests support metadata in the `_quarto` key to control when tests are run:

**Skip tests on CI:**

```yaml
_quarto:
tests-on-ci: false
```

**Skip tests on specific operating systems:**

```yaml
_quarto:
skip-on-os: linux # Skip only on Linux
skip-on-os: [linux, darwin] # Skip on Linux and macOS
skip-on-os: windows # Skip only on Windows
```

Valid OS values are: `linux`, `darwin` (macOS), `windows`

This is useful when tests require platform-specific dependencies or have known platform-specific issues that need separate investigation.

```bash
# run tests for all documents in docs/smoke-all/
./run-tests.sh smoke/smoke-all.tests.ts
Expand Down
129 changes: 129 additions & 0 deletions tests/docs/manual/mermaid-svg-pdf-tooling.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: "Manual Test: Mermaid SVG with PDF - External Tooling"
format:
pdf:
mermaid-format: svg
keep-tex: true
---

## Purpose

This document is for **manual testing** of mermaid-format:svg with PDF output,
specifically to verify behavior with different external tooling configurations.

**Why manual?** Automated CI tests cannot easily verify:
- Actual PDF generation with rsvg-convert
- Inkscape fallback behavior
- Platform-specific tooling issues (especially Windows)
- Full conversion pipeline end-to-end

## Simple Diagram

```{mermaid}
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Good]
B -->|No| D[Bad]
C --> E[End]
D --> E
```

## Multi-line Labels (Clipping Test)

This tests potential text clipping issues with multi-line labels:

```{mermaid}
graph TD
A["Line 1<br/>Line 2<br/>Line 3"] --> B["Another<br/>Multi<br/>Line<br/>Label"]
B --> C["Final<br/>Node"]
```

## Manual Testing Checklist

### Test 1: With rsvg-convert (Default)
- [ ] Ensure `rsvg-convert` is on PATH
- [ ] Run: `quarto render mermaid-svg-pdf-tooling.qmd`
- [ ] Verify: INFO message includes "requires external tooling"
- [ ] Verify: PDF generates successfully
- [ ] Check `.tex` file for `\includesvg` commands
- [ ] Verify: No script tags in LaTeX output
- [ ] Open PDF: Diagrams render correctly

### Test 2: Without rsvg-convert
- [ ] Remove rsvg-convert from PATH or rename binary temporarily
- [ ] Run: `quarto render mermaid-svg-pdf-tooling.qmd`
- [ ] Verify: INFO message about tooling requirement
- [ ] Verify: Error about missing rsvg-convert
- [ ] Expected behavior: Render fails with clear error

### Test 3: Inkscape Fallback (use-rsvg-convert: false)
Create variant document with:
```yaml
format:
pdf:
mermaid-format: svg
use-rsvg-convert: false
pdf-engine-opt: ["-shell-escape"]
keep-tex: true
```

- [ ] Ensure Inkscape is installed
- [ ] Run render with above config
- [ ] Verify: INFO message about tooling
- [ ] Verify: PDF generates via Inkscape (check logs)
- [ ] Check `.tex` file: uses `\includesvg` with Inkscape
- [ ] Open PDF: Diagrams render correctly

### Test 4: Windows-Specific
- [ ] Test on Windows with rsvg-convert (if available via Scoop/other)
- [ ] Test on Windows without rsvg-convert
- [ ] Test Inkscape fallback on Windows
- [ ] Document any Windows-specific issues

### Test 5: Comparison with PNG (Control)
Create variant with `mermaid-format: png`:

- [ ] Run: `quarto render` with png format
- [ ] Verify: NO warning about external tooling
- [ ] Verify: PDF generates successfully
- [ ] Quality comparison: SVG vs PNG in final PDF

## Expected Results Summary

| Scenario | Warning | PDF Generation | Notes |
|----------|---------|----------------|-------|
| rsvg-convert available | ✅ Yes | ✅ Success | Default path |
| No rsvg-convert | ✅ Yes | ❌ Error | Clear error message |
| Inkscape + shell-escape | ✅ Yes | ✅ Success | Fallback works |
| PNG format | ❌ No | ✅ Success | No tooling needed |

## Platform-Specific Notes

### Linux/Mac
- rsvg-convert typically available via package managers
- `librsvg` package usually includes rsvg-convert
- Inkscape widely available

### Windows
- rsvg-convert NOT easily available (complex setup)
- Can use Scoop: `scoop install rsvg-convert` (if r-bucket configured)
- Inkscape available but requires shell-escape configuration
- Most users should prefer PNG format on Windows

## Recording Results

After completing manual tests, document results in the beads issue notes field
for quarto-cli-idi. Include:

- Platforms tested (OS, versions)
- Which scenarios passed/failed
- Any unexpected behavior
- Screenshots if helpful
- Recommendations for users

## See Also

- Automated test: `tests/docs/smoke-all/2025/11/10/13661.qmd`
- DOCX test: `tests/docs/smoke-all/2025/11/14/mermaid-svg-docx.qmd`
- Beads issue: quarto-cli-idi
- GitHub issue: #13661
11 changes: 0 additions & 11 deletions tests/docs/smoke-all/2024/01/26/issue-8299-1.qmd

This file was deleted.

12 changes: 0 additions & 12 deletions tests/docs/smoke-all/2024/01/26/issue-8299-2.qmd

This file was deleted.

41 changes: 41 additions & 0 deletions tests/docs/smoke-all/2025/11/10/13661.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: "Mermaid SVG format with LaTeX - No script tags (#13661)"
# Test strategy: Use format:latex with use-rsvg-convert:false to:
# - Test mermaid-format:svg (the actual bug scenario)
# - Generate .tex file without compiling PDF (avoids needing rsvg-convert/Inkscape in CI)
# - Verify warning message about clipping + external tooling
# - Verify LaTeX uses \includesvg (not \includegraphics)
# - Verify NO HTML <script> tags in LaTeX output (the original bug)
format:
latex:
mermaid-format: svg
use-rsvg-convert: false
_quarto:
skip-on-os: linux
tests:
latex:
printsMessage:
level: INFO
regex: 'multi-line text labels may experience clipping.*requires external tooling'
ensureFileRegexMatches:
- ["\\\\includesvg(\\[.*?\\])?\\{[^}]*mermaid-figure-[^}]*\\}"]
- ["<script[^>]*>", "mermaid-postprocess-shim"]
---

## Test Diagram

Simple mermaid diagram to test SVG format with LaTeX output.

**What this tests:**
- Bug fix: HTML script tags should NOT appear in LaTeX output
- Warning: Should emit INFO about clipping AND requiring external tooling
- LaTeX structure: Should use `\includesvg` command for SVG files

```{mermaid}
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Good]
B -->|No| D[Bad]
C --> E[End]
D --> E
```
30 changes: 30 additions & 0 deletions tests/docs/smoke-all/2025/11/14/mermaid-svg-docx.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: "Mermaid SVG with DOCX - Clipping warning expected (#13661)"
format:
docx:
mermaid-format: svg
_quarto:
skip-on-os: linux
tests:
docx:
printsMessage:
level: INFO
regex: 'multi-line text labels may experience clipping'
---

## Test Diagram

This tests that DOCX format with mermaid-format:svg emits a warning about
potential text clipping issues (but NOT about external tooling requirements).

```{mermaid}
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Good]
B -->|No| D[Bad]
C --> E[End]
D --> E
```

Expected: Warning about text clipping in multi-line labels.
NOT expected: Warning about rsvg-convert/Inkscape (DOCX doesn't strictly require it).
37 changes: 37 additions & 0 deletions tests/docs/smoke-all/2025/11/18/mermaid-gfm-default.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: "GFM with default mermaid format"
format: gfm
_quarto:
tests:
gfm:
ensureFileRegexMatches:
- ['``` mermaid\s+graph'] # Verify raw mermaid code block is preserved (note space after ```)
- ['mermaid-figure-.*?\.svg'] # Should NOT have SVG files
printsMessage:
level: INFO
regex: 'Using mermaid-format'
negate: true # Should NOT print any mermaid-format warnings
---

## GFM Default Mermaid Test

This tests that GFM format uses GitHub's native mermaid code block support by default.

```{mermaid}
graph LR
A[Start] --> B{Decision}
B -->|Yes| C[Option 1]
B -->|No| D[Option 2]
C --> E[End]
D --> E
```

## Multi-line Labels Test

GitHub's native mermaid renderer should handle this:

```{mermaid}
graph TD
A["This is a very long label<br/>with multiple lines<br/>of text content"] --> B["Another multi-line<br/>label here"]
B --> C[Short]
```
Loading
Loading