Merge branch 'develop' into fix/maps

This commit is contained in:
Yash Singh
2024-05-02 15:34:50 -07:00
committed by GitHub
15 changed files with 1305 additions and 913 deletions

View File

@@ -160,7 +160,7 @@ In a real world use of state diagrams you often end up with diagrams that are mu
have several internal states. These are called composite states in this terminology. have several internal states. These are called composite states in this terminology.
In order to define a composite state you need to use the state keyword followed by an id and the body of the composite In order to define a composite state you need to use the state keyword followed by an id and the body of the composite
state between {}. See the example below: state between {}. You can name a composite state on a separate line just like a simple state. See the example below:
```mermaid-example ```mermaid-example
stateDiagram-v2 stateDiagram-v2
@@ -169,6 +169,14 @@ stateDiagram-v2
[*] --> second [*] --> second
second --> [*] second --> [*]
} }
[*] --> NamedComposite
NamedComposite: Another Composite
state NamedComposite {
[*] --> namedSimple
namedSimple --> [*]
namedSimple: Another simple
}
``` ```
```mermaid ```mermaid
@@ -178,6 +186,14 @@ stateDiagram-v2
[*] --> second [*] --> second
second --> [*] second --> [*]
} }
[*] --> NamedComposite
NamedComposite: Another Composite
state NamedComposite {
[*] --> namedSimple
namedSimple --> [*]
namedSimple: Another simple
}
``` ```
You can do this in several layers: You can do this in several layers:

View File

@@ -21,7 +21,7 @@ export const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: Mermaid
let sumOfDirectives: MermaidConfig = {}; let sumOfDirectives: MermaidConfig = {};
for (const d of _directives) { for (const d of _directives) {
sanitize(d); sanitize(d);
// Apply the data from the directive where the the overrides the themeVariables // Apply the data from the directive where the overrides the themeVariables
sumOfDirectives = assignWithDepth(sumOfDirectives, d); sumOfDirectives = assignWithDepth(sumOfDirectives, d);
} }

View File

@@ -45,7 +45,7 @@ flowchart
a --> C2 a --> C2
``` ```
To handle this case a special type of edge is inserted. The edge to/from the cluster is replaced with an edge to/from a node in the cluster which is tagged with toCluster/fromCluster. When rendering this edge the intersection between the edge and the border of the cluster is calculated making the edge start/stop there. In practice this renders like an an edge to/from the cluster. To handle this case a special type of edge is inserted. The edge to/from the cluster is replaced with an edge to/from a node in the cluster which is tagged with toCluster/fromCluster. When rendering this edge the intersection between the edge and the border of the cluster is calculated making the edge start/stop there. In practice this renders like an edge to/from the cluster.
In the diagram above the root diagram would be rendered with C1 whereas C2 would be rendered recursively. In the diagram above the root diagram would be rendered with C1 whereas C2 would be rendered recursively.

View File

@@ -1,5 +1,5 @@
/* /*
* Borrowed with love from from dagre-d3. Many thanks to cpettitt! * Borrowed with love from dagre-d3. Many thanks to cpettitt!
*/ */
import node from './intersect-node.js'; import node from './intersect-node.js';

View File

