Compare commits

..

6 Commits

Author SHA1 Message Date
Sidharth Vinod
af3bbdc591 Merge pull request #6894 from mermaid-js/changeset-release/master
Version Packages
2025-08-22 17:37:05 +05:30
github-actions[bot]
8813cf2c94 Version Packages 2025-08-22 09:03:57 +00:00
Sidharth Vinod
d145c0e910 Merge pull request #6890 from mermaid-js/develop
Pre Release
2025-08-22 14:31:33 +05:30
Shubham P
29886b8dd4 Merge pull request #6886 from mermaid-js/6721/Bidirectional-arrows--render-incorrectly-with-autonumber-in-sequence-diagrams
6721: Correct rendering of bidirectional arrows with auto number
2025-08-21 15:57:22 +00:00
darshanr0107
e0b45c2d2b chore: added changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-08-21 19:15:30 +05:30
darshanr0107
d4c76968e9 fix: correct rendering of bidirectional arrows with autonumber
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-08-21 19:09:39 +05:30
11 changed files with 60 additions and 119 deletions

View File

@@ -893,6 +893,17 @@ describe('Sequence diagram', () => {
} }
); );
}); });
it('should handle bidirectional arrows with autonumber', () => {
imgSnapshotTest(`
sequenceDiagram
autonumber
participant A
participant B
A<<->>B: This is a bidirectional message
A->B: This is a normal message`);
});
it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => { it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => {
//Be aware that the syntax for "properties" is likely to be changed. //Be aware that the syntax for "properties" is likely to be changed.
imgSnapshotTest( imgSnapshotTest(

View File

@@ -12,7 +12,7 @@
> **addDirective**(`directive`): `void` > **addDirective**(`directive`): `void`
Defined in: [packages/mermaid/src/config.ts:202](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L202) Defined in: [packages/mermaid/src/config.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L188)
Pushes in a directive to the configuration Pushes in a directive to the configuration

View File

@@ -12,7 +12,7 @@
> **reset**(`config`): `void` > **reset**(`config`): `void`
Defined in: [packages/mermaid/src/config.ts:235](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L235) Defined in: [packages/mermaid/src/config.ts:221](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L221)
## reset ## reset

View File

@@ -10,7 +10,7 @@
# Function: sanitize() # Function: sanitize()
> **sanitize**(`options`, `path`): `void` > **sanitize**(`options`): `void`
Defined in: [packages/mermaid/src/config.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L146) Defined in: [packages/mermaid/src/config.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L146)
@@ -31,10 +31,6 @@ options in-place
The potential setConfig parameter The potential setConfig parameter
### path
`string`\[] = `[]`
## Returns ## Returns
`void` `void`

View File

@@ -1,5 +1,11 @@
# mermaid # mermaid
## 11.10.1
### Patch Changes
- [#6886](https://github.com/mermaid-js/mermaid/pull/6886) [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Handle arrows correctly when auto number is enabled
## 11.10.0 ## 11.10.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "mermaid", "name": "mermaid",
"version": "11.10.0", "version": "11.10.1",
"description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.", "description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.",
"type": "module", "type": "module",
"module": "./dist/mermaid.core.mjs", "module": "./dist/mermaid.core.mjs",

View File

@@ -34,92 +34,6 @@ describe('when working with site config', () => {
expect(cfg.fontSize).toBe(config_0.fontSize); expect(cfg.fontSize).toBe(config_0.fontSize);
expect(cfg.securityLevel).toBe(config_0.securityLevel); expect(cfg.securityLevel).toBe(config_0.securityLevel);
}); });
it('should respect nested secure keys when applying directives', () => {
const config_0: MermaidConfig = {
fontFamily: 'foo-font',
themeVariables: {
fontSize: 16,
fontFamily: 'default-font',
},
secure: [
...configApi.defaultConfig.secure!,
'themeVariables.fontSize',
'themeVariables.fontFamily',
],
};
configApi.setSiteConfig(config_0);
const directive: MermaidConfig = {
fontFamily: 'baf',
themeVariables: {
fontSize: 24, // shouldn't be changed
fontFamily: 'new-font', // shouldn't be changed
primaryColor: '#ff0000', // should be allowed
},
};
const cfg: MermaidConfig = configApi.updateCurrentConfig(config_0, [directive]);
expect(cfg.fontFamily).toEqual(directive.fontFamily);
expect(cfg.themeVariables!.fontSize).toBe(config_0.themeVariables!.fontSize);
expect(cfg.themeVariables!.fontFamily).toBe(config_0.themeVariables!.fontFamily);
expect(cfg.themeVariables!.primaryColor).toBe(directive.themeVariables!.primaryColor);
});
it('should handle deeply nested secure keys', () => {
const config_0: MermaidConfig = {
flowchart: {
nodeSpacing: 50,
rankSpacing: 50,
curve: 'basis',
htmlLabels: true,
useMaxWidth: true,
diagramPadding: 8,
},
secure: [
...configApi.defaultConfig.secure!,
'flowchart.nodeSpacing',
'flowchart.rankSpacing',
],
};
configApi.setSiteConfig(config_0);
const directive: MermaidConfig = {
flowchart: {
nodeSpacing: 100, // shouldn't be changed
rankSpacing: 100, // shouldn't be changed
curve: 'linear', // should be allowed
htmlLabels: false, // should be allowed
},
};
const cfg: MermaidConfig = configApi.updateCurrentConfig(config_0, [directive]);
expect(cfg.flowchart!.nodeSpacing).toBe(config_0.flowchart!.nodeSpacing);
expect(cfg.flowchart!.rankSpacing).toBe(config_0.flowchart!.rankSpacing);
expect(cfg.flowchart!.curve).toBe(directive.flowchart!.curve);
expect(cfg.flowchart!.htmlLabels).toBe(directive.flowchart!.htmlLabels);
expect(cfg.flowchart!.diagramPadding).toBe(config_0.flowchart!.diagramPadding);
});
it('should handle mixed top-level and nested secure keys', () => {
const config_0: MermaidConfig = {
fontFamily: 'foo-font',
themeVariables: {
fontSize: 16,
primaryColor: '#000000',
},
secure: [...configApi.defaultConfig.secure!, 'fontFamily', 'themeVariables.fontSize'],
};
configApi.setSiteConfig(config_0);
const directive: MermaidConfig = {
fontFamily: 'new-font', // shouldn't be changed
themeVariables: {
fontSize: 24, // shouldn't be changed
primaryColor: '#ff0000', // should be allowed
},
};
const cfg: MermaidConfig = configApi.updateCurrentConfig(config_0, [directive]);
expect(cfg.fontFamily).toBe(config_0.fontFamily);
expect(cfg.themeVariables!.fontSize).toBe(config_0.themeVariables!.fontSize);
expect(cfg.themeVariables!.primaryColor).toBe(directive.themeVariables!.primaryColor);
});
it('should allow setting partial options', () => { it('should allow setting partial options', () => {
const defaultConfig = configApi.getConfig(); const defaultConfig = configApi.getConfig();

View File

@@ -143,29 +143,17 @@ export const getConfig = (): MermaidConfig => {
* *
* @param options - The potential setConfig parameter * @param options - The potential setConfig parameter
*/ */
export const sanitize = (options: any, path: string[] = []) => { export const sanitize = (options: any) => {
if (!options) { if (!options) {
return; return;
} }
// Checking that options are not in the list of excluded options // Checking that options are not in the list of excluded options
['secure', ...(siteConfig.secure ?? [])].forEach((secureKey) => { ['secure', ...(siteConfig.secure ?? [])].forEach((key) => {
const securePath = secureKey.split('.'); if (Object.hasOwn(options, key)) {
// DO NOT attempt to print options[key] within `${}` as a malicious script
// Check if current path matches the secure key path // can exploit the logger's attempt to stringify the value and execute arbitrary code
if (path.length >= securePath.length - 1) { log.debug(`Denied attempt to modify a secure key ${key}`, options[key]);
const targetKey = securePath[securePath.length - 1]; delete options[key];
const pathSuffix = path.slice(-(securePath.length - 1));
const pathPrefix = securePath.slice(0, -1);
const isMatch =
securePath.length === 1 ? path.length === 0 : pathSuffix.join('.') === pathPrefix.join('.');
if (isMatch && Object.hasOwn(options, targetKey)) {
const fullPath = path.length > 0 ? `${path.join('.')}.${secureKey}` : secureKey;
log.debug(`Denied attempt to modify a secure key ${fullPath}`, options[targetKey]);
delete options[targetKey];
}
} }
}); });
@@ -175,7 +163,6 @@ export const sanitize = (options: any, path: string[] = []) => {
delete options[key]; delete options[key];
} }
}); });
// Check that there no attempts of xss, there should be no tags at all in the directive // Check that there no attempts of xss, there should be no tags at all in the directive
// blocking data urls as base64 urls can contain svg's with inline script tags // blocking data urls as base64 urls can contain svg's with inline script tags
Object.keys(options).forEach((key) => { Object.keys(options).forEach((key) => {
@@ -187,9 +174,8 @@ export const sanitize = (options: any, path: string[] = []) => {
) { ) {
delete options[key]; delete options[key];
} }
if (typeof options[key] === 'object' && options[key] !== null) { if (typeof options[key] === 'object') {
// Recursively sanitize nested objects with updated path sanitize(options[key]);
sanitize(options[key], [...path, key]);
} }
}); });
}; };

View File

@@ -476,7 +476,29 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
// add node number // add node number
if (sequenceVisible || conf.showSequenceNumbers) { if (sequenceVisible || conf.showSequenceNumbers) {
line.attr('marker-start', 'url(' + url + '#sequencenumber)'); const isBidirectional =
type === diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID ||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED;
if (isBidirectional) {
const SEQUENCE_NUMBER_RADIUS = 6;
if (startx < stopx) {
line.attr('x1', startx + 2 * SEQUENCE_NUMBER_RADIUS);
} else {
line.attr('x1', startx + SEQUENCE_NUMBER_RADIUS);
}
}
diagram
.append('line')
.attr('x1', startx)
.attr('y1', lineStartY)
.attr('x2', startx)
.attr('y2', lineStartY)
.attr('stroke-width', 0)
.attr('marker-start', 'url(' + url + '#sequencenumber)');
diagram diagram
.append('text') .append('text')
.attr('x', startx) .attr('x', startx)

View File

@@ -1,5 +1,11 @@
# mermaid # mermaid
## 11.10.1
### Patch Changes
- [#6886](https://github.com/mermaid-js/mermaid/pull/6886) [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Handle arrows correctly when auto number is enabled
## 11.10.0 ## 11.10.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mermaid-js/tiny", "name": "@mermaid-js/tiny",
"version": "11.10.0", "version": "11.10.1",
"description": "Tiny version of mermaid", "description": "Tiny version of mermaid",
"type": "commonjs", "type": "commonjs",
"main": "./dist/mermaid.tiny.js", "main": "./dist/mermaid.tiny.js",