Compare commits

..

20 Commits

Author SHA1 Message Date
darshanr0107
cd6f7a3019 Merge branch 'fix-markdown-labels-6087' of https://github.com/mermaid-js/mermaid into fix-markdown-labels-6087 2025-10-09 19:10:38 +05:30
darshanr0107
1f0cb96d16 Revert: rollback recent diagram utility and markdown label changes 2025-10-09 19:09:34 +05:30
autofix-ci[bot]
db4a837e9b [autofix.ci] apply automated fixes 2025-10-09 12:56:41 +00:00
darshanr0107
047b7fccc7 Merge branch 'fix-markdown-labels-6087' of https://github.com/mermaid-js/mermaid into fix-markdown-labels-6087 2025-10-09 18:20:50 +05:30
darshanr0107
a53c0d4305 refactor: remove diagram specific checks from utils
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-09 18:18:20 +05:30
autofix-ci[bot]
13f2040b37 [autofix.ci] apply automated fixes 2025-10-09 11:24:45 +00:00
darshanr0107
e351a7a488 fix: some argos , added checks for flowchart
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-09 16:48:35 +05:30
autofix-ci[bot]
fe8597d0c8 [autofix.ci] apply automated fixes 2025-10-08 14:34:38 +00:00
darshanr0107
178ea182c3 Resolve merge conflicts with develop 2025-10-08 19:56:34 +05:30
autofix-ci[bot]
3a23372af4 [autofix.ci] apply automated fixes 2025-08-14 20:01:40 +00:00
Anthony Juckel
cd6f7192bf Use explicit markdown for unsupported markdown integration test 2025-08-14 14:56:27 -05:00
Anthony Juckel
ebb77578e8 Check for htmlLabels in the flowchart config 2025-08-14 14:54:52 -05:00
Anthony Juckel
4d76af679b Revert changes in this branch to knsv2.html 2025-08-14 14:54:21 -05:00
Anthony Juckel
b7b05f4a55 wip: some nullability changes...? 2025-08-14 12:27:21 -05:00
Anthony Juckel
44a6434e59 Apply non-markdown label change for subgroups 2025-08-14 12:27:21 -05:00
Anthony Juckel
37269b47b5 Default to markdown for nodes from metadata 2025-08-14 12:25:10 -05:00
Anthony Juckel
560abf4218 Only process node labels as markdown if properly delimited 2025-08-14 12:25:10 -05:00
Justin Greywolf
0943edc114 Update cypress/integration/rendering/flowchart.spec.js
Co-authored-by: Sidharth Vinod <github@sidharth.dev>
2025-08-14 12:25:10 -05:00
Knut Sveidqvist
40402a2bd9 Adding changeset 2025-08-14 12:25:10 -05:00
Knut Sveidqvist
dc51c027d6 Adding back create label for the cases where you do not want markdown text 2025-08-14 12:25:10 -05:00
13 changed files with 126 additions and 39 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Proper separation between strings and markdown strings

View File

@@ -58,7 +58,7 @@ jobs:
echo "EOF" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT
- name: Commit and create pull request - name: Commit and create pull request
uses: peter-evans/create-pull-request@46cdba753c74545733b821043d64bd6925fc4da9 uses: peter-evans/create-pull-request@915d841dae6a4f191bb78faf61a257411d7be4d2
with: with:
add-paths: | add-paths: |
cypress/timings.json cypress/timings.json

View File

@@ -1174,8 +1174,8 @@ end
end end
githost["Github, Gitlab, BitBucket, etc."] githost["Github, Gitlab, BitBucket, etc."]
githost2["\`Github, Gitlab, BitBucket, etc.\`"] githost2["\`Github, Gitlab, BitBucket, etc.\`"]
a["1."] a["\`1.\`"]
b["- x"] b["\`- x\`"]
`; `;
it('should render raw strings', () => { it('should render raw strings', () => {

View File

@@ -973,4 +973,49 @@ 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' }
);
});
}); });

View File

@@ -10,7 +10,7 @@
# Interface: ParseOptions # Interface: ParseOptions
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88) Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mer
> `optional` **suppressErrors**: `boolean` > `optional` **suppressErrors**: `boolean`
Defined in: [packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93) Defined in: [packages/mermaid/src/types.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L94)
If `true`, parse will return `false` instead of throwing error when the diagram is invalid. If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
The `parseError` function will not be called. The `parseError` function will not be called.

View File

