From 810071c46b28b03b5492818c70a1ff1732dd68b2 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 9 Sep 2025 19:08:00 +0530 Subject: [PATCH] fix: ensure edge labels respect htmlLabels=false on-behalf-of: @Mermaid-Chart --- .../rendering/flowchart-v2.spec.js | 40 +++++++++++++++++++ .../rendering-elements/clusters.js | 4 +- .../rendering-elements/edges.js | 7 ++-- .../rendering-elements/shapes/util.ts | 9 ++++- packages/mermaid/src/utils.ts | 28 +++++++++---- 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 8c6cde57a..85f17a104 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -122,6 +122,46 @@ describe('Flowchart v2', () => { expect(svg).to.not.have.attr('style'); }); }); + it('renders only pure SVG labels (no ) when flowchart.htmlLabels=false', () => { + renderGraph( + `--- +config: + flowchart: + htmlLabels: false +--- + flowchart LR + subgraph \`**One**\` + a["\`**The cat** + in the hat\`"] -- "\`**edge label**\`" --> b{{"\`**The dog** in the hog\`"}} + end + subgraph \`**Two**\` + c["\`**The cat** + in the hat\`"] -- "\`**Bold edge label**\`" --> d["\`The dog in the hog\`"] + end + ` + ); + cy.get('svg').find('foreignObject').should('not.exist'); + }); + + it('renders only pure SVG labels (no ) when global htmlLabels=false', () => { + renderGraph( + `--- +config: + htmlLabels: false +--- + flowchart LR + subgraph \`**One**\` + a["\`**The cat** + in the hat\`"] -- "\`**edge label**\`" --> b{{"\`**The dog** in the hog\`"}} + end + subgraph \`**Two**\` + c["\`**The cat** + in the hat\`"] -- "\`**Bold edge label**\`" --> d["\`The dog in the hog\`"] + end + ` + ); + cy.get('svg').find('foreignObject').should('not.exist'); + }); it('V2 - 16: Render Stadium shape', () => { imgSnapshotTest( diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 1dd87d438..7fd980222 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -9,6 +9,7 @@ import intersectRect from '../rendering-elements/intersect/intersect-rect.js'; import createLabel from './createLabel.js'; import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; import { styles2String, userNodeOverrides } from './shapes/handDrawnShapeStyles.js'; +import { shouldUseHtmlLabels } from '../../utils.js'; const rect = async (parent, node) => { log.info('Creating subgraph rect for ', node.id, node); @@ -25,8 +26,7 @@ const rect = async (parent, node) => { .attr('id', node.id) .attr('data-look', node.look); - const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); - + const useHtmlLabels = shouldUseHtmlLabels(); // Create the label and insert it after the rect const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 3292b3811..b37e16567 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -1,8 +1,8 @@ import { getConfig } from '../../diagram-api/diagramAPI.js'; -import { evaluate, getUrl } from '../../diagrams/common/common.js'; +import { getUrl } from '../../diagrams/common/common.js'; import { log } from '../../logger.js'; import { createText } from '../createText.js'; -import utils from '../../utils.js'; +import utils, { shouldUseHtmlLabels } from '../../utils.js'; import { getLineFunctionsWithOffset } from '../../utils/lineWithOffset.js'; import { getSubGraphTitleMargins } from '../../utils/subGraphTitleMargins.js'; @@ -41,8 +41,7 @@ export const getLabelStyles = (styleArray) => { }; export const insertEdgeLabel = async (elem, edge) => { - let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); - + const useHtmlLabels = shouldUseHtmlLabels(); const labelElement = await createText(elem, edge.label, { style: getLabelStyles(edge.labelStyle), useHtmlLabels, 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 52471ecc0..ffd5f4145 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,12 @@ import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { select } from 'd3'; import defaultConfig from '../../../defaultConfig.js'; import { evaluate, sanitizeText } from '../../../diagrams/common/common.js'; -import { decodeEntities, handleUndefinedAttr, parseFontSize } from '../../../utils.js'; +import { + decodeEntities, + handleUndefinedAttr, + parseFontSize, + shouldUseHtmlLabels, +} from '../../../utils.js'; import type { D3Selection, Point } from '../../../types.js'; export const labelHelper = async ( @@ -13,7 +18,7 @@ export const labelHelper = async ( _classes?: string ) => { let cssClasses; - const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.htmlLabels); + const useHtmlLabels = shouldUseHtmlLabels(); if (!_classes) { cssClasses = 'node default'; } else { diff --git a/packages/mermaid/src/utils.ts b/packages/mermaid/src/utils.ts index 0f1bfbecf..b46f7c84a 100644 --- a/packages/mermaid/src/utils.ts +++ b/packages/mermaid/src/utils.ts @@ -7,12 +7,12 @@ import { curveBumpX, curveBumpY, curveBundle, + curveCardinal, curveCardinalClosed, curveCardinalOpen, - curveCardinal, + curveCatmullRom, curveCatmullRomClosed, curveCatmullRomOpen, - curveCatmullRom, curveLinear, curveLinearClosed, curveMonotoneX, @@ -23,16 +23,17 @@ import { curveStepBefore, select, } from 'd3'; -import common from './diagrams/common/common.js'; -import { sanitizeDirective } from './utils/sanitizeDirective.js'; -import { log } from './logger.js'; -import { detectType } from './diagram-api/detectType.js'; -import assignWithDepth from './assignWithDepth.js'; -import type { MermaidConfig } from './config.type.js'; import memoize from 'lodash-es/memoize.js'; import merge from 'lodash-es/merge.js'; +import assignWithDepth from './assignWithDepth.js'; +import { getUserDefinedConfig } from './config.js'; +import type { MermaidConfig } from './config.type.js'; +import { detectType } from './diagram-api/detectType.js'; import { directiveRegex } from './diagram-api/regexes.js'; +import common, { evaluate } from './diagrams/common/common.js'; +import { log } from './logger.js'; import type { D3Element, Point, TextDimensionConfig, TextDimensions } from './types.js'; +import { sanitizeDirective } from './utils/sanitizeDirective.js'; export const ZERO_WIDTH_SPACE = '\u200b'; @@ -981,3 +982,14 @@ export function isLabelCoordinateInPath(point: Point, dAttr: string) { return sanitizedD.includes(roundedX.toString()) || sanitizedD.includes(roundedY.toString()); } + +export const shouldUseHtmlLabels = () => { + const siteConfig = getUserDefinedConfig(); + let useHtmlLabels; + if (siteConfig.flowchart?.htmlLabels !== undefined) { + useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); + } else { + useHtmlLabels = evaluate(siteConfig.htmlLabels); + } + return useHtmlLabels; +};