Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(flowchart): support linkStyle - to style the previous line defined #4483

Draft
wants to merge 19 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions cypress/integration/rendering/flowchart.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ graph TD
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});

it('66: apply class called default on node called default', () => {
imgSnapshotTest(
`
Expand All @@ -914,4 +915,21 @@ graph TD
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});

it('68: should render a flowchart with linkStyle - no numbers', () => {
imgSnapshotTest(
`flowchart TD
Driving --> TrafficLight{ Orange? }
TrafficLight --> |No| Go{Green?}
linkStyle - stroke:blue;
TrafficLight ---> |Yes| SpeedUp
linkStyle - stroke:orange;
Go --> |Yes| JustCruise
linkStyle - stroke:green;
Go --> |No| Breaks[Hit the brakes]
linkStyle - stroke:red;
`,
{ flowchart: { htmlLabels: true } }
);
});
});
18 changes: 18 additions & 0 deletions demos/flowchart.html
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,24 @@ <h3>flowchart</h3>

<h1 id="link-clicked">Anchor for "link-clicked" test</h1>

<pre class="mermaid">
---
title: Traffic light
---
flowchart TD
Driving --> TrafficLight{ Orange? }
TrafficLight --> |No| Go{Green?}
linkStyle - stroke:blue;
TrafficLight ---> |Yes| SpeedUp
linkStyle - stroke:orange;
Go --> |Yes| JustCruise
linkStyle - stroke:green;
Go --> |No| Breaks[Hit the brakes]
linkStyle - stroke:red;
</pre
>
<hr />

<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
Expand Down
22 changes: 18 additions & 4 deletions docs/syntax/flowchart.md
Original file line number Diff line number Diff line change
Expand Up @@ -976,8 +976,7 @@ flowchart LR

### Styling links

It is possible to style links. For instance, you might want to style a link that is going backwards in the flow. As links
have no ids in the same way as nodes, some other way of deciding what style the links should be attached to is required.
It is possible to style links. For instance, you might want to style a link that is going backwards in the flow. As links have no ids in the same way as nodes, some other way of deciding what style the links should be attached to is required.
Instead of ids, the order number of when the link was defined in the graph is used, or use default to apply to all links.
In the example below the style defined in the linkStyle statement will belong to the fourth link in the graph:

Expand All @@ -987,6 +986,13 @@ It is also possible to add style to multiple links in a single statement, by sep

linkStyle 1,2,7 color:blue;

From vMERMAID_RELEASE_VERSION+, linkStyle can be attached to the previous connection by defining the style after the link definition. The link number can be replaced with a `-`, removing the need to remember link numbers.

A --> B
linkStyle - stroke:red;
B --> C
linkStyle - stroke:green;

### Styling line curves

It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
Expand All @@ -995,8 +1001,12 @@ Available curve styles include `basis`, `bumpX`, `bumpY`, `cardinal`, `catmullRo

In this example, a left-to-right graph uses the `stepBefore` curve style:

%%{ init: { 'flowchart': { 'curve': 'stepBefore' } } }%%
graph LR
```

%%{ init: { 'flowchart': { 'curve': 'stepBefore' } } }%%
graph LR

```

For a full list of available curves, including an explanation of custom curves, refer to
the [Shapes](https://github.com/d3/d3-shape/blob/main/README.md#curves) documentation in the
Expand Down Expand Up @@ -1200,3 +1210,7 @@ mermaid.flowchartConfig = {
width: 100%
}
```

### TODOs

- [ ] linkStyle interpolate feature docs missing
2 changes: 1 addition & 1 deletion packages/mermaid/src/diagram.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('diagram detection', () => {
"Parse error on line 2:
graph TD; A-->
--------------^
Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'EOF'"
Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'MINUS', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MULT', 'UNICODE_TEXT', got 'EOF'"
`);
await expect(getDiagramFromText('sequenceDiagram; A-->B')).rejects
.toThrowErrorMatchingInlineSnapshot(`
Expand Down
5 changes: 5 additions & 0 deletions packages/mermaid/src/diagrams/flowchart/flowDb.js
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,10 @@ const makeUniq = (sg, allSubgraphs) => {
return { nodes: res };
};

const lastEdgeIndex = () => {
return edges.length - 1;
};

export const lex = {
firstGraph,
};
Expand Down Expand Up @@ -822,4 +826,5 @@ export default {
makeUniq,
setDiagramTitle,
getDiagramTitle,
lastEdgeIndex,
};
96 changes: 76 additions & 20 deletions packages/mermaid/src/diagrams/flowchart/parser/flow-lines.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,75 +13,134 @@ describe('[Lines] when parsing', () => {
});

it('should handle line interpolation default definitions', function () {
const res = flow.parser.parse('graph TD\n' + 'A-->B\n' + 'linkStyle default interpolate basis');
flow.parser.parse('graph TD\n' + 'A-->B\n' + 'linkStyle default interpolate basis');

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges.defaultInterpolate).toBe('basis');
});

it('should handle line interpolation numbered definitions', function () {
const res = flow.parser.parse(
flow.parser.parse(
'graph TD\n' +
'A-->B\n' +
'A-->C\n' +
'linkStyle 0 interpolate basis\n' +
'linkStyle 1 interpolate cardinal'
);

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('cardinal');
});

it('should handle line interpolation multi-numbered definitions', function () {
const res = flow.parser.parse(
'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0,1 interpolate basis'
it('should handle line interpolation non-numbered definitions', function () {
flow.parser.parse(
'graph TD\n' +
'A-->B\n' +
'linkStyle - interpolate basis\n' +
'A-->C\n' +
'linkStyle - interpolate cardinal'
);

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('cardinal');
});

it('should handle line interpolation multi-numbered definitions', function () {
flow.parser.parse('graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0,1 interpolate basis');

const edges = flow.parser.yy.getEdges();

expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('basis');
});

it('should handle line interpolation default with style', function () {
const res = flow.parser.parse(
flow.parser.parse(
'graph TD\n' + 'A-->B\n' + 'linkStyle default interpolate basis stroke-width:1px;'
);

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges.defaultInterpolate).toBe('basis');
});

it('should handle line interpolation numbered with style', function () {
const res = flow.parser.parse(
flow.parser.parse(
'graph TD\n' +
'A-->B\n' +
'A-->C\n' +
'linkStyle 0 interpolate basis stroke-width:1px;\n' +
'linkStyle 1 interpolate cardinal stroke-width:1px;'
);

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('cardinal');
});

it('should handle line interpolation non-numbered with style', function () {
flow.parser.parse(
'graph TD\n' +
'A-->B\n' +
'linkStyle - interpolate basis stroke-width:1px;\n' +
nirname marked this conversation as resolved.
Show resolved Hide resolved
'A-->C\n' +
'linkStyle - interpolate cardinal stroke-width:3px;'
);

const edges = flow.parser.yy.getEdges();

expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('cardinal');
expect(edges[0].style).toMatchInlineSnapshot(`
[
"stroke-width:1px",
"fill:none",
]
`);
expect(edges[1].style).toMatchInlineSnapshot(`
[
"stroke-width:3px",
"fill:none",
]
`);
});

it('should handle non-numbered line style', function () {
flow.parser.parse(
'graph TD\n' +
'A-->B\n' +
'linkStyle - stroke-width:1px;\n' +
'A-->C\n' +
'linkStyle - stroke-width:3px;'
);

const edges = flow.parser.yy.getEdges();

expect(edges[0].style).toMatchInlineSnapshot(`
[
"stroke-width:1px",
"fill:none",
]
`);
expect(edges[1].style).toMatchInlineSnapshot(`
[
"stroke-width:3px",
"fill:none",
]
`);
});

it('should handle line interpolation multi-numbered with style', function () {
const res = flow.parser.parse(
flow.parser.parse(
'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0,1 interpolate basis stroke-width:1px;'
);

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges[0].interpolate).toBe('basis');
Expand All @@ -90,27 +149,24 @@ describe('[Lines] when parsing', () => {

describe('it should handle new line type notation', function () {
it('should handle regular lines', function () {
const res = flow.parser.parse('graph TD;A-->B;');
flow.parser.parse('graph TD;A-->B;');

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges[0].stroke).toBe('normal');
});

it('should handle dotted lines', function () {
const res = flow.parser.parse('graph TD;A-.->B;');
flow.parser.parse('graph TD;A-.->B;');

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges[0].stroke).toBe('dotted');
});

it('should handle dotted lines', function () {
const res = flow.parser.parse('graph TD;A==>B;');
flow.parser.parse('graph TD;A==>B;');

const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

expect(edges[0].stroke).toBe('thick');
Expand Down
Loading
Loading