mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-15 21:39:40 +02:00
feat(arch): implemented node labels
This commit is contained in:
@@ -48,7 +48,7 @@ const clear = (): void => {
|
||||
commonClear();
|
||||
};
|
||||
|
||||
const addService = function ({ id, icon, in: parent, title }: Omit<ArchitectureService, "edges">) {
|
||||
const addService = function ({ id, icon, in: parent, title, iconText }: Omit<ArchitectureService, "edges">) {
|
||||
if (state.records.registeredIds[id] !== undefined) {
|
||||
throw new Error(`The service id [${id}] is already in use by another ${state.records.registeredIds[id]}`);
|
||||
}
|
||||
@@ -71,6 +71,7 @@ const addService = function ({ id, icon, in: parent, title }: Omit<ArchitectureS
|
||||
state.records.services[id] = {
|
||||
id,
|
||||
icon,
|
||||
iconText,
|
||||
title,
|
||||
edges: [],
|
||||
in: parent,
|
||||
|
@@ -19,6 +19,20 @@ const getStyles: DiagramStylesProvider = (options: ArchitectureStyleOptions) =>
|
||||
stroke-width: ${options.archGroupBorderStrokeWidth};
|
||||
stroke-dasharray: 8;
|
||||
}
|
||||
.node-icon-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.node-icon-text > div {
|
||||
color: #fff;
|
||||
margin: 1px;
|
||||
height: fit-content;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
`;
|
||||
|
||||
export default getStyles;
|
||||
|
@@ -183,6 +183,7 @@ export interface ArchitectureService {
|
||||
id: string;
|
||||
edges: ArchitectureEdge[];
|
||||
icon?: string;
|
||||
iconText?: string;
|
||||
title?: string;
|
||||
in?: string;
|
||||
width?: number;
|
||||
|
@@ -118,15 +118,16 @@ export const drawEdges = function (edgesEl: D3Element, cy: cytoscape.Core) {
|
||||
|
||||
// Calculate the new width/height with the rotation applied, and transform to the proper position
|
||||
const bboxNew = textElem.node().getBoundingClientRect();
|
||||
textElem
|
||||
.attr('transform', `
|
||||
translate(${midX}, ${midY - (bboxOrig.height / 2)})
|
||||
translate(${x * bboxNew.width / 2}, ${y * bboxNew.height / 2})
|
||||
textElem.attr(
|
||||
'transform',
|
||||
`
|
||||
translate(${midX}, ${midY - bboxOrig.height / 2})
|
||||
translate(${(x * bboxNew.width) / 2}, ${(y * bboxNew.height) / 2})
|
||||
rotate(${-1 * x * y * 45}, 0, ${bboxOrig.height / 2})
|
||||
`);
|
||||
`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -163,12 +164,16 @@ export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
|
||||
getIcon(data.icon)?.(bkgElem, groupIconSize);
|
||||
bkgElem.attr(
|
||||
'transform',
|
||||
'translate(' + (shiftedX1 + halfIconSize + 1) + ', ' + (shiftedY1 + halfIconSize + 1) + ')'
|
||||
'translate(' +
|
||||
(shiftedX1 + halfIconSize + 1) +
|
||||
', ' +
|
||||
(shiftedY1 + halfIconSize + 1) +
|
||||
')'
|
||||
);
|
||||
shiftedX1 += groupIconSize;
|
||||
// TODO: test with more values
|
||||
// - 1 - 2 comes from the Y axis transform of the icon and label
|
||||
shiftedY1 += ((fontSize / 2) - 1 - 2);
|
||||
shiftedY1 += fontSize / 2 - 1 - 2;
|
||||
}
|
||||
if (data.label) {
|
||||
const textElem = groupLabelContainer.append('g');
|
||||
@@ -190,7 +195,11 @@ export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
|
||||
|
||||
textElem.attr(
|
||||
'transform',
|
||||
'translate(' + (shiftedX1 + halfIconSize + 4) + ', ' + (shiftedY1 + halfIconSize + 2) + ')'
|
||||
'translate(' +
|
||||
(shiftedX1 + halfIconSize + 4) +
|
||||
', ' +
|
||||
(shiftedY1 + halfIconSize + 2) +
|
||||
')'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -218,6 +227,7 @@ export const drawServices = function (
|
||||
},
|
||||
getConfig()
|
||||
);
|
||||
|
||||
textElem
|
||||
.attr('dy', '1em')
|
||||
.attr('alignment-baseline', 'middle')
|
||||
@@ -234,6 +244,17 @@ export const drawServices = function (
|
||||
// throw new Error(`Invalid SVG Icon name: "${service.icon}"`);
|
||||
// }
|
||||
bkgElem = getIcon(service.icon)?.(bkgElem, iconSize);
|
||||
} else if (service.iconText) {
|
||||
bkgElem = getIcon('blank')?.(bkgElem, iconSize);
|
||||
const textElemContainer = bkgElem.append('g');
|
||||
const fo = textElemContainer.append('foreignObject').attr('width', iconSize).attr('height', iconSize);
|
||||
const divElem = fo
|
||||
.append('div')
|
||||
.attr('class', 'node-icon-text')
|
||||
.attr('style', `height: ${iconSize}px;`)
|
||||
.append('div').html(service.iconText);
|
||||
const fontSize = parseInt(window.getComputedStyle(divElem.node(), null).getPropertyValue("font-size").replace(/[^\d]/g, '')) ?? 16;
|
||||
divElem.attr('style', `-webkit-line-clamp: ${Math.floor((iconSize - 2) / fontSize)};`)
|
||||
} else {
|
||||
bkgElem
|
||||
.append('path')
|
||||
|
11
packages/mermaid/src/rendering-util/svg/blank.ts
Normal file
11
packages/mermaid/src/rendering-util/svg/blank.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Designer: Nicolas Newman
|
||||
*/
|
||||
import { createIcon } from '../svgRegister.js';
|
||||
|
||||
export default createIcon(
|
||||
`<g>
|
||||
<rect width="80" height="80" style="fill: #087ebf; stroke-width: 0px;"/>
|
||||
</g>`,
|
||||
80
|
||||
);
|
@@ -5,6 +5,7 @@ import disk from './disk.js';
|
||||
import internet from './internet.js';
|
||||
import cloud from './cloud.js';
|
||||
import unknown from './unknown.js';
|
||||
import blank from './blank.js';
|
||||
|
||||
const defaultIconLibrary: IconLibrary = {
|
||||
database: database,
|
||||
@@ -13,6 +14,7 @@ const defaultIconLibrary: IconLibrary = {
|
||||
internet: internet,
|
||||
cloud: cloud,
|
||||
unknown: unknown,
|
||||
blank: blank,
|
||||
};
|
||||
|
||||
export default defaultIconLibrary;
|
||||
|
@@ -26,7 +26,7 @@ Group:
|
||||
;
|
||||
|
||||
Service:
|
||||
'service' id=ARCH_ID icon=ARCH_ICON? title=ARCH_TITLE? ('in' in=ARCH_ID)? EOL
|
||||
'service' id=ARCH_ID (iconText=ARCH_TEXT_ICON | icon=ARCH_ICON)? title=ARCH_TITLE? ('in' in=ARCH_ID)? EOL
|
||||
;
|
||||
|
||||
Edge:
|
||||
@@ -35,6 +35,7 @@ Edge:
|
||||
|
||||
terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B';
|
||||
terminal ARCH_ID: /[\w]+/;
|
||||
terminal ARCH_TEXT_ICON: /\("[^"]+"\)/;
|
||||
terminal ARCH_ICON: /\([\w]+\)/;
|
||||
terminal ARCH_TITLE: /\[[\w ]+\]/;
|
||||
terminal ARROW_INTO: /\(|\)/;
|
@@ -11,6 +11,8 @@ export class ArchitectureValueConverter extends AbstractMermaidValueConverter {
|
||||
): ValueType | undefined {
|
||||
if (rule.name === 'ARCH_ICON') {
|
||||
return input.replace(/[()]/g, '').trim();
|
||||
} else if (rule.name === 'ARCH_TEXT_ICON') {
|
||||
return input.replace(/[()"]/g, '');
|
||||
} else if (rule.name === 'ARCH_TITLE') {
|
||||
return input.replace(/[[\]]/g, '').trim();
|
||||
}
|
||||
|
Reference in New Issue
Block a user