@@ -10,7 +10,7 @@
# Interface: ParseResult # Interface: ParseResult
Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96) Defined in: [packages/mermaid/src/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L97)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mer
> **config**: [`MermaidConfig`](MermaidConfig.md) > **config**: [`MermaidConfig`](MermaidConfig.md)
Defined in: [packages/mermaid/src/types.ts:104](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L104) Defined in: [packages/mermaid/src/types.ts:105](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L105)
The config passed as YAML frontmatter or directives The config passed as YAML frontmatter or directives
@@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives
> **diagramType**: `string` > **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100) Defined in: [packages/mermaid/src/types.ts:101](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L101)
The diagram type, e.g. 'flowchart', 'sequence', etc. The diagram type, e.g. 'flowchart', 'sequence', etc.

View File

@@ -10,7 +10,7 @@
# Interface: RenderResult # Interface: RenderResult
Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114) Defined in: [packages/mermaid/src/types.ts:115](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L115)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/me
> `optional` **bindFunctions**: (`element`) => `void` > `optional` **bindFunctions**: (`element`) => `void`
Defined in: [packages/mermaid/src/types.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L132) Defined in: [packages/mermaid/src/types.ts:133](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L133)
Bind function to be called after the svg has been inserted into the DOM. 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. 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` > **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L122) Defined in: [packages/mermaid/src/types.ts:123](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L123)
The diagram type, e.g. 'flowchart', 'sequence', etc. The diagram type, e.g. 'flowchart', 'sequence', etc.
@@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
> **svg**: `string` > **svg**: `string`
Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118) Defined in: [packages/mermaid/src/types.ts:119](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L119)
The svg code for the rendered graph. The svg code for the rendered graph.

View File

@@ -85,6 +85,17 @@ export class FlowDB implements DiagramDB {
return common.sanitizeText(txt, this.config); 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. * Function to lookup domId from id in the graph definition.
* *
@@ -208,6 +219,7 @@ export class FlowDB implements DiagramDB {
if (doc?.label) { if (doc?.label) {
vertex.text = doc?.label; vertex.text = doc?.label;
vertex.labelType = this.sanitizeNodeLabelType(doc?.labelType);
} }
if (doc?.icon) { if (doc?.icon) {
vertex.icon = doc?.icon; vertex.icon = doc?.icon;
@@ -267,7 +279,7 @@ export class FlowDB implements DiagramDB {
if (edge.text.startsWith('"') && edge.text.endsWith('"')) { if (edge.text.startsWith('"') && edge.text.endsWith('"')) {
edge.text = edge.text.substring(1, edge.text.length - 1); edge.text = edge.text.substring(1, edge.text.length - 1);
} }
edge.labelType = linkTextObj.type; edge.labelType = this.sanitizeNodeLabelType(linkTextObj.type);
} }
if (type !== undefined) { if (type !== undefined) {
@@ -702,7 +714,7 @@ You have to call mermaid.initialize.`
title: title.trim(), title: title.trim(),
classes: [], classes: [],
dir, dir,
labelType: _title.type, labelType: this.sanitizeNodeLabelType(_title?.type),
}; };
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir); log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
@@ -1012,6 +1024,7 @@ You have to call mermaid.initialize.`
const baseNode = { const baseNode = {
id: vertex.id, id: vertex.id,
label: vertex.text, label: vertex.text,
labelType: vertex.labelType,
labelStyle: '', labelStyle: '',
parentId, parentId,
padding: config.flowchart?.padding || 8, padding: config.flowchart?.padding || 8,
@@ -1088,6 +1101,7 @@ You have to call mermaid.initialize.`
id: subGraph.id, id: subGraph.id,
label: subGraph.title, label: subGraph.title,
labelStyle: '', labelStyle: '',
labelType: subGraph.labelType,
parentId: parentDB.get(subGraph.id), parentId: parentDB.get(subGraph.id),
padding: 8, padding: 8,
cssCompiledStyles: this.getCompiledStyles(subGraph.classes), cssCompiledStyles: this.getCompiledStyles(subGraph.classes),
@@ -1119,6 +1133,7 @@ You have to call mermaid.initialize.`
end: rawEdge.end, end: rawEdge.end,
type: rawEdge.type ?? 'normal', type: rawEdge.type ?? 'normal',
label: rawEdge.text, label: rawEdge.text,
labelType: rawEdge.labelType,
labelpos: 'c', labelpos: 'c',
thickness: rawEdge.stroke, thickness: rawEdge.stroke,
minlen: rawEdge.length, minlen: rawEdge.length,

View File

@@ -29,7 +29,7 @@ export interface FlowVertex {
domId: string; domId: string;
haveCallback?: boolean; haveCallback?: boolean;
id: string; id: string;
labelType: 'text'; labelType: 'markdown' | 'string' | 'text';
link?: string; link?: string;
linkTarget?: string; linkTarget?: string;
props?: any; props?: any;
@@ -62,7 +62,7 @@ export interface FlowEdge {
style?: string[]; style?: string[];
length?: number; length?: number;
text: string; text: string;
labelType: 'text'; labelType: 'markdown' | 'string' | 'text';
classes: string[]; classes: string[];
id?: string; id?: string;
animation?: 'fast' | 'slow'; animation?: 'fast' | 'slow';

View File

@@ -30,11 +30,17 @@ const rect = async (parent, node) => {
// Create the label and insert it after the rect // Create the label and insert it after the rect
const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label ');
const text = await createText(labelEl, node.label, { let text;
if (node.labelType === 'markdown') {
text = await createText(labelEl, node.label, {
style: node.labelStyle, style: node.labelStyle,
useHtmlLabels, useHtmlLabels,
isNode: true, isNode: true,
}); });
} else {
const labelElement = await createLabel(node.label, node.labelStyle, false, true);
text = labelEl.node()?.appendChild(labelElement);
}
// Get the size of the label // Get the size of the label
let bbox = text.getBBox(); let bbox = text.getBBox();

View File

@@ -29,7 +29,7 @@ import {
import rough from 'roughjs'; import rough from 'roughjs';
import createLabel from './createLabel.js'; import createLabel from './createLabel.js';
import { addEdgeMarkers } from './edgeMarker.ts'; import { addEdgeMarkers } from './edgeMarker.ts';
import { isLabelStyle, styles2String } from './shapes/handDrawnShapeStyles.js'; import { isLabelStyle } from './shapes/handDrawnShapeStyles.js';
export const edgeLabels = new Map(); export const edgeLabels = new Map();
export const terminalLabels = new Map(); export const terminalLabels = new Map();
@@ -47,14 +47,16 @@ export const getLabelStyles = (styleArray) => {
export const insertEdgeLabel = async (elem, edge) => { export const insertEdgeLabel = async (elem, edge) => {
let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
const { labelStyles } = styles2String(edge); const labelElement =
edge.labelStyle = labelStyles; edge.labelType === 'markdown'
const labelElement = await createText(elem, edge.label, { ? await createText(elem, edge.label, {
style: edge.labelStyle, style: getLabelStyles(edge.labelStyle),
useHtmlLabels, useHtmlLabels,
addSvgBackground: true, addSvgBackground: true,
isNode: false, isNode: false,
}); })
: await createLabel(edge.label, getLabelStyles(edge.labelStyle), undefined, false);
log.info('abc82', edge, edge.labelType); log.info('abc82', edge, edge.labelType);
// Create outer g, edgeLabel, this will be positioned after graph layout // Create outer g, edgeLabel, this will be positioned after graph layout

View File

@@ -1,3 +1,4 @@
import createLabel from '../createLabel.js';
import { createText } from '../../createText.js'; import { createText } from '../../createText.js';
import type { Node } from '../../types.js'; import type { Node } from '../../types.js';
import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js';
@@ -13,7 +14,7 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
_classes?: string _classes?: string
) => { ) => {
let cssClasses; let cssClasses;
const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.htmlLabels); const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.flowchart?.htmlLabels);
if (!_classes) { if (!_classes) {
cssClasses = 'node default'; cssClasses = 'node default';
} else { } else {
@@ -40,7 +41,9 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
label = typeof node.label === 'string' ? node.label : node.label[0]; label = typeof node.label === 'string' ? node.label : node.label[0];
} }
const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { let text;
if (node.labelType === 'markdown') {
text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
useHtmlLabels, useHtmlLabels,
width: node.width || getConfig().flowchart?.wrappingWidth, width: node.width || getConfig().flowchart?.wrappingWidth,
// @ts-expect-error -- This is currently not used. Should this be `classes` instead? // @ts-expect-error -- This is currently not used. Should this be `classes` instead?
@@ -48,6 +51,16 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
style: node.labelStyle, style: node.labelStyle,
addSvgBackground: !!node.icon || !!node.img, addSvgBackground: !!node.icon || !!node.img,
}); });
} else {
const labelElement = await createLabel(
sanitizeText(decodeEntities(label), getConfig()),
node.labelStyle,
false,
true
);
text = labelEl.node()?.appendChild(labelElement);
}
// Get the size of the label // Get the size of the label
let bbox = text.getBBox(); let bbox = text.getBBox();
const halfPadding = (node?.padding ?? 0) / 2; const halfPadding = (node?.padding ?? 0) / 2;

View File

@@ -1,6 +1,7 @@
export interface NodeMetaData { export interface NodeMetaData {
shape?: string; shape?: string;
label?: string; label?: string;
labelType?: string;
icon?: string; icon?: string;
form?: string; form?: string;
pos?: 't' | 'b'; pos?: 't' | 'b';