diff --git a/cypress/platform/knsv-pos.html b/cypress/platform/knsv-pos.html index ce54d42d9..b53598ff4 100644 --- a/cypress/platform/knsv-pos.html +++ b/cypress/platform/knsv-pos.html @@ -105,6 +105,12 @@ stateDiagram S:Stillas T:Tiger U:Ulv + state Z { + state X { + Y:Ypsilon + } + } + A S --> T: angrepp T --> U: Apa @@ -116,7 +122,11 @@ stateDiagram S: { x: 0, y: 0 }, T: { x: 100, y: 100, width: 100, height: 100 }, U: { x: 200, y: 200 }, - V: { x: 300, y: 100 }, + V: { x: 300, y: 120 }, + Z: { x: 300, y: 10, width: 160, height: 100 }, + X: { x: 300, y: 20, width: 80, height: 60 }, + Y: { x: 300, y: 30, width: 50, height: 20 }, + A: { x: 300, y: 75, width: 20, height: 20 }, }, edges: { edge0: { diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index e4d904528..76c4608fe 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -75,37 +75,28 @@
--%%{ - init: { - "theme":"base", - "fontFamily": "Kalam", - "themeVariables": - { - "background": "#FFFFFF", - "primaryColor": "#7bdfa7", - "primaryTextColor": "#3c3c3b", - "secondaryColor": "#642470", - "secondaryTextColor": "#3c3c3b", - "tertiaryColor": "#1c736D", - "tertiaryTextColor": "#3c3c3b", - "noteBkgColor": "#9fd8ef", - "loopTextColor": "#636362", - "labelBoxBkgColor": "#642470", - "labelBoxBorderColor": "#642470", - "labelTextColor": "#d4d4d4", - "signalTextColor": "#636362", - "signalColor": "#642470" - } - } -}%% -sequenceDiagram - Alice->>+John: Hello John, how are you? - Alice->>+John: John, can you hear me? - John-->>-Alice: Hi Alice, I can hear you! - John-->>-Alice: I feel great! ++stateDiagram +direction LR + state Gorilla0 { + state Apa0 { + A0 --> B0 + } + + } + Apa0 --> C0 + A0 --> C0++flowchart LR + subgraph Gorilla + subgraph Apa + A[A] --- B + end + end + Apa --- C + A --x CstateDiagram @@ -115,8 +106,16 @@ stateDiagram-stateDiagram - state "This is a state description" as S + %%{init: {"layout": "dagre", "mergeEdges": false} }%% +flowchart LR + A ==> B(This is B) + A[Start] --> B(Is it?) + B -- Yes --> C[OK] + C --> D[Rethink] + D --> B + B -. No ...-> E[End] + +@@ -135,7 +134,7 @@ flowchart if_state --> True : if n >= 0-+%%{init: {"layout": "elk", "mergeEdges": false, "elk.nodePlacement.strategy": "SIMPLE"} }%% stateDiagram state if_state <<choice>> @@ -150,8 +149,10 @@ flowchart stateDiagram direction TB State T1 { - T11 + T11 --> T12 } + T1 --> T2 + T11 --> T2@@ -211,7 +212,7 @@ stateDiagram end note-+stateDiagram-v2 direction LR [*] --> Active @@ -234,12 +235,13 @@ stateDiagram-v2 }; mermaid.initialize({ // theme: 'base', - handdrawnSeed: 12, + // handdrawnSeed: 12, look: 'handdrawn', - 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX', + // 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX', // layout: 'dagre', - // layout: 'elk', - layout: 'fixed', + layout: 'elk', + // layout: 'fixed', + // htmlLabels: false, flowchart: { titleTopMargin: 10 }, // fontFamily: 'Caveat', fontFamily: 'Kalam', diff --git a/packages/mermaid-layout-elk/package.json b/packages/mermaid-layout-elk/package.json index 45f3871b9..bef3dee6a 100644 --- a/packages/mermaid-layout-elk/package.json +++ b/packages/mermaid-layout-elk/package.json @@ -1,5 +1,5 @@ { - "name": "@mermaid-js/layout-elk", + "name": "@mermaid-chart/layout-elk", "version": "0.0.1", "description": "ELK layout engine for mermaid", "module": "dist/mermaid-layout-elk.core.mjs", @@ -40,4 +40,4 @@ "files": [ "dist" ] -} +} \ No newline at end of file diff --git a/packages/mermaid-layout-elk/src/render.ts b/packages/mermaid-layout-elk/src/render.ts index 6b18e2e5d..912066c92 100644 --- a/packages/mermaid-layout-elk/src/render.ts +++ b/packages/mermaid-layout-elk/src/render.ts @@ -60,7 +60,7 @@ export const addVertex = async (nodeEl, graph, nodeArr, node) => { graph.children.push(child); nodeDb[node.id] = child; - // // Add the element to the DOM + // Add the element to the DOM if (!node.isGroup) { const childNodeEl = await insertNode(nodeEl, node, node.dir); boundingBox = childNodeEl.node().getBBox(); @@ -93,7 +93,7 @@ export const addVertex = async (nodeEl, graph, nodeArr, node) => { export const addVertices = async function (nodeEl, nodeArr, graph, parentId) { const siblings = nodeArr.filter((node) => node.parentId === parentId); - log.info('addVertices DAGA', siblings, parentId); + log.info('addVertices APA12', siblings, parentId); // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition await Promise.all( siblings.map(async (node) => { @@ -512,9 +512,7 @@ export const render = async (data4Layout, svg, element, algorithm) => { const node = nodeDb[n.id]; // Subgraph - console.log('Subgraph XCX before'); if (parentLookupDb.childrenById[node.id] !== undefined) { - console.log('Subgraph XCX', node.id, node, node.labelData); node.labels = [ { text: node.labelText, @@ -553,21 +551,21 @@ export const render = async (data4Layout, svg, element, algorithm) => { } }); - console.log('before layout', JSON.stringify(elkGraph, null, 2)); + // log.info('before layout', JSON.stringify(elkGraph, null, 2)); const g = await elk.layout(elkGraph); - log.info('after layout', JSON.stringify(g)); + // log.info('after layout', JSON.stringify(g)); // debugger; drawNodes(0, 0, g.children, svg, subGraphsEl, 0); g.edges?.map((edge) => { // (elem, edge, clusterDb, diagramType, graph, id) - edge.start = nodeDb[edge.sources[0]]; - edge.end = nodeDb[edge.targets[0]]; - const sourceId = edge.start.id; - const targetId = edge.end.id; + const startNode = nodeDb[edge.sources[0]]; + const endNode = nodeDb[edge.targets[0]]; + const sourceId = edge.start; + const targetId = edge.end; const offset = calcOffset(sourceId, targetId, parentLookupDb); - + log.info('APA12 offset', offset, sourceId, targetId, edge); if (edge.sections) { const src = edge.sections[0].startPoint; const dest = edge.sections[0].endPoint; @@ -586,9 +584,11 @@ export const render = async (data4Layout, svg, element, algorithm) => { edge, clusterDb, data4Layout.type, - g, + startNode, + endNode, data4Layout.diagramId ); + log.info('APA12 edge points after insert', JSON.stringify(edge.points)); edge.x = edge.labels[0].x + offset.x + edge.labels[0].width / 2; edge.y = edge.labels[0].y + offset.y + edge.labels[0].height / 2; diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index 5dbc9ee43..064774c4c 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -1,6 +1,6 @@ { "name": "@mermaid-chart/mermaid", - "version": "11.0.0-beta.6", + "version": "11.0.0-beta.12", "description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "type": "module", "module": "./dist/mermaid.core.mjs", @@ -137,4 +137,4 @@ "README.md" ], "sideEffects": false -} +} \ No newline at end of file diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index 605e8d5ea..b2c38efe8 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -1,5 +1,5 @@ import { select } from 'd3'; -import utils from '../../utils.js'; +import utils, { getEdgeId } from '../../utils.js'; import { getConfig, defaultConfig } from '../../diagram-api/diagramAPI.js'; import common from '../common/common.js'; import type { LayoutData, LayoutMethod, Node, Edge } from '../../rendering-util/types.js'; @@ -767,6 +767,39 @@ const getTypeFromVertex = (vertex: FlowVertex) => { return vertex.type || 'squareRect'; }; +const findNode = (nodes: Node[], id: string) => nodes.find((node) => node.id === id); + +const addNodeFromVertex = ( + vertex: FlowVertex, + nodes: Node[], + parentDB: Map, + subGraphDB: Map , + config: any, + useRough: boolean +): Node => { + let parentId = parentDB.get(vertex.id); + let isGroup = subGraphDB.get(vertex.id) || false; + + let node = findNode(nodes, vertex.id); + if (!node) { + nodes.push({ + id: vertex.id, + label: vertex.text, + labelStyle: '', + parentId, + padding: config.flowchart?.padding || 8, + cssStyles: vertex.styles.join(' '), + cssClasses: vertex.classes.join(' '), + shape: getTypeFromVertex(vertex), + dir: vertex.dir, + domId: vertex.domId, + type: isGroup ? 'group' : undefined, + isGroup, + useRough, + }); + } +}; + export const getData = () => { const config = getConfig(); const nodes: Node[] = []; @@ -775,23 +808,76 @@ export const getData = () => { // extract(getRootDocV2()); // const diagramStates = getStates(); const useRough = config.look === 'handdrawn'; + const subGraphs = getSubGraphs(); + log.info('Subgraphs - APA12', subGraphs); + const parentDB = new Map (); + const subGraphDB = new Map (); + + for (let i = subGraphs.length - 1; i >= 0; i--) { + const subGraph = subGraphs[i]; + if (subGraph.nodes.length > 0) { + subGraphDB.set(subGraph.id, true); + } + subGraph.nodes.forEach((id) => { + parentDB.set(id, subGraph.id); + }); + nodes.push({ + id: subGraph.id, + label: subGraph.title, + labelStyle: '', + parentId: parentDB.get(subGraph.id), + padding: config.flowchart?.padding || 8, + cssStyles: '', + cssClasses: '', + shape: 'rect', + dir: subGraph.dir, + domId: subGraph.domId, + type: 'group', + isGroup: true, + useRough, + }); + } + console.log('APA12 nodes - 1', nodes.length); + 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, + const node = addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, useRough); + if (node) { + nodes.push(node); + } + }); + + console.log('APA12 nodes', nodes.length); + + const e = getEdges(); + e.forEach((rawEdge, index) => { + const edge: Edge = { + id: getEdgeId(rawEdge.start, rawEdge.end, { counter: index, prefix: 'edge' }), + start: rawEdge.start, + end: rawEdge.end, + 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', + arrowheadStyle: 'fill: #333', + // stroke: rawEdge.pattern, + pattern: rawEdge.stroke, + // shape: getTypeFromVertex(rawEdge), + // dir: rawEdge.dir, + // domId: verawEdgertex.domId, + // rawEdge: undefined, + // isGroup: false, useRough, }; - nodes.push(node); + // console.log('rawEdge SPLIT', rawEdge, index); + edges.push(edge); }); //const useRough = config.look === 'handdrawn'; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts b/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts index e3db21540..1be74da55 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts @@ -1,7 +1,7 @@ // @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 flowRendererV2 from './flowRenderer-v2.js'; import flowRendererV3 from './flowRenderer-v3-unified.js'; import flowStyles from './styles.js'; import type { MermaidConfig } from '../../config.type.js'; diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v3-unified.ts b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v3-unified.ts index 01bf79fcb..1d6b353d6 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v3-unified.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v3-unified.ts @@ -60,7 +60,8 @@ export const draw = async function (text: string, id: string, _version: string, data4Layout.direction = DIR; data4Layout.nodeSpacing = conf?.nodeSpacing || 50; data4Layout.rankSpacing = conf?.rankSpacing || 50; - data4Layout.markers = ['barb']; + data4Layout.markers = ['point', 'circle', 'cross']; + data4Layout.diagramId = id; console.log('REF1:', data4Layout); await render(data4Layout, svg, element); diff --git a/packages/mermaid/src/diagrams/flowchart/types.ts b/packages/mermaid/src/diagrams/flowchart/types.ts index 954759f39..59ccf6a1d 100644 --- a/packages/mermaid/src/diagrams/flowchart/types.ts +++ b/packages/mermaid/src/diagrams/flowchart/types.ts @@ -23,7 +23,7 @@ export interface FlowEdge { end: string; interpolate?: string; type?: string; - stroke?: string; + stroke?: 'normal' | 'thick' | 'invisible'; style?: string[]; length?: number; text: string; diff --git a/packages/mermaid/src/diagrams/state/dataFetcher.js b/packages/mermaid/src/diagrams/state/dataFetcher.js index b8302cc22..3bdf1abe0 100644 --- a/packages/mermaid/src/diagrams/state/dataFetcher.js +++ b/packages/mermaid/src/diagrams/state/dataFetcher.js @@ -206,8 +206,20 @@ function getClassesFromDbInfo(dbInfoItem) { if (dbInfoItem === undefined || dbInfoItem === null) { return ''; } else { - if (dbInfoItem.cssClasses) { - return dbInfoItem.cssClasses.join(' '); + if (dbInfoItem.classes) { + let classStr = ''; + // for each class in classes, add it to the string as comma separated + for (let i = 0; i < dbInfoItem.classes.length; i++) { + //do not add comma for the last class + if (i === dbInfoItem.classes.length - 1) { + classStr += dbInfoItem.classes[i]; + } + //add comma for all other classes + else { + classStr += dbInfoItem.classes[i] + ' '; + } + } + return classStr; } else { return ''; } @@ -224,7 +236,7 @@ export const dataFetcher = ( look ) => { const itemId = parsedItem.id; - const classStr = getClassesFromDbInfo(diagramStates[itemId]); + const classStr = getClassesFromDbInfo(diagramStates.get(itemId)); if (itemId !== 'root') { let shape = SHAPE_STATE; @@ -344,6 +356,7 @@ export const dataFetcher = ( padding: 0, //getConfig().flowchart.padding useRough, look, + position: parsedItem.note.position, }; const groupData = { labelStyle: '', @@ -358,6 +371,7 @@ export const dataFetcher = ( padding: 16, //getConfig().flowchart.padding useRough, look, + position: parsedItem.note.position, }; graphItemCount++; diff --git a/packages/mermaid/src/diagrams/state/stateDb.js b/packages/mermaid/src/diagrams/state/stateDb.js index 1b7f542fb..f6bddf0ea 100644 --- a/packages/mermaid/src/diagrams/state/stateDb.js +++ b/packages/mermaid/src/diagrams/state/stateDb.js @@ -579,7 +579,6 @@ export const getData = () => { // nodes.push({...currentDocument.states[key]}); // } // } - extract(getRootDocV2()); const diagramStates = getStates(); const config = getConfig(); const useRough = config.look === 'handdrawn'; diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js index 3ba76ff9f..0237e20b8 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js @@ -230,7 +230,9 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge); edge.points.forEach((point) => (point.y += subGraphTitleTotalMargin / 2)); - const paths = insertEdge(edgePaths, edge, clusterDb, diagramType, graph, id); + const startNode = graph.node(e.v); + var endNode = graph.node(e.w); + const paths = insertEdge(edgePaths, edge, clusterDb, diagramType, startNode, endNode, id); positionEdgeLabel(edge, paths); }); @@ -284,7 +286,7 @@ export const render = async (data4Layout, svg, element) => { log.debug('Edges:', data4Layout.edges); data4Layout.edges.forEach((edge) => { - graph.setEdge(edge.start, edge.end, { ...edge }); + graph.setEdge(edge.start, edge.end, { ...edge }, edge.id); }); log.warn('Graph at first:', JSON.stringify(graphlibJson.write(graph))); diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js index f56cba285..73b6797df 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js @@ -159,10 +159,8 @@ export const validate = (graph) => { * @param {any} graph */ export const findNonClusterChild = (id, graph) => { - // const node = graph.node(id); log.trace('Searching', id); - // const children = graph.children(id).reverse(); - const children = graph.children(id); //.reverse(); + const children = graph.children(id).reverse(); log.trace('Searching children of id ', id, children); if (children.length < 1) { log.trace('This is a valid node', id); diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js index 2691e7f3d..510df2855 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js @@ -16,7 +16,11 @@ import { clear as clearNodes, setNodeElem, } from '../../rendering-elements/nodes.js'; -import { insertCluster, clear as clearClusters } from '../../rendering-elements/clusters.js'; +import { + insertCluster, + clear as clearClusters, + positionCluster, +} from '../../rendering-elements/clusters.js'; import { insertEdgeLabel, positionEdgeLabel, @@ -53,15 +57,28 @@ const doRender = async (_elem, data4Layout, siteConfig, positions) => { const nodeDB = {}; await Promise.all( data4Layout.nodes.map(async function (node) { + let pos; if (node.x === undefined || node.y === undefined) { - const pos = positions.nodes[node.id]; - node.x = pos?.x || 0; - node.y = pos?.y || 0; + pos = positions.nodes[node.id]; node.height = pos?.height || 0; node.width = pos?.width || 0; } - - await insertNode(nodes, node, 'TB'); + if (node.isGroup) { + node.x = 0; + node.y = 0; + await insertCluster(nodes, node, 'TB'); + // Don't set the coordinates before they "layout", this will mess up the positioning + if (pos) { + node.x = pos?.x || 0; + node.y = pos?.y || 0; + } + } else { + if (pos) { + node.x = pos?.x || 0; + node.y = pos?.y || 0; + } + await insertNode(nodes, node, 'TB'); + } nodeDB[node.id] = node; }) ); @@ -79,7 +96,11 @@ const doRender = async (_elem, data4Layout, siteConfig, positions) => { // Position the nodes await Promise.all( data4Layout.nodes.map(async function (node) { - positionNode(node); + if (node.isGroup) { + positionCluster(node); + } else { + positionNode(node); + } }) ); diff --git a/packages/mermaid/src/rendering-util/render.ts b/packages/mermaid/src/rendering-util/render.ts index ece248317..d592334b8 100644 --- a/packages/mermaid/src/rendering-util/render.ts +++ b/packages/mermaid/src/rendering-util/render.ts @@ -28,6 +28,10 @@ const registerDefaultLayoutLoaders = () => { name: 'fixed', loader: async () => await import('./layout-algorithms/fixed/index.js'), }, + // { + // name: 'elk', + // loader: async () => await import('../../../mermaid-layout-elk/src/render.js'), + // }, ]); }; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 014fc9235..d0133f7d6 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -8,6 +8,7 @@ import { createText } from '../createText.ts'; import intersectRect from '../rendering-elements/intersect/intersect-rect.js'; import createLabel from './createLabel.js'; import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; +import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; // Helper function to calculate the offset correction for the label const calcLabelOffsetCorrection = (diff) => { @@ -17,13 +18,13 @@ const calcLabelOffsetCorrection = (diff) => { const rect = (parent, node) => { log.info('Creating subgraph rect for ', node.id, node); const siteConfig = getConfig(); + const { themeVariables, handdrawnSeed } = siteConfig; + const { clusterBkg, clusterBorder } = themeVariables; + let { useRough } = node; // Add outer g element const shapeSvg = parent.insert('g').attr('class', 'cluster').attr('id', node.id); - // add the rect - const rect = shapeSvg.insert('rect', ':first-child'); - const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); // Create the label and insert it after the rect @@ -49,7 +50,6 @@ const rect = (parent, node) => { } const padding = 0 * node.padding; - const halfPadding = padding / 2; const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width; if (node.width <= bbox.width + padding) { @@ -58,17 +58,45 @@ const rect = (parent, node) => { node.diff = -node.padding / 2; } - log.trace('Data ', node, JSON.stringify(node)); - // center the rect around its coordinate - rect - .attr('style', node.cssStyles) - .attr('rx', node.rx) - .attr('ry', node.ry) - .attr('x', node.x - width / 2) - .attr('y', node.y - node.height / 2 - halfPadding) - .attr('width', width) - .attr('height', node.height + padding); + const totalWidth = width + padding; + const totalHeight = node.height + padding; + const x = node.x - totalWidth / 2; + const y = node.y - totalHeight / 2; + log.trace('Data ', node, JSON.stringify(node)); + let rect; + if (useRough) { + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { + roughness: 0.7, + fill: clusterBkg, + // fill: 'red', + 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); + return roughNode; + }, ':first-child'); + } else { + // add the rect + rect = shapeSvg.insert('rect', ':first-child'); + // center the rect around its coordinate + rect + .attr('style', node.cssStyles) + .attr('rx', node.rx) + .attr('ry', node.ry) + .attr('x', x) + .attr('y', y) + .attr('width', totalWidth) + .attr('height', totalHeight); + } const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig); if (useHtmlLabels) { labelEl.attr( @@ -311,8 +339,8 @@ const divider = (parent, node) => { return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } }; }; - -const shapes = { rect, roundedWithTitle, noteGroup, divider }; +const squareRect = rect; +const shapes = { rect, squareRect, roundedWithTitle, noteGroup, divider }; let clusterElems = {}; @@ -335,8 +363,20 @@ export const clear = () => { }; export const positionCluster = (node) => { - log.info('Position cluster (' + node.id + ', ' + node.x + ', ' + node.y + ')'); + log.info( + 'Position cluster (' + + node.id + + ', ' + + node.x + + ', ' + + node.y + + ') (' + + node?.width + + ', ' + + node?.height + + ')', + clusterElems[node.id] + ); const el = clusterElems[node.id]; - - el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')'); + el.cluster.attr('transform', 'translate(' + node.x + ', ' + node.y + ')'); }; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 68140f705..c8e9a948a 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -494,28 +494,28 @@ function roundedCornersLine(lineData) { } return path; } -export const insertEdge = function (elem, edge, clusterDb, diagramType, graph, id) { +export const insertEdge = function (elem, edge, clusterDb, diagramType, startNode, endNode, id) { const { handdrawnSeed } = getConfig(); let points = edge.points; let pointsHasChanged = false; - const tail = edge.start; - var head = edge.end; + const tail = startNode; + var head = endNode; - log.info('abc88 InsertEdge: ', points); + // log.info('abc88 InsertEdge SPLIT: ', points, edge.start, id); if (head.intersect && tail.intersect) { - log.info('abc88 InsertEdge: 0.5', points); - // points = points.slice(1, edge.points.length - 1); - log.info('abc88 InsertEdge: 0.7', points); - // points.unshift(tail.intersect(points[0])); - // log.info( - // 'Last point abc88', - // points[points.length - 1], - // head, - // head.intersect(points[points.length - 1]) - // ); - // points.push(head.intersect(points[points.length - 1])); + // log.info('abc88 InsertEdge SPLIT: 0.5', points); + points = points.slice(1, edge.points.length - 1); + // log.info('abc88 InsertEdge SPLIT: 0.7', points); + points.unshift(tail.intersect(points[0])); + log.info( + 'Last point abc88', + points[points.length - 1], + head, + head.intersect(points[points.length - 1]) + ); + points.push(head.intersect(points[points.length - 1])); } - log.info('abc88 InsertEdge 2: ', points); + // log.info('abc88 InsertEdge 2 SPLIT: ', points); if (edge.toCluster) { log.info('to cluster abc88', clusterDb[edge.toCluster]); points = cutPathAtIntersect(edge.points, clusterDb[edge.toCluster].node); @@ -534,14 +534,14 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, graph, i let lineData = points.filter((p) => !Number.isNaN(p.y)); const { cornerPoints, cornerPointPositions } = extractCornerPoints(lineData); lineData = fixCorners(lineData); - let lastPoint = lineData[0]; + let lastPoint = lineData[lineData.length - 1]; if (lineData.length > 1) { lastPoint = lineData[lineData.length - 1]; const secondLastPoint = lineData[lineData.length - 2]; // Calculate the mid point of the last two points - const diffX = (lastPoint.x - secondLastPoint.x) / 4; - const diffY = (lastPoint.y - secondLastPoint.y) / 4; - const midPoint = { x: secondLastPoint.x + 3 * diffX, y: secondLastPoint.y + 3 * diffY }; + const diffX = (lastPoint.x - secondLastPoint.x) / 2; + const diffY = (lastPoint.y - secondLastPoint.y) / 2; + const midPoint = { x: secondLastPoint.x + diffX, y: secondLastPoint.y + diffY }; lineData.splice(-1, 0, midPoint); } // This is the accessor function we talked about above @@ -597,11 +597,16 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, graph, i let useRough = edge.useRough; let svgPath; let path = ''; - + let linePath = lineFunction(lineData); if (useRough) { const rc = rough.svg(elem); const ld = Object.assign([], lineData); - const svgPathNode = rc.path(lineFunction(ld.splice(0, ld.length - 1)), { + // const svgPathNode = rc.path(lineFunction(ld.splice(0, ld.length-1)), { + // const svgPathNode = rc.path(lineFunction(ld), { + // roughness: 0.3, + // seed: handdrawnSeed, + // }); + const svgPathNode = rc.path(linePath, { roughness: 0.3, seed: handdrawnSeed, }); @@ -615,13 +620,12 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, graph, i .attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : '')) .attr('style', edge.style); let d = svgPath.attr('d'); - d = d + ' L ' + lastPoint.x + ' ' + lastPoint.y; svgPath.attr('d', d); elem.node().appendChild(svgPath.node()); } else { svgPath = elem .append('path') - .attr('d', lineFunction(lineData)) + .attr('d', linePath) .attr('id', edge.id) .attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : '')) .attr('style', edge.style); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/markers.js b/packages/mermaid/src/rendering-util/rendering-elements/markers.js index 55716613b..42c0536da 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/markers.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/markers.js @@ -159,11 +159,11 @@ const point = (elem, type, id) => { .attr('id', id + '_' + type + '-pointEnd') .attr('class', 'marker ' + type) .attr('viewBox', '0 0 10 10') - .attr('refX', 6) + .attr('refX', 5) .attr('refY', 5) .attr('markerUnits', 'userSpaceOnUse') - .attr('markerWidth', 12) - .attr('markerHeight', 12) + .attr('markerWidth', 8) + .attr('markerHeight', 8) .attr('orient', 'auto') .append('path') .attr('d', 'M 0 0 L 10 5 L 0 10 z') @@ -178,8 +178,8 @@ const point = (elem, type, id) => { .attr('refX', 4.5) .attr('refY', 5) .attr('markerUnits', 'userSpaceOnUse') - .attr('markerWidth', 12) - .attr('markerHeight', 12) + .attr('markerWidth', 11) + .attr('markerHeight', 11) .attr('orient', 'auto') .append('path') .attr('d', 'M 0 5 L 10 10 L 10 0 z') @@ -272,7 +272,7 @@ const barb = (elem, type, id) => { .attr('refY', 7) .attr('markerWidth', 20) .attr('markerHeight', 14) - .attr('markerUnits', 'strokeWidth') + .attr('markerUnits', 'userSpaceOnUse') .attr('orient', 'auto') .append('path') .attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z'); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts index 98c6d4707..c72e567cf 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts @@ -65,7 +65,7 @@ export const question = async (parent: SVGAElement, node: Node): Promise