From a493e2fbb31d141301f717efc0b21fe402161af7 Mon Sep 17 00:00:00 2001 From: NicolasNewman Date: Mon, 25 Mar 2024 14:17:05 -0500 Subject: [PATCH] feat(arch): dynamic node sizing --- packages/mermaid/src/config.type.ts | 2 +- .../diagrams/architecture/architectureDb.ts | 17 ++++++++++++----- .../architecture/architectureRenderer.ts | 11 +++++------ .../src/diagrams/architecture/svgDraw.ts | 19 ++++++++++++------- .../mermaid/src/schemas/config.schema.yaml | 6 +++--- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 014ff65e7..e57e0d886 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -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 diff --git a/packages/mermaid/src/diagrams/architecture/architectureDb.ts b/packages/mermaid/src/diagrams/architecture/architectureDb.ts index 896c342aa..6f00be0d4 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureDb.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureDb.ts @@ -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 = {}; let cnt = DEFAULT_ARCHITECTURE_DB.cnt; -const config: Required = structuredClone(DEFAULT_ARCHITECTURE_CONFIG); - -const getConfig = (): Required => 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(field: T): Required[T] { + const arch = getConfig().architecture; + if (arch && arch[field] !== undefined) { + const a = arch[field]; + return arch[field] as Required[T] + } + return DEFAULT_ARCHITECTURE_CONFIG[field] +} + +export { getConfigField } \ No newline at end of file diff --git a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts index 3063849c3..29b6e4d44 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts @@ -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') ); }; diff --git a/packages/mermaid/src/diagrams/architecture/svgDraw.ts b/packages/mermaid/src/diagrams/architecture/svgDraw.ts index 473bf7407..446704af6 100644 --- a/packages/mermaid/src/diagrams/architecture/svgDraw.ts +++ b/packages/mermaid/src/diagrams/architecture/svgDraw.ts @@ -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'); diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index 8723d4ca1..146237eb8 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -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