Skip to content

Commit

Permalink
#5237 WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ashishjain0512 committed Apr 26, 2024
1 parent a2702e4 commit dd5bfb3
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 7 deletions.
12 changes: 10 additions & 2 deletions cypress/platform/knsv2.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,16 @@
<body>
<pre id="diagram" class="mermaid">
stateDiagram-v2
Second --> Third
Second --> Fourth
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 --> [*]
</pre
>
<pre id="diagram" class="mermaid2">
Expand Down
2 changes: 2 additions & 0 deletions packages/mermaid/src/diagrams/state/stateCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const G_EDGE_LABELTYPE = 'text';
export const G_EDGE_THICKNESS = 'normal';

export const CSS_EDGE = 'transition';
export const CSS_DIAGRAM = 'statediagram';

export default {
DEFAULT_DIAGRAM_DIRECTION,
Expand All @@ -44,4 +45,5 @@ export default {
G_EDGE_LABELTYPE,
G_EDGE_THICKNESS,
CSS_EDGE,
CSS_DIAGRAM,
};
32 changes: 30 additions & 2 deletions packages/mermaid/src/diagrams/state/stateDb.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
G_EDGE_THICKNESS,
CSS_EDGE,
} from './stateCommon.js';
import { rect } from 'dagre-d3-es/src/dagre-js/intersect/index.js';

