mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Merge branch 'develop' into 5435/inconsistent-math-rendering
This commit is contained in:
commit
22bd26272d
@ -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.
|
||||
|
||||
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
|
||||
stateDiagram-v2
|
||||
@ -169,6 +169,14 @@ stateDiagram-v2
|
||||
[*] --> second
|
||||
second --> [*]
|
||||
}
|
||||
|
||||
[*] --> NamedComposite
|
||||
NamedComposite: Another Composite
|
||||
state NamedComposite {
|
||||
[*] --> namedSimple
|
||||
namedSimple --> [*]
|
||||
namedSimple: Another simple
|
||||
}
|
||||
```
|
||||
|
||||
```mermaid
|
||||
@ -178,6 +186,14 @@ stateDiagram-v2
|
||||
[*] --> second
|
||||
second --> [*]
|
||||
}
|
||||
|
||||
[*] --> NamedComposite
|
||||
NamedComposite: Another Composite
|
||||
state NamedComposite {
|
||||
[*] --> namedSimple
|
||||
namedSimple --> [*]
|
||||
namedSimple: Another simple
|
||||
}
|
||||
```
|
||||
|
||||
You can do this in several layers:
|
||||
|
@ -21,7 +21,7 @@ export const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: Mermaid
|
||||
let sumOfDirectives: MermaidConfig = {};
|
||||
for (const d of _directives) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ flowchart
|
||||
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.
|
||||
|
||||
|
@ -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';
|
||||
|
@ -262,7 +262,7 @@ const getBlocksFlat = () => {
|
||||
return [...Object.values(blockDatabase)];
|
||||
};
|
||||
/**
|
||||
* Returns the the hierarchy of blocks
|
||||
* Returns the hierarchy of blocks
|
||||
* @returns
|
||||
*/
|
||||
const getBlocks = () => {
|
||||
|
@ -141,7 +141,7 @@ describe('when parsing flowcharts', function () {
|
||||
expect(edges[3].type).toBe('arrow_point');
|
||||
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(`
|
||||
graph TD
|
||||
A --> B & B2 & C --> D2;
|
||||
@ -181,7 +181,7 @@ describe('when parsing flowcharts', function () {
|
||||
expect(edges[5].type).toBe('arrow_point');
|
||||
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(`
|
||||
graph TD
|
||||
A[ h ] -- hello --> B[" test "]:::exClass & C --> D;
|
||||
|
@ -64,7 +64,7 @@ describe('parsing a flow chart', function () {
|
||||
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 res = flow.parser.parse('graph TD;A(' + char + ')-->B;');
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* (c) 2014-2015 Knut Sveidqvist
|
||||
* MIT license.
|
||||
*
|
||||
* Based on js sequence diagrams jison grammr
|
||||
* Based on js sequence diagrams jison grammar
|
||||
* https://bramp.github.io/js-sequence-diagrams/
|
||||
* (c) 2012-2013 Andrew Brampton (bramp.net)
|
||||
* 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 off 'NEWLINE' { $$ = {type:'sequenceIndex', sequenceVisible:false, 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};}
|
||||
| 'deactivate' actor 'NEWLINE' {$$={type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, 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.actor};}
|
||||
| note_statement 'NEWLINE'
|
||||
| links_statement 'NEWLINE'
|
||||
| link_statement 'NEWLINE'
|
||||
@ -288,11 +288,11 @@ placement
|
||||
signal
|
||||
: actor signaltype '+' actor text2
|
||||
{ $$ = [$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
|
||||
{ $$ = [$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
|
||||
{ $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]}
|
||||
|
@ -115,17 +115,16 @@ const activationCount = (part: string) => {
|
||||
if (!part) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < state.records.messages.length; i++) {
|
||||
if (
|
||||
state.records.messages[i].type === LINETYPE.ACTIVE_START &&
|
||||
state.records.messages[i].from?.actor === part
|
||||
state.records.messages[i].from === part
|
||||
) {
|
||||
count++;
|
||||
}
|
||||
if (
|
||||
state.records.messages[i].type === LINETYPE.ACTIVE_END &&
|
||||
state.records.messages[i].from?.actor === part
|
||||
state.records.messages[i].from === part
|
||||
) {
|
||||
count--;
|
||||
}
|
||||
@ -156,12 +155,10 @@ export const addSignal = function (
|
||||
activate: boolean = false
|
||||
) {
|
||||
if (messageType === LINETYPE.ACTIVE_END) {
|
||||
const cnt = activationCount(idFrom?.actor || '');
|
||||
const cnt = activationCount(idFrom || '');
|
||||
if (cnt < 1) {
|
||||
// Bail out as there is an activation signal from an inactive participant
|
||||
const error = new Error(
|
||||
'Trying to inactivate an inactive participant (' + idFrom?.actor + ')'
|
||||
);
|
||||
const error = new Error('Trying to inactivate an inactive participant (' + idFrom + ')');
|
||||
|
||||
// @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 = {
|
||||
|
@ -534,10 +534,10 @@ deactivate Bob`;
|
||||
expect(messages.length).toBe(4);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
|
||||
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[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 () => {
|
||||
const str = `
|
||||
@ -556,10 +556,10 @@ deactivate Bob`;
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
|
||||
expect(messages[0].activate).toBeTruthy();
|
||||
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[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 () => {
|
||||
const str = `
|
||||
@ -579,14 +579,14 @@ deactivate Bob`;
|
||||
expect(messages.length).toBe(8);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
|
||||
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[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].from.actor).toBe('Bob');
|
||||
expect(messages[5].from).toBe('Bob');
|
||||
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 () => {
|
||||
const str = `
|
||||
|
@ -144,15 +144,15 @@ export const bounds = {
|
||||
this.updateBounds(_startx, _starty, _stopx, _stopy);
|
||||
},
|
||||
newActivation: function (message, diagram, actors) {
|
||||
const actorRect = actors[message.from.actor];
|
||||
const stackedSize = actorActivations(message.from.actor).length || 0;
|
||||
const actorRect = actors[message.from];
|
||||
const stackedSize = actorActivations(message.from).length || 0;
|
||||
const x = actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
|
||||
this.activations.push({
|
||||
startx: x,
|
||||
starty: this.verticalPos + 2,
|
||||
stopx: x + conf.activationWidth,
|
||||
stopy: undefined,
|
||||
actor: message.from.actor,
|
||||
actor: message.from,
|
||||
anchored: svgDraw.anchorElement(diagram),
|
||||
});
|
||||
},
|
||||
@ -162,7 +162,7 @@ export const bounds = {
|
||||
.map(function (activation) {
|
||||
return activation.actor;
|
||||
})
|
||||
.lastIndexOf(message.from.actor);
|
||||
.lastIndexOf(message.from);
|
||||
return this.activations.splice(lastActorActivationIdx, 1)[0];
|
||||
},
|
||||
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,
|
||||
verticalPos,
|
||||
conf,
|
||||
actorActivations(msg.from.actor).length
|
||||
actorActivations(msg.from).length
|
||||
);
|
||||
|
||||
bounds.insert(activationData.startx, verticalPos - 10, activationData.stopx, verticalPos);
|
||||
@ -1545,14 +1545,14 @@ const calculateLoopBounds = async function (messages, actors, _maxWidthPerActor,
|
||||
break;
|
||||
case diagObj.db.LINETYPE.ACTIVE_START:
|
||||
{
|
||||
const actorRect = actors[msg.from ? msg.from.actor : msg.to.actor];
|
||||
const stackedSize = actorActivations(msg.from ? msg.from.actor : msg.to.actor).length;
|
||||
const actorRect = actors[msg.from ? msg.from : msg.to.actor];
|
||||
const stackedSize = actorActivations(msg.from ? msg.from : msg.to.actor).length;
|
||||
const x =
|
||||
actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
|
||||
const toAdd = {
|
||||
startx: x,
|
||||
stopx: x + conf.activationWidth,
|
||||
actor: msg.from.actor,
|
||||
actor: msg.from,
|
||||
enabled: true,
|
||||
};
|
||||
bounds.activations.push(toAdd);
|
||||
@ -1562,7 +1562,7 @@ const calculateLoopBounds = async function (messages, actors, _maxWidthPerActor,
|
||||
{
|
||||
const lastActorActivationIdx = bounds.activations
|
||||
.map((a) => a.actor)
|
||||
.lastIndexOf(msg.from.actor);
|
||||
.lastIndexOf(msg.from);
|
||||
delete bounds.activations.splice(lastActorActivationIdx, 1)[0];
|
||||
}
|
||||
break;
|
||||
|
@ -20,8 +20,8 @@ export interface Actor {
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
from?: { actor: string };
|
||||
to?: { actor: string };
|
||||
from?: string;
|
||||
to?: string;
|
||||
message:
|
||||
| string
|
||||
| {
|
||||
|
@ -145,7 +145,7 @@ const getRootDocV2 = () => {
|
||||
* Ex: the section within a fork has its own statements, and incoming and outgoing statements
|
||||
* 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.
|
||||
* 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
|
||||
*/
|
||||
|
@ -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.
|
||||
|
||||
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
|
||||
stateDiagram-v2
|
||||
@ -107,6 +107,14 @@ stateDiagram-v2
|
||||
[*] --> second
|
||||
second --> [*]
|
||||
}
|
||||
|
||||
[*] --> NamedComposite
|
||||
NamedComposite: Another Composite
|
||||
state NamedComposite {
|
||||
[*] --> namedSimple
|
||||
namedSimple --> [*]
|
||||
namedSimple: Another simple
|
||||
}
|
||||
```
|
||||
|
||||
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
Loading…
x
Reference in New Issue
Block a user