mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
style(arch): linting
This commit is contained in:
parent
734bde3877
commit
48e6901936
@ -25,7 +25,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
|
||||
'sankey',
|
||||
'block',
|
||||
'packet',
|
||||
'architecture'
|
||||
'architecture',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
|
@ -40,17 +40,25 @@ const state = new ImperativeState<ArchitectureState>(() => ({
|
||||
registeredIds: {},
|
||||
config: DEFAULT_ARCHITECTURE_CONFIG,
|
||||
dataStructures: undefined,
|
||||
elements: {}
|
||||
}))
|
||||
elements: {},
|
||||
}));
|
||||
|
||||
const clear = (): void => {
|
||||
state.reset()
|
||||
state.reset();
|
||||
commonClear();
|
||||
};
|
||||
|
||||
const addService = function ({ id, icon, in: parent, title, iconText }: 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]}`);
|
||||
throw new Error(
|
||||
`The service id [${id}] is already in use by another ${state.records.registeredIds[id]}`
|
||||
);
|
||||
}
|
||||
if (parent !== undefined) {
|
||||
if (id === parent) {
|
||||
@ -82,7 +90,9 @@ const getServices = (): ArchitectureService[] => Object.values(state.records.ser
|
||||
|
||||
const addGroup = function ({ id, icon, in: parent, title }: ArchitectureGroup) {
|
||||
if (state.records.registeredIds[id] !== undefined) {
|
||||
throw new Error(`The group id [${id}] is already in use by another ${state.records.registeredIds[id]}`);
|
||||
throw new Error(
|
||||
`The group id [${id}] is already in use by another ${state.records.registeredIds[id]}`
|
||||
);
|
||||
}
|
||||
if (parent !== undefined) {
|
||||
if (id === parent) {
|
||||
@ -111,10 +121,15 @@ const getGroups = (): ArchitectureGroup[] => {
|
||||
return Object.values(state.records.groups);
|
||||
};
|
||||
|
||||
const addEdge = function (
|
||||
{ lhsId, rhsId, lhsDir, rhsDir, lhsInto, rhsInto, title }: ArchitectureEdge
|
||||
) {
|
||||
|
||||
const addEdge = function ({
|
||||
lhsId,
|
||||
rhsId,
|
||||
lhsDir,
|
||||
rhsDir,
|
||||
lhsInto,
|
||||
rhsInto,
|
||||
title,
|
||||
}: ArchitectureEdge) {
|
||||
if (!isArchitectureDirection(lhsDir)) {
|
||||
throw new Error(
|
||||
`Invalid direction given for left hand side of edge ${lhsId}--${rhsId}. Expected (L,R,T,B) got ${lhsDir}`
|
||||
@ -152,7 +167,6 @@ const addEdge = function (
|
||||
state.records.services[lhsId].edges.push(state.records.edges[state.records.edges.length - 1]);
|
||||
state.records.services[rhsId].edges.push(state.records.edges[state.records.edges.length - 1]);
|
||||
} else if (state.records.groups[lhsId] && state.records.groups[rhsId]) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -168,28 +182,27 @@ const getDataStructures = () => {
|
||||
// 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.services).reduce<{ [id: string]: ArchitectureDirectionPairMap }>(
|
||||
(prevOuter, [id, service]) => {
|
||||
prevOuter[id] = service.edges.reduce<ArchitectureDirectionPairMap>((prevInner, edge) => {
|
||||
if (edge.lhsId === id) {
|
||||
// source is LHS
|
||||
const pair = getArchitectureDirectionPair(edge.lhsDir, edge.rhsDir);
|
||||
if (pair) {
|
||||
prevInner[pair] = edge.rhsId;
|
||||
}
|
||||
} else {
|
||||
// source is RHS
|
||||
const pair = getArchitectureDirectionPair(edge.rhsDir, edge.lhsDir);
|
||||
if (pair) {
|
||||
prevInner[pair] = edge.lhsId;
|
||||
}
|
||||
const adjList = Object.entries(state.records.services).reduce<{
|
||||
[id: string]: ArchitectureDirectionPairMap;
|
||||
}>((prevOuter, [id, service]) => {
|
||||
prevOuter[id] = service.edges.reduce<ArchitectureDirectionPairMap>((prevInner, edge) => {
|
||||
if (edge.lhsId === id) {
|
||||
// source is LHS
|
||||
const pair = getArchitectureDirectionPair(edge.lhsDir, edge.rhsDir);
|
||||
if (pair) {
|
||||
prevInner[pair] = edge.rhsId;
|
||||
}
|
||||
return prevInner;
|
||||
}, {});
|
||||
return prevOuter;
|
||||
},
|
||||
{}
|
||||
);
|
||||
} else {
|
||||
// source is RHS
|
||||
const pair = getArchitectureDirectionPair(edge.rhsDir, edge.lhsDir);
|
||||
if (pair) {
|
||||
prevInner[pair] = edge.lhsId;
|
||||
}
|
||||
}
|
||||
return prevInner;
|
||||
}, {});
|
||||
return prevOuter;
|
||||
}, {});
|
||||
|
||||
// Configuration for the initial pass of BFS
|
||||
const firstId = Object.keys(adjList)[0];
|
||||
|
@ -12,7 +12,7 @@ import type {
|
||||
ArchitectureDataStructures,
|
||||
ArchitectureSpatialMap,
|
||||
EdgeSingularData,
|
||||
EdgeSingular
|
||||
EdgeSingular,
|
||||
} from './architectureTypes.js';
|
||||
import {
|
||||
type ArchitectureDB,
|
||||
@ -25,7 +25,7 @@ import {
|
||||
isArchitectureDirectionXY,
|
||||
isArchitectureDirectionY,
|
||||
nodeData,
|
||||
edgeData
|
||||
edgeData,
|
||||
} from './architectureTypes.js';
|
||||
import { select } from 'd3';
|
||||
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
@ -54,8 +54,10 @@ function addServices(services: ArchitectureService[], cy: cytoscape.Core) {
|
||||
|
||||
function positionServices(db: ArchitectureDB, cy: cytoscape.Core) {
|
||||
cy.nodes().map((node) => {
|
||||
const data = nodeData(node)
|
||||
if (data.type === 'group') { return; }
|
||||
const data = nodeData(node);
|
||||
if (data.type === 'group') {
|
||||
return;
|
||||
}
|
||||
data.x = node.position().x;
|
||||
data.y = node.position().y;
|
||||
|
||||
@ -126,8 +128,12 @@ function getAlignments(spatialMaps: ArchitectureSpatialMap[]): fcose.FcoseAlignm
|
||||
const verticalAlignments: Record<number, string[]> = {};
|
||||
// Group service ids in an object with their x and y coordinate as the key
|
||||
Object.entries(spatialMap).forEach(([id, [x, y]]) => {
|
||||
if (!horizontalAlignments[y]) { horizontalAlignments[y] = []; }
|
||||
if (!verticalAlignments[x]) { verticalAlignments[x] = []; }
|
||||
if (!horizontalAlignments[y]) {
|
||||
horizontalAlignments[y] = [];
|
||||
}
|
||||
if (!verticalAlignments[x]) {
|
||||
verticalAlignments[x] = [];
|
||||
}
|
||||
horizontalAlignments[y].push(id);
|
||||
verticalAlignments[x].push(id);
|
||||
});
|
||||
@ -221,7 +227,7 @@ function layoutArchitecture(
|
||||
selector: 'edge',
|
||||
style: {
|
||||
'curve-style': 'straight',
|
||||
'label': 'data(label)',
|
||||
label: 'data(label)',
|
||||
'source-endpoint': 'data(sourceEndpoint)',
|
||||
'target-endpoint': 'data(targetEndpoint)',
|
||||
},
|
||||
@ -300,16 +306,16 @@ function layoutArchitecture(
|
||||
// Hacky fix for: https://github.com/iVis-at-Bilkent/cytoscape.js-fcose/issues/67
|
||||
idealEdgeLength(edge: EdgeSingular) {
|
||||
const [nodeA, nodeB] = edge.connectedNodes();
|
||||
const { parent: parentA } = nodeData(nodeA)
|
||||
const { parent: parentB } = nodeData(nodeB)
|
||||
const { parent: parentA } = nodeData(nodeA);
|
||||
const { parent: parentB } = nodeData(nodeB);
|
||||
const elasticity =
|
||||
parentA === parentB ? 1.5 * getConfigField('iconSize') : 0.5 * getConfigField('iconSize');
|
||||
return elasticity;
|
||||
},
|
||||
edgeElasticity(edge: EdgeSingular) {
|
||||
const [nodeA, nodeB] = edge.connectedNodes();
|
||||
const { parent: parentA } = nodeData(nodeA)
|
||||
const { parent: parentB } = nodeData(nodeB)
|
||||
const { parent: parentA } = nodeData(nodeA);
|
||||
const { parent: parentB } = nodeData(nodeB);
|
||||
const elasticity = parentA === parentB ? 0.45 : 0.001;
|
||||
return elasticity;
|
||||
},
|
||||
@ -374,7 +380,7 @@ function layoutArchitecture(
|
||||
if (sX !== tX && sY !== tY) {
|
||||
const sEP = edge.sourceEndpoint();
|
||||
const tEP = edge.targetEndpoint();
|
||||
const { sourceDir } = edgeData(edge)
|
||||
const { sourceDir } = edgeData(edge);
|
||||
const [pointX, pointY] = isArchitectureDirectionY(sourceDir)
|
||||
? [sEP.x, tEP.y]
|
||||
: [tEP.x, sEP.y];
|
||||
|
@ -21,8 +21,7 @@ export type ArchitectureDirectionPair = Exclude<
|
||||
>;
|
||||
export type ArchitectureDirectionPairXY = Exclude<
|
||||
InvalidArchitectureDirectionPair,
|
||||
'LL' | 'RR' | 'TT' | 'BB'
|
||||
| 'LR' | 'RL' | 'TB' | 'BT'
|
||||
'LL' | 'RR' | 'TT' | 'BB' | 'LR' | 'RL' | 'TB' | 'BT'
|
||||
>;
|
||||
|
||||
export const ArchitectureDirectionName = {
|
||||
@ -85,7 +84,7 @@ export const isArchitectureDirectionXY = function (
|
||||
};
|
||||
|
||||
export const isArchitecturePairXY = function (
|
||||
pair: ArchitectureDirectionPair,
|
||||
pair: ArchitectureDirectionPair
|
||||
): pair is ArchitectureDirectionPairXY {
|
||||
const lhs = pair[0] as ArchitectureDirection;
|
||||
const rhs = pair[1] as ArchitectureDirection;
|
||||
@ -161,13 +160,13 @@ export const getArchitectureDirectionXYFactors = function (
|
||||
pair: ArchitectureDirectionPairXY
|
||||
): number[] {
|
||||
if (pair === 'LT' || pair === 'TL') {
|
||||
return [1, 1]
|
||||
return [1, 1];
|
||||
} else if (pair === 'BL' || pair === 'LB') {
|
||||
return [1, -1]
|
||||
return [1, -1];
|
||||
} else if (pair === 'BR' || pair === 'RB') {
|
||||
return [-1, -1]
|
||||
return [-1, -1];
|
||||
} else {
|
||||
return [-1, 1]
|
||||
return [-1, 1];
|
||||
}
|
||||
};
|
||||
|
||||
@ -209,13 +208,11 @@ export interface ArchitectureEdge {
|
||||
|
||||
export interface ArchitectureDB extends DiagramDB {
|
||||
clear: () => void;
|
||||
addService: (service: Omit<ArchitectureService, "edges">) => void;
|
||||
addService: (service: Omit<ArchitectureService, 'edges'>) => void;
|
||||
getServices: () => ArchitectureService[];
|
||||
addGroup: (group: ArchitectureGroup) => void;
|
||||
getGroups: () => ArchitectureGroup[];
|
||||
addEdge: (
|
||||
edge: ArchitectureEdge
|
||||
) => void;
|
||||
addEdge: (edge: ArchitectureEdge) => void;
|
||||
getEdges: () => ArchitectureEdge[];
|
||||
setElementForId: (id: string, element: D3Element) => void;
|
||||
getElementById: (id: string) => D3Element;
|
||||
@ -257,7 +254,7 @@ export type EdgeSingularData = {
|
||||
|
||||
export const edgeData = (edge: cytoscape.EdgeSingular) => {
|
||||
return edge.data() as EdgeSingularData;
|
||||
}
|
||||
};
|
||||
|
||||
export interface EdgeSingular extends cytoscape.EdgeSingular {
|
||||
_private: {
|
||||
@ -275,28 +272,29 @@ export interface EdgeSingular extends cytoscape.EdgeSingular {
|
||||
data<T extends keyof EdgeSingularData>(key: T): EdgeSingularData[T];
|
||||
}
|
||||
|
||||
export type NodeSingularData = {
|
||||
type: 'service';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
width: number;
|
||||
height: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
export type NodeSingularData =
|
||||
| {
|
||||
type: 'group';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
type: 'service';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
width: number;
|
||||
height: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
| {
|
||||
type: 'group';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export const nodeData = (node: cytoscape.NodeSingular) => {
|
||||
return node.data() as NodeSingularData;
|
||||
}
|
||||
};
|
||||
|
||||
export interface NodeSingular extends cytoscape.NodeSingular {
|
||||
_private: {
|
||||
|
@ -227,7 +227,7 @@ export const drawServices = function (
|
||||
},
|
||||
getConfig()
|
||||
);
|
||||
|
||||
|
||||
textElem
|
||||
.attr('dy', '1em')
|
||||
.attr('alignment-baseline', 'middle')
|
||||
@ -247,14 +247,24 @@ export const drawServices = function (
|
||||
} 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 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)};`)
|
||||
.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')
|
||||
|
@ -20,7 +20,7 @@ architecture
|
||||
|
||||
## Syntax
|
||||
|
||||
The building blocks of an architecture are `groups`, `services`, and `edges`.
|
||||
The building blocks of an architecture are `groups`, `services`, and `edges`.
|
||||
|
||||
For supporting components, icons are declared by surrounding the icon name with `()`, while labels are declared by surrounding the text with `[]`.
|
||||
|
||||
@ -29,6 +29,7 @@ To begin an architecture diagram, use the keyword `architecture`, followed by yo
|
||||
### Groups
|
||||
|
||||
The syntax for declaring a group is:
|
||||
|
||||
```
|
||||
group {group id}({icon name})[{title}] (in {parent id})?
|
||||
```
|
||||
@ -48,12 +49,15 @@ group private_api(cloud)[Private API] in public_api
|
||||
```
|
||||
|
||||
### Services
|
||||
|
||||
The syntax for declaring a group is:
|
||||
|
||||
```
|
||||
service {service id}({icon name})[{title}] (in {parent id})?
|
||||
```
|
||||
|
||||
Put together:
|
||||
|
||||
```
|
||||
service database(db)[Database]
|
||||
```
|
||||
@ -67,6 +71,7 @@ service database(db)[Database] in private_api
|
||||
```
|
||||
|
||||
### Edges
|
||||
|
||||
TODO
|
||||
|
||||
## Configuration
|
||||
## Configuration
|
||||
|
@ -16,7 +16,7 @@ import type { DetailedError } from './utils.js';
|
||||
import type { ExternalDiagramDefinition } from './diagram-api/types.js';
|
||||
import type { UnknownDiagramError } from './errors.js';
|
||||
import type { IconLibrary, IconResolver } from './rendering-util/svgRegister.js';
|
||||
import { createIcon } from './rendering-util/svgRegister.js';
|
||||
import { createIcon } from './rendering-util/svgRegister.js';
|
||||
import { addDiagrams } from './diagram-api/diagram-orchestration.js';
|
||||
|
||||
export type {
|
||||
@ -29,10 +29,10 @@ export type {
|
||||
ParseResult,
|
||||
UnknownDiagramError,
|
||||
IconLibrary,
|
||||
IconResolver
|
||||
IconResolver,
|
||||
};
|
||||
|
||||
export { createIcon }
|
||||
export { createIcon };
|
||||
|
||||
export interface RunOptions {
|
||||
/**
|
||||
|
@ -5,9 +5,9 @@
|
||||
import { createIcon } from '../svgRegister.js';
|
||||
|
||||
export default createIcon(
|
||||
`<g>
|
||||
`<g>
|
||||
<rect width="80" height="80" style="fill: #087ebf; stroke-width: 0px;"/>
|
||||
<path d="m65,47.5c0,2.76-2.24,5-5,5H20c-2.76,0-5-2.24-5-5,0-1.87,1.03-3.51,2.56-4.36-.04-.21-.06-.42-.06-.64,0-2.6,2.48-4.74,5.65-4.97,1.65-4.51,6.34-7.76,11.85-7.76.86,0,1.69.08,2.5.23,2.09-1.57,4.69-2.5,7.5-2.5,6.1,0,11.19,4.38,12.28,10.17,2.14.56,3.72,2.51,3.72,4.83,0,.03,0,.07-.01.1,2.29.46,4.01,2.48,4.01,4.9Z" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/>
|
||||
</g>`,
|
||||
80
|
||||
);
|
||||
80
|
||||
);
|
||||
|
@ -43,4 +43,12 @@ const getIcon = (name: string): IconResolver | null => {
|
||||
return icons['unknown'];
|
||||
};
|
||||
|
||||
export { registerIcon, registerIcons, getIcon, isIconNameInUse, createIcon, IconLibrary, IconResolver };
|
||||
export {
|
||||
registerIcon,
|
||||
registerIcons,
|
||||
getIcon,
|
||||
isIconNameInUse,
|
||||
createIcon,
|
||||
IconLibrary,
|
||||
IconResolver,
|
||||
};
|
||||
|
@ -35,7 +35,10 @@ export type ArchitectureServices = LangiumCoreServices & ArchitectureAddedServic
|
||||
* Dependency injection module that overrides Langium default services and
|
||||
* contributes the declared `Architecture` services.
|
||||
*/
|
||||
export const ArchitectureModule: Module<ArchitectureServices, PartialLangiumCoreServices & ArchitectureAddedServices> = {
|
||||
export const ArchitectureModule: Module<
|
||||
ArchitectureServices,
|
||||
PartialLangiumCoreServices & ArchitectureAddedServices
|
||||
> = {
|
||||
parser: {
|
||||
TokenBuilder: () => new ArchitectureTokenBuilder(),
|
||||
ValueConverter: () => new ArchitectureValueConverter(),
|
||||
@ -56,7 +59,9 @@ export const ArchitectureModule: Module<ArchitectureServices, PartialLangiumCore
|
||||
* @param context - Optional module context with the LSP connection
|
||||
* @returns An object wrapping the shared services and the language-specific services
|
||||
*/
|
||||
export function createArchitectureServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): {
|
||||
export function createArchitectureServices(
|
||||
context: DefaultSharedCoreModuleContext = EmptyFileSystem
|
||||
): {
|
||||
shared: LangiumSharedCoreServices;
|
||||
Architecture: ArchitectureServices;
|
||||
} {
|
||||
|
@ -10,12 +10,12 @@ export class ArchitectureValueConverter extends AbstractMermaidValueConverter {
|
||||
_cstNode: CstNode
|
||||
): ValueType | undefined {
|
||||
if (rule.name === 'ARCH_ICON') {
|
||||
return input.replace(/[()]/g, '').trim();
|
||||
return input.replace(/[()]/g, '').trim();
|
||||
} else if (rule.name === 'ARCH_TEXT_ICON') {
|
||||
return input.replace(/[()"]/g, '');
|
||||
return input.replace(/[()"]/g, '');
|
||||
} else if (rule.name === 'ARCH_TITLE') {
|
||||
return input.replace(/[[\]]/g, '').trim();
|
||||
return input.replace(/[[\]]/g, '').trim();
|
||||
}
|
||||
return undefined
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ export {
|
||||
isPacketBlock,
|
||||
isPie,
|
||||
isPieSection,
|
||||
isArchitecture
|
||||
isArchitecture,
|
||||
} from './generated/ast.js';
|
||||
|
||||
export {
|
||||
@ -20,7 +20,7 @@ export {
|
||||
MermaidGeneratedSharedModule,
|
||||
PacketGeneratedModule,
|
||||
PieGeneratedModule,
|
||||
ArchitectureGeneratedModule
|
||||
ArchitectureGeneratedModule,
|
||||
} from './generated/module.js';
|
||||
|
||||
export * from './common/index.js';
|
||||
|
Loading…
x
Reference in New Issue
Block a user