• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mermaid-js / mermaid / 4608236643

pending completion
4608236643

push

github

Knut Sveidqvist
Merge branch 'release/10.1.0'

1643 of 1996 branches covered (82.31%)

Branch coverage included in aggregate %.

801 of 801 new or added lines in 37 files covered. (100.0%)

16190 of 33430 relevant lines covered (48.43%)

403.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

26.36
/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js
1
/** Created by knut on 14-12-11. */
1✔
2
import { select } from 'd3';
1✔
3
import { log } from '../../logger';
1✔
4
import { getConfig } from '../../config';
1✔
5
import { setupGraphViewbox } from '../../setupGraphViewbox';
1✔
6
import svgDraw from './svgDraw';
1✔
7
import cytoscape from 'cytoscape/dist/cytoscape.umd.js';
1✔
8
import coseBilkent from 'cytoscape-cose-bilkent';
1✔
9
import * as db from './mindmapDb';
1✔
10

1✔
11
// Inject the layout algorithm into cytoscape
1✔
12
cytoscape.use(coseBilkent);
1✔
13

1✔
14
/**
1✔
15
 * @param {any} svg The svg element to draw the diagram onto
1✔
16
 * @param {object} mindmap The mindmap data and hierarchy
1✔
17
 * @param section
1✔
18
 * @param {object} conf The configuration object
1✔
19
 */
1✔
20
function drawNodes(svg, mindmap, section, conf) {
×
21
  svgDraw.drawNode(svg, mindmap, section, conf);
×
22
  if (mindmap.children) {
×
23
    mindmap.children.forEach((child, index) => {
×
24
      drawNodes(svg, child, section < 0 ? index : section, conf);
×
25
    });
×
26
  }
×
27
}
×
28

1✔
29
/**
1✔
30
 * @param edgesEl
1✔
31
 * @param cy
1✔
32
 */
1✔
33
function drawEdges(edgesEl, cy) {
×
34
  cy.edges().map((edge, id) => {
×
35
    const data = edge.data();
×
36
    if (edge[0]._private.bodyBounds) {
×
37
      const bounds = edge[0]._private.rscratch;
×
38
      log.trace('Edge: ', id, data);
×
39
      edgesEl
×
40
        .insert('path')
×
41
        .attr(
×
42
          'd',
×
43
          `M ${bounds.startX},${bounds.startY} L ${bounds.midX},${bounds.midY} L${bounds.endX},${bounds.endY} `
×
44
        )
×
45
        .attr('class', 'edge section-edge-' + data.section + ' edge-depth-' + data.depth);
×
46
    }
×
47
  });
×
48
}
×
49

1✔
50
/**
1✔
51
 * @param mindmap The mindmap data and hierarchy
1✔
52
 * @param cy
1✔
53
 * @param conf The configuration object
1✔
54
 * @param level
1✔
55
 */
1✔
56
function addNodes(mindmap, cy, conf, level) {
×
57
  cy.add({
×
58
    group: 'nodes',
×
59
    data: {
×
60
      id: mindmap.id,
×
61
      labelText: mindmap.descr,
×
62
      height: mindmap.height,
×
63
      width: mindmap.width,
×
64
      level: level,
×
65
      nodeId: mindmap.id,
×
66
      padding: mindmap.padding,
×
67
      type: mindmap.type,
×
68
    },
×
69
    position: {
×
70
      x: mindmap.x,
×
71
      y: mindmap.y,
×
72
    },
×
73
  });
×
74
  if (mindmap.children) {
×
75
    mindmap.children.forEach((child) => {
×
76
      addNodes(child, cy, conf, level + 1);
×
77
      cy.add({
×
78
        group: 'edges',
×
79
        data: {
×
80
          id: `${mindmap.id}_${child.id}`,
×
81
          source: mindmap.id,
×
82
          target: child.id,
×
83
          depth: level,
×
84
          section: child.section,
×
85
        },
×
86
      });
×
87
    });
×
88
  }
×
89
}
×
90

1✔
91
/**
1✔
92
 * @param node
1✔
93
 * @param conf
1✔
94
 * @param cy
1✔
95
 */
