diff --git a/.cspell/code-terms.txt b/.cspell/code-terms.txt index fa063616a..640b32d53 100644 --- a/.cspell/code-terms.txt +++ b/.cspell/code-terms.txt @@ -89,6 +89,7 @@ reqs rewritelinks rgba RIGHTOF +roughjs sankey sequencenumber shrc diff --git a/package.json b/package.json index f3e0b4e28..d2fbfb54c 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "build:esbuild": "pnpm run -r clean && tsx .esbuild/build.ts", "build:mermaid": "pnpm build:esbuild --mermaid", "build:viz": "pnpm build:esbuild --visualize", - "build:types": "tsx .build/types.ts", + "build:types": "pnpm --filter mermaid types:build-config && tsx .build/types.ts", "build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch", "dev": "tsx .esbuild/server.ts", "dev:vite": "tsx .vite/server.ts", diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index ea57d22ed..7daa01fed 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -64,7 +64,21 @@ export interface MermaidConfig { theme?: 'default' | 'forest' | 'dark' | 'neutral' | 'null'; themeVariables?: any; themeCSS?: string; - handdrawn?: boolean; // Different from theme as it could be combined with any theme in the future + /** + * Defines which main look to use for the diagram. + * + */ + look?: 'classic' | 'handdrawn' | 'slick'; + /** + * Defines the seed to be used when using handdrawn look. This is important for the automated tests as they will always find differences without the seed. The default value is 0 which gives a random seed. + * + */ + handdrawnSeed?: number; + /** + * Defines which layout algorithm to use for rendering the diagram. + * + */ + layout?: string; /** * The maximum allowed size of the users text diagram */ diff --git a/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts b/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts index 5ecfd4d26..949e2d05f 100644 --- a/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts +++ b/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts @@ -62,7 +62,7 @@ export const getClasses = function ( export const draw = async function (text: string, id: string, _version: string, diag: any) { log.info('REF0:'); log.info('Drawing state diagram (v2)', id); - const { securityLevel, state: conf } = getConfig(); + const { securityLevel, state: conf, layout } = getConfig(); // Extracting the data from the parsed structure into a more usable form // Not related to the refactoring, but this is the first step in the rendering process diag.db.extract(diag.db.getRootDocV2()); @@ -89,7 +89,7 @@ export const draw = async function (text: string, id: string, _version: string, data4Layout.type = diag.type; // data4Layout.layoutAlgorithm = 'dagre-wrapper'; // data4Layout.layoutAlgorithm = 'elk'; - data4Layout.layoutAlgorithm = getConfig().layout; + data4Layout.layoutAlgorithm = layout; data4Layout.direction = DIR; data4Layout.nodeSpacing = conf.nodeSpacing || 50; data4Layout.rankSpacing = conf.rankSpacing || 50; diff --git a/packages/mermaid/src/rendering-util/doLayout.ts b/packages/mermaid/src/rendering-util/doLayout.ts index a1f6c456b..b3798ca39 100644 --- a/packages/mermaid/src/rendering-util/doLayout.ts +++ b/packages/mermaid/src/rendering-util/doLayout.ts @@ -1,4 +1,5 @@ -import { LayoutData, LayoutMethod, RenderData } from './types'; +import { log } from '$root/logger.js'; +import type { LayoutData, LayoutMethod, RenderData } from './types.js'; const layoutAlgorithms = {} as Record; @@ -8,7 +9,7 @@ const performLayout = ( _version: string, layoutMethod: LayoutMethod ): RenderData => { - console.log('Performing layout', layoutData, id, _version, layoutMethod); - return { items: [], otherDetails:{} }; + log.info('Performing layout', layoutData, id, _version, layoutMethod); + return { items: [] }; }; export default performLayout; diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js index 002e4a093..db0c1e0f6 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js @@ -27,7 +27,7 @@ import { log } from '$root/logger.js'; import { getSubGraphTitleMargins } from '../../../utils/subGraphTitleMargins.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; -const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster, siteConfig) => { +const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, siteConfig) => { log.info('Graph in recursive render: XXX', graphlibJson.write(graph), parentCluster); const dir = graph.graph().rankdir; log.trace('Dir in recursive render - dir:', dir); @@ -68,7 +68,7 @@ const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster, sit const o = await recursiveRender( nodes, node.graph, - diagramtype, + diagramType, id, graph.node(v), siteConfig @@ -106,7 +106,7 @@ const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster, sit log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e))); // Check if link is either from or to a cluster - log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translateing: ', clusterDb[e.v], clusterDb[e.w]); + log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translating: ', clusterDb[e.v], clusterDb[e.w]); insertEdgeLabel(edgeLabels, edge); }); @@ -158,7 +158,7 @@ const recursiveRender = async (_elem, graph, diagramtype, id, parentCluster, sit log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge); edge.points.forEach((point) => (point.y += subGraphTitleTotalMargin / 2)); - const paths = insertEdge(edgePaths, edge, clusterDb, diagramtype, graph, id); + const paths = insertEdge(edgePaths, edge, clusterDb, diagramType, graph, id); positionEdgeLabel(edge, paths); }); @@ -205,7 +205,7 @@ export const render = async (data4Layout, svg, element) => { } }); - console.log('Edges:', data4Layout.edges); + log.debug('Edges:', data4Layout.edges); data4Layout.edges.forEach((edge) => { graph.setEdge(edge.start, edge.end, { ...edge }); }); diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js index ee2df03c8..005bb8f83 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js @@ -1,7 +1,7 @@ /** Decorates with functions required by mermaids dagre-wrapper. */ import { log } from '$root/logger.js'; -import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; +import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js'; export let clusterDb = {}; let descendants = {}; @@ -13,32 +13,24 @@ export const clear = () => { clusterDb = {}; }; -const isDescendant = (id, ancenstorId) => { - // if (id === ancenstorId) return true; - - log.trace('In isDecendant', ancenstorId, ' ', id, ' = ', descendants[ancenstorId].includes(id)); - if (descendants[ancenstorId].includes(id)) { - return true; - } - - return false; +const isDescendant = (id, ancestorId) => { + log.trace('In isDescendant', ancestorId, ' ', id, ' = ', descendants[ancestorId].includes(id)); + return descendants[ancestorId].includes(id); }; const edgeInCluster = (edge, clusterId) => { - log.info('Decendants of ', clusterId, ' is ', descendants[clusterId]); + log.info('Descendants of ', clusterId, ' is ', descendants[clusterId]); log.info('Edge is ', edge); // Edges to/from the cluster is not in the cluster, they are in the parent - if (edge.v === clusterId) { - return false; - } - if (edge.w === clusterId) { + if (edge.v === clusterId || edge.w === clusterId) { return false; } if (!descendants[clusterId]) { - log.debug('Tilt, ', clusterId, ',not in decendants'); + log.debug('Tilt, ', clusterId, ',not in descendants'); return false; } + return ( descendants[clusterId].includes(edge.v) || isDescendant(edge.v, clusterId) || @@ -244,7 +236,7 @@ export const adjustClustersAndEdges = (graph, depth) => { // d1 xor d2 - if either d1 is true and d2 is false or the other way around if (d1 ^ d2) { log.warn('Edge: ', edge, ' leaves cluster ', id); - log.warn('Decendants of XXX ', id, ': ', descendants[id]); + log.warn('Descendants of XXX ', id, ': ', descendants[id]); clusterDb[id].externalConnections = true; } } @@ -337,7 +329,7 @@ export const adjustClustersAndEdges = (graph, depth) => { // Remove references to extracted cluster // graph.edges().forEach(edge => { - // if (isDecendant(edge.v, clusterId) || isDecendant(edge.w, clusterId)) { + // if (isDescendant(edge.v, clusterId) || isDescendant(edge.w, clusterId)) { // graph.removeEdge(edge); // } // }); diff --git a/packages/mermaid/src/rendering-util/types.d.ts b/packages/mermaid/src/rendering-util/types.d.ts index b07d84edc..4c3e60df0 100644 --- a/packages/mermaid/src/rendering-util/types.d.ts +++ b/packages/mermaid/src/rendering-util/types.d.ts @@ -91,12 +91,12 @@ interface ClassDiagramNode extends Node { export interface LayoutData { nodes: Node[]; edges: Edge[]; - other: any; // Additional properties not yet defined + [key: string]: any; // Additional properties not yet defined } export interface RenderData { items: (Node | Edge)[]; - otherDetails: any; // Placeholder for additional, undefined properties + [key: string]: any; // Additional properties not yet defined } // This refactored approach ensures that common properties are included in the base `Node` and `Edge` interfaces, with specific types extending these bases with additional properties as needed. This maintains flexibility while ensuring type safety and reducing redundancy. diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index 29b33364c..6e8929bea 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -82,7 +82,7 @@ properties: default: 'classic' handdrawnSeed: description: | - Defines the seed to be used when using handdrawn look. This is important for the automated tests as they will always find differentces without the seed. The default value is 0 which gives a random seed. + Defines the seed to be used when using handdrawn look. This is important for the automated tests as they will always find differences without the seed. The default value is 0 which gives a random seed. type: number default: 0 layout: