Skip to content

Commit

Permalink
Merge pull request #5209 from Ronid1/feature/4051_sequence_diagram-mu…
Browse files Browse the repository at this point in the history
…lti-directional-arrow

Feature/4051 sequence diagram multi directional arrow
  • Loading branch information
sidharthv96 authored Jun 20, 2024
2 parents 3af4020 + 1a199d6 commit cda41a1
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 31 deletions.
15 changes: 14 additions & 1 deletion cypress/integration/rendering/sequencediagram.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference types="Cypress" />
// <reference types="Cypress" />

import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';

Expand Down Expand Up @@ -68,6 +68,19 @@ context('Sequence diagram', () => {
{ sequence: { actorFontFamily: 'courier' } }
);
});
it('should render bidirectional arrows', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice<<->>John: Hello John, how are you?
Alice<<-->>John: Hi Alice, I can hear you!
John<<->>Alice: This also works the other way
John<<-->>Alice: Yes
Alice->John: Test
John->>Alice: Still works
`
);
});
it('should handle different line breaks', () => {
imgSnapshotTest(
`
Expand Down
26 changes: 14 additions & 12 deletions docs/syntax/sequenceDiagram.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,18 +206,20 @@ Messages can be of two displayed either solid or with a dotted line.
[Actor][Arrow][Actor]:Message text
```

There are six types of arrows currently supported:

| Type | Description |
| ------ | ------------------------------------------------ |
| `->` | Solid line without arrow |
| `-->` | Dotted line without arrow |
| `->>` | Solid line with arrowhead |
| `-->>` | Dotted line with arrowhead |
| `-x` | Solid line with a cross at the end |
| `--x` | Dotted line with a cross at the end. |
| `-)` | Solid line with an open arrow at the end (async) |
| `--)` | Dotted line with a open arrow at the end (async) |
There are ten types of arrows currently supported:

| Type | Description |
| -------- | ------------------------------------------------------------------------ |
| `->` | Solid line without arrow |
| `-->` | Dotted line without arrow |
| `->>` | Solid line with arrowhead |
| `-->>` | Dotted line with arrowhead |
| `<<->>` | Solid line with bidirectional arrowheads (v\<MERMAID_RELEASE_VERSION>+) |
| `<<-->>` | Dotted line with bidirectional arrowheads (v\<MERMAID_RELEASE_VERSION>+) |
| `-x` | Solid line with a cross at the end |
| `--x` | Dotted line with a cross at the end. |
| `-)` | Solid line with an open arrow at the end (async) |
| `--)` | Dotted line with a open arrow at the end (async) |

## Activations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"actor" { this.begin('ID'); return 'participant_actor'; }
"create" return 'create';
"destroy" { this.begin('ID'); return 'destroy'; }
<ID>[^\->:\n,;]+?([\-]*[^\->:\n,;]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
<ID>[^\<->\->:\n,;]+?([\-]*[^\<->\->:\n,;]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
<ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; }
"loop" { this.begin('LINE'); return 'loop'; }
Expand Down Expand Up @@ -73,9 +73,11 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
"off" return 'off';
"," return ',';
";" return 'NEWLINE';
[^\+\->:\n,;]+((?!(\-x|\-\-x|\-\)|\-\-\)))[\-]*[^\+\->:\n,;]+)* { yytext = yytext.trim(); return 'ACTOR'; }
[^\+\<->\->:\n,;]+((?!(\-x|\-\-x|\-\)|\-\-\)))[\-]*[^\+\<->\->:\n,;]+)* { yytext = yytext.trim(); return 'ACTOR'; }
"->>" return 'SOLID_ARROW';
"<<->>" return 'BIDIRECTIONAL_SOLID_ARROW';
"-->>" return 'DOTTED_ARROW';
"<<-->>" return 'BIDIRECTIONAL_DOTTED_ARROW';
"->" return 'SOLID_OPEN_ARROW';
"-->" return 'DOTTED_OPEN_ARROW';
\-[x] return 'SOLID_CROSS';
Expand Down Expand Up @@ -310,7 +312,9 @@ signaltype
: SOLID_OPEN_ARROW { $$ = yy.LINETYPE.SOLID_OPEN; }
| DOTTED_OPEN_ARROW { $$ = yy.LINETYPE.DOTTED_OPEN; }
| SOLID_ARROW { $$ = yy.LINETYPE.SOLID; }
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
| DOTTED_ARROW { $$ = yy.LINETYPE.DOTTED; }
| BIDIRECTIONAL_DOTTED_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_DOTTED; }
| SOLID_CROSS { $$ = yy.LINETYPE.SOLID_CROSS; }
| DOTTED_CROSS { $$ = yy.LINETYPE.DOTTED_CROSS; }
| SOLID_POINT { $$ = yy.LINETYPE.SOLID_POINT; }
Expand Down
2 changes: 2 additions & 0 deletions packages/mermaid/src/diagrams/sequence/sequenceDb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ export const LINETYPE = {
BREAK_START: 30,
BREAK_END: 31,
PAR_OVER_START: 32,
BIDIRECTIONAL_SOLID: 33,
BIDIRECTIONAL_DOTTED: 34,
};

export const ARROWTYPE = {
Expand Down
30 changes: 30 additions & 0 deletions packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,36 @@ Alice->>Bob:Hello Bob, how are you?`;
expect(messages.length).toBe(1);
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
});
it('should handle bidirectional arrow messages', async () => {
const str = `
sequenceDiagram
Alice<<->>Bob:Hello Bob, how are you?`;

await mermaidAPI.parse(str);
const actors = diagram.db.getActors();
expect(actors.get('Alice').description).toBe('Alice');
expect(actors.get('Bob').description).toBe('Bob');

const messages = diagram.db.getMessages();

expect(messages.length).toBe(1);
expect(messages[0].type).toBe(diagram.db.LINETYPE.BIDIRECTIONAL_SOLID);
});
it('should handle bidirectional dotted arrow messages', async () => {
const str = `
sequenceDiagram
Alice<<-->>Bob:Hello Bob, how are you?`;

await mermaidAPI.parse(str);
const actors = diagram.db.getActors();
expect(actors.get('Alice').description).toBe('Alice');
expect(actors.get('Bob').description).toBe('Bob');

const messages = diagram.db.getMessages();

expect(messages.length).toBe(1);
expect(messages[0].type).toBe(diagram.db.LINETYPE.BIDIRECTIONAL_DOTTED);
});
it('should handle actor activation', async () => {
const str = `
sequenceDiagram
Expand Down
27 changes: 25 additions & 2 deletions packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,8 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
type === diagObj.db.LINETYPE.DOTTED ||
type === diagObj.db.LINETYPE.DOTTED_CROSS ||
type === diagObj.db.LINETYPE.DOTTED_POINT ||
type === diagObj.db.LINETYPE.DOTTED_OPEN
type === diagObj.db.LINETYPE.DOTTED_OPEN ||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED
) {
line.style('stroke-dasharray', '3, 3');
line.attr('class', 'messageLine1');
Expand All @@ -462,6 +463,13 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
if (type === diagObj.db.LINETYPE.SOLID || type === diagObj.db.LINETYPE.DOTTED) {
line.attr('marker-end', 'url(' + url + '#arrowhead)');
}
if (
type === diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID ||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED
) {
line.attr('marker-start', 'url(' + url + '#arrowhead)');
line.attr('marker-end', 'url(' + url + '#arrowhead)');
}
if (type === diagObj.db.LINETYPE.SOLID_POINT || type === diagObj.db.LINETYPE.DOTTED_POINT) {
line.attr('marker-end', 'url(' + url + '#filled-head)');
}
Expand Down Expand Up @@ -1036,6 +1044,8 @@ export const draw = async function (_text: string, id: string, _version: string,
diagObj.db.LINETYPE.DOTTED_CROSS,
diagObj.db.LINETYPE.SOLID_POINT,
diagObj.db.LINETYPE.DOTTED_POINT,
diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID,
diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED,
].includes(msg.type)
) {
sequenceIndex = sequenceIndex + sequenceIndexStep;
Expand Down Expand Up @@ -1416,14 +1426,16 @@ const buildMessageModel = function (msg, actors, diagObj) {
diagObj.db.LINETYPE.DOTTED_CROSS,
diagObj.db.LINETYPE.SOLID_POINT,
diagObj.db.LINETYPE.DOTTED_POINT,
diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID,
diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED,
].includes(msg.type)
) {
return {};
}
const [fromLeft, fromRight] = activationBounds(msg.from, actors);
const [toLeft, toRight] = activationBounds(msg.to, actors);
const isArrowToRight = fromLeft <= toLeft;
const startx = isArrowToRight ? fromRight : fromLeft;
let startx = isArrowToRight ? fromRight : fromLeft;
let stopx = isArrowToRight ? toLeft : toRight;

// As the line width is considered, the left and right values will be off by 2.
Expand Down Expand Up @@ -1462,6 +1474,17 @@ const buildMessageModel = function (msg, actors, diagObj) {
if (![diagObj.db.LINETYPE.SOLID_OPEN, diagObj.db.LINETYPE.DOTTED_OPEN].includes(msg.type)) {
stopx += adjustValue(3);
}

/**
* Shorten start position of bidirectional arrow to accommodate for second arrowhead
*/
if (
[diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID, diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED].includes(
msg.type
)
) {
startx -= adjustValue(3);
}
}

const allBounds = [fromLeft, fromRight, toLeft, toRight];
Expand Down
2 changes: 1 addition & 1 deletion packages/mermaid/src/diagrams/sequence/svgDraw.js
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ export const insertArrowHead = function (elem) {
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 12)
.attr('markerHeight', 12)
.attr('orient', 'auto')
.attr('orient', 'auto-start-reverse')
.append('path')
.attr('d', 'M -1 0 L 10 5 L 0 10 z'); // this is actual shape for arrowhead
};
Expand Down
26 changes: 14 additions & 12 deletions packages/mermaid/src/docs/syntax/sequenceDiagram.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,20 @@ Messages can be of two displayed either solid or with a dotted line.
[Actor][Arrow][Actor]:Message text
```

There are six types of arrows currently supported:

| Type | Description |
| ------ | ------------------------------------------------ |
| `->` | Solid line without arrow |
| `-->` | Dotted line without arrow |
| `->>` | Solid line with arrowhead |
| `-->>` | Dotted line with arrowhead |
| `-x` | Solid line with a cross at the end |
| `--x` | Dotted line with a cross at the end. |
| `-)` | Solid line with an open arrow at the end (async) |
| `--)` | Dotted line with a open arrow at the end (async) |
There are ten types of arrows currently supported:

| Type | Description |
| -------- | ----------------------------------------------------------------------- |
| `->` | Solid line without arrow |
| `-->` | Dotted line without arrow |
| `->>` | Solid line with arrowhead |
| `-->>` | Dotted line with arrowhead |
| `<<->>` | Solid line with bidirectional arrowheads (v<MERMAID_RELEASE_VERSION>+) |
| `<<-->>` | Dotted line with bidirectional arrowheads (v<MERMAID_RELEASE_VERSION>+) |
| `-x` | Solid line with a cross at the end |
| `--x` | Dotted line with a cross at the end. |
| `-)` | Solid line with an open arrow at the end (async) |
| `--)` | Dotted line with a open arrow at the end (async) |

## Activations

Expand Down
2 changes: 1 addition & 1 deletion packages/mermaid/src/mermaid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ describe('when using mermaid and ', () => {
[Error: Parse error on line 2:
...equenceDiagramAlice:->Bob: Hello Bob, h...
----------------------^
Expecting 'SOLID_OPEN_ARROW', 'DOTTED_OPEN_ARROW', 'SOLID_ARROW', 'DOTTED_ARROW', 'SOLID_CROSS', 'DOTTED_CROSS', 'SOLID_POINT', 'DOTTED_POINT', got 'TXT']
Expecting 'SOLID_OPEN_ARROW', 'DOTTED_OPEN_ARROW', 'SOLID_ARROW', 'BIDIRECTIONAL_SOLID_ARROW', 'DOTTED_ARROW', 'BIDIRECTIONAL_DOTTED_ARROW', 'SOLID_CROSS', 'DOTTED_CROSS', 'SOLID_POINT', 'DOTTED_POINT', got 'TXT']
`);
});

Expand Down

0 comments on commit cda41a1

Please sign in to comment.