Compare commits

...

8 Commits

Author SHA1 Message Date
darshanr0107
920d55402c fix: update styling to match Agros
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-16 15:48:48 +05:30
darshanr0107
eb373ef207 fix: Move HTML entity decoding logic from generic insertEdgeLabel to requirement-specific getData method
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-16 13:56:12 +05:30
darshanr0107
5be5415eee fix: requirement diagram edge labels not rendering correctly with htmlLabels=false
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-16 13:09:20 +05:30
darshanr0107
1f6d235d23 fix: failing flowchart tests
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-15 19:05:05 +05:30
darshanr0107
464ff95e5b fix: breaking edge labels
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-15 18:15:14 +05:30
darshanr0107
ade130747e Merge branch 'develop' of https://github.com/mermaid-js/mermaid into fix/html-labels-false-edge-labels 2025-09-15 16:17:44 +05:30
autofix-ci[bot]
b85f75d434 [autofix.ci] apply automated fixes 2025-09-09 13:46:21 +00:00
darshanr0107
810071c46b fix: ensure edge labels respect htmlLabels=false
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-09 19:08:00 +05:30
11 changed files with 106 additions and 31 deletions

View File

@@ -122,6 +122,46 @@ describe('Flowchart v2', () => {
expect(svg).to.not.have.attr('style');
});
});
it('renders only pure SVG labels (no <foreignObject>) 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 <foreignObject>) 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(

View File

@@ -10,7 +10,7 @@
# Interface: DetailedError
Defined in: [packages/mermaid/src/utils.ts:783](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L783)
Defined in: [packages/mermaid/src/utils.ts:784](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L784)
## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/utils.ts:783](https://github.com/mermaid-js/me
> `optional` **error**: `any`
Defined in: [packages/mermaid/src/utils.ts:788](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L788)
Defined in: [packages/mermaid/src/utils.ts:789](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L789)
---
@@ -26,7 +26,7 @@ Defined in: [packages/mermaid/src/utils.ts:788](https://github.com/mermaid-js/me
> **hash**: `any`
Defined in: [packages/mermaid/src/utils.ts:786](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L786)
Defined in: [packages/mermaid/src/utils.ts:787](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L787)
---
@@ -34,7 +34,7 @@ Defined in: [packages/mermaid/src/utils.ts:786](https://github.com/mermaid-js/me
> `optional` **message**: `string`
Defined in: [packages/mermaid/src/utils.ts:789](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L789)
Defined in: [packages/mermaid/src/utils.ts:790](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L790)
---
@@ -42,4 +42,4 @@ Defined in: [packages/mermaid/src/utils.ts:789](https://github.com/mermaid-js/me
> **str**: `string`
Defined in: [packages/mermaid/src/utils.ts:784](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L784)
Defined in: [packages/mermaid/src/utils.ts:785](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/utils.ts#L785)

View File

@@ -33,10 +33,7 @@ const getStyles = (options: FlowChartStyleOptions) =>
background-color: ${fade(options.tertiaryColor, 0.5)};
}
.edgeLabel .label {
fill: ${options.nodeBorder};
font-size: 14px;
}
.label {
font-family: ${options.fontFamily};
@@ -68,6 +65,14 @@ const getStyles = (options: FlowChartStyleOptions) =>
stroke: ${options.lineColor} !important;
stroke-width: 1;
}
.background {
fill: ${options.tertiaryColor};
opacity: 0.7;
background-color: ${options.tertiaryColor};
rect {
opacity: 0.5;
}
}
`;
export default getStyles;

View File

@@ -2,6 +2,7 @@ import { getConfig } from '../../diagram-api/diagramAPI.js';
import type { DiagramDB } from '../../diagram-api/types.js';
import { log } from '../../logger.js';
import type { Node, Edge } from '../../rendering-util/types.js';
import { shouldUseHtmlLabels } from '../../utils.js';
import {
setAccTitle,
@@ -317,11 +318,17 @@ export class RequirementDB implements DiagramDB {
for (const relation of this.relations) {
let counter = 0;
const isContains = relation.type === this.Relationships.CONTAINS;
let relationLabel = `&lt;&lt;${relation.type}&gt;&gt;`;
if (!shouldUseHtmlLabels()) {
relationLabel = relationLabel.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
}
const edge: Edge = {
id: `${relation.src}-${relation.dst}-${counter}`,
start: this.requirements.get(relation.src)?.name ?? this.elements.get(relation.src)?.name,
end: this.requirements.get(relation.dst)?.name ?? this.elements.get(relation.dst)?.name,
label: `&lt;&lt;${relation.type}&gt;&gt;`,
label: relationLabel,
classes: 'relationshipLine',
style: ['fill:none', isContains ? '' : 'stroke-dasharray: 10,7'],
labelpos: 'c',

View File

@@ -55,6 +55,11 @@ const getStyles = (options) => `
.labelBkg {
background-color: ${options.edgeLabelBackground};
}
.background {
fill: ${options.edgeLabelBackground};
stroke: none;
}
`;
// fill', conf.rect_fill)

View File

@@ -176,8 +176,9 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) {
if (index === 0) {
innerTspan.text(word.content);
} else {
// TODO: check what joiner to use.
innerTspan.text(' ' + word.content);
const prev = wrappedLine[index - 1].content;
const insertSpace = !prev.endsWith('<') && !word.content.startsWith('>');
innerTspan.text((insertSpace ? ' ' : '') + word.content);
}
});
}

View File

@@ -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 ');

View File

@@ -1,13 +1,12 @@
import { select } from 'd3';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import common, {
evaluate,
hasKatex,
renderKatexSanitized,
sanitizeText,
} from '../../diagrams/common/common.js';
import { log } from '../../logger.js';
import { decodeEntities } from '../../utils.js';
import { decodeEntities, shouldUseHtmlLabels } from '../../utils.js';
/**
* @param dom
@@ -63,8 +62,7 @@ const createLabel = async (_vertexText, style, isTitle, isNode) => {
if (typeof vertexText === 'object') {
vertexText = vertexText[0];
}
if (evaluate(getConfig().flowchart.htmlLabels)) {
if (shouldUseHtmlLabels()) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
vertexText = vertexText.replace(/\\n|\n/g, '<br />');
log.info('vertexText' + vertexText);

View File

@@ -1,8 +1,7 @@
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { evaluate } 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,
markerOffsets,
@@ -45,10 +44,13 @@ export const getLabelStyles = (styleArray) => {
};
export const insertEdgeLabel = async (elem, edge) => {
let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
const useHtmlLabels = shouldUseHtmlLabels();
const { labelStyles } = styles2String(edge);
edge.labelStyle = labelStyles;
// if (useHtmlLabels === false) {
// edge.label = edge.label.replaceAll('&gt;', '>').replaceAll('&lt;', '<');
// }
const labelElement = await createText(elem, edge.label, {
style: edge.labelStyle,
useHtmlLabels,

View File

@@ -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 <T extends SVGGraphicsElement>(
@@ -13,7 +18,7 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
_classes?: string
) => {
let cssClasses;
const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.htmlLabels);
const useHtmlLabels = shouldUseHtmlLabels();
if (!_classes) {
cssClasses = 'node default';
} else {

View File

@@ -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;
};