From 7e7354c40d6ae2d48a082e82ea6344e8b4a6ea6c Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 11 Nov 2025 19:13:25 +0530 Subject: [PATCH] fix: failing visual tests on-behalf-of: @Mermaid-Chart --- .../mermaid/src/rendering-util/createText.ts | 83 ++++++++++++++----- .../rendering-elements/shapes/util.ts | 30 +++---- 2 files changed, 73 insertions(+), 40 deletions(-) diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts index 759330390..e73459634 100644 --- a/packages/mermaid/src/rendering-util/createText.ts +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -26,7 +26,8 @@ async function addHtmlSpan( classes, addBackground = false, // TODO: Make config mandatory - config: MermaidConfig = getConfig() + config: MermaidConfig = getConfig(), + useLegacyStyle = false ) { const fo = element.append('foreignObject'); // This is not the final width but used in order to make sure the foreign @@ -35,28 +36,50 @@ async function addHtmlSpan( fo.attr('height', `${10 * width}px`); const div = fo.append('xhtml:div'); - const sanitizedLabel = hasKatex(node.label) - ? await renderKatexSanitized(node.label.replace(common.lineBreakRegex, '\n'), config) - : sanitizeText(node.label, config); const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; - const span = div.append('span'); - span.html(sanitizedLabel); - applyStyle(span, node.labelStyle); - span.attr('class', `${labelClass} ${classes}`); - applyStyle(div, node.labelStyle); - div.style('display', 'table-cell'); - div.style('white-space', 'nowrap'); - div.style('line-height', '1.5'); - div.style('max-width', width + 'px'); - div.style('text-align', 'center'); + if (useLegacyStyle) { + let label = node.label; + if (node.label && hasKatex(node.label)) { + label = await renderKatexSanitized(node.label.replace(common.lineBreakRegex, '\n'), config); + } + const labelSpan = + '' + + label + + ''; + div.html(sanitizeText(labelSpan, config)); + applyStyle(div, node.labelStyle); + div.style('display', 'inline-block'); + div.style('white-space', 'nowrap'); + div.style('padding-right', '1px'); + } else { + // Use new createText styling for markdown labels + const sanitizedLabel = hasKatex(node.label) + ? await renderKatexSanitized(node.label.replace(common.lineBreakRegex, '\n'), config) + : sanitizeText(node.label, config); + const span = div.append('span'); + span.html(sanitizedLabel); + applyStyle(span, node.labelStyle); + span.attr('class', `${labelClass} ${classes}`); + + applyStyle(div, node.labelStyle); + div.style('display', 'table-cell'); + div.style('white-space', 'nowrap'); + div.style('line-height', '1.5'); + div.style('max-width', width + 'px'); + div.style('text-align', 'center'); + } div.attr('xmlns', 'http://www.w3.org/1999/xhtml'); if (addBackground) { div.attr('class', 'labelBkg'); } let bbox = div.node().getBoundingClientRect(); - if (bbox.width === width) { + if (!useLegacyStyle && bbox.width === width) { div.style('display', 'table'); div.style('white-space', 'break-spaces'); div.style('width', width + 'px'); @@ -227,6 +250,7 @@ export const createText = async ( isNode = true, width = 200, addSvgBackground = false, + useLegacyStyle = false, } = {}, config?: MermaidConfig ) => { @@ -239,23 +263,42 @@ export const createText = async ( useHtmlLabels, isNode, 'addSvgBackground: ', - addSvgBackground + addSvgBackground, + 'useLegacyStyle: ', + useLegacyStyle ); if (useHtmlLabels) { // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const htmlText = markdownToHTML(text, config); - const decodedReplacedText = await replaceIconSubstring(decodeEntities(htmlText), config); + let processedLabel; + if (useLegacyStyle) { + const textWithBreaks = text.replace(/\\n|\n/g, '
'); + processedLabel = decodeEntities(textWithBreaks).replace( + /fa[blrs]?:fa-[\w-]+/g, + (s) => `` + ); + } else { + const htmlText = markdownToHTML(text, config); + processedLabel = await replaceIconSubstring(decodeEntities(htmlText), config); + } //for Katex the text could contain escaped characters, \\relax that should be transformed to \relax const inputForKatex = text.replace(/\\\\/g, '\\'); const node = { isNode, - label: hasKatex(text) ? inputForKatex : decodedReplacedText, + label: hasKatex(text) ? inputForKatex : processedLabel, labelStyle: style.replace('fill:', 'color:'), }; - const vertexNode = await addHtmlSpan(el, node, width, classes, addSvgBackground, config); + const vertexNode = await addHtmlSpan( + el, + node, + width, + classes, + addSvgBackground, + config, + useLegacyStyle + ); return vertexNode; } else { //sometimes the user might add br tags with 1 or more spaces in between, so we need to replace them with
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 5911f8f34..f7ab70401 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -1,4 +1,3 @@ -import createLabel from '../createLabel.js'; import { createText } from '../../createText.js'; import type { Node } from '../../types.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; @@ -41,26 +40,17 @@ export const labelHelper = async ( label = typeof node.label === 'string' ? node.label : node.label[0]; } - let text; - if (node.labelType === 'markdown') { - 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, - }); - } else { - const labelElement = await createLabel( - sanitizeText(decodeEntities(label), getConfig()), - node.labelStyle, - false, - true - ); - text = labelEl.node()?.appendChild(labelElement); - } + const useLegacyStyle = node.labelType !== 'markdown'; + 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, + useLegacyStyle, + }); // Get the size of the label let bbox = text.getBBox(); const halfPadding = (node?.padding ?? 0) / 2;