mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-28 11:49:37 +02:00
feat(arch): dynamic node sizing
This commit is contained in:
@@ -638,7 +638,7 @@ export interface RequirementDiagramConfig extends BaseDiagramConfig {
|
||||
*/
|
||||
export interface ArchitectureDiagramConfig extends BaseDiagramConfig {
|
||||
padding?: number;
|
||||
maxNodeWidth?: number;
|
||||
iconSize?: number;
|
||||
}
|
||||
/**
|
||||
* The object containing configurations specific for mindmap diagrams
|
||||
|
@@ -6,6 +6,7 @@ import type {
|
||||
ArchitectureDirection,
|
||||
ArchitectureLine,
|
||||
} from './architectureTypes.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import { isArchitectureDirection } from './architectureTypes.js';
|
||||
import {
|
||||
setAccTitle,
|
||||
@@ -36,10 +37,6 @@ let lines = DEFAULT_ARCHITECTURE_DB.lines;
|
||||
let elements: Record<string, D3Element> = {};
|
||||
let cnt = DEFAULT_ARCHITECTURE_DB.cnt;
|
||||
|
||||
const config: Required<ArchitectureDiagramConfig> = structuredClone(DEFAULT_ARCHITECTURE_CONFIG);
|
||||
|
||||
const getConfig = (): Required<ArchitectureDiagramConfig> => structuredClone(config);
|
||||
|
||||
const clear = (): void => {
|
||||
services = structuredClone(DEFAULT_ARCHITECTURE_DB.services);
|
||||
groups = structuredClone(DEFAULT_ARCHITECTURE_DB.groups);
|
||||
@@ -109,7 +106,6 @@ const setElementForId = (id: string, element: D3Element) => {
|
||||
const getElementById = (id: string) => elements[id];
|
||||
|
||||
export const db: ArchitectureDB = {
|
||||
getConfig,
|
||||
clear,
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
@@ -127,3 +123,14 @@ export const db: ArchitectureDB = {
|
||||
setElementForId,
|
||||
getElementById,
|
||||
};
|
||||
|
||||
function getConfigField<T extends keyof ArchitectureDiagramConfig>(field: T): Required<ArchitectureDiagramConfig>[T] {
|
||||
const arch = getConfig().architecture;
|
||||
if (arch && arch[field] !== undefined) {
|
||||
const a = arch[field];
|
||||
return arch[field] as Required<ArchitectureDiagramConfig>[T]
|
||||
}
|
||||
return DEFAULT_ARCHITECTURE_CONFIG[field]
|
||||
}
|
||||
|
||||
export { getConfigField }
|
@@ -17,9 +17,9 @@ import {
|
||||
} from './architectureTypes.js';
|
||||
import { select } from 'd3';
|
||||
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
import defaultConfig from '../../defaultConfig.js';
|
||||
import type { D3Element } from '../../mermaidAPI.js';
|
||||
import { drawEdges, drawGroups, drawService } from './svgDraw.js';
|
||||
import { getConfigField } from './architectureDb.js';
|
||||
|
||||
cytoscape.use(fcose);
|
||||
|
||||
@@ -33,9 +33,8 @@ function addServices(services: ArchitectureService[], cy: cytoscape.Core) {
|
||||
icon: service.icon,
|
||||
label: service.title,
|
||||
parent: service.in,
|
||||
// TODO: dynamic size
|
||||
width: 80,
|
||||
height: 80,
|
||||
width: getConfigField('iconSize'),
|
||||
height: getConfigField('iconSize'),
|
||||
},
|
||||
classes: 'node-service',
|
||||
});
|
||||
@@ -286,8 +285,8 @@ export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram)
|
||||
setupGraphViewbox(
|
||||
undefined,
|
||||
svg,
|
||||
conf.architecture?.padding ?? defaultConfig.architecture.padding,
|
||||
conf.architecture?.useMaxWidth ?? defaultConfig.architecture.useMaxWidth
|
||||
getConfigField('padding'),
|
||||
getConfigField('useMaxWidth')
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -8,6 +8,7 @@ import type { MermaidConfig } from '../../config.type.js';
|
||||
import type cytoscape from 'cytoscape';
|
||||
import { log } from '../../logger.js';
|
||||
import { getIcon, isIconNameInUse } from '../../rendering-util/svgRegister.js';
|
||||
import { getConfigField } from './architectureDb.js';
|
||||
|
||||
declare module 'cytoscape' {
|
||||
interface EdgeSingular {
|
||||
@@ -76,20 +77,23 @@ export const drawEdges = function (edgesEl: D3Element, cy: cytoscape.Core) {
|
||||
};
|
||||
|
||||
export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
|
||||
const iconSize = getConfigField('iconSize')
|
||||
const halfIconSize = iconSize / 2
|
||||
|
||||
cy.nodes().map((node, id) => {
|
||||
const data = node.data();
|
||||
if (data.type === 'group') {
|
||||
const { h, w, x1, x2, y1, y2 } = node.boundingBox();
|
||||
let bkgElem = groupsEl
|
||||
.append('rect')
|
||||
.attr('x', x1 + 40)
|
||||
.attr('y', y1 + 40)
|
||||
.attr('x', x1 + halfIconSize)
|
||||
.attr('y', y1 + halfIconSize)
|
||||
.attr('width', w)
|
||||
.attr('height', h)
|
||||
.attr('class', 'node-bkg');
|
||||
|
||||
const textElem = groupsEl.append('g');
|
||||
createText(textElem, data.title, {
|
||||
createText(textElem, data.label, {
|
||||
useHtmlLabels: false,
|
||||
width: w,
|
||||
classes: 'architecture-service-label',
|
||||
@@ -100,7 +104,7 @@ export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
|
||||
.attr('dominant-baseline', 'start')
|
||||
.attr('text-anchor', 'start');
|
||||
|
||||
textElem.attr('transform', 'translate(' + (x1 + 44) + ', ' + (y1 + 42) + ')');
|
||||
textElem.attr('transform', 'translate(' + (x1 + halfIconSize + 4) + ', ' + (y1 + halfIconSize + 2) + ')');
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -112,6 +116,7 @@ export const drawService = function (
|
||||
conf: MermaidConfig
|
||||
): number {
|
||||
const serviceElem = elem.append('g');
|
||||
const iconSize = getConfigField('iconSize')
|
||||
|
||||
if (service.title) {
|
||||
const textElem = serviceElem.append('g');
|
||||
@@ -129,7 +134,7 @@ export const drawService = function (
|
||||
textElem.attr(
|
||||
'transform',
|
||||
// TODO: dynamic size
|
||||
'translate(' + 80 / 2 + ', ' + 80 + ')'
|
||||
'translate(' + (iconSize / 2) + ', ' + iconSize + ')'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -138,13 +143,13 @@ export const drawService = function (
|
||||
if (!isIconNameInUse(service.icon)) {
|
||||
throw new Error(`Invalid SVG Icon name: "${service.icon}"`);
|
||||
}
|
||||
bkgElem = getIcon(service.icon)?.(bkgElem);
|
||||
bkgElem = getIcon(service.icon)?.(bkgElem, iconSize);
|
||||
} else {
|
||||
bkgElem
|
||||
.append('path')
|
||||
.attr('class', 'node-bkg')
|
||||
.attr('id', 'node-' + service.id)
|
||||
.attr('d', `M0 ${80 - 0} v${-80 + 2 * 0} q0,-5 5,-5 h${80 - 2 * 0} q5,0 5,5 v${80 - 0} H0 Z`);
|
||||
.attr('d', `M0 ${iconSize - 0} v${-iconSize + 2 * 0} q0,-5 5,-5 h${iconSize - 2 * 0} q5,0 5,5 v${iconSize - 0} H0 Z`);
|
||||
}
|
||||
|
||||
serviceElem.attr('class', 'architecture-service');
|
||||
|
@@ -865,14 +865,14 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file)
|
||||
required:
|
||||
- useMaxWidth
|
||||
- padding
|
||||
- maxNodeWidth
|
||||
- iconSize
|
||||
properties:
|
||||
padding:
|
||||
type: number
|
||||
default: 10
|
||||
maxNodeWidth:
|
||||
iconSize:
|
||||
type: number
|
||||
default: 200
|
||||
default: 80
|
||||
|
||||
MindmapDiagramConfig:
|
||||
title: Mindmap Diagram Config
|
||||
|
Reference in New Issue
Block a user