Skip to content

Mermaid v11 diagrams render empty nodes — DOMParser('image/svg+xml') strips foreignObject HTML content #37

@thomnico

Description

@thomnico

Bug

The Mermaid zoom/pan JS pattern in references/css-patterns.md uses DOMParser.parseFromString(svg, 'image/svg+xml') to insert rendered Mermaid SVGs into the DOM. This silently destroys all node labels when using Mermaid v11+.

Root cause

Mermaid v11 renders node labels using <foreignObject> containing HTML <div> elements (not <text> elements). When DOMParser parses this SVG string as image/svg+xml, the HTML namespace content inside <foreignObject> is treated as invalid XML and stripped. The result:

  • Subgraph cluster frames render (their labels use a different mechanism)
  • Individual nodes render as empty boxes with no labels
  • Edges render but without visible connections to invisible nodes
  • The SVG has a valid viewBox and dimensions — it looks like a partial render

Reproduction

const result = await mermaid.render(id, 'graph LR\n  A["Hello"] --> B["World"]');

// BUG: 0 nodes visible — foreignObject HTML stripped
const parser = new DOMParser();
const doc = parser.parseFromString(result.svg, 'image/svg+xml');
console.log(doc.querySelectorAll('parsererror').length); // 1
console.log(doc.querySelectorAll('.node').length); // 0 or 1

// FIX: 2 nodes visible — mixed namespaces preserved
container.innerHTML = result.svg;
const svg = container.querySelector('svg');
console.log(svg.querySelectorAll('.node').length); // 2

Affected code

In references/css-patterns.md, the render function around the "JavaScript" section under "Mermaid Zoom Controls":

// CURRENT (broken with Mermaid v11)
const { svg } = await mermaid.render(id, code);
const parser = new DOMParser();
const doc = parser.parseFromString(svg, 'image/svg+xml');
canvas.appendChild(document.adoptNode(doc.documentElement));

// FIX
const { svg } = await mermaid.render(id, code);
canvas.innerHTML = svg;
const svgEl = canvas.querySelector('svg');

Verified with

  • Chrome 146 (headless + headed)
  • Mermaid v11 via CDN (https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js)
  • Diagnosed using WebDriverIO automation: before fix = 1 node/0 edges, after fix = 17 nodes/19 edges on a complex diagram with 6 subgraphs

Impact

Every diagram generated by the skill's template has invisible node labels. Only subgraph cluster titles are visible, making diagrams appear mostly empty.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions