Compare commits

..

2 Commits

Author SHA1 Message Date
darshanr0107
015af7603e chore: add changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-17 12:49:15 +05:30
darshanr0107
c810fab231 fix: handle backslash parsing in math formulas within new shape syntax
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-17 12:43:59 +05:30
10 changed files with 25 additions and 76 deletions

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Correct viewBox casing and make SVGs responsive

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Handle backslash parsing in math formulas within new flowchart shape syntax

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Allow IDs starting with L, R, T, or B in parser

View File

@@ -99,7 +99,6 @@ export const openURLAndVerifyRendering = (
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
cy.get('svg').should('not.have.attr', 'viewbox');
if (validation) {
cy.get('svg').should(validation);

View File

@@ -144,6 +144,16 @@ describe('when parsing directions', function () {
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('DD');
});
it('should handle mathematical formulas with backslashes in quoted strings', function () {
const res = flow.parser.parse(`flowchart TB
A@{ shape: rect, label: "$$\\sin x$$"}`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('rect');
expect(data4Layout.nodes[0].label).toEqual('$$\\sin x$$');
});
it('should be possible to link to a node with more data', function () {
const res = flow.parser.parse(`flowchart TB
A --> D@{

View File

@@ -53,6 +53,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multilin
// console.log('shapeData', yytext);
const re = /\n\s*/g;
yytext = yytext.replace(re,"<br/>");
yytext = yytext.replace(/\\/g, "\\\\");
return 'SHAPE_DATA'}
<shapeData>[^}^"]+ {
// console.log('shapeData', yytext);

View File

@@ -16,7 +16,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
const svgWidth = bitWidth * bitsPerRow + 2;
const svg: SVG = selectSvgElement(id);
svg.attr('viewBox', `0 0 ${svgWidth} ${svgHeight}`);
svg.attr('viewbox', `0 0 ${svgWidth} ${svgHeight}`);
configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth);
for (const [word, packet] of words.entries()) {

View File

@@ -2,7 +2,6 @@ import type { Diagram } from '../../Diagram.js';
import type { RadarDiagramConfig } from '../../config.type.js';
import type { DiagramRenderer, DrawDefinition, SVG, SVGGroup } from '../../diagram-api/types.js';
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { RadarDB, RadarAxis, RadarCurve } from './types.js';
const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
@@ -54,9 +53,11 @@ const drawFrame = (svg: SVG, config: Required<RadarDiagramConfig>): SVGGroup =>
x: config.marginLeft + config.width / 2,
y: config.marginTop + config.height / 2,
};
configureSvgSize(svg, totalHeight, totalWidth, config.useMaxWidth ?? true);
svg.attr('viewBox', `0 0 ${totalWidth} ${totalHeight}`);
// Initialize the SVG
svg
.attr('viewbox', `0 0 ${totalWidth} ${totalHeight}`)
.attr('width', totalWidth)
.attr('height', totalHeight);
// g element to center the radar chart
return svg.append('g').attr('transform', `translate(${center.x}, ${center.y})`);
};

View File

@@ -20,11 +20,11 @@ fragment Statement:
;
fragment LeftPort:
':' lhsDir=ID
':'lhsDir=ARROW_DIRECTION
;
fragment RightPort:
rhsDir=ID ':'
rhsDir=ARROW_DIRECTION':'
;
fragment Arrow:
@@ -47,5 +47,6 @@ Edge:
lhsId=ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ID rhsGroup?=ARROW_GROUP? EOL
;
terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B';
terminal ARROW_GROUP: /\{group\}/;
terminal ARROW_INTO: /<|>/;

View File

@@ -19,64 +19,6 @@ describe('architecture', () => {
});
});
describe('should handle services', () => {
it('should handle service with icon', () => {
const context = `architecture-beta
service TH(disk)
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(1);
expect(result.value.services?.[0].id).toBe('TH');
expect(result.value.services?.[0].icon).toBe('disk');
});
it('should handle service with icon starting with arrow direction letters', () => {
const context = `architecture-beta
service T(disk)
service TH(database)
service L(server)
service R(cloud)
service B(internet)
service TOP(disk)
service LEFT(disk)
service RIGHT(disk)
service BOTTOM(disk)
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(9);
});
it('should handle service with icon and title', () => {
const context = `architecture-beta
service db(database)[Database]
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(1);
expect(result.value.services?.[0].id).toBe('db');
expect(result.value.services?.[0].icon).toBe('database');
expect(result.value.services?.[0].title).toBe('Database');
});
it('should handle service in a group', () => {
const context = `architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(1);
expect(result.value.services?.[0].id).toBe('db');
expect(result.value.services?.[0].in).toBe('api');
});
});
describe('should handle TitleAndAccessibilities', () => {
it.each([
`architecture-beta title sample title`,