From 84915234dc8bb0d729098bd72b69a96ba24bfcbc Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 29 Dec 2025 18:27:35 +0530 Subject: [PATCH 01/62] fix: Add markdown-specific behavior on top of the common rendering changes. on-behalf-of: @Mermaid-Chart --- .changeset/swift-cloths-run.md | 5 +++ .../rendering/flowchart-v2.spec.js | 4 +- .../integration/rendering/flowchart.spec.js | 45 +++++++++++++++++++ .../mermaid/src/diagrams/flowchart/flowDb.ts | 19 +++++++- .../mermaid/src/diagrams/flowchart/types.ts | 4 +- .../mermaid/src/diagrams/kanban/kanbanDb.ts | 2 + .../mermaid/src/diagrams/mindmap/mindmapDb.ts | 1 + .../src/diagrams/mindmap/mindmapTypes.ts | 1 + .../mermaid/src/diagrams/state/dataFetcher.ts | 1 + .../mermaid/src/diagrams/state/stateDb.ts | 1 + .../rendering-elements/clusters.js | 26 ++++++++--- .../rendering-elements/edges.js | 24 +++++++--- .../rendering-elements/shapes/util.ts | 35 +++++++++++---- packages/mermaid/src/types.ts | 1 + 14 files changed, 143 insertions(+), 26 deletions(-) create mode 100644 .changeset/swift-cloths-run.md diff --git a/.changeset/swift-cloths-run.md b/.changeset/swift-cloths-run.md new file mode 100644 index 00000000000..31663779c6b --- /dev/null +++ b/.changeset/swift-cloths-run.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Add markdown-specific behavior on top of the common rendering changes. diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index cd3676fbf3d..bf7ff5b8c6b 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1186,8 +1186,8 @@ end end githost["Github, Gitlab, BitBucket, etc."] githost2["\`Github, Gitlab, BitBucket, etc.\`"] - a["1."] - b["- x"] + a["\`1.\`"] + b["\`- x\`"] `; it('should render raw strings', () => { diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index 5e19843771a..c5c76d910e7 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -1004,3 +1004,48 @@ graph TD ); }); }); +it('#5824: should be able to render string and markdown labels', () => { + imgSnapshotTest( + ` +flowchart TB + mermaid{"What is\nyourmermaid version?"} --> v10["<11"] --"\`<**1**1\`"--> fine["No bug"] + mermaid --> v11[">= v11"] -- ">= v11" --> broken["Affected by https://github.com/mermaid-js/mermaid/issues/5824"] + subgraph subgraph1["\`How to fix **fix**\`"] + broken --> B["B"] + end + githost["Github, Gitlab, BitBucket, etc."] + githost2["\`Github, Gitlab, BitBucket, etc.\`"] + a["1."] + b["- x"] + `, + { + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); +}); +it('69: should render subgraphs with adhoc list headings', () => { + imgSnapshotTest( + ` + graph TB + subgraph "1. first" + a1-->a2 + end + subgraph 2. second + b1-->b2 + end + `, + { fontFamily: 'courier' } + ); +}); +it('70: should render subgraphs with markdown headings', () => { + imgSnapshotTest( + ` + graph TB + subgraph "\`**strong**\`" + a1-->a2 + end + `, + { fontFamily: 'courier' } + ); +}); diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index 632633730a5..2329f0aced0 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -85,6 +85,17 @@ export class FlowDB implements DiagramDB { return common.sanitizeText(txt, this.config); } + private sanitizeNodeLabelType(labelType?: string) { + switch (labelType) { + case 'markdown': + case 'string': + case 'text': + return labelType; + default: + return 'markdown'; + } + } + /** * Function to lookup domId from id in the graph definition. * @@ -208,6 +219,7 @@ export class FlowDB implements DiagramDB { if (doc?.label) { vertex.text = doc?.label; + vertex.labelType = this.sanitizeNodeLabelType(doc?.labelType); } if (doc?.icon) { vertex.icon = doc?.icon; @@ -267,7 +279,7 @@ export class FlowDB implements DiagramDB { if (edge.text.startsWith('"') && edge.text.endsWith('"')) { edge.text = edge.text.substring(1, edge.text.length - 1); } - edge.labelType = linkTextObj.type; + edge.labelType = this.sanitizeNodeLabelType(linkTextObj.type); } if (type !== undefined) { @@ -702,7 +714,7 @@ You have to call mermaid.initialize.` title: title.trim(), classes: [], dir, - labelType: _title.type, + labelType: this.sanitizeNodeLabelType(_title?.type), }; log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir); @@ -1012,6 +1024,7 @@ You have to call mermaid.initialize.` const baseNode = { id: vertex.id, label: vertex.text, + labelType: vertex.labelType, labelStyle: '', parentId, padding: config.flowchart?.padding || 8, @@ -1088,6 +1101,7 @@ You have to call mermaid.initialize.` id: subGraph.id, label: subGraph.title, labelStyle: '', + labelType: subGraph.labelType, parentId: parentDB.get(subGraph.id), padding: 8, cssCompiledStyles: this.getCompiledStyles(subGraph.classes), @@ -1119,6 +1133,7 @@ You have to call mermaid.initialize.` end: rawEdge.end, type: rawEdge.type ?? 'normal', label: rawEdge.text, + labelType: rawEdge.labelType, labelpos: 'c', thickness: rawEdge.stroke, minlen: rawEdge.length, diff --git a/packages/mermaid/src/diagrams/flowchart/types.ts b/packages/mermaid/src/diagrams/flowchart/types.ts index 54156091b16..ac2d0401518 100644 --- a/packages/mermaid/src/diagrams/flowchart/types.ts +++ b/packages/mermaid/src/diagrams/flowchart/types.ts @@ -29,7 +29,7 @@ export interface FlowVertex { domId: string; haveCallback?: boolean; id: string; - labelType: 'text'; + labelType: 'markdown' | 'string' | 'text'; link?: string; linkTarget?: string; props?: any; @@ -62,7 +62,7 @@ export interface FlowEdge { style?: string[]; length?: number; text: string; - labelType: 'text'; + labelType: 'markdown' | 'string' | 'text'; classes: string[]; id?: string; animation?: 'fast' | 'slow'; diff --git a/packages/mermaid/src/diagrams/kanban/kanbanDb.ts b/packages/mermaid/src/diagrams/kanban/kanbanDb.ts index a9bcbb7b814..24edf1457ff 100644 --- a/packages/mermaid/src/diagrams/kanban/kanbanDb.ts +++ b/packages/mermaid/src/diagrams/kanban/kanbanDb.ts @@ -62,6 +62,7 @@ const getData = function () { const node = { id: section.id, label: sanitizeText(section.label ?? '', conf), + labelType: 'markdown', isGroup: true, ticket: section.ticket, shape: 'kanbanSection', @@ -76,6 +77,7 @@ const getData = function () { id: item.id, parentId: section.id, label: sanitizeText(item.label ?? '', conf), + labelType: 'markdown', isGroup: false, ticket: item?.ticket, priority: item?.priority, diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts index 07f945d61e7..6daaad78c91 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts @@ -261,6 +261,7 @@ export class MindmapDB { id: node.id.toString(), domId: 'node_' + node.id.toString(), label: node.descr, + labelType: 'markdown', isGroup: false, shape: getShapeFromType(node.type), width: node.width, diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts index aeed2358fd1..c467ae0dff4 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts @@ -16,6 +16,7 @@ export interface MindmapNode { x?: number; y?: number; isRoot?: boolean; + labelType?: string; } export type FilledMindMapNode = RequiredDeep; diff --git a/packages/mermaid/src/diagrams/state/dataFetcher.ts b/packages/mermaid/src/diagrams/state/dataFetcher.ts index f38084899de..a77de5a895a 100644 --- a/packages/mermaid/src/diagrams/state/dataFetcher.ts +++ b/packages/mermaid/src/diagrams/state/dataFetcher.ts @@ -291,6 +291,7 @@ export const dataFetcher = ( rx: 10, ry: 10, look, + labelType: 'markdown', }; // Clear the label for dividers who have no description diff --git a/packages/mermaid/src/diagrams/state/stateDb.ts b/packages/mermaid/src/diagrams/state/stateDb.ts index e40b06a9c92..adb15d661d3 100644 --- a/packages/mermaid/src/diagrams/state/stateDb.ts +++ b/packages/mermaid/src/diagrams/state/stateDb.ts @@ -161,6 +161,7 @@ export interface NodeData { centerLabel?: boolean; position?: string; description?: string | string[]; + labelType?: string; } export interface Edge { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 0062bf49148..6d02599a3b6 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -30,11 +30,25 @@ const rect = async (parent, node) => { // Create the label and insert it after the rect const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); - const text = await createText(labelEl, node.label, { - style: node.labelStyle, - useHtmlLabels, - isNode: true, - }); + let text; + if (node.labelType === 'markdown') { + text = await createText(labelEl, node.label, { + style: node.labelStyle, + useHtmlLabels, + isNode: true, + width: node.width, + }); + } else { + const labelElement = await createLabel( + node.label, + node.labelStyle, + false, + true, + false, + node.width + ); + text = labelEl.node()?.appendChild(labelElement); + } // Get the size of the label let bbox = text.getBBox(); @@ -177,6 +191,8 @@ const roundedWithTitle = async (parent, node) => { // add the rect const outerRectG = shapeSvg.insert('g', ':first-child'); + const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); + // Create the label and insert it after the rect const label = shapeSvg.insert('g').attr('class', 'cluster-label'); let innerRect = shapeSvg.append('rect'); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 2f037748b6d..a7b1b8a855b 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -54,12 +54,24 @@ export const insertEdgeLabel = async (elem, edge) => { const { labelStyles } = styles2String(edge); edge.labelStyle = labelStyles; - const labelElement = await createText(elem, edge.label, { - style: edge.labelStyle, - useHtmlLabels, - addSvgBackground: true, - isNode: false, - }); + const labelElement = + edge.labelType === 'markdown' + ? await createText(elem, edge.label, { + style: getLabelStyles(edge.labelStyle), + useHtmlLabels, + addSvgBackground: true, + isNode: false, + width, + }) + : await createLabel( + edge.label, + getLabelStyles(edge.labelStyle), + undefined, + false, + true, + width + ); + log.info('abc82', edge, edge.labelType); // Create outer g, edgeLabel, this will be positioned after graph layout diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index 8b571906859..bd30c94fc59 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -1,9 +1,10 @@ +import createLabel from '../createLabel.js'; import { createText } from '../../createText.js'; import type { Node } from '../../types.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { getEffectiveHtmlLabels } from '../../../config.js'; import { select } from 'd3'; -import { evaluate, sanitizeText } from '../../../diagrams/common/common.js'; +import { evaluate, hasKatex, sanitizeText } from '../../../diagrams/common/common.js'; import { decodeEntities, handleUndefinedAttr } from '../../../utils.js'; import type { D3Selection, Point } from '../../../types.js'; import { configureLabelImages } from './labelImageUtils.js'; @@ -41,14 +42,30 @@ export const labelHelper = async ( label = typeof node.label === 'string' ? node.label : node.label[0]; } - const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { - useHtmlLabels, - width: node.width || getConfig().flowchart?.wrappingWidth, - // @ts-expect-error -- This is currently not used. Should this be `classes` instead? - cssClasses: 'markdown-node-label', - style: node.labelStyle, - addSvgBackground: !!node.icon || !!node.img, - }); + let text; + const addBackground = !!node.icon || !!node.img; + const width = node.width || getConfig().flowchart?.wrappingWidth; + if (node.labelType === 'markdown' || hasKatex(label)) { + text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { + useHtmlLabels, + width, + // @ts-expect-error -- This is currently not used. Should this be `classes` instead? + cssClasses: 'markdown-node-label', + style: node.labelStyle, + addSvgBackground: addBackground, + }); + } else { + const labelElement = await createLabel( + sanitizeText(decodeEntities(label), getConfig()), + node.labelStyle, + false, + true, + addBackground, + width + ); + text = labelEl.node()?.appendChild(labelElement); + } + // Get the size of the label let bbox = text.getBBox(); const halfPadding = (node?.padding ?? 0) / 2; diff --git a/packages/mermaid/src/types.ts b/packages/mermaid/src/types.ts index 49940410642..5b4713d6913 100644 --- a/packages/mermaid/src/types.ts +++ b/packages/mermaid/src/types.ts @@ -11,6 +11,7 @@ export interface NodeMetaData { priority: 'Very High' | 'High' | 'Medium' | 'Low' | 'Very Low'; assigned?: string; ticket?: string; + labelType?: string; } export interface ParticipantMetaData { From 5a8ddd0a7e843122882247f82825cbfd8d1d5b72 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 20 Jan 2026 17:15:08 +0530 Subject: [PATCH 02/62] fix: streamline label creation in labelHelper function --- .../rendering-util/rendering-elements/shapes/util.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index bd30c94fc59..763c42bb635 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -55,15 +55,13 @@ export const labelHelper = async ( addSvgBackground: addBackground, }); } else { - const labelElement = await createLabel( + text = await createLabel( + labelEl, sanitizeText(decodeEntities(label), getConfig()), - node.labelStyle, + node.labelStyle || '', false, - true, - addBackground, - width + true ); - text = labelEl.node()?.appendChild(labelElement); } // Get the size of the label From 2cc90ef4e42af308aca7882f44d43137fa892d41 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 20 Jan 2026 18:13:37 +0530 Subject: [PATCH 03/62] fix: remove unused HTML label handling and streamline edge label creation on-behalf-of: @Mermaid-Chart --- .../rendering-elements/clusters.js | 2 - .../rendering-elements/edges.js | 44 ++++++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 6d02599a3b6..b2f17497ad1 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -191,8 +191,6 @@ const roundedWithTitle = async (parent, node) => { // add the rect const outerRectG = shapeSvg.insert('g', ':first-child'); - const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); - // Create the label and insert it after the rect const label = shapeSvg.insert('g').attr('class', 'cluster-label'); let innerRect = shapeSvg.append('rect'); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index a7b1b8a855b..a5660d46992 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -51,36 +51,30 @@ export const getLabelStyles = (styleArray) => { export const insertEdgeLabel = async (elem, edge) => { let useHtmlLabels = getEffectiveHtmlLabels(getConfig()); + const width = edge.width || 200; const { labelStyles } = styles2String(edge); edge.labelStyle = labelStyles; + + // Create outer g, edgeLabel, this will be positioned after graph layout + const edgeLabel = elem.insert('g').attr('class', 'edgeLabel'); + + // Create inner g, label, this will be positioned now for centering the text + const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); + const labelElement = edge.labelType === 'markdown' - ? await createText(elem, edge.label, { + ? await createText(label, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, isNode: false, width, }) - : await createLabel( - edge.label, - getLabelStyles(edge.labelStyle), - undefined, - false, - true, - width - ); + : await createLabel(label, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); log.info('abc82', edge, edge.labelType); - // Create outer g, edgeLabel, this will be positioned after graph layout - const edgeLabel = elem.insert('g').attr('class', 'edgeLabel'); - - // Create inner g, label, this will be positioned now for centering the text - const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); - label.node().appendChild(labelElement); - // Center the label let bbox = labelElement.getBBox(); if (useHtmlLabels) { @@ -107,7 +101,9 @@ export const insertEdgeLabel = async (elem, edge) => { const startLabelElement = await createLabel( inner, edge.startLabelLeft, - getLabelStyles(edge.labelStyle) + getLabelStyles(edge.labelStyle) || '', + false, + false ); fo = startLabelElement; let slBox = startLabelElement.getBBox(); @@ -130,9 +126,11 @@ export const insertEdgeLabel = async (elem, edge) => { const startEdgeLabelRight = elem.insert('g').attr('class', 'edgeTerminals'); const inner = startEdgeLabelRight.insert('g').attr('class', 'inner'); const startLabelElement = await createLabel( - startEdgeLabelRight, + inner, edge.startLabelRight, - getLabelStyles(edge.labelStyle) + getLabelStyles(edge.labelStyle) || '', + false, + false ); fo = startLabelElement; inner.node().appendChild(startLabelElement); @@ -159,7 +157,9 @@ export const insertEdgeLabel = async (elem, edge) => { const endLabelElement = await createLabel( inner, edge.endLabelLeft, - getLabelStyles(edge.labelStyle) + getLabelStyles(edge.labelStyle) || '', + false, + false ); fo = endLabelElement; let slBox = endLabelElement.getBBox(); @@ -188,7 +188,9 @@ export const insertEdgeLabel = async (elem, edge) => { const endLabelElement = await createLabel( inner, edge.endLabelRight, - getLabelStyles(edge.labelStyle) + getLabelStyles(edge.labelStyle) || '', + false, + false ); fo = endLabelElement; let slBox = endLabelElement.getBBox(); From ef2e43d09437389fe9135dbbc4fc36ee02b514fe Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 12:50:41 +0000 Subject: [PATCH 04/62] [autofix.ci] apply automated fixes --- docs/config/setup/mermaid/interfaces/ParseOptions.md | 4 ++-- docs/config/setup/mermaid/interfaces/ParseResult.md | 6 +++--- docs/config/setup/mermaid/interfaces/RenderResult.md | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/config/setup/mermaid/interfaces/ParseOptions.md b/docs/config/setup/mermaid/interfaces/ParseOptions.md index 0ff3bf00423..9d30198de41 100644 --- a/docs/config/setup/mermaid/interfaces/ParseOptions.md +++ b/docs/config/setup/mermaid/interfaces/ParseOptions.md @@ -10,7 +10,7 @@ # Interface: ParseOptions -Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89) +Defined in: [packages/mermaid/src/types.ts:90](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L90) ## Properties @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mer > `optional` **suppressErrors**: `boolean` -Defined in: [packages/mermaid/src/types.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L94) +Defined in: [packages/mermaid/src/types.ts:95](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L95) If `true`, parse will return `false` instead of throwing error when the diagram is invalid. The `parseError` function will not be called. diff --git a/docs/config/setup/mermaid/interfaces/ParseResult.md b/docs/config/setup/mermaid/interfaces/ParseResult.md index 66e5de194cf..17f2ede3089 100644 --- a/docs/config/setup/mermaid/interfaces/ParseResult.md +++ b/docs/config/setup/mermaid/interfaces/ParseResult.md @@ -10,7 +10,7 @@ # Interface: ParseResult -Defined in: [packages/mermaid/src/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L97) +Defined in: [packages/mermaid/src/types.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L98) ## Properties @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:97](https://github.com/mermaid-js/mer > **config**: [`MermaidConfig`](MermaidConfig.md) -Defined in: [packages/mermaid/src/types.ts:105](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L105) +Defined in: [packages/mermaid/src/types.ts:106](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L106) The config passed as YAML frontmatter or directives @@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives > **diagramType**: `string` -Defined in: [packages/mermaid/src/types.ts:101](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L101) +Defined in: [packages/mermaid/src/types.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L102) The diagram type, e.g. 'flowchart', 'sequence', etc. diff --git a/docs/config/setup/mermaid/interfaces/RenderResult.md b/docs/config/setup/mermaid/interfaces/RenderResult.md index 9d6771ad1c7..054e4fbec37 100644 --- a/docs/config/setup/mermaid/interfaces/RenderResult.md +++ b/docs/config/setup/mermaid/interfaces/RenderResult.md @@ -10,7 +10,7 @@ # Interface: RenderResult -Defined in: [packages/mermaid/src/types.ts:115](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L115) +Defined in: [packages/mermaid/src/types.ts:116](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L116) ## Properties @@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:115](https://github.com/mermaid-js/me > `optional` **bindFunctions**: (`element`) => `void` -Defined in: [packages/mermaid/src/types.ts:133](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L133) +Defined in: [packages/mermaid/src/types.ts:134](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L134) Bind function to be called after the svg has been inserted into the DOM. This is necessary for adding event listeners to the elements in the svg. @@ -45,7 +45,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present. > **diagramType**: `string` -Defined in: [packages/mermaid/src/types.ts:123](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L123) +Defined in: [packages/mermaid/src/types.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L124) The diagram type, e.g. 'flowchart', 'sequence', etc. @@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc. > **svg**: `string` -Defined in: [packages/mermaid/src/types.ts:119](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L119) +Defined in: [packages/mermaid/src/types.ts:120](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L120) The svg code for the rendered graph. From 50fa149c76c14589dd2ded67214fb94ed3e6e3fe Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 20 Jan 2026 19:13:03 +0530 Subject: [PATCH 05/62] fix: simplify label creation in rect function by directly assigning text variable on-behalf-of: @Mermaid-Chart --- .../src/rendering-util/rendering-elements/clusters.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index b2f17497ad1..a2b9d2ee987 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -39,15 +39,7 @@ const rect = async (parent, node) => { width: node.width, }); } else { - const labelElement = await createLabel( - node.label, - node.labelStyle, - false, - true, - false, - node.width - ); - text = labelEl.node()?.appendChild(labelElement); + text = await createLabel(labelEl, node.label, node.labelStyle || '', false, true); } // Get the size of the label From 287b94dfc83a1fd56474a4b65e26f3218beecd65 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 22 Jan 2026 00:19:05 +0530 Subject: [PATCH 06/62] fix: update useHtmlLabels logic in labelHelper function on-behalf-of: @Mermaid-Chart --- .../src/rendering-util/rendering-elements/shapes/util.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index 763c42bb635..1fd0fd0b0c7 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -4,7 +4,7 @@ import type { Node } from '../../types.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { getEffectiveHtmlLabels } from '../../../config.js'; import { select } from 'd3'; -import { evaluate, hasKatex, sanitizeText } from '../../../diagrams/common/common.js'; +import { hasKatex, sanitizeText } from '../../../diagrams/common/common.js'; import { decodeEntities, handleUndefinedAttr } from '../../../utils.js'; import type { D3Selection, Point } from '../../../types.js'; import { configureLabelImages } from './labelImageUtils.js'; @@ -15,7 +15,7 @@ export const labelHelper = async ( _classes?: string ) => { let cssClasses; - const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.htmlLabels); + const useHtmlLabels = node.useHtmlLabels || getEffectiveHtmlLabels(getConfig()); if (!_classes) { cssClasses = 'node default'; } else { From 99be5502c217ccf4b1ad718b3b99644adee32480 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 22 Jan 2026 09:30:41 +0530 Subject: [PATCH 07/62] fix: refactor label handling for markdown in clusters and edges on-behalf-of: @Mermaid-Chart --- .../rendering-elements/clusters.js | 15 +++------- .../rendering-elements/edges.js | 24 +++++++++------ .../rendering-elements/shapes/util.ts | 29 ++++++++++--------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index a2b9d2ee987..24843646bf8 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -30,17 +30,10 @@ const rect = async (parent, node) => { // Create the label and insert it after the rect const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); - let text; - if (node.labelType === 'markdown') { - text = await createText(labelEl, node.label, { - style: node.labelStyle, - useHtmlLabels, - isNode: true, - width: node.width, - }); - } else { - text = await createLabel(labelEl, node.label, node.labelStyle || '', false, true); - } + const text = + node.labelType === 'markdown' + ? createText(labelEl, node.labelText, { style: node.labelStyle, useHtmlLabels }, siteConfig) + : await createLabel(labelEl, node.labelText, node.labelStyle, undefined, true); // Get the size of the label let bbox = text.getBBox(); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index a5660d46992..b2361c40f40 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -51,7 +51,7 @@ export const getLabelStyles = (styleArray) => { export const insertEdgeLabel = async (elem, edge) => { let useHtmlLabels = getEffectiveHtmlLabels(getConfig()); - const width = edge.width || 200; + const config = getConfig(); const { labelStyles } = styles2String(edge); edge.labelStyle = labelStyles; @@ -64,14 +64,20 @@ export const insertEdgeLabel = async (elem, edge) => { const labelElement = edge.labelType === 'markdown' - ? await createText(label, edge.label, { - style: getLabelStyles(edge.labelStyle), - useHtmlLabels, - addSvgBackground: true, - isNode: false, - width, - }) - : await createLabel(label, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); + ? // TODO: the createText function returns a `Promise`, so do we need an wait here? + createText( + elem, + edge.label, + { + style: edge.labelStyle, + useHtmlLabels, + addSvgBackground: true, + }, + config + ) + : await createLabel(elem, edge.label, edge.labelStyle); + + label.node().appendChild(labelElement); log.info('abc82', edge, edge.labelType); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index 1fd0fd0b0c7..620e1a7b136 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -4,7 +4,7 @@ import type { Node } from '../../types.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { getEffectiveHtmlLabels } from '../../../config.js'; import { select } from 'd3'; -import { hasKatex, sanitizeText } from '../../../diagrams/common/common.js'; +import { sanitizeText } from '../../../diagrams/common/common.js'; import { decodeEntities, handleUndefinedAttr } from '../../../utils.js'; import type { D3Selection, Point } from '../../../types.js'; import { configureLabelImages } from './labelImageUtils.js'; @@ -14,6 +14,7 @@ export const labelHelper = async ( node: Node, _classes?: string ) => { + const config = getConfig(); let cssClasses; const useHtmlLabels = node.useHtmlLabels || getEffectiveHtmlLabels(getConfig()); if (!_classes) { @@ -43,22 +44,22 @@ export const labelHelper = async ( } let text; - const addBackground = !!node.icon || !!node.img; - const width = node.width || getConfig().flowchart?.wrappingWidth; - if (node.labelType === 'markdown' || hasKatex(label)) { - text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { - useHtmlLabels, - width, - // @ts-expect-error -- This is currently not used. Should this be `classes` instead? - cssClasses: 'markdown-node-label', - style: node.labelStyle, - addSvgBackground: addBackground, - }); + if (node.labelType === 'markdown') { + text = createText( + label, + sanitizeText(decodeEntities(label), config), + { + useHtmlLabels, + width: node.width || config.flowchart?.wrappingWidth, + classes: 'markdown-node-label', + }, + config + ); } else { text = await createLabel( labelEl, - sanitizeText(decodeEntities(label), getConfig()), - node.labelStyle || '', + sanitizeText(decodeEntities(label), config), + node.labelStyle ?? '', false, true ); From f7de94291b708d2965d996e732f79188a5443ab6 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 22 Jan 2026 10:43:18 +0530 Subject: [PATCH 08/62] Revert "fix: refactor label handling for markdown in clusters and edges" This reverts commit 99be5502c217ccf4b1ad718b3b99644adee32480. --- .../rendering-elements/clusters.js | 15 +++++++--- .../rendering-elements/edges.js | 24 ++++++--------- .../rendering-elements/shapes/util.ts | 29 +++++++++---------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 24843646bf8..a2b9d2ee987 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -30,10 +30,17 @@ const rect = async (parent, node) => { // Create the label and insert it after the rect const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); - const text = - node.labelType === 'markdown' - ? createText(labelEl, node.labelText, { style: node.labelStyle, useHtmlLabels }, siteConfig) - : await createLabel(labelEl, node.labelText, node.labelStyle, undefined, true); + let text; + if (node.labelType === 'markdown') { + text = await createText(labelEl, node.label, { + style: node.labelStyle, + useHtmlLabels, + isNode: true, + width: node.width, + }); + } else { + text = await createLabel(labelEl, node.label, node.labelStyle || '', false, true); + } // Get the size of the label let bbox = text.getBBox(); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index b2361c40f40..a5660d46992 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -51,7 +51,7 @@ export const getLabelStyles = (styleArray) => { export const insertEdgeLabel = async (elem, edge) => { let useHtmlLabels = getEffectiveHtmlLabels(getConfig()); - const config = getConfig(); + const width = edge.width || 200; const { labelStyles } = styles2String(edge); edge.labelStyle = labelStyles; @@ -64,20 +64,14 @@ export const insertEdgeLabel = async (elem, edge) => { const labelElement = edge.labelType === 'markdown' - ? // TODO: the createText function returns a `Promise`, so do we need an wait here? - createText( - elem, - edge.label, - { - style: edge.labelStyle, - useHtmlLabels, - addSvgBackground: true, - }, - config - ) - : await createLabel(elem, edge.label, edge.labelStyle); - - label.node().appendChild(labelElement); + ? await createText(label, edge.label, { + style: getLabelStyles(edge.labelStyle), + useHtmlLabels, + addSvgBackground: true, + isNode: false, + width, + }) + : await createLabel(label, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); log.info('abc82', edge, edge.labelType); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index 620e1a7b136..1fd0fd0b0c7 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -4,7 +4,7 @@ import type { Node } from '../../types.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { getEffectiveHtmlLabels } from '../../../config.js'; import { select } from 'd3'; -import { sanitizeText } from '../../../diagrams/common/common.js'; +import { hasKatex, sanitizeText } from '../../../diagrams/common/common.js'; import { decodeEntities, handleUndefinedAttr } from '../../../utils.js'; import type { D3Selection, Point } from '../../../types.js'; import { configureLabelImages } from './labelImageUtils.js'; @@ -14,7 +14,6 @@ export const labelHelper = async ( node: Node, _classes?: string ) => { - const config = getConfig(); let cssClasses; const useHtmlLabels = node.useHtmlLabels || getEffectiveHtmlLabels(getConfig()); if (!_classes) { @@ -44,22 +43,22 @@ export const labelHelper = async ( } let text; - if (node.labelType === 'markdown') { - text = createText( - label, - sanitizeText(decodeEntities(label), config), - { - useHtmlLabels, - width: node.width || config.flowchart?.wrappingWidth, - classes: 'markdown-node-label', - }, - config - ); + const addBackground = !!node.icon || !!node.img; + const width = node.width || getConfig().flowchart?.wrappingWidth; + if (node.labelType === 'markdown' || hasKatex(label)) { + text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { + useHtmlLabels, + width, + // @ts-expect-error -- This is currently not used. Should this be `classes` instead? + cssClasses: 'markdown-node-label', + style: node.labelStyle, + addSvgBackground: addBackground, + }); } else { text = await createLabel( labelEl, - sanitizeText(decodeEntities(label), config), - node.labelStyle ?? '', + sanitizeText(decodeEntities(label), getConfig()), + node.labelStyle || '', false, true ); From 649ee28947912efda90c3817768d4146161e9efb Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Sat, 24 Jan 2026 14:28:36 +0530 Subject: [PATCH 09/62] fix: set labelType to markdown for class relations on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/class/classDb.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index 70489164460..b4e9c33ef3a 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -737,6 +737,7 @@ export class ClassDB implements DiagramDB { style: classRelation.style || '', pattern: classRelation.relation.lineType == 1 ? 'dashed' : 'solid', look: config.look, + labelType: 'markdown', }; edges.push(edge); } From 931f3dfd5635d4bbffe5edd620993a5b2af95629 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Sat, 24 Jan 2026 15:22:12 +0530 Subject: [PATCH 10/62] fix: set labelType to markdown for relationship edges on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/er/erDb.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/diagrams/er/erDb.ts b/packages/mermaid/src/diagrams/er/erDb.ts index 95f2210b7cb..1cfd2b301a1 100644 --- a/packages/mermaid/src/diagrams/er/erDb.ts +++ b/packages/mermaid/src/diagrams/er/erDb.ts @@ -235,6 +235,7 @@ export class ErDB implements DiagramDB { arrowTypeEnd: relationship.relSpec.cardA.toLowerCase(), pattern: relationship.relSpec.relType == 'IDENTIFYING' ? 'solid' : 'dashed', look: config.look, + labelType: 'markdown', }; edges.push(edge); } From a2587bce62641f0f8bba03722119d34743d5f48d Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 27 Jan 2026 11:27:13 +0530 Subject: [PATCH 11/62] fix: set labelType to markdown for requirement edges on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/requirement/requirementDb.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/diagrams/requirement/requirementDb.ts b/packages/mermaid/src/diagrams/requirement/requirementDb.ts index 25dabdb53af..050062ff267 100644 --- a/packages/mermaid/src/diagrams/requirement/requirementDb.ts +++ b/packages/mermaid/src/diagrams/requirement/requirementDb.ts @@ -331,6 +331,7 @@ export class RequirementDB implements DiagramDB { arrowTypeStart: isContains ? 'requirement_contains' : '', arrowTypeEnd: isContains ? '' : 'requirement_arrow', look: config.look, + labelType: 'markdown', }; edges.push(edge); From 4893a9d854a444ba1bebb0391ab1c92fd0078e6f Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 27 Jan 2026 11:47:00 +0530 Subject: [PATCH 12/62] fix: update label type to markdown for state diagram edge labels on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/state/stateCommon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/state/stateCommon.ts b/packages/mermaid/src/diagrams/state/stateCommon.ts index b1de78405ae..dd6efbe6ba3 100644 --- a/packages/mermaid/src/diagrams/state/stateCommon.ts +++ b/packages/mermaid/src/diagrams/state/stateCommon.ts @@ -32,7 +32,7 @@ export const DIVIDER_TYPE = 'divider'; export const G_EDGE_STYLE = 'fill:none'; export const G_EDGE_ARROWHEADSTYLE = 'fill: #333'; export const G_EDGE_LABELPOS = 'c'; -export const G_EDGE_LABELTYPE = 'text'; +export const G_EDGE_LABELTYPE = 'markdown'; export const G_EDGE_THICKNESS = 'normal'; export const SHAPE_STATE = 'rect'; From 443ff410cebc39375016b59a9d45605398ffcfea Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 27 Jan 2026 14:17:41 +0530 Subject: [PATCH 13/62] fix: update erBox to use getEffectiveHtmlLabels for label rendering on-behalf-of: @Mermaid-Chart --- .../rendering-elements/shapes/erBox.ts | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts index 9dd4c90e2b2..68668162f2c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts @@ -4,10 +4,10 @@ import type { Node } from '../../types.js'; import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { drawRect } from './drawRect.js'; -import { getConfig } from '../../../config.js'; +import { getConfig, getEffectiveHtmlLabels } from '../../../config.js'; import type { EntityNode } from '../../../diagrams/er/erTypes.js'; import { createText } from '../../createText.js'; -import { evaluate, parseGenericTypes } from '../../../diagrams/common/common.js'; +import { parseGenericTypes } from '../../../diagrams/common/common.js'; import { select } from 'd3'; import { calculateTextWidth } from '../../../utils.js'; import type { MermaidConfig } from '../../../config.type.js'; @@ -35,7 +35,8 @@ export async function erBox(parent: D3Selection } const config = getConfig(); - node.useHtmlLabels = config.htmlLabels; + const useHtmlLabels = getEffectiveHtmlLabels(config); + node.useHtmlLabels = useHtmlLabels; let PADDING = config.er?.diagramPadding ?? 10; let TEXT_PADDING = config.er?.entityPadding ?? 6; @@ -61,7 +62,7 @@ export async function erBox(parent: D3Selection const shapeSvg = await drawRect(parent, node, options); // drawRect doesn't center non-htmlLabels correctly as of now, so translate label - if (!evaluate(config.htmlLabels)) { + if (!useHtmlLabels) { const textElement = shapeSvg.select('text'); const bbox = (textElement.node() as SVGTextElement)?.getBBox(); textElement.attr('transform', `translate(${-bbox.width / 2}, 0)`); @@ -69,7 +70,7 @@ export async function erBox(parent: D3Selection return shapeSvg; } - if (!config.htmlLabels) { + if (!useHtmlLabels) { PADDING *= 1.25; TEXT_PADDING *= 1.25; } @@ -85,7 +86,16 @@ export async function erBox(parent: D3Selection .attr('class', cssClasses) .attr('id', node.domId || node.id); - const nameBBox = await addText(shapeSvg, node.label ?? '', config, 0, 0, ['name'], labelStyles); + const nameBBox = await addText( + shapeSvg, + node.label ?? '', + config, + useHtmlLabels, + 0, + 0, + ['name'], + labelStyles + ); nameBBox.height += TEXT_PADDING; let yOffset = 0; const yOffsets = []; @@ -101,6 +111,7 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.type, config, + useHtmlLabels, 0, yOffset, ['attribute-type'], @@ -111,6 +122,7 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.name, config, + useHtmlLabels, 0, yOffset, ['attribute-name'], @@ -121,6 +133,7 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.keys.join(), config, + useHtmlLabels, 0, yOffset, ['attribute-keys'], @@ -131,6 +144,7 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.comment, config, + useHtmlLabels, 0, yOffset, ['attribute-comment'], @@ -318,6 +332,7 @@ async function addText( shapeSvg: D3Selection, labelText: string, config: MermaidConfig, + useHtmlLabels: boolean, translateX = 0, translateY = 0, classes: string[] = [], @@ -343,7 +358,7 @@ async function addText( { width: calculateTextWidth(labelText, config) + 100, style, - useHtmlLabels: config.htmlLabels, + useHtmlLabels, }, config ) @@ -360,7 +375,7 @@ async function addText( } let bbox = text.getBBox(); - if (evaluate(config.htmlLabels)) { + if (useHtmlLabels) { const div = text.children[0]; div.style.textAlign = 'start'; const dv = select(text); From 5ac588ae95a6ee8c40e5d91101ae1dd79d90bfce Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 27 Jan 2026 14:46:33 +0530 Subject: [PATCH 14/62] Revert "fix: update erBox to use getEffectiveHtmlLabels for label rendering" This reverts commit 443ff410cebc39375016b59a9d45605398ffcfea. --- .../rendering-elements/shapes/erBox.ts | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts index 68668162f2c..9dd4c90e2b2 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts @@ -4,10 +4,10 @@ import type { Node } from '../../types.js'; import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { drawRect } from './drawRect.js'; -import { getConfig, getEffectiveHtmlLabels } from '../../../config.js'; +import { getConfig } from '../../../config.js'; import type { EntityNode } from '../../../diagrams/er/erTypes.js'; import { createText } from '../../createText.js'; -import { parseGenericTypes } from '../../../diagrams/common/common.js'; +import { evaluate, parseGenericTypes } from '../../../diagrams/common/common.js'; import { select } from 'd3'; import { calculateTextWidth } from '../../../utils.js'; import type { MermaidConfig } from '../../../config.type.js'; @@ -35,8 +35,7 @@ export async function erBox(parent: D3Selection } const config = getConfig(); - const useHtmlLabels = getEffectiveHtmlLabels(config); - node.useHtmlLabels = useHtmlLabels; + node.useHtmlLabels = config.htmlLabels; let PADDING = config.er?.diagramPadding ?? 10; let TEXT_PADDING = config.er?.entityPadding ?? 6; @@ -62,7 +61,7 @@ export async function erBox(parent: D3Selection const shapeSvg = await drawRect(parent, node, options); // drawRect doesn't center non-htmlLabels correctly as of now, so translate label - if (!useHtmlLabels) { + if (!evaluate(config.htmlLabels)) { const textElement = shapeSvg.select('text'); const bbox = (textElement.node() as SVGTextElement)?.getBBox(); textElement.attr('transform', `translate(${-bbox.width / 2}, 0)`); @@ -70,7 +69,7 @@ export async function erBox(parent: D3Selection return shapeSvg; } - if (!useHtmlLabels) { + if (!config.htmlLabels) { PADDING *= 1.25; TEXT_PADDING *= 1.25; } @@ -86,16 +85,7 @@ export async function erBox(parent: D3Selection .attr('class', cssClasses) .attr('id', node.domId || node.id); - const nameBBox = await addText( - shapeSvg, - node.label ?? '', - config, - useHtmlLabels, - 0, - 0, - ['name'], - labelStyles - ); + const nameBBox = await addText(shapeSvg, node.label ?? '', config, 0, 0, ['name'], labelStyles); nameBBox.height += TEXT_PADDING; let yOffset = 0; const yOffsets = []; @@ -111,7 +101,6 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.type, config, - useHtmlLabels, 0, yOffset, ['attribute-type'], @@ -122,7 +111,6 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.name, config, - useHtmlLabels, 0, yOffset, ['attribute-name'], @@ -133,7 +121,6 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.keys.join(), config, - useHtmlLabels, 0, yOffset, ['attribute-keys'], @@ -144,7 +131,6 @@ export async function erBox(parent: D3Selection shapeSvg, attribute.comment, config, - useHtmlLabels, 0, yOffset, ['attribute-comment'], @@ -332,7 +318,6 @@ async function addText( shapeSvg: D3Selection, labelText: string, config: MermaidConfig, - useHtmlLabels: boolean, translateX = 0, translateY = 0, classes: string[] = [], @@ -358,7 +343,7 @@ async function addText( { width: calculateTextWidth(labelText, config) + 100, style, - useHtmlLabels, + useHtmlLabels: config.htmlLabels, }, config ) @@ -375,7 +360,7 @@ async function addText( } let bbox = text.getBBox(); - if (useHtmlLabels) { + if (evaluate(config.htmlLabels)) { const div = text.children[0]; div.style.textAlign = 'start'; const dv = select(text); From ab2d919126f534a51c1d41f9b87821a40bf8c3f3 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 27 Jan 2026 15:03:34 +0530 Subject: [PATCH 15/62] fix: enhance labelHelper to support markdown labels and improve label width handling on-behalf-of: @Mermaid-Chart --- .../rendering-elements/shapes/util.ts | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index 1fd0fd0b0c7..a13cd37d42e 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -1,10 +1,9 @@ -import createLabel from '../createLabel.js'; import { createText } from '../../createText.js'; import type { Node } from '../../types.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; -import { getEffectiveHtmlLabels } from '../../../config.js'; +import { evaluate, getEffectiveHtmlLabels } from '../../../config.js'; import { select } from 'd3'; -import { hasKatex, sanitizeText } from '../../../diagrams/common/common.js'; +import { sanitizeText } from '../../../diagrams/common/common.js'; import { decodeEntities, handleUndefinedAttr } from '../../../utils.js'; import type { D3Selection, Point } from '../../../types.js'; import { configureLabelImages } from './labelImageUtils.js'; @@ -15,7 +14,7 @@ export const labelHelper = async ( _classes?: string ) => { let cssClasses; - const useHtmlLabels = node.useHtmlLabels || getEffectiveHtmlLabels(getConfig()); + const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.htmlLabels); if (!_classes) { cssClasses = 'node default'; } else { @@ -42,27 +41,24 @@ export const labelHelper = async ( label = typeof node.label === 'string' ? node.label : node.label[0]; } - let text; const addBackground = !!node.icon || !!node.img; - const width = node.width || getConfig().flowchart?.wrappingWidth; - if (node.labelType === 'markdown' || hasKatex(label)) { - text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { + const isMarkdown = node.labelType === 'markdown'; + const text = await createText( + labelEl, + sanitizeText(decodeEntities(label), getConfig()), + { useHtmlLabels, - width, + width: + node.width ?? + (isMarkdown ? getConfig().flowchart?.wrappingWidth : Number.POSITIVE_INFINITY), // @ts-expect-error -- This is currently not used. Should this be `classes` instead? - cssClasses: 'markdown-node-label', + cssClasses: isMarkdown ? 'markdown-node-label' : undefined, style: node.labelStyle, addSvgBackground: addBackground, - }); - } else { - text = await createLabel( - labelEl, - sanitizeText(decodeEntities(label), getConfig()), - node.labelStyle || '', - false, - true - ); - } + markdown: isMarkdown, + }, + getConfig() + ); // Get the size of the label let bbox = text.getBBox(); From a3841e8f7c28307a5fcaf6f4d4868f2650ce5d2e Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 27 Jan 2026 22:38:05 +0530 Subject: [PATCH 16/62] fix: set labelType to markdown for note labels on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/state/dataFetcher.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/diagrams/state/dataFetcher.ts b/packages/mermaid/src/diagrams/state/dataFetcher.ts index a77de5a895a..7a80dea1be0 100644 --- a/packages/mermaid/src/diagrams/state/dataFetcher.ts +++ b/packages/mermaid/src/diagrams/state/dataFetcher.ts @@ -312,6 +312,7 @@ export const dataFetcher = ( labelStyle: '', shape: SHAPE_NOTE, label: parsedItem.note.text, + labelType: 'markdown', cssClasses: CSS_DIAGRAM_NOTE, // useHtmlLabels: false, cssStyles: [], From 31abe0c2e555bca4963f4758fcc030fb469c8921 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 27 Jan 2026 23:46:15 +0530 Subject: [PATCH 17/62] fix: update labelHelper to use logical OR for width calculation and set markdown class for labels(fixes mindmap diffs) on-behalf-of: @Mermaid-Chart --- .../src/rendering-util/rendering-elements/shapes/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index a13cd37d42e..430572d3198 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -49,7 +49,7 @@ export const labelHelper = async ( { useHtmlLabels, width: - node.width ?? + node.width || (isMarkdown ? getConfig().flowchart?.wrappingWidth : Number.POSITIVE_INFINITY), // @ts-expect-error -- This is currently not used. Should this be `classes` instead? cssClasses: isMarkdown ? 'markdown-node-label' : undefined, From 80de539949a5fca862a38773f9ef6906e0ed5066 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 28 Jan 2026 13:08:44 +0530 Subject: [PATCH 18/62] fix: update edge label handling by removing default width and improving label style application on-behalf-of: @Mermaid-Chart --- .../mermaid/src/rendering-util/rendering-elements/edges.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index a5660d46992..9f58d3e6a96 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -51,8 +51,6 @@ export const getLabelStyles = (styleArray) => { export const insertEdgeLabel = async (elem, edge) => { let useHtmlLabels = getEffectiveHtmlLabels(getConfig()); - const width = edge.width || 200; - const { labelStyles } = styles2String(edge); edge.labelStyle = labelStyles; @@ -69,7 +67,6 @@ export const insertEdgeLabel = async (elem, edge) => { useHtmlLabels, addSvgBackground: true, isNode: false, - width, }) : await createLabel(label, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); From 1e064387b3e3d2a60414f69a7c87e7947e0048ff Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 28 Jan 2026 14:50:22 +0530 Subject: [PATCH 19/62] fix: append label element to edge label node for proper rendering on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/rendering-util/rendering-elements/edges.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 9f58d3e6a96..cff49905c20 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -70,6 +70,7 @@ export const insertEdgeLabel = async (elem, edge) => { }) : await createLabel(label, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); + label.node().appendChild(labelElement); log.info('abc82', edge, edge.labelType); // Center the label From 2a045faa39af0ea06c397f616fdbb577d6e788d9 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 28 Jan 2026 15:03:29 +0530 Subject: [PATCH 20/62] fix: update insertEdgeLabel to pass the element to createText for markdown labels on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/rendering-util/rendering-elements/edges.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index cff49905c20..89cc90a0913 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -62,7 +62,7 @@ export const insertEdgeLabel = async (elem, edge) => { const labelElement = edge.labelType === 'markdown' - ? await createText(label, edge.label, { + ? await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, From bc5382e43944431e9b9b3c0513537f13fe1a44e9 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 28 Jan 2026 16:13:02 +0530 Subject: [PATCH 21/62] fix: update insertEdgeLabel to pass the element for label creation on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/rendering-util/rendering-elements/edges.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 89cc90a0913..b4cd841654d 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -68,7 +68,7 @@ export const insertEdgeLabel = async (elem, edge) => { addSvgBackground: true, isNode: false, }) - : await createLabel(label, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); + : await createLabel(elem, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); label.node().appendChild(labelElement); log.info('abc82', edge, edge.labelType); From 5f3b5a875c713b14646ba21db53649cfd61699c4 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 28 Jan 2026 19:50:47 +0530 Subject: [PATCH 22/62] fix: enhance insertEdgeLabel to support markdown and adjust width handling on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/dagre-wrapper/edges.js | 32 ++++++++++--------- .../rendering-elements/edges.js | 19 +++++------ 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index 0af13bde442..8aaafe62dda 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -21,27 +21,29 @@ export const clear = () => { export const insertEdgeLabel = async (elem, edge) => { const config = getConfig(); const useHtmlLabels = getEffectiveHtmlLabels(config); - // Create the actual text element - const labelElement = - edge.labelType === 'markdown' - ? // TODO: the createText function returns a `Promise`, so do we need an wait here? - createText( - elem, - edge.label, - { - style: edge.labelStyle, - useHtmlLabels, - addSvgBackground: true, - }, - config - ) - : await createLabel(elem, edge.label, edge.labelStyle); // Create outer g, edgeLabel, this will be positioned after graph layout const edgeLabel = elem.insert('g').attr('class', 'edgeLabel'); // Create inner g, label, this will be positioned now for centering the text const label = edgeLabel.insert('g').attr('class', 'label'); + + // Create the actual text element + const isMarkdown = edge.labelType === 'markdown'; + const labelElement = await createText( + elem, + edge.label, + { + style: edge.labelStyle, + useHtmlLabels, + addSvgBackground: true, + markdown: isMarkdown, + // If using markdown, wrap using default width + width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, + }, + config + ); + label.node().appendChild(labelElement); // Center the label diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index b4cd841654d..83c52412d5c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -60,15 +60,16 @@ export const insertEdgeLabel = async (elem, edge) => { // Create inner g, label, this will be positioned now for centering the text const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); - const labelElement = - edge.labelType === 'markdown' - ? await createText(elem, edge.label, { - style: getLabelStyles(edge.labelStyle), - useHtmlLabels, - addSvgBackground: true, - isNode: false, - }) - : await createLabel(elem, edge.label, getLabelStyles(edge.labelStyle) || '', false, false); + const isMarkdown = edge.labelType === 'markdown'; + const labelElement = await createText(elem, edge.label, { + style: getLabelStyles(edge.labelStyle), + useHtmlLabels, + addSvgBackground: true, + isNode: false, + markdown: isMarkdown, + // If using markdown, wrap using default width + width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, + }); label.node().appendChild(labelElement); log.info('abc82', edge, edge.labelType); From 25e14498413f6a6619daf8fb5c56a46dfcec1e34 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 28 Jan 2026 21:42:52 +0530 Subject: [PATCH 23/62] fix: wrap non-markdown text in paragraph tags for proper HTML formatting on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/rendering-util/createText.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts index d5f1e100bea..8ad6f1cb3b9 100644 --- a/packages/mermaid/src/rendering-util/createText.ts +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -257,7 +257,9 @@ export const createText = async ( if (useHtmlLabels) { // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const htmlText = markdown ? markdownToHTML(text, config) : text.replace(/\\n|\n/g, '
'); + const htmlText = markdown + ? markdownToHTML(text, config) + : `

