Merge branch 'alanaV11' into pebr/neo-style

This commit is contained in:
Per Brolin
2024-06-10 10:24:43 +02:00
21 changed files with 321 additions and 140 deletions

View File

@@ -105,6 +105,12 @@ stateDiagram
S:Stillas S:Stillas
T:Tiger T:Tiger
U:Ulv U:Ulv
state Z {
state X {
Y:Ypsilon
}
}
A
S --> T: angrepp S --> T: angrepp
T --> U: Apa T --> U: Apa
@@ -116,7 +122,11 @@ stateDiagram
S: { x: 0, y: 0 }, S: { x: 0, y: 0 },
T: { x: 100, y: 100, width: 100, height: 100 }, T: { x: 100, y: 100, width: 100, height: 100 },
U: { x: 200, y: 200 }, 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: { edges: {
edge0: { edge0: {

View File

@@ -75,37 +75,28 @@
</style> </style>
</head> </head>
<body> <body>
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid">
%%{ stateDiagram
init: { direction LR
"theme":"base", state Gorilla0 {
"fontFamily": "Kalam", state Apa0 {
"themeVariables": A0 --> B0
{ }
"background": "#FFFFFF",
"primaryColor": "#7bdfa7", }
"primaryTextColor": "#3c3c3b", Apa0 --> C0
"secondaryColor": "#642470", A0 --> C0
"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!
</pre </pre
> >
<pre id="diagram" class="mermaid">
flowchart LR
subgraph Gorilla
subgraph Apa
A[A] --- B
end
end
Apa --- C
A --x C
<pre id="diagram" class="mermaid"> <pre id="diagram" class="mermaid">
stateDiagram stateDiagram
@@ -115,8 +106,16 @@ stateDiagram
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid2">
stateDiagram %%{init: {"layout": "dagre", "mergeEdges": false} }%%
state "This is a state description" as S 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]
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid2">
@@ -135,7 +134,7 @@ flowchart
if_state --> True : if n >= 0 if_state --> True : if n >= 0
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid3">
%%{init: {"layout": "elk", "mergeEdges": false, "elk.nodePlacement.strategy": "SIMPLE"} }%% %%{init: {"layout": "elk", "mergeEdges": false, "elk.nodePlacement.strategy": "SIMPLE"} }%%
stateDiagram stateDiagram
state if_state &lt;&lt;choice&gt;&gt; state if_state &lt;&lt;choice&gt;&gt;
@@ -150,8 +149,10 @@ flowchart
stateDiagram stateDiagram
direction TB direction TB
State T1 { State T1 {
T11 T11 --> T12
} }
T1 --> T2
T11 --> T2
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid2">
@@ -211,7 +212,7 @@ stateDiagram
end note end note
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid">
stateDiagram-v2 stateDiagram-v2
direction LR direction LR
[*] --> Active [*] --> Active
@@ -234,12 +235,13 @@ stateDiagram-v2
}; };
mermaid.initialize({ mermaid.initialize({
// theme: 'base', // theme: 'base',
handdrawnSeed: 12, // handdrawnSeed: 12,
look: 'handdrawn', look: 'handdrawn',
'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX', // 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre', // layout: 'dagre',
// layout: 'elk', layout: 'elk',
layout: 'fixed', // layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 }, flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat', // fontFamily: 'Caveat',
fontFamily: 'Kalam', fontFamily: 'Kalam',

View File

@@ -1,5 +1,5 @@
{ {
"name": "@mermaid-js/layout-elk", "name": "@mermaid-chart/layout-elk",
"version": "0.0.1", "version": "0.0.1",
"description": "ELK layout engine for mermaid", "description": "ELK layout engine for mermaid",
"module": "dist/mermaid-layout-elk.core.mjs", "module": "dist/mermaid-layout-elk.core.mjs",
@@ -40,4 +40,4 @@
"files": [ "files": [
"dist" "dist"
] ]
} }

View File

@@ -60,7 +60,7 @@ export const addVertex = async (nodeEl, graph, nodeArr, node) => {
graph.children.push(child); graph.children.push(child);
nodeDb[node.id] = child; nodeDb[node.id] = child;
// // Add the element to the DOM // Add the element to the DOM
if (!node.isGroup) { if (!node.isGroup) {
const childNodeEl = await insertNode(nodeEl, node, node.dir); const childNodeEl = await insertNode(nodeEl, node, node.dir);
boundingBox = childNodeEl.node().getBBox(); 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) { export const addVertices = async function (nodeEl, nodeArr, graph, parentId) {
const siblings = nodeArr.filter((node) => node.parentId === 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 // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
await Promise.all( await Promise.all(
siblings.map(async (node) => { siblings.map(async (node) => {
@@ -512,9 +512,7 @@ export const render = async (data4Layout, svg, element, algorithm) => {
const node = nodeDb[n.id]; const node = nodeDb[n.id];
// Subgraph // Subgraph
console.log('Subgraph XCX before');
if (parentLookupDb.childrenById[node.id] !== undefined) { if (parentLookupDb.childrenById[node.id] !== undefined) {
console.log('Subgraph XCX', node.id, node, node.labelData);
node.labels = [ node.labels = [
{ {
text: node.labelText, 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); const g = await elk.layout(elkGraph);
log.info('after layout', JSON.stringify(g)); // log.info('after layout', JSON.stringify(g));
// debugger; // debugger;
drawNodes(0, 0, g.children, svg, subGraphsEl, 0); drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
g.edges?.map((edge) => { g.edges?.map((edge) => {
// (elem, edge, clusterDb, diagramType, graph, id) // (elem, edge, clusterDb, diagramType, graph, id)
edge.start = nodeDb[edge.sources[0]]; const startNode = nodeDb[edge.sources[0]];
edge.end = nodeDb[edge.targets[0]]; const endNode = nodeDb[edge.targets[0]];
const sourceId = edge.start.id; const sourceId = edge.start;
const targetId = edge.end.id; const targetId = edge.end;
const offset = calcOffset(sourceId, targetId, parentLookupDb); const offset = calcOffset(sourceId, targetId, parentLookupDb);
log.info('APA12 offset', offset, sourceId, targetId, edge);
if (edge.sections) { if (edge.sections) {
const src = edge.sections[0].startPoint; const src = edge.sections[0].startPoint;
const dest = edge.sections[0].endPoint; const dest = edge.sections[0].endPoint;
@@ -586,9 +584,11 @@ export const render = async (data4Layout, svg, element, algorithm) => {
edge, edge,
clusterDb, clusterDb,
data4Layout.type, data4Layout.type,
g, startNode,
endNode,
data4Layout.diagramId 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.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; edge.y = edge.labels[0].y + offset.y + edge.labels[0].height / 2;

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mermaid-chart/mermaid", "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.", "description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module", "type": "module",
"module": "./dist/mermaid.core.mjs", "module": "./dist/mermaid.core.mjs",
@@ -137,4 +137,4 @@
"README.md" "README.md"
], ],
"sideEffects": false "sideEffects": false
} }

View File

@@ -1,5 +1,5 @@
import { select } from 'd3'; import { select } from 'd3';
import utils from '../../utils.js'; import utils, { getEdgeId } 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 type { LayoutData, LayoutMethod, Node, Edge } from '../../rendering-util/types.js';
@@ -767,6 +767,39 @@ const getTypeFromVertex = (vertex: FlowVertex) => {
return vertex.type || 'squareRect'; return vertex.type || 'squareRect';
}; };
const findNode = (nodes: Node[], id: string) => nodes.find((node) => node.id === id);
const addNodeFromVertex = (
vertex: FlowVertex,
nodes: Node[],
parentDB: Map<string, string>,
subGraphDB: Map<string, boolean>,
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 = () => { export const getData = () => {
const config = getConfig(); const config = getConfig();
const nodes: Node[] = []; const nodes: Node[] = [];
@@ -775,23 +808,76 @@ export const getData = () => {
// extract(getRootDocV2()); // extract(getRootDocV2());
// const diagramStates = getStates(); // const diagramStates = getStates();
const useRough = config.look === 'handdrawn'; const useRough = config.look === 'handdrawn';
const subGraphs = getSubGraphs();
log.info('Subgraphs - APA12', subGraphs);
const parentDB = new Map<string, string>();
const subGraphDB = new Map<string, boolean>();
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(); const n = getVertices();
n.forEach((vertex) => { n.forEach((vertex) => {
const node: Node = { const node = addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, useRough);
id: vertex.id, if (node) {
label: vertex.text, nodes.push(node);
labelStyle: '', }
padding: config.flowchart?.padding || 8, });
cssStyles: vertex.styles.join(' '),
cssClasses: vertex.classes.join(' '), console.log('APA12 nodes', nodes.length);
shape: getTypeFromVertex(vertex),
dir: vertex.dir, const e = getEdges();
domId: vertex.domId, e.forEach((rawEdge, index) => {
type: undefined, const edge: Edge = {
isGroup: false, 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, useRough,
}; };
nodes.push(node); // console.log('rawEdge SPLIT', rawEdge, index);
edges.push(edge);
}); });
//const useRough = config.look === 'handdrawn'; //const useRough = config.look === 'handdrawn';

View File

@@ -1,7 +1,7 @@
// @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 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';

View File

@@ -60,7 +60,8 @@ export const draw = async function (text: string, id: string, _version: string,
data4Layout.direction = DIR; data4Layout.direction = DIR;
data4Layout.nodeSpacing = conf?.nodeSpacing || 50; data4Layout.nodeSpacing = conf?.nodeSpacing || 50;
data4Layout.rankSpacing = conf?.rankSpacing || 50; data4Layout.rankSpacing = conf?.rankSpacing || 50;
data4Layout.markers = ['barb']; data4Layout.markers = ['point', 'circle', 'cross'];
data4Layout.diagramId = id; data4Layout.diagramId = id;
console.log('REF1:', data4Layout); console.log('REF1:', data4Layout);
await render(data4Layout, svg, element); await render(data4Layout, svg, element);

View File

@@ -23,7 +23,7 @@ export interface FlowEdge {
end: string; end: string;
interpolate?: string; interpolate?: string;
type?: string; type?: string;
stroke?: string; stroke?: 'normal' | 'thick' | 'invisible';
style?: string[]; style?: string[];
length?: number; length?: number;
text: string; text: string;

View File

@@ -206,8 +206,20 @@ function getClassesFromDbInfo(dbInfoItem) {
if (dbInfoItem === undefined || dbInfoItem === null) { if (dbInfoItem === undefined || dbInfoItem === null) {
return ''; return '';
} else { } else {
if (dbInfoItem.cssClasses) { if (dbInfoItem.classes) {
return dbInfoItem.cssClasses.join(' '); 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 { } else {
return ''; return '';
} }
@@ -224,7 +236,7 @@ export const dataFetcher = (
look look
) => { ) => {
const itemId = parsedItem.id; const itemId = parsedItem.id;
const classStr = getClassesFromDbInfo(diagramStates[itemId]); const classStr = getClassesFromDbInfo(diagramStates.get(itemId));
if (itemId !== 'root') { if (itemId !== 'root') {
let shape = SHAPE_STATE; let shape = SHAPE_STATE;
@@ -344,6 +356,7 @@ export const dataFetcher = (
padding: 0, //getConfig().flowchart.padding padding: 0, //getConfig().flowchart.padding
useRough, useRough,
look, look,
position: parsedItem.note.position,
}; };
const groupData = { const groupData = {
labelStyle: '', labelStyle: '',
@@ -358,6 +371,7 @@ export const dataFetcher = (
padding: 16, //getConfig().flowchart.padding padding: 16, //getConfig().flowchart.padding
useRough, useRough,
look, look,
position: parsedItem.note.position,
}; };
graphItemCount++; graphItemCount++;

View File

@@ -579,7 +579,6 @@ export const getData = () => {
// nodes.push({...currentDocument.states[key]}); // nodes.push({...currentDocument.states[key]});
// } // }
// } // }
extract(getRootDocV2());
const diagramStates = getStates(); const diagramStates = getStates();
const config = getConfig(); const config = getConfig();
const useRough = config.look === 'handdrawn'; const useRough = config.look === 'handdrawn';

View File

@@ -230,7 +230,9 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge); log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
edge.points.forEach((point) => (point.y += subGraphTitleTotalMargin / 2)); 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); positionEdgeLabel(edge, paths);
}); });
@@ -284,7 +286,7 @@ export const render = async (data4Layout, svg, element) => {
log.debug('Edges:', data4Layout.edges); log.debug('Edges:', data4Layout.edges);
data4Layout.edges.forEach((edge) => { 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))); log.warn('Graph at first:', JSON.stringify(graphlibJson.write(graph)));

View File

@@ -159,10 +159,8 @@ export const validate = (graph) => {
* @param {any} graph * @param {any} graph
*/ */
export const findNonClusterChild = (id, graph) => { export const findNonClusterChild = (id, graph) => {
// const node = graph.node(id);
log.trace('Searching', 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); log.trace('Searching children of id ', id, children);
if (children.length < 1) { if (children.length < 1) {
log.trace('This is a valid node', id); log.trace('This is a valid node', id);

View File

@@ -16,7 +16,11 @@ import {
clear as clearNodes, clear as clearNodes,
setNodeElem, setNodeElem,
} from '../../rendering-elements/nodes.js'; } 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 { import {
insertEdgeLabel, insertEdgeLabel,
positionEdgeLabel, positionEdgeLabel,
@@ -53,15 +57,28 @@ const doRender = async (_elem, data4Layout, siteConfig, positions) => {
const nodeDB = {}; const nodeDB = {};
await Promise.all( await Promise.all(
data4Layout.nodes.map(async function (node) { data4Layout.nodes.map(async function (node) {
let pos;
if (node.x === undefined || node.y === undefined) { if (node.x === undefined || node.y === undefined) {
const pos = positions.nodes[node.id]; pos = positions.nodes[node.id];
node.x = pos?.x || 0;
node.y = pos?.y || 0;
node.height = pos?.height || 0; node.height = pos?.height || 0;
node.width = pos?.width || 0; node.width = pos?.width || 0;
} }
if (node.isGroup) {
await insertNode(nodes, node, 'TB'); 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; nodeDB[node.id] = node;
}) })
); );
@@ -79,7 +96,11 @@ const doRender = async (_elem, data4Layout, siteConfig, positions) => {
// Position the nodes // Position the nodes
await Promise.all( await Promise.all(
data4Layout.nodes.map(async function (node) { data4Layout.nodes.map(async function (node) {
positionNode(node); if (node.isGroup) {
positionCluster(node);
} else {
positionNode(node);
}
}) })
); );

View File

@@ -28,6 +28,10 @@ const registerDefaultLayoutLoaders = () => {
name: 'fixed', name: 'fixed',
loader: async () => await import('./layout-algorithms/fixed/index.js'), loader: async () => await import('./layout-algorithms/fixed/index.js'),
}, },
// {
// name: 'elk',
// loader: async () => await import('../../../mermaid-layout-elk/src/render.js'),
// },
]); ]);
}; };

View File

@@ -8,6 +8,7 @@ import { createText } from '../createText.ts';
import intersectRect from '../rendering-elements/intersect/intersect-rect.js'; import intersectRect from '../rendering-elements/intersect/intersect-rect.js';
import createLabel from './createLabel.js'; import createLabel from './createLabel.js';
import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; 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 // Helper function to calculate the offset correction for the label
const calcLabelOffsetCorrection = (diff) => { const calcLabelOffsetCorrection = (diff) => {
@@ -17,13 +18,13 @@ const calcLabelOffsetCorrection = (diff) => {
const rect = (parent, node) => { const rect = (parent, node) => {
log.info('Creating subgraph rect for ', node.id, node); log.info('Creating subgraph rect for ', node.id, node);
const siteConfig = getConfig(); const siteConfig = getConfig();
const { themeVariables, handdrawnSeed } = siteConfig;
const { clusterBkg, clusterBorder } = themeVariables;
let { useRough } = node;
// Add outer g element // Add outer g element
const shapeSvg = parent.insert('g').attr('class', 'cluster').attr('id', node.id); 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); const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels);
// Create the label and insert it after the rect // Create the label and insert it after the rect
@@ -49,7 +50,6 @@ const rect = (parent, node) => {
} }
const padding = 0 * node.padding; const padding = 0 * node.padding;
const halfPadding = padding / 2;
const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width; const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width;
if (node.width <= bbox.width + padding) { if (node.width <= bbox.width + padding) {
@@ -58,17 +58,45 @@ const rect = (parent, node) => {
node.diff = -node.padding / 2; node.diff = -node.padding / 2;
} }
log.trace('Data ', node, JSON.stringify(node)); const totalWidth = width + padding;
// center the rect around its coordinate const totalHeight = node.height + padding;
rect const x = node.x - totalWidth / 2;
.attr('style', node.cssStyles) const y = node.y - totalHeight / 2;
.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);
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); const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
if (useHtmlLabels) { if (useHtmlLabels) {
labelEl.attr( labelEl.attr(
@@ -311,8 +339,8 @@ const divider = (parent, node) => {
return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } }; return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } };
}; };
const squareRect = rect;
const shapes = { rect, roundedWithTitle, noteGroup, divider }; const shapes = { rect, squareRect, roundedWithTitle, noteGroup, divider };
let clusterElems = {}; let clusterElems = {};
@@ -335,8 +363,20 @@ export const clear = () => {
}; };
export const positionCluster = (node) => { 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]; const el = clusterElems[node.id];
el.cluster.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
}; };

View File

@@ -494,28 +494,28 @@ function roundedCornersLine(lineData) {
} }
return path; 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(); const { handdrawnSeed } = getConfig();
let points = edge.points; let points = edge.points;
let pointsHasChanged = false; let pointsHasChanged = false;
const tail = edge.start; const tail = startNode;
var head = edge.end; var head = endNode;
log.info('abc88 InsertEdge: ', points); // log.info('abc88 InsertEdge SPLIT: ', points, edge.start, id);
if (head.intersect && tail.intersect) { if (head.intersect && tail.intersect) {
log.info('abc88 InsertEdge: 0.5', points); // log.info('abc88 InsertEdge SPLIT: 0.5', points);
// points = points.slice(1, edge.points.length - 1); points = points.slice(1, edge.points.length - 1);
log.info('abc88 InsertEdge: 0.7', points); // log.info('abc88 InsertEdge SPLIT: 0.7', points);
// points.unshift(tail.intersect(points[0])); points.unshift(tail.intersect(points[0]));
// log.info( log.info(
// 'Last point abc88', 'Last point abc88',
// points[points.length - 1], points[points.length - 1],
// head, head,
// head.intersect(points[points.length - 1]) head.intersect(points[points.length - 1])
// ); );
// points.push(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) { if (edge.toCluster) {
log.info('to cluster abc88', clusterDb[edge.toCluster]); log.info('to cluster abc88', clusterDb[edge.toCluster]);
points = cutPathAtIntersect(edge.points, clusterDb[edge.toCluster].node); 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)); let lineData = points.filter((p) => !Number.isNaN(p.y));
const { cornerPoints, cornerPointPositions } = extractCornerPoints(lineData); const { cornerPoints, cornerPointPositions } = extractCornerPoints(lineData);
lineData = fixCorners(lineData); lineData = fixCorners(lineData);
let lastPoint = lineData[0]; let lastPoint = lineData[lineData.length - 1];
if (lineData.length > 1) { if (lineData.length > 1) {
lastPoint = lineData[lineData.length - 1]; lastPoint = lineData[lineData.length - 1];
const secondLastPoint = lineData[lineData.length - 2]; const secondLastPoint = lineData[lineData.length - 2];
// Calculate the mid point of the last two points // Calculate the mid point of the last two points
const diffX = (lastPoint.x - secondLastPoint.x) / 4; const diffX = (lastPoint.x - secondLastPoint.x) / 2;
const diffY = (lastPoint.y - secondLastPoint.y) / 4; const diffY = (lastPoint.y - secondLastPoint.y) / 2;
const midPoint = { x: secondLastPoint.x + 3 * diffX, y: secondLastPoint.y + 3 * diffY }; const midPoint = { x: secondLastPoint.x + diffX, y: secondLastPoint.y + diffY };
lineData.splice(-1, 0, midPoint); lineData.splice(-1, 0, midPoint);
} }
// This is the accessor function we talked about above // 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 useRough = edge.useRough;
let svgPath; let svgPath;
let path = ''; let path = '';
let linePath = lineFunction(lineData);
if (useRough) { if (useRough) {
const rc = rough.svg(elem); const rc = rough.svg(elem);
const ld = Object.assign([], lineData); 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, roughness: 0.3,
seed: handdrawnSeed, seed: handdrawnSeed,
}); });
@@ -615,13 +620,12 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, graph, i
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : '')) .attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
.attr('style', edge.style); .attr('style', edge.style);
let d = svgPath.attr('d'); let d = svgPath.attr('d');
d = d + ' L ' + lastPoint.x + ' ' + lastPoint.y;
svgPath.attr('d', d); svgPath.attr('d', d);
elem.node().appendChild(svgPath.node()); elem.node().appendChild(svgPath.node());
} else { } else {
svgPath = elem svgPath = elem
.append('path') .append('path')
.attr('d', lineFunction(lineData)) .attr('d', linePath)
.attr('id', edge.id) .attr('id', edge.id)
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : '')) .attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
.attr('style', edge.style); .attr('style', edge.style);

View File

@@ -159,11 +159,11 @@ const point = (elem, type, id) => {
.attr('id', id + '_' + type + '-pointEnd') .attr('id', id + '_' + type + '-pointEnd')
.attr('class', 'marker ' + type) .attr('class', 'marker ' + type)
.attr('viewBox', '0 0 10 10') .attr('viewBox', '0 0 10 10')
.attr('refX', 6) .attr('refX', 5)
.attr('refY', 5) .attr('refY', 5)
.attr('markerUnits', 'userSpaceOnUse') .attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 12) .attr('markerWidth', 8)
.attr('markerHeight', 12) .attr('markerHeight', 8)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 0 0 L 10 5 L 0 10 z') .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('refX', 4.5)
.attr('refY', 5) .attr('refY', 5)
.attr('markerUnits', 'userSpaceOnUse') .attr('markerUnits', 'userSpaceOnUse')
.attr('markerWidth', 12) .attr('markerWidth', 11)
.attr('markerHeight', 12) .attr('markerHeight', 11)
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 0 5 L 10 10 L 10 0 z') .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('refY', 7)
.attr('markerWidth', 20) .attr('markerWidth', 20)
.attr('markerHeight', 14) .attr('markerHeight', 14)
.attr('markerUnits', 'strokeWidth') .attr('markerUnits', 'userSpaceOnUse')
.attr('orient', 'auto') .attr('orient', 'auto')
.append('path') .append('path')
.attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z'); .attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z');

View File

@@ -65,7 +65,7 @@ export const question = async (parent: SVGAElement, node: Node): Promise<SVGAEle
updateNodeBounds(node, polygon); updateNodeBounds(node, polygon);
node.intersect = function (point) { node.intersect = function (point) {
log.warn('Intersect called'); log.info('Intersect called SPLIT');
return intersect.polygon(node, points, point); return intersect.polygon(node, points, point);
}; };

View File

@@ -93,7 +93,7 @@ interface Edge {
labelStyle?: string; labelStyle?: string;
minlen?: number; minlen?: number;
pattern?: string; pattern?: string;
thickness?: number; thickness?: 'normal' | 'thick' | 'invisible';
useRough?: boolean; useRough?: boolean;
} }

View File

@@ -9,7 +9,7 @@ const markerOffsets = {
composition: 18, composition: 18,
dependency: 6, dependency: 6,
lollipop: 13.5, lollipop: 13.5,
arrow_point: 5.3, arrow_point: 4,
} as const; } as const;
/** /**