Skip to content

Commit

Permalink
Merge pull request #19 from mermaid-js/develop
Browse files Browse the repository at this point in the history
Merge into fork
  • Loading branch information
jgreywolf committed Apr 2, 2020
2 parents ccfc735 + 933cc33 commit 366f9db
Show file tree
Hide file tree
Showing 61 changed files with 4,020 additions and 159 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ dist/classTest.html
dist/sequenceTest.html

.vscode/
cypress/platform/current.html
cypress/platform/current.html
cypress/platform/experimental.html
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ For more information and help in getting started, please view our [documentation

With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams.

![Image show the two new diagram types](.docs/img/new-diagrams.png)
![Image show the two new diagram types](./docs/img/new-diagrams.png)

## Special note regarding version 8.2

Expand Down
91 changes: 91 additions & 0 deletions cypress/integration/rendering/erDiagram.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';

describe('Entity Relationship Diagram', () => {
it('should render a simple ER diagram', () => {
imgSnapshotTest(
`
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`,
{logLevel : 1}
);
cy.get('svg');
});

it('should render an ER diagram with a recursive relationship', () => {
imgSnapshotTest(
`
erDiagram
CUSTOMER ||..o{ CUSTOMER : refers
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`,
{logLevel : 1}
);
cy.get('svg');
});

it('should render an ER diagram with multiple relationships between the same two entities', () => {
imgSnapshotTest(
`
erDiagram
CUSTOMER ||--|{ ADDRESS : "invoiced at"
CUSTOMER ||--|{ ADDRESS : "receives goods at"
`,
{logLevel : 1}
);
cy.get('svg');
});

it('should render a cyclical ER diagram', () => {
imgSnapshotTest(
`
erDiagram
A ||--|{ B : likes
B ||--|{ C : likes
C ||--|{ A : likes
`,
{logLevel : 1}
);
cy.get('svg');
});

it('should render a not-so-simple ER diagram', () => {
imgSnapshotTest(
`
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
`,
{logLevel : 1}
);
cy.get('svg');
});

it('should render multiple ER diagrams', () => {
imgSnapshotTest(
[
`
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`,
`
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`
],
{logLevel : 1}
);
cy.get('svg');
});
});
171 changes: 156 additions & 15 deletions cypress/platform/current.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,169 @@
<style>
body {
background: white;
font-family: 'Noto Sans SC', sans-serif;
font-family: 'Arial';
}
h1 { color: white;}
.arrowheadPath {fill: red;}

.edgePath .path {stroke: red;}
.mermaid2 {
display: none;
}
</style>
</head>
<body>
<h1>info below</h1>
<div style="display: flex;width: 100%; height: 100%">
<div class="mermaid" style="width: 100%; height: 100%">
sequenceDiagram
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
<div class="mermaid2" style="width: 100%; height: 20%;">
flowchart LR
a --> b

subgraph id1 [Test]
a --apa--> c
b
c-->b
b-->H
end
G-->H
G-->c
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
flowchart LR
subgraph id1 [Test]
b
end
a-->id1
</div>
<div class="mermaid mermaid-apa" style="width: 100%; height: 20%;">
stateDiagram
[*] --> Still
Still --> [*]
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
</div>
<div class="mermaid" style="width: 100%; height: 100%;">
stateDiagram-v2
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.
</div>
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
[*]-->TV

state TV {
[*] --> Off: Off to start with
On --> Off : Turn off
Off --> On : Turn on
}

TV--> Console

state Console {
[*] --> Off2: Off to start with
On2--> Off2 : Turn off
Off2 --> On2 : Turn on
On2-->Playing

state Playing {
Alive --> Dead
Dead-->Alive
}
}

</div>

<div style="display: flex;flex-direction:column;width: 100%; height: 100%">
<div class="mermaid2" style="width: 100%; height: 100%;">
stateDiagram-v2
state apa {
[*] --> Still
Still --> [*]

Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
}

</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart TB
a --> b

subgraph id1 [Test]
a --apa--> c
b
c-->b
b-->H
end
G-->H
G-->id1
id1 --> I
I --> G
</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart RL
a --> b

subgraph id1 [Test]
a --apa--> c
b
c-->b
b-->H
end
G-->H
G-->id1
id1 --> I
I --> G
</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart RL

subgraph id1 [Test]
a
end
Note right of John: Rational thoughts!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
b-->id1
</div>
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart RL

subgraph id1 [Test1]
a
end
subgraph id2 [Test2]
b
end
a --> id2
a --> b
b-->id1
id1 --> id2
</div>
new:
<div class="mermaid2" style="width: 100%; height: 100%">
flowchart LR
a <--> b
b o--o c
c x--x d
a21([In the box]) --> b2
b2((b2)) --o c2
c2(c2) --x d2 --> id1{{This is the text in the box}} --> A[(cylindrical<br />shape<br />test)]
</div>
old:
<div class="mermaid2" style="width: 100%; height: 100%">
graph LR
a((a)) --> b --> id1{{This is the text in the box}}
A[(cylindrical<br />shape<br />test)]
</div>

</div>
<script src="./mermaid.js"></script>
<script>
Expand All @@ -43,7 +183,8 @@ <h1>info below</h1>
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"Noto Sans SC", sans-serif'
fontFamily: '"arial", sans-serif',
curve: 'linear',
});
</script>
</script>
Expand Down
80 changes: 80 additions & 0 deletions docs/entityRelationshipDiagram.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Entity Relationship Diagrams

