mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-09 10:36:43 +02:00
#945 Some bug fixes and draft docs
This commit is contained in:
@@ -13,6 +13,17 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
|
it('should render a single state with short descr', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
stateDiagram
|
||||||
|
state "A long long name" as long1
|
||||||
|
state "A" as longlonglongid
|
||||||
|
`,
|
||||||
|
{ logLevel: 0 }
|
||||||
|
);
|
||||||
|
cy.get('svg');
|
||||||
|
});
|
||||||
it('should render a state with a note', () => {
|
it('should render a state with a note', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
@@ -145,7 +156,7 @@ describe('State diagram', () => {
|
|||||||
Off --> On : Turn on
|
Off --> On : Turn on
|
||||||
}
|
}
|
||||||
|
|
||||||
TV--> Console : KarlMartin
|
TV--> Console
|
||||||
|
|
||||||
state Console {
|
state Console {
|
||||||
[*] --> Off2: Off to start with
|
[*] --> Off2: Off to start with
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
- Diagrams
|
- Diagrams
|
||||||
|
|
||||||
- [Flowchart](flowchart.md)
|
- [Flowchart](flowchart.md)
|
||||||
|
- [State diagram](stateDiagram.md)
|
||||||
- [Sequence diagram](sequenceDiagram.md)
|
- [Sequence diagram](sequenceDiagram.md)
|
||||||
- [Gantt](gantt.md)
|
- [Gantt](gantt.md)
|
||||||
- [Pie Chart](pie.md)
|
- [Pie Chart](pie.md)
|
||||||
|
@@ -7,8 +7,8 @@
|
|||||||
<meta name="description" content="Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.">
|
<meta name="description" content="Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.">
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
|
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
|
||||||
<script src="//cdn.jsdelivr.net/npm/mermaid@8.3.1/dist/mermaid.min.js"></script>
|
<!-- <script src="//cdn.jsdelivr.net/npm/mermaid@8.3.1/dist/mermaid.min.js"></script> -->
|
||||||
<!-- <script src="//localhost:9000/mermaidq.js"></script> -->
|
<script src="//localhost:9000/mermaid.js"></script>
|
||||||
<style>
|
<style>
|
||||||
.markdown-section {
|
.markdown-section {
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
|
267
docs/stateDiagram.md
Executable file
267
docs/stateDiagram.md
Executable file
@@ -0,0 +1,267 @@
|
|||||||
|
# State diagrams
|
||||||
|
|
||||||
|
> A state diagram is a type of diagram used in computer science and related fields to describe the behavior of systems. State diagrams require that the system described is composed of a finite number of states; sometimes, this is indeed the case, while at other times this is a reasonable abstraction.
|
||||||
|
|
||||||
|
Mermaid can render state diagrams with a syntax derived from plantUml, this to make the diagrams easier to use.
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
[*] --> Still
|
||||||
|
Still --> [*]
|
||||||
|
|
||||||
|
Still --> Moving
|
||||||
|
Moving --> Still
|
||||||
|
Moving --> Crash
|
||||||
|
Crash --> [*]
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
[*] --> Still
|
||||||
|
Still --> [*]
|
||||||
|
|
||||||
|
Still --> Moving
|
||||||
|
Moving --> Still
|
||||||
|
Moving --> Crash
|
||||||
|
Crash --> [*]
|
||||||
|
```
|
||||||
|
|
||||||
|
## States
|
||||||
|
|
||||||
|
A state can be declares in multiple ways. The simplest way is to define a state id as a description.
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
s1
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
s1
|
||||||
|
```
|
||||||
|
|
||||||
|
Another way is by using the state key word as per below:
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
state "This ia state decription" as s2
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
state "This ia state decription" as s2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transitions
|
||||||
|
|
||||||
|
Transitions are path/edges when one state passes into another. This is represented using text arrow, "-->".
|
||||||
|
|
||||||
|
Transitions from and to states that are not defined implicitly defines these states.
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
s1 --> s2
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
s1 --> s2
|
||||||
|
```
|
||||||
|
|
||||||
|
It is possieblt to add text to a transition.
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
s1 --> s2: A transition
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
s1 --> s2: A transition
|
||||||
|
```
|
||||||
|
|
||||||
|
There are two special states indicating the start of the diagram and the stop of the diagram. These are written with the [*] syntax.
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
[*] --> s1
|
||||||
|
s1 --> [*]
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
[*] --> s1
|
||||||
|
s1 --> [*]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Composit states
|
||||||
|
|
||||||
|
In a real world use of state diagrams you often end up with diagrams that are multi-dimensional as one state can have several internal states.
|
||||||
|
|
||||||
|
In order to define a composit state you need to use the state keyword as per below:
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
[*] --> First
|
||||||
|
state First {
|
||||||
|
[*] --> second
|
||||||
|
second --> [*]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
[*] --> First
|
||||||
|
state First {
|
||||||
|
[*] --> second
|
||||||
|
second --> [*]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can do this in several layers:
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
[*] --> First
|
||||||
|
First --> Second
|
||||||
|
First --> Third
|
||||||
|
|
||||||
|
state First {
|
||||||
|
[*] --> fir
|
||||||
|
fir --> [*]
|
||||||
|
}
|
||||||
|
state Second {
|
||||||
|
[*] --> sec
|
||||||
|
sec --> [*]
|
||||||
|
}
|
||||||
|
state Third {
|
||||||
|
[*] --> thi
|
||||||
|
thi --> [*]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
[*] --> First
|
||||||
|
First --> Second
|
||||||
|
First --> Third
|
||||||
|
|
||||||
|
state First {
|
||||||
|
[*] --> fir
|
||||||
|
fir --> [*]
|
||||||
|
}
|
||||||
|
state Second {
|
||||||
|
[*] --> sec
|
||||||
|
sec --> [*]
|
||||||
|
}
|
||||||
|
state Third {
|
||||||
|
[*] --> thi
|
||||||
|
thi --> [*]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Forks
|
||||||
|
|
||||||
|
It is possible to specify a fork in the diagram using <<fork>> <<join>>.
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
state fork_state <<fork>>
|
||||||
|
[*] --> fork_state
|
||||||
|
fork_state --> State2
|
||||||
|
fork_state --> State3
|
||||||
|
|
||||||
|
state join_state <<join>>
|
||||||
|
State2 --> join_state
|
||||||
|
State3 --> join_state
|
||||||
|
join_state --> State4
|
||||||
|
State4 --> [*]
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
state fork_state <<fork>>
|
||||||
|
[*] --> fork_state
|
||||||
|
fork_state --> State2
|
||||||
|
fork_state --> State3
|
||||||
|
|
||||||
|
state join_state <<join>>
|
||||||
|
State2 --> join_state
|
||||||
|
State3 --> join_state
|
||||||
|
join_state --> State4
|
||||||
|
State4 --> [*]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Sometimes nothing says it better then a postit note. That is also the case in state diagrams.
|
||||||
|
|
||||||
|
Here you canb choose to put the onte to the right or to the left of a node.
|
||||||
|
|
||||||
|
```
|
||||||
|
stateDiagram
|
||||||
|
State1: The state with a note
|
||||||
|
note right of State1
|
||||||
|
Important information! You can write
|
||||||
|
notes.
|
||||||
|
end note
|
||||||
|
State1 --> State2
|
||||||
|
note left of State2 : This is the note to the left.
|
||||||
|
```
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
State1: The state with a note
|
||||||
|
note right of State1
|
||||||
|
Important information! You can write
|
||||||
|
notes.
|
||||||
|
end note
|
||||||
|
State1 --> State2
|
||||||
|
note left of State2 : This is the note to the left.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Concurrency
|
||||||
|
|
||||||
|
As in plantUml you can specify concurrency using the -- symbol.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
stateDiagram
|
||||||
|
[*] --> Active
|
||||||
|
|
||||||
|
state Active {
|
||||||
|
[*] --> NumLockOff
|
||||||
|
NumLockOff --> NumLockOn : EvNumLockPressed
|
||||||
|
NumLockOn --> NumLockOff : EvNumLockPressed
|
||||||
|
--
|
||||||
|
[*] --> CapsLockOff
|
||||||
|
CapsLockOff --> CapsLockOn : EvCapsLockPressed
|
||||||
|
CapsLockOn --> CapsLockOff : EvCapsLockPressed
|
||||||
|
--
|
||||||
|
[*] --> ScrollLockOff
|
||||||
|
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
|
||||||
|
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
Styling of the a sequence diagram is done by defining a number of css classes. During rendering these classes are extracted from the file located at src/themes/sequence.scss
|
||||||
|
|
||||||
|
### Classes used (TB Written)
|
||||||
|
|
||||||
|
Class | Description
|
||||||
|
--- | ---
|
||||||
|
Fakenote | Styles for the note box.
|
||||||
|
FakenoteText | Styles for the text on in the note boxes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Is it possible to adjust the margins etc for the stateDiagram ... TB written
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
mermaid.stateConfig = {
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Possible configuration params:
|
||||||
|
|
||||||
|
Param | Description | Default value
|
||||||
|
--- | --- | ---
|
||||||
|
TBS | Turns on/off the rendering of actors below the diagram as well as above it | false
|
||||||
|
|
@@ -112,7 +112,8 @@ line
|
|||||||
;
|
;
|
||||||
|
|
||||||
statement
|
statement
|
||||||
: idStatement DESCR { /*console.warn('got id and descr', $1, $2.trim());*/$$={ stmt: 'state', id: $1, type: 'default', description: $2.trim()};}
|
: idStatement { /*console.warn('got id and descr', $1);*/$$={ stmt: 'state', id: $1, type: 'default', description: ''};}
|
||||||
|
| idStatement DESCR { /*console.warn('got id and descr', $1, $2.trim());*/$$={ stmt: 'state', id: $1, type: 'default', description: $2.trim()};}
|
||||||
| idStatement '-->' idStatement
|
| idStatement '-->' idStatement
|
||||||
{
|
{
|
||||||
/*console.warn('got id', $1);yy.addRelation($1, $3);*/
|
/*console.warn('got id', $1);yy.addRelation($1, $3);*/
|
||||||
@@ -128,10 +129,11 @@ statement
|
|||||||
| COMPOSIT_STATE
|
| COMPOSIT_STATE
|
||||||
| COMPOSIT_STATE STRUCT_START document STRUCT_STOP
|
| COMPOSIT_STATE STRUCT_START document STRUCT_STOP
|
||||||
{
|
{
|
||||||
|
|
||||||
/* console.warn('Adding document for state without id ', $1);*/
|
/* console.warn('Adding document for state without id ', $1);*/
|
||||||
$$={ stmt: 'state', id: $1, type: 'default', description: '', doc: $3 }
|
$$={ stmt: 'state', id: $1, type: 'default', description: '', doc: $3 }
|
||||||
}
|
}
|
||||||
| STATE_DESCR AS ID { $$={id: $3, type: 'default', description: $1.trim()};}
|
| STATE_DESCR AS ID { $$={stmt: 'state', id: $3, type: 'default', description: $1.trim()};}
|
||||||
| STATE_DESCR AS ID STRUCT_START document STRUCT_STOP
|
| STATE_DESCR AS ID STRUCT_START document STRUCT_STOP
|
||||||
{
|
{
|
||||||
//console.warn('Adding document for state with id ', $3, $4); yy.addDocument($3);
|
//console.warn('Adding document for state with id ', $3, $4); yy.addDocument($3);
|
||||||
|
@@ -82,7 +82,8 @@ export const drawDescrState = (g, stateDef) => {
|
|||||||
.attr('class', 'state-title')
|
.attr('class', 'state-title')
|
||||||
.text(stateDef.id);
|
.text(stateDef.id);
|
||||||
|
|
||||||
const titleHeight = title.node().getBBox().height;
|
const titleBox = title.node().getBBox();
|
||||||
|
const titleHeight = titleBox.height;
|
||||||
|
|
||||||
const description = g
|
const description = g
|
||||||
.append('text') // text label for the x axis
|
.append('text') // text label for the x axis
|
||||||
@@ -104,13 +105,16 @@ export const drawDescrState = (g, stateDef) => {
|
|||||||
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2)
|
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2)
|
||||||
.attr('class', 'descr-divider');
|
.attr('class', 'descr-divider');
|
||||||
const descrBox = description.node().getBBox();
|
const descrBox = description.node().getBBox();
|
||||||
descrLine.attr('x2', descrBox.width + 3 * conf.padding);
|
console.warn(descrBox.width, titleBox.width);
|
||||||
|
const width = Math.max(descrBox.width, titleBox.width);
|
||||||
|
|
||||||
|
descrLine.attr('x2', width + 3 * conf.padding);
|
||||||
// const classBox = title.node().getBBox();
|
// const classBox = title.node().getBBox();
|
||||||
|
|
||||||
g.insert('rect', ':first-child')
|
g.insert('rect', ':first-child')
|
||||||
.attr('x', conf.padding)
|
.attr('x', conf.padding)
|
||||||
.attr('y', conf.padding)
|
.attr('y', conf.padding)
|
||||||
.attr('width', descrBox.width + 2 * conf.padding)
|
.attr('width', width + 2 * conf.padding)
|
||||||
.attr('height', descrBox.height + titleHeight + 2 * conf.padding)
|
.attr('height', descrBox.height + titleHeight + 2 * conf.padding)
|
||||||
.attr('rx', '5');
|
.attr('rx', '5');
|
||||||
|
|
||||||
|
@@ -73,6 +73,7 @@ export const draw = function(text, id) {
|
|||||||
compound: true,
|
compound: true,
|
||||||
// acyclicer: 'greedy',
|
// acyclicer: 'greedy',
|
||||||
rankdir: 'RL'
|
rankdir: 'RL'
|
||||||
|
// ranksep: '20'
|
||||||
});
|
});
|
||||||
|
|
||||||
// // Set an object for the graph label
|
// // Set an object for the graph label
|
||||||
@@ -91,9 +92,13 @@ export const draw = function(text, id) {
|
|||||||
|
|
||||||
const bounds = diagram.node().getBBox();
|
const bounds = diagram.node().getBBox();
|
||||||
|
|
||||||
diagram.attr('height', '100%');
|
// diagram.attr('height', '100%');
|
||||||
diagram.attr('width', '100%');
|
// diagram.attr('width', 'fit-content');
|
||||||
diagram.attr('viewBox', '0 0 ' + bounds.width * 2 + ' ' + (bounds.height + 50));
|
diagram.attr('style', 'width: fit-content;');
|
||||||
|
diagram.attr(
|
||||||
|
'viewBox',
|
||||||
|
'0 0 ' + (bounds.width + conf.padding * 2) + ' ' + (bounds.height + conf.padding * 2)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const getLabelWidth = text => {
|
const getLabelWidth = text => {
|
||||||
return text ? text.length * 5.02 : 1;
|
return text ? text.length * 5.02 : 1;
|
||||||
@@ -124,6 +129,7 @@ const renderDoc = (doc, diagram, parentId) => {
|
|||||||
// isCompound: true,
|
// isCompound: true,
|
||||||
// acyclicer: 'greedy',
|
// acyclicer: 'greedy',
|
||||||
// ranker: 'longest-path'
|
// ranker: 'longest-path'
|
||||||
|
ranksep: '20',
|
||||||
ranker: 'tight-tree'
|
ranker: 'tight-tree'
|
||||||
// ranker: 'network-simplex'
|
// ranker: 'network-simplex'
|
||||||
// isMultiGraph: false
|
// isMultiGraph: false
|
||||||
@@ -155,7 +161,7 @@ const renderDoc = (doc, diagram, parentId) => {
|
|||||||
node = renderDoc(stateDef.doc, sub, stateDef.id);
|
node = renderDoc(stateDef.doc, sub, stateDef.id);
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
// first = false;
|
||||||
sub = addIdAndBox(sub, stateDef);
|
sub = addIdAndBox(sub, stateDef);
|
||||||
let boxBounds = sub.node().getBBox();
|
let boxBounds = sub.node().getBBox();
|
||||||
node.width = boxBounds.width;
|
node.width = boxBounds.width;
|
||||||
|
Reference in New Issue
Block a user