mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
#5237 Adding new rendering for flowcharts
This commit is contained in:
parent
7da85b9005
commit
fa6bcd8b30
@ -136,15 +136,19 @@ sequenceDiagram
|
|||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
|
|
||||||
<pre id="diagram" class="mermaid">
|
<pre id="diagram" class="mermaid2">
|
||||||
%%{init: {"layout": "elk", "mergeEdges": true} }%%
|
%%{init: {"layout": "elk", "mergeEdges": true} }%%
|
||||||
stateDiagram
|
stateDiagram
|
||||||
direction TB
|
A --> B
|
||||||
T00 --> T0
|
|
||||||
T00 --> T1
|
|
||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram" class="mermaid">
|
<pre id="diagram" class="mermaid">
|
||||||
|
%%{init: {"layout": "elk", "mergeEdges": true} }%%
|
||||||
|
flowchart
|
||||||
|
A --> B(This is B)
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<pre id="diagram" class="mermaid2">
|
||||||
%%{init: {"layout": "elk", "mergeEdges": false, "elk.nodePlacement.strategy": "NETWORK_SIMPLEX"} }%%
|
%%{init: {"layout": "elk", "mergeEdges": false, "elk.nodePlacement.strategy": "NETWORK_SIMPLEX"} }%%
|
||||||
stateDiagram
|
stateDiagram
|
||||||
State T0 {
|
State T0 {
|
||||||
|
@ -1135,8 +1135,6 @@ export const insertNode = async (elem, node, dir) => {
|
|||||||
let newEl;
|
let newEl;
|
||||||
let el;
|
let el;
|
||||||
|
|
||||||
console.log('insertNode element', elem, elem.node());
|
|
||||||
// debugger;
|
|
||||||
// Add link when appropriate
|
// Add link when appropriate
|
||||||
if (node.link) {
|
if (node.link) {
|
||||||
let target;
|
let target;
|
||||||
|
@ -2,6 +2,7 @@ import { select } from 'd3';
|
|||||||
import utils from '../../utils.js';
|
import utils from '../../utils.js';
|
||||||
import { getConfig, defaultConfig } from '../../diagram-api/diagramAPI.js';
|
import { getConfig, defaultConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
import common from '../common/common.js';
|
import common from '../common/common.js';
|
||||||
|
import type { LayoutData, LayoutMethod, Node, Edge } from '../../rendering-util/types.js';
|
||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import {
|
import {
|
||||||
setAccTitle,
|
setAccTitle,
|
||||||
@ -755,11 +756,53 @@ export const lex = {
|
|||||||
firstGraph,
|
firstGraph,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getTypeFromVertex = (vertex: FlowVertex) => {
|
||||||
|
if (vertex.type === 'square') {
|
||||||
|
return 'squareRect';
|
||||||
|
}
|
||||||
|
if (vertex.type === 'round') {
|
||||||
|
return 'roundedRect';
|
||||||
|
}
|
||||||
|
|
||||||
|
return vertex.type || 'squareRect';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getData = () => {
|
||||||
|
const config = getConfig();
|
||||||
|
const nodes: Node[] = [];
|
||||||
|
const edges: Edge[] = [];
|
||||||
|
|
||||||
|
// extract(getRootDocV2());
|
||||||
|
// const diagramStates = getStates();
|
||||||
|
const n = getVertices();
|
||||||
|
n.forEach((vertex) => {
|
||||||
|
const node: Node = {
|
||||||
|
id: vertex.id,
|
||||||
|
label: vertex.text,
|
||||||
|
labelStyle: '',
|
||||||
|
padding: config.flowchart?.padding || 8,
|
||||||
|
cssStyles: vertex.styles.join(' '),
|
||||||
|
cssClasses: vertex.classes.join(' '),
|
||||||
|
shape: getTypeFromVertex(vertex),
|
||||||
|
dir: vertex.dir,
|
||||||
|
domId: vertex.domId,
|
||||||
|
type: undefined,
|
||||||
|
isGroup: false,
|
||||||
|
};
|
||||||
|
nodes.push(node);
|
||||||
|
});
|
||||||
|
|
||||||
|
const useRough = config.look === 'handdrawn';
|
||||||
|
|
||||||
|
return { nodes, edges, other: {}, config };
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
defaultConfig: () => defaultConfig.flowchart,
|
defaultConfig: () => defaultConfig.flowchart,
|
||||||
setAccTitle,
|
setAccTitle,
|
||||||
getAccTitle,
|
getAccTitle,
|
||||||
getAccDescription,
|
getAccDescription,
|
||||||
|
getData,
|
||||||
setAccDescription,
|
setAccDescription,
|
||||||
addVertex,
|
addVertex,
|
||||||
lookUpDomId,
|
lookUpDomId,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// @ts-ignore: JISON doesn't support types
|
// @ts-ignore: JISON doesn't support types
|
||||||
import flowParser from './parser/flow.jison';
|
import flowParser from './parser/flow.jison';
|
||||||
import flowDb from './flowDb.js';
|
import flowDb from './flowDb.js';
|
||||||
import flowRendererV2 from './flowRenderer-v2.js';
|
// import flowRendererV2 from './flowRenderer-v2.js';
|
||||||
|
import flowRendererV3 from './flowRenderer-v3-unified.js';
|
||||||
import flowStyles from './styles.js';
|
import flowStyles from './styles.js';
|
||||||
import type { MermaidConfig } from '../../config.type.js';
|
import type { MermaidConfig } from '../../config.type.js';
|
||||||
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
@ -9,7 +10,8 @@ import { setConfig } from '../../diagram-api/diagramAPI.js';
|
|||||||
export const diagram = {
|
export const diagram = {
|
||||||
parser: flowParser,
|
parser: flowParser,
|
||||||
db: flowDb,
|
db: flowDb,
|
||||||
renderer: flowRendererV2,
|
// renderer: flowRendererV2,
|
||||||
|
renderer: flowRendererV3,
|
||||||
styles: flowStyles,
|
styles: flowStyles,
|
||||||
init: (cnf: MermaidConfig) => {
|
init: (cnf: MermaidConfig) => {
|
||||||
if (!cnf.flowchart) {
|
if (!cnf.flowchart) {
|
||||||
@ -18,7 +20,7 @@ export const diagram = {
|
|||||||
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
// flowchart-v2 uses dagre-wrapper, which doesn't have access to flowchart cnf
|
// flowchart-v2 uses dagre-wrapper, which doesn't have access to flowchart cnf
|
||||||
setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } });
|
setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } });
|
||||||
flowRendererV2.setConf(cnf.flowchart);
|
flowRendererV3.setConf(cnf.flowchart);
|
||||||
flowDb.clear();
|
flowDb.clear();
|
||||||
flowDb.setGen('gen-2');
|
flowDb.setGen('gen-2');
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
// @ts-ignore: JISON doesn't support types
|
||||||
|
import flowParser from './parser/flow.jison';
|
||||||
|
import flowDb from './flowDb.js';
|
||||||
|
import flowRendererV2 from './flowRenderer-v2.js';
|
||||||
|
import flowStyles from './styles.js';
|
||||||
|
import type { MermaidConfig } from '../../config.type.js';
|
||||||
|
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
|
|
||||||
|
export const diagram = {
|
||||||
|
parser: flowParser,
|
||||||
|
db: flowDb,
|
||||||
|
renderer: flowRendererV2,
|
||||||
|
styles: flowStyles,
|
||||||
|
init: (cnf: MermaidConfig) => {
|
||||||
|
if (!cnf.flowchart) {
|
||||||
|
cnf.flowchart = {};
|
||||||
|
}
|
||||||
|
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
|
// flowchart-v2 uses dagre-wrapper, which doesn't have access to flowchart cnf
|
||||||
|
setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } });
|
||||||
|
flowRendererV2.setConf(cnf.flowchart);
|
||||||
|
flowDb.clear();
|
||||||
|
flowDb.setGen('gen-2');
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,81 @@
|
|||||||
|
import { log } from '../../logger.js';
|
||||||
|
import type { DiagramStyleClassDef } from '../../diagram-api/types.js';
|
||||||
|
import type { LayoutData, LayoutMethod } from '../../rendering-util/types.js';
|
||||||
|
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
|
import { render } from '../../rendering-util/render.js';
|
||||||
|
import { getDiagramElements } from '../../rendering-util/inserElementsForSize.js';
|
||||||
|
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
|
||||||
|
import { getDirection } from './flowDb.js';
|
||||||
|
|
||||||
|
import utils from '../../utils.js';
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
const conf: Record<string, any> = {};
|
||||||
|
|
||||||
|
export const setConf = function (cnf: Record<string, any>) {
|
||||||
|
const keys = Object.keys(cnf);
|
||||||
|
for (const key of keys) {
|
||||||
|
conf[key] = cnf[key];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getClasses = function (
|
||||||
|
text: string,
|
||||||
|
diagramObj: any
|
||||||
|
): Record<string, DiagramStyleClassDef> {
|
||||||
|
// diagramObj.db.extract(diagramObj.db.getRootDocV2());
|
||||||
|
return diagramObj.db.getClasses();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const draw = async function (text: string, id: string, _version: string, diag: any) {
|
||||||
|
log.info('REF0:');
|
||||||
|
log.info('Drawing state diagram (v2)', id);
|
||||||
|
const { securityLevel, state: conf, layout } = getConfig();
|
||||||
|
|
||||||
|
const DIR = getDirection();
|
||||||
|
|
||||||
|
// The getData method provided in all supported diagrams is used to extract the data from the parsed structure
|
||||||
|
// into the Layout data format
|
||||||
|
console.log('Before getData: ');
|
||||||
|
const data4Layout = diag.db.getData() as LayoutData;
|
||||||
|
console.log('Data: ', data4Layout);
|
||||||
|
// Create the root SVG - the element is the div containing the SVG element
|
||||||
|
const { element, svg } = getDiagramElements(id, securityLevel);
|
||||||
|
|
||||||
|
// // For some diagrams this call is not needed, but in the state diagram it is
|
||||||
|
// await insertElementsForSize(element, data4Layout);
|
||||||
|
|
||||||
|
// console.log('data4Layout:', data4Layout);
|
||||||
|
|
||||||
|
// // Now we have layout data with real sizes, we can perform the layout
|
||||||
|
// const data4Rendering = doLayout(data4Layout, id, _version, 'dagre-wrapper');
|
||||||
|
|
||||||
|
// // The performRender method provided in all supported diagrams is used to render the data
|
||||||
|
// performRender(data4Rendering);
|
||||||
|
|
||||||
|
data4Layout.type = diag.type;
|
||||||
|
// data4Layout.layoutAlgorithm = 'dagre-wrapper';
|
||||||
|
// data4Layout.layoutAlgorithm = 'elk';
|
||||||
|
data4Layout.layoutAlgorithm = layout;
|
||||||
|
data4Layout.direction = DIR;
|
||||||
|
data4Layout.nodeSpacing = conf?.nodeSpacing || 50;
|
||||||
|
data4Layout.rankSpacing = conf?.rankSpacing || 50;
|
||||||
|
data4Layout.markers = ['barb'];
|
||||||
|
data4Layout.diagramId = id;
|
||||||
|
console.log('REF1:', data4Layout);
|
||||||
|
await render(data4Layout, svg, element);
|
||||||
|
const padding = 8;
|
||||||
|
utils.insertTitle(
|
||||||
|
element,
|
||||||
|
'statediagramTitleText',
|
||||||
|
conf?.titleTopMargin || 0,
|
||||||
|
diag.db.getDiagramTitle()
|
||||||
|
);
|
||||||
|
setupViewPortForSVG(svg, padding, 'flowchart', conf?.useMaxWidth || false);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setConf,
|
||||||
|
getClasses,
|
||||||
|
draw,
|
||||||
|
};
|
@ -585,6 +585,7 @@ export const getData = () => {
|
|||||||
const useRough = config.look === 'handdrawn';
|
const useRough = config.look === 'handdrawn';
|
||||||
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, useRough);
|
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, useRough);
|
||||||
|
|
||||||
|
console.log('State Nodes XDX:', nodes);
|
||||||
return { nodes, edges, other: {}, config };
|
return { nodes, edges, other: {}, config };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { log } from '$root/logger.js';
|
import { log } from '$root/logger.js';
|
||||||
import { rect } from './shapes/rect.ts';
|
import { state } from './shapes/state.ts';
|
||||||
|
import { roundedRect } from './shapes/roundedRect.ts';
|
||||||
|
import { squareRect } from './shapes/squareRect.ts';
|
||||||
import { stateStart } from './shapes/stateStart.ts';
|
import { stateStart } from './shapes/stateStart.ts';
|
||||||
import { stateEnd } from './shapes/stateEnd.ts';
|
import { stateEnd } from './shapes/stateEnd.ts';
|
||||||
import { forkJoin } from './shapes/forkJoin.ts';
|
import { forkJoin } from './shapes/forkJoin.ts';
|
||||||
@ -15,13 +17,15 @@ const formatClass = (str) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const shapes = {
|
const shapes = {
|
||||||
rect,
|
state,
|
||||||
stateStart,
|
stateStart,
|
||||||
stateEnd,
|
stateEnd,
|
||||||
fork: forkJoin,
|
fork: forkJoin,
|
||||||
join: forkJoin,
|
join: forkJoin,
|
||||||
choice,
|
choice,
|
||||||
note,
|
note,
|
||||||
|
roundedRect,
|
||||||
|
squareRect,
|
||||||
};
|
};
|
||||||
|
|
||||||
let nodeElems = {};
|
let nodeElems = {};
|
||||||
@ -30,7 +34,6 @@ export const insertNode = async (elem, node, dir) => {
|
|||||||
let newEl;
|
let newEl;
|
||||||
let el;
|
let el;
|
||||||
|
|
||||||
// debugger;
|
|
||||||
// Add link when appropriate
|
// Add link when appropriate
|
||||||
if (node.link) {
|
if (node.link) {
|
||||||
let target;
|
let target;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { log } from '$root/logger.js';
|
import { log } from '$root/logger.js';
|
||||||
import { labelHelper, updateNodeBounds } from './util.js';
|
import { labelHelper, updateNodeBounds } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '$root/rendering-util/types.d.ts';
|
import type { Node, RectOptions } from '$root/rendering-util/types.d.ts';
|
||||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||||
import { getConfig } from '$root/diagram-api/diagramAPI.js';
|
import { getConfig } from '$root/diagram-api/diagramAPI.js';
|
||||||
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
|
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
|
||||||
@ -58,7 +58,7 @@ function applyNodePropertyBorders(
|
|||||||
rect.attr('stroke-dasharray', strokeDashArray.join(' '));
|
rect.attr('stroke-dasharray', strokeDashArray.join(' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const rect = async (parent: SVGAElement, node: Node) => {
|
export const drawRect = async (parent: SVGAElement, node: Node, options: RectOptions) => {
|
||||||
const { themeVariables, handdrawnSeed } = getConfig();
|
const { themeVariables, handdrawnSeed } = getConfig();
|
||||||
const { nodeBorder, mainBkg } = themeVariables;
|
const { nodeBorder, mainBkg } = themeVariables;
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ export const rect = async (parent: SVGAElement, node: Node) => {
|
|||||||
const y = -bbox.height / 2 - halfPadding;
|
const y = -bbox.height / 2 - halfPadding;
|
||||||
|
|
||||||
let rect;
|
let rect;
|
||||||
const { rx, ry, style: cssStyles, useRough } = node;
|
const { rx, ry, cssStyles, useRough } = node;
|
||||||
if (useRough) {
|
if (useRough) {
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {
|
const options = userNodeOverrides(node, {
|
||||||
@ -101,6 +101,8 @@ export const rect = async (parent: SVGAElement, node: Node) => {
|
|||||||
.attr('class', 'basic label-container')
|
.attr('class', 'basic label-container')
|
||||||
.attr('style', cssStyles)
|
.attr('style', cssStyles)
|
||||||
.attr('rx', rx)
|
.attr('rx', rx)
|
||||||
|
.attr('data-id', 'abc')
|
||||||
|
.attr('data-et', 'node')
|
||||||
.attr('ry', ry)
|
.attr('ry', ry)
|
||||||
.attr('x', x)
|
.attr('x', x)
|
||||||
.attr('y', y)
|
.attr('y', y)
|
@ -0,0 +1,13 @@
|
|||||||
|
import type { Node, RectOptions } from '$root/rendering-util/types.d.ts';
|
||||||
|
import { drawRect } from './drawRect.js';
|
||||||
|
|
||||||
|
export const roundedRect = async (parent: SVGAElement, node: Node) => {
|
||||||
|
const options = {
|
||||||
|
rx: 5,
|
||||||
|
ry: 5,
|
||||||
|
classes: '',
|
||||||
|
} as RectOptions;
|
||||||
|
|
||||||
|
console.log('roundedRect XDX');
|
||||||
|
return drawRect(parent, node, options);
|
||||||
|
};
|
@ -0,0 +1,11 @@
|
|||||||
|
import type { Node, RectOptions } from '$root/rendering-util/types.d.ts';
|
||||||
|
import { drawRect } from './drawRect.js';
|
||||||
|
|
||||||
|
export const squareRect = async (parent: SVGAElement, node: Node) => {
|
||||||
|
const options = {
|
||||||
|
rx: 0,
|
||||||
|
ry: 0,
|
||||||
|
classes: '',
|
||||||
|
} as RectOptions;
|
||||||
|
return drawRect(parent, node, options);
|
||||||
|
};
|
@ -0,0 +1,11 @@
|
|||||||
|
import type { Node } from '$root/rendering-util/types.d.ts';
|
||||||
|
import { drawRect } from './drawRect.js';
|
||||||
|
|
||||||
|
export const state = async (parent: SVGAElement, node: Node) => {
|
||||||
|
const options = {
|
||||||
|
rx: 5,
|
||||||
|
ry: 5,
|
||||||
|
classes: 'flowchart-node',
|
||||||
|
};
|
||||||
|
return drawRect(parent, node, options);
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
import config from '../../dist/defaultConfig';
|
import config from '../../dist/defaultConfig';
|
||||||
import { MermaidConfig } from '../../dist/config.type';
|
import type { MermaidConfig } from '../../dist/config.type';
|
||||||
export type MarkdownWordType = 'normal' | 'strong' | 'emphasis';
|
export type MarkdownWordType = 'normal' | 'strong' | 'emphasis';
|
||||||
export interface MarkdownWord {
|
export interface MarkdownWord {
|
||||||
content: string;
|
content: string;
|
||||||
@ -90,6 +90,12 @@ interface Edge {
|
|||||||
useRough?: boolean;
|
useRough?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RectOptions {
|
||||||
|
rx: number;
|
||||||
|
ry: number;
|
||||||
|
classes: string;
|
||||||
|
}
|
||||||
|
|
||||||
// Extending the Node interface for specific types if needed
|
// Extending the Node interface for specific types if needed
|
||||||
interface ClassDiagramNode extends Node {
|
interface ClassDiagramNode extends Node {
|
||||||
memberData: any; // Specific property for class diagram nodes
|
memberData: any; // Specific property for class diagram nodes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user