const START_NODE = '[*]';
const START_TYPE = 'start';
Expand Down Expand Up @@ -555,17 +556,44 @@ const dataFetcher = (parentId, doc, nodes, edges) => {

stateKeys.forEach((key) => {
const item = currentDocument.states[key];
console.log('Item:', item);

Check failure on line 559 in packages/mermaid/src/diagrams/state/stateDb.js

View workflow job for this annotation

GitHub Actions / lint (18.x)

Unexpected console statement

let itemShape = 'rect';
if (item.type === 'default' && item.id === 'root_start') {
itemShape = 'stateStart';
}
if (item.type === 'default' && item.id === 'root_end') {
itemShape = 'stateEnd';
}

if (item.type === 'fork' || item.type === 'join') {
itemShape = 'forkJoin';
}

if (item.type === 'choice') {
itemShape = 'choice';
}

if (item.id === '</choice>' && item.type === 'default') {
//ignore this item
return;
}

if (item.id === '</join></fork>' && item.type === 'default') {
//ignore this item
return;
}

if (parentId) {
nodes.push({ ...item, labelText: item.id, labelType: 'text', parentId, shape: 'rect' });
nodes.push({ ...item, labelText: item.id, labelType: 'text', parentId, shape: itemShape });
} else {
nodes.push({
...item,
labelText: item.id,
// description: item.id,
labelType: 'text',
labelStyle: '',
shape: 'rect',
shape: itemShape,
padding: 15,
classes: ' statediagram-state',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import { render } from '../../rendering-util/render.js';
import insertElementsForSize, {
getDiagramElements,
} from '../../rendering-util/inserElementsForSize.js';
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
import {
DEFAULT_DIAGRAM_DIRECTION,
DEFAULT_NESTED_DOC_DIR,
STMT_STATE,
STMT_RELATION,
DEFAULT_STATE_TYPE,
DIVIDER_TYPE,
CSS_DIAGRAM,
} from './stateCommon.js';

// Configuration
Expand Down Expand Up @@ -93,6 +95,8 @@ export const draw = async function (text: string, id: string, _version: string,
data4Layout.diagramId = id;
console.log('REF1:', data4Layout);
await render(data4Layout, svg, element);
const padding = 8;
setupViewPortForSVG(svg, padding, CSS_DIAGRAM, conf.useMaxWidth);
};

export default {
Expand Down
12 changes: 10 additions & 2 deletions packages/mermaid/src/rendering-util/rendering-elements/nodes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { log } from '$root/logger.js';
import { rect } from './shapes/rect.js';
import { rect } from './shapes/rect.ts';
import { stateStart } from './shapes/stateStart.ts';
import { stateEnd } from './shapes/stateEnd.ts';
import { forkJoin } from './shapes/forkJoin.ts';
import { choice } from './shapes/choice.ts';
import { getConfig } from '$root/diagram-api/diagramAPI.js';

const formatClass = (str) => {
Expand All @@ -11,6 +15,10 @@ const formatClass = (str) => {

const shapes = {
rect,
stateStart,
stateEnd,
forkJoin,
choice,
};

let nodeElems = {};
Expand All @@ -19,9 +27,9 @@ export const insertNode = async (elem, node, dir) => {
let newEl;
let el;

console.log('insertNode element', elem, elem.node(), rect);
// debugger;
// Add link when appropriate
console.log('node.link', node.link);
if (node.link) {
let target;
if (getConfig().securityLevel === 'sandbox') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import intersect from '../intersect/index.js';
import type { Node } from '$root/rendering-util/types.d.ts';
import type { SVG } from '$root/diagram-api/types.js';

export const choice = (parent: SVG, node: Node) => {
const shapeSvg = parent
.insert('g')
.attr('class', 'node default')
.attr('id', node.domId || node.id);

const s = 28;
const points = [
{ x: 0, y: s / 2 },
{ x: s / 2, y: 0 },
{ x: 0, y: -s / 2 },
{ x: -s / 2, y: 0 },
];

const choice = shapeSvg.insert('polygon', ':first-child').attr(
'points',
points
.map(function (d) {
return d.x + ',' + d.y;
})
.join(' ')
);
// center the circle around its coordinate
choice.attr('class', 'state-start').attr('r', 7).attr('width', 28).attr('height', 28);
node.width = 28;
node.height = 28;

node.intersect = function (point) {
return intersect.circle(node, 14, point);
};

return shapeSvg;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { log } from '$root/logger.js';
import { updateNodeBounds } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '$root/rendering-util/types.d.ts';
import type { SVG } from '$root/diagram-api/types.js';

export const forkJoin = (parent: SVG, node: Node, dir: string) => {
const shapeSvg = parent
.insert('g')
.attr('class', 'node default')
.attr('id', node.domId || node.id);

let width = 70;
let height = 10;

if (dir === 'LR') {
width = 10;
height = 70;
}

const shape = shapeSvg
.append('rect')
.attr('x', (-1 * width) / 2)
.attr('y', (-1 * height) / 2)
.attr('width', width)
.attr('height', height)
.attr('class', 'fork-join');

updateNodeBounds(node, shape);
let nodeHeight = 0;
let nodeWidth = 0;
let nodePadding = 10;
if (node.height) {
nodeHeight = node.height;
}
if (node.width) {
nodeWidth = node.width;
}

if (node.padding) {
nodePadding = node.padding;
}

node.height = nodeHeight + nodePadding / 2;
node.width = nodeWidth + nodePadding / 2;
node.intersect = function (point) {
return intersect.rect(node, point);
};

return shapeSvg;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import intersect from '../intersect/index.js';
import type { Node } from '$root/rendering-util/types.d.ts';
import rough from 'roughjs';
import { select } from 'd3';

/**
*
* @param rect
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { log } from '$root/logger.js';
import { updateNodeBounds } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '$root/rendering-util/types.d.ts';
import type { SVG } from '$root/diagram-api/types.js';

export const stateEnd = (parent: SVG, node: Node) => {
const shapeSvg = parent
.insert('g')
.attr('class', 'node default')
.attr('id', node.domId || node.id);
const innerCircle = shapeSvg.insert('circle', ':first-child');
const circle = shapeSvg.insert('circle', ':first-child');

circle.attr('class', 'state-start').attr('r', 7).attr('width', 14).attr('height', 14);

innerCircle.attr('class', 'state-end').attr('r', 5).attr('width', 10).attr('height', 10);

updateNodeBounds(node, circle);

node.intersect = function (point) {
return intersect.circle(node, 7, point);
};

return shapeSvg;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { log } from '$root/logger.js';
import { updateNodeBounds } from './util.js';
import intersect from '../intersect/index.js';
import type { Node } from '$root/rendering-util/types.d.ts';
import type { SVG } from '$root/diagram-api/types.js';

export const stateStart = (parent: SVG, node: Node) => {
const shapeSvg = parent
.insert('g')
.attr('class', 'node default')
.attr('id', node.domId || node.id);
const circle = shapeSvg.insert('circle', ':first-child');

// center the circle around its coordinate
circle.attr('class', 'state-start').attr('r', 7).attr('width', 14).attr('height', 14);

updateNodeBounds(node, circle);

node.intersect = function (point) {
return intersect.circle(node, 7, point);
};

return shapeSvg;
};
40 changes: 40 additions & 0 deletions packages/mermaid/src/rendering-util/setupViewPortForSVG.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { configureSvgSize } from '$root/setupGraphViewbox.js';
import type { SVG } from '$root/diagram-api/types.js';
import { log } from '$root/logger.js';

export const setupViewPortForSVG = (
svg: SVG,
padding: number,
cssDiagram: string,
useMaxWidth: boolean
) => {
// Initialize the SVG element and set the diagram class
svg.attr('class', cssDiagram);

// Calculate the dimensions and position with padding
const { width, height, x, y } = calculateDimensionsWithPadding(svg, padding);

// Configure the size and aspect ratio of the SVG
configureSvgSize(svg, height, width, useMaxWidth);

// Update the viewBox to ensure all content is visible with padding
const viewBox = createViewBox(x, y, width, height, padding);
svg.attr('viewBox', viewBox);

// Log the viewBox configuration for debugging
log.debug(`viewBox configured: ${viewBox}`);
};

const calculateDimensionsWithPadding = (svg: SVG, padding: number) => {
const bounds = svg.node()?.getBBox() || { width: 0, height: 0, x: 0, y: 0 };
return {
width: bounds.width + padding * 2,
height: bounds.height + padding * 2,
x: bounds.x,
y: bounds.y,
};
};

const createViewBox = (x: number, y: number, width: number, height: number, padding: number) => {
return `${x - padding} ${y - padding} ${width} ${height}`;
};
4 changes: 3 additions & 1 deletion packages/mermaid/src/rendering-util/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ interface Node {
tooltip?: string;
type: string;
width?: number;
intersect?: (point: any) => any;
height?: number;

// Specific properties for State Diagram nodes TODO remove and use generic properties
intersect?: (point: any) => any;
style?: string;
class?: string;
borders?: string;
Expand Down

0 comments on commit dd5bfb3

Please sign in to comment.