mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-31 14:16:42 +02:00
7
.github/pull_request_template.md
vendored
Normal file
7
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
## Summary
|
||||
Brief description about the content of your PR.
|
||||
|
||||
## Design Decisions
|
||||
Describe the way your implementation works or what design decisions you made if applicable.
|
||||
|
||||
Resolves #<your issue id here>
|
@@ -164,7 +164,31 @@ describe('Class diagram', () => {
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('5: should render a simple class diagram with Generic class', () => {
|
||||
it('5: should render a simple class diagram with abstract method', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
Class01 : someMethod()*
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('6: should render a simple class diagram with static method', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
Class01 : someMethod()$
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('7: should render a simple class diagram with Generic class', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
@@ -184,7 +208,7 @@ describe('Class diagram', () => {
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('6: should render a simple class diagram with Generic class and relations', () => {
|
||||
it('8: should render a simple class diagram with Generic class and relations', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
|
@@ -396,4 +396,61 @@ describe('Flowcart', () => {
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('15: Render Stadium shape', () => {
|
||||
imgSnapshotTest(
|
||||
` graph TD
|
||||
A([stadium shape test])
|
||||
A -->|Get money| B([Go shopping])
|
||||
B --> C([Let me think...<br />Do I want something for work,<br />something to spend every free second with,<br />or something to get around?])
|
||||
C -->|One| D([Laptop])
|
||||
C -->|Two| E([iPhone])
|
||||
C -->|Three| F([Car<br/>wroom wroom])
|
||||
click A "index.html#link-clicked" "link test"
|
||||
click B testClick "click test"
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;`,
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('16: Render Stadium shape', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
A1[Multi<br>Line] -->|Multi<br>Line| B1(Multi<br>Line)
|
||||
C1[Multi<br/>Line] -->|Multi<br/>Line| D1(Multi<br/>Line)
|
||||
E1[Multi<br />Line] -->|Multi<br />Line| F1(Multi<br />Line)
|
||||
A2[Multi<br>Line] -->|Multi<br>Line| B2(Multi<br>Line)
|
||||
C2[Multi<br/>Line] -->|Multi<br/>Line| D2(Multi<br/>Line)
|
||||
E2[Multi<br />Line] -->|Multi<br />Line| F2(Multi<br />Line)
|
||||
linkStyle 0 stroke:DarkGray,stroke-width:2px
|
||||
linkStyle 1 stroke:DarkGray,stroke-width:2px
|
||||
linkStyle 2 stroke:DarkGray,stroke-width:2px
|
||||
`,
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('17: Chaining of nodes', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
a --> b --> c
|
||||
`,
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('18: Multiple nodes and chaining in one statement', () => {
|
||||
imgSnapshotTest(
|
||||
`graph LR
|
||||
a --> b c--> d
|
||||
`,
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
it('19: Multiple nodes and chaining in one statement', () => {
|
||||
imgSnapshotTest(
|
||||
`graph TD
|
||||
A[ h ] -- hello --> B[" test "]:::exClass C --> D;
|
||||
classDef exClass background:#bbb,border:1px solid red;
|
||||
`,
|
||||
{ flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -38,4 +38,20 @@ describe('Sequencediagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('Multiple dependencies syntax', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %d/%m
|
||||
title Adding GANTT diagram to mermaid
|
||||
excludes weekdays 2014-01-10
|
||||
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
context('Aliasing', () => {
|
||||
it('should render a simple sequence diagrams', () => {
|
||||
context('Sequence diagram', () => {
|
||||
it('should render a simple sequence diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
@@ -32,6 +32,23 @@ context('Aliasing', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should handle different line breaks', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant 1 as multiline<br>using #lt;br#gt;
|
||||
participant 2 as multiline<br/>using #lt;br/#gt;
|
||||
participant 3 as multiline<br />using #lt;br /#gt;
|
||||
1->>2: multiline<br>using #lt;br#gt;
|
||||
note right of 2: multiline<br>using #lt;br#gt;
|
||||
2->>3: multiline<br/>using #lt;br/#gt;
|
||||
note right of 3: multiline<br/>using #lt;br/#gt;
|
||||
3->>1: multiline<br />using #lt;br /#gt;
|
||||
note right of 1: multiline<br />using #lt;br /#gt;
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
context('background rects', () => {
|
||||
it('should render a single and nested rects', () => {
|
||||
imgSnapshotTest(
|
||||
|
@@ -16,11 +16,16 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>info below</h1>
|
||||
<div style="display: flex;">
|
||||
<div class="mermaid">graph TD
|
||||
A ==> B
|
||||
A --> C
|
||||
A -.-> D
|
||||
<div style="display: flex;width: 100%; height: 100%">
|
||||
<div class="mermaid" style="width: 100%; height: 100%">
|
||||
graph TB
|
||||
A --> B
|
||||
A ==> C
|
||||
A .-> D
|
||||
A === E
|
||||
A -.- F
|
||||
D -- Hello --> a
|
||||
D-- text including R TD space --xb
|
||||
</div>
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
@@ -29,9 +34,9 @@
|
||||
theme: 'dark',
|
||||
// arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
logLevel: 3,
|
||||
logLevel: 0,
|
||||
flowchart: { curve: 'linear', "htmlLabels": false },
|
||||
gantt: { axisFormat: '%m/%d/%Y' },
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50 },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
});
|
||||
|
37
dist/index.html
vendored
37
dist/index.html
vendored
@@ -300,6 +300,31 @@ click B testClick "click test"
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;
|
||||
</div>
|
||||
<div class="mermaid">
|
||||
graph TD
|
||||
A([stadium shape test])
|
||||
A -->|Get money| B([Go shopping])
|
||||
B --> C([Let me think...<br />Do I want something for work,<br />something to spend every free second with,<br />or something to get around?])
|
||||
C -->|One| D([Laptop])
|
||||
C -->|Two| E([iPhone])
|
||||
C -->|Three| F([Car<br/>wroom wroom])
|
||||
click A "index.html#link-clicked" "link test"
|
||||
click B testClick "click test"
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;
|
||||
</div>
|
||||
<div class="mermaid">
|
||||
graph LR
|
||||
A1[Multi<br>Line] -->|Multi<br>Line| B1(Multi<br>Line)
|
||||
C1[Multi<br/>Line] -->|Multi<br/>Line| D1(Multi<br/>Line)
|
||||
E1[Multi<br />Line] -->|Multi<br />Line| F1(Multi<br />Line)
|
||||
A2[Multi<br>Line] -->|Multi<br>Line| B2(Multi<br>Line)
|
||||
C2[Multi<br/>Line] -->|Multi<br/>Line| D2(Multi<br/>Line)
|
||||
E2[Multi<br />Line] -->|Multi<br />Line| F2(Multi<br />Line)
|
||||
linkStyle 0 stroke:DarkGray,stroke-width:2px
|
||||
linkStyle 1 stroke:DarkGray,stroke-width:2px
|
||||
linkStyle 2 stroke:DarkGray,stroke-width:2px
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
@@ -331,6 +356,18 @@ and
|
||||
Alice -->> John: Parallel message 2
|
||||
end
|
||||
</div>
|
||||
<div class="mermaid">
|
||||
sequenceDiagram
|
||||
participant 1 as multiline<br>using #lt;br#gt;
|
||||
participant 2 as multiline<br/>using #lt;br/#gt;
|
||||
participant 3 as multiline<br />using #lt;br /#gt;
|
||||
1->>2: multiline<br>using #lt;br#gt;
|
||||
note right of 2: multiline<br>using #lt;br#gt;
|
||||
2->>3: multiline<br/>using #lt;br/#gt;
|
||||
note right of 3: multiline<br/>using #lt;br/#gt;
|
||||
3->>1: multiline<br />using #lt;br /#gt;
|
||||
note right of 1: multiline<br />using #lt;br /#gt;
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
[](https://travis-ci.org/knsv/mermaid)
|
||||
[](https://travis-ci.org/mermaid-js/mermaid)
|
||||
[](https://coveralls.io/github/knsv/mermaid?branch=master)
|
||||
[](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
|
@@ -105,17 +105,10 @@ Naming convention: a class name should be composed of alphanumeric (unicode allo
|
||||
|
||||
UML provides mechanisms to represent class members, such as attributes and methods, and additional information about them.
|
||||
|
||||
#### Visibility
|
||||
To specify the visibility of a class member (i.e. any attribute or method), these notations may be placed before the member's name, but is it optional:
|
||||
Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The ones with `()` are treated as functions/methods, and others as attributes.
|
||||
|
||||
- `+` Public
|
||||
- `-` Private
|
||||
- `#` Protected
|
||||
- `~` Package
|
||||
|
||||
Mermaid distinguishes between attributes and functions/methods based on if the **parenthesis** `()` are present or not. The one with `()` are treated as functions/methods, and others as attributes.
|
||||
|
||||
There are two ways to define the members of a class, and regardless of the whichever syntax is used to define the members, the output will still be same. The two different ways are :
|
||||
There are two ways to define the members of a class, and regardless of whichever syntax is used to define the members, the output will still be same. The two different ways are :
|
||||
- Associate a member of a class using **:** (colon) followed by member name, useful to define one member at a time. For example:
|
||||
|
||||
```
|
||||
@@ -125,7 +118,7 @@ There are two ways to define the members of a class, and regardless of the which
|
||||
BankAccount : +deposit(amount)
|
||||
BankAccount : +withdrawl(amount)
|
||||
```
|
||||
```mermaid
|
||||
``` mermaid
|
||||
classDiagram
|
||||
class BankAccount
|
||||
BankAccount : +String owner
|
||||
@@ -150,7 +143,22 @@ class BankAccount{
|
||||
+BigDecimal balance
|
||||
+deposit(amount)
|
||||
+withdrawl(amount)
|
||||
}```
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### Visibility
|
||||
To specify the visibility of a class member (i.e. any attribute or method), these notations may be placed before the member's name, but it is optional:
|
||||
|
||||
- `+` Public
|
||||
- `-` Private
|
||||
- `#` Protected
|
||||
- `~` Package
|
||||
|
||||
>_note_ you can also include additional _classifers_ to a method definition by adding the following notations to the end of the method, i.e.: after the `()`:
|
||||
> - `*` Abstract e.g.: `someAbstractMethod()*`
|
||||
> - `$` Static e.g.: `someStaticMethod()$`
|
||||
|
||||
|
||||
## Defining Relationship
|
||||
A relationship is a general term covering the specific types of logical connections found on class and object diagrams.
|
||||
|
@@ -78,6 +78,17 @@ graph LR
|
||||
id1(This is the text in the box)
|
||||
```
|
||||
|
||||
### A stadium-shaped node
|
||||
|
||||
```
|
||||
graph LR
|
||||
id1([This is the text in the box])
|
||||
```
|
||||
```mermaid
|
||||
graph LR
|
||||
id1([This is the text in the box])
|
||||
```
|
||||
|
||||
### A node in the form of a circle
|
||||
|
||||
```
|
||||
|
@@ -87,6 +87,20 @@ gantt
|
||||
Add another diagram to demo page :48h
|
||||
```
|
||||
|
||||
It is possible to set multiple depenendenies separated by space:
|
||||
```
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
```
|
||||
```
|
||||
gantt
|
||||
apple :a, 2017-07-20, 1w
|
||||
banana :crit, b, 2017-07-23, 1d
|
||||
cherry :active, c, after b a, 1d
|
||||
```
|
||||
|
||||
### Title
|
||||
|
||||
Tbd
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<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">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
|
||||
<script src="//cdn.jsdelivr.net/npm/mermaid@8.4.3/dist/mermaid.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/mermaid@8.4.4/dist/mermaid.min.js"></script>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
@@ -159,14 +159,13 @@ The main idea of the API is to be able to call a render function with the graph
|
||||
will render the graph and call a callback with the resulting svg code. With this approach it is up to the site creator to
|
||||
fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site.
|
||||
|
||||
To do this, include mermaidAPI on your web website instead of mermaid.js. The example below show an outline of how this
|
||||
could be used. The example just logs the resulting svg to the javascript console.
|
||||
The example below show an outline of how this could be used. The example just logs the resulting svg to the javascript console.
|
||||
|
||||
```html
|
||||
<script src="mermaidAPI.js"></script>
|
||||
<script src="mermaid.js"></script>
|
||||
|
||||
<script>
|
||||
mermaidAPI.initialize({
|
||||
mermaid.mermaidAPI.initialize({
|
||||
startOnLoad:false
|
||||
});
|
||||
$(function(){
|
||||
@@ -178,7 +177,7 @@ could be used. The example just logs the resulting svg to the javascript console
|
||||
};
|
||||
|
||||
var graphDefinition = 'graph TB\na-->b';
|
||||
var graph = mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
|
||||
var graph = mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mermaid",
|
||||
"version": "8.4.3",
|
||||
"version": "8.4.4",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"main": "dist/mermaid.core.js",
|
||||
"keywords": [
|
||||
|
@@ -94,7 +94,7 @@ export const addMember = function(className, member) {
|
||||
if (memberString.startsWith('<<') && memberString.endsWith('>>')) {
|
||||
// Remove leading and trailing brackets
|
||||
theClass.annotations.push(memberString.substring(2, memberString.length - 2));
|
||||
} else if (memberString.endsWith(')')) {
|
||||
} else if (memberString.indexOf(')') > 0) {
|
||||
theClass.methods.push(memberString);
|
||||
} else if (memberString) {
|
||||
theClass.members.push(memberString);
|
||||
|
@@ -442,5 +442,27 @@ describe('class diagram, ', function () {
|
||||
expect(testClass.methods[0]).toBe('test()');
|
||||
expect(testClass.methods[1]).toBe('foo()');
|
||||
});
|
||||
|
||||
it('should handle abstract methods', function () {
|
||||
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()*';
|
||||
parser.parse(str);
|
||||
|
||||
const testClass = parser.yy.getClass('Class1');
|
||||
expect(testClass.annotations.length).toBe(0);
|
||||
expect(testClass.members.length).toBe(0);
|
||||
expect(testClass.methods.length).toBe(1);
|
||||
expect(testClass.methods[0]).toBe('someMethod()*');
|
||||
});
|
||||
|
||||
it('should handle static methods', function () {
|
||||
const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()$';
|
||||
parser.parse(str);
|
||||
|
||||
const testClass = parser.yy.getClass('Class1');
|
||||
expect(testClass.annotations.length).toBe(0);
|
||||
expect(testClass.members.length).toBe(0);
|
||||
expect(testClass.methods.length).toBe(1);
|
||||
expect(testClass.methods[0]).toBe('someMethod()$');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -281,10 +281,34 @@ const drawClass = function(elem, classDef) {
|
||||
logger.info('Rendering class ' + classDef);
|
||||
|
||||
const addTspan = function(textEl, txt, isFirst) {
|
||||
let displayText = txt;
|
||||
let cssStyle = '';
|
||||
let methodEnd = txt.indexOf(')') + 1;
|
||||
|
||||
if (methodEnd > 1 && methodEnd <= txt.length) {
|
||||
let classifier = txt.substring(methodEnd);
|
||||
|
||||
switch (classifier) {
|
||||
case '*':
|
||||
cssStyle = 'font-style:italic;';
|
||||
break;
|
||||
case '$':
|
||||
cssStyle = 'text-decoration:underline;';
|
||||
break;
|
||||
}
|
||||
|
||||
displayText = txt.substring(0, methodEnd);
|
||||
}
|
||||
|
||||
const tSpan = textEl
|
||||
.append('tspan')
|
||||
.attr('x', conf.padding)
|
||||
.text(txt);
|
||||
.text(displayText);
|
||||
|
||||
if (cssStyle !== '') {
|
||||
tSpan.attr('style', cssStyle);
|
||||
}
|
||||
|
||||
if (!isFirst) {
|
||||
tSpan.attr('dy', conf.textHeight);
|
||||
}
|
||||
|
@@ -135,9 +135,29 @@ function rect_right_inv_arrow(parent, bbox, node) {
|
||||
return shapeSvg;
|
||||
}
|
||||
|
||||
function stadium(parent, bbox, node) {
|
||||
const h = bbox.height;
|
||||
const w = bbox.width + h / 4;
|
||||
|
||||
const shapeSvg = parent
|
||||
.insert('rect', ':first-child')
|
||||
.attr('rx', h / 2)
|
||||
.attr('ry', h / 2)
|
||||
.attr('x', -w / 2)
|
||||
.attr('y', -h / 2)
|
||||
.attr('width', w)
|
||||
.attr('height', h);
|
||||
|
||||
node.intersect = function(point) {
|
||||
return dagreD3.intersect.rect(node, point);
|
||||
};
|
||||
return shapeSvg;
|
||||
}
|
||||
|
||||
export function addToRender(render) {
|
||||
render.shapes().question = question;
|
||||
render.shapes().hexagon = hexagon;
|
||||
render.shapes().stadium = stadium;
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
render.shapes().rect_left_inv_arrow = rect_left_inv_arrow;
|
||||
|
@@ -1,6 +1,29 @@
|
||||
import { addToRender } from './flowChartShapes';
|
||||
|
||||
describe('flowchart shapes', function() {
|
||||
// rect-based shapes
|
||||
[
|
||||
['stadium', useWidth, useHeight]
|
||||
].forEach(function([shapeType, getW, getH]) {
|
||||
it(`should add a ${shapeType} shape that renders a properly positioned rect element`, function() {
|
||||
const mockRender = MockRender();
|
||||
const mockSvg = MockSvg();
|
||||
addToRender(mockRender);
|
||||
|
||||
[[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) {
|
||||
const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {});
|
||||
const w = width + height / 4;
|
||||
const h = height;
|
||||
const dx = -getW(w, h) / 2;
|
||||
const dy = -getH(w, h) / 2;
|
||||
expect(shape.__tag).toEqual('rect');
|
||||
expect(shape.__attrs).toHaveProperty('x', dx);
|
||||
expect(shape.__attrs).toHaveProperty('y', dy);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// polygon-based shapes
|
||||
[
|
||||
[
|
||||
'question',
|
||||
|
@@ -102,7 +102,7 @@ export const addVertex = function(_id, text, type, style, classes) {
|
||||
* @param type
|
||||
* @param linktext
|
||||
*/
|
||||
export const addLink = function(_start, _end, type, linktext) {
|
||||
export const addSingleLink = function(_start, _end, type, linktext) {
|
||||
let start = _start;
|
||||
let end = _end;
|
||||
if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
|
||||
@@ -127,6 +127,14 @@ export const addLink = function(_start, _end, type, linktext) {
|
||||
}
|
||||
edges.push(edge);
|
||||
};
|
||||
export const addLink = function(_start, _end, type, linktext) {
|
||||
let i, j;
|
||||
for (i = 0; i < _start.length; i++) {
|
||||
for (j = 0; j < _end.length; j++) {
|
||||
addSingleLink(_start[i], _end[j], type, linktext);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates a link's line interpolation algorithm
|
||||
@@ -501,6 +509,130 @@ export const firstGraph = () => {
|
||||
return false;
|
||||
};
|
||||
|
||||
const destructStartLink = _str => {
|
||||
const str = _str.trim();
|
||||
|
||||
switch (str) {
|
||||
case '<--':
|
||||
return { type: 'arrow', stroke: 'normal' };
|
||||
case 'x--':
|
||||
return { type: 'arrow_cross', stroke: 'normal' };
|
||||
case 'o--':
|
||||
return { type: 'arrow_circle', stroke: 'normal' };
|
||||
case '<-.':
|
||||
return { type: 'arrow', stroke: 'dotted' };
|
||||
case 'x-.':
|
||||
return { type: 'arrow_cross', stroke: 'dotted' };
|
||||
case 'o-.':
|
||||
return { type: 'arrow_circle', stroke: 'dotted' };
|
||||
case '<==':
|
||||
return { type: 'arrow', stroke: 'thick' };
|
||||
case 'x==':
|
||||
return { type: 'arrow_cross', stroke: 'thick' };
|
||||
case 'o==':
|
||||
return { type: 'arrow_circle', stroke: 'thick' };
|
||||
case '--':
|
||||
return { type: 'arrow_open', stroke: 'normal' };
|
||||
case '==':
|
||||
return { type: 'arrow_open', stroke: 'thick' };
|
||||
case '-.':
|
||||
return { type: 'arrow_open', stroke: 'dotted' };
|
||||
}
|
||||
};
|
||||
|
||||
const destructEndLink = _str => {
|
||||
const str = _str.trim();
|
||||
|
||||
switch (str) {
|
||||
case '--x':
|
||||
return { type: 'arrow_cross', stroke: 'normal' };
|
||||
case '-->':
|
||||
return { type: 'arrow', stroke: 'normal' };
|
||||
case '<-->':
|
||||
return { type: 'double_arrow_point', stroke: 'normal' };
|
||||
case 'x--x':
|
||||
return { type: 'double_arrow_cross', stroke: 'normal' };
|
||||
case 'o--o':
|
||||
return { type: 'double_arrow_circle', stroke: 'normal' };
|
||||
case 'o.-o':
|
||||
return { type: 'double_arrow_circle', stroke: 'dotted' };
|
||||
case '<==>':
|
||||
return { type: 'double_arrow_point', stroke: 'thick' };
|
||||
case 'o==o':
|
||||
return { type: 'double_arrow_circle', stroke: 'thick' };
|
||||
case 'x==x':
|
||||
return { type: 'double_arrow_cross', stroke: 'thick' };
|
||||
case 'x.-x':
|
||||
return { type: 'double_arrow_cross', stroke: 'dotted' };
|
||||
case 'x-.-x':
|
||||
return { type: 'double_arrow_cross', stroke: 'dotted' };
|
||||
case '<.->':
|
||||
return { type: 'double_arrow_point', stroke: 'dotted' };
|
||||
case '<-.->':
|
||||
return { type: 'double_arrow_point', stroke: 'dotted' };
|
||||
case 'o-.-o':
|
||||
return { type: 'double_arrow_circle', stroke: 'dotted' };
|
||||
case '--o':
|
||||
return { type: 'arrow_circle', stroke: 'normal' };
|
||||
case '---':
|
||||
return { type: 'arrow_open', stroke: 'normal' };
|
||||
case '-.-x':
|
||||
return { type: 'arrow_cross', stroke: 'dotted' };
|
||||
case '-.->':
|
||||
return { type: 'arrow', stroke: 'dotted' };
|
||||
case '-.-o':
|
||||
return { type: 'arrow_circle', stroke: 'dotted' };
|
||||
case '-.-':
|
||||
return { type: 'arrow_open', stroke: 'dotted' };
|
||||
case '.-x':
|
||||
return { type: 'arrow_cross', stroke: 'dotted' };
|
||||
case '.->':
|
||||
return { type: 'arrow', stroke: 'dotted' };
|
||||
case '.-o':
|
||||
return { type: 'arrow_circle', stroke: 'dotted' };
|
||||
case '.-':
|
||||
return { type: 'arrow_open', stroke: 'dotted' };
|
||||
case '==x':
|
||||
return { type: 'arrow_cross', stroke: 'thick' };
|
||||
case '==>':
|
||||
return { type: 'arrow', stroke: 'thick' };
|
||||
case '==o':
|
||||
return { type: 'arrow_circle', stroke: 'thick' };
|
||||
case '===':
|
||||
return { type: 'arrow_open', stroke: 'thick' };
|
||||
}
|
||||
};
|
||||
|
||||
const destructLink = (_str, _startStr) => {
|
||||
const info = destructEndLink(_str);
|
||||
let startInfo;
|
||||
if (_startStr) {
|
||||
startInfo = destructStartLink(_startStr);
|
||||
console.log(startInfo, info);
|
||||
if (startInfo.stroke !== info.stroke) {
|
||||
return { type: 'INVALID', stroke: 'INVALID' };
|
||||
}
|
||||
|
||||
if (startInfo.type === 'arrow_open') {
|
||||
// -- xyz --> - take arrow type form ending
|
||||
startInfo.type = info.type;
|
||||
} else {
|
||||
// x-- xyz --> - not supported
|
||||
if (startInfo.type !== info.type) return { type: 'INVALID', stroke: 'INVALID' };
|
||||
|
||||
startInfo.type = 'double_' + startInfo.type;
|
||||
}
|
||||
|
||||
if (startInfo.type === 'double_arrow') {
|
||||
startInfo.type = 'double_arrow_point';
|
||||
}
|
||||
|
||||
return startInfo;
|
||||
}
|
||||
|
||||
return info;
|
||||
};
|
||||
|
||||
export default {
|
||||
addVertex,
|
||||
addLink,
|
||||
@@ -523,6 +655,7 @@ export default {
|
||||
getDepthFirstPos,
|
||||
indexNodes,
|
||||
getSubGraphs,
|
||||
destructLink,
|
||||
lex: {
|
||||
firstGraph
|
||||
}
|
||||
|
@@ -154,6 +154,9 @@ export const addVertices = function(vert, g, svgId) {
|
||||
case 'ellipse':
|
||||
_shape = 'ellipse';
|
||||
break;
|
||||
case 'stadium':
|
||||
_shape = 'stadium';
|
||||
break;
|
||||
case 'group':
|
||||
_shape = 'rect';
|
||||
break;
|
||||
@@ -236,18 +239,18 @@ export const addEdges = function(edges, g) {
|
||||
}
|
||||
} else {
|
||||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
if (typeof edge.style === 'undefined') {
|
||||
edgeData.labelpos = 'c';
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
edgeData.labelType = 'html';
|
||||
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
|
||||
} else {
|
||||
edgeData.labelType = 'text';
|
||||
edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none';
|
||||
edgeData.label = edge.text.replace(/<br>/g, '\n');
|
||||
}
|
||||
edgeData.labelpos = 'c';
|
||||
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
edgeData.labelType = 'html';
|
||||
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
|
||||
} else {
|
||||
edgeData.label = edge.text.replace(/<br>/g, '\n');
|
||||
edgeData.labelType = 'text';
|
||||
edgeData.label = edge.text.replace(/<br ?\/?>/g, '\n');
|
||||
|
||||
if (typeof edge.style === 'undefined') {
|
||||
edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none';
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add the edge to the graph
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { addVertices } from './flowRenderer';
|
||||
import { addVertices, addEdges } from './flowRenderer';
|
||||
import { setConfig } from '../../config';
|
||||
|
||||
setConfig({
|
||||
@@ -22,6 +22,7 @@ describe('the flowchart renderer', function() {
|
||||
['odd_right', 'rect_left_inv_arrow'],
|
||||
['circle', 'circle'],
|
||||
['ellipse', 'ellipse'],
|
||||
['stadium', 'stadium'],
|
||||
['group', 'rect']
|
||||
].forEach(function([type, expectedShape, expectedRadios = 0]) {
|
||||
it(`should add the correct shaped node to the graph for vertex type ${type}`, function() {
|
||||
@@ -93,4 +94,32 @@ describe('the flowchart renderer', function() {
|
||||
expect(addedNodes[0][1]).toHaveProperty('labelStyle', expectedLabelStyle);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when adding edges to a graph', function() {
|
||||
it('should handle multiline texts and set centered label position', function() {
|
||||
const addedEdges = [];
|
||||
const mockG = {
|
||||
setEdge: function(s, e, data, c) {
|
||||
addedEdges.push(data);
|
||||
}
|
||||
};
|
||||
addEdges(
|
||||
[
|
||||
{ text: 'Multi<br>Line' },
|
||||
{ text: 'Multi<br/>Line' },
|
||||
{ text: 'Multi<br />Line' },
|
||||
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br>Line' },
|
||||
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br/>Line' },
|
||||
{ style: ['stroke:DarkGray', 'stroke-width:2px'], text: 'Multi<br />Line' }
|
||||
],
|
||||
mockG,
|
||||
'svg-id'
|
||||
);
|
||||
|
||||
addedEdges.forEach(function(edge) {
|
||||
expect(edge).toHaveProperty('label', 'Multi\nLine');
|
||||
expect(edge).toHaveProperty('labelpos', 'c');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -87,7 +87,7 @@ describe('[Edges] when parsing', () => {
|
||||
expect(edges[0].text).toBe('');
|
||||
});
|
||||
|
||||
it('should handle double edged nodes with text on thick arrows', function() {
|
||||
it('should handle double edged nodes with text on thick arrows XYZ1', function() {
|
||||
const res = flow.parser.parse('graph TD;\nA x== text ==x B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
@@ -22,6 +22,16 @@ describe('[Singlenodes] when parsing', () => {
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['A'].styles.length).toBe(0);
|
||||
});
|
||||
it('should handle a single node with white space after it (SN1)', function() {
|
||||
// Silly but syntactically correct
|
||||
const res = flow.parser.parse('graph TD;A ;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['A'].styles.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a single square node', function() {
|
||||
// Silly but syntactically correct
|
||||
|
@@ -182,7 +182,7 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
expect(edges[0].stroke).toBe('normal');
|
||||
});
|
||||
it('it should handle dotted text on lines', function() {
|
||||
it('it should handle dotted text on lines (TD3)', function() {
|
||||
const res = flow.parser.parse('graph TD;A-. test text with == .->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -265,7 +265,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].text).toBe('text including URL space');
|
||||
});
|
||||
|
||||
it('should handle space and dir (TD)', function() {
|
||||
it('should handle space and dir (TD2)', function() {
|
||||
const res = flow.parser.parse('graph TD;A-- text including R TD space --xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
@@ -34,4 +34,179 @@ describe('when parsing flowcharts', function() {
|
||||
expect(edges[1].type).toBe('arrow');
|
||||
expect(edges[1].text).toBe('');
|
||||
});
|
||||
it('should handle chaining of vertices', function() {
|
||||
const res = flow.parser.parse(`
|
||||
graph TD
|
||||
A B --> C;
|
||||
`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('C');
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
expect(edges[0].text).toBe('');
|
||||
expect(edges[1].start).toBe('B');
|
||||
expect(edges[1].end).toBe('C');
|
||||
expect(edges[1].type).toBe('arrow');
|
||||
expect(edges[1].text).toBe('');
|
||||
});
|
||||
it('should multiple vertices in link statement in the begining', function() {
|
||||
const res = flow.parser.parse(`
|
||||
graph TD
|
||||
A-->B C;
|
||||
`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
expect(edges[0].text).toBe('');
|
||||
expect(edges[1].start).toBe('A');
|
||||
expect(edges[1].end).toBe('C');
|
||||
expect(edges[1].type).toBe('arrow');
|
||||
expect(edges[1].text).toBe('');
|
||||
});
|
||||
it('should multiple vertices in link statement at the end', function() {
|
||||
const res = flow.parser.parse(`
|
||||
graph TD
|
||||
A B--> C D;
|
||||
`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D'].id).toBe('D');
|
||||
expect(edges.length).toBe(4);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('C');
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
expect(edges[0].text).toBe('');
|
||||
expect(edges[1].start).toBe('A');
|
||||
expect(edges[1].end).toBe('D');
|
||||
expect(edges[1].type).toBe('arrow');
|
||||
expect(edges[1].text).toBe('');
|
||||
expect(edges[2].start).toBe('B');
|
||||
expect(edges[2].end).toBe('C');
|
||||
expect(edges[2].type).toBe('arrow');
|
||||
expect(edges[2].text).toBe('');
|
||||
expect(edges[3].start).toBe('B');
|
||||
expect(edges[3].end).toBe('D');
|
||||
expect(edges[3].type).toBe('arrow');
|
||||
expect(edges[3].text).toBe('');
|
||||
});
|
||||
it('should handle chaining of vertices at both ends at once', function() {
|
||||
const res = flow.parser.parse(`
|
||||
graph TD
|
||||
A B--> C D;
|
||||
`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D'].id).toBe('D');
|
||||
expect(edges.length).toBe(4);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('C');
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
expect(edges[0].text).toBe('');
|
||||
expect(edges[1].start).toBe('A');
|
||||
expect(edges[1].end).toBe('D');
|
||||
expect(edges[1].type).toBe('arrow');
|
||||
expect(edges[1].text).toBe('');
|
||||
expect(edges[2].start).toBe('B');
|
||||
expect(edges[2].end).toBe('C');
|
||||
expect(edges[2].type).toBe('arrow');
|
||||
expect(edges[2].text).toBe('');
|
||||
expect(edges[3].start).toBe('B');
|
||||
expect(edges[3].end).toBe('D');
|
||||
expect(edges[3].type).toBe('arrow');
|
||||
expect(edges[3].text).toBe('');
|
||||
});
|
||||
it('should handle chaining and multiple nodes in in link statement', function() {
|
||||
const res = flow.parser.parse(`
|
||||
graph TD
|
||||
A --> B C --> D;
|
||||
`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D'].id).toBe('D');
|
||||
expect(edges.length).toBe(4);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
expect(edges[0].text).toBe('');
|
||||
expect(edges[1].start).toBe('A');
|
||||
expect(edges[1].end).toBe('C');
|
||||
expect(edges[1].type).toBe('arrow');
|
||||
expect(edges[1].text).toBe('');
|
||||
expect(edges[2].start).toBe('B');
|
||||
expect(edges[2].end).toBe('D');
|
||||
expect(edges[2].type).toBe('arrow');
|
||||
expect(edges[2].text).toBe('');
|
||||
expect(edges[3].start).toBe('C');
|
||||
expect(edges[3].end).toBe('D');
|
||||
expect(edges[3].type).toBe('arrow');
|
||||
expect(edges[3].text).toBe('');
|
||||
});
|
||||
it('should handle chaining and multiple nodes in in link statement with extra info in statements', function() {
|
||||
const res = flow.parser.parse(`
|
||||
graph TD
|
||||
A[ h ] -- hello --> B[" test "]:::exClass C --> D;
|
||||
classDef exClass background:#bbb,border:1px solid red;
|
||||
`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['B'].classes[0]).toBe('exClass');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D'].id).toBe('D');
|
||||
expect(edges.length).toBe(4);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
expect(edges[0].text).toBe('hello');
|
||||
expect(edges[1].start).toBe('A');
|
||||
expect(edges[1].end).toBe('C');
|
||||
expect(edges[1].type).toBe('arrow');
|
||||
expect(edges[1].text).toBe('hello');
|
||||
expect(edges[2].start).toBe('B');
|
||||
expect(edges[2].end).toBe('D');
|
||||
expect(edges[2].type).toBe('arrow');
|
||||
expect(edges[2].text).toBe('');
|
||||
expect(edges[3].start).toBe('C');
|
||||
expect(edges[3].end).toBe('D');
|
||||
expect(edges[3].type).toBe('arrow');
|
||||
expect(edges[3].text).toBe('');
|
||||
});
|
||||
});
|
||||
|
@@ -8,6 +8,7 @@
|
||||
%lex
|
||||
%x string
|
||||
%x dir
|
||||
%x vertex
|
||||
%%
|
||||
\%\%[^\n]*\n* /* do nothing */
|
||||
["] this.begin("string");
|
||||
@@ -40,48 +41,50 @@
|
||||
";" return 'SEMI';
|
||||
"," return 'COMMA';
|
||||
"*" return 'MULT';
|
||||
\s*\-\-[x]\s* return 'ARROW_CROSS';
|
||||
\s*\-\-\>\s* return 'ARROW_POINT';
|
||||
\s*\<\-\-\>\s* return 'DOUBLE_ARROW_POINT';
|
||||
\s*[x]\-\-[x]\s* return 'DOUBLE_ARROW_CROSS';
|
||||
\s*[o]\-\-[o]\s* return 'DOUBLE_ARROW_CIRCLE';
|
||||
\s*[o]\.\-[o]\s* return 'DOUBLE_DOTTED_ARROW_CIRCLE';
|
||||
\s*\<\=\=\>\s* return 'DOUBLE_THICK_ARROW_POINT';
|
||||
\s*[o]\=\=[o]\s* return 'DOUBLE_THICK_ARROW_CIRCLE';
|
||||
\s*[x]\=\=[x]\s* return 'DOUBLE_THICK_ARROW_CROSS';
|
||||
\s*[x].\-[x]\s* return 'DOUBLE_DOTTED_ARROW_CROSS';
|
||||
\s*[x]\-\.\-[x]\s* return 'DOUBLE_DOTTED_ARROW_CROSS';
|
||||
\s*\<\.\-\>\s* return 'DOUBLE_DOTTED_ARROW_POINT';
|
||||
\s*\<\-\.\-\>\s* return 'DOUBLE_DOTTED_ARROW_POINT';
|
||||
\s*[o]\-\.\-[o]\s* return 'DOUBLE_DOTTED_ARROW_CIRCLE';
|
||||
\s*\-\-[o]\s* return 'ARROW_CIRCLE';
|
||||
\s*\-\-\-\s* return 'ARROW_OPEN';
|
||||
\s*\-\.\-[x]\s* return 'DOTTED_ARROW_CROSS';
|
||||
\s*\-\.\-\>\s* return 'DOTTED_ARROW_POINT';
|
||||
\s*\-\.\-[o]\s* return 'DOTTED_ARROW_CIRCLE';
|
||||
\s*\-\.\-\s* return 'DOTTED_ARROW_OPEN';
|
||||
\s*.\-[x]\s* return 'DOTTED_ARROW_CROSS';
|
||||
\s*\.\-\>\s* return 'DOTTED_ARROW_POINT';
|
||||
\s*\.\-[o]\s* return 'DOTTED_ARROW_CIRCLE';
|
||||
\s*\.\-\s* return 'DOTTED_ARROW_OPEN';
|
||||
\s*\=\=[x]\s* return 'THICK_ARROW_CROSS';
|
||||
\s*\=\=\>\s* return 'THICK_ARROW_POINT';
|
||||
\s*\=\=[o]\s* return 'THICK_ARROW_CIRCLE';
|
||||
\s*\=\=[\=]\s* return 'THICK_ARROW_OPEN';
|
||||
\s*\<\-\-\s* return 'START_DOUBLE_ARROW_POINT';
|
||||
\s*[x]\-\-\s* return 'START_DOUBLE_ARROW_CROSS';
|
||||
\s*[o]\-\-\s* return 'START_DOUBLE_ARROW_CIRCLE';
|
||||
\s*\<\-\.\s* return 'START_DOUBLE_DOTTED_ARROW_POINT';
|
||||
\s*[x]\-\.\s* return 'START_DOUBLE_DOTTED_ARROW_CROSS';
|
||||
\s*[o]\-\.\s* return 'START_DOUBLE_DOTTED_ARROW_CIRCLE';
|
||||
\s*\<\=\=\s* return 'START_DOUBLE_THICK_ARROW_POINT';
|
||||
\s*[x]\=\=\s* return 'START_DOUBLE_THICK_ARROW_CROSS';
|
||||
\s*[o]\=\=\s* return 'START_DOUBLE_THICK_ARROW_CIRCLE';
|
||||
\s*\-\-\s* return '--';
|
||||
\s*\-\.\s* return '-.';
|
||||
\s*\=\=\s* return '==';
|
||||
\s*\-\-[x]\s* return 'LINK';
|
||||
\s*\-\-\>\s* return 'LINK';
|
||||
\s*\<\-\-\>\s* return 'LINK';
|
||||
\s*[x]\-\-[x]\s* return 'LINK';
|
||||
\s*[o]\-\-[o]\s* return 'LINK';
|
||||
\s*[o]\.\-[o]\s* return 'LINK';
|
||||
\s*\<\=\=\>\s* return 'LINK';
|
||||
\s*[o]\=\=[o]\s* return 'LINK';
|
||||
\s*[x]\=\=[x]\s* return 'LINK';
|
||||
\s*[x].\-[x]\s* return 'LINK';
|
||||
\s*[x]\-\.\-[x]\s* return 'LINK';
|
||||
\s*\<\.\-\>\s* return 'LINK';
|
||||
\s*\<\-\.\-\>\s* return 'LINK';
|
||||
\s*[o]\-\.\-[o]\s* return 'LINK';
|
||||
\s*\-\-[o]\s* return 'LINK';
|
||||
\s*\-\-\-\s* return 'LINK';
|
||||
\s*\-\.\-[x]\s* return 'LINK';
|
||||
\s*\-\.\-\>\s* return 'LINK';
|
||||
\s*\-\.\-[o]\s* return 'LINK';
|
||||
\s*\-\.\-\s* return 'LINK';
|
||||
\s*.\-[x]\s* return 'LINK';
|
||||
\s*\.\-\>\s* return 'LINK';
|
||||
\s*\.\-[o]\s* return 'LINK';
|
||||
\s*\.\-\s* return 'LINK';
|
||||
\s*\=\=[x]\s* return 'LINK';
|
||||
\s*\=\=\>\s* return 'LINK';
|
||||
\s*\=\=[o]\s* return 'LINK';
|
||||
\s*\=\=[\=]\s* return 'LINK';
|
||||
\s*\<\-\-\s* return 'START_LINK';
|
||||
\s*[x]\-\-\s* return 'START_LINK';
|
||||
\s*[o]\-\-\s* return 'START_LINK';
|
||||
\s*\<\-\.\s* return 'START_LINK';
|
||||
\s*[x]\-\.\s* return 'START_LINK';
|
||||
\s*[o]\-\.\s* return 'START_LINK';
|
||||
\s*\<\=\=\s* return 'START_LINK';
|
||||
\s*[x]\=\=\s* return 'START_LINK';
|
||||
\s*[o]\=\=\s* return 'START_LINK';
|
||||
\s*\-\-\s* return 'START_LINK';
|
||||
\s*\-\.\s* return 'START_LINK';
|
||||
\s*\=\=\s* return 'START_LINK';
|
||||
"(-" return '(-';
|
||||
"-)" return '-)';
|
||||
"([" return 'STADIUMSTART';
|
||||
"])" return 'STADIUMEND';
|
||||
\- return 'MINUS';
|
||||
"." return 'DOT';
|
||||
[\_] return 'UNDERSCORE';
|
||||
@@ -92,12 +95,13 @@
|
||||
"<" return 'TAGSTART';
|
||||
">" return 'TAGEND';
|
||||
"^" return 'UP';
|
||||
"\|" return 'SEP';
|
||||
"v" return 'DOWN';
|
||||
[A-Za-z]+ return 'ALPHA';
|
||||
"\\]" return 'TRAPEND';
|
||||
"[/" return 'TRAPSTART';
|
||||
"/]" return 'INVTRAPEND';
|
||||
"[\\" return 'INVTRAPSTART';
|
||||
"/]" return 'INVTRAPEND';
|
||||
"[\\" return 'INVTRAPSTART';
|
||||
[!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION';
|
||||
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
||||
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
||||
@@ -245,7 +249,7 @@ spaceList
|
||||
|
||||
statement
|
||||
: verticeStatement separator
|
||||
{ $$=$1}
|
||||
{ /* console.warn('finat vs', $1.nodes); */ $$=$1.nodes}
|
||||
| styleStatement separator
|
||||
{$$=[];}
|
||||
| linkStyleStatement separator
|
||||
@@ -283,68 +287,49 @@ separator: NEWLINE | SEMI | EOF ;
|
||||
// {$$ = [$1];yy.setClass($1,$3)}
|
||||
// ;
|
||||
|
||||
verticeStatement: verticeStatement link node { yy.addLink($1[0],$3[0],$2); $$ = $3.concat($1) }
|
||||
|node { $$ = $1 }
|
||||
|
||||
verticeStatement: verticeStatement link node
|
||||
{ /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
|
||||
| verticeStatement link node spaceList
|
||||
{ /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
|
||||
|node spaceList {/*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
|
||||
|node { /*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
|
||||
;
|
||||
|
||||
node: vertex
|
||||
{ $$ = [$1];}
|
||||
{ /* console.warn('nod', $1); */ $$ = [$1];}
|
||||
| node spaceList vertex
|
||||
{ $$ = [$1[0], $3]; /*console.warn('pip', $1, $3, $$);*/ }
|
||||
| vertex STYLE_SEPARATOR idString
|
||||
{$$ = [$1];yy.setClass($1,$3)}
|
||||
;
|
||||
|
||||
vertex: idString SQS text SQE
|
||||
{$$ = $1;yy.addVertex($1,$3,'square');}
|
||||
| idString SQS text SQE spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'square');}
|
||||
| idString PS PS text PE PE
|
||||
{$$ = $1;yy.addVertex($1,$4,'circle');}
|
||||
| idString PS PS text PE PE spaceList
|
||||
{$$ = $1;yy.addVertex($1,$4,'circle');}
|
||||
| idString '(-' text '-)'
|
||||
{$$ = $1;yy.addVertex($1,$3,'ellipse');}
|
||||
| idString '(-' text '-)' spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'ellipse');}
|
||||
| idString STADIUMSTART text STADIUMEND
|
||||
{$$ = $1;yy.addVertex($1,$3,'stadium');}
|
||||
| idString PS text PE
|
||||
{$$ = $1;yy.addVertex($1,$3,'round');}
|
||||
| idString PS text PE spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'round');}
|
||||
| idString DIAMOND_START text DIAMOND_STOP
|
||||
{$$ = $1;yy.addVertex($1,$3,'diamond');}
|
||||
| idString DIAMOND_START text DIAMOND_STOP spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'diamond');}
|
||||
| idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP
|
||||
{$$ = $1;yy.addVertex($1,$4,'hexagon');}
|
||||
| idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP spaceList
|
||||
{$$ = $1;yy.addVertex($1,$4,'hexagon');}
|
||||
| idString TAGEND text SQE
|
||||
{$$ = $1;yy.addVertex($1,$3,'odd');}
|
||||
| idString TAGEND text SQE spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'odd');}
|
||||
| idString TRAPSTART text TRAPEND
|
||||
{$$ = $1;yy.addVertex($1,$3,'trapezoid');}
|
||||
| idString TRAPSTART text TRAPEND spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'trapezoid');}
|
||||
| idString INVTRAPSTART text INVTRAPEND
|
||||
{$$ = $1;yy.addVertex($1,$3,'inv_trapezoid');}
|
||||
| idString INVTRAPSTART text INVTRAPEND spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'inv_trapezoid');}
|
||||
| idString TRAPSTART text INVTRAPEND
|
||||
{$$ = $1;yy.addVertex($1,$3,'lean_right');}
|
||||
| idString TRAPSTART text INVTRAPEND spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'lean_right');}
|
||||
| idString INVTRAPSTART text TRAPEND
|
||||
{$$ = $1;yy.addVertex($1,$3,'lean_left');}
|
||||
| idString INVTRAPSTART text TRAPEND spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'lean_left');}
|
||||
/* | idString SQS text TAGSTART
|
||||
{$$ = $1;yy.addVertex($1,$3,'odd_right');}
|
||||
| idString SQS text TAGSTART spaceList
|
||||
{$$ = $1;yy.addVertex($1,$3,'odd_right');} */
|
||||
| idString
|
||||
{$$ = $1;yy.addVertex($1);}
|
||||
| idString spaceList
|
||||
{$$ = $1;yy.addVertex($1);}
|
||||
{ /*console.warn('h: ', $1);*/$$ = $1;yy.addVertex($1);}
|
||||
;
|
||||
|
||||
|
||||
@@ -357,92 +342,12 @@ link: linkStatement arrowText
|
||||
{$1.text = $2;$$ = $1;}
|
||||
| linkStatement
|
||||
{$$ = $1;}
|
||||
| '--' text ARROW_POINT
|
||||
{$$ = {"type":"arrow","stroke":"normal","text":$2};}
|
||||
| 'START_DOUBLE_ARROW_POINT' text ARROW_POINT
|
||||
{$$ = {"type":"double_arrow_point","stroke":"normal","text":$2};}
|
||||
| '--' text ARROW_CIRCLE
|
||||
{$$ = {"type":"arrow_circle","stroke":"normal","text":$2};}
|
||||
| 'START_DOUBLE_ARROW_CIRCLE' text ARROW_CIRCLE
|
||||
{$$ = {"type":"double_arrow_circle","stroke":"normal","text":$2};}
|
||||
| '--' text ARROW_CROSS
|
||||
{$$ = {"type":"arrow_cross","stroke":"normal","text":$2};}
|
||||
| 'START_DOUBLE_ARROW_CROSS' text ARROW_CROSS
|
||||
{$$ = {"type":"double_arrow_cross","stroke":"normal","text":$2};}
|
||||
| '--' text ARROW_OPEN
|
||||
{$$ = {"type":"arrow_open","stroke":"normal","text":$2};}
|
||||
| '-.' text DOTTED_ARROW_POINT
|
||||
{$$ = {"type":"arrow","stroke":"dotted","text":$2};}
|
||||
| 'START_DOUBLE_DOTTED_ARROW_POINT' text DOTTED_ARROW_POINT
|
||||
{$$ = {"type":"double_arrow_point","stroke":"dotted","text":$2};}
|
||||
| '-.' text DOTTED_ARROW_CIRCLE
|
||||
{$$ = {"type":"arrow_circle","stroke":"dotted","text":$2};}
|
||||
| 'START_DOUBLE_DOTTED_ARROW_CIRCLE' text DOTTED_ARROW_CIRCLE
|
||||
{$$ = {"type":"double_arrow_circle","stroke":"dotted","text":$2};}
|
||||
| '-.' text DOTTED_ARROW_CROSS
|
||||
{$$ = {"type":"arrow_cross","stroke":"dotted","text":$2};}
|
||||
| 'START_DOUBLE_DOTTED_ARROW_CROSS' text DOTTED_ARROW_CROSS
|
||||
{$$ = {"type":"double_arrow_cross","stroke":"dotted","text":$2};}
|
||||
| '-.' text DOTTED_ARROW_OPEN
|
||||
{$$ = {"type":"arrow_open","stroke":"dotted","text":$2};}
|
||||
| '==' text THICK_ARROW_POINT
|
||||
{$$ = {"type":"arrow","stroke":"thick","text":$2};}
|
||||
| 'START_DOUBLE_THICK_ARROW_POINT' text THICK_ARROW_POINT
|
||||
{$$ = {"type":"double_arrow_point","stroke":"thick","text":$2};}
|
||||
| '==' text THICK_ARROW_CIRCLE
|
||||
{$$ = {"type":"arrow_circle","stroke":"thick","text":$2};}
|
||||
| 'START_DOUBLE_THICK_ARROW_CIRCLE' text THICK_ARROW_CIRCLE
|
||||
{$$ = {"type":"double_arrow_circle","stroke":"thick","text":$2};}
|
||||
| '==' text THICK_ARROW_CROSS
|
||||
{$$ = {"type":"arrow_cross","stroke":"thick","text":$2};}
|
||||
| 'START_DOUBLE_THICK_ARROW_CROSS' text THICK_ARROW_CROSS
|
||||
{$$ = {"type":"double_arrow_cross","stroke":"thick","text":$2};}
|
||||
| '==' text THICK_ARROW_OPEN
|
||||
{$$ = {"type":"arrow_open","stroke":"thick","text":$2};}
|
||||
| START_LINK text LINK
|
||||
{var inf = yy.destructLink($3, $1); $$ = {"type":inf.type,"stroke":inf.stroke,"text":$2};}
|
||||
;
|
||||
|
||||
linkStatement: ARROW_POINT
|
||||
{$$ = {"type":"arrow","stroke":"normal"};}
|
||||
| DOUBLE_ARROW_POINT
|
||||
{$$ = {"type":"double_arrow_point","stroke":"normal"};}
|
||||
| ARROW_CIRCLE
|
||||
{$$ = {"type":"arrow_circle","stroke":"normal"};}
|
||||
| DOUBLE_ARROW_CIRCLE
|
||||
{$$ = {"type":"double_arrow_circle","stroke":"normal"};}
|
||||
| ARROW_CROSS
|
||||
{$$ = {"type":"arrow_cross","stroke":"normal"};}
|
||||
| DOUBLE_ARROW_CROSS
|
||||
{$$ = {"type":"double_arrow_cross","stroke":"normal"};}
|
||||
| ARROW_OPEN
|
||||
{$$ = {"type":"arrow_open","stroke":"normal"};}
|
||||
| DOTTED_ARROW_POINT
|
||||
{$$ = {"type":"arrow","stroke":"dotted"};}
|
||||
| DOUBLE_DOTTED_ARROW_POINT
|
||||
{$$ = {"type":"double_arrow_point","stroke":"dotted"};}
|
||||
| DOTTED_ARROW_CIRCLE
|
||||
{$$ = {"type":"arrow_circle","stroke":"dotted"};}
|
||||
| DOUBLE_DOTTED_ARROW_CIRCLE
|
||||
{$$ = {"type":"double_arrow_circle","stroke":"dotted"};}
|
||||
| DOTTED_ARROW_CROSS
|
||||
{$$ = {"type":"arrow_cross","stroke":"dotted"};}
|
||||
| DOUBLE_DOTTED_ARROW_CROSS
|
||||
{$$ = {"type":"double_arrow_cross","stroke":"dotted"};}
|
||||
| DOTTED_ARROW_OPEN
|
||||
{$$ = {"type":"arrow_open","stroke":"dotted"};}
|
||||
| THICK_ARROW_POINT
|
||||
{$$ = {"type":"arrow","stroke":"thick"};}
|
||||
| DOUBLE_THICK_ARROW_POINT
|
||||
{$$ = {"type":"double_arrow_point","stroke":"thick"};}
|
||||
| THICK_ARROW_CIRCLE
|
||||
{$$ = {"type":"arrow_circle","stroke":"thick"};}
|
||||
| DOUBLE_THICK_ARROW_CIRCLE
|
||||
{$$ = {"type":"double_arrow_circle","stroke":"thick"};}
|
||||
| THICK_ARROW_CROSS
|
||||
{$$ = {"type":"arrow_cross","stroke":"thick"};}
|
||||
| DOUBLE_THICK_ARROW_CROSS
|
||||
{$$ = {"type":"double_arrow_cross","stroke":"thick"};}
|
||||
| THICK_ARROW_OPEN
|
||||
{$$ = {"type":"arrow_open","stroke":"thick"};}
|
||||
linkStatement: LINK
|
||||
{var inf = yy.destructLink($1);$$ = {"type":inf.type,"stroke":inf.stroke};}
|
||||
;
|
||||
|
||||
arrowText:
|
||||
@@ -530,7 +435,7 @@ styleComponent: ALPHA | COLON | MINUS | NUM | UNIT | SPACE | HEX | BRKT | DOT |
|
||||
|
||||
/* Token lists */
|
||||
|
||||
textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT | DEFAULT;
|
||||
textToken : textNoTagsToken | TAGSTART | TAGEND | START_LINK | PCT | DEFAULT;
|
||||
|
||||
textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ;
|
||||
|
||||
@@ -563,5 +468,5 @@ alphaNumToken : PUNCTUATION | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | PLUS
|
||||
|
||||
idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION;
|
||||
|
||||
graphCodeTokens: TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI ;
|
||||
graphCodeTokens: STADIUMSTART | STADIUMEND | TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI;
|
||||
%%
|
||||
|
@@ -16,6 +16,7 @@ describe('when parsing subgraphs', function() {
|
||||
const subgraphs = flow.parser.yy.getSubGraphs();
|
||||
expect(subgraphs.length).toBe(1);
|
||||
const subgraph = subgraphs[0];
|
||||
|
||||
expect(subgraph.nodes.length).toBe(2);
|
||||
expect(subgraph.nodes[0]).toBe('a2');
|
||||
expect(subgraph.nodes[1]).toBe('a1');
|
||||
@@ -191,6 +192,15 @@ describe('when parsing subgraphs', function() {
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
});
|
||||
|
||||
it('should handle subgraphs3', function() {
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle \n\n c-->d \nend\n');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
});
|
||||
|
||||
it('should handle nested subgraphs', function() {
|
||||
const str =
|
||||
'graph TD\n' +
|
||||
@@ -218,6 +228,14 @@ describe('when parsing subgraphs', function() {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
});
|
||||
it('should handle subgraphs with multi node statements in it', function() {
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\na b --> c e\n end;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
});
|
||||
});
|
||||
|
@@ -134,18 +134,32 @@ const getStartDate = function(prevTime, dateFormat, str) {
|
||||
str = str.trim();
|
||||
|
||||
// Test for after
|
||||
const re = /^after\s+([\d\w-]+)/;
|
||||
const re = /^after\s+([\d\w- ]+)/;
|
||||
const afterStatement = re.exec(str.trim());
|
||||
|
||||
if (afterStatement !== null) {
|
||||
const task = findTaskById(afterStatement[1]);
|
||||
// check all after ids and take the latest
|
||||
let latestEndingTask = null;
|
||||
afterStatement[1].split(' ').forEach(function(id) {
|
||||
let task = findTaskById(id);
|
||||
if (typeof task !== 'undefined') {
|
||||
if (!latestEndingTask) {
|
||||
latestEndingTask = task;
|
||||
} else {
|
||||
if (task.endTime > latestEndingTask.endTime) {
|
||||
latestEndingTask = task;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof task === 'undefined') {
|
||||
if (!latestEndingTask) {
|
||||
const dt = new Date();
|
||||
dt.setHours(0, 0, 0, 0);
|
||||
return dt;
|
||||
} else {
|
||||
return latestEndingTask.endTime;
|
||||
}
|
||||
return task.endTime;
|
||||
}
|
||||
|
||||
// Check for actual date set
|
||||
|
@@ -302,6 +302,7 @@ export const draw = function(txt, id, ver) {
|
||||
try {
|
||||
const parser = gitGraphParser.parser;
|
||||
parser.yy = db;
|
||||
parser.yy.clear();
|
||||
|
||||
logger.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver);
|
||||
// Parse the graph definition
|
||||
|
@@ -49,7 +49,7 @@ line
|
||||
|
||||
statement
|
||||
: STR VALUE {
|
||||
console.log('str:'+$1+' value: '+$2)
|
||||
/*console.log('str:'+$1+' value: '+$2)*/
|
||||
yy.addSection($1,yy.cleanupValue($2)); }
|
||||
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
|
||||
;
|
||||
|
@@ -333,6 +333,34 @@ describe('when parsing a sequenceDiagram', function() {
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('John');
|
||||
});
|
||||
it('it should handle different line breaks', function() {
|
||||
const str =
|
||||
'sequenceDiagram\n' +
|
||||
'participant 1 as multiline<br>text\n' +
|
||||
'participant 2 as multiline<br/>text\n' +
|
||||
'participant 3 as multiline<br />text\n' +
|
||||
'1->>2: multiline<br>text\n' +
|
||||
'note right of 2: multiline<br>text\n' +
|
||||
'2->>3: multiline<br/>text\n' +
|
||||
'note right of 3: multiline<br/>text\n' +
|
||||
'3->>1: multiline<br />text\n' +
|
||||
'note right of 1: multiline<br />text\n';
|
||||
|
||||
parser.parse(str);
|
||||
|
||||
const actors = parser.yy.getActors();
|
||||
expect(actors['1'].description).toBe('multiline<br>text');
|
||||
expect(actors['2'].description).toBe('multiline<br/>text');
|
||||
expect(actors['3'].description).toBe('multiline<br />text');
|
||||
|
||||
const messages = parser.yy.getMessages();
|
||||
expect(messages[0].message).toBe('multiline<br>text');
|
||||
expect(messages[1].message).toBe('multiline<br>text');
|
||||
expect(messages[2].message).toBe('multiline<br/>text');
|
||||
expect(messages[3].message).toBe('multiline<br/>text');
|
||||
expect(messages[4].message).toBe('multiline<br />text');
|
||||
expect(messages[5].message).toBe('multiline<br />text');
|
||||
});
|
||||
it('it should handle notes over a single actor', function() {
|
||||
const str =
|
||||
'sequenceDiagram\n' + 'Alice->Bob: Hello Bob, how are you?\n' + 'Note over Bob: Bob thinks\n';
|
||||
|
@@ -168,7 +168,7 @@ export const bounds = {
|
||||
|
||||
const _drawLongText = (text, x, y, g, width) => {
|
||||
let textHeight = 0;
|
||||
const lines = text.split(/<br\/?>/gi);
|
||||
const lines = text.split(/<br ?\/?>/gi);
|
||||
for (const line of lines) {
|
||||
const textObj = svgDraw.getTextObj();
|
||||
textObj.x = x;
|
||||
@@ -233,7 +233,7 @@ const drawMessage = function(elem, startx, stopx, verticalPos, msg, sequenceInde
|
||||
let textElem;
|
||||
let counterBreaklines = 0;
|
||||
let breaklineOffset = 17;
|
||||
const breaklines = msg.message.split(/<br\/?>/gi);
|
||||
const breaklines = msg.message.split(/<br ?\/?>/gi);
|
||||
for (const breakline of breaklines) {
|
||||
textElem = g
|
||||
.append('text') // text label for the x axis
|
||||
|
@@ -18,7 +18,7 @@ export const drawRect = function(elem, rectData) {
|
||||
|
||||
export const drawText = function(elem, textData) {
|
||||
// Remove and ignore br:s
|
||||
const nText = textData.text.replace(/<br\/?>/gi, ' ');
|
||||
const nText = textData.text.replace(/<br ?\/?>/gi, ' ');
|
||||
|
||||
const textElem = elem.append('text');
|
||||
textElem.attr('x', textData.x);
|
||||
@@ -321,7 +321,7 @@ const _drawTextCandidateFunc = (function() {
|
||||
function byTspan(content, g, x, y, width, height, textAttrs, conf) {
|
||||
const { actorFontSize, actorFontFamily } = conf;
|
||||
|
||||
const lines = content.split(/<br\/?>/gi);
|
||||
const lines = content.split(/<br ?\/?>/gi);
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const dy = i * actorFontSize - (actorFontSize * (lines.length - 1)) / 2;
|
||||
const text = g
|
||||
|
@@ -23,23 +23,34 @@ export const setLogLevel = function(level) {
|
||||
logger.error = () => {};
|
||||
logger.fatal = () => {};
|
||||
if (level <= LEVELS.fatal) {
|
||||
logger.fatal = console.log.bind(console, '\x1b[35m', format('FATAL'));
|
||||
logger.fatal = console.error
|
||||
? console.error.bind(console, format('FATAL'), 'color: orange')
|
||||
: console.log.bind(console, '\x1b[35m', format('FATAL'));
|
||||
}
|
||||
if (level <= LEVELS.error) {
|
||||
logger.error = console.log.bind(console, '\x1b[31m', format('ERROR'));
|
||||
logger.error = console.error
|
||||
? console.error.bind(console, format('ERROR'), 'color: orange')
|
||||
: console.log.bind(console, '\x1b[31m', format('ERROR'));
|
||||
}
|
||||
if (level <= LEVELS.warn) {
|
||||
logger.warn = console.log.bind(console, `\x1b[33m`, format('WARN'));
|
||||
logger.warn = console.warn
|
||||
? console.warn.bind(console, format('WARN'), 'color: orange')
|
||||
: console.log.bind(console, `\x1b[33m`, format('WARN'));
|
||||
}
|
||||
if (level <= LEVELS.info) {
|
||||
logger.info = console.log.bind(console, '\x1b[34m', format('INFO'));
|
||||
logger.info = console.info
|
||||
? // ? console.info.bind(console, '\x1b[34m', format('INFO'), 'color: blue')
|
||||
console.info.bind(console, format('INFO'), 'color: lightblue')
|
||||
: console.log.bind(console, '\x1b[34m', format('INFO'));
|
||||
}
|
||||
if (level <= LEVELS.debug) {
|
||||
logger.debug = console.log.bind(console, '\x1b[32m', format('DEBUG'));
|
||||
logger.debug = console.debug
|
||||
? console.debug.bind(console, format('DEBUG'), 'color: lightgreen')
|
||||
: console.log.bind(console, '\x1b[32m', format('DEBUG'));
|
||||
}
|
||||
};
|
||||
|
||||
const format = level => {
|
||||
const time = moment().format('HH:mm:ss.SSS');
|
||||
return `${time} : ${level} : `;
|
||||
const time = moment().format('ss.SSS');
|
||||
return `%c${time} : ${level} : `;
|
||||
};
|
||||
|
@@ -116,7 +116,6 @@ const init = function() {
|
||||
};
|
||||
|
||||
const initialize = function(config) {
|
||||
logger.debug('Initializing mermaid ');
|
||||
if (typeof config.mermaid !== 'undefined') {
|
||||
if (typeof config.mermaid.startOnLoad !== 'undefined') {
|
||||
mermaid.startOnLoad = config.mermaid.startOnLoad;
|
||||
@@ -126,6 +125,7 @@ const initialize = function(config) {
|
||||
}
|
||||
}
|
||||
mermaidAPI.initialize(config);
|
||||
logger.debug('Initializing mermaid ');
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -54,7 +54,7 @@
|
||||
|
||||
.grid .tick {
|
||||
stroke: $gridColor;
|
||||
opacity: 0.3;
|
||||
opacity: 0.8;
|
||||
shape-rendering: crispEdges;
|
||||
text {
|
||||
font-family: 'trebuchet ms', verdana, arial;
|
||||
|
Reference in New Issue
Block a user