mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-25 03:06:50 +02:00
Merge pull request #5041 from mathbraga/feature/4935_subgraph-title-margin-config-option
Feature/4935 subgraph title margin config option
This commit is contained in:
@@ -886,4 +886,93 @@ end
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('Subgraph title margins', () => {
|
||||||
|
it('Should render subgraphs with title margins set (LR)', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`flowchart LR
|
||||||
|
|
||||||
|
subgraph TOP
|
||||||
|
direction TB
|
||||||
|
subgraph B1
|
||||||
|
direction RL
|
||||||
|
i1 -->f1
|
||||||
|
end
|
||||||
|
subgraph B2
|
||||||
|
direction BT
|
||||||
|
i2 -->f2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
A --> TOP --> B
|
||||||
|
B1 --> B2
|
||||||
|
`,
|
||||||
|
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Should render subgraphs with title margins set (TD)', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`flowchart TD
|
||||||
|
|
||||||
|
subgraph TOP
|
||||||
|
direction LR
|
||||||
|
subgraph B1
|
||||||
|
direction RL
|
||||||
|
i1 -->f1
|
||||||
|
end
|
||||||
|
subgraph B2
|
||||||
|
direction BT
|
||||||
|
i2 -->f2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
A --> TOP --> B
|
||||||
|
B1 --> B2
|
||||||
|
`,
|
||||||
|
{ flowchart: { subGraphTitleMargin: { top: 8, bottom: 16 } } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Should render subgraphs with title margins set (LR) and htmlLabels set to false', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`flowchart LR
|
||||||
|
|
||||||
|
subgraph TOP
|
||||||
|
direction TB
|
||||||
|
subgraph B1
|
||||||
|
direction RL
|
||||||
|
i1 -->f1
|
||||||
|
end
|
||||||
|
subgraph B2
|
||||||
|
direction BT
|
||||||
|
i2 -->f2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
A --> TOP --> B
|
||||||
|
B1 --> B2
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
htmlLabels: false,
|
||||||
|
flowchart: { htmlLabels: false, subGraphTitleMargin: { top: 10, bottom: 5 } },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Should render subgraphs with title margins and edge labels', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`flowchart LR
|
||||||
|
|
||||||
|
subgraph TOP
|
||||||
|
direction TB
|
||||||
|
subgraph B1
|
||||||
|
direction RL
|
||||||
|
i1 --lb1-->f1
|
||||||
|
end
|
||||||
|
subgraph B2
|
||||||
|
direction BT
|
||||||
|
i2 --lb2-->f2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
A --lb3--> TOP --lb4--> B
|
||||||
|
B1 --lb5--> B2
|
||||||
|
`,
|
||||||
|
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1411,6 +1411,14 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
|
|||||||
* Margin top for the text over the diagram
|
* Margin top for the text over the diagram
|
||||||
*/
|
*/
|
||||||
titleTopMargin?: number;
|
titleTopMargin?: number;
|
||||||
|
/**
|
||||||
|
* Defines a top/bottom margin for subgraph titles
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
subGraphTitleMargin?: {
|
||||||
|
top?: number;
|
||||||
|
bottom?: number;
|
||||||
|
};
|
||||||
arrowMarkerAbsolute?: boolean;
|
arrowMarkerAbsolute?: boolean;
|
||||||
/**
|
/**
|
||||||
* The amount of padding around the diagram as a whole so that embedded
|
* The amount of padding around the diagram as a whole so that embedded
|
||||||
|
@@ -5,9 +5,11 @@ import { createText } from '../rendering-util/createText.js';
|
|||||||
import { select } from 'd3';
|
import { select } from 'd3';
|
||||||
import { getConfig } from '../diagram-api/diagramAPI.js';
|
import { getConfig } from '../diagram-api/diagramAPI.js';
|
||||||
import { evaluate } from '../diagrams/common/common.js';
|
import { evaluate } from '../diagrams/common/common.js';
|
||||||
|
import { getSubGraphTitleMargins } from '../utils/subGraphTitleMargins.js';
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
// Add outer g element
|
// Add outer g element
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
@@ -18,7 +20,7 @@ const rect = (parent, node) => {
|
|||||||
// add the rect
|
// add the rect
|
||||||
const rect = shapeSvg.insert('rect', ':first-child');
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
const useHtmlLabels = evaluate(getConfig().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
|
||||||
const label = shapeSvg.insert('g').attr('class', 'cluster-label');
|
const label = shapeSvg.insert('g').attr('class', 'cluster-label');
|
||||||
@@ -34,7 +36,7 @@ const rect = (parent, node) => {
|
|||||||
// Get the size of the label
|
// Get the size of the label
|
||||||
let bbox = text.getBBox();
|
let bbox = text.getBBox();
|
||||||
|
|
||||||
if (evaluate(getConfig().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);
|
||||||
bbox = div.getBoundingClientRect();
|
bbox = div.getBoundingClientRect();
|
||||||
@@ -63,17 +65,18 @@ const rect = (parent, node) => {
|
|||||||
.attr('width', width)
|
.attr('width', width)
|
||||||
.attr('height', node.height + padding);
|
.attr('height', node.height + padding);
|
||||||
|
|
||||||
|
const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
|
||||||
if (useHtmlLabels) {
|
if (useHtmlLabels) {
|
||||||
label.attr(
|
label.attr(
|
||||||
'transform',
|
'transform',
|
||||||
// This puts the labal on top of the box instead of inside it
|
// This puts the labal on top of the box instead of inside it
|
||||||
'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2) + ')'
|
`translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
label.attr(
|
label.attr(
|
||||||
'transform',
|
'transform',
|
||||||
// This puts the labal on top of the box instead of inside it
|
// This puts the labal on top of the box instead of inside it
|
||||||
'translate(' + node.x + ', ' + (node.y - node.height / 2) + ')'
|
`translate(${node.x}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Center the label
|
// Center the label
|
||||||
@@ -127,6 +130,8 @@ const noteGroup = (parent, node) => {
|
|||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
};
|
||||||
const roundedWithTitle = (parent, node) => {
|
const roundedWithTitle = (parent, node) => {
|
||||||
|
const siteConfig = getConfig();
|
||||||
|
|
||||||
// Add outer g element
|
// Add outer g element
|
||||||
const shapeSvg = parent.insert('g').attr('class', node.classes).attr('id', node.id);
|
const shapeSvg = parent.insert('g').attr('class', node.classes).attr('id', node.id);
|
||||||
|
|
||||||
@@ -143,7 +148,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(getConfig().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);
|
||||||
bbox = div.getBoundingClientRect();
|
bbox = div.getBoundingClientRect();
|
||||||
@@ -175,6 +180,7 @@ const roundedWithTitle = (parent, node) => {
|
|||||||
.attr('width', width + padding)
|
.attr('width', width + padding)
|
||||||
.attr('height', node.height + padding - bbox.height - 3);
|
.attr('height', node.height + padding - bbox.height - 3);
|
||||||
|
|
||||||
|
const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
|
||||||
// Center the label
|
// Center the label
|
||||||
label.attr(
|
label.attr(
|
||||||
'transform',
|
'transform',
|
||||||
@@ -184,7 +190,8 @@ const roundedWithTitle = (parent, node) => {
|
|||||||
(node.y -
|
(node.y -
|
||||||
node.height / 2 -
|
node.height / 2 -
|
||||||
node.padding / 3 +
|
node.padding / 3 +
|
||||||
(evaluate(getConfig().flowchart.htmlLabels) ? 5 : 3)) +
|
(evaluate(siteConfig.flowchart.htmlLabels) ? 5 : 3)) +
|
||||||
|
subGraphTitleTopMargin +
|
||||||
')'
|
')'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ import { getConfig } from '../diagram-api/diagramAPI.js';
|
|||||||
import utils from '../utils.js';
|
import utils from '../utils.js';
|
||||||
import { evaluate } from '../diagrams/common/common.js';
|
import { evaluate } from '../diagrams/common/common.js';
|
||||||
import { getLineFunctionsWithOffset } from '../utils/lineWithOffset.js';
|
import { getLineFunctionsWithOffset } from '../utils/lineWithOffset.js';
|
||||||
|
import { getSubGraphTitleMargins } from '../utils/subGraphTitleMargins.js';
|
||||||
import { addEdgeMarkers } from './edgeMarker.js';
|
import { addEdgeMarkers } from './edgeMarker.js';
|
||||||
|
|
||||||
let edgeLabels = {};
|
let edgeLabels = {};
|
||||||
@@ -136,6 +137,8 @@ function setTerminalWidth(fo, value) {
|
|||||||
export const positionEdgeLabel = (edge, paths) => {
|
export const positionEdgeLabel = (edge, paths) => {
|
||||||
log.info('Moving label abc78 ', edge.id, edge.label, edgeLabels[edge.id]);
|
log.info('Moving label abc78 ', edge.id, edge.label, edgeLabels[edge.id]);
|
||||||
let path = paths.updatedPath ? paths.updatedPath : paths.originalPath;
|
let path = paths.updatedPath ? paths.updatedPath : paths.originalPath;
|
||||||
|
const siteConfig = getConfig();
|
||||||
|
const { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);
|
||||||
if (edge.label) {
|
if (edge.label) {
|
||||||
const el = edgeLabels[edge.id];
|
const el = edgeLabels[edge.id];
|
||||||
let x = edge.x;
|
let x = edge.x;
|
||||||
@@ -159,7 +162,7 @@ export const positionEdgeLabel = (edge, paths) => {
|
|||||||
y = pos.y;
|
y = pos.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
el.attr('transform', 'translate(' + x + ', ' + y + ')');
|
el.attr('transform', `translate(${x}, ${y + subGraphTitleTotalMargin / 2})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
//let path = paths.updatedPath ? paths.updatedPath : paths.originalPath;
|
//let path = paths.updatedPath ? paths.updatedPath : paths.originalPath;
|
||||||
@@ -173,7 +176,7 @@ export const positionEdgeLabel = (edge, paths) => {
|
|||||||
x = pos.x;
|
x = pos.x;
|
||||||
y = pos.y;
|
y = pos.y;
|
||||||
}
|
}
|
||||||
el.attr('transform', 'translate(' + x + ', ' + y + ')');
|
el.attr('transform', `translate(${x}, ${y})`);
|
||||||
}
|
}
|
||||||
if (edge.startLabelRight) {
|
if (edge.startLabelRight) {
|
||||||
const el = terminalLabels[edge.id].startRight;
|
const el = terminalLabels[edge.id].startRight;
|
||||||
@@ -189,7 +192,7 @@ export const positionEdgeLabel = (edge, paths) => {
|
|||||||
x = pos.x;
|
x = pos.x;
|
||||||
y = pos.y;
|
y = pos.y;
|
||||||
}
|
}
|
||||||
el.attr('transform', 'translate(' + x + ', ' + y + ')');
|
el.attr('transform', `translate(${x}, ${y})`);
|
||||||
}
|
}
|
||||||
if (edge.endLabelLeft) {
|
if (edge.endLabelLeft) {
|
||||||
const el = terminalLabels[edge.id].endLeft;
|
const el = terminalLabels[edge.id].endLeft;
|
||||||
@@ -201,7 +204,7 @@ export const positionEdgeLabel = (edge, paths) => {
|
|||||||
x = pos.x;
|
x = pos.x;
|
||||||
y = pos.y;
|
y = pos.y;
|
||||||
}
|
}
|
||||||
el.attr('transform', 'translate(' + x + ', ' + y + ')');
|
el.attr('transform', `translate(${x}, ${y})`);
|
||||||
}
|
}
|
||||||
if (edge.endLabelRight) {
|
if (edge.endLabelRight) {
|
||||||
const el = terminalLabels[edge.id].endRight;
|
const el = terminalLabels[edge.id].endRight;
|
||||||
@@ -213,7 +216,7 @@ export const positionEdgeLabel = (edge, paths) => {
|
|||||||
x = pos.x;
|
x = pos.x;
|
||||||
y = pos.y;
|
y = pos.y;
|
||||||
}
|
}
|
||||||
el.attr('transform', 'translate(' + x + ', ' + y + ')');
|
el.attr('transform', `translate(${x}, ${y})`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -13,8 +13,10 @@ import { insertNode, positionNode, clear as clearNodes, setNodeElem } from './no
|
|||||||
import { insertCluster, clear as clearClusters } from './clusters.js';
|
import { insertCluster, clear as clearClusters } from './clusters.js';
|
||||||
import { insertEdgeLabel, positionEdgeLabel, insertEdge, clear as clearEdges } from './edges.js';
|
import { insertEdgeLabel, positionEdgeLabel, insertEdge, clear as clearEdges } from './edges.js';
|
||||||
import { log } from '../logger.js';
|
import { log } from '../logger.js';
|
||||||
|
import { getSubGraphTitleMargins } from '../utils/subGraphTitleMargins.js';
|
||||||
|
import { getConfig } from '../diagram-api/diagramAPI.js';
|
||||||
|
|
||||||
const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster) => {
|
const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster, siteConfig) => {
|
||||||
log.info('Graph in recursive render: XXX', graphlibJson.write(graph), parentCluster);
|
log.info('Graph in recursive render: XXX', graphlibJson.write(graph), parentCluster);
|
||||||
const dir = graph.graph().rankdir;
|
const dir = graph.graph().rankdir;
|
||||||
log.trace('Dir in recursive render - dir:', dir);
|
log.trace('Dir in recursive render - dir:', dir);
|
||||||
@@ -52,7 +54,14 @@ const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster) =>
|
|||||||
if (node && node.clusterNode) {
|
if (node && node.clusterNode) {
|
||||||
// const children = graph.children(v);
|
// const children = graph.children(v);
|
||||||
log.info('Cluster identified', v, node.width, graph.node(v));
|
log.info('Cluster identified', v, node.width, graph.node(v));
|
||||||
const o = await recursiveRender(nodes, node.graph, diagramtype, id, graph.node(v));
|
const o = await recursiveRender(
|
||||||
|
nodes,
|
||||||
|
node.graph,
|
||||||
|
diagramtype,
|
||||||
|
id,
|
||||||
|
graph.node(v),
|
||||||
|
siteConfig
|
||||||
|
);
|
||||||
const newEl = o.elem;
|
const newEl = o.elem;
|
||||||
updateNodeBounds(node, newEl);
|
updateNodeBounds(node, newEl);
|
||||||
node.diff = o.diff || 0;
|
node.diff = o.diff || 0;
|
||||||
@@ -101,6 +110,7 @@ const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster) =>
|
|||||||
log.info('Graph after layout:', graphlibJson.write(graph));
|
log.info('Graph after layout:', graphlibJson.write(graph));
|
||||||
// Move the nodes to the correct place
|
// Move the nodes to the correct place
|
||||||
let diff = 0;
|
let diff = 0;
|
||||||
|
const { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);
|
||||||
sortNodesByHierarchy(graph).forEach(function (v) {
|
sortNodesByHierarchy(graph).forEach(function (v) {
|
||||||
const node = graph.node(v);
|
const node = graph.node(v);
|
||||||
log.info('Position ' + v + ': ' + JSON.stringify(graph.node(v)));
|
log.info('Position ' + v + ': ' + JSON.stringify(graph.node(v)));
|
||||||
@@ -114,16 +124,18 @@ const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster) =>
|
|||||||
);
|
);
|
||||||
if (node && node.clusterNode) {
|
if (node && node.clusterNode) {
|
||||||
// clusterDb[node.id].node = node;
|
// clusterDb[node.id].node = node;
|
||||||
|
node.y += subGraphTitleTotalMargin;
|
||||||
positionNode(node);
|
positionNode(node);
|
||||||
} else {
|
} else {
|
||||||
// Non cluster node
|
// Non cluster node
|
||||||
if (graph.children(v).length > 0) {
|
if (graph.children(v).length > 0) {
|
||||||
// A cluster in the non-recursive way
|
// A cluster in the non-recursive way
|
||||||
// positionCluster(node);
|
// positionCluster(node);
|
||||||
|
node.height += subGraphTitleTotalMargin;
|
||||||
insertCluster(clusters, node);
|
insertCluster(clusters, node);
|
||||||
clusterDb[node.id].node = node;
|
clusterDb[node.id].node = node;
|
||||||
} else {
|
} else {
|
||||||
|
node.y += subGraphTitleTotalMargin / 2;
|
||||||
positionNode(node);
|
positionNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,6 +146,7 @@ const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster) =>
|
|||||||
const edge = graph.edge(e);
|
const edge = graph.edge(e);
|
||||||
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));
|
||||||
const paths = insertEdge(edgePaths, e, edge, clusterDb, diagramtype, graph, id);
|
const paths = insertEdge(edgePaths, e, edge, clusterDb, diagramtype, graph, id);
|
||||||
positionEdgeLabel(edge, paths);
|
positionEdgeLabel(edge, paths);
|
||||||
});
|
});
|
||||||
@@ -159,7 +172,8 @@ export const render = async (elem, graph, markers, diagramtype, id) => {
|
|||||||
adjustClustersAndEdges(graph);
|
adjustClustersAndEdges(graph);
|
||||||
log.warn('Graph after:', JSON.stringify(graphlibJson.write(graph)));
|
log.warn('Graph after:', JSON.stringify(graphlibJson.write(graph)));
|
||||||
// log.warn('Graph ever after:', graphlibJson.write(graph.node('A').graph));
|
// log.warn('Graph ever after:', graphlibJson.write(graph.node('A').graph));
|
||||||
await recursiveRender(elem, graph, diagramtype, id);
|
const siteConfig = getConfig();
|
||||||
|
await recursiveRender(elem, graph, diagramtype, id, undefined, siteConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const shapeDefinitions = {};
|
// const shapeDefinitions = {};
|
||||||
|
@@ -1863,6 +1863,7 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file)
|
|||||||
unevaluatedProperties: false
|
unevaluatedProperties: false
|
||||||
required:
|
required:
|
||||||
- titleTopMargin
|
- titleTopMargin
|
||||||
|
- subGraphTitleMargin
|
||||||
- diagramPadding
|
- diagramPadding
|
||||||
- htmlLabels
|
- htmlLabels
|
||||||
- nodeSpacing
|
- nodeSpacing
|
||||||
@@ -1875,6 +1876,20 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file)
|
|||||||
titleTopMargin:
|
titleTopMargin:
|
||||||
$ref: '#/$defs/GitGraphDiagramConfig/properties/titleTopMargin'
|
$ref: '#/$defs/GitGraphDiagramConfig/properties/titleTopMargin'
|
||||||
default: 25
|
default: 25
|
||||||
|
subGraphTitleMargin:
|
||||||
|
description: |
|
||||||
|
Defines a top/bottom margin for subgraph titles
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
top:
|
||||||
|
type: integer
|
||||||
|
minimum: 0
|
||||||
|
bottom:
|
||||||
|
type: integer
|
||||||
|
minimum: 0
|
||||||
|
default:
|
||||||
|
top: 0
|
||||||
|
bottom: 0
|
||||||
arrowMarkerAbsolute:
|
arrowMarkerAbsolute:
|
||||||
type: boolean # TODO, is this actually used here (it has no default value but was in types)
|
type: boolean # TODO, is this actually used here (it has no default value but was in types)
|
||||||
diagramPadding:
|
diagramPadding:
|
||||||
|
22
packages/mermaid/src/utils/subGraphTitleMargins.spec.ts
Normal file
22
packages/mermaid/src/utils/subGraphTitleMargins.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { getSubGraphTitleMargins } from './subGraphTitleMargins.js';
|
||||||
|
import * as configApi from '../config.js';
|
||||||
|
|
||||||
|
describe('getSubGraphTitleMargins', () => {
|
||||||
|
it('should get subgraph title margins after config has been set', () => {
|
||||||
|
const config_0 = {
|
||||||
|
flowchart: {
|
||||||
|
subGraphTitleMargin: {
|
||||||
|
top: 10,
|
||||||
|
bottom: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
configApi.setSiteConfig(config_0);
|
||||||
|
expect(getSubGraphTitleMargins(config_0)).toEqual({
|
||||||
|
subGraphTitleTopMargin: 10,
|
||||||
|
subGraphTitleBottomMargin: 5,
|
||||||
|
subGraphTitleTotalMargin: 15,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
21
packages/mermaid/src/utils/subGraphTitleMargins.ts
Normal file
21
packages/mermaid/src/utils/subGraphTitleMargins.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import type { FlowchartDiagramConfig } from '../config.type.js';
|
||||||
|
|
||||||
|
export const getSubGraphTitleMargins = ({
|
||||||
|
flowchart,
|
||||||
|
}: {
|
||||||
|
flowchart: FlowchartDiagramConfig;
|
||||||
|
}): {
|
||||||
|
subGraphTitleTopMargin: number;
|
||||||
|
subGraphTitleBottomMargin: number;
|
||||||
|
subGraphTitleTotalMargin: number;
|
||||||
|
} => {
|
||||||
|
const subGraphTitleTopMargin = flowchart?.subGraphTitleMargin?.top ?? 0;
|
||||||
|
const subGraphTitleBottomMargin = flowchart?.subGraphTitleMargin?.bottom ?? 0;
|
||||||
|
const subGraphTitleTotalMargin = subGraphTitleTopMargin + subGraphTitleBottomMargin;
|
||||||
|
|
||||||
|
return {
|
||||||
|
subGraphTitleTopMargin,
|
||||||
|
subGraphTitleBottomMargin,
|
||||||
|
subGraphTitleTotalMargin,
|
||||||
|
};
|
||||||
|
};
|
Reference in New Issue
Block a user