@@ -263,7 +263,7 @@ const getBlocksFlat = () => {
return [...blockDatabase.values()]; return [...blockDatabase.values()];
}; };
/** /**
* Returns the the hierarchy of blocks * Returns the hierarchy of blocks
* @returns * @returns
*/ */
const getBlocks = () => { const getBlocks = () => {

View File

@@ -141,7 +141,7 @@ describe('when parsing flowcharts', function () {
expect(edges[3].type).toBe('arrow_point'); expect(edges[3].type).toBe('arrow_point');
expect(edges[3].text).toBe(''); expect(edges[3].text).toBe('');
}); });
it('should handle chaining and multiple nodes in in link statement FVC ', function () { it('should handle chaining and multiple nodes in link statement FVC ', function () {
const res = flow.parser.parse(` const res = flow.parser.parse(`
graph TD graph TD
A --> B & B2 & C --> D2; A --> B & B2 & C --> D2;
@@ -181,7 +181,7 @@ describe('when parsing flowcharts', function () {
expect(edges[5].type).toBe('arrow_point'); expect(edges[5].type).toBe('arrow_point');
expect(edges[5].text).toBe(''); expect(edges[5].text).toBe('');
}); });
it('should handle chaining and multiple nodes in in link statement with extra info in statements', function () { it('should handle chaining and multiple nodes in link statement with extra info in statements', function () {
const res = flow.parser.parse(` const res = flow.parser.parse(`
graph TD graph TD
A[ h ] -- hello --> B[" test "]:::exClass & C --> D; A[ h ] -- hello --> B[" test "]:::exClass & C --> D;

View File

@@ -64,7 +64,7 @@ describe('parsing a flow chart', function () {
expect(edges[0].end).toBe('monograph'); expect(edges[0].end).toBe('monograph');
}); });
describe('special characters should be be handled.', function () { describe('special characters should be handled.', function () {
const charTest = function (char, result) { const charTest = function (char, result) {
const res = flow.parser.parse('graph TD;A(' + char + ')-->B;'); const res = flow.parser.parse('graph TD;A(' + char + ')-->B;');

View File

@@ -3,7 +3,7 @@
* (c) 2014-2015 Knut Sveidqvist * (c) 2014-2015 Knut Sveidqvist
* MIT license. * MIT license.
* *
* Based on js sequence diagrams jison grammr * Based on js sequence diagrams jison grammar
* https://bramp.github.io/js-sequence-diagrams/ * https://bramp.github.io/js-sequence-diagrams/
* (c) 2012-2013 Andrew Brampton (bramp.net) * (c) 2012-2013 Andrew Brampton (bramp.net)
* Simplified BSD license. * Simplified BSD license.
@@ -138,8 +138,8 @@ statement
| autonumber NUM 'NEWLINE' { $$ = {type:'sequenceIndex',sequenceIndex: Number($2), sequenceIndexStep:1, sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER};} | autonumber NUM 'NEWLINE' { $$ = {type:'sequenceIndex',sequenceIndex: Number($2), sequenceIndexStep:1, sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER};}
| autonumber off 'NEWLINE' { $$ = {type:'sequenceIndex', sequenceVisible:false, signalType:yy.LINETYPE.AUTONUMBER};} | autonumber off 'NEWLINE' { $$ = {type:'sequenceIndex', sequenceVisible:false, signalType:yy.LINETYPE.AUTONUMBER};}
| autonumber 'NEWLINE' {$$ = {type:'sequenceIndex', sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER}; } | autonumber 'NEWLINE' {$$ = {type:'sequenceIndex', sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER}; }
| 'activate' actor 'NEWLINE' {$$={type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $2};} | 'activate' actor 'NEWLINE' {$$={type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $2.actor};}
| 'deactivate' actor 'NEWLINE' {$$={type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $2};} | 'deactivate' actor 'NEWLINE' {$$={type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $2.actor};}
| note_statement 'NEWLINE' | note_statement 'NEWLINE'
| links_statement 'NEWLINE' | links_statement 'NEWLINE'
| link_statement 'NEWLINE' | link_statement 'NEWLINE'
@@ -288,11 +288,11 @@ placement
signal signal
: actor signaltype '+' actor text2 : actor signaltype '+' actor text2
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5, activate: true}, { $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5, activate: true},
{type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $4} {type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $4.actor}
]} ]}
| actor signaltype '-' actor text2 | actor signaltype '-' actor text2
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5}, { $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5},
{type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $1} {type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $1.actor}
]} ]}
| actor signaltype actor text2 | actor signaltype actor text2
{ $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]} { $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]}

View File

