Convert MindmapRenderer.ts

This commit is contained in:
Sidharth Vinod
2024-01-28 16:03:37 +05:30
parent f069de5487
commit d346a77e3c

View File

@@ -1,23 +1,21 @@
/** Created by knut on 14-12-11. */
import { select } from 'd3'; import { select } from 'd3';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { getConfig } from '../../diagram-api/diagramAPI.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import svgDraw from './svgDraw.js'; import svgDraw from './svgDraw.js';
import cytoscape from 'cytoscape/dist/cytoscape.umd.js'; import cytoscape from 'cytoscape';
// @ts-expect-error No types available
import coseBilkent from 'cytoscape-cose-bilkent'; import coseBilkent from 'cytoscape-cose-bilkent';
import * as db from './mindmapDb.js'; import * as db from './mindmapDb.js';
import type { MermaidConfig, MermaidConfigWithDefaults } from '../../config.type.js';
import type { Diagram } from '../../Diagram.js';
import type { MindmapDB } from './mindmapTypes.js';
import type { D3Element } from '../../mermaidAPI.js';
// Inject the layout algorithm into cytoscape // Inject the layout algorithm into cytoscape
cytoscape.use(coseBilkent); cytoscape.use(coseBilkent);
/** function drawNodes(svg: D3Element, mindmap: db.MindMapNode, section: number, conf: MermaidConfig) {
* @param {any} svg The svg element to draw the diagram onto
* @param {object} mindmap The mindmap data and hierarchy
* @param section
* @param {object} conf The configuration object
*/
function drawNodes(svg, mindmap, section, conf) {
svgDraw.drawNode(svg, mindmap, section, conf); svgDraw.drawNode(svg, mindmap, section, conf);
if (mindmap.children) { if (mindmap.children) {
mindmap.children.forEach((child, index) => { mindmap.children.forEach((child, index) => {
@@ -26,11 +24,23 @@ function drawNodes(svg, mindmap, section, conf) {
} }
} }
/** declare module 'cytoscape' {
* @param edgesEl interface EdgeSingular {
* @param cy _private: {
*/ bodyBounds: unknown;
function drawEdges(edgesEl, cy) { rscratch: {
startX: number;
startY: number;
midX: number;
midY: number;
endX: number;
endY: number;
};
};
}
}
function drawEdges(edgesEl: D3Element, cy: cytoscape.Core) {
cy.edges().map((edge, id) => { cy.edges().map((edge, id) => {
const data = edge.data(); const data = edge.data();
if (edge[0]._private.bodyBounds) { if (edge[0]._private.bodyBounds) {
@@ -47,17 +57,11 @@ function drawEdges(edgesEl, cy) {
}); });
} }
/** function addNodes(mindmap: db.MindMapNode, cy: cytoscape.Core, conf: MermaidConfig, level: number) {
* @param mindmap The mindmap data and hierarchy
* @param cy
* @param conf The configuration object
* @param level
*/
function addNodes(mindmap, cy, conf, level) {
cy.add({ cy.add({
group: 'nodes', group: 'nodes',
data: { data: {
id: mindmap.id, id: mindmap.id.toString(),
labelText: mindmap.descr, labelText: mindmap.descr,
height: mindmap.height, height: mindmap.height,
width: mindmap.width, width: mindmap.width,
@@ -67,8 +71,8 @@ function addNodes(mindmap, cy, conf, level) {
type: mindmap.type, type: mindmap.type,
}, },
position: { position: {
x: mindmap.x, x: mindmap.x!,
y: mindmap.y, y: mindmap.y!,
}, },
}); });
if (mindmap.children) { if (mindmap.children) {
@@ -88,12 +92,10 @@ function addNodes(mindmap, cy, conf, level) {
} }
} }
/** function layoutMindmap(
* @param node node: db.MindMapNode,
* @param conf conf: MermaidConfigWithDefaults
* @param cy ): Promise<cytoscape.Core> {
*/
function layoutMindmap(node, conf) {
return new Promise((resolve) => { return new Promise((resolve) => {
// Add temporary render element // Add temporary render element
const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none'); const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none');
@@ -122,8 +124,8 @@ function layoutMindmap(node, conf) {
cy.layout({ cy.layout({
name: 'cose-bilkent', name: 'cose-bilkent',
// @ts-ignore Types for cose-bilkent are not correct?
quality: 'proof', quality: 'proof',
// headless: true,
styleEnabled: false, styleEnabled: false,
animate: false, animate: false,
}).run(); }).run();
@@ -133,13 +135,8 @@ function layoutMindmap(node, conf) {
}); });
}); });
} }
/**
* @param node function positionNodes(cy: cytoscape.Core) {
* @param cy
* @param positionedMindmap
* @param conf
*/
function positionNodes(cy) {
cy.nodes().map((node, id) => { cy.nodes().map((node, id) => {
const data = node.data(); const data = node.data();
data.x = node.position().x; data.x = node.position().x;
@@ -155,38 +152,33 @@ function positionNodes(cy) {
}); });
} }
/** export const draw = async (text: string, id: string, version: string, diagObj: Diagram) => {
* Draws a an info picture in the tag with id: id based on the graph definition in text.
*
* @param {any} text
* @param {any} id
* @param {any} version
* @param diagObj
*/
export const draw = async (text, id, version, diagObj) => {
const conf = getConfig(); const conf = getConfig();
conf.htmlLabels = false; conf.htmlLabels = false;
log.debug('Rendering mindmap diagram\n' + text, diagObj.parser); log.debug('Rendering mindmap diagram\n' + text, diagObj.parser);
const securityLevel = getConfig().securityLevel; const securityLevel = conf.securityLevel;
// Handle root and Document for when rendering in sandbox mode // Handle root and Document for when rendering in sandbox mode
let sandboxElement; // eslint-disable-next-line @typescript-eslint/no-explicit-any
let sandboxElement: any;
if (securityLevel === 'sandbox') { if (securityLevel === 'sandbox') {
sandboxElement = select('#i' + id); sandboxElement = select('#i' + id);
} }
const root = // eslint-disable-next-line @typescript-eslint/no-explicit-any
const root: any =
securityLevel === 'sandbox' securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body) ? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body'); : select('body');
// Parse the graph definition
const svg = root.select('#' + id); const svg = root.select('#' + id);
svg.append('g'); svg.append('g');
const mm = diagObj.db.getMindmap(); const mm = (diagObj.db as MindmapDB).getMindmap();
if (!mm) {
return;
}
// Draw the graph and start with drawing the nodes without proper position // Draw the graph and start with drawing the nodes without proper position
// this gives us the size of the nodes and we can set the positions later // this gives us the size of the nodes and we can set the positions later
@@ -201,9 +193,9 @@ export const draw = async (text, id, version, diagObj) => {
const cy = await layoutMindmap(mm, conf); const cy = await layoutMindmap(mm, conf);
// // After this we can draw, first the edges and the then nodes with the correct position // After this we can draw, first the edges and the then nodes with the correct position
drawEdges(edgesElem, cy, conf); drawEdges(edgesElem, cy);
positionNodes(cy, conf); positionNodes(cy);
// Setup the view box and size of the svg element // Setup the view box and size of the svg element
setupGraphViewbox(undefined, svg, conf.mindmap.padding, conf.mindmap.useMaxWidth); setupGraphViewbox(undefined, svg, conf.mindmap.padding, conf.mindmap.useMaxWidth);