From 9c4cf2855631e86510472d066c80f890b538a940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Wed, 12 Aug 2026 23:49:32 +0200 Subject: [PATCH] fix: emit mermaid diagrams in a raw html block A bare `---` line in a mermaid diagram, such as the closing delimiter of mermaid's own front matter, was read as a YAML front matter delimiter when quarto split the document into cells. It hid the rest of the document, so `ojs` cells placed after a mermaid diagram never reached the ojs compiler and rendered as plain code. Wrapping the `
` element in a `{=html}` raw block keeps the cell
splitter out of the diagram source. Pandoc's markdown reader already
produced the same `RawBlock (Format "html")` for the bare html block, so
the rendered output does not change.
Also removes the commented-out mermaid tooltip code. Its note said
"removed until we use mermaid 10.0.0"; the bundled runtime is 11.12.0 and
mermaid now creates the `.mermaidTooltip` div itself.
---
news/changelog-1.11.md | 4 +++
src/core/handlers/mermaid.ts | 26 ++++++++----------
tests/docs/smoke-all/2026/08/12/14765.qmd | 32 +++++++++++++++++++++++
3 files changed, 47 insertions(+), 15 deletions(-)
create mode 100644 tests/docs/smoke-all/2026/08/12/14765.qmd
diff --git a/news/changelog-1.11.md b/news/changelog-1.11.md
index 35f6ee3a280..640dc1e0d2d 100644
--- a/news/changelog-1.11.md
+++ b/news/changelog-1.11.md
@@ -5,3 +5,7 @@ All changes included in 1.11:
### `knitr`
- ([#14735](https://github.com/quarto-dev/quarto-cli/issues/14735)): Fix `cache-globals` rejecting arrays and booleans, so it now accepts the same forms as `cache-vars` and as knitr itself. Previously only a single string validated, which rejected both `cache-globals: [var_1, var_2]` and the documented `cache-globals: false`.
+
+## Other fixes and improvements
+
+- ([#14765](https://github.com/quarto-dev/quarto-cli/issues/14765)): Emit `mermaid` diagrams in a `{=html}` raw block. Quarto no longer reads a bare `---` line in the diagram as a YAML front matter delimiter. Before, such a line hid the rest of the document, and the `ojs` cells after it did not run. (author: @mcanouil) (author: @mcanouil)
diff --git a/src/core/handlers/mermaid.ts b/src/core/handlers/mermaid.ts
index 8bef0cd1846..c997a49177a 100644
--- a/src/core/handlers/mermaid.ts
+++ b/src/core/handlers/mermaid.ts
@@ -37,7 +37,7 @@ import {
import { Element } from "../deno-dom.ts";
import { convertFromYaml } from "../lib/yaml-schema/from-yaml.ts";
import { readYamlFromString } from "../yaml.ts";
-import { pandocHtmlBlock, pandocRawStr } from "../pandoc/codegen.ts";
+import { pandocCode, pandocHtmlBlock, pandocRawStr } from "../pandoc/codegen.ts";
import { LocalizedError } from "../lib/located-error.ts";
import { info, warning } from "../../deno_ral/log.ts";
import { FormatDependency } from "../../config/types.ts";
@@ -402,13 +402,6 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
// deno-lint-ignore require-await
const makeJs = async () => {
setupMermaidJsRuntime();
- // removed until we use mermaid 10.0.0
- //
- // const { baseName: tooltipName } = handlerContext
- // .uniqueFigureName(
- // "mermaid-tooltip-",
- // "",
- // );
const preAttrs = [];
if (options.label) {
preAttrs.push(`label="${options.label}"`);
@@ -426,16 +419,19 @@ mermaid.initialize(${JSON.stringify(mermaidOpts)});
attrs.reveal = true;
}
+ // the diagram source is user text emitted verbatim, and can contain lines
+ // that breakQuartoMd would read as yaml front matter delimiters (mermaid's
+ // own `---` config block, see https://github.com/quarto-dev/quarto-cli/issues/14765).
+ // a raw html block keeps the markdown splitter from looking inside it.
+ const rawHtmlBlock = pandocCode({
+ language: "=html",
+ contents: [preEl],
+ });
+
return this.build(
handlerContext,
cell,
- mappedConcat([
- preEl.mappedString(),
- // tooltips appear to be broken in mermaid 9.2.2?
- // They don't even work on their website: https://mermaid-js.github.io/mermaid/#/flowchart
- // we drop them for now.
- // `\n`,
- ]),
+ rawHtmlBlock.mappedString(),
options,
attrs,
new Set([kMermaidFormat]),
diff --git a/tests/docs/smoke-all/2026/08/12/14765.qmd b/tests/docs/smoke-all/2026/08/12/14765.qmd
new file mode 100644
index 00000000000..b27e2d52742
--- /dev/null
+++ b/tests/docs/smoke-all/2026/08/12/14765.qmd
@@ -0,0 +1,32 @@
+---
+title: "mermaid config front matter and ojs"
+format: html
+_quarto:
+ tests:
+ html:
+ ensureHtmlElements:
+ - ["pre.mermaid.mermaid-js", "div[id^=\"ojs-cell-\"]"]
+ - []
+---
+
+A `mermaid` cell can carry Mermaid's own `---` front matter to set diagram
+options such as `config`. That source is emitted verbatim into the intermediate
+markdown, where its closing `---` used to be read as the start of a YAML front
+matter block. Everything after it, including the `ojs` cell below, was swallowed
+into that never-terminated block, so no OJS cell was ever compiled and the cell
+rendered as plain code instead.
+
+```{mermaid}
+---
+config:
+ look: handDrawn
+---
+graph LR
+ A --> B
+```
+
+```{ojs}
+//| echo: true
+x = 2
+x ** 5
+```