mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-11 18:19:42 +02:00
Merge branch 'develop' into 5435/inconsistent-math-rendering
This commit is contained in:
@@ -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:
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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.
|
||||||
|
|
||||||
|
@@ -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';
|
||||||
|
@@ -262,7 +262,7 @@ const getBlocksFlat = () => {
|
|||||||
return [...Object.values(blockDatabase)];
|
return [...Object.values(blockDatabase)];
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Returns the the hierarchy of blocks
|
* Returns the hierarchy of blocks
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getBlocks = () => {
|
const getBlocks = () => {
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;');
|
||||||
|
|
||||||
|
@@ -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}]}
|
||||||
|
@@ -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 = {
|
||||||
|
@@ -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 = `
|
||||||
|
@@ -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[message.from.actor];
|
const actorRect = actors[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);
|
||||||
@@ -1545,14 +1545,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[msg.from ? msg.from.actor : msg.to.actor];
|
const actorRect = actors[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);
|
||||||
@@ -1562,7 +1562,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;
|
||||||
|
@@ -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
|
||||||
| {
|
| {
|
||||||
|
@@ -145,7 +145,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
|
||||||
*/
|
*/
|
||||||
|
@@ -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
2115
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user