1✔
96
function layoutMindmap(node, conf) {
×
97
  return new Promise((resolve) => {
×
98
    // Add temporary render element
×
99
    const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none');
×
100
    const cy = cytoscape({
×
101
      container: document.getElementById('cy'), // container to render in
×
102
      style: [
×
103
        {
×
104
          selector: 'edge',
×
105
          style: {
×
106
            'curve-style': 'bezier',
×
107
          },
×
108
        },
×
109
      ],
×
110
    });
×
111
    // Remove element after layout
×
112
    renderEl.remove();
×
113
    addNodes(node, cy, conf, 0);
×
114

×
115
    // Make cytoscape care about the dimensions of the nodes
×
116
    cy.nodes().forEach(function (n) {
×
117
      n.layoutDimensions = () => {
×
118
        const data = n.data();
×
119
        return { w: data.width, h: data.height };
×
120
      };
×
121
    });
×
122

×
123
    cy.layout({
×
124
      name: 'cose-bilkent',
×
125
      quality: 'proof',
×
126
      // headless: true,
×
127
      styleEnabled: false,
×
128
      animate: false,
×
129
    }).run();
×
130
    cy.ready((e) => {
×
131
      log.info('Ready', e);
×
132
      resolve(cy);
×
133
    });
×
134
  });
×
135
}
×
136
/**
1✔
137
 * @param node
1✔
138
 * @param cy
1✔
139
 * @param positionedMindmap
1✔
140
 * @param conf
1✔
141
 */
1✔
142
function positionNodes(cy) {
×
143
  cy.nodes().map((node, id) => {
×
144
    const data = node.data();
×
145
    data.x = node.position().x;
×
146
    data.y = node.position().y;
×
147
    svgDraw.positionNode(data);
×
148
    const el = db.getElementById(data.nodeId);
×
149
    log.info('Id:', id, 'Position: (', node.position().x, ', ', node.position().y, ')', data);
×
150
    el.attr(
×
151
      'transform',
×
152
      `translate(${node.position().x - data.width / 2}, ${node.position().y - data.height / 2})`
×
153
    );
×
154
    el.attr('attr', `apa-${id})`);
×
155
  });
×
156
}
×
157

1✔
158
/**
1✔
159
 * Draws a an info picture in the tag with id: id based on the graph definition in text.
1✔
160
 *
1✔
161
 * @param {any} text
1✔
162
 * @param {any} id
1✔
163
 * @param {any} version
1✔
164
 * @param diagObj
1✔
165
 */
1✔
166

1✔
167
export const draw = async (text, id, version, diagObj) => {
1✔
168
  const conf = getConfig();
×
169

×
170
  // console.log('Config: ', conf);
×
171
  conf.htmlLabels = false;
×
172

×
173
  // This is done only for throwing the error if the text is not valid.
×
174
  diagObj.db.clear();
×
175
  // Parse the graph definition
×
176
  diagObj.parser.parse(text);
×
177

×
178
  log.debug('Rendering mindmap diagram\n' + text, diagObj.parser);
×
179

×
180
  const securityLevel = getConfig().securityLevel;
×
181
  // Handle root and Document for when rendering in sandbox mode
×
182
  let sandboxElement;
×
183
  if (securityLevel === 'sandbox') {
×
184
    sandboxElement = select('#i' + id);
×
185
  }
×
186
  const root =
×
187
    securityLevel === 'sandbox'
×
188
      ? select(sandboxElement.nodes()[0].contentDocument.body)
×
189
      : select('body');
×
190
  // Parse the graph definition
×
191

×
192
  const svg = root.select('#' + id);
×
193

×
194
  svg.append('g');
×
195
  const mm = diagObj.db.getMindmap();
×
196

×
197
  // Draw the graph and start with drawing the nodes without proper position
×
198
  // this gives us the size of the nodes and we can set the positions later
×
199

×
200
  const edgesElem = svg.append('g');
×
201
  edgesElem.attr('class', 'mindmap-edges');
×
202
  const nodesElem = svg.append('g');
×
203
  nodesElem.attr('class', 'mindmap-nodes');
×
204
  drawNodes(nodesElem, mm, -1, conf);
×
205

×
206
  // Next step is to layout the mindmap, giving each node a position
×
207

×
208
  const cy = await layoutMindmap(mm, conf);
×
209

×
210
  // // After this we can draw, first the edges and the then nodes with the correct position
×
211
  drawEdges(edgesElem, cy, conf);
×
212
  positionNodes(cy, conf);
×
213

×
214
  // Setup the view box and size of the svg element
×
215
  setupGraphViewbox(undefined, svg, conf.mindmap.padding, conf.mindmap.useMaxWidth);
×
216
};
×
217

1✔
218
export default {
1✔
219
  draw,
1✔
220
};
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc