Merge branch 'alanaV11' into pebr/neo-style

This commit is contained in:
Per Brolin
2024-06-11 16:14:34 +02:00
8 changed files with 156 additions and 47 deletions

View File

@@ -76,6 +76,62 @@
</head> </head>
<body> <body>
<pre id="diagram" class="mermaid"> <pre id="diagram" class="mermaid">
flowchart LR
subgraph Apa["Apa"]
A["Start"]
B["This is B"]
end
A --> B & C["C"]
Apa --> C
</pre
>
<pre id="diagram" class="mermaid">
flowchart LR
subgraph Apa["Apa"]
B["This is B"]
A["Start"]
end
A --> B & C["C"]
Apa --> C
</pre
>
<pre id="diagram" class="mermaid">
flowchart RL
subgraph Apa["Apa"]
subgraph Gorilla
A["Start"]
B["This is B"]
end
end
A --> B & C["C"]
Gorilla --> C
</pre
>
<pre id="diagram" class="mermaid">
flowchart LR
subgraph Apa["Apa"]
subgraph Gorilla
A["Start"]
B["This is B"]
end
end
A --> B & C["C"]
Apa --> C
</pre
>
<pre id="diagram" class="mermaid2">
flowchart LR
subgraph Apa["Apa"]
subgraph Gorilla
B["This is B"]
A["Start"]
end
end
Apa --> C
A --> B & C["C"]
</pre
>
<pre id="diagram" class="mermaid2">
stateDiagram stateDiagram
direction LR direction LR
state Gorilla0 { state Gorilla0 {
@@ -88,7 +144,7 @@ direction LR
A0 --> C0 A0 --> C0
</pre </pre
> >
<pre id="diagram" class="mermaid"> <pre id="diagram" class="mermaid2">
flowchart LR flowchart LR
subgraph Gorilla subgraph Gorilla
subgraph Apa subgraph Apa
@@ -106,6 +162,17 @@ stateDiagram
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid2">
flowchart LR
subgraph Apa["Apa"]
A["Start"]
B["This is B"]
end
A --> B & C["C"]
Apa --> C
</pre
>
<pre id="diagram" class="mermaid2">
%%{init: {"layout": "dagre", "mergeEdges": false} }%% %%{init: {"layout": "dagre", "mergeEdges": false} }%%
flowchart LR flowchart LR
A ==> B(This is B) A ==> B(This is B)
@@ -134,7 +201,7 @@ flowchart
if_state --> True : if n >= 0 if_state --> True : if n >= 0
</pre </pre
> >
<pre id="diagram" class="mermaid3"> <pre id="diagram" class="mermaid2">
%%{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;
@@ -144,12 +211,12 @@ flowchart
if_state --> True : if n >= 0 if_state --> True : if n >= 0
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid">
%%{init: {"layout": "dagre", "mergeEdges": true} }%% %%{init: {"layout": "dagre", "mergeEdges": true} }%%
stateDiagram stateDiagram
direction TB direction TB
State T1 { State T1 {
T11 --> T12 T12--> T11
} }
T1 --> T2 T1 --> T2
T11 --> T2 T11 --> T2
@@ -165,16 +232,17 @@ State T1 {
} }
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid">
%%{init: {"layout": "elk", "mergeEdges": true} }%% %%{init: {"layouts": "elk2", "mergeEdges": true} }%%
stateDiagram stateDiagram
State S1 {
direction TB direction TB
State T1 { S11
T11
} }
S1 --> S2
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid">
%%{init: {"layout": "elk", "mergeEdges": true} }%% %%{init: {"layout": "elk", "mergeEdges": true} }%%
stateDiagram stateDiagram
State T1 { State T1 {
@@ -184,7 +252,7 @@ State T1 {
} }
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid">
%%{init: {"layout": "elk", "mergeEdges": true} }%% %%{init: {"layout": "elk", "mergeEdges": true} }%%
stateDiagram stateDiagram
[*] --> T1 [*] --> T1
@@ -228,18 +296,18 @@ stateDiagram-v2
<script type="module"> <script type="module">
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
import { layouts } from './mermaid-layout-elk.esm.mjs'; // import { layouts } from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts); // mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) { mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err); console.error('Mermaid error: ', err);
}; };
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, // htmlLabels: false,
flowchart: { titleTopMargin: 10 }, flowchart: { titleTopMargin: 10 },

View File

@@ -7,6 +7,12 @@ export const findCommonAncestor = (id1: string, id2: string, treeData: TreeData)
const { parentById } = treeData; const { parentById } = treeData;
const visited = new Set(); const visited = new Set();
let currentId = id1; let currentId = id1;
// Edge case with self edges
if (id1 === id2) {
return parentById[id1] || 'root';
}
while (currentId) { while (currentId) {
visited.add(currentId); visited.add(currentId);
if (currentId === id2) { if (currentId === id2) {

View File

@@ -68,6 +68,15 @@ g.stateGroup line {
fill: ${options.labelBackgroundColor}; fill: ${options.labelBackgroundColor};
opacity: 0.5; opacity: 0.5;
} }
.edgeLabel {
background-color: ${options.edgeLabelBackground};
rect {
opacity: 0.5;
background-color: ${options.edgeLabelBackground};
fill: ${options.edgeLabelBackground};
}
text-align: center;
}
.edgeLabel .label text { .edgeLabel .label text {
fill: ${options.transitionLabelColor || options.tertiaryTextColor}; fill: ${options.transitionLabelColor || options.tertiaryTextColor};
} }
@@ -124,6 +133,7 @@ g.stateGroup line {
.cluster-label, .nodeLabel { .cluster-label, .nodeLabel {
color: ${options.stateLabelColor}; color: ${options.stateLabelColor};
line-height: 1.0;
} }
.statediagram-cluster rect.outer { .statediagram-cluster rect.outer {

View File

@@ -162,7 +162,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
node.x -= 8; node.x -= 8;
log.info( log.info(
'A tainted cluster node XBX', 'A pure cluster node XBX',
v, v,
node.id, node.id,
node.width, node.width,
@@ -188,7 +188,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
// A cluster in the non-recursive way // A cluster in the non-recursive way
log.info( log.info(
'A pure cluster node with children XBX', 'A tainted cluster node with children XBX',
v, v,
node.id, node.id,
node.width, node.width,

View File

@@ -152,27 +152,58 @@ export const validate = (graph) => {
return true; return true;
}; };
const findCommonEdges = (graph, id1, id2) => {
const edges1 = graph.edges().filter((edge) => edge.v === id1 || edge.w === id1);
const edges2 = graph.edges().filter((edge) => edge.v === id2 || edge.w === id2);
const edges1Prim = edges1.map((edge) => {
return { v: edge.v === id1 ? id2 : edge.v, w: edge.w === id1 ? id1 : edge.w };
});
const edges2Prim = edges2.map((edge) => {
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 result;
};
/** /**
* Finds a child that is not a cluster. When faking an edge between a node and a cluster. * Finds a child that is not a cluster. When faking an edge between a node and a cluster.
* *
* @param id * @param id
* @param {any} graph * @param {any} graph
*/ */
export const findNonClusterChild = (id, graph) => { export const findNonClusterChild = (id, graph, clusterId) => {
log.trace('Searching', id); const children = graph.children(id);
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);
return id; return id;
} }
let reserve;
for (const child of children) { for (const child of children) {
const _id = findNonClusterChild(child, graph); const _id = findNonClusterChild(child, graph, clusterId);
// Edge chase where the cluster has an edge to a node and the selected
// child has a link to the same node
const commonEdges = findCommonEdges(graph, clusterId, _id);
if (_id) { if (_id) {
log.trace('Found replacement for', id, ' => ', _id); if (commonEdges.length > 0) {
// console.log(
// '\x1B[44;93;4m abc24 The replacement also has an edge',
// clusterId,
// ' => ',
// _id,
// graph.edges()
// );
reserve = _id;
} else {
return _id; return _id;
} }
} }
}
return reserve;
}; };
const getAnchorId = (id) => { const getAnchorId = (id) => {
@@ -207,10 +238,10 @@ export const adjustClustersAndEdges = (graph, depth) => {
'Cluster identified', 'Cluster identified',
id, id,
' Replacement id in edges: ', ' Replacement id in edges: ',
findNonClusterChild(id, graph) findNonClusterChild(id, graph, id)
); );
descendants[id] = extractDescendants(id, graph); descendants[id] = extractDescendants(id, graph);
clusterDb[id] = { id: findNonClusterChild(id, graph), clusterData: graph.node(id) }; clusterDb[id] = { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) };
} }
}); });

View File

@@ -10,11 +10,6 @@ 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'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
// Helper function to calculate the offset correction for the label
const calcLabelOffsetCorrection = (diff) => {
return diff * 0.75 - 6;
};
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();
@@ -196,6 +191,7 @@ const roundedWithTitle = (parent, node) => {
// Get the size of the label // Get the size of the label
let bbox = text.getBBox(); let bbox = text.getBBox();
if (evaluate(siteConfig.flowchart.htmlLabels)) { if (evaluate(siteConfig.flowchart.htmlLabels)) {
const div = text.children[0]; const div = text.children[0];
const dv = select(text); const dv = select(text);
@@ -203,6 +199,7 @@ const roundedWithTitle = (parent, node) => {
dv.attr('width', bbox.width); dv.attr('width', bbox.width);
dv.attr('height', bbox.height); dv.attr('height', bbox.height);
} }
const padding = 0 * node.padding; const padding = 0 * node.padding;
const halfPadding = padding / 2; const halfPadding = padding / 2;
@@ -216,10 +213,11 @@ const roundedWithTitle = (parent, node) => {
const x = node.x - width / 2 - halfPadding; const x = node.x - width / 2 - halfPadding;
const y = node.y - node.height / 2 - halfPadding; const y = node.y - node.height / 2 - halfPadding;
const innerY = node.y - node.height / 2 - halfPadding + bbox.height - 1; const innerY = node.y - node.height / 2 - halfPadding + bbox.height + 2;
const height = node.height + padding; const height = node.height + padding;
const innerHeight = node.height + padding - bbox.height - 3; const innerHeight = node.height + padding - bbox.height - 2;
const look = siteConfig.look; const look = siteConfig.look;
// add the rect // add the rect
let rect; let rect;
if (node.look === 'handdrawn') { if (node.look === 'handdrawn') {
@@ -270,12 +268,9 @@ const roundedWithTitle = (parent, node) => {
.attr('height', innerHeight); .attr('height', innerHeight);
} }
let diff = bbox.height - (innerY - y) / 2;
let correction = calcLabelOffsetCorrection(diff, bbox.height);
label.attr( label.attr(
'transform', 'transform',
`translate(${node.x - bbox.width / 2}, ${(innerY - y) / 2 - correction})` `translate(${node.x - bbox.width / 2}, ${y + 1 - (evaluate(siteConfig.flowchart.htmlLabels) ? 0 : 3)})`
); );
const rectBox = rect.node().getBBox(); const rectBox = rect.node().getBBox();

View File

@@ -273,7 +273,6 @@ export const intersection = (node, outsidePoint, insidePoint) => {
// log.warn(); // log.warn();
if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) { if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) {
// Intersection is top or bottom of rect. // Intersection is top or bottom of rect.
// let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y; let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
r = (R * q) / Q; r = (R * q) / Q;
const res = { const res = {
@@ -281,10 +280,10 @@ export const intersection = (node, outsidePoint, insidePoint) => {
y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q, y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q,
}; };
if (r === 0) { // if (r === 0) {
res.x = outsidePoint.x; // res.x = outsidePoint.x;
res.y = outsidePoint.y; // res.y = outsidePoint.y;
} // }
if (R === 0) { if (R === 0) {
res.x = outsidePoint.x; res.x = outsidePoint.x;
} }
@@ -292,7 +291,7 @@ export const intersection = (node, outsidePoint, insidePoint) => {
res.y = outsidePoint.y; res.y = outsidePoint.y;
} }
log.warn(`abc89 top/bot calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res); log.warn(`abc89 top/bot calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res, 'apa');
return res; return res;
} else { } else {
@@ -347,7 +346,7 @@ const cutPathAtIntersect = (_points, boundaryNode) => {
// Calc the intersection coord between the point anf the last point outside the rect // Calc the intersection coord between the point anf the last point outside the rect
const inter = intersection(boundaryNode, lastPointOutside, point); const inter = intersection(boundaryNode, lastPointOutside, point);
log.warn('abc88 inside', point, lastPointOutside, inter); log.warn('abc88 inside', point, lastPointOutside, inter);
log.warn('abc88 intersection', inter); log.warn('abc88 intersection', inter, boundaryNode);
// // Check case where the intersection is the same as the last point // // Check case where the intersection is the same as the last point
let pointPresent = false; let pointPresent = false;

View File

@@ -34,7 +34,7 @@ class Theme {
this.arrowheadColor = '#333333'; this.arrowheadColor = '#333333';
this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif';
this.fontSize = '16px'; this.fontSize = '16px';
this.labelBackground = '#e8e8e8'; this.labelBackground = 'rgba(232,232,232,0.6)';
this.textColor = '#333'; this.textColor = '#333';
this.THEME_COLOR_LIMIT = 12; this.THEME_COLOR_LIMIT = 12;
this.radius = 5; this.radius = 5;