core/plugins/diagram.definition.plugin.ts
core/plugins/diagram.definition.plugin.ts is a file in GovLab Docs. 71 lines of code and 13 definitions.
import type { ClassBox, ClassModel, ClassRelation, ClassRelationKind } from "#types/diagram.types";
import {
DIAGRAM_DESCRIPTIONS,
DIAGRAM_LEGENDS,
DIAGRAM_TITLES,
typeRelationshipTitle,
} from "#configuration/strings/figure.strings";
import type { DiagramContext, DiagramKind, DiagramSource } from "#types/figure.types";
import type { TypeEdge, TypeGraph, TypeNode } from "#types/graph.types";
import { emitClassDiagram } from "#core/formatters/diagram.structure.formatter";
const MIN_EDGES = 1;
const RELATION_KIND: ReadonlyMap<TypeEdge["kind"], ClassRelationKind> = new Map<TypeEdge["kind"], ClassRelationKind>([
["extends", "realization"],
["implements", "realization"],
["has", "aggregation"],
["uses", "dependency"],
]);
const connectedIds = function connectedIds(graph: TypeGraph): Set<string> {
return new Set(graph.edges.flatMap((edge) => [edge.from, edge.to]));
};
const classBoxes = function classBoxes(nodes: readonly TypeNode[], keep: ReadonlySet<string>): ClassBox[] {
return nodes
.filter((node) => keep.has(node.id))
.map((node) => ({ id: node.id, label: node.label, members: node.members.map((name) => ({ name })) }));
};
const classRelations = function classRelations(edges: readonly TypeEdge[]): ClassRelation[] {
return edges.flatMap((edge) => {
const kind = RELATION_KIND.get(edge.kind);
return kind === undefined ? [] : [{ from: edge.from, kind, to: edge.to }];
});
};
const sourcesOf = function sourcesOf(nodes: readonly TypeNode[], keep: ReadonlySet<string>): DiagramSource[] {
return nodes
.filter((node) => keep.has(node.id))
.map((node) => ({ file: node.source.file, label: node.label, line: node.source.line }));
};
const buildModel = function buildModel(
context: DiagramContext,
graph: TypeGraph,
keep: ReadonlySet<string>,
): ClassModel {
return {
accDescr: DIAGRAM_DESCRIPTIONS.typeRelationship,
accTitle: typeRelationshipTitle(context.moduleName),
classes: classBoxes(graph.nodes, keep),
relations: classRelations(graph.edges),
};
};
export const diagram: DiagramKind = {
appliesTo(context) {
return (context.typeGraph?.edges.length ?? 0) >= MIN_EDGES;
},
id: "type-relationship",
order: 5,
render(context) {
const graph = context.typeGraph;
if (!graph || graph.edges.length < MIN_EDGES) {
return null;
}
const keep = connectedIds(graph);
if (keep.size === 0) {
return null;
}
return {
legend: DIAGRAM_LEGENDS.typeRelationship,
mermaid: emitClassDiagram(buildModel(context, graph, keep)),
sources: sourcesOf(graph.nodes, keep),
};
},
title: DIAGRAM_TITLES.typeRelationship,
};