diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index 2bbfa8412..21dbda293 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -58,7 +58,7 @@ jobs: echo "EOF" >> $GITHUB_OUTPUT - name: Commit and create pull request - uses: peter-evans/create-pull-request@cb4d3bfce175d44325c6b7697f81e0afe8a79bdf + uses: peter-evans/create-pull-request@18e469570b1cf0dfc11d60ec121099f8ff3e617a with: add-paths: | cypress/timings.json diff --git a/cypress/timings.json b/cypress/timings.json index 86d5b5222..5708c3414 100644 --- a/cypress/timings.json +++ b/cypress/timings.json @@ -2,219 +2,223 @@ "durations": [ { "spec": "cypress/integration/other/configuration.spec.js", - "duration": 6297 + "duration": 6162 }, { "spec": "cypress/integration/other/external-diagrams.spec.js", - "duration": 2187 + "duration": 2148 }, { "spec": "cypress/integration/other/ghsa.spec.js", - "duration": 3509 + "duration": 3585 }, { "spec": "cypress/integration/other/iife.spec.js", - "duration": 2218 + "duration": 2099 }, { "spec": "cypress/integration/other/interaction.spec.js", - "duration": 12104 + "duration": 12119 }, { "spec": "cypress/integration/other/rerender.spec.js", - "duration": 2151 + "duration": 2063 }, { "spec": "cypress/integration/other/xss.spec.js", - "duration": 33064 + "duration": 31921 }, { "spec": "cypress/integration/rendering/appli.spec.js", - "duration": 3488 + "duration": 3385 }, { "spec": "cypress/integration/rendering/architecture.spec.ts", - "duration": 106 + "duration": 108 }, { "spec": "cypress/integration/rendering/block.spec.js", - "duration": 18317 + "duration": 18063 }, { "spec": "cypress/integration/rendering/c4.spec.js", - "duration": 5592 + "duration": 5519 }, { "spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js", - "duration": 39358 + "duration": 40040 }, { "spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js", - "duration": 37160 + "duration": 38665 }, { "spec": "cypress/integration/rendering/classDiagram-v2.spec.js", - "duration": 23660 + "duration": 22836 }, { "spec": "cypress/integration/rendering/classDiagram-v3.spec.js", - "duration": 36866 + "duration": 37096 }, { "spec": "cypress/integration/rendering/classDiagram.spec.js", - "duration": 17334 + "duration": 16452 }, { "spec": "cypress/integration/rendering/conf-and-directives.spec.js", - "duration": 9871 + "duration": 10387 }, { "spec": "cypress/integration/rendering/current.spec.js", - "duration": 2833 + "duration": 2803 }, { "spec": "cypress/integration/rendering/erDiagram-unified.spec.js", - "duration": 85321 + "duration": 86891 }, { "spec": "cypress/integration/rendering/erDiagram.spec.js", - "duration": 15673 + "duration": 15206 }, { "spec": "cypress/integration/rendering/errorDiagram.spec.js", - "duration": 3724 + "duration": 3540 }, { "spec": "cypress/integration/rendering/flowchart-elk.spec.js", - "duration": 41178 + "duration": 41975 }, { "spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js", - "duration": 29966 + "duration": 30909 }, { "spec": "cypress/integration/rendering/flowchart-icon.spec.js", - "duration": 7689 + "duration": 7881 }, { "spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts", - "duration": 24709 + "duration": 24294 }, { "spec": "cypress/integration/rendering/flowchart-v2.spec.js", - "duration": 45565 + "duration": 47652 }, { "spec": "cypress/integration/rendering/flowchart.spec.js", - "duration": 31144 + "duration": 32049 }, { "spec": "cypress/integration/rendering/gantt.spec.js", - "duration": 20808 + "duration": 20248 }, { "spec": "cypress/integration/rendering/gitGraph.spec.js", - "duration": 49985 + "duration": 51202 }, { "spec": "cypress/integration/rendering/iconShape.spec.ts", - "duration": 273272 + "duration": 283546 }, { "spec": "cypress/integration/rendering/imageShape.spec.ts", - "duration": 55880 + "duration": 57257 }, { "spec": "cypress/integration/rendering/info.spec.ts", - "duration": 3271 + "duration": 3352 }, { "spec": "cypress/integration/rendering/journey.spec.js", - "duration": 7293 + "duration": 7423 }, { "spec": "cypress/integration/rendering/kanban.spec.ts", - "duration": 7861 + "duration": 7804 }, { "spec": "cypress/integration/rendering/katex.spec.js", - "duration": 3922 + "duration": 3847 }, { "spec": "cypress/integration/rendering/marker_unique_id.spec.js", - "duration": 2726 + "duration": 2637 }, { "spec": "cypress/integration/rendering/mindmap.spec.ts", - "duration": 11670 + "duration": 11658 }, { "spec": "cypress/integration/rendering/newShapes.spec.ts", - "duration": 146020 + "duration": 149500 }, { "spec": "cypress/integration/rendering/oldShapes.spec.ts", - "duration": 114244 + "duration": 115427 }, { "spec": "cypress/integration/rendering/packet.spec.ts", - "duration": 5036 + "duration": 4801 }, { "spec": "cypress/integration/rendering/pie.spec.ts", - "duration": 6545 + "duration": 6786 }, { "spec": "cypress/integration/rendering/quadrantChart.spec.js", - "duration": 9097 + "duration": 9422 }, { "spec": "cypress/integration/rendering/radar.spec.js", - "duration": 5676 + "duration": 5652 }, { "spec": "cypress/integration/rendering/requirement.spec.js", - "duration": 2795 + "duration": 2787 }, { "spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js", - "duration": 51660 + "duration": 53631 }, { "spec": "cypress/integration/rendering/sankey.spec.ts", - "duration": 6957 + "duration": 7075 + }, + { + "spec": "cypress/integration/rendering/sequencediagram-v2.spec.js", + "duration": 20446 }, { "spec": "cypress/integration/rendering/sequencediagram.spec.js", - "duration": 36026 + "duration": 37326 }, { "spec": "cypress/integration/rendering/stateDiagram-v2.spec.js", - "duration": 29551 + "duration": 29208 }, { "spec": "cypress/integration/rendering/stateDiagram.spec.js", - "duration": 17364 + "duration": 16328 }, { "spec": "cypress/integration/rendering/theme.spec.js", - "duration": 30209 + "duration": 30541 }, { "spec": "cypress/integration/rendering/timeline.spec.ts", - "duration": 8699 + "duration": 8611 }, { "spec": "cypress/integration/rendering/treemap.spec.ts", - "duration": 12168 + "duration": 11878 }, { "spec": "cypress/integration/rendering/xyChart.spec.js", - "duration": 21453 + "duration": 20400 }, { "spec": "cypress/integration/rendering/zenuml.spec.js", - "duration": 3577 + "duration": 3528 } ] } diff --git a/docs/config/setup/config/README.md b/docs/config/setup/config/README.md index 67fca78eb..c811c7b08 100644 --- a/docs/config/setup/config/README.md +++ b/docs/config/setup/config/README.md @@ -19,6 +19,7 @@ - [addDirective](functions/addDirective.md) - [getConfig](functions/getConfig.md) - [getSiteConfig](functions/getSiteConfig.md) +- [getUserDefinedConfig](functions/getUserDefinedConfig.md) - [reset](functions/reset.md) - [sanitize](functions/sanitize.md) - [saveConfigFromInitialize](functions/saveConfigFromInitialize.md) diff --git a/docs/config/setup/config/functions/getUserDefinedConfig.md b/docs/config/setup/config/functions/getUserDefinedConfig.md new file mode 100644 index 000000000..ed39f1337 --- /dev/null +++ b/docs/config/setup/config/functions/getUserDefinedConfig.md @@ -0,0 +1,19 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md). + +[**mermaid**](../../README.md) + +--- + +# Function: getUserDefinedConfig() + +> **getUserDefinedConfig**(): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) + +Defined in: [packages/mermaid/src/config.ts:252](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L252) + +## Returns + +[`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md) diff --git a/docs/syntax/flowchart.md b/docs/syntax/flowchart.md index daaa29581..08c145f6f 100644 --- a/docs/syntax/flowchart.md +++ b/docs/syntax/flowchart.md @@ -983,11 +983,23 @@ flowchart TD - `b` - **w**: The width of the image. If not defined, this will default to the natural width of the image. - **h**: The height of the image. If not defined, this will default to the natural height of the image. -- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are: +- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the width (`w`) accordingly to the height (`h`). If not defined, this will default to `off` Possible values are: - `on` - `off` -These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging. +If you want to resize an image, but keep the same aspect ratio, set `h`, and set `constraint: on` to constrain the aspect ratio. E.g. + +```mermaid-example +flowchart TD + %% My image with a constrained aspect ratio + A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" } +``` + +```mermaid +flowchart TD + %% My image with a constrained aspect ratio + A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" } +``` ## Links between nodes diff --git a/packages/mermaid/src/config.spec.ts b/packages/mermaid/src/config.spec.ts index 000be1282..7fbae03af 100644 --- a/packages/mermaid/src/config.spec.ts +++ b/packages/mermaid/src/config.spec.ts @@ -78,3 +78,187 @@ describe('when working with site config', () => { expect(config_4.altFontFamily).toBeUndefined(); }); }); + +describe('getUserDefinedConfig', () => { + beforeEach(() => { + configApi.reset(); + }); + + it('should return empty object when no user config is defined', () => { + const userConfig = configApi.getUserDefinedConfig(); + expect(userConfig).toEqual({}); + }); + + it('should return config from initialize only', () => { + const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial' }; + configApi.saveConfigFromInitialize(initConfig); + + const userConfig = configApi.getUserDefinedConfig(); + expect(userConfig).toEqual(initConfig); + }); + + it('should return config from directives only', () => { + const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 }; + const directive2: MermaidConfig = { theme: 'forest' }; + + configApi.addDirective(directive1); + configApi.addDirective(directive2); + + expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(` + { + "fontFamily": "Arial", + "fontSize": 14, + "layout": "elk", + "theme": "forest", + } + `); + }); + + it('should combine initialize config and directives', () => { + const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial', layout: 'dagre' }; + const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 }; + const directive2: MermaidConfig = { theme: 'forest' }; + + configApi.saveConfigFromInitialize(initConfig); + configApi.addDirective(directive1); + configApi.addDirective(directive2); + + const userConfig = configApi.getUserDefinedConfig(); + expect(userConfig).toMatchInlineSnapshot(` + { + "fontFamily": "Arial", + "fontSize": 14, + "layout": "elk", + "theme": "forest", + } + `); + }); + + it('should handle nested config objects properly', () => { + const initConfig: MermaidConfig = { + flowchart: { nodeSpacing: 50, rankSpacing: 100 }, + theme: 'default', + }; + const directive: MermaidConfig = { + flowchart: { nodeSpacing: 75, curve: 'basis' }, + mindmap: { padding: 20 }, + }; + + configApi.saveConfigFromInitialize(initConfig); + configApi.addDirective(directive); + + const userConfig = configApi.getUserDefinedConfig(); + expect(userConfig).toMatchInlineSnapshot(` + { + "flowchart": { + "curve": "basis", + "nodeSpacing": 75, + "rankSpacing": 100, + }, + "mindmap": { + "padding": 20, + }, + "theme": "default", + } + `); + }); + + it('should handle complex nested overrides', () => { + const initConfig: MermaidConfig = { + flowchart: { + nodeSpacing: 50, + rankSpacing: 100, + curve: 'linear', + }, + theme: 'default', + }; + const directive1: MermaidConfig = { + flowchart: { + nodeSpacing: 75, + }, + fontSize: 12, + }; + const directive2: MermaidConfig = { + flowchart: { + curve: 'basis', + nodeSpacing: 100, + }, + mindmap: { + padding: 15, + }, + }; + + configApi.saveConfigFromInitialize(initConfig); + configApi.addDirective(directive1); + configApi.addDirective(directive2); + + const userConfig = configApi.getUserDefinedConfig(); + expect(userConfig).toMatchInlineSnapshot(` + { + "flowchart": { + "curve": "basis", + "nodeSpacing": 100, + "rankSpacing": 100, + }, + "fontSize": 12, + "mindmap": { + "padding": 15, + }, + "theme": "default", + } + `); + }); + + it('should return independent copies (not references)', () => { + const initConfig: MermaidConfig = { theme: 'dark', flowchart: { nodeSpacing: 50 } }; + configApi.saveConfigFromInitialize(initConfig); + + const userConfig1 = configApi.getUserDefinedConfig(); + const userConfig2 = configApi.getUserDefinedConfig(); + + userConfig1.theme = 'neutral'; + userConfig1.flowchart!.nodeSpacing = 999; + + expect(userConfig2).toMatchInlineSnapshot(` + { + "flowchart": { + "nodeSpacing": 50, + }, + "theme": "dark", + } + `); + }); + + it('should handle edge cases with undefined values', () => { + const initConfig: MermaidConfig = { theme: 'dark', layout: undefined }; + const directive: MermaidConfig = { fontSize: 14, fontFamily: undefined }; + + configApi.saveConfigFromInitialize(initConfig); + configApi.addDirective(directive); + + expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(` + { + "fontSize": 14, + "layout": undefined, + "theme": "dark", + } + `); + }); + + it('should retain config from initialize after reset', () => { + const initConfig: MermaidConfig = { theme: 'dark' }; + const directive: MermaidConfig = { layout: 'elk' }; + + configApi.saveConfigFromInitialize(initConfig); + configApi.addDirective(directive); + + expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(` + { + "layout": "elk", + "theme": "dark", + } + `); + + configApi.reset(); + }); +}); diff --git a/packages/mermaid/src/config.ts b/packages/mermaid/src/config.ts index 9468a3e46..4fcb3224d 100644 --- a/packages/mermaid/src/config.ts +++ b/packages/mermaid/src/config.ts @@ -248,3 +248,17 @@ const checkConfig = (config: MermaidConfig) => { issueWarning('LAZY_LOAD_DEPRECATED'); } }; + +export const getUserDefinedConfig = (): MermaidConfig => { + let userConfig: MermaidConfig = {}; + + if (configFromInitialize) { + userConfig = assignWithDepth(userConfig, configFromInitialize); + } + + for (const d of directives) { + userConfig = assignWithDepth(userConfig, d); + } + + return userConfig; +}; diff --git a/packages/mermaid/src/docs/syntax/flowchart.md b/packages/mermaid/src/docs/syntax/flowchart.md index a19dcff21..341143c47 100644 --- a/packages/mermaid/src/docs/syntax/flowchart.md +++ b/packages/mermaid/src/docs/syntax/flowchart.md @@ -590,11 +590,17 @@ flowchart TD - `b` - **w**: The width of the image. If not defined, this will default to the natural width of the image. - **h**: The height of the image. If not defined, this will default to the natural height of the image. -- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are: +- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the width (`w`) accordingly to the height (`h`). If not defined, this will default to `off` Possible values are: - `on` - `off` -These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging. +If you want to resize an image, but keep the same aspect ratio, set `h`, and set `constraint: on` to constrain the aspect ratio. E.g. + +```mermaid +flowchart TD + %% My image with a constrained aspect ratio + A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" } +``` ## Links between nodes