Merge branch 'master' into update-latest-news

This commit is contained in:
Steph 2023-11-02 05:05:04 -07:00
commit 99244ffae5
136 changed files with 7878 additions and 3905 deletions

View File

@ -49,8 +49,10 @@ module.exports = {
'no-unused-vars': 'off',
'cypress/no-async-tests': 'off',
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/ban-ts-comment': [
'error',
{

View File

@ -17,6 +17,9 @@ body:
- Use a clear and concise title
- Fill out the text fields with as much detail as possible.
- Never be shy to give us screenshots and/or code samples. It will help!
There is a chance that the bug is already fixed in the git `develop` branch, but is not released yet.
So please check in [Live Editor - Develop](https://develop.git.mermaid.live) before raising an issue.
- type: textarea
attributes:
label: Description
@ -43,7 +46,7 @@ body:
attributes:
label: Code Sample
description: |-
If applicable, add the code sample or a link to the [Live Editor](https://mermaid.live).
If applicable, add the code sample or a link to the [Live Editor - Develop](https://develop.git.mermaid.live).
Any text pasted here will be rendered as a Code block.
render: text
- type: textarea

View File

@ -7,8 +7,14 @@ contact_links:
url: https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE
about: Join our Community on Slack for Help and a casual chat.
- name: Documentation
url: https://mermaid-js.github.io
url: https://mermaid.js.org
about: Read our documentation for all that Mermaid.js can offer.
- name: Live Editor
url: https://mermaid.live
about: Try the live editor to preview graphs in no time.
- name: Live Editor - Develop
url: https://develop.git.mermaid.live
about: Try unreleased changes in the develop branch.
- name: Live Editor - Next
url: https://next.git.mermaid.live
about: Try unreleased changes in the next branch.

View File

@ -18,6 +18,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'er',
'pie',
'quadrantChart',
'xyChart',
'requirement',
'mindmap',
'timeline',

View File

@ -68,7 +68,7 @@ try {
### Init deprecated and InitThrowsErrors removed
The config passed to `init` was not being used eariler.
The config passed to `init` was not being used earlier.
It will now be used.
The `init` function is deprecated and will be removed in the next major release.
init currently works as a wrapper to `initialize` and `run`.
@ -195,7 +195,7 @@ mermaid.run({
- "Cannot activate" in sequenceDiagram [\#647](https://github.com/knsv/mermaid/issues/647)
- Link \("click" statement\) in flowchart does not work in exported SVG [\#646](https://github.com/knsv/mermaid/issues/646)
- How to pass styling [\#639](https://github.com/knsv/mermaid/issues/639)
- The live editor cant show seq diagram with notes for 8.0.0-alpha.3 [\#638](https://github.com/knsv/mermaid/issues/638)
- The live editor can't show seq diagram with notes for 8.0.0-alpha.3 [\#638](https://github.com/knsv/mermaid/issues/638)
- import mermaid.css with ES6 + NPM [\#634](https://github.com/knsv/mermaid/issues/634)
- Actor line cuts through other elements [\#633](https://github.com/knsv/mermaid/issues/633)
- Graph TD line out of the picture \(left side\) [\#630](https://github.com/knsv/mermaid/issues/630)
@ -504,7 +504,7 @@ mermaid.run({
- Docs css: code hard to read [\#324](https://github.com/knsv/mermaid/issues/324)
- About Markpad integration [\#323](https://github.com/knsv/mermaid/issues/323)
- How to link backwords in flowchat? [\#321](https://github.com/knsv/mermaid/issues/321)
- How to link backwards in flowchat? [\#321](https://github.com/knsv/mermaid/issues/321)
- Help with editor [\#310](https://github.com/knsv/mermaid/issues/310)
- +1 [\#293](https://github.com/knsv/mermaid/issues/293)
- Basic chart does not render on Chome, but does in Firefox [\#290](https://github.com/knsv/mermaid/issues/290)
@ -619,7 +619,7 @@ mermaid.run({
- render to png from the cli does not display the marker-end arrow heads [\#181](https://github.com/knsv/mermaid/issues/181)
- Links in sequence diagrams [\#159](https://github.com/knsv/mermaid/issues/159)
- comment characters `%%` cause parse error [\#141](https://github.com/knsv/mermaid/issues/141)
- Add a reversed assymetric shape [\#124](https://github.com/knsv/mermaid/issues/124)
- Add a reversed asymmetric shape [\#124](https://github.com/knsv/mermaid/issues/124)
- Add syntax for double headed arrows [\#123](https://github.com/knsv/mermaid/issues/123)
- Support for font-awesome [\#49](https://github.com/knsv/mermaid/issues/49)
@ -659,7 +659,7 @@ mermaid.run({
- Auto linewrap for notes in sequence diagrams [\#178](https://github.com/knsv/mermaid/issues/178)
- Execute code after initialize [\#176](https://github.com/knsv/mermaid/issues/176)
- Autoscaling for all diagram types [\#175](https://github.com/knsv/mermaid/issues/175)
- Problem wit click event callback [\#174](https://github.com/knsv/mermaid/issues/174)
- Problem with click event callback [\#174](https://github.com/knsv/mermaid/issues/174)
- How to escape characters? [\#170](https://github.com/knsv/mermaid/issues/170)
- it can not work [\#167](https://github.com/knsv/mermaid/issues/167)
- UML Class diagram [\#154](https://github.com/knsv/mermaid/issues/154)
@ -762,7 +762,7 @@ mermaid.run({
- subgraph background is black in rendered flowchart PNG via CLI [\#121](https://github.com/knsv/mermaid/issues/121)
- Integrate editor at https://github.com/naseer/mermaid-webapp [\#110](https://github.com/knsv/mermaid/issues/110)
- Internet Explorer Support [\#99](https://github.com/knsv/mermaid/issues/99)
- Assymetric shapes not documented [\#82](https://github.com/knsv/mermaid/issues/82)
- Asymmetric shapes not documented [\#82](https://github.com/knsv/mermaid/issues/82)
- NoModificationAllowedError [\#23](https://github.com/knsv/mermaid/issues/23)
- Improve arrows [\#3](https://github.com/knsv/mermaid/issues/3)
@ -908,7 +908,7 @@ mermaid.run({
- Question marks don't render properly with /dist/mermaid.full.min.js [\#30](https://github.com/knsv/mermaid/issues/30)
- Error with some characters [\#25](https://github.com/knsv/mermaid/issues/25)
- Provide parse function in browser widthout `require`? [\#21](https://github.com/knsv/mermaid/issues/21)
- Provide parse function in browser without `require`? [\#21](https://github.com/knsv/mermaid/issues/21)
- Better label text support [\#18](https://github.com/knsv/mermaid/issues/18)
- Cap-cased words break parser [\#8](https://github.com/knsv/mermaid/issues/8)

View File

@ -59,8 +59,8 @@ representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at security@mermaid.live
.
reported to the community leaders responsible for enforcement at <security@mermaid.live>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@ -20,6 +20,9 @@ Generate diagrams from markdown-like text.
<p align="center">
<a href="./README.zh-CN.md">简体中文</a>
</p>
<p align="center">
Try Live Editor previews of future releases: <a href="https://develop.git.mermaid.live/" title="Try the mermaid version from the develop branch.">Develop</a> | <a href="https://next.git.mermaid.live/" title="Try the mermaid version from the next branch.">Next</a>
</p>
<br>
<br>
@ -31,7 +34,7 @@ Generate diagrams from markdown-like text.
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=twitter)](https://twitter.com/mermaidjs_)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
<img src="./img/header.png" alt="" />

View File

@ -12,7 +12,7 @@ Mermaid
<p>
<p align="center">
<a href="https://mermaid.live/"><b>Live Editor!</b></a>
<a href="https://mermaid.live/"><b>实时编辑器!</b></a>
</p>
<p align="center">
<a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE" title="Slack invite">🙌 加入我们</a>
@ -21,6 +21,10 @@ Mermaid
<a href="./README.md">English</a>
</p>
<p align="center">
尝试未来版本的实时编辑器预览: <a href="https://develop.git.mermaid.live/" title="尝试来自develop分支的mermaid版本。">Develop</a> | <a href="https://next.git.mermaid.live/" title="尝试来自next分支的mermaid版本。">Next</a>
</p>
<br>
<br>
@ -31,7 +35,7 @@ Mermaid
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=twitter)](https://twitter.com/mermaidjs_)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
<img src="./img/header.png" alt="" />

View File

@ -156,6 +156,7 @@
"vitepress",
"vueuse",
"xlink",
"xychart",
"yash",
"yokozuna",
"zenuml",

View File

@ -1,4 +1,4 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts';
describe('Configuration and directives - nodes should be light blue', () => {
it('No config - use default', () => {
@ -206,8 +206,7 @@ graph TD
describe('when rendering several diagrams', () => {
it('diagrams should not taint later diagrams', () => {
const url = 'http://localhost:9000/theme-directives.html';
cy.visit(url);
cy.matchImageSnapshot('conf-and-directives.spec-when-rendering-several-diagrams-diagram-1');
urlSnapshotTest(url, {});
});
});
});

View File

@ -520,7 +520,15 @@ describe('Gantt diagram', () => {
);
});
it('should render a gantt diagram with very large intervals, skipping excludes if interval > 5 years', () => {
// TODO: fix it
//
// This test is skipped deliberately
// because it fails and blocks our development pipeline
// It was added as an attempt to fix gantt performance issues
//
// https://github.com/mermaid-js/mermaid/issues/3274
//
it.skip('should render a gantt diagram with very large intervals, skipping excludes if interval > 5 years', () => {
imgSnapshotTest(
`gantt
title A long Gantt Diagram
@ -528,7 +536,6 @@ describe('Gantt diagram', () => {
axisFormat %m-%d
tickInterval 1day
excludes weekends
section Section
A task : a1, 9999-10-01, 30d
Another task : after a1, 20d

View File

@ -26,7 +26,7 @@ describe('Git Graph diagram', () => {
`gitGraph
commit id: "Normal Commit"
commit id: "Reverse Commit" type: REVERSE
commit id: "Hightlight Commit" type: HIGHLIGHT
commit id: "Highlight Commit" type: HIGHLIGHT
`,
{}
);
@ -36,7 +36,7 @@ describe('Git Graph diagram', () => {
`gitGraph
commit id: "Normal Commit with tag" tag: "v1.0.0"
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
commit id: "Hightlight Commit" type: HIGHLIGHT tag: "8.8.4"
commit id: "Highlight Commit" type: HIGHLIGHT tag: "8.8.4"
`,
{}
);
@ -102,7 +102,7 @@ describe('Git Graph diagram', () => {
{}
);
});
it('8: should render a simple gitgraph with more than 8 branchs & overriding variables', () => {
it('8: should render a simple gitgraph with more than 8 branches & overriding variables', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ffffff',
@ -358,7 +358,7 @@ gitGraph
`gitGraph TB:
commit id: "Normal Commit"
commit id: "Reverse Commit" type: REVERSE
commit id: "Hightlight Commit" type: HIGHLIGHT
commit id: "Highlight Commit" type: HIGHLIGHT
`,
{}
);
@ -368,7 +368,7 @@ gitGraph
`gitGraph TB:
commit id: "Normal Commit with tag" tag: "v1.0.0"
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
commit id: "Hightlight Commit" type: HIGHLIGHT tag: "8.8.4"
commit id: "Highlight Commit" type: HIGHLIGHT tag: "8.8.4"
`,
{}
);
@ -434,7 +434,7 @@ gitGraph
{}
);
});
it('22: should render a simple gitgraph with more than 8 branchs & overriding variables | Vertical Branch', () => {
it('22: should render a simple gitgraph with more than 8 branches & overriding variables | Vertical Branch', () => {
imgSnapshotTest(
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'gitBranchLabel0': '#ffffff',

View File

@ -160,4 +160,70 @@ describe('Quadrant Chart', () => {
);
cy.get('svg');
});
it('should render x-axis labels in the center, if x-axis has two labels', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
it('should render y-axis labels in the center, if y-axis has two labels', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
it('should render both axes labels on the left and bottom, if both axes have only one label', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Reach -->
y-axis Engagement -->
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
`,
{}
);
cy.get('svg');
});
});

View File

@ -57,7 +57,7 @@ describe('Timeline diagram', () => {
{}
);
});
it('5: should render a simple timeline with directive overriden colors', () => {
it('5: should render a simple timeline with directive overridden colors', () => {
imgSnapshotTest(
` %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
'cScale0': '#ff0000',

View File

@ -0,0 +1,322 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('XY Chart', () => {
it('should render the simplest possible chart', () => {
imgSnapshotTest(
`
xychart-beta
line [10, 30, 20]
`,
{}
);
cy.get('svg');
});
it('Should render a complete chart', () => {
imgSnapshotTest(
`
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
});
it('Should render a chart without title', () => {
imgSnapshotTest(
`
xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('y-axis title not required', () => {
imgSnapshotTest(
`
xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Should render a chart without y-axis with different range', () => {
imgSnapshotTest(
`
xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('x axis title not required', () => {
imgSnapshotTest(
`
xychart-beta
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('Multiple plots can be rendered', () => {
imgSnapshotTest(
`
xychart-beta
line [23, 46, 77, 34]
line [45, 32, 33, 12]
bar [87, 54, 99, 85]
line [78, 88, 22, 4]
line [22, 29, 75, 33]
bar [52, 96, 35, 10]
`,
{}
);
cy.get('svg');
});
it('Decimals and negative numbers are supported', () => {
imgSnapshotTest(
`
xychart-beta
y-axis -2.4 --> 3.5
line [+1.3, .6, 2.4, -.34]
`,
{}
);
cy.get('svg');
});
it('Render spark line with "plotReservedSpacePercent"', () => {
imgSnapshotTest(
`
---
config:
theme: dark
xyChart:
width: 200
height: 20
plotReservedSpacePercent: 100
---
xychart-beta
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('Render spark bar without displaying other property', () => {
imgSnapshotTest(
`
---
config:
theme: dark
xyChart:
width: 200
height: 20
xAxis:
showLabel: false
showTitle: false
showTick: false
showAxisLine: false
yAxis:
showLabel: false
showTitle: false
showTick: false
showAxisLine: false
---
xychart-beta
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
`,
{}
);
cy.get('svg');
});
it('Should use all the config from directive', () => {
imgSnapshotTest(
`
%%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60 }}}%%
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Should use all the config from yaml', () => {
imgSnapshotTest(
`
---
config:
theme: forest
xyChart:
width: 1000
height: 600
titlePadding: 5
titleFontSize: 10
xAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
yAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
chartOrientation: horizontal
plotReservedSpacePercent: 60
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis title false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showTitle: false
yAxis:
showTitle: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis label false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showLabel: false
yAxis:
showLabel: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis tick false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showTick: false
yAxis:
showTick: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render with show axis line false', () => {
imgSnapshotTest(
`
---
config:
xyChart:
xAxis:
showAxisLine: false
yAxis:
showAxisLine: false
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
it('Render all the theme color', () => {
imgSnapshotTest(
`
---
config:
themeVariables:
xyChart:
titleColor: "#ff0000"
backgroundColor: "#f0f8ff"
yAxisLabelColor: "#ee82ee"
yAxisTitleColor: "#7fffd4"
yAxisTickColor: "#87ceeb"
yAxisLineColor: "#ff6347"
xAxisLabelColor: "#7fffd4"
xAxisTitleColor: "#ee82ee"
xAxisTickColor: "#ff6347"
xAxisLineColor: "#87ceeb"
plotColorPalette: "#008000, #faba63"
---
xychart-beta
title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`,
{}
);
cy.get('svg');
});
});

File diff suppressed because one or more lines are too long

View File

@ -58,8 +58,19 @@
</head>
<body>
<pre id="diagram" class="mermaid">
classDiagram
`Class<img src=x onerror=alert(1)>` <|-- `Class2<img src=x onerror=alert(2)>`
flowchart TB
C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z & A1 & A2 & A3 & A4 & A5 & A6 & A7 & A8
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z & A1 & A2 & A3 & A4 & A5 & A6 & A7 & A8
</pre>
<pre id="diagram" class="mermaid2">
flowchart TB
A & A & A & A & A & A & A & A ---> C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z
</pre>
<pre id="diagram" class="mermaid2">
flowchart TB
A1 & A2 & A3 & A4 & A5 & A6 & A7 & A8 --> C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X & Y & Z
</pre>
<pre id="diagram" class="mermaid2">
flowchart
@ -439,6 +450,7 @@ mindmap
messageFontFamily: 'courier',
},
fontSize: 16,
logLevel: 0,
});
function callback() {
alert('It worked');

View File

@ -42,7 +42,8 @@
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({ startOnLoad: true, logLevel: 0 });
mermaid.initialize({ startOnLoad: false, logLevel: 0 });
await mermaid.run();
if (window.Cypress) {
window.rendered = true;

View File

@ -1,15 +1,6 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
@ -122,26 +113,21 @@
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
// theme: 'dark',
// theme: 'dark',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
// flowchart: { useMaxWidth: true },
graph: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict',
startOnLoad: false,
});
function callback() {
alert('It worked');
await mermaid.run();
if (window.Cypress) {
window.rendered = true;
}
</script>
</body>

View File

@ -173,7 +173,7 @@
Container(mobile, "Mobile App", "Xamarin", "Provides a limited subset of the Internet Banking functionality to customers via their mobile device.")
}
Deployment_Node(comp, "Customer's computer", "Mircosoft Windows or Apple macOS"){
Deployment_Node(comp, "Customer's computer", "Microsoft Windows or Apple macOS"){
Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox,<br/> Apple Safari or Microsoft Edge"){
Container(spa, "Single Page Application", "JavaScript and Angular", "Provides all of the Internet Banking functionality to customers via their web browser.")
}

View File

@ -22,7 +22,7 @@
---
graph LR
accTitle: This is a complicated flow
accDescr: This is the descriptoin for the complicated flow.
accDescr: This is the description for the complicated flow.
sid-B3655226-6C29-4D00-B685-3D5C734DC7E1["

View File

@ -60,6 +60,9 @@
<li>
<h2><a href="./quadrantchart.html">Quadrant charts</a></h2>
</li>
<li>
<h2><a href="./xychart.html">XY charts</a></h2>
</li>
<li>
<h2><a href="./requirements.html">Requirements</a></h2>
</li>

View File

@ -17,7 +17,7 @@
<h1>Requirement diagram demos</h1>
<pre class="mermaid">
requirementDiagram
accTitle: Requirments demo in black and white
accTitle: Requirements demo in black and white
accDescr: A series of requirement boxes showing relationships among them. Has meaningless task names
requirement test_req {

View File

@ -183,7 +183,7 @@
</pre>
<hr />
<h2>Compsite states can link to themselves</h2>
<h2>Composite states can link to themselves</h2>
<pre class="mermaid">
stateDiagram-v2
state Active {
@ -199,7 +199,7 @@
stateDiagram-v2
[*] --> S1
S1 --> S2: This long line uses a br tag<br />to create multiple<br />lines.
S1 --> S3: This transition descripton uses \na newline character\nto create multiple\nlines.
S1 --> S3: This transition description uses \na newline character\nto create multiple\nlines.
</pre>
<hr />

184
demos/xychart.html Normal file
View File

@ -0,0 +1,184 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h1>XY Charts demos</h1>
<pre class="mermaid">
xychart-beta
title "Sales Revenue (in $)"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
</pre>
<hr />
<h1>XY Charts horizontal</h1>
<pre class="mermaid">
xychart-beta horizontal
title "Basic xychart"
x-axis "this is x axis" [category1, "category 2", category3, category4]
y-axis yaxisText 10 --> 150
bar "sample bat" [52, 96, 35, 10]
line [23, 46, 75, 43]
</pre>
<hr />
<h1>XY Charts only lines and bar</h1>
<pre class="mermaid">
xychart-beta
line [23, 46, 77, 34]
line [45, 32, 33, 12]
line [87, 54, 99, 85]
line [78, 88, 22, 4]
line [22, 29, 75, 33]
bar [52, 96, 35, 10]
</pre>
<hr />
<h1>XY Charts with +ve and -ve numbers</h1>
<pre class="mermaid">
xychart-beta
line [+1.3, .6, 2.4, -.34]
</pre>
<h1>XY Charts Bar with multiple category</h1>
<pre class="mermaid">
xychart-beta
title "Basic xychart with many categories"
x-axis "this is x axis" [category1, "category 2", category3, category4, category5, category6, category7]
y-axis yaxisText 10 --> 150
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
</pre>
<h1>XY Charts line with multiple category</h1>
<pre class="mermaid">
xychart-beta
title "Line chart with many category"
x-axis "this is x axis" [category1, "category 2", category3, category4, category5, category6, category7]
y-axis yaxisText 10 --> 150
line "sample line" [52, 96, 35, 10, 87, 34, 67, 99]
</pre>
<h1>XY Charts category with large text</h1>
<pre class="mermaid">
xychart-beta
title "Basic xychart with many categories with category overlap"
x-axis "this is x axis" [category1, "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.", category3, category4, category5, category6, category7]
y-axis yaxisText 10 --> 150
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
</pre>
<h1>sparkline demo</h1>
<pre class="mermaid">
---
config:
theme: dark
xyChart:
width: 200
height: 20
plotReservedSpacePercent: 100
---
xychart-beta
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
</pre>
<h1>sparkBar demo</h1>
<pre class="mermaid">
---
config:
theme: dark
xyChart:
width: 200
height: 20
plotReservedSpacePercent: 100
---
xychart-beta
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
</pre>
<h1>XY Charts demos with all configs</h1>
<pre class="mermaid">
---
config:
theme: forest
xyChart:
width: 1000
height: 600
titlePadding: 5
titleFontSize: 10
xAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
yAxis:
labelFontSize: 20
labelPadding: 10
titleFontSize: 30
titlePadding: 20
tickLength: 10
tickWidth: 5
axisLineWidth: 5
chartOrientation: horizontal
plotReservedSpacePercent: 60
---
xychart-beta
title "Sales Revene"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
</pre>
<h1>XY Charts demos with all theme config</h1>
<pre class="mermaid">
---
config:
themeVariables:
xyChart:
titleColor: "#ff0000"
backgroundColor: "#f0f8ff"
yAxisLabelColor: "#ee82ee"
yAxisTitleColor: "#7fffd4"
yAxisTickColor: "#87ceeb"
yAxisLineColor: "#ff6347"
xAxisLabelColor: "#7fffd4"
xAxisTitleColor: "#ee82ee"
xAxisTickColor: "#ff6347"
xAxisLineColor: "#87ceeb"
plotColorPalette: "#008000, #faba63"
---
xychart-beta
title "Sales Revene"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
</pre>
<hr />
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
theme: 'default',
logLevel: 3,
securityLevel: 'loose',
});
</script>
</body>
</html>

View File

@ -1,7 +1,7 @@
version: '3.9'
services:
mermaid:
image: node:18.17.1-alpine3.18
image: node:18.18.2-alpine3.18
stdin_open: true
tty: true
working_dir: /mermaid

View File

@ -97,7 +97,7 @@ See [the accTitle and accDescr usage examples](#acctitle-and-accdescr-usage-exam
graph LR
accTitle: Big Decisions
accDescr: Bob's Burgers process for making big decisions
A[Identify Big Descision] --> B{Make Big Decision}
A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done]
```
@ -105,7 +105,7 @@ See [the accTitle and accDescr usage examples](#acctitle-and-accdescr-usage-exam
graph LR
accTitle: Big Decisions
accDescr: Bob's Burgers process for making big decisions
A[Identify Big Descision] --> B{Make Big Decision}
A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done]
```
@ -137,7 +137,7 @@ Here is the HTML generated for the SVG element: _(Note that some of the SVG attr
for making very, very big decisions.
This is actually a very simple flow: identify the big decision and then make the big decision.
}
A[Identify Big Descision] --> B{Make Big Decision}
A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done]
```
@ -149,7 +149,7 @@ Here is the HTML generated for the SVG element: _(Note that some of the SVG attr
for making very, very big decisions.
This is actually a very simple flow: identify the big decision and then make the big decision.
}
A[Identify Big Descision] --> B{Make Big Decision}
A[Identify Big Decision] --> B{Make Big Decision}
B --> D[Be done]
```

View File

@ -14,7 +14,7 @@
#### Defined in
[defaultConfig.ts:268](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L268)
[defaultConfig.ts:272](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L272)
---

View File

@ -41,6 +41,8 @@ Below are a list of community plugins and integrations created with Mermaid.
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
- [LiveBook](https://livebook.dev) ✅
- [Atlassian Products](https://www.atlassian.com)
- [Mermaid Charts & Diagrams for Confluence](https://marketplace.atlassian.com/apps/1222572/)
- [Mermaid Charts & Diagrams for Jira](https://marketplace.atlassian.com/apps/1224537/)
- [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview)
- [Mermaid Plugin for Confluence](https://marketplace.atlassian.com/apps/1214124/mermaid-plugin-for-confluence?hosting=server&tab=overview)
- [CloudScript.io Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
@ -49,7 +51,7 @@ Below are a list of community plugins and integrations created with Mermaid.
- [Mermaid Macro](https://www.redmine.org/plugins/redmine_mermaid_macro)
- [redmine-mermaid](https://github.com/styz/redmine_mermaid)
- [markdown-for-mermaid-plugin](https://github.com/jamieh-mongolian/markdown-for-mermaid-plugin)
- [JetBrains IDE eg Pycharm](https://www.jetbrains.com/go/guide/tips/mermaid-js-support-in-markdown/)
- [Mermaid Plugin for JetBrains IDEs](https://plugins.jetbrains.com/plugin/20146-mermaid)
- [mermerd](https://github.com/KarnerTh/mermerd)
- Visual Studio Code [Polyglot Interactive Notebooks](https://github.com/dotnet/interactive#net-interactive)
@ -173,7 +175,7 @@ Communication tools and platforms
- [remark](https://remark.js.org/)
- [remark-mermaidjs](https://github.com/remcohaszing/remark-mermaidjs)
- [rehype](https://github.com/rehypejs/rehype)
- [rehype-mermaidjs](https://github.com/remcohaszing/rehype-mermaidjs)
- [rehype-mermaid](https://github.com/remcohaszing/rehype-mermaid)
- [Gatsby](https://www.gatsbyjs.com/)
- [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid)
- [JSDoc](https://jsdoc.app/)

View File

@ -283,6 +283,26 @@ quadrantChart
Campaign F: [0.35, 0.78]
```
### [XY Chart](../syntax/xyChart.md)
```mermaid-example
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
```mermaid
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
## Installation
**In depth guides and examples can be found at [Getting Started](./getting-started.md) and [Usage](../config/usage.md).**

View File

@ -764,7 +764,7 @@ flowchart LR
end
%% ^ These subgraphs are identical, except for the links to them:
%% Link *to* subgraph1: subgraph1 direction is mantained
%% Link *to* subgraph1: subgraph1 direction is maintained
outside --> subgraph1
%% Link *within* subgraph2:
%% subgraph2 inherits the direction of the top-level graph (LR)
@ -783,7 +783,7 @@ flowchart LR
end
%% ^ These subgraphs are identical, except for the links to them:
%% Link *to* subgraph1: subgraph1 direction is mantained
%% Link *to* subgraph1: subgraph1 direction is maintained
outside --> subgraph1
%% Link *within* subgraph2:
%% subgraph2 inherits the direction of the top-level graph (LR)
@ -1112,7 +1112,7 @@ flowchart TD
B-->E(A fa:fa-camera-retro perhaps?)
```
Mermaid is compatible with Font Awesome up to verion 5, Free icons only. Check that the icons you use are from the [supported set of icons](https://fontawesome.com/v5/search?o=r&m=free).
Mermaid is compatible with Font Awesome up to version 5, Free icons only. Check that the icons you use are from the [supported set of icons](https://fontawesome.com/v5/search?o=r&m=free).
## Graph declarations with spaces between vertices and link and without semicolon
@ -1146,7 +1146,7 @@ The layout of the diagram is done with the renderer. The default renderer is dag
Starting with Mermaid version 9.4, you can use an alternate renderer named elk. The elk renderer is better for larger and/or more complex diagrams.
The _elk_ renderer is an experimenal feature.
The _elk_ renderer is an experimental feature.
You can change the renderer to elk by adding this directive:
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%

View File

@ -827,18 +827,25 @@ Here, we have changed the default main branch name to `MetroLine1`.
## Orientation (v10.3.0+)
In Mermaid, the default orientation is Left to Right. The branches are lined vertically.
Mermaid supports two graph orientations: **Left-to-Right** (default) and **Top-to-Bottom**.
You can set this with either `LR:` (for [**Left-to-Right**](#left-to-right-default-lr)) or `TB:` (for [**Top-to-Bottom**](#top-to-bottom-tb)) after `gitGraph`.
### Left to Right (default, `LR:`)
In Mermaid, the default orientation is for commits to run from left to right and for branches to be stacked on top of one another.
However, you can set this explicitly with `LR:` after `gitGraph`.
Usage example:
```mermaid-example
gitGraph
gitGraph LR:
commit
commit
branch develop
commit
commit
commit
checkout main
commit
commit
@ -848,13 +855,12 @@ Usage example:
```
```mermaid
gitGraph
gitGraph LR:
commit
commit
branch develop
commit
commit
commit
checkout main
commit
commit
@ -863,9 +869,11 @@ Usage example:
commit
```
Sometimes we may want to change the orientation. Currently, Mermaid supports two orientations: **Left to Right**(default) and **Top to Bottom**.
### Top to Bottom (`TB:`)
In order to change the orientation from top to bottom i.e. branches lined horizontally, you need to add `TB` along with `gitGraph`.
In `TB` (**Top-to-Bottom**) orientation, the commits run from top to bottom of the graph and branches are arranged side-by-side.
To orient the graph this way, you need to add `TB:` after gitGraph.
Usage example:
@ -876,7 +884,6 @@ Usage example:
branch develop
commit
commit
commit
checkout main
commit
commit
@ -892,7 +899,6 @@ Usage example:
branch develop
commit
commit
commit
checkout main
commit
commit

View File

@ -102,26 +102,26 @@ Points are used to plot a circle inside the quadrantChart. The syntax is `<text>
## Chart Configurations
| Parameter | Description | Default value |
| --------------------------------- | ------------------------------------------------------------------------------------------------- | :-----------: |
| chartWidth | Width of the chart | 500 |
| chartHeight | Height of the chart | 500 |
| titlePadding | Top and Bottom padding of the title | 10 |
| titleFontSize | Title font size | 20 |
| quadrantPadding | Padding outside all the quadrants | 5 |
| quadrantTextTopPadding | Quadrant text top padding when text is drawn on top ( not data points are there) | 5 |
| quadrantLabelFontSize | Quadrant text font size | 16 |
| quadrantInternalBorderStrokeWidth | Border stroke width inside the quadrants | 1 |
| quadrantExternalBorderStrokeWidth | Quadrant external border stroke width | 2 |
| xAxisLabelPadding | Top and bottom padding of x-axis text | 5 |
| xAxisLabelFontSize | X-axis texts font size | 16 |
| xAxisPosition | Position of x-axis (top , bottom) if there are points the x-axis will alway be rendered in bottom | 'top' |
| yAxisLabelPadding | Left and Right padding of y-axis text | 5 |
| yAxisLabelFontSize | Y-axis texts font size | 16 |
| yAxisPosition | Position of y-axis (left , right) | 'left' |
| pointTextPadding | Padding between point and the below text | 5 |
| pointLabelFontSize | Point text font size | 12 |
| pointRadius | Radius of the point to be drawn | 5 |
| Parameter | Description | Default value |
| --------------------------------- | -------------------------------------------------------------------------------------------------- | :-----------: |
| chartWidth | Width of the chart | 500 |
| chartHeight | Height of the chart | 500 |
| titlePadding | Top and Bottom padding of the title | 10 |
| titleFontSize | Title font size | 20 |
| quadrantPadding | Padding outside all the quadrants | 5 |
| quadrantTextTopPadding | Quadrant text top padding when text is drawn on top ( not data points are there) | 5 |
| quadrantLabelFontSize | Quadrant text font size | 16 |
| quadrantInternalBorderStrokeWidth | Border stroke width inside the quadrants | 1 |
| quadrantExternalBorderStrokeWidth | Quadrant external border stroke width | 2 |
| xAxisLabelPadding | Top and bottom padding of x-axis text | 5 |
| xAxisLabelFontSize | X-axis texts font size | 16 |
| xAxisPosition | Position of x-axis (top , bottom) if there are points the x-axis will always be rendered in bottom | 'top' |
| yAxisLabelPadding | Left and Right padding of y-axis text | 5 |
| yAxisLabelFontSize | Y-axis texts font size | 16 |
| yAxisPosition | Position of y-axis (left , right) | 'left' |
| pointTextPadding | Padding between point and the below text | 5 |
| pointLabelFontSize | Point text font size | 12 |
| pointRadius | Radius of the point to be drawn | 5 |
## Chart Theme Variables

View File

@ -217,7 +217,7 @@ Note that there are no sections defined, and each time period and its correspond
2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme.
You will need to add this option either via mermaid.intialize function or directives.
You will need to add this option either via mermaid.initialize function or directives.
```javascript
mermaid.initialize({

188
docs/syntax/xyChart.md Normal file
View File

@ -0,0 +1,188 @@
> **Warning**
>
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/xyChart.md](../../packages/mermaid/src/docs/syntax/xyChart.md).
# XY Chart
> In the context of mermaid-js, the XY chart is a comprehensive charting module that encompasses various types of charts that utilize both x-axis and y-axis for data representation. Presently, it includes two fundamental chart types: the bar chart and the line chart. These charts are designed to visually display and analyze data that involve two numerical variables.
> It's important to note that while the current implementation of mermaid-js includes these two chart types, the framework is designed to be dynamic and adaptable. Therefore, it has the capacity for expansion and the inclusion of additional chart types in the future. This means that users can expect an evolving suite of charting options within the XY chart module, catering to various data visualization needs as new chart types are introduced over time.
## Example
```mermaid-example
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
```mermaid
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
## Syntax
> **Note**
> All text values that contain only one word can be written without `"`. If a text value has many words in it, specifically if it contains spaces, enclose the value in `"`
### Orientations
The chart can be drawn horizontal or vertical, default value is vertical.
xychart-beta horizontal
...
### Title
The title is a short description of the chart and it will always render on top of the chart.
#### Example
xychart-beta
title "This is a simple example"
...
> **Note**
> If the title is a single word one no need to use `"`, but if it has space `"` is needed
### x-axis
The x-axis primarily serves as a categorical value, although it can also function as a numeric range value when needed.
#### Example
1. `x-axis title min --> max` x-axis will function as numeric with the given range
2. `x-axis "title with space" [cat1, "cat2 with space", cat3]` x-axis if categorical, categories are text type
### y-axis
The y-axis is employed to represent numerical range values, it cannot have categorical values.
#### Example
1. `y-axis title min --> max`
2. `y-axis title` it will only add the title, the range will be auto generated from data.
> **Note**
> Both x and y axis are optional if not provided we will try to create the range
### Line chart
A line chart offers the capability to graphically depict lines.
#### Example
1. `line [2.3, 45, .98, -3.4]` it can have all valid numeric values.
### Bar chart
A bar chart offers the capability to graphically depict bars.
#### Example
1. `bar [2.3, 45, .98, -3.4]` it can have all valid numeric values.
#### Simplest example
The only two things required are the chart name (`xychart-beta`) and one data set. So you will be able to draw a chart with a simple config like
xychart-beta
line [+1.3, .6, 2.4, -.34]
## Chart Configurations
| Parameter | Description | Default value |
| ------------------------ | ---------------------------------------------- | :-----------: |
| width | Width of the chart | 700 |
| height | Height of the chart | 500 |
| titlePadding | Top and Bottom padding of the title | 10 |
| titleFontSize | Title font size | 20 |
| showTitle | Title to be shown or not | true |
| xAxis | xAxis configuration | AxisConfig |
| yAxis | yAxis configuration | AxisConfig |
| chartOrientation | 'vertical' or 'horizontal' | 'vertical' |
| plotReservedSpacePercent | Minimum space plots will take inside the chart | 50 |
### AxisConfig
| Parameter | Description | Default value |
| ------------- | ------------------------------------ | :-----------: |
| showLabel | Show axis labels or tick values | true |
| labelFontSize | Font size of the label to be drawn | 14 |
| labelPadding | Top and Bottom padding of the label | 5 |
| showTitle | Axis title to be shown or not | true |
| titleFontSize | Axis title font size | 16 |
| titlePadding | Top and Bottom padding of Axis title | 5 |
| showTick | Tick to be shown or not | true |
| tickLength | How long the tick will be | 5 |
| tickWidth | How width the tick will be | 2 |
| showAxisLine | Axis line to be shown or not | true |
| axisLineWidth | Thickness of the axis line | 2 |
## Chart Theme Variables
> **Note**
> Themes for xychart resides inside xychart attribute so to set the variables use this syntax
> %%{init: { "themeVariables": {"xyChart": {"titleColor": "#ff0000"} } }}%%
| Parameter | Description |
| ---------------- | --------------------------------------------------------- |
| backgroundColor | Background color of the whole chart |
| titleColor | Color of the Title text |
| xAxisLableColor | Color of the x-axis labels |
| xAxisTitleColor | Color of the x-axis title |
| xAxisTickColor | Color of the x-axis tick |
| xAxisLineColor | Color of the x-axis line |
| yAxisLableColor | Color of the y-axis labels |
| yAxisTitleColor | Color of the y-axis title |
| yAxisTickColor | Color of the y-axis tick |
| yAxisLineColor | Color of the y-axis line |
| plotColorPalette | String of colors separated by comma e.g. "#f3456, #43445" |
## Example on config and theme
```mermaid-example
---
config:
xyChart:
width: 900
height: 600
themeVariables:
xyChart:
titleColor: "#ff0000"
---
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```
```mermaid
---
config:
xyChart:
width: 900
height: 600
themeVariables:
xyChart:
titleColor: "#ff0000"
---
xychart-beta
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
```

View File

@ -4,7 +4,7 @@
"version": "10.2.4",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module",
"packageManager": "pnpm@8.7.5",
"packageManager": "pnpm@8.9.2",
"keywords": [
"diagram",
"markdown",
@ -77,8 +77,8 @@
"@types/node": "^18.16.0",
"@types/prettier": "^2.7.2",
"@types/rollup-plugin-visualizer": "^4.2.1",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"@typescript-eslint/eslint-plugin": "^6.7.2",
"@typescript-eslint/parser": "^6.7.2",
"@vitest/coverage-v8": "^0.34.0",
"@vitest/spy": "^0.34.0",
"@vitest/ui": "^0.34.0",
@ -88,7 +88,7 @@
"cypress": "^12.10.0",
"cypress-image-snapshot": "^4.0.1",
"esbuild": "^0.19.0",
"eslint": "^8.39.0",
"eslint": "^8.47.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-cypress": "^2.13.2",
"eslint-plugin-html": "^7.1.0",
@ -123,7 +123,7 @@
"vitest": "^0.34.0"
},
"volta": {
"node": "18.17.1"
"node": "18.18.2"
},
"nyc": {
"report-dir": "coverage/cypress"

View File

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

View File

@ -47,6 +47,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'er',
'pie',
'quadrantChart',
'xyChart',
'requirement',
'mindmap',
'timeline',

View File

@ -150,6 +150,7 @@ export interface MermaidConfig {
er?: ErDiagramConfig;
pie?: PieDiagramConfig;
quadrantChart?: QuadrantChartConfig;
xyChart?: XYChartConfig;
requirement?: RequirementDiagramConfig;
mindmap?: MindmapDiagramConfig;
gitGraph?: GitGraphDiagramConfig;
@ -703,6 +704,194 @@ export interface QuadrantChartConfig extends BaseDiagramConfig {
*/
quadrantExternalBorderStrokeWidth?: number;
}
/**
* This object contains configuration for XYChart axis config
*
* This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "XYChartAxisConfig".
*/
export interface XYChartAxisConfig {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/**
* This object contains configuration specific to XYCharts
*
* This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "XYChartConfig".
*/
export interface XYChartConfig extends BaseDiagramConfig {
/**
* width of the chart
*/
width?: number;
/**
* height of the chart
*/
height?: number;
/**
* Font size of the chart title
*/
titleFontSize?: number;
/**
* Top and bottom space from the chart title
*/
titlePadding?: number;
/**
* Should show the chart title
*/
showTitle?: boolean;
xAxis?: XYChartAxisConfig1;
yAxis?: XYChartAxisConfig2;
/**
* How to plot will be drawn horizontal or vertical
*/
chartOrientation?: 'vertical' | 'horizontal';
/**
* Minimum percent of space plots of the chart will take
*/
plotReservedSpacePercent?: number;
}
/**
* This object contains configuration for XYChart axis config
*/
export interface XYChartAxisConfig1 {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/**
* This object contains configuration for XYChart axis config
*/
export interface XYChartAxisConfig2 {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/**
* The object containing configurations specific for entity relationship diagrams
*

View File

@ -3,7 +3,7 @@ import { log } from '../logger.js';
import createLabel from './createLabel.js';
import { createText } from '../rendering-util/createText.js';
import { select } from 'd3';
import { getConfig } from '../config.js';
import { getConfig } from '../diagram-api/diagramAPI.js';
import { evaluate } from '../diagrams/common/common.js';
const rect = (parent, node) => {

View File

@ -1,6 +1,6 @@
import { select } from 'd3';
import { log } from '../logger.js';
import { getConfig } from '../config.js';
import { getConfig } from '../diagram-api/diagramAPI.js';
import { evaluate } from '../diagrams/common/common.js';
import { decodeEntities } from '../mermaidAPI.js';

View File

@ -2,7 +2,7 @@ import { log } from '../logger.js';
import createLabel from './createLabel.js';
import { createText } from '../rendering-util/createText.js';
import { line, curveBasis, select } from 'd3';
import { getConfig } from '../config.js';
import { getConfig } from '../diagram-api/diagramAPI.js';
import utils from '../utils.js';
import { evaluate } from '../diagrams/common/common.js';
import { getLineFunctionsWithOffset } from '../utils/lineWithOffset.js';

View File

@ -231,12 +231,12 @@ export const adjustClustersAndEdges = (graph, depth) => {
if (children.length > 0) {
log.debug('Cluster identified', id, descendants);
edges.forEach((edge) => {
// log.debug('Edge, decendants: ', edge, decendants[id]);
// log.debug('Edge, descendants: ', edge, descendants[id]);
// Check if any edge leaves the cluster (not the actual cluster, that's a link from the box)
if (edge.v !== id && edge.w !== id) {
// Any edge where either the one of the nodes is descending to the cluster but not the other
// if (decendants[id].indexOf(edge.v) < 0 && decendants[id].indexOf(edge.w) < 0) {
// if (descendants[id].indexOf(edge.v) < 0 && descendants[id].indexOf(edge.w) < 0) {
const d1 = isDescendant(edge.v, id);
const d2 = isDescendant(edge.w, id);

View File

@ -419,7 +419,7 @@ describe('extractDescendants', function () {
return {};
});
});
it('Simple case of one level decendants GLB9', function () {
it('Simple case of one level descendants GLB9', function () {
/*
subgraph A
a

View File

@ -1,7 +1,7 @@
import { select } from 'd3';
import { log } from '../logger.js';
import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util.js';
import { getConfig } from '../config.js';
import { getConfig } from '../diagram-api/diagramAPI.js';
import intersect from './intersect/index.js';
import createLabel from './createLabel.js';
import note from './shapes/note.js';

View File

@ -1,6 +1,6 @@
import { updateNodeBounds, labelHelper } from './util.js';
import { log } from '../../logger.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import intersect from '../intersect/index.js';
const note = async (parent, node) => {

View File

@ -1,6 +1,6 @@
import createLabel from '../createLabel.js';
import { createText } from '../../rendering-util/createText.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { decodeEntities } from '../../mermaidAPI.js';
import { select } from 'd3';
import { evaluate, sanitizeText } from '../../diagrams/common/common.js';

View File

@ -236,6 +236,10 @@ const config: RequiredDeep<MermaidConfig> = {
...defaultConfigJson.pie,
useWidth: 984,
},
xyChart: {
...defaultConfigJson.xyChart,
useWidth: undefined,
},
requirement: {
...defaultConfigJson.requirement,
useWidth: undefined,

View File

@ -7,6 +7,7 @@ import gantt from '../diagrams/gantt/ganttDetector.js';
import { info } from '../diagrams/info/infoDetector.js';
import { pie } from '../diagrams/pie/pieDetector.js';
import quadrantChart from '../diagrams/quadrant-chart/quadrantDetector.js';
import xychart from '../diagrams/xychart/xychartDetector.js';
import requirement from '../diagrams/requirement/requirementDetector.js';
import sequence from '../diagrams/sequence/sequenceDetector.js';
import classDiagram from '../diagrams/class/classDetector.js';
@ -85,6 +86,7 @@ export const addDiagrams = () => {
state,
journey,
quadrantChart,
sankey
sankey,
xychart
);
};

View File

@ -1,6 +1,11 @@
import { addDetector } from './detectType.js';
import { log as _log, setLogLevel as _setLogLevel } from '../logger.js';
import { getConfig as _getConfig } from '../config.js';
import {
getConfig as _getConfig,
setConfig as _setConfig,
defaultConfig as _defaultConfig,
setSiteConfig as _setSiteConfig,
} from '../config.js';
import { sanitizeText as _sanitizeText } from '../diagrams/common/common.js';
import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox.js';
import { addStylesForDiagram } from '../styles.js';
@ -15,6 +20,9 @@ import * as _commonDb from '../diagrams/common/commonDb.js';
export const log = _log;
export const setLogLevel = _setLogLevel;
export const getConfig = _getConfig;
export const setConfig = _setConfig;
export const defaultConfig = _defaultConfig;
export const setSiteConfig = _setSiteConfig;
export const sanitizeText = (text: string) => _sanitizeText(text, getConfig());
export const setupGraphViewbox = _setupGraphViewbox;
export const getCommonDb = () => {

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { sanitizeText } from '../common/common.js';
import {
setAccTitle,
@ -33,7 +33,7 @@ export const getC4Type = function () {
};
export const setC4Type = function (c4TypeParam) {
let sanitizedText = sanitizeText(c4TypeParam, configApi.getConfig());
let sanitizedText = sanitizeText(c4TypeParam, getConfig());
c4Type = sanitizedText;
};
@ -783,7 +783,7 @@ export const PLACEMENT = {
};
export const setTitle = function (txt) {
let sanitizedText = sanitizeText(txt, configApi.getConfig());
let sanitizedText = sanitizeText(txt, getConfig());
title = sanitizedText;
};
@ -816,7 +816,7 @@ export default {
getAccTitle,
getAccDescription,
setAccDescription,
getConfig: () => configApi.getConfig().c4,
getConfig: () => getConfig().c4,
clear,
LINETYPE,
ARROWTYPE,

View File

@ -4,7 +4,7 @@ import { log } from '../../logger.js';
import { parser } from './parser/c4Diagram.jison';
import common from '../common/common.js';
import c4Db from './c4Db.js';
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import assignWithDepth from '../../assignWithDepth.js';
import { wrapLabel, calculateTextWidth, calculateTextHeight } from '../../utils.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
@ -580,8 +580,8 @@ function drawInsideBoundary(
* @param diagObj
*/
export const draw = function (_text, id, _version, diagObj) {
conf = configApi.getConfig().c4;
const securityLevel = configApi.getConfig().securityLevel;
conf = getConfig().c4;
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sandbox mode
let sandboxElement;
if (securityLevel === 'sandbox') {

View File

@ -1,7 +1,7 @@
import type { Selection } from 'd3';
import { select } from 'd3';
import { log } from '../../logger.js';
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import common from '../common/common.js';
import utils from '../../utils.js';
import {
@ -34,10 +34,10 @@ let namespaceCounter = 0;
let functions: any[] = [];
const sanitizeText = (txt: string) => common.sanitizeText(txt, configApi.getConfig());
const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig());
const splitClassNameAndType = function (_id: string) {
const id = common.sanitizeText(_id, configApi.getConfig());
const id = common.sanitizeText(_id, getConfig());
let genericType = '';
let className = id;
@ -51,7 +51,7 @@ const splitClassNameAndType = function (_id: string) {
};
export const setClassLabel = function (_id: string, label: string) {
const id = common.sanitizeText(_id, configApi.getConfig());
const id = common.sanitizeText(_id, getConfig());
if (label) {
label = sanitizeText(label);
}
@ -67,14 +67,14 @@ export const setClassLabel = function (_id: string, label: string) {
* @public
*/
export const addClass = function (_id: string) {
const id = common.sanitizeText(_id, configApi.getConfig());
const id = common.sanitizeText(_id, getConfig());
const { className, type } = splitClassNameAndType(id);
// Only add class if not exists
if (Object.hasOwn(classes, className)) {
return;
}
// alert('Adding class: ' + className);
const name = common.sanitizeText(className, configApi.getConfig());
const name = common.sanitizeText(className, getConfig());
// alert('Adding class after: ' + name);
classes[name] = {
id: name,
@ -97,7 +97,7 @@ export const addClass = function (_id: string) {
* @public
*/
export const lookUpDomId = function (_id: string): string {
const id = common.sanitizeText(_id, configApi.getConfig());
const id = common.sanitizeText(_id, getConfig());
if (id in classes) {
return classes[id].domId;
}
@ -139,15 +139,9 @@ export const addRelation = function (relation: ClassRelation) {
relation.id1 = splitClassNameAndType(relation.id1).className;
relation.id2 = splitClassNameAndType(relation.id2).className;
relation.relationTitle1 = common.sanitizeText(
relation.relationTitle1.trim(),
configApi.getConfig()
);
relation.relationTitle1 = common.sanitizeText(relation.relationTitle1.trim(), getConfig());
relation.relationTitle2 = common.sanitizeText(
relation.relationTitle2.trim(),
configApi.getConfig()
);
relation.relationTitle2 = common.sanitizeText(relation.relationTitle2.trim(), getConfig());
relations.push(relation);
};
@ -267,7 +261,7 @@ export const getTooltip = function (id: string, namespace?: string) {
* @param target - Target of the link, _blank by default as originally defined in the svgDraw.js file
*/
export const setLink = function (ids: string, linkStr: string, target: string) {
const config = configApi.getConfig();
const config = getConfig();
ids.split(',').forEach(function (_id) {
let id = _id;
if (_id[0].match(/\d/)) {
@ -303,8 +297,8 @@ export const setClickEvent = function (ids: string, functionName: string, functi
};
const setClickFunc = function (_domId: string, functionName: string, functionArgs: string) {
const domId = common.sanitizeText(_domId, configApi.getConfig());
const config = configApi.getConfig();
const domId = common.sanitizeText(_domId, getConfig());
const config = getConfig();
if (config.securityLevel !== 'loose') {
return;
}
@ -465,7 +459,7 @@ export default {
getAccTitle,
getAccDescription,
setAccDescription,
getConfig: () => configApi.getConfig().class,
getConfig: () => getConfig().class,
addClass,
bindFunctions,
clear,

View File

@ -2,7 +2,7 @@
import { select, curveLinear } from 'd3';
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { log } from '../../logger.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { render } from '../../dagre-wrapper/index.js';
import utils from '../../utils.js';
import { interpolateToCurve, getStylesFromArray } from '../../utils.js';

View File

@ -4,7 +4,7 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { log } from '../../logger.js';
import svgDraw from './svgDraw.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
let idCache = {};
const padding = 20;

View File

@ -1,4 +1,4 @@
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { parseGenericTypes, sanitizeText } from '../common/common.js';
export interface ClassNode {

View File

@ -1,7 +1,6 @@
const getStyles = (options) =>
`g.classGroup text {
fill: ${options.nodeBorder};
fill: ${options.classText};
fill: ${options.nodeBorder || options.classText};
stroke: none;
font-family: ${options.fontFamily};
font-size: 10px;

View File

@ -1,5 +1,5 @@
import { log } from '../../logger.js';
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import {
setAccTitle,
@ -83,7 +83,7 @@ const clear = function () {
export default {
Cardinality,
Identification,
getConfig: () => configApi.getConfig().er,
getConfig: () => getConfig().er,
addEntity,
addAttributes,
getEntities,

View File

@ -1,7 +1,7 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { line, curveBasis, select } from 'd3';
import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { log } from '../../logger.js';
import utils from '../../utils.js';
import erMarkers from './erMarkers.js';
@ -202,7 +202,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
let attribStyle = 'attributeBoxOdd'; // We will flip the style on alternate rows to achieve a banded effect
attributeNodes.forEach((attributeNode) => {
// Calculate the alignment y co-ordinate for the type/name of the attribute
// Calculate the alignment y coordinate for the type/name of the attribute
const alignY = heightOffset + heightPadding + attributeNode.height / 2;
// Position the type attribute
@ -579,8 +579,8 @@ export const draw = function (text, id, _version, diagObj) {
// 2. Make sure they are all added to the graph
// 3. Add all the edges (relationships) to the graph as well
// 4. Let dagre do its magic to lay out the graph. This assigns:
// - the centre co-ordinates for each node, bearing in mind the dimensions and edge relationships
// - the path co-ordinates for each edge
// - the centre coordinates for each node, bearing in mind the dimensions and edge relationships
// - the path coordinates for each edge
// But it has no impact on the svg child nodes - the diagram remains with every entity rooted at 0,0
// 5. Now assign a transform to each entity in the svg node so that it gets drawn in the correct place, as determined by
// its centre point, which is obtained from the graph, and it's width and height

View File

@ -92,7 +92,7 @@ describe('when parsing ER diagram it...', function () {
});
});
it('cannot contain % because it interfers with parsing comments', function () {
it('cannot contain % because it interferes with parsing comments', function () {
expect(() => {
erDiagram.parser.parse(`erDiagram\n "Blo%rf"\n`);
const entities = erDb.getEntities();

View File

@ -561,7 +561,7 @@ export const addEdges = function (edges, diagObj, graph, svg) {
};
// TODO: break out and share with dagre wrapper. The current code in dagre wrapper also adds
// adds the line to the graph, but we don't need that here. This is why we cant use the dagre
// adds the line to the graph, but we don't need that here. This is why we can't use the dagre
// wrapper directly for this
/**
* Add the markers to the edge depending on the type of arrow is
@ -803,8 +803,14 @@ const insertChildren = (nodeArray, parentLookupDb) => {
*/
export const draw = async function (text, id, _version, diagObj) {
// Add temporary render element
diagObj.db.clear();
nodeDb = {};
portPos = {};
diagObj.db.setGen('gen-2');
// Parse the graph definition
diagObj.parser.parse(text);
const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy');
let graph = {
id: 'root',

View File

@ -1,6 +1,6 @@
import { select } from 'd3';
import utils from '../../utils.js';
import * as configApi from '../../config.js';
import { getConfig, defaultConfig } from '../../diagram-api/diagramAPI.js';
import common from '../common/common.js';
import { log } from '../../logger.js';
import {
@ -12,10 +12,11 @@ import {
setDiagramTitle,
getDiagramTitle,
} from '../common/commonDb.js';
import errorDiagram from '../error/errorDiagram.js';
const MERMAID_DOM_ID_PREFIX = 'flowchart-';
let vertexCounter = 0;
let config = configApi.getConfig();
let config = getConfig();
let vertices = {};
let edges = [];
let classes = {};
@ -84,7 +85,7 @@ export const addVertex = function (_id, textObj, type, style, classes, dir, prop
}
vertexCounter++;
if (textObj !== undefined) {
config = configApi.getConfig();
config = getConfig();
txt = sanitizeText(textObj.text.trim());
vertices[id].labelType = textObj.type;
// strip quotes if string starts and ends with a quote
@ -156,7 +157,15 @@ export const addSingleLink = function (_start, _end, type) {
edge.stroke = type.stroke;
edge.length = type.length;
}
edges.push(edge);
if (edge?.length > 10) {
edge.length = 10;
}
if (edges.length < 280) {
log.info('abc78 pushing edge...');
edges.push(edge);
} else {
throw new Error('Too many edges');
}
};
export const addLink = function (_start, _end, type) {
log.info('addLink (abc78)', _start, _end, type);
@ -277,7 +286,7 @@ const setTooltip = function (ids, tooltip) {
const setClickFun = function (id, functionName, functionArgs) {
let domId = lookUpDomId(id);
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (configApi.getConfig().securityLevel !== 'loose') {
if (getConfig().securityLevel !== 'loose') {
return;
}
if (functionName === undefined) {
@ -766,7 +775,7 @@ export const lex = {
firstGraph,
};
export default {
defaultConfig: () => configApi.defaultConfig.flowchart,
defaultConfig: () => defaultConfig.flowchart,
setAccTitle,
getAccTitle,
getAccDescription,

View File

@ -4,7 +4,7 @@ import flowDb from './flowDb.js';
import flowRendererV2 from './flowRenderer-v2.js';
import flowStyles from './styles.js';
import type { MermaidConfig } from '../../config.type.js';
import { setConfig } from '../../config.js';
import { setConfig } from '../../diagram-api/diagramAPI.js';
export const diagram = {
parser: flowParser,

View File

@ -1,6 +1,6 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select, curveLinear, selectAll } from 'd3';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import utils from '../../utils.js';
import { render } from '../../dagre-wrapper/index.js';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';

View File

@ -1,6 +1,6 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select, curveLinear, selectAll } from 'd3';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { render as Render } from 'dagre-d3-es';
import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';

View File

@ -1,5 +1,5 @@
import { addVertices, addEdges } from './flowRenderer.js';
import { setConfig } from '../../config.js';
import { setConfig } from '../../diagram-api/diagramAPI.js';
setConfig({
flowchart: {

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@ import dayjsIsoWeek from 'dayjs/plugin/isoWeek.js';
import dayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js';
import dayjsAdvancedFormat from 'dayjs/plugin/advancedFormat.js';
import { log } from '../../logger.js';
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import utils from '../../utils.js';
import {
@ -603,7 +603,7 @@ const compileTasks = function () {
*/
export const setLink = function (ids, _linkStr) {
let linkStr = _linkStr;
if (configApi.getConfig().securityLevel !== 'loose') {
if (getConfig().securityLevel !== 'loose') {
linkStr = sanitizeUrl(_linkStr);
}
ids.split(',').forEach(function (id) {
@ -634,7 +634,7 @@ export const setClass = function (ids, className) {
};
const setClickFun = function (id, functionName, functionArgs) {
if (configApi.getConfig().securityLevel !== 'loose') {
if (getConfig().securityLevel !== 'loose') {
return;
}
if (functionName === undefined) {
@ -725,7 +725,7 @@ export const bindFunctions = function (element) {
};
export default {
getConfig: () => configApi.getConfig().gantt,
getConfig: () => getConfig().gantt,
clear,
setDateFormat,
getDateFormat,

View File

@ -25,7 +25,7 @@ import {
timeMonth,
} from 'd3';
import common from '../common/common.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
export const setConf = function () {

View File

@ -1,7 +1,6 @@
import { log } from '../../logger.js';
import { random } from '../../utils.js';
import * as configApi from '../../config.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import common from '../common/common.js';
import {
setAccTitle,
@ -106,9 +105,9 @@ export const getOptions = function () {
export const commit = function (msg, id, type, tag) {
log.debug('Entering commit:', msg, id, type, tag);
id = common.sanitizeText(id, configApi.getConfig());
msg = common.sanitizeText(msg, configApi.getConfig());
tag = common.sanitizeText(tag, configApi.getConfig());
id = common.sanitizeText(id, getConfig());
msg = common.sanitizeText(msg, getConfig());
tag = common.sanitizeText(tag, getConfig());
const commit = {
id: id ? id : seq + '-' + getId(),
message: msg,
@ -125,7 +124,7 @@ export const commit = function (msg, id, type, tag) {
};
export const branch = function (name, order) {
name = common.sanitizeText(name, configApi.getConfig());
name = common.sanitizeText(name, getConfig());
if (branches[name] === undefined) {
branches[name] = head != null ? head.id : null;
branchesConfig[name] = { name, order: order ? parseInt(order, 10) : null };
@ -149,8 +148,8 @@ export const branch = function (name, order) {
};
export const merge = function (otherBranch, custom_id, override_type, custom_tag) {
otherBranch = common.sanitizeText(otherBranch, configApi.getConfig());
custom_id = common.sanitizeText(custom_id, configApi.getConfig());
otherBranch = common.sanitizeText(otherBranch, getConfig());
custom_id = common.sanitizeText(custom_id, getConfig());
const currentCommit = commits[branches[curBranch]];
const otherCommit = commits[branches[otherBranch]];
@ -258,9 +257,9 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
export const cherryPick = function (sourceId, targetId, tag) {
log.debug('Entering cherryPick:', sourceId, targetId, tag);
sourceId = common.sanitizeText(sourceId, configApi.getConfig());
targetId = common.sanitizeText(targetId, configApi.getConfig());
tag = common.sanitizeText(tag, configApi.getConfig());
sourceId = common.sanitizeText(sourceId, getConfig());
targetId = common.sanitizeText(targetId, getConfig());
tag = common.sanitizeText(tag, getConfig());
if (!sourceId || commits[sourceId] === undefined) {
let error = new Error(
@ -338,7 +337,7 @@ export const cherryPick = function (sourceId, targetId, tag) {
}
};
export const checkout = function (branch) {
branch = common.sanitizeText(branch, configApi.getConfig());
branch = common.sanitizeText(branch, getConfig());
if (branches[branch] === undefined) {
let error = new Error(
'Trying to checkout branch which is not yet created. (Help try using "branch ' + branch + '")'
@ -502,7 +501,7 @@ export const commitType = {
};
export default {
getConfig: () => configApi.getConfig().gitGraph,
getConfig: () => getConfig().gitGraph,
setDirection,
setOptions,
getOptions,

View File

@ -6,7 +6,7 @@ describe('when parsing a gitGraph', function () {
parser.yy = gitGraphAst;
parser.yy.clear();
});
it('should handle a gitGraph commit with NO pararms, get auto-genrated reandom ID', function () {
it('should handle a gitGraph commit with NO pararms, get auto-generated reandom ID', function () {
const str = `gitGraph:
commit
`;

View File

@ -1,4 +1,4 @@
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
export default (dir, _branches) => {
const config = getConfig().gitGraph;

View File

@ -129,7 +129,7 @@ root
expect(child.nodeId).toEqual('theId');
expect(child.type).toEqual(mindmap.yy.nodeType.ROUNDED_RECT);
});
it('MMP-10 mutiple types (circle)', function () {
it('MMP-10 multiple types (circle)', function () {
let str = `mindmap
root((the root))
`;
@ -141,7 +141,7 @@ root
expect(mm.type).toEqual(mindmap.yy.nodeType.CIRCLE);
});
it('MMP-11 mutiple types (cloud)', function () {
it('MMP-11 multiple types (cloud)', function () {
let str = `mindmap
root)the root(
`;
@ -152,7 +152,7 @@ root
expect(mm.children.length).toEqual(0);
expect(mm.type).toEqual(mindmap.yy.nodeType.CLOUD);
});
it('MMP-12 mutiple types (bang)', function () {
it('MMP-12 multiple types (bang)', function () {
let str = `mindmap
root))the root((
`;
@ -164,7 +164,7 @@ root
expect(mm.type).toEqual(mindmap.yy.nodeType.BANG);
});
it('MMP-12-a mutiple types (hexagon)', function () {
it('MMP-12-a multiple types (hexagon)', function () {
let str = `mindmap
root{{the root}}
`;

View File

@ -1,4 +1,4 @@
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { sanitizeText as _sanitizeText } from '../../diagrams/common/common.js';
import { log } from '../../logger.js';

View File

@ -1,7 +1,7 @@
/** Created by knut on 14-12-11. */
import { select } from 'd3';
import { log } from '../../logger.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import svgDraw from './svgDraw.js';
import cytoscape from 'cytoscape/dist/cytoscape.umd.js';

View File

@ -1,7 +1,7 @@
// @ts-ignore: JISON doesn't support types
import { parser } from './parser/pie.jison';
import { DEFAULT_PIE_DB, db } from './pieDb.js';
import { setConfig } from '../../config.js';
import { setConfig } from '../../diagram-api/diagramAPI.js';
setConfig({
securityLevel: 'strict',

View File

@ -1,5 +1,5 @@
import { log } from '../../logger.js';
import { getConfig as commonGetConfig } from '../../config.js';
import { getConfig as commonGetConfig } from '../../diagram-api/diagramAPI.js';
import { sanitizeText } from '../common/common.js';
import {
setAccTitle,

View File

@ -3,7 +3,7 @@ import { scaleOrdinal, pie as d3pie, arc } from 'd3';
import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { cleanAndMerge, parseFontSize } from '../../utils.js';
import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js';
import type { D3Sections, PieDB, Sections } from './pieTypes.js';

View File

@ -1,4 +1,3 @@
// @ts-ignore: TODO Fix ts errors
import { scaleLinear } from 'd3';
import { log } from '../../logger.js';
import type { BaseDiagramConfig, QuadrantChartConfig } from '../../config.type.js';
@ -283,14 +282,17 @@ export class QuadrantBuilder {
quadrantTop,
quadrantWidth,
} = quadrantSpace;
const drawAxisLabelInMiddle = this.data.points.length === 0;
const drawXAxisLabelsInMiddle = Boolean(this.data.xAxisRightText);
const drawYAxisLabelsInMiddle = Boolean(this.data.yAxisTopText);
const axisLabels: QuadrantTextType[] = [];
if (this.data.xAxisLeftText && showXAxis) {
axisLabels.push({
text: this.data.xAxisLeftText,
fill: this.themeConfig.quadrantXAxisTextFill,
x: quadrantLeft + (drawAxisLabelInMiddle ? quadrantHalfWidth / 2 : 0),
x: quadrantLeft + (drawXAxisLabelsInMiddle ? quadrantHalfWidth / 2 : 0),
y:
xAxisPosition === 'top'
? this.config.xAxisLabelPadding + titleSpace.top
@ -299,7 +301,7 @@ export class QuadrantBuilder {
quadrantHeight +
this.config.quadrantPadding,
fontSize: this.config.xAxisLabelFontSize,
verticalPos: drawAxisLabelInMiddle ? 'center' : 'left',
verticalPos: drawXAxisLabelsInMiddle ? 'center' : 'left',
horizontalPos: 'top',
rotation: 0,
});
@ -308,7 +310,7 @@ export class QuadrantBuilder {
axisLabels.push({
text: this.data.xAxisRightText,
fill: this.themeConfig.quadrantXAxisTextFill,
x: quadrantLeft + quadrantHalfWidth + (drawAxisLabelInMiddle ? quadrantHalfWidth / 2 : 0),
x: quadrantLeft + quadrantHalfWidth + (drawXAxisLabelsInMiddle ? quadrantHalfWidth / 2 : 0),
y:
xAxisPosition === 'top'
? this.config.xAxisLabelPadding + titleSpace.top
@ -317,7 +319,7 @@ export class QuadrantBuilder {
quadrantHeight +
this.config.quadrantPadding,
fontSize: this.config.xAxisLabelFontSize,
verticalPos: drawAxisLabelInMiddle ? 'center' : 'left',
verticalPos: drawXAxisLabelsInMiddle ? 'center' : 'left',
horizontalPos: 'top',
rotation: 0,
});
@ -334,9 +336,9 @@ export class QuadrantBuilder {
quadrantLeft +
quadrantWidth +
this.config.quadrantPadding,
y: quadrantTop + quadrantHeight - (drawAxisLabelInMiddle ? quadrantHalfHeight / 2 : 0),
y: quadrantTop + quadrantHeight - (drawYAxisLabelsInMiddle ? quadrantHalfHeight / 2 : 0),
fontSize: this.config.yAxisLabelFontSize,
verticalPos: drawAxisLabelInMiddle ? 'center' : 'left',
verticalPos: drawYAxisLabelsInMiddle ? 'center' : 'left',
horizontalPos: 'top',
rotation: -90,
});
@ -352,9 +354,10 @@ export class QuadrantBuilder {
quadrantLeft +
quadrantWidth +
this.config.quadrantPadding,
y: quadrantTop + quadrantHalfHeight - (drawAxisLabelInMiddle ? quadrantHalfHeight / 2 : 0),
y:
quadrantTop + quadrantHalfHeight - (drawYAxisLabelsInMiddle ? quadrantHalfHeight / 2 : 0),
fontSize: this.config.yAxisLabelFontSize,
verticalPos: drawAxisLabelInMiddle ? 'center' : 'left',
verticalPos: drawYAxisLabelsInMiddle ? 'center' : 'left',
horizontalPos: 'top',
rotation: -90,
});

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { sanitizeText } from '../common/common.js';
import {
setAccTitle,
@ -11,7 +11,7 @@ import {
} from '../common/commonDb.js';
import { QuadrantBuilder } from './quadrantBuilder.js';
const config = configApi.getConfig();
const config = getConfig();
function textSanitizer(text: string) {
return sanitizeText(text.trim(), config);
@ -66,7 +66,7 @@ function setHeight(height: number) {
}
function getQuadrantData() {
const config = configApi.getConfig();
const config = getConfig();
const { themeVariables, quadrantChart: quadrantChartConfig } = config;
if (quadrantChartConfig) {
quadrantBuilder.setConfig(quadrantChartConfig);

View File

@ -1,6 +1,6 @@
// @ts-nocheck - don't check until handle it
import { select } from 'd3';
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { Diagram } from '../../Diagram.js';
@ -27,7 +27,7 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram
return `translate(${data.x}, ${data.y}) rotate(${data.rotation || 0})`;
}
const conf = configApi.getConfig();
const conf = getConfig();
log.debug('Rendering quadrant chart\n' + txt);

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { log } from '../../logger.js';
import {
@ -144,7 +144,7 @@ export default {
VerifyType,
Relationships,
getConfig: () => configApi.getConfig().req,
getConfig: () => getConfig().req,
addRequirement,
getRequirements,

View File

@ -5,7 +5,7 @@ import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import common from '../common/common.js';
import markers from './requirementMarkers.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
let conf = {};
let relCnt = 0;

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import common from '../common/common.js';
import {
setAccTitle,
@ -42,7 +42,7 @@ class SankeyNode {
}
const findOrCreateNode = (ID: string): SankeyNode => {
ID = common.sanitizeText(ID, configApi.getConfig());
ID = common.sanitizeText(ID, getConfig());
if (!nodesMap[ID]) {
nodesMap[ID] = new SankeyNode(ID);
@ -65,7 +65,7 @@ const getGraph = () => ({
export default {
nodesMap,
getConfig: () => configApi.getConfig().sankey,
getConfig: () => getConfig().sankey,
getNodes,
getLinks,
getGraph,

View File

@ -1,5 +1,5 @@
import type { Diagram } from '../../Diagram.js';
import * as configApi from '../../config.js';
import { getConfig, defaultConfig } from '../../diagram-api/diagramAPI.js';
import {
select as d3select,
@ -41,8 +41,8 @@ const alignmentsMap: Record<
*/
export const draw = function (text: string, id: string, _version: string, diagObj: Diagram): void {
// Get Sankey config
const { securityLevel, sankey: conf } = configApi.getConfig();
const defaultSankeyConfig = configApi!.defaultConfig!.sankey!;
const { securityLevel, sankey: conf } = getConfig();
const defaultSankeyConfig = defaultConfig!.sankey!;
// TODO:
// This code repeats for every diagram

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { log } from '../../logger.js';
import { sanitizeText } from '../common/common.js';
import {
@ -196,7 +196,7 @@ export const autoWrap = () => {
if (wrapEnabled !== undefined) {
return wrapEnabled;
}
return configApi.getConfig().sequence.wrap;
return getConfig().sequence.wrap;
};
export const clear = function () {
@ -251,7 +251,7 @@ export const parseBoxData = function (str) {
color: color,
text:
title !== undefined
? sanitizeText(title.replace(/^:?(?:no)?wrap:/, ''), configApi.getConfig())
? sanitizeText(title.replace(/^:?(?:no)?wrap:/, ''), getConfig())
: undefined,
wrap:
title !== undefined
@ -337,7 +337,7 @@ export const addLinks = function (actorId, text) {
const actor = getActor(actorId);
// JSON.parse the text
try {
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
let sanitizedText = sanitizeText(text.text, getConfig());
sanitizedText = sanitizedText.replace(/&amp;/g, '&');
sanitizedText = sanitizedText.replace(/&equals;/g, '=');
const links = JSON.parse(sanitizedText);
@ -353,7 +353,7 @@ export const addALink = function (actorId, text) {
const actor = getActor(actorId);
try {
const links = {};
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
let sanitizedText = sanitizeText(text.text, getConfig());
var sep = sanitizedText.indexOf('@');
sanitizedText = sanitizedText.replace(/&amp;/g, '&');
sanitizedText = sanitizedText.replace(/&equals;/g, '=');
@ -387,7 +387,7 @@ export const addProperties = function (actorId, text) {
const actor = getActor(actorId);
// JSON.parse the text
try {
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
let sanitizedText = sanitizeText(text.text, getConfig());
const properties = JSON.parse(sanitizedText);
// add the deserialized text to the actor's property field.
insertProperties(actor, properties);
@ -629,7 +629,7 @@ export default {
getBoxes,
getDiagramTitle,
setDiagramTitle,
getConfig: () => configApi.getConfig().sequence,
getConfig: () => getConfig().sequence,
clear,
parseMessage,
parseBoxData,

View File

@ -1,5 +1,5 @@
import { vi } from 'vitest';
import * as configApi from '../../config.js';
import { setSiteConfig } from '../../diagram-api/diagramAPI.js';
import mermaidAPI from '../../mermaidAPI.js';
import { Diagram, getDiagramFromText } from '../../Diagram.js';
import { addDiagrams } from '../../diagram-api/diagram-orchestration.js';
@ -1610,7 +1610,7 @@ describe('when rendering a sequenceDiagram APA', function () {
wrap: false,
mirrorActors: false,
};
configApi.setSiteConfig({ logLevel: 5, sequence: conf });
setSiteConfig({ logLevel: 5, sequence: conf });
});
let conf;
beforeEach(function () {
@ -1631,7 +1631,7 @@ describe('when rendering a sequenceDiagram APA', function () {
wrap: false,
mirrorActors: false,
};
configApi.setSiteConfig({ logLevel: 5, sequence: conf });
setSiteConfig({ logLevel: 5, sequence: conf });
diagram = new Diagram(`
sequenceDiagram
Alice->Bob:Hello Bob, how are you?

View File

@ -4,7 +4,7 @@ import svgDraw, { ACTOR_TYPE_WIDTH, drawText, fixLifeLineHeights } from './svgDr
import { log } from '../../logger.js';
import common from '../common/common.js';
import * as svgDrawCommon from '../common/svgDrawCommon.js';
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import assignWithDepth from '../../assignWithDepth.js';
import utils from '../../utils.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
@ -91,7 +91,7 @@ export const bounds = {
stopy: undefined,
};
this.verticalPos = 0;
setConf(configApi.getConfig());
setConf(getConfig());
},
updateVal: function (obj, key, val, fun) {
if (obj[key] === undefined) {
@ -747,7 +747,7 @@ function adjustCreatedDestroyedData(
* @param diagObj - A standard diagram containing the db and the text and type etc of the diagram
*/
export const draw = function (_text: string, id: string, _version: string, diagObj: Diagram) {
const { securityLevel, sequence } = configApi.getConfig();
const { securityLevel, sequence } = getConfig();
conf = sequence;
// Handle root and Document for when rendering in sandbox mode
let sandboxElement;

View File

@ -3,7 +3,7 @@ import idCache from './id-cache.js';
import stateDb from './stateDb.js';
import utils from '../../utils.js';
import common from '../common/common.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { log } from '../../logger.js';
/**

View File

@ -1,7 +1,7 @@
import { log } from '../../logger.js';
import { generateId } from '../../utils.js';
import common from '../common/common.js';
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import {
setAccTitle,
getAccTitle,
@ -253,7 +253,7 @@ export const addState = function (
currentDocument.states[trimmedId].note = note;
currentDocument.states[trimmedId].note.text = common.sanitizeText(
currentDocument.states[trimmedId].note.text,
configApi.getConfig()
getConfig()
);
}
@ -398,7 +398,7 @@ export function addRelationObjs(item1, item2, relationTitle) {
currentDocument.relations.push({
id1,
id2,
relationTitle: common.sanitizeText(relationTitle, configApi.getConfig()),
relationTitle: common.sanitizeText(relationTitle, getConfig()),
});
}
@ -423,7 +423,7 @@ export const addRelation = function (item1, item2, title) {
currentDocument.relations.push({
id1,
id2,
title: common.sanitizeText(title, configApi.getConfig()),
title: common.sanitizeText(title, getConfig()),
});
}
};
@ -431,7 +431,7 @@ export const addRelation = function (item1, item2, title) {
export const addDescription = function (id, descr) {
const theState = currentDocument.states[id];
const _descr = descr.startsWith(':') ? descr.replace(':', '').trim() : descr;
theState.descriptions.push(common.sanitizeText(_descr, configApi.getConfig()));
theState.descriptions.push(common.sanitizeText(_descr, getConfig()));
};
export const cleanupLabel = function (label) {
@ -542,7 +542,7 @@ const setDirection = (dir) => {
const trimColon = (str) => (str && str[0] === ':' ? str.substr(1).trim() : str.trim());
export default {
getConfig: () => configApi.getConfig().state,
getConfig: () => getConfig().state,
addState,
clear,
getState,

View File

@ -212,14 +212,14 @@ describe('state diagram, ', function () {
parser.parse(str);
});
it('should handle state defintions with separation of id', function () {
it('should handle state definitions with separation of id', function () {
const str = `stateDiagram\n
state "Long state description" as state1
`;
parser.parse(str);
});
it('should handle state defintions with separation of id', function () {
it('should handle state definitions with separation of id', function () {
const str = `stateDiagram
state "Not Shooting State" as NotShooting {
state "Idle mode" as Idle
@ -360,7 +360,7 @@ describe('state diagram, ', function () {
parser.parse(str);
});
it('should handle notes for composit states', function () {
it('should handle notes for composite states', function () {
const str = `stateDiagram\n
[*] --> NotShooting

View File

@ -1,6 +1,6 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select } from 'd3';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { render } from '../../dagre-wrapper/index.js';
import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';

View File

@ -4,7 +4,7 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { log } from '../../logger.js';
import common from '../common/common.js';
import { drawState, addTitleAndBox, drawEdge } from './shapes.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
// TODO Move conf object to main conf in mermaidAPI

View File

@ -3,7 +3,7 @@ import type { Selection } from 'd3';
import { select } from 'd3';
import svgDraw from './svgDraw.js';
import { log } from '../../logger.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import type { Diagram } from '../../Diagram.js';
import type { MermaidConfig } from '../../config.type.js';

View File

@ -1,4 +1,4 @@
import * as configApi from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import {
setAccTitle,
getAccTitle,
@ -113,7 +113,7 @@ const getActors = function () {
};
export default {
getConfig: () => configApi.getConfig().journey,
getConfig: () => getConfig().journey,
clear,
setDiagramTitle,
getDiagramTitle,

View File

@ -1,7 +1,7 @@
// @ts-nocheck TODO: fix file
import { select } from 'd3';
import svgDraw from './svgDraw.js';
import { getConfig } from '../../config.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
export const setConf = function (cnf) {

View File

@ -0,0 +1,45 @@
import type { ScaleBand } from 'd3';
import { scaleBand } from 'd3';
import { log } from '../../../../../logger.js';
import type { TextDimensionCalculator } from '../../textDimensionCalculator.js';
import { BaseAxis } from './baseAxis.js';
import type { XYChartAxisThemeConfig, XYChartAxisConfig } from '../../interfaces.js';
export class BandAxis extends BaseAxis {
private scale: ScaleBand<string>;
private categories: string[];
constructor(
axisConfig: XYChartAxisConfig,
axisThemeConfig: XYChartAxisThemeConfig,
categories: string[],
title: string,
textDimensionCalculator: TextDimensionCalculator
) {
super(axisConfig, title, textDimensionCalculator, axisThemeConfig);
this.categories = categories;
this.scale = scaleBand().domain(this.categories).range(this.getRange());
}
setRange(range: [number, number]): void {
super.setRange(range);
}
recalculateScale(): void {
this.scale = scaleBand()
.domain(this.categories)
.range(this.getRange())
.paddingInner(1)
.paddingOuter(0)
.align(0.5);
log.trace('BandAxis axis final categories, range: ', this.categories, this.getRange());
}
getTickValues(): (string | number)[] {
return this.categories;
}
getScaleValue(value: string): number {
return this.scale(value) || this.getRange()[0];
}
}

View File

@ -0,0 +1,422 @@
import type {
BoundingRect,
Dimension,
DrawableElem,
Point,
XYChartAxisConfig,
XYChartAxisThemeConfig,
} from '../../interfaces.js';
import type { TextDimensionCalculator } from '../../textDimensionCalculator.js';
import type { Axis, AxisPosition } from './index.js';
const BAR_WIDTH_TO_TICK_WIDTH_RATIO = 0.7;
const MAX_OUTER_PADDING_PERCENT_FOR_WRT_LABEL = 0.2;
export abstract class BaseAxis implements Axis {
protected boundingRect: BoundingRect = { x: 0, y: 0, width: 0, height: 0 };
protected axisPosition: AxisPosition = 'left';
private range: [number, number];
protected showTitle = false;
protected showLabel = false;
protected showTick = false;
protected showAxisLine = false;
protected outerPadding = 0;
protected titleTextHeight = 0;
protected labelTextHeight = 0;
constructor(
protected axisConfig: XYChartAxisConfig,
protected title: string,
protected textDimensionCalculator: TextDimensionCalculator,
protected axisThemeConfig: XYChartAxisThemeConfig
) {
this.range = [0, 10];
this.boundingRect = { x: 0, y: 0, width: 0, height: 0 };
this.axisPosition = 'left';
}
setRange(range: [number, number]): void {
this.range = range;
if (this.axisPosition === 'left' || this.axisPosition === 'right') {
this.boundingRect.height = range[1] - range[0];
} else {
this.boundingRect.width = range[1] - range[0];
}
this.recalculateScale();
}
getRange(): [number, number] {
return [this.range[0] + this.outerPadding, this.range[1] - this.outerPadding];
}
setAxisPosition(axisPosition: AxisPosition): void {
this.axisPosition = axisPosition;
this.setRange(this.range);
}
abstract getScaleValue(value: number | string): number;
abstract recalculateScale(): void;
abstract getTickValues(): Array<string | number>;
getTickDistance(): number {
const range = this.getRange();
return Math.abs(range[0] - range[1]) / this.getTickValues().length;
}
getAxisOuterPadding(): number {
return this.outerPadding;
}
private getLabelDimension(): Dimension {
return this.textDimensionCalculator.getMaxDimension(
this.getTickValues().map((tick) => tick.toString()),
this.axisConfig.labelFontSize
);
}
recalculateOuterPaddingToDrawBar(): void {
if (BAR_WIDTH_TO_TICK_WIDTH_RATIO * this.getTickDistance() > this.outerPadding * 2) {
this.outerPadding = Math.floor((BAR_WIDTH_TO_TICK_WIDTH_RATIO * this.getTickDistance()) / 2);
}
this.recalculateScale();
}
private calculateSpaceIfDrawnHorizontally(availableSpace: Dimension) {
let availableHeight = availableSpace.height;
if (this.axisConfig.showAxisLine && availableHeight > this.axisConfig.axisLineWidth) {
availableHeight -= this.axisConfig.axisLineWidth;
this.showAxisLine = true;
}
if (this.axisConfig.showLabel) {
const spaceRequired = this.getLabelDimension();
const maxPadding = MAX_OUTER_PADDING_PERCENT_FOR_WRT_LABEL * availableSpace.width;
this.outerPadding = Math.min(spaceRequired.width / 2, maxPadding);
const heightRequired = spaceRequired.height + this.axisConfig.labelPadding * 2;
this.labelTextHeight = spaceRequired.height;
if (heightRequired <= availableHeight) {
availableHeight -= heightRequired;
this.showLabel = true;
}
}
if (this.axisConfig.showTick && availableHeight >= this.axisConfig.tickLength) {
this.showTick = true;
availableHeight -= this.axisConfig.tickLength;
}
if (this.axisConfig.showTitle && this.title) {
const spaceRequired = this.textDimensionCalculator.getMaxDimension(
[this.title],
this.axisConfig.titleFontSize
);
const heightRequired = spaceRequired.height + this.axisConfig.titlePadding * 2;
this.titleTextHeight = spaceRequired.height;
if (heightRequired <= availableHeight) {
availableHeight -= heightRequired;
this.showTitle = true;
}
}
this.boundingRect.width = availableSpace.width;
this.boundingRect.height = availableSpace.height - availableHeight;
}
private calculateSpaceIfDrawnVertical(availableSpace: Dimension) {
let availableWidth = availableSpace.width;
if (this.axisConfig.showAxisLine && availableWidth > this.axisConfig.axisLineWidth) {
availableWidth -= this.axisConfig.axisLineWidth;
this.showAxisLine = true;
}
if (this.axisConfig.showLabel) {
const spaceRequired = this.getLabelDimension();
const maxPadding = MAX_OUTER_PADDING_PERCENT_FOR_WRT_LABEL * availableSpace.height;
this.outerPadding = Math.min(spaceRequired.height / 2, maxPadding);
const widthRequired = spaceRequired.width + this.axisConfig.labelPadding * 2;
if (widthRequired <= availableWidth) {
availableWidth -= widthRequired;
this.showLabel = true;
}
}
if (this.axisConfig.showTick && availableWidth >= this.axisConfig.tickLength) {
this.showTick = true;
availableWidth -= this.axisConfig.tickLength;
}
if (this.axisConfig.showTitle && this.title) {
const spaceRequired = this.textDimensionCalculator.getMaxDimension(
[this.title],
this.axisConfig.titleFontSize
);
const widthRequired = spaceRequired.height + this.axisConfig.titlePadding * 2;
this.titleTextHeight = spaceRequired.height;
if (widthRequired <= availableWidth) {
availableWidth -= widthRequired;
this.showTitle = true;
}
}
this.boundingRect.width = availableSpace.width - availableWidth;
this.boundingRect.height = availableSpace.height;
}
calculateSpace(availableSpace: Dimension): Dimension {
if (this.axisPosition === 'left' || this.axisPosition === 'right') {
this.calculateSpaceIfDrawnVertical(availableSpace);
} else {
this.calculateSpaceIfDrawnHorizontally(availableSpace);
}
this.recalculateScale();
return {
width: this.boundingRect.width,
height: this.boundingRect.height,
};
}
setBoundingBoxXY(point: Point): void {
this.boundingRect.x = point.x;
this.boundingRect.y = point.y;
}
private getDrawableElementsForLeftAxis(): DrawableElem[] {
const drawableElement: DrawableElem[] = [];
if (this.showAxisLine) {
const x = this.boundingRect.x + this.boundingRect.width - this.axisConfig.axisLineWidth / 2;
drawableElement.push({
type: 'path',
groupTexts: ['left-axis', 'axisl-line'],
data: [
{
path: `M ${x},${this.boundingRect.y} L ${x},${
this.boundingRect.y + this.boundingRect.height
} `,
strokeFill: this.axisThemeConfig.axisLineColor,
strokeWidth: this.axisConfig.axisLineWidth,
},
],
});
}
if (this.showLabel) {
drawableElement.push({
type: 'text',
groupTexts: ['left-axis', 'label'],
data: this.getTickValues().map((tick) => ({
text: tick.toString(),
x:
this.boundingRect.x +
this.boundingRect.width -
(this.showLabel ? this.axisConfig.labelPadding : 0) -
(this.showTick ? this.axisConfig.tickLength : 0) -
(this.showAxisLine ? this.axisConfig.axisLineWidth : 0),
y: this.getScaleValue(tick),
fill: this.axisThemeConfig.labelColor,
fontSize: this.axisConfig.labelFontSize,
rotation: 0,
verticalPos: 'middle',
horizontalPos: 'right',
})),
});
}
if (this.showTick) {
const x =
this.boundingRect.x +
this.boundingRect.width -
(this.showAxisLine ? this.axisConfig.axisLineWidth : 0);
drawableElement.push({
type: 'path',
groupTexts: ['left-axis', 'ticks'],
data: this.getTickValues().map((tick) => ({
path: `M ${x},${this.getScaleValue(tick)} L ${
x - this.axisConfig.tickLength
},${this.getScaleValue(tick)}`,
strokeFill: this.axisThemeConfig.tickColor,
strokeWidth: this.axisConfig.tickWidth,
})),
});
}
if (this.showTitle) {
drawableElement.push({
type: 'text',
groupTexts: ['left-axis', 'title'],
data: [
{
text: this.title,
x: this.boundingRect.x + this.axisConfig.titlePadding,
y: this.boundingRect.y + this.boundingRect.height / 2,
fill: this.axisThemeConfig.titleColor,
fontSize: this.axisConfig.titleFontSize,
rotation: 270,
verticalPos: 'top',
horizontalPos: 'center',
},
],
});
}
return drawableElement;
}
private getDrawableElementsForBottomAxis(): DrawableElem[] {
const drawableElement: DrawableElem[] = [];
if (this.showAxisLine) {
const y = this.boundingRect.y + this.axisConfig.axisLineWidth / 2;
drawableElement.push({
type: 'path',
groupTexts: ['bottom-axis', 'axis-line'],
data: [
{
path: `M ${this.boundingRect.x},${y} L ${
this.boundingRect.x + this.boundingRect.width
},${y}`,
strokeFill: this.axisThemeConfig.axisLineColor,
strokeWidth: this.axisConfig.axisLineWidth,
},
],
});
}
if (this.showLabel) {
drawableElement.push({
type: 'text',
groupTexts: ['bottom-axis', 'label'],
data: this.getTickValues().map((tick) => ({
text: tick.toString(),
x: this.getScaleValue(tick),
y:
this.boundingRect.y +
this.axisConfig.labelPadding +
(this.showTick ? this.axisConfig.tickLength : 0) +
(this.showAxisLine ? this.axisConfig.axisLineWidth : 0),
fill: this.axisThemeConfig.labelColor,
fontSize: this.axisConfig.labelFontSize,
rotation: 0,
verticalPos: 'top',
horizontalPos: 'center',
})),
});
}
if (this.showTick) {
const y = this.boundingRect.y + (this.showAxisLine ? this.axisConfig.axisLineWidth : 0);
drawableElement.push({
type: 'path',
groupTexts: ['bottom-axis', 'ticks'],
data: this.getTickValues().map((tick) => ({
path: `M ${this.getScaleValue(tick)},${y} L ${this.getScaleValue(tick)},${
y + this.axisConfig.tickLength
}`,
strokeFill: this.axisThemeConfig.tickColor,
strokeWidth: this.axisConfig.tickWidth,
})),
});
}
if (this.showTitle) {
drawableElement.push({
type: 'text',
groupTexts: ['bottom-axis', 'title'],
data: [
{
text: this.title,
x: this.range[0] + (this.range[1] - this.range[0]) / 2,
y:
this.boundingRect.y +
this.boundingRect.height -
this.axisConfig.titlePadding -
this.titleTextHeight,
fill: this.axisThemeConfig.titleColor,
fontSize: this.axisConfig.titleFontSize,
rotation: 0,
verticalPos: 'top',
horizontalPos: 'center',
},
],
});
}
return drawableElement;
}
private getDrawableElementsForTopAxis(): DrawableElem[] {
const drawableElement: DrawableElem[] = [];
if (this.showAxisLine) {
const y = this.boundingRect.y + this.boundingRect.height - this.axisConfig.axisLineWidth / 2;
drawableElement.push({
type: 'path',
groupTexts: ['top-axis', 'axis-line'],
data: [
{
path: `M ${this.boundingRect.x},${y} L ${
this.boundingRect.x + this.boundingRect.width
},${y}`,
strokeFill: this.axisThemeConfig.axisLineColor,
strokeWidth: this.axisConfig.axisLineWidth,
},
],
});
}
if (this.showLabel) {
drawableElement.push({
type: 'text',
groupTexts: ['top-axis', 'label'],
data: this.getTickValues().map((tick) => ({
text: tick.toString(),
x: this.getScaleValue(tick),
y:
this.boundingRect.y +
(this.showTitle ? this.titleTextHeight + this.axisConfig.titlePadding * 2 : 0) +
this.axisConfig.labelPadding,
fill: this.axisThemeConfig.labelColor,
fontSize: this.axisConfig.labelFontSize,
rotation: 0,
verticalPos: 'top',
horizontalPos: 'center',
})),
});
}
if (this.showTick) {
const y = this.boundingRect.y;
drawableElement.push({
type: 'path',
groupTexts: ['top-axis', 'ticks'],
data: this.getTickValues().map((tick) => ({
path: `M ${this.getScaleValue(tick)},${
y + this.boundingRect.height - (this.showAxisLine ? this.axisConfig.axisLineWidth : 0)
} L ${this.getScaleValue(tick)},${
y +
this.boundingRect.height -
this.axisConfig.tickLength -
(this.showAxisLine ? this.axisConfig.axisLineWidth : 0)
}`,
strokeFill: this.axisThemeConfig.tickColor,
strokeWidth: this.axisConfig.tickWidth,
})),
});
}
if (this.showTitle) {
drawableElement.push({
type: 'text',
groupTexts: ['top-axis', 'title'],
data: [
{
text: this.title,
x: this.boundingRect.x + this.boundingRect.width / 2,
y: this.boundingRect.y + this.axisConfig.titlePadding,
fill: this.axisThemeConfig.titleColor,
fontSize: this.axisConfig.titleFontSize,
rotation: 0,
verticalPos: 'top',
horizontalPos: 'center',
},
],
});
}
return drawableElement;
}
getDrawableElements(): DrawableElem[] {
if (this.axisPosition === 'left') {
return this.getDrawableElementsForLeftAxis();
}
if (this.axisPosition === 'right') {
throw Error('Drawing of right axis is not implemented');
}
if (this.axisPosition === 'bottom') {
return this.getDrawableElementsForBottomAxis();
}
if (this.axisPosition === 'top') {
return this.getDrawableElementsForTopAxis();
}
return [];
}
}

View File

@ -0,0 +1,47 @@
import type { Group } from '../../../../../diagram-api/types.js';
import type {
AxisDataType,
ChartComponent,
XYChartAxisConfig,
XYChartAxisThemeConfig,
} from '../../interfaces.js';
import { isBandAxisData } from '../../interfaces.js';
import { TextDimensionCalculatorWithFont } from '../../textDimensionCalculator.js';
import { BandAxis } from './bandAxis.js';
import { LinearAxis } from './linearAxis.js';
export type AxisPosition = 'left' | 'right' | 'top' | 'bottom';
export interface Axis extends ChartComponent {
getScaleValue(value: string | number): number;
setAxisPosition(axisPosition: AxisPosition): void;
getAxisOuterPadding(): number;
getTickDistance(): number;
recalculateOuterPaddingToDrawBar(): void;
setRange(range: [number, number]): void;
}
export function getAxis(
data: AxisDataType,
axisConfig: XYChartAxisConfig,
axisThemeConfig: XYChartAxisThemeConfig,
tmpSVGGroup: Group
): Axis {
const textDimansionCalculator = new TextDimensionCalculatorWithFont(tmpSVGGroup);
if (isBandAxisData(data)) {
return new BandAxis(
axisConfig,
axisThemeConfig,
data.categories,
data.title,
textDimansionCalculator
);
}
return new LinearAxis(
axisConfig,
axisThemeConfig,
[data.min, data.max],
data.title,
textDimansionCalculator
);
}

View File

@ -0,0 +1,38 @@
import type { ScaleLinear } from 'd3';
import { scaleLinear } from 'd3';
import type { TextDimensionCalculator } from '../../textDimensionCalculator.js';
import { BaseAxis } from './baseAxis.js';
import type { XYChartAxisThemeConfig, XYChartAxisConfig } from '../../interfaces.js';
export class LinearAxis extends BaseAxis {
private scale: ScaleLinear<number, number>;
private domain: [number, number];
constructor(
axisConfig: XYChartAxisConfig,
axisThemeConfig: XYChartAxisThemeConfig,
domain: [number, number],
title: string,
textDimensionCalculator: TextDimensionCalculator
) {
super(axisConfig, title, textDimensionCalculator, axisThemeConfig);
this.domain = domain;
this.scale = scaleLinear().domain(this.domain).range(this.getRange());
}
getTickValues(): (string | number)[] {
return this.scale.ticks();
}
recalculateScale(): void {
const domain = [...this.domain]; // copy the array so if reverse is called two times it should not cancel the reverse effect
if (this.axisPosition === 'left') {
domain.reverse(); // since y-axis in svg start from top
}
this.scale = scaleLinear().domain(domain).range(this.getRange());
}
getScaleValue(value: number): number {
return this.scale(value);
}
}

Some files were not shown because too many files have changed in this diff Show More