quarto-dev / quarto-dev/quarto-cli
Mermaid `fig-cap` renders as `<p>` instead of `<figcaption>` when label is non-`fig-*`
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 6k
- Forks
- 458
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 41
Description
I have:
- searched the issue tracker for similar issues.
- installed the latest version of Quarto CLI.
- formatted my issue following the Bug Reports guide.
Bug description
Mermaid code cells with fig-cap are rendered as a semantic figure when there is no label, but adding a non-crossref label (for example label: my-diag) changes the caption output from <figcaption> to a plain <p>.
This causes inconsistent HTML semantics and styling for what is still a figure-like output.
Initially from:
- #13933
Steps to reproduce
---
title: "Mermaid caption semantics with non-fig label"
format: html
---
No label:
```{mermaid}
%%| fig-cap: "Diagram Caption"
flowchart TD
A([Test])
```
Non-fig label:
```{mermaid}
%%| fig-cap: "Diagram Caption"
%%| label: my-diag
flowchart TD
A([Test])
```
- Render the document to HTML with
quarto render. - Inspect the two rendered Mermaid blocks in the HTML output.
Actual behavior
The first block (caption only) renders with <figure> and <figcaption>.
The second block (caption plus label: my-diag) renders as a generic <div id="my-diag"> with caption in a <p>, with no <figcaption> element.
This happens because any label disables the fallback <figure>/<figcaption> path, but only recognised crossref labels (for example fig-*) are promoted to
figure references downstream.
Expected behavior
When fig-cap is present, caption markup should probably remain semantically consistent and use figure caption output.
Adding a non-fig-* label should not silently downgrade the caption to a plain paragraph.
If non-crossref labels are intentionally unsupported for mermaid figure, Quarto should probably warn clearly and still preserve predictable caption HTML.
Your environment
- IDE: Visual Studio Code.
- OS: macOS (Darwin).
Quarto check output
Quarto 99.9.9
[✓] Checking environment information...
Quarto cache location: /Users/mcanouil/Library/Caches/quarto
[✓] Checking versions of quarto binary dependencies...
Pandoc version 3.8.3: OK
Dart Sass version 1.87.0: OK
Deno version 2.4.5: OK
Typst version 0.14.2: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
Version: 99.9.9
commit: c792ec2170a142d767b9779fc01c986f17d49454
Path: /Users/mcanouil/Projects/quarto-dev/quarto-cli/package/dist/bin
[✓] Checking tools....................OK
TinyTeX: v2026.02
VeraPDF: 1.28.2
Chromium: (not installed)
Chrome Headless Shell: (not installed)
[✓] Checking LaTeX....................OK
Using: TinyTex
Path: /Users/mcanouil/Library/TinyTeX/bin/universal-darwin
Version: 2025
[✓] Checking Chrome Headless....................OK
Using: Chrome from QUARTO_CHROMIUM
Path: /Applications/Brave Browser.app/Contents/MacOS/Brave Browser
[✓] Checking basic markdown render....OK
[✓] Checking R installation...........OK
Version: 4.5.2
Path: /Library/Frameworks/R.framework/Resources
knitr: 1.50
rmarkdown: 2.30
[✓] Checking Knitr engine render......OK
[✓] Checking Python 3 installation....OK
Version: 3.14.2
Path: /opt/homebrew/opt/python@3.14/bin/python3.14
Jupyter: (None)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Mermaid reproduction document in the issue and render it with quarto render; inspect the generated HTML for the caption-only and non-fig label cases. Done means a fig-cap caption remains represented by a semantic <figcaption> when a non-fig-* label is present, or the behavior is clearly warned about and documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling, web-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100