mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-12 11:59:39 +02:00
fix(#5952): handled additional edge cases
This commit is contained in:
@@ -219,13 +219,15 @@ const getEdges = (): ArchitectureEdge[] => state.records.edges;
|
|||||||
*/
|
*/
|
||||||
const getDataStructures = () => {
|
const getDataStructures = () => {
|
||||||
if (state.records.dataStructures === undefined) {
|
if (state.records.dataStructures === undefined) {
|
||||||
// Create an adjacency list of the diagram to perform BFS on
|
// Tracks how groups are aligned with one another. Generated while creating the adj list
|
||||||
// Outer reduce applied on all services
|
|
||||||
// Inner reduce applied on the edges for a service
|
|
||||||
const groupAlignments: Record<
|
const groupAlignments: Record<
|
||||||
string,
|
string,
|
||||||
Record<string, Exclude<ArchitectureAlignment, 'bend'>>
|
Record<string, Exclude<ArchitectureAlignment, 'bend'>>
|
||||||
> = {};
|
> = {};
|
||||||
|
|
||||||
|
// Create an adjacency list of the diagram to perform BFS on
|
||||||
|
// Outer reduce applied on all services
|
||||||
|
// Inner reduce applied on the edges for a service
|
||||||
const adjList = Object.entries(state.records.nodes).reduce<
|
const adjList = Object.entries(state.records.nodes).reduce<
|
||||||
Record<string, ArchitectureDirectionPairMap>
|
Record<string, ArchitectureDirectionPairMap>
|
||||||
>((prevOuter, [id, service]) => {
|
>((prevOuter, [id, service]) => {
|
||||||
|
@@ -159,11 +159,11 @@ function getAlignments(
|
|||||||
/**
|
/**
|
||||||
* Flattens the alignment object so nodes in different groups will be in the same alignment array IFF their groups don't connect in a conflicting alignment
|
* Flattens the alignment object so nodes in different groups will be in the same alignment array IFF their groups don't connect in a conflicting alignment
|
||||||
*
|
*
|
||||||
* i.e., two groups which connect horizontally should not have vertical alignments with one another
|
* i.e., two groups which connect horizontally should not have nodes with vertical alignments to one another
|
||||||
*
|
*
|
||||||
* See: #5952
|
* See: #5952
|
||||||
*
|
*
|
||||||
* @param alignmentObj - alignment object with the outer key being the row/col and the inner key being the group name
|
* @param alignmentObj - alignment object with the outer key being the row/col # and the inner key being the group name mapped to the nodes on that axis in the group
|
||||||
* @param alignmentDir - alignment direction
|
* @param alignmentDir - alignment direction
|
||||||
* @returns flattened alignment object with an arbitrary key mapping to nodes in the same row/col
|
* @returns flattened alignment object with an arbitrary key mapping to nodes in the same row/col
|
||||||
*/
|
*/
|
||||||
@@ -173,24 +173,36 @@ function getAlignments(
|
|||||||
): Record<string, string[]> => {
|
): Record<string, string[]> => {
|
||||||
return Object.entries(alignmentObj).reduce(
|
return Object.entries(alignmentObj).reduce(
|
||||||
(prev, [dir, alignments]) => {
|
(prev, [dir, alignments]) => {
|
||||||
|
// prev is the mapping of x/y coordinate to an array of the nodes in that row/column
|
||||||
let cnt = 0;
|
let cnt = 0;
|
||||||
const arr = Object.entries(alignments);
|
const arr = Object.entries(alignments); // [group name, array of nodes within the group on axis dir]
|
||||||
if (arr.length === 1) {
|
if (arr.length === 1) {
|
||||||
|
// If only one group exists in the row/column, we don't need to do anything else
|
||||||
prev[dir] = arr[0][1];
|
prev[dir] = arr[0][1];
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < arr.length - 1; i += 1) {
|
for (let i = 0; i < arr.length - 1; i++) {
|
||||||
const [aGroupId, aNodeIds] = arr[i];
|
for (let j = i + 1; j < arr.length; j++) {
|
||||||
const [bGroupId, bNodeIds] = arr[i + 1];
|
// Not optimal but arr will not grow large enough to be a concern
|
||||||
const alignment = groupAlignments[aGroupId][bGroupId];
|
const [aGroupId, aNodeIds] = arr[i];
|
||||||
if (alignment === alignmentDir) {
|
const [bGroupId, bNodeIds] = arr[j];
|
||||||
prev[dir] ??= [];
|
const alignment = groupAlignments[aGroupId]?.[bGroupId]; // Get how the two groups are intended to align (undefined if they aren't)
|
||||||
prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds];
|
|
||||||
} else {
|
if (alignment === alignmentDir) {
|
||||||
const keyA = `${dir}-${cnt++}`;
|
// If the intended alignment between the two groups is the same as the alignment we are parsing
|
||||||
prev[keyA] = aNodeIds;
|
prev[dir] ??= [];
|
||||||
const keyB = `${dir}-${cnt++}`;
|
prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds]; // add the node ids of both groups to the axis array in prev
|
||||||
prev[keyB] = bNodeIds;
|
} else if (aGroupId === 'default' || bGroupId === 'default') {
|
||||||
|
// If either of the groups are in the default space (not in a group), use the same behavior as above
|
||||||
|
prev[dir] ??= [];
|
||||||
|
prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds];
|
||||||
|
} else {
|
||||||
|
// Otherwise, the nodes in the two groups are not intended to align
|
||||||
|
const keyA = `${dir}-${cnt++}`;
|
||||||
|
prev[keyA] = aNodeIds;
|
||||||
|
const keyB = `${dir}-${cnt++}`;
|
||||||
|
prev[keyB] = bNodeIds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +388,6 @@ function layoutArchitecture(
|
|||||||
addServices(services, cy);
|
addServices(services, cy);
|
||||||
addJunctions(junctions, cy);
|
addJunctions(junctions, cy);
|
||||||
addEdges(edges, cy);
|
addEdges(edges, cy);
|
||||||
|
|
||||||
// Use the spatial map to create alignment arrays for fcose
|
// Use the spatial map to create alignment arrays for fcose
|
||||||
const alignmentConstraint = getAlignments(db, spatialMaps, groupAlignments);
|
const alignmentConstraint = getAlignments(db, spatialMaps, groupAlignments);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user