diff --git a/.github/workflows/test-smokes.yml b/.github/workflows/test-smokes.yml index bbde6d158ad..b50359571df 100644 --- a/.github/workflows/test-smokes.yml +++ b/.github/workflows/test-smokes.yml @@ -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: | diff --git a/news/changelog-1.9.md b/news/changelog-1.9.md index be96d684a8c..da6de3c010c 100644 --- a/news/changelog-1.9.md +++ b/news/changelog-1.9.md @@ -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 diff --git a/src/core/handlers/mermaid.ts b/src/core/handlers/mermaid.ts index edb5484bc0d..8bef0cd1846 100644 --- a/src/core/handlers/mermaid.ts +++ b/src/core/handlers/mermaid.ts @@ -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"; @@ -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, @@ -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-", @@ -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, diff --git a/src/resources/filters/quarto-post/pdf-images.lua b/src/resources/filters/quarto-post/pdf-images.lua index fc21e3e0026..daf8a3e5fa7 100644 --- a/src/resources/filters/quarto-post/pdf-images.lua +++ b/src/resources/filters/quarto-post/pdf-images.lua @@ -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 diff --git a/tests/README.md b/tests/README.md index 5a6c200169f..99677e6d7b5 100644 --- a/tests/README.md +++ b/tests/README.md @@ -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 diff --git a/tests/docs/manual/mermaid-svg-pdf-tooling.qmd b/tests/docs/manual/mermaid-svg-pdf-tooling.qmd new file mode 100644 index 00000000000..593b364ac38 --- /dev/null +++ b/tests/docs/manual/mermaid-svg-pdf-tooling.qmd @@ -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
Line 2
Line 3"] --> B["Another
Multi
Line
Label"] + B --> C["Final
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 diff --git a/tests/docs/smoke-all/2024/01/26/issue-8299-1.qmd b/tests/docs/smoke-all/2024/01/26/issue-8299-1.qmd deleted file mode 100644 index b4227a1458b..00000000000 --- a/tests/docs/smoke-all/2024/01/26/issue-8299-1.qmd +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: issue-8299 -format: pdf -_quarto: - tests: - pdf: - fileExists: - outputPath: simple-svg.pdf ---- - -![An image we would otherwise trounce](simple-svg.svg) \ No newline at end of file diff --git a/tests/docs/smoke-all/2024/01/26/issue-8299-2.qmd b/tests/docs/smoke-all/2024/01/26/issue-8299-2.qmd deleted file mode 100644 index d2b57dd2f3f..00000000000 --- a/tests/docs/smoke-all/2024/01/26/issue-8299-2.qmd +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: issue-8299-2 -format: latex -use-rsvg-convert: false -_quarto: - tests: - latex: - ensureFileRegexMatches: - - ["simple-svg.pdf"] ---- - -![An SVG image that exists as PDF in the filesystem and will be transparently converted](simple-svg.svg) \ No newline at end of file diff --git a/tests/docs/smoke-all/2025/11/10/13661.qmd b/tests/docs/smoke-all/2025/11/10/13661.qmd new file mode 100644 index 00000000000..6068bfb2359 --- /dev/null +++ b/tests/docs/smoke-all/2025/11/10/13661.qmd @@ -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