> An entity–relationship model (or ER model) describes interrelated things of interest in a specific domain of knowledge. A basic ER model is composed of entity types (which classify the things of interest) and specifies relationships that can exist between entities (instances of those entity types). Wikipedia.
Note that practitioners of ER modelling almost always refer to entity types simply as entities. For example the CUSTOMER entity type would be referred to simply as the CUSTOMER entity. This is so common it would be inadvisable to do anything else, but technically an entity is an abstract *instance* of an entity type, and this is what an ER diagram shows - abstract instances, and the relationships between them. This is why entities are always named using singular nouns.

Mermaid can render ER diagrams
```
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ : DELIVERY-ADDRESS : uses
```
```mermaid
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ : DELIVERY-ADDRESS : uses
```

Entity names are often capitalised, although there is no accepted standard on this, and it is not required in Mermaid.

Relationships between entities are represented by lines with end markers representing cardinality. Mermaid uses the most popular crow's foot notation. The crow's foot intuitively conveys the possibility of many instances of the entity that it connects to.

## Status

ER diagrams are a new feature in Mermaid and are **experimental**. There are likely to be a few bugs and constraints, and enhancements will be made in due course.

## Syntax

### Entities and Relationships

Mermaid syntax for ER diagrams is compatible with PlantUML, with an extension to label the relationship. Each statement consists of the following parts, all of which are mandatory:
```
<first-entity> <relationship> <second-entity> : <relationship-label>
```
Where:

- `first-entity` is the name of an entity. Names must begin with an alphabetic character and may also contain digits and hyphens
- `relationship` describes the way that both entities inter-relate. See below.
- `second-entity` is the name of the other entity
- `relationship-label` describes the relationship from the perspective of the first entity.

For example:

```
PROPERTY ||--|{ ROOM : contains
```

This statement can be read as *a property contains one or more rooms, and a room is part of one and only one property*. You can see that the label here is from the first entity's perspective: a property contains a room, but a room does not contain a property. When considered from the perspective of the second entity, the equivalent label is usually very easy to infer. (Some ER diagrams label relationships from both perspectives, but this is not supported here, and is usually superfluous).

### Relationship Syntax

The `relationship` part of each statement can be broken down into three sub-components:

- the cardinality of the first entity with respect to the second,
- whether the relationship confers identity on a 'child' entity
- the cardinality of the second entity with respect to the first

Cardinality is a property that describes how many elements of another entity can be related to the entity in question. In the above example a `PROPERTY` can have one or more `ROOM` instances associated to it, whereas a `ROOM` can only be associated with one `PROPERTY`. In each cardinality marker there are two characters. The outermost character represents a maximum value, and the innermost character represents a minimum value. The table below summarises possible cardinalities.

| Value (left) | Value (right) | Meaning |
|:------------:|:-------------:|--------------------------------------------------------|
| `|o` | `o|` | Zero or one |
| `||` | `||` | Exactly one |
| `}o` | `o{` | Zero or more (no upper limit) |
| `}|` | `|{` | One or more (no upper limit) |

### Identification

Relationships may be classified as either *identifying* or *non-identifying* and these are rendered with either solid or dashed lines respectively. This is relevant when one of the entities in question can not have independent existence without the other. For example a firm that insures people to drive cars might need to store data on `NAMED-DRIVER`s. In modelling this we might start out by observing that a `CAR` can be driven by many `PERSON` instances, and a `PERSON` can drive many `CAR`s - both entities can exist without the other, so this is a non-identifying relationship that we might specify in Mermaid as: `PERSON }|..|{ CAR : "driver"`. Note the two dots in the middle of the relationship that will result in a dashed line being drawn between the two entities. But when this many-to-many relationship is resolved into two one-to-many relationships, we observe that a `NAMED-DRIVER` cannot exist without both a `PERSON` and a `CAR` - the relationships become identifying and would be specified using hyphens, which translate to a solid line:

```
CAR ||--o{ NAMED-DRIVER : allows
PERSON ||--o{ NAMED-DRIVER : is
```
### Other Things

- If you want the relationship label to be more than one word, you must use double quotes around the phrase
- If you don't want a label at all on a relationship, you must use an empty double-quoted string
Loading

0 comments on commit 366f9db

Please sign in to comment.