${text.replace(/\\n|\n/g, '
')}

`; const decodedReplacedText = await replaceIconSubstring(decodeEntities(htmlText), config); //for Katex the text could contain escaped characters, \\relax that should be transformed to \relax From fa2f6c01985bc70622b4ad58ab7821f049c32202 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 29 Jan 2026 12:38:48 +0530 Subject: [PATCH 24/62] chore: update changeset --- .changeset/swift-cloths-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/swift-cloths-run.md b/.changeset/swift-cloths-run.md index 31663779c6b..000b58fc2b7 100644 --- a/.changeset/swift-cloths-run.md +++ b/.changeset/swift-cloths-run.md @@ -2,4 +2,4 @@ 'mermaid': patch --- -fix: Add markdown-specific behavior on top of the common rendering changes. +fix: Restore proper rendering of non-markdown flowchart labels with multiline support From 904a589a46b3c49c2ecfbb611a051414ad95d2fb Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 29 Jan 2026 13:39:26 +0530 Subject: [PATCH 25/62] fix: add nonMarkdownToHTML function for proper HTML conversion of non-markdown text on-behalf-of: @Mermaid-Chart --- .../mermaid/src/rendering-util/createText.ts | 5 ++-- .../rendering-util/handle-markdown-text.ts | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts index 8ad6f1cb3b9..165fa77bd97 100644 --- a/packages/mermaid/src/rendering-util/createText.ts +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -9,6 +9,7 @@ import { log } from '../logger.js'; import { markdownToHTML, markdownToLines, + nonMarkdownToHTML, nonMarkdownToLines, } from '../rendering-util/handle-markdown-text.js'; import { decodeEntities } from '../utils.js'; @@ -257,9 +258,7 @@ export const createText = async ( if (useHtmlLabels) { // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const htmlText = markdown - ? markdownToHTML(text, config) - : `

${text.replace(/\\n|\n/g, '
')}

`; + const htmlText = markdown ? markdownToHTML(text, config) : nonMarkdownToHTML(text); const decodedReplacedText = await replaceIconSubstring(decodeEntities(htmlText), config); //for Katex the text could contain escaped characters, \\relax that should be transformed to \relax diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts index 1eafd910286..22476eb889e 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -84,6 +84,35 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M return lines; } +/** + * Counterpart to {@link markdownToHTML} for non-markdown text. + * + * Non-markdown text is not wrapped normally, and users can use an explicit `\n` + * sequence to add a line break. + * + * @param text - Non-markdown text to convert to HTML. + */ +export function nonMarkdownToHTML(text: string) { + if (!text) { + return ''; + } + /* + * Edge labels may have double backgrounds if `addBackground` is `true`. + * This `

` wrapper aligns with how {@link markdownToHTML} wraps its output, and + * ensures both backgrounds are the same size. + * + * We can't set it for empty labels, otherwise it causes rendering changes. + */ + return `

${ + /** + * Replace new lines with
tags. + * + * Unlike in markdown text, `\n` sequences are treated as line breaks here. + */ + text.replace(/\\n|\n/g, '
') + }

`; +} + export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) { const nodes = marked.lexer(markdown); From 43ca299edebff4508bda8ce6fca5eaa78ebcdda7 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 29 Jan 2026 17:08:36 +0530 Subject: [PATCH 26/62] fix: specify labelType as markdown in insertEdges for block diagram on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/block/renderHelpers.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts index 8957b4d8fa4..03494ad5a1d 100644 --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts @@ -235,6 +235,7 @@ export async function insertEdges( await insertEdgeLabel(elem, { ...edge, label: edge.label, + labelType: 'markdown', labelStyle: 'stroke: #333; stroke-width: 1.5px;fill:none;', arrowTypeEnd: edge.arrowTypeEnd, arrowTypeStart: edge.arrowTypeStart, From 9da586416a3941ad5f1d63917fe9477df844af8c Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 29 Jan 2026 17:23:33 +0530 Subject: [PATCH 27/62] chore: add changeset for autoWrap in flowcharts on-behalf-of: @Mermaid-Chart --- .changeset/curvy-cases-battle.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/curvy-cases-battle.md diff --git a/.changeset/curvy-cases-battle.md b/.changeset/curvy-cases-battle.md new file mode 100644 index 00000000000..8e5ae4ab128 --- /dev/null +++ b/.changeset/curvy-cases-battle.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: respect markdownAutoWrap: false to prevent text auto-wrapping in flowchart nodes From 7949762fe57e2be5a249fc557d3124189453ae00 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 29 Jan 2026 21:30:00 +0530 Subject: [PATCH 28/62] fix: add isNode property to edge label configuration for block diagram and remove labelType for markdown --- packages/mermaid/src/dagre-wrapper/edges.js | 1 + packages/mermaid/src/diagrams/block/renderHelpers.ts | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index 8aaafe62dda..304a2bc9206 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -37,6 +37,7 @@ export const insertEdgeLabel = async (elem, edge) => { style: edge.labelStyle, useHtmlLabels, addSvgBackground: true, + isNode: false, markdown: isMarkdown, // If using markdown, wrap using default width width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts index 03494ad5a1d..8957b4d8fa4 100644 --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts @@ -235,7 +235,6 @@ export async function insertEdges( await insertEdgeLabel(elem, { ...edge, label: edge.label, - labelType: 'markdown', labelStyle: 'stroke: #333; stroke-width: 1.5px;fill:none;', arrowTypeEnd: edge.arrowTypeEnd, arrowTypeStart: edge.arrowTypeStart, From 4e7d35f3d12a6083dc0e7857fc37d4d887a862f3 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 30 Jan 2026 12:04:11 +0530 Subject: [PATCH 29/62] fix: update label background color handling in block diagram on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/block/styles.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/diagrams/block/styles.ts b/packages/mermaid/src/diagrams/block/styles.ts index 1a092142d08..fd79dfc82f0 100644 --- a/packages/mermaid/src/diagrams/block/styles.ts +++ b/packages/mermaid/src/diagrams/block/styles.ts @@ -101,8 +101,13 @@ const getStyles = (options: BlockChartStyleOptions) => /* For html labels only */ .labelBkg { - background-color: ${fade(options.edgeLabelBackground, 0.5)}; - // background-color: + background-color: ${options.edgeLabelBackground}; + } + + .labelBkg p { + margin: 0; + padding: 0; + display: inline-block; } .node .cluster { From 5083b0cda8438313dcde5fd8df5c89db45d38530 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 30 Jan 2026 12:41:12 +0530 Subject: [PATCH 30/62] fix: change label background color to transparent in block styles on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/block/styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/block/styles.ts b/packages/mermaid/src/diagrams/block/styles.ts index fd79dfc82f0..0fd4090526d 100644 --- a/packages/mermaid/src/diagrams/block/styles.ts +++ b/packages/mermaid/src/diagrams/block/styles.ts @@ -107,7 +107,7 @@ const getStyles = (options: BlockChartStyleOptions) => .labelBkg p { margin: 0; padding: 0; - display: inline-block; + background-color: transparent; } .node .cluster { From 8d38c52997ed6505aaa25eae061c26ba5fb6e3c3 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 30 Jan 2026 14:58:08 +0530 Subject: [PATCH 31/62] fix: update edge label background handling for markdown compatibility in block diagrams --- packages/mermaid/src/dagre-wrapper/edges.js | 4 +++- packages/mermaid/src/diagrams/block/styles.ts | 17 +++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index 304a2bc9206..cc3c78e19ca 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -36,7 +36,9 @@ export const insertEdgeLabel = async (elem, edge) => { { style: edge.labelStyle, useHtmlLabels, - addSvgBackground: true, + // TODO: The old code only set addSvgBackground when using markdown, but + // this function is only used by block diagrams which never use markdown. + addSvgBackground: isMarkdown, isNode: false, markdown: isMarkdown, // If using markdown, wrap using default width diff --git a/packages/mermaid/src/diagrams/block/styles.ts b/packages/mermaid/src/diagrams/block/styles.ts index 0fd4090526d..a8fa4e3feb0 100644 --- a/packages/mermaid/src/diagrams/block/styles.ts +++ b/packages/mermaid/src/diagrams/block/styles.ts @@ -91,6 +91,17 @@ const getStyles = (options: BlockChartStyleOptions) => .edgeLabel { background-color: ${options.edgeLabelBackground}; + /* + * This is for backward compatibility with existing code that didn't + * add a \`

\` around edge labels. + * + * TODO: We should probably remove this in a future release. + */ + p { + margin: 0; + padding: 0; + display: inline; + } rect { opacity: 0.5; background-color: ${options.edgeLabelBackground}; @@ -104,12 +115,6 @@ const getStyles = (options: BlockChartStyleOptions) => background-color: ${options.edgeLabelBackground}; } - .labelBkg p { - margin: 0; - padding: 0; - background-color: transparent; - } - .node .cluster { // fill: ${fade(options.mainBkg, 0.5)}; fill: ${fade(options.clusterBkg, 0.5)}; From 0ee366e8d27c5858c466c64f10c2e42d530a87c2 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 3 Feb 2026 22:21:36 +0530 Subject: [PATCH 32/62] fix: maintain backward compatibility for markdown label handling in edge labels on-behalf-of: @Mermaid-Chart --- .../src/rendering-util/rendering-elements/edges.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 83c52412d5c..2549170db2e 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -61,14 +61,18 @@ export const insertEdgeLabel = async (elem, edge) => { const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); const isMarkdown = edge.labelType === 'markdown'; + // Only pass markdown and width parameters if labelType is explicitly set to 'markdown' + // This maintains backward compatibility with diagrams that don't set labelType const labelElement = await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, isNode: false, - markdown: isMarkdown, - // If using markdown, wrap using default width - width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, + ...(isMarkdown && { + markdown: true, + // If using markdown, wrap using default width + width: undefined, + }), }); label.node().appendChild(labelElement); From 8bd8039afa11a4c1a99c62385b5f842d626dea37 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 3 Feb 2026 22:34:28 +0530 Subject: [PATCH 33/62] Revert "fix: maintain backward compatibility for markdown label handling in edge labels" This reverts commit 0ee366e8d27c5858c466c64f10c2e42d530a87c2. --- .../src/rendering-util/rendering-elements/edges.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 2549170db2e..83c52412d5c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -61,18 +61,14 @@ export const insertEdgeLabel = async (elem, edge) => { const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); const isMarkdown = edge.labelType === 'markdown'; - // Only pass markdown and width parameters if labelType is explicitly set to 'markdown' - // This maintains backward compatibility with diagrams that don't set labelType const labelElement = await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, isNode: false, - ...(isMarkdown && { - markdown: true, - // If using markdown, wrap using default width - width: undefined, - }), + markdown: isMarkdown, + // If using markdown, wrap using default width + width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, }); label.node().appendChild(labelElement); From deb45824173e883f21f659a303cfe5b53f47d471 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 4 Feb 2026 12:53:49 +0530 Subject: [PATCH 34/62] fix: simplify text content handling in addText function on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/class/shapeUtil.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/mermaid/src/diagrams/class/shapeUtil.ts b/packages/mermaid/src/diagrams/class/shapeUtil.ts index 94c8f817aef..0548097285d 100644 --- a/packages/mermaid/src/diagrams/class/shapeUtil.ts +++ b/packages/mermaid/src/diagrams/class/shapeUtil.ts @@ -148,14 +148,7 @@ async function addText( const textChild = text.children[0]; if (text.textContent === '' || text.textContent.includes('>')) { textChild.textContent = - textContent[0] + - textContent.substring(1).replaceAll('>', '>').replaceAll('<', '<').trim(); - - // Text was improperly removed due to spaces (preserve one space if present) - const preserveSpace = textContent[1] === ' '; - if (preserveSpace) { - textChild.textContent = textChild.textContent[0] + ' ' + textChild.textContent.substring(1); - } + textContent[0] + textContent.substring(1).replaceAll('>', '>').replaceAll('<', '<'); } // To support empty boxes From 3b730a0903ffb062fa0684a9962e0f1b54bd51da Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 4 Feb 2026 13:12:40 +0530 Subject: [PATCH 35/62] fix: enhance text handling in addText function for class diagrams on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/class/shapeUtil.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/class/shapeUtil.ts b/packages/mermaid/src/diagrams/class/shapeUtil.ts index 0548097285d..491aeac9bb0 100644 --- a/packages/mermaid/src/diagrams/class/shapeUtil.ts +++ b/packages/mermaid/src/diagrams/class/shapeUtil.ts @@ -131,6 +131,7 @@ async function addText( width: calculateTextWidth(textContent, config) + 50, // Add room for error when splitting text into multiple lines classes: 'markdown-node-label', useHtmlLabels, + markdown: false, // Class diagram syntax is not markdown }, config ); @@ -148,7 +149,14 @@ async function addText( const textChild = text.children[0]; if (text.textContent === '' || text.textContent.includes('>')) { textChild.textContent = - textContent[0] + textContent.substring(1).replaceAll('>', '>').replaceAll('<', '<'); + textContent[0] + + textContent.substring(1).replaceAll('>', '>').replaceAll('<', '<').trim(); + + // Text was improperly removed due to spaces (preserve one space if present) + const preserveSpace = textContent[1] === ' '; + if (preserveSpace) { + textChild.textContent = textChild.textContent[0] + ' ' + textChild.textContent.substring(1); + } } // To support empty boxes From 8745456f2fb1d27638039e268dcd59a652755310 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 4 Feb 2026 13:24:49 +0530 Subject: [PATCH 36/62] fix: add labelType markdown for class diagram Nodes on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/class/classDb.ts | 2 ++ packages/mermaid/src/diagrams/class/shapeUtil.ts | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index 59d8daeba05..cb3fd8f1855 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -649,6 +649,7 @@ export class ClassDB implements DiagramDB { shape: 'rect', cssStyles: [], look: config.look, + labelType: 'markdown', }; nodes.push(node); } @@ -660,6 +661,7 @@ export class ClassDB implements DiagramDB { isGroup: false, parentId: classNode.parent, look: config.look, + labelType: 'markdown', }; nodes.push(node); } diff --git a/packages/mermaid/src/diagrams/class/shapeUtil.ts b/packages/mermaid/src/diagrams/class/shapeUtil.ts index 491aeac9bb0..94c8f817aef 100644 --- a/packages/mermaid/src/diagrams/class/shapeUtil.ts +++ b/packages/mermaid/src/diagrams/class/shapeUtil.ts @@ -131,7 +131,6 @@ async function addText( width: calculateTextWidth(textContent, config) + 50, // Add room for error when splitting text into multiple lines classes: 'markdown-node-label', useHtmlLabels, - markdown: false, // Class diagram syntax is not markdown }, config ); From 5438e9cc7d99637ac34f6a91dabf28c24eece765 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 4 Feb 2026 13:38:57 +0530 Subject: [PATCH 37/62] Revert "fix: add labelType markdown for class diagram Nodes" This reverts commit 8745456f2fb1d27638039e268dcd59a652755310. --- packages/mermaid/src/diagrams/class/classDb.ts | 2 -- packages/mermaid/src/diagrams/class/shapeUtil.ts | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index cb3fd8f1855..59d8daeba05 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -649,7 +649,6 @@ export class ClassDB implements DiagramDB { shape: 'rect', cssStyles: [], look: config.look, - labelType: 'markdown', }; nodes.push(node); } @@ -661,7 +660,6 @@ export class ClassDB implements DiagramDB { isGroup: false, parentId: classNode.parent, look: config.look, - labelType: 'markdown', }; nodes.push(node); } diff --git a/packages/mermaid/src/diagrams/class/shapeUtil.ts b/packages/mermaid/src/diagrams/class/shapeUtil.ts index 94c8f817aef..491aeac9bb0 100644 --- a/packages/mermaid/src/diagrams/class/shapeUtil.ts +++ b/packages/mermaid/src/diagrams/class/shapeUtil.ts @@ -131,6 +131,7 @@ async function addText( width: calculateTextWidth(textContent, config) + 50, // Add room for error when splitting text into multiple lines classes: 'markdown-node-label', useHtmlLabels, + markdown: false, // Class diagram syntax is not markdown }, config ); From 3c118d7b6402f2b7f09c4853b0fe0180167b4eb9 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 4 Feb 2026 13:52:12 +0530 Subject: [PATCH 38/62] fix: revert changes in shapeUtil on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/class/shapeUtil.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/class/shapeUtil.ts b/packages/mermaid/src/diagrams/class/shapeUtil.ts index 491aeac9bb0..94c8f817aef 100644 --- a/packages/mermaid/src/diagrams/class/shapeUtil.ts +++ b/packages/mermaid/src/diagrams/class/shapeUtil.ts @@ -131,7 +131,6 @@ async function addText( width: calculateTextWidth(textContent, config) + 50, // Add room for error when splitting text into multiple lines classes: 'markdown-node-label', useHtmlLabels, - markdown: false, // Class diagram syntax is not markdown }, config ); From 185ccf0788c0c0bec76c0f86876f993c96c853cb Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 4 Feb 2026 14:40:29 +0530 Subject: [PATCH 39/62] fix: remove labelType markdown from class diagram edges on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/class/classDb.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index 59d8daeba05..d745f1ac1d3 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -741,7 +741,6 @@ export class ClassDB implements DiagramDB { style: classRelation.style || '', pattern: classRelation.relation.lineType == 1 ? 'dashed' : 'solid', look: config.look, - labelType: 'markdown', }; edges.push(edge); } From 0d1d64e44a8e4707a48e31f5c9eba0789123d113 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 4 Feb 2026 15:17:11 +0530 Subject: [PATCH 40/62] Revert "fix: remove labelType markdown from class diagram edges" This reverts commit 185ccf0788c0c0bec76c0f86876f993c96c853cb. --- packages/mermaid/src/diagrams/class/classDb.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index d745f1ac1d3..59d8daeba05 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -741,6 +741,7 @@ export class ClassDB implements DiagramDB { style: classRelation.style || '', pattern: classRelation.relation.lineType == 1 ? 'dashed' : 'solid', look: config.look, + labelType: 'markdown', }; edges.push(edge); } From 863808f88d77e467fe22c50d80732709480f6271 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 6 Feb 2026 12:01:54 +0530 Subject: [PATCH 41/62] fix: set labelType to markdown for ER diagram node label on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/er/erDb.ts | 1 + packages/mermaid/src/diagrams/er/erTypes.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/mermaid/src/diagrams/er/erDb.ts b/packages/mermaid/src/diagrams/er/erDb.ts index 1cfd2b301a1..fb220d2e6f8 100644 --- a/packages/mermaid/src/diagrams/er/erDb.ts +++ b/packages/mermaid/src/diagrams/er/erDb.ts @@ -62,6 +62,7 @@ export class ErDB implements DiagramDB { look: getConfig().look ?? 'default', cssClasses: 'default', cssStyles: [], + labelType: 'markdown', }); log.info('Added new entity :', name); } else if (!this.entities.get(name)?.alias && alias) { diff --git a/packages/mermaid/src/diagrams/er/erTypes.ts b/packages/mermaid/src/diagrams/er/erTypes.ts index 13f9b26697e..a0c9749146a 100644 --- a/packages/mermaid/src/diagrams/er/erTypes.ts +++ b/packages/mermaid/src/diagrams/er/erTypes.ts @@ -8,6 +8,7 @@ export interface EntityNode { cssClasses?: string; cssStyles?: string[]; cssCompiledStyles?: string[]; + labelType?: string; } export interface Attribute { From 144794b76a9a6751e2dbe031c5fba83620061b8d Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 6 Feb 2026 12:13:43 +0530 Subject: [PATCH 42/62] fix: set labelType to markdown for class diagram notes on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/diagrams/class/classDb.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index 59d8daeba05..edb246f3f08 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -679,6 +679,7 @@ export class ClassDB implements DiagramDB { ], look: config.look, parentId: note.parent, + labelType: 'markdown', }; nodes.push(noteNode); From 1336d22866dfb8df81099cc19bff8c65b11faf95 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 6 Feb 2026 14:15:18 +0530 Subject: [PATCH 43/62] chore:update changeset on-behalf-of: @Mermaid-Chart --- .changeset/swift-cloths-run.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.changeset/swift-cloths-run.md b/.changeset/swift-cloths-run.md index 000b58fc2b7..a3f86c2f75c 100644 --- a/.changeset/swift-cloths-run.md +++ b/.changeset/swift-cloths-run.md @@ -2,4 +2,23 @@ 'mermaid': patch --- -fix: Restore proper rendering of non-markdown flowchart labels with multiline support +fix: Restore proper rendering of plain text flowchart labels with multiline support + +This fix restores backwards compatibility with Mermaid v10 by ensuring that plain text labels in flowcharts are rendered correctly with proper multiline support. In Mermaid v11, all labels were incorrectly being treated as markdown by default, which caused issues with text wrapping, multiline breaks, and backwards compatibility. + +**What changed:** + +- Plain text labels (without markdown syntax) now render as regular text with proper multiline support +- Labels with `\n` characters now correctly create line breaks +- Text that looks like markdown (e.g., "1.", "- x") is no longer misinterpreted + +**If you want markdown formatting:** +You can still use markdown in your flowchart labels by using the proper markdown syntax. Wrap your markdown text with double quotes and backticks: `["`Your **markdown** text`"]` + +Example: + +```mermaid +flowchart LR + plain["Plain text label"] + markdown["`This is **bold** markdown`"] +``` From 7732a237a8784836d06f437a85b896286147225f Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 6 Feb 2026 15:17:08 +0530 Subject: [PATCH 44/62] chore:update changeset on-behalf-of: @Mermaid-Chart --- .changeset/swift-cloths-run.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.changeset/swift-cloths-run.md b/.changeset/swift-cloths-run.md index a3f86c2f75c..f7bcfe811a5 100644 --- a/.changeset/swift-cloths-run.md +++ b/.changeset/swift-cloths-run.md @@ -2,23 +2,26 @@ 'mermaid': patch --- -fix: Restore proper rendering of plain text flowchart labels with multiline support +fix: Restore proper rendering of plain text flowchart labels without auto line-wrapping -This fix restores backwards compatibility with Mermaid v10 by ensuring that plain text labels in flowcharts are rendered correctly with proper multiline support. In Mermaid v11, all labels were incorrectly being treated as markdown by default, which caused issues with text wrapping, multiline breaks, and backwards compatibility. +This fix restores backwards compatibility with Mermaid v10 by ensuring that plain text labels in flowcharts are rendered correctly without auto line-wrapping. In Mermaid v11, all labels were incorrectly being treated as markdown by default, which caused issues with text wrapping, multiline breaks, and backwards compatibility. **What changed:** -- Plain text labels (without markdown syntax) now render as regular text with proper multiline support +- Plain text labels (without markdown syntax) now render as regular text without auto line-wrapping - Labels with `\n` characters now correctly create line breaks - Text that looks like markdown (e.g., "1.", "- x") is no longer misinterpreted **If you want markdown formatting:** -You can still use markdown in your flowchart labels by using the proper markdown syntax. Wrap your markdown text with double quotes and backticks: `["`Your **markdown** text`"]` +You can still use markdown in your flowchart labels by using the proper markdown syntax. Wrap your markdown text with double quotes and backticks: +``node["`_markdown_ **text**`"]`` Example: +````markdown ```mermaid -flowchart LR - plain["Plain text label"] - markdown["`This is **bold** markdown`"] +flowchart TD + plain["Plain text\nwith manual line break"] + markdown["`This is a **markdown** _label_ that wraps and doesn't replace \n with newlines`"] ``` +```` From 1384d58adc4f81b66d72f3510e5a15d222666f81 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 12 Feb 2026 21:17:19 +0530 Subject: [PATCH 45/62] fix: autowrapping in flowchart node labels on-behalf-of: @Mermaid-Chart --- .../src/rendering-util/rendering-elements/shapes/util.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts index 430572d3198..568a08c39cc 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -48,9 +48,7 @@ export const labelHelper = async ( sanitizeText(decodeEntities(label), getConfig()), { useHtmlLabels, - width: - node.width || - (isMarkdown ? getConfig().flowchart?.wrappingWidth : Number.POSITIVE_INFINITY), + width: node.width || getConfig().flowchart?.wrappingWidth, // @ts-expect-error -- This is currently not used. Should this be `classes` instead? cssClasses: isMarkdown ? 'markdown-node-label' : undefined, style: node.labelStyle, From 1a18d30e9db6ede20e2ea2e354a094b226fa53df Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 13 Feb 2026 17:44:03 +0530 Subject: [PATCH 46/62] fix: add space after html tag to non markdown text on-behalf-of: @Mermaid-Chart --- .../mermaid/src/rendering-util/handle-markdown-text.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts index 22476eb889e..57aceb99365 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -25,14 +25,15 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi /** * @param nonMarkdownText - Non-markdown text to split into plain-text formatted lines. * This treats new lines, `\n`, and `
` as line breaks, and splits on spaces for words. + * HTML tags are preserved as separate words to maintain proper formatting. */ export function nonMarkdownToLines(nonMarkdownText: string): MarkdownLine[] { - return nonMarkdownText.split(/\\n|\n|/gi).map( + return nonMarkdownText.split(/\r?\n|/gi).map( (line) => line .trim() - .split(/\s/g) - .map((word) => ({ content: word, type: 'normal' })) satisfies MarkdownLine + .match(/<[^>]+>|[^\s<>]+/g) // keeps HTML tags intact + ?.map((word) => ({ content: word, type: 'normal' })) ?? [] ); } From 9ffe1cf315314b62ef8a21f850334b106c0bc02f Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 16 Feb 2026 14:41:13 +0530 Subject: [PATCH 47/62] chore: update changeset on-behalf-of: @Mermaid-Chart --- .changeset/swift-cloths-run.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.changeset/swift-cloths-run.md b/.changeset/swift-cloths-run.md index f7bcfe811a5..a5c5702ad34 100644 --- a/.changeset/swift-cloths-run.md +++ b/.changeset/swift-cloths-run.md @@ -4,13 +4,16 @@ fix: Restore proper rendering of plain text flowchart labels without auto line-wrapping -This fix restores backwards compatibility with Mermaid v10 by ensuring that plain text labels in flowcharts are rendered correctly without auto line-wrapping. In Mermaid v11, all labels were incorrectly being treated as markdown by default, which caused issues with text wrapping, multiline breaks, and backwards compatibility. +This fix restores backwards compatibility with Mermaid v10 by ensuring that plain text labels in flowcharts are rendered correctly. In Mermaid v11, all labels were incorrectly being treated as markdown by default, which caused issues with text wrapping, multiline breaks, and backwards compatibility. **What changed:** -- Plain text labels (without markdown syntax) now render as regular text without auto line-wrapping -- Labels with `\n` characters now correctly create line breaks -- Text that looks like markdown (e.g., "1.", "- x") is no longer misinterpreted +- Plain text labels in flowcharts (without markdown syntax) now render as regular text + - For node labels, these will line-wrap automatically. Although this isn't backwards compatible with v10, we think this is a minor change and it's worth keeping to avoid too many changes from diagrams created from v11 onwards. + - For edge labels, these will **not** line-wrap automatically. + - Plain text labels in other diagrams will continue to not line wrap. +- Plain text labels with `\n` characters now correctly create line breaks +- Plain text that looks like markdown (e.g., "1.", "- x") is no longer misinterpreted **If you want markdown formatting:** You can still use markdown in your flowchart labels by using the proper markdown syntax. Wrap your markdown text with double quotes and backticks: From 10d2f77b20ecd0eb49bfe010527f52aec1e58205 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 16 Feb 2026 16:11:37 +0530 Subject: [PATCH 48/62] fix: update handling of markdownAutoWrap to prevent text auto-wrapping in flowchart labels with htmlLabels enabled on-behalf-of: @Mermaid-Chart --- .changeset/curvy-cases-battle.md | 5 ++++- packages/mermaid/src/rendering-util/handle-markdown-text.ts | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.changeset/curvy-cases-battle.md b/.changeset/curvy-cases-battle.md index 8e5ae4ab128..e0489c0bfd4 100644 --- a/.changeset/curvy-cases-battle.md +++ b/.changeset/curvy-cases-battle.md @@ -2,4 +2,7 @@ 'mermaid': patch --- -fix: respect markdownAutoWrap: false to prevent text auto-wrapping in flowchart nodes +fix: respect `markdownAutoWrap: false` to prevent text auto-wrapping in flowchart markdown labels with `htmlLabels` enabled. + +Markdown labels with `markdownAutoWrap: false, htmlLabels: false` set doesn't work +correctly. diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts index 57aceb99365..14c86d8f6b6 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -17,7 +17,10 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi // Remove extra spaces at the beginning of each line const withoutExtraSpaces = dedent(withoutMultipleNewlines); if (markdownAutoWrap === false) { - return withoutExtraSpaces.replace(/ /g, ' '); + // TODO: Disabling `markdownAutoWrap` is currently broken for `htmlLabels: false`, + // since the code calls `splitWordToFitWidth` to split words even we can't + // break on spaces. + // return withoutExtraSpaces.replace(/ /g, '\u00A0'); } return withoutExtraSpaces; } From a11ca1f548c03de5302c94ec31ca4b2d283ef5ef Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 16 Feb 2026 16:43:21 +0530 Subject: [PATCH 49/62] fix: failing unit tests on-behalf-of: @Mermaid-Chart --- .../rendering-util/handle-markdown-text.spec.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts index 2000d58b844..869ed738d62 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts @@ -214,13 +214,25 @@ test('markdownToLines - No auto wrapping', () => { [ [ { - "content": "Hello, how do", + "content": "Hello,", + "type": "normal", + }, + { + "content": "how", + "type": "normal", + }, + { + "content": "do", "type": "normal", }, ], [ { - "content": "you do?", + "content": "you", + "type": "normal", + }, + { + "content": "do?", "type": "normal", }, ], From c46cb9804fbffb001cb73e9f12997c75a23815e4 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 16 Feb 2026 16:55:20 +0530 Subject: [PATCH 50/62] fix: autowrapping for edge labels on-behalf-of: @Mermaid-Chart --- .../mermaid/src/rendering-util/rendering-elements/edges.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 83c52412d5c..8cd1f87ca93 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -60,15 +60,11 @@ export const insertEdgeLabel = async (elem, edge) => { // Create inner g, label, this will be positioned now for centering the text const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); - const isMarkdown = edge.labelType === 'markdown'; const labelElement = await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, isNode: false, - markdown: isMarkdown, - // If using markdown, wrap using default width - width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, }); label.node().appendChild(labelElement); From 9bbb075bc0231d31d86c03ef8e788cdb6e143b40 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 16 Feb 2026 19:49:19 +0530 Subject: [PATCH 51/62] fix: update edge label handling to respect markdownAutoWrap configuration on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/dagre-wrapper/edges.js | 5 +++-- .../mermaid/src/rendering-util/rendering-elements/edges.js | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index cc3c78e19ca..d514ed48775 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -30,6 +30,7 @@ export const insertEdgeLabel = async (elem, edge) => { // Create the actual text element const isMarkdown = edge.labelType === 'markdown'; + const markdownWidth = config.markdownAutoWrap === false ? Number.POSITIVE_INFINITY : undefined; const labelElement = await createText( elem, edge.label, @@ -41,8 +42,8 @@ export const insertEdgeLabel = async (elem, edge) => { addSvgBackground: isMarkdown, isNode: false, markdown: isMarkdown, - // If using markdown, wrap using default width - width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, + // Plain text edge labels should auto-wrap, markdown edge labels respect markdownAutoWrap config + width: isMarkdown ? markdownWidth : undefined, }, config ); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 8cd1f87ca93..ada185c913b 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -60,11 +60,17 @@ export const insertEdgeLabel = async (elem, edge) => { // Create inner g, label, this will be positioned now for centering the text const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); + const isMarkdown = edge.labelType === 'markdown'; + const config = getConfig(); + const markdownWidth = config.markdownAutoWrap === false ? Number.POSITIVE_INFINITY : undefined; const labelElement = await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, isNode: false, + markdown: isMarkdown, + // Plain text edge labels should auto-wrap, markdown edge labels respect markdownAutoWrap config + width: isMarkdown ? markdownWidth : undefined, }); label.node().appendChild(labelElement); From 40f9993049ee29a4099b5e2b26787000db88ddad Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 18 Feb 2026 14:28:28 +0530 Subject: [PATCH 52/62] chore: add tests for auto wrapping of flowchart edge labels on-behalf-of: @Mermaid-Chart --- .../rendering/flowchart-v2.spec.js | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index bf7ff5b8c6b..987144d604f 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1211,4 +1211,54 @@ class link myClass ` ); }); + + describe('Edge label auto-wrapping: plain text vs markdown with markdownAutoWrap', () => { + it('should handle edge labels with markdownAutoWrap true and htmlLabels true', () => { + imgSnapshotTest( + `flowchart TD + A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] + B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] + A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B + B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C + `, + { markdownAutoWrap: true, htmlLabels: true } + ); + }); + + it('should handle edge labels with markdownAutoWrap false and htmlLabels true', () => { + imgSnapshotTest( + `flowchart TD + A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] + B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] + A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B + B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C + `, + { markdownAutoWrap: false, htmlLabels: true } + ); + }); + + it('should handle edge labels with markdownAutoWrap true and htmlLabels false', () => { + imgSnapshotTest( + `flowchart TD + A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] + B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] + A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B + B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C + `, + { markdownAutoWrap: true, htmlLabels: false } + ); + }); + + it('should handle edge labels with markdownAutoWrap false and htmlLabels false', () => { + imgSnapshotTest( + `flowchart TD + A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] + B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] + A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B + B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C + `, + { markdownAutoWrap: false, htmlLabels: false } + ); + }); + }); }); From 7d32db1a234011647af409bad1bc63a59861b388 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Wed, 18 Feb 2026 14:37:11 +0530 Subject: [PATCH 53/62] chore: update changeset on-behalf-of: @Mermaid-Chart --- .changeset/swift-cloths-run.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.changeset/swift-cloths-run.md b/.changeset/swift-cloths-run.md index a5c5702ad34..7f4240ecc34 100644 --- a/.changeset/swift-cloths-run.md +++ b/.changeset/swift-cloths-run.md @@ -9,8 +9,7 @@ This fix restores backwards compatibility with Mermaid v10 by ensuring that plai **What changed:** - Plain text labels in flowcharts (without markdown syntax) now render as regular text - - For node labels, these will line-wrap automatically. Although this isn't backwards compatible with v10, we think this is a minor change and it's worth keeping to avoid too many changes from diagrams created from v11 onwards. - - For edge labels, these will **not** line-wrap automatically. + - For node labels and edge labels, these will line-wrap automatically. Although this isn't backwards compatible with v10, we think this is a minor change and it's worth keeping to avoid too many changes from diagrams created from v11 onwards. - Plain text labels in other diagrams will continue to not line wrap. - Plain text labels with `\n` characters now correctly create line breaks - Plain text that looks like markdown (e.g., "1.", "- x") is no longer misinterpreted From c7f58504b5106cb88f7f14ede1612f62f0737d69 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 19 Feb 2026 11:37:07 +0530 Subject: [PATCH 54/62] revert changes to the markdownToLines - No auto wrapping unit tests on-behalf-of: @Mermaid-Chart --- .../handle-markdown-text.spec.ts | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts index 869ed738d62..1fe496fb735 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts @@ -202,7 +202,8 @@ Word!`; const output = markdownToLines(input); expect(output).toEqual(expectedOutput); }); - +// TODO: Fix markdownAutoWrap=false behavior for htmlLabels:false. +// Expected output may need update after resolving space handling logic. test('markdownToLines - No auto wrapping', () => { expect( markdownToLines( @@ -214,25 +215,13 @@ test('markdownToLines - No auto wrapping', () => { [ [ { - "content": "Hello,", - "type": "normal", - }, - { - "content": "how", - "type": "normal", - }, - { - "content": "do", + "content": "Hello, how do", "type": "normal", }, ], [ { - "content": "you", - "type": "normal", - }, - { - "content": "do?", + "content": "you do?", "type": "normal", }, ], From fb6edefa75d8de720d34862d0384ad15a5f08e1d Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 19 Feb 2026 11:57:36 +0530 Subject: [PATCH 55/62] Revert "fix: update edge label handling to respect markdownAutoWrap configuration" This reverts commit 9bbb075bc0231d31d86c03ef8e788cdb6e143b40. --- packages/mermaid/src/dagre-wrapper/edges.js | 5 ++--- .../mermaid/src/rendering-util/rendering-elements/edges.js | 6 ------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index d514ed48775..cc3c78e19ca 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -30,7 +30,6 @@ export const insertEdgeLabel = async (elem, edge) => { // Create the actual text element const isMarkdown = edge.labelType === 'markdown'; - const markdownWidth = config.markdownAutoWrap === false ? Number.POSITIVE_INFINITY : undefined; const labelElement = await createText( elem, edge.label, @@ -42,8 +41,8 @@ export const insertEdgeLabel = async (elem, edge) => { addSvgBackground: isMarkdown, isNode: false, markdown: isMarkdown, - // Plain text edge labels should auto-wrap, markdown edge labels respect markdownAutoWrap config - width: isMarkdown ? markdownWidth : undefined, + // If using markdown, wrap using default width + width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, }, config ); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index ada185c913b..8cd1f87ca93 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -60,17 +60,11 @@ export const insertEdgeLabel = async (elem, edge) => { // Create inner g, label, this will be positioned now for centering the text const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); - const isMarkdown = edge.labelType === 'markdown'; - const config = getConfig(); - const markdownWidth = config.markdownAutoWrap === false ? Number.POSITIVE_INFINITY : undefined; const labelElement = await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, isNode: false, - markdown: isMarkdown, - // Plain text edge labels should auto-wrap, markdown edge labels respect markdownAutoWrap config - width: isMarkdown ? markdownWidth : undefined, }); label.node().appendChild(labelElement); From 5d1e84f4c80c6297ef8738e5486cb64522bfe7d3 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 19 Feb 2026 12:46:58 +0530 Subject: [PATCH 56/62] fix: update nonMarkdownToLines to preserve spaces between HTML tags and text on-behalf-of: @Mermaid-Chart --- packages/mermaid/src/rendering-util/handle-markdown-text.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts index 14c86d8f6b6..9964017c165 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -31,11 +31,11 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi * HTML tags are preserved as separate words to maintain proper formatting. */ export function nonMarkdownToLines(nonMarkdownText: string): MarkdownLine[] { - return nonMarkdownText.split(/\r?\n|/gi).map( + return nonMarkdownText.split(/\\n|\n|/gi).map( (line) => line .trim() - .match(/<[^>]+>|[^\s<>]+/g) // keeps HTML tags intact + .match(/<[^>]+>|[^\s<>]+/g) // keeps HTML tags intact and preserves space between tags and text ?.map((word) => ({ content: word, type: 'normal' })) ?? [] ); } From 7517f83ed369a44c81160cf47cef85ec11bf3657 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 19 Feb 2026 18:29:24 +0530 Subject: [PATCH 57/62] fix: update tests for flowcharts edge label auto wrapping on-behalf-of: @Mermaid-Chart --- .../rendering/flowchart-v2.spec.js | 63 ++++++------------- 1 file changed, 20 insertions(+), 43 deletions(-) diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 987144d604f..d7b2cf31704 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1212,52 +1212,29 @@ class link myClass ); }); - describe('Edge label auto-wrapping: plain text vs markdown with markdownAutoWrap', () => { - it('should handle edge labels with markdownAutoWrap true and htmlLabels true', () => { + describe('Edge label auto-wrapping', () => { + it('should wrap edge labels', () => { imgSnapshotTest( - `flowchart TD - A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] - B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] - A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B - B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C - `, - { markdownAutoWrap: true, htmlLabels: true } - ); - }); - - it('should handle edge labels with markdownAutoWrap false and htmlLabels true', () => { - imgSnapshotTest( - `flowchart TD - A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] - B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] - A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B - B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C - `, - { markdownAutoWrap: false, htmlLabels: true } - ); - }); - - it('should handle edge labels with markdownAutoWrap true and htmlLabels false', () => { - imgSnapshotTest( - `flowchart TD - A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] - B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] - A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B - B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C - `, - { markdownAutoWrap: true, htmlLabels: false } - ); - }); - - it('should handle edge labels with markdownAutoWrap false and htmlLabels false', () => { - imgSnapshotTest( - `flowchart TD - A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] + [ + { + markdownAutoWrap: true, + htmlLabels: true, + }, + { markdownAutoWrap: true, htmlLabels: false }, + { markdownAutoWrap: false, htmlLabels: true }, + // TODO: currently broken + // {markdownAutoWrap: false, htmlLabels: false}, + ].map( + ({ markdownAutoWrap, htmlLabels }) => `--- +config: ${JSON.stringify({ markdownAutoWrap, htmlLabels })} +--- +flowchart TD + A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] - A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \n But newline characters work." --> B + A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \\n But newline characters work." --> B B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C - `, - { markdownAutoWrap: false, htmlLabels: false } +` + ) ); }); }); From b8e7dec855bba50332a709cd9e60c55289198185 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 26 Feb 2026 13:06:12 +0530 Subject: [PATCH 58/62] chore:skip the markdownToLines - No auto wrapping test on-behalf-of: @Mermaid-Chart --- .../mermaid/src/rendering-util/handle-markdown-text.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts index 1fe496fb735..1aac0fb07d5 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts @@ -204,7 +204,7 @@ Word!`; }); // TODO: Fix markdownAutoWrap=false behavior for htmlLabels:false. // Expected output may need update after resolving space handling logic. -test('markdownToLines - No auto wrapping', () => { +test.skip('markdownToLines - No auto wrapping', () => { expect( markdownToLines( `Hello, how do From 047618219b8cbe5527bfd99e1dd64c78827651cf Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 26 Feb 2026 15:44:49 +0530 Subject: [PATCH 59/62] fix: ensure plain text edge labels are not treated as markdown on-behalf-of: @Mermaid-Chart --- .../mermaid/src/rendering-util/rendering-elements/edges.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 8cd1f87ca93..83c52412d5c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -60,11 +60,15 @@ export const insertEdgeLabel = async (elem, edge) => { // Create inner g, label, this will be positioned now for centering the text const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); + const isMarkdown = edge.labelType === 'markdown'; const labelElement = await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, addSvgBackground: true, isNode: false, + markdown: isMarkdown, + // If using markdown, wrap using default width + width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, }); label.node().appendChild(labelElement); From ae60bc292c1280bbd995f3c1b6b9b866fd74ac3c Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Thu, 26 Feb 2026 20:20:50 +0530 Subject: [PATCH 60/62] fix: refactor insertEdgeLabel to improve markdown label handling and width configuration --- .../rendering-elements/edges.js | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 83c52412d5c..2cb3b1593b0 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -50,7 +50,8 @@ export const getLabelStyles = (styleArray) => { }; export const insertEdgeLabel = async (elem, edge) => { - let useHtmlLabels = getEffectiveHtmlLabels(getConfig()); + const config = getConfig(); + let useHtmlLabels = getEffectiveHtmlLabels(config); const { labelStyles } = styles2String(edge); edge.labelStyle = labelStyles; @@ -61,15 +62,21 @@ export const insertEdgeLabel = async (elem, edge) => { const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id); const isMarkdown = edge.labelType === 'markdown'; - const labelElement = await createText(elem, edge.label, { - style: getLabelStyles(edge.labelStyle), - useHtmlLabels, - addSvgBackground: true, - isNode: false, - markdown: isMarkdown, - // If using markdown, wrap using default width - width: isMarkdown ? undefined : Number.POSITIVE_INFINITY, - }); + const markdownWidth = undefined; // Use default width for markdown labels + const labelElement = await createText( + elem, + edge.label, + { + style: getLabelStyles(edge.labelStyle), + useHtmlLabels, + addSvgBackground: true, + isNode: false, + markdown: isMarkdown, + // Plain text edge labels should auto-wrap, markdown edge labels respect markdownAutoWrap config + width: isMarkdown ? markdownWidth : undefined, + }, + config + ); label.node().appendChild(labelElement); log.info('abc82', edge, edge.labelType); From 703995ae7fc5fae7f85dd52d8551fa3d4cd76f5a Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 27 Feb 2026 12:39:18 +0530 Subject: [PATCH 61/62] chore:update Edge label auto-wrapping tests and add nonMarkdownToLines tests on-behalf-of: @Mermaid-Chart --- .../rendering/flowchart-v2.spec.js | 9 +++--- .../handle-markdown-text.spec.ts | 32 ++++++++++++++++++- .../rendering-util/handle-markdown-text.ts | 4 +-- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index d7b2cf31704..0bc5ba6ec62 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1227,12 +1227,13 @@ class link myClass ].map( ({ markdownAutoWrap, htmlLabels }) => `--- config: ${JSON.stringify({ markdownAutoWrap, htmlLabels })} +title: Testing with ${JSON.stringify({ markdownAutoWrap, htmlLabels })} --- flowchart TD - A["\`This is a really **long** line of plain text that will auto-wrap and support\`"] - B["\`This is a really long line of markdown text that will autowrap, unless markdownAutoWrap:false is set.\`"] - A -- "Plain text **labels** in flowcharts will however not autowrap, unlike node labels. \\n But newline characters work." --> B - B -- "\`Markdown edge labels will auto-wrap, even if markdownAutoWrap: false is set\`" --> C + A["This is a really long line of plain text that will autowrap and support \\n newlines too."] + B["\`This is a really long line of **markdown** text that will autowrap, unless markdownAutoWrap:false is set.\`"] + A -- "Plain text **labels** in flowcharts will autowrap,like node labels. \\n Newline characters work too." --> B + B -- "\`**Markdown** edge labels will autowrap, even if markdownAutoWrap: false is set\`" --> C ` ) ); diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts index 1aac0fb07d5..5519195abcc 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts @@ -1,4 +1,4 @@ -import { markdownToLines, markdownToHTML } from './handle-markdown-text.js'; +import { markdownToLines, markdownToHTML, nonMarkdownToLines } from './handle-markdown-text.js'; import { test, expect } from 'vitest'; test('markdownToLines - Basic test', () => { @@ -312,3 +312,33 @@ test('markdownToHTML - auto wrapping', () => { ) ).toMatchInlineSnapshot('"

Hello, how do
you do?

"'); }); + +test('nonMarkdownToLines - splits text by newlines, preserves SVG tags, does not process markdown', () => { + // Splits by newlines (\n, \\n,
) and preserves SVG tags + expect(nonMarkdownToLines('Line 1\\nLine 2
Text with tag')).toEqual([ + [ + { content: 'Line', type: 'normal' }, + { content: '1', type: 'normal' }, + ], + [ + { content: 'Line', type: 'normal' }, + { content: '2', type: 'normal' }, + ], + [ + { content: 'Text', type: 'normal' }, + { content: 'with', type: 'normal' }, + { content: '', type: 'normal' }, + { content: 'tag', type: 'normal' }, + { content: '', type: 'normal' }, + ], + ]); + + // Markdown syntax is NOT processed - stays as plain text + expect(nonMarkdownToLines('**bold** and *italic*')).toEqual([ + [ + { content: '**bold**', type: 'normal' }, + { content: 'and', type: 'normal' }, + { content: '*italic*', type: 'normal' }, + ], + ]); +}); diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts index 9964017c165..2caec30b4c7 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -28,14 +28,14 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi /** * @param nonMarkdownText - Non-markdown text to split into plain-text formatted lines. * This treats new lines, `\n`, and `
` as line breaks, and splits on spaces for words. - * HTML tags are preserved as separate words to maintain proper formatting. + * SVG tags are preserved as separate words to maintain proper formatting. */ export function nonMarkdownToLines(nonMarkdownText: string): MarkdownLine[] { return nonMarkdownText.split(/\\n|\n|/gi).map( (line) => line .trim() - .match(/<[^>]+>|[^\s<>]+/g) // keeps HTML tags intact and preserves space between tags and text + .match(/<[^>]+>|[^\s<>]+/g) // keeps SVG tags intact and preserves space between tags and text ?.map((word) => ({ content: word, type: 'normal' })) ?? [] ); } From 5b1dc431e518c56c5109816aedfd20b6785d6acb Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 27 Feb 2026 13:11:29 +0530 Subject: [PATCH 62/62] chore:update edge label autowrapping tests on-behalf-of: @Mermaid-Chart --- cypress/integration/rendering/flowchart-v2.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 0bc5ba6ec62..bcee3d899e3 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1212,7 +1212,7 @@ class link myClass ); }); - describe('Edge label auto-wrapping', () => { + describe('Edge label autowrapping', () => { it('should wrap edge labels', () => { imgSnapshotTest( [ @@ -1233,7 +1233,7 @@ flowchart TD A["This is a really long line of plain text that will autowrap and support \\n newlines too."] B["\`This is a really long line of **markdown** text that will autowrap, unless markdownAutoWrap:false is set.\`"] A -- "Plain text **labels** in flowcharts will autowrap,like node labels. \\n Newline characters work too." --> B - B -- "\`**Markdown** edge labels will autowrap, even if markdownAutoWrap: false is set\`" --> C + B -- "\`**Markdown** edge labels will autowrap, unless markdownAutoWrap: false is set\`" --> C ` ) );