@@ -115,17 +115,16 @@ const activationCount = (part: string) => {
if (!part) { if (!part) {
return 0; return 0;
} }
for (i = 0; i < state.records.messages.length; i++) { for (i = 0; i < state.records.messages.length; i++) {
if ( if (
state.records.messages[i].type === LINETYPE.ACTIVE_START && state.records.messages[i].type === LINETYPE.ACTIVE_START &&
state.records.messages[i].from?.actor === part state.records.messages[i].from === part
) { ) {
count++; count++;
} }
if ( if (
state.records.messages[i].type === LINETYPE.ACTIVE_END && state.records.messages[i].type === LINETYPE.ACTIVE_END &&
state.records.messages[i].from?.actor === part state.records.messages[i].from === part
) { ) {
count--; count--;
} }
@@ -156,12 +155,10 @@ export const addSignal = function (
activate: boolean = false activate: boolean = false
) { ) {
if (messageType === LINETYPE.ACTIVE_END) { if (messageType === LINETYPE.ACTIVE_END) {
const cnt = activationCount(idFrom?.actor || ''); const cnt = activationCount(idFrom || '');
if (cnt < 1) { if (cnt < 1) {
// Bail out as there is an activation signal from an inactive participant // Bail out as there is an activation signal from an inactive participant
const error = new Error( const error = new Error('Trying to inactivate an inactive participant (' + idFrom + ')');
'Trying to inactivate an inactive participant (' + idFrom?.actor + ')'
);
// @ts-ignore: we are passing hash param to the error object, however we should define our own custom error class to make it type safe // @ts-ignore: we are passing hash param to the error object, however we should define our own custom error class to make it type safe
error.hash = { error.hash = {

View File

@@ -534,10 +534,10 @@ deactivate Bob`;
expect(messages.length).toBe(4); expect(messages.length).toBe(4);
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START);
expect(messages[1].from.actor).toBe('Bob'); expect(messages[1].from).toBe('Bob');
expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED);
expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END);
expect(messages[3].from.actor).toBe('Bob'); expect(messages[3].from).toBe('Bob');
}); });
it('should handle actor one line notation activation', async () => { it('should handle actor one line notation activation', async () => {
const str = ` const str = `
@@ -556,10 +556,10 @@ deactivate Bob`;
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
expect(messages[0].activate).toBeTruthy(); expect(messages[0].activate).toBeTruthy();
expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START);
expect(messages[1].from.actor).toBe('Bob'); expect(messages[1].from).toBe('Bob');
expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED);
expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END);
expect(messages[3].from.actor).toBe('Bob'); expect(messages[3].from).toBe('Bob');
}); });
it('should handle stacked activations', async () => { it('should handle stacked activations', async () => {
const str = ` const str = `
@@ -579,14 +579,14 @@ deactivate Bob`;
expect(messages.length).toBe(8); expect(messages.length).toBe(8);
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START);
expect(messages[1].from.actor).toBe('Bob'); expect(messages[1].from).toBe('Bob');
expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED);
expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_START);
expect(messages[3].from.actor).toBe('Carol'); expect(messages[3].from).toBe('Carol');
expect(messages[5].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[5].type).toBe(diagram.db.LINETYPE.ACTIVE_END);
expect(messages[5].from.actor).toBe('Bob'); expect(messages[5].from).toBe('Bob');
expect(messages[7].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[7].type).toBe(diagram.db.LINETYPE.ACTIVE_END);
expect(messages[7].from.actor).toBe('Carol'); expect(messages[7].from).toBe('Carol');
}); });
it('should handle fail parsing when activating an inactive participant', async () => { it('should handle fail parsing when activating an inactive participant', async () => {
const str = ` const str = `

View File

@@ -144,15 +144,15 @@ export const bounds = {
this.updateBounds(_startx, _starty, _stopx, _stopy); this.updateBounds(_startx, _starty, _stopx, _stopy);
}, },
newActivation: function (message, diagram, actors) { newActivation: function (message, diagram, actors) {
const actorRect = actors.get(message.from.actor); const actorRect = actors.get(message.from);
const stackedSize = actorActivations(message.from.actor).length || 0; const stackedSize = actorActivations(message.from).length || 0;
const x = actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2; const x = actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
this.activations.push({ this.activations.push({
startx: x, startx: x,
starty: this.verticalPos + 2, starty: this.verticalPos + 2,
stopx: x + conf.activationWidth, stopx: x + conf.activationWidth,
stopy: undefined, stopy: undefined,
actor: message.from.actor, actor: message.from,
anchored: svgDraw.anchorElement(diagram), anchored: svgDraw.anchorElement(diagram),
}); });
}, },
@@ -162,7 +162,7 @@ export const bounds = {
.map(function (activation) { .map(function (activation) {
return activation.actor; return activation.actor;
}) })
.lastIndexOf(message.from.actor); .lastIndexOf(message.from);
return this.activations.splice(lastActorActivationIdx, 1)[0]; return this.activations.splice(lastActorActivationIdx, 1)[0];
}, },
createLoop: function (title = { message: undefined, wrap: false, width: undefined }, fill) { createLoop: function (title = { message: undefined, wrap: false, width: undefined }, fill) {
@@ -836,7 +836,7 @@ export const draw = async function (_text: string, id: string, _version: string,
activationData, activationData,
verticalPos, verticalPos,
conf, conf,
actorActivations(msg.from.actor).length actorActivations(msg.from).length
); );
bounds.insert(activationData.startx, verticalPos - 10, activationData.stopx, verticalPos); bounds.insert(activationData.startx, verticalPos - 10, activationData.stopx, verticalPos);
@@ -1538,14 +1538,14 @@ const calculateLoopBounds = async function (messages, actors, _maxWidthPerActor,
break; break;
case diagObj.db.LINETYPE.ACTIVE_START: case diagObj.db.LINETYPE.ACTIVE_START:
{ {
const actorRect = actors.get(msg.from ? msg.from.actor : msg.to.actor); const actorRect = actors.get(msg.from ? msg.from : msg.to.actor);
const stackedSize = actorActivations(msg.from ? msg.from.actor : msg.to.actor).length; const stackedSize = actorActivations(msg.from ? msg.from : msg.to.actor).length;
const x = const x =
actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2; actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
const toAdd = { const toAdd = {
startx: x, startx: x,
stopx: x + conf.activationWidth, stopx: x + conf.activationWidth,
actor: msg.from.actor, actor: msg.from,
enabled: true, enabled: true,
}; };
bounds.activations.push(toAdd); bounds.activations.push(toAdd);
@@ -1555,7 +1555,7 @@ const calculateLoopBounds = async function (messages, actors, _maxWidthPerActor,
{ {
const lastActorActivationIdx = bounds.activations const lastActorActivationIdx = bounds.activations
.map((a) => a.actor) .map((a) => a.actor)
.lastIndexOf(msg.from.actor); .lastIndexOf(msg.from);
delete bounds.activations.splice(lastActorActivationIdx, 1)[0]; delete bounds.activations.splice(lastActorActivationIdx, 1)[0];
} }
break; break;

View File

@@ -20,8 +20,8 @@ export interface Actor {
} }
export interface Message { export interface Message {
from?: { actor: string }; from?: string;
to?: { actor: string }; to?: string;
message: message:
| string | string
| { | {

View File

@@ -146,7 +146,7 @@ const getRootDocV2 = () => {
* Ex: the section within a fork has its own statements, and incoming and outgoing statements * Ex: the section within a fork has its own statements, and incoming and outgoing statements
* refer to the fork as a whole (document). * refer to the fork as a whole (document).
* See the parser grammar: the definition of a document is a document then a 'line', where a line can be a statement. * See the parser grammar: the definition of a document is a document then a 'line', where a line can be a statement.
* This will push the statement into the the list of statements for the current document. * This will push the statement into the list of statements for the current document.
* *
* @param _doc * @param _doc
*/ */

View File

@@ -98,7 +98,7 @@ In a real world use of state diagrams you often end up with diagrams that are mu
have several internal states. These are called composite states in this terminology. have several internal states. These are called composite states in this terminology.
In order to define a composite state you need to use the state keyword followed by an id and the body of the composite In order to define a composite state you need to use the state keyword followed by an id and the body of the composite
state between \{\}. See the example below: state between \{\}. You can name a composite state on a separate line just like a simple state. See the example below:
```mermaid-example ```mermaid-example
stateDiagram-v2 stateDiagram-v2
@@ -107,6 +107,14 @@ stateDiagram-v2
[*] --> second [*] --> second
second --> [*] second --> [*]
} }
[*] --> NamedComposite
NamedComposite: Another Composite
state NamedComposite {
[*] --> namedSimple
namedSimple --> [*]
namedSimple: Another simple
}
``` ```
You can do this in several layers: You can do this in several layers:

2115
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff