Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11

This commit is contained in:
Ashish Jain
2024-06-12 11:37:13 +02:00
24 changed files with 60 additions and 146 deletions

View File

@@ -465,7 +465,7 @@ export const render = async (data4Layout, svg, element, algorithm) => {
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
'elk.algorithm': algorithm,
'nodePlacement.strategy': data4Layout.config['elk.nodePlacement.strategy'],
'elk.layered.mergeEdges': data4Layout.config.mergeEdges,
'elk.layered.mergeEdges': data4Layout.config['elk.mergeEdges'],
'elk.direction': 'DOWN',
'spacing.baseValue': 30,
// 'spacing.nodeNode': 40,

View File

@@ -89,7 +89,7 @@ export interface MermaidConfig {
*/
maxEdges?: number;
/**
* Elk specific option that allows edge egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
* Elk specific option that allows egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
*
*/
'elk.mergeEdges'?: boolean;

View File

@@ -768,7 +768,25 @@ const getTypeFromVertex = (vertex: FlowVertex) => {
};
const findNode = (nodes: Node[], id: string) => nodes.find((node) => node.id === id);
const destructEdgeType = (type: string | undefined) => {
let arrowTypeStart = 'none';
let arrowTypeEnd = 'arrow_point';
switch (type) {
case 'arrow_point':
case 'arrow_circle':
case 'arrow_cross':
arrowTypeEnd = type;
break;
case 'double_arrow_point':
case 'double_arrow_circle':
case 'double_arrow_cross':
arrowTypeStart = type.replace('double_', '');
arrowTypeEnd = arrowTypeStart;
break;
}
return { arrowTypeStart, arrowTypeEnd };
};
const addNodeFromVertex = (
vertex: FlowVertex,
nodes: Node[],
@@ -776,7 +794,7 @@ const addNodeFromVertex = (
subGraphDB: Map<string, boolean>,
config: any,
look: string
): Node => {
) => {
const parentId = parentDB.get(vertex.id);
const isGroup = subGraphDB.get(vertex.id) || false;
@@ -793,7 +811,6 @@ const addNodeFromVertex = (
shape: getTypeFromVertex(vertex),
dir: vertex.dir,
domId: vertex.domId,
type: isGroup ? 'group' : undefined,
isGroup,
look,
});
@@ -830,26 +847,19 @@ export const getData = () => {
cssClasses: '',
shape: 'rect',
dir: subGraph.dir,
domId: subGraph.domId,
type: 'group',
isGroup: true,
look: config.look,
});
}
console.log('APA12 nodes - 1', nodes.length);
const n = getVertices();
n.forEach((vertex) => {
const node = addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, config.look);
if (node) {
nodes.push(node);
}
});
console.log('APA12 nodes', nodes.length);
const e = getEdges();
e.forEach((rawEdge, index) => {
const { arrowTypeStart, arrowTypeEnd } = destructEdgeType(rawEdge.type);
const edge: Edge = {
id: getEdgeId(rawEdge.start, rawEdge.end, { counter: index, prefix: 'edge' }),
start: rawEdge.start,
@@ -857,25 +867,16 @@ export const getData = () => {
type: rawEdge.type || 'normal',
label: rawEdge.text,
labelpos: 'c',
// labelStyle: '',
// cssStyles: rawEdge.styles.join(' '),
thickness: rawEdge.stroke,
minlen: rawEdge.length,
classes: 'edge-thickness-normal edge-pattern-solid flowchart-link',
arrowhead: 'none',
arrowTypeEnd: 'arrow_point',
// arrowTypeEnd: 'arrow_barb',
arrowTypeStart,
arrowTypeEnd,
arrowheadStyle: 'fill: #333',
// stroke: rawEdge.pattern,
pattern: rawEdge.stroke,
// shape: getTypeFromVertex(rawEdge),
// dir: rawEdge.dir,
// domId: verawEdgertex.domId,
// rawEdge: undefined,
// isGroup: false,
look: config.look,
};
// console.log('rawEdge SPLIT', rawEdge, index);
console.log('rawEdge SPLIT', rawEdge, index);
edges.push(edge);
});

View File

@@ -36,26 +36,13 @@ export const draw = async function (text: string, id: string, _version: string,
// 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: ');
log.debug('Before getData: ');
const data4Layout = diag.db.getData() as LayoutData;
console.log('Data: ', data4Layout);
log.debug('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;
@@ -63,7 +50,7 @@ export const draw = async function (text: string, id: string, _version: string,
data4Layout.markers = ['point', 'circle', 'cross'];
data4Layout.diagramId = id;
console.log('REF1:', data4Layout);
log.debug('REF1:', data4Layout);
await render(data4Layout, svg, element);
const padding = 8;
utils.insertTitle(

View File

@@ -71,6 +71,9 @@ function newClassesList() {
return new Map();
}
let nodes = [];
let edges = [];
let direction = DEFAULT_DIAGRAM_DIRECTION;
let rootDoc = [];
let classes = newClassesList(); // style classes defined by a classDef
@@ -222,6 +225,12 @@ const extract = (_doc) => {
break;
}
});
const diagramStates = getStates();
const config = getConfig();
const look = config.look;
resetDataFetching();
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true,look);
};
/**
@@ -306,6 +315,8 @@ export const addState = function (
};
export const clear = function (saveCommon) {
nodes = [];
edges = [];
documents = {
root: newDoc(),
};
@@ -571,20 +582,7 @@ const setDirection = (dir) => {
const trimColon = (str) => (str && str[0] === ':' ? str.substr(1).trim() : str.trim());
export const getData = () => {
const nodes = [];
const edges = [];
// for (const key in currentDocument.states) {
// if (currentDocument.states.hasOwnProperty(key)) {
// nodes.push({...currentDocument.states[key]});
// }
// }
const diagramStates = getStates();
const config = getConfig();
const look = config.look;
resetDataFetching();
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look);
return { nodes, edges, other: {}, config };
};

View File

@@ -162,7 +162,7 @@ const findCommonEdges = (graph, id1, id2) => {
return { v: edge.v, w: edge.w };
});
const result = edges1Prim.filter((edgeIn1) => {
return edges2Prim.filter((edge) => edgeIn1.v === edge.v && edgeIn1.w === edge.w).length > 0;
return edges2Prim.some((edge) => edgeIn1.v === edge.v && edgeIn1.w === edge.w);
});
return result;

View File

@@ -69,13 +69,12 @@ const rect = (parent, node) => {
stroke: clusterBorder,
fillWeight: 3,
seed: handdrawnSeed,
stroke: clusterBorder,
});
const roughNode = rc.path(createRoundedRectPathD(x, y, totalWidth, totalHeight, 0), options);
// console.log('Rough node insert CXC', roughNode);
rect = shapeSvg.insert(() => {
console.log('Rough node insert CXC', roughNode);
log.debug('Rough node insert CXC', roughNode);
return roughNode;
}, ':first-child');
} else {

View File

@@ -444,7 +444,7 @@ const fixCorners = function (lineData) {
const a = Math.sqrt(2) * 2;
let newCornerPoint = { x: cornerPoint.x, y: cornerPoint.y };
if (Math.abs(nextPoint.x - prevPoint.x) > 10 && Math.abs(nextPoint.y - prevPoint.y) >= 10) {
console.log(
log.debug(
'Corner point fixing',
Math.abs(nextPoint.x - prevPoint.x),
Math.abs(nextPoint.y - prevPoint.y)
@@ -462,7 +462,7 @@ const fixCorners = function (lineData) {
};
}
} else {
console.log(
log.debug(
'Corner point skipping fixing',
Math.abs(nextPoint.x - prevPoint.x),
Math.abs(nextPoint.y - prevPoint.y)

View File

@@ -178,8 +178,8 @@ const point = (elem, type, id) => {
.attr('refX', 4.5)
.attr('refY', 5)
.attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 11)
.attr('markerHeight', 11)
.attr('markerWidth', 8)
.attr('markerHeight', 8)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M 0 5 L 10 10 L 10 0 z')

View File

@@ -18,7 +18,7 @@ export const circle = async (parent: SVGAElement, node: Node): Promise<SVGAEleme
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const roughNode = rc.circle(0, 0, radius * 2, options);

View File

@@ -5,16 +5,6 @@ import type { Node } from '$root/rendering-util/types.d.ts';
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
import rough from 'roughjs';
/**
* Creates an SVG path for a cylindrical shape.
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} width - The width of the cylinder.
* @param {number} height - The height of the cylinder.
* @param {number} rx - The x-radius of the cylinder's ends.
* @param {number} ry - The y-radius of the cylinder's ends.
* @returns {string} The path data for the cylindrical shape.
*/
export const createCylinderPathD = (
x: number,
y: number,
@@ -71,7 +61,7 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);

View File

@@ -20,8 +20,8 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise<SVG
let circleGroup;
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
if (node.look === 'handdrawn') {e
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 });

View File

@@ -7,15 +7,6 @@ import rough from 'roughjs';
import { insertPolygonShape } from './insertPolygonShape.js';
/**
* Creates an SVG path for a hexagon shape.
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} width - The width of the hexagon.
* @param {number} height - The height of the hexagon.
* @param {number} m - The margin size for the hexagon.
* @returns {string} The path data for the hexagon shape.
*/
export const createHexagonPathD = (
x: number,
y: number,
@@ -59,7 +50,7 @@ export const hexagon = async (parent: SVGAElement, node: Node): Promise<SVGAElem
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createHexagonPathD(0, 0, w, h, m);

View File

@@ -1,9 +1,3 @@
/**
* @param parent
* @param w
* @param h
* @param points
*/
export function insertPolygonShape(
parent: any,
w: number,

View File

@@ -7,14 +7,6 @@ import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shape
import rough from 'roughjs';
import { insertPolygonShape } from './insertPolygonShape.js';
/**
* Creates an SVG path for an inverted trapezoid shape.
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} width - The width of the shape.
* @param {number} height - The height of the shape.
* @returns {string} The path data for the inverted trapezoid shape.
*/
export const createInvertedTrapezoidPathD = (
x: number,
y: number,
@@ -46,7 +38,7 @@ export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise<SV
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createInvertedTrapezoidPathD(0, 0, w, h);

View File

@@ -6,14 +6,6 @@ import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shape
import rough from 'roughjs';
import { insertPolygonShape } from './insertPolygonShape.js';
/**
* Creates an SVG path for a lean left shape.
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} width - The width of the shape.
* @param {number} height - The height of the shape.
* @returns {string} The path data for the lean left shape.
*/
export const createLeanLeftPathD = (
x: number,
y: number,
@@ -45,7 +37,7 @@ export const lean_left = async (parent: SVGAElement, node: Node): Promise<SVGAEl
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createLeanLeftPathD(0, 0, w, h);

View File

@@ -6,14 +6,6 @@ import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shape
import rough from 'roughjs';
import { insertPolygonShape } from './insertPolygonShape.js';
/**
* Creates an SVG path for a lean right shape.
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} width - The width of the shape.
* @param {number} height - The height of the shape.
* @returns {string} The path data for the lean right shape.
*/
export const createLeanRightPathD = (
x: number,
y: number,
@@ -45,7 +37,7 @@ export const lean_right = async (parent: SVGAElement, node: Node): Promise<SVGAE
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createLeanRightPathD(0, 0, w, h);

View File

@@ -6,13 +6,6 @@ import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shape
import rough from 'roughjs';
import { insertPolygonShape } from './insertPolygonShape.js';
/**
* Creates an SVG path for a decision box shape (question shape).
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} size - The size of the shape.
* @returns {string} The path data for the decision box shape.
*/
export const createDecisionBoxPathD = (x: number, y: number, size: number): string => {
return [
`M${x + size / 2},${y}`,
@@ -41,7 +34,7 @@ export const question = async (parent: SVGAElement, node: Node): Promise<SVGAEle
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createDecisionBoxPathD(0, 0, s);

View File

@@ -6,14 +6,6 @@ import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shape
import rough from 'roughjs';
import { insertPolygonShape } from './insertPolygonShape.js';
/**
* Creates an SVG path for a special polygon shape with a left-inverted arrow.
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} width - The width of the shape.
* @param {number} height - The height of the shape.
* @returns {string} The path data for the special polygon shape.
*/
export const createPolygonPathD = (x: number, y: number, width: number, height: number): string => {
return [
`M${x - height / 2},${y}`,
@@ -45,7 +37,7 @@ export const rect_left_inv_arrow = async (
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPolygonPathD(0, 0, w, h);

View File

@@ -60,7 +60,7 @@ export const stadium = async (parent: SVGAElement, node: Node) => {
let rect;
const { cssStyles } = node;
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});

View File

@@ -55,7 +55,7 @@ export const subroutine = async (parent: SVGAElement, node: Node) => {
];
if (node.look === 'handdrawn') {
// @ts-ignore
// @ts-ignore - rough is not typed
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createSubroutinePathD(-w / 2, -h / 2, w, h);

View File

@@ -6,14 +6,6 @@ import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shape
import rough from 'roughjs';
import { insertPolygonShape } from './insertPolygonShape.js';
/**
* Creates an SVG path for a trapezoid shape.
* @param {number} x - The x coordinate of the top-left corner.
* @param {number} y - The y coordinate of the top-left corner.
* @param {number} width - The width of the shape.
* @param {number} height - The height of the shape.
* @returns {string} The path data for the trapezoid shape.
*/
export const createTrapezoidPathD = (
x: number,
y: number,

View File

@@ -27,7 +27,8 @@ interface Node {
// Flowchart specific properties
labelType?: string; // REMOVE? Always use markdown string, need to check for KaTeX - ⏳ wait with this one
domId: string;
domId?: string; // When you create the node in the getData function you do not have the domId yet
// Rendering specific properties for both Flowchart and State Diagram nodes
dir?: string; // Only relevant for isGroup true, i.e. a sub-graph or composite state.
haveCallback?: boolean;

View File

@@ -102,7 +102,7 @@ properties:
minimum: 0
elk.mergeEdges:
description: |
Elk specific option that allows edge egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
Elk specific option that allows egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
type: boolean
default: false
elk.nodePlacement.strategy: