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

mermaid-js / mermaid / 4877493129

pending completion
4877493129

Pull #4259

github

GitHub
Merge 61e31b3fe into bf3795652
Pull Request #4259: Refactor to consolidate shared svgDraw components

1732 of 2144 branches covered (80.78%)

Branch coverage included in aggregate %.

157 of 157 new or added lines in 7 files covered. (100.0%)

18628 of 33485 relevant lines covered (55.63%)

394.7 hits per line

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

69.51
/packages/mermaid/src/diagrams/sequence/svgDraw.js
1
import common from '../common/common.js';
1✔
2
import * as svgDrawCommon from '../common/svgDrawCommon';
1✔
3
import { addFunction } from '../../interactionDb.js';
1✔
4
import { parseFontSize } from '../../utils.js';
1✔
5
import { sanitizeUrl } from '@braintree/sanitize-url';
1✔
6

1✔
7
export const drawRect = function (elem, rectData) {
1✔
8
  return svgDrawCommon.drawRect(elem, rectData);
80✔
9
};
80✔
10

1✔
11
const addPopupInteraction = (id, actorCnt) => {
1✔
12
  addFunction(() => {
49✔
13
    const arr = document.querySelectorAll(id);
×
14
    // This will be the case when running in sandboxed mode
×
15
    if (arr.length === 0) {
×
16
      return;
×
17
    }
×
18
    arr[0].addEventListener('mouseover', function () {
×
19
      popupMenuUpFunc('actor' + actorCnt + '_popup');
×
20
    });
×
21
    arr[0].addEventListener('mouseout', function () {
×
22
      popupMenuDownFunc('actor' + actorCnt + '_popup');
×
23
    });
×
24
  });
49✔
25
};
49✔
26

1✔
27
export const drawPopup = function (elem, actor, minMenuWidth, textAttrs, forceMenus) {
1✔
28
  if (actor.links === undefined || actor.links === null || Object.keys(actor.links).length === 0) {
49✔
29
    return { height: 0, width: 0 };
49✔
30
  }
49✔
31

×
32
  const links = actor.links;
×
33
  const actorCnt = actor.actorCnt;
×
34
  const rectData = actor.rectData;
×
35

×
36
  var displayValue = 'none';
×
37
  if (forceMenus) {
×
38
    displayValue = 'block !important';
×
39
  }
×
40

×
41
  const g = elem.append('g');
×
42
  g.attr('id', 'actor' + actorCnt + '_popup');
×
43
  g.attr('class', 'actorPopupMenu');
×
44
  g.attr('display', displayValue);
×
45
  addPopupInteraction('#actor' + actorCnt + '_popup', actorCnt);
×
46
  var actorClass = '';
×
47
  if (rectData.class !== undefined) {
×
48
    actorClass = ' ' + rectData.class;
×
49
  }
×
50

×
51
  let menuWidth = rectData.width > minMenuWidth ? rectData.width : minMenuWidth;
49!
52

49✔
53
  const rectElem = g.append('rect');
49✔
54
  rectElem.attr('class', 'actorPopupMenuPanel' + actorClass);
49✔
55
  rectElem.attr('x', rectData.x);
49✔
56
  rectElem.attr('y', rectData.height);
49✔
57
  rectElem.attr('fill', rectData.fill);
49✔
58
  rectElem.attr('stroke', rectData.stroke);
49✔
59
  rectElem.attr('width', menuWidth);
49✔
60
  rectElem.attr('height', rectData.height);
49✔
61
  rectElem.attr('rx', rectData.rx);
49✔
62
  rectElem.attr('ry', rectData.ry);
49✔
63
  if (links != null) {
49!
64
    var linkY = 20;
×
65
    for (let key in links) {
×
66
      var linkElem = g.append('a');
×
67
      var sanitizedLink = sanitizeUrl(links[key]);
×
68
      linkElem.attr('xlink:href', sanitizedLink);
×
69
      linkElem.attr('target', '_blank');
×
70

×
71
      _drawMenuItemTextCandidateFunc(textAttrs)(
×
72
        key,
×
73
        linkElem,
×
74
        rectData.x + 10,
×
75
        rectData.height + linkY,
×
76
        menuWidth,
×
77
        20,
×
78
        { class: 'actor' },
×
79
        textAttrs
×
80
      );
×
81

×
82
      linkY += 30;
×
83
    }
×
84
  }
×
85

×
86
  rectElem.attr('height', linkY);
×
87

×
88
  return { height: rectData.height + linkY, width: menuWidth };
×
89
};
×
90

1✔
91
export const popupMenu = function (popid) {
1✔
92
  return (
×
93
    "var pu = document.getElementById('" +
×
94
    popid +
×
95
    "'); if (pu != null) { pu.style.display = 'block'; }"
×
96
  );
×
97
};
×
98

1✔
99
export const popdownMenu = function (popid) {
1✔
100
  return (
×
101
    "var pu = document.getElementById('" +
×
102
    popid +
×
103
    "'); if (pu != null) { pu.style.display = 'none'; }"
×
104
  );
×
105
};
×
106

1✔
107
const popupMenuUpFunc = function (popupId) {
1✔
108
  var pu = document.getElementById(popupId);
×
109
  if (pu != null) {
×
110
    pu.style.display = 'block';
×
111
  }
×
112
};
×
113

1✔
114
const popupMenuDownFunc = function (popupId) {
1✔
115
  var pu = document.getElementById(popupId);
×
116
  if (pu != null) {
×
117
    pu.style.display = 'none';
×
118
  }
×
119
};
×
120

1✔
121
export const drawText = function (elem, textData) {
1✔
122
  let prevTextHeight = 0;
51✔
123
  let textHeight = 0;
51✔
124
  const lines = textData.text.split(common.lineBreakRegex);
51✔
125

51✔
126
  const [_textFontSize, _textFontSizePx] = parseFontSize(textData.fontSize);
51✔
127

51✔
128
  let textElems = [];
51✔
129
  let dy = 0;
51✔
130
  let yfunc = () => textData.y;
51✔
131
  if (
51✔
132
    textData.valign !== undefined &&
51✔
133
    textData.textMargin !== undefined &&
51✔
134
    textData.textMargin > 0
48✔
135
  ) {
51✔
136
    switch (textData.valign) {
48✔
137
      case 'top':
48!
138
      case 'start':
48!
139
        yfunc = () => Math.round(textData.y + textData.textMargin);
×
140
        break;
×
141
      case 'middle':
48✔
142
      case 'center':
48✔
143
        yfunc = () =>
48✔
144
          Math.round(textData.y + (prevTextHeight + textHeight + textData.textMargin) / 2);
48✔
145
        break;
48✔
146
      case 'bottom':
48!
147
      case 'end':
48!
148
        yfunc = () =>
×
149
          Math.round(
×
150
            textData.y +
×
151
              (prevTextHeight + textHeight + 2 * textData.textMargin) -
×
152
              textData.textMargin
×
153
          );
×
154
        break;
×
155
    }
48✔
156
  }
48✔
157

51✔
158
  if (
51✔
159
    textData.anchor !== undefined &&
51✔
160
    textData.textMargin !== undefined &&
51✔
161
    textData.width !== undefined
48✔
162
  ) {
51✔
163
    switch (textData.anchor) {
48✔
164
      case 'left':
48!
165
      case 'start':
48!
166
        textData.x = Math.round(textData.x + textData.textMargin);
×
167
        textData.anchor = 'start';
×
168
        textData.dominantBaseline = 'middle';
×
169
        textData.alignmentBaseline = 'middle';
×
170
        break;
×
171
      case 'middle':
48✔
172
      case 'center':
48✔
173
        textData.x = Math.round(textData.x + textData.width / 2);
48✔
174
        textData.anchor = 'middle';
48✔
175
        textData.dominantBaseline = 'middle';
48✔
176
        textData.alignmentBaseline = 'middle';
48✔
177
        break;
48✔
178
      case 'right':
48!
179
      case 'end':
48!
180
        textData.x = Math.round(textData.x + textData.width - textData.textMargin);
×
181
        textData.anchor = 'end';
×
182
        textData.dominantBaseline = 'middle';
×
183
        textData.alignmentBaseline = 'middle';
×
184
        break;
×
185
    }
48✔
186
  }
48✔
187

51✔
188
  for (let [i, line] of lines.entries()) {
51✔
189
    if (
53✔
190
      textData.textMargin !== undefined &&
53✔
191
      textData.textMargin === 0 &&
53!
192
      _textFontSize !== undefined
×
193
    ) {
53!
194
      dy = i * _textFontSize;
×
195
    }
×
196

53✔
197
    const textElem = elem.append('text');
53✔
198
    textElem.attr('x', textData.x);
53✔
199
    textElem.attr('y', yfunc());
53✔
200
    if (textData.anchor !== undefined) {
53✔
201
      textElem
48✔
202
        .attr('text-anchor', textData.anchor)
48✔
203
        .attr('dominant-baseline', textData.dominantBaseline)
48✔
204
        .attr('alignment-baseline', textData.alignmentBaseline);
48✔
205
    }
48✔
206
    if (textData.fontFamily !== undefined) {
53✔
207
      textElem.style('font-family', textData.fontFamily);
50✔
208
    }
50✔
209
    if (_textFontSizePx !== undefined) {
53✔
210
      textElem.style('font-size', _textFontSizePx);
50✔
211
    }
50✔
212
    if (textData.fontWeight !== undefined) {
53✔
213
      textElem.style('font-weight', textData.fontWeight);
50✔
214
    }
50✔
215
    if (textData.fill !== undefined) {
53!
216
      textElem.attr('fill', textData.fill);
×
217
    }
×
218
    if (textData.class !== undefined) {
53✔
219
      textElem.attr('class', textData.class);
50✔
220
    }
50✔
221
    if (textData.dy !== undefined) {
53✔
222
      textElem.attr('dy', textData.dy);
48✔
223
    } else if (dy !== 0) {
53!
224
      textElem.attr('dy', dy);
×
225
    }
×
226

53✔
227
    if (textData.tspan) {
53✔
228
      const span = textElem.append('tspan');
16✔
229
      span.attr('x', textData.x);
16✔
230
      if (textData.fill !== undefined) {
16!
231
        span.attr('fill', textData.fill);
×
232
      }
×
233
      span.text(line);
16✔
234
    } else {
53✔
235
      textElem.text(line);
37✔
236
    }
37✔
237
    if (
53✔
238
      textData.valign !== undefined &&
53✔
239
      textData.textMargin !== undefined &&
53✔
240
      textData.textMargin > 0
48✔
241
    ) {
53✔
242
      textHeight += (textElem._groups || textElem)[0][0].getBBox().height;
48✔
243
      prevTextHeight = textHeight;
48✔
244
    }
48✔
245

53✔
246
    textElems.push(textElem);
53✔
247
  }
53✔
248

51✔
249
  return textElems;
51✔
250
};
51✔
251

1✔
252
export const drawLabel = function (elem, txtObject) {
1✔
253
  /**
1✔
254
   * @param {any} x
1✔
255
   * @param {any} y
1✔
256
   * @param {any} width
1✔
257
   * @param {any} height
1✔
258
   * @param {any} cut
1✔
259
   * @returns {any}
1✔
260
   */
1✔
261
  function genPoints(x, y, width, height, cut) {
1✔
262
    return (
1✔
263
      x +
1✔
264
      ',' +
1✔
265
      y +
1✔
266
      ' ' +
1✔
267
      (x + width) +
1✔
268
      ',' +
1✔
269
      y +
1✔
270
      ' ' +
1✔
271
      (x + width) +
1✔
272
      ',' +
1✔
273
      (y + height - cut) +
1✔
274
      ' ' +
1✔
275
      (x + width - cut * 1.2) +
1✔
276
      ',' +
1✔
277
      (y + height) +
1✔
278
      ' ' +
1✔
279
      x +
1✔
280
      ',' +
1✔
281
      (y + height)
1✔
282
    );
1✔
283
  }
1✔
284
  const polygon = elem.append('polygon');
1✔
285
  polygon.attr('points', genPoints(txtObject.x, txtObject.y, txtObject.width, txtObject.height, 7));
1✔
286
  polygon.attr('class', 'labelBox');
1✔
287

1✔
288
  txtObject.y = txtObject.y + txtObject.height / 2;
1✔
289

1✔
290
  drawText(elem, txtObject);
1✔
291
  return polygon;
1✔
292
};
1✔
293

1✔
294
let actorCnt = -1;
1✔
295

1✔
296
export const fixLifeLineHeights = (diagram, bounds) => {
1✔
297
  if (!diagram.selectAll) {
10✔
298
    return;
10✔
299
  }
10✔
300
  diagram
×
301
    .selectAll('.actor-line')
×
302
    .attr('class', '200')
×
303
    .attr('y2', bounds - 55);
×
304
};
×
305

1✔
306
/**
1✔
307
 * Draws an actor in the diagram with the attached line
1✔
308
 *
1✔
309
 * @param {any} elem - The diagram we'll draw to.
1✔
310
 * @param {any} actor - The actor to draw.
1✔
311
 * @param {any} conf - DrawText implementation discriminator object
1✔
312
 * @param {boolean} isFooter - If the actor is the footer one
1✔
313
 */
1✔
314
const drawActorTypeParticipant = function (elem, actor, conf, isFooter) {
1✔
315
  const center = actor.x + actor.width / 2;
63✔
316
  const centerY = actor.y + 5;
63✔
317

63✔
318
  const boxpluslineGroup = elem.append('g');
63✔
319
  var g = boxpluslineGroup;
63✔
320

63✔
321
  if (!isFooter) {
63✔
322
    actorCnt++;
49✔
323
    g.append('line')
49✔
324
      .attr('id', 'actor' + actorCnt)
49✔
325
      .attr('x1', center)
49✔
326
      .attr('y1', centerY)
49✔
327
      .attr('x2', center)
49✔
328
      .attr('y2', 2000)
49✔
329
      .attr('class', 'actor-line')
49✔
330
      .attr('stroke-width', '0.5px')
49✔
331
      .attr('stroke', '#999');
49✔
332

49✔
333
    g = boxpluslineGroup.append('g');
49✔
334
    actor.actorCnt = actorCnt;
49✔
335

49✔
336
    if (actor.links != null) {
49✔
337
      g.attr('id', 'root-' + actorCnt);
49✔
338
      addPopupInteraction('#root-' + actorCnt, actorCnt);
49✔
339
    }
49✔
340
  }
49✔
341

63✔
342
  const rect = svgDrawCommon.getNoteRect();
63✔
343
  var cssclass = 'actor';
63✔
344
  if (actor.properties != null && actor.properties['class']) {
63!
345
    cssclass = actor.properties['class'];
×
346
  } else {
63✔
347
    rect.fill = '#eaeaea';
63✔
348
  }
63✔
349
  rect.x = actor.x;
63✔
350
  rect.y = actor.y;
63✔
351
  rect.width = actor.width;
63✔
352
  rect.height = actor.height;
63✔
353
  rect.class = cssclass;
63✔
354
  rect.rx = 3;
63✔
355
  rect.ry = 3;
63✔
356
  const rectElem = drawRect(g, rect);
63✔
357
  actor.rectData = rect;
63✔
358

63✔
359
  if (actor.properties != null && actor.properties['icon']) {
63!
360
    const iconSrc = actor.properties['icon'].trim();
×
361
    if (iconSrc.charAt(0) === '@') {
×
362
      svgDrawCommon.drawEmbeddedImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc.substr(1));
×
363
    } else {
×
364
      svgDrawCommon.drawImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc);
×
365
    }
×
366
  }
×
367

63✔
368
  _drawTextCandidateFunc(conf)(
63✔
369
    actor.description,
63✔
370
    g,
63✔
371
    rect.x,
63✔
372
    rect.y,
63✔
373
    rect.width,
63✔
374
    rect.height,
63✔
375
    { class: 'actor' },
63✔
376
    conf
63✔
377
  );
63✔
378

63✔
379
  let height = actor.height;
63✔
380
  if (rectElem.node) {
63!
381
    const bounds = rectElem.node().getBBox();
×
382
    actor.height = bounds.height;
×
383
    height = bounds.height;
×
384
  }
×
385

63✔
386
  return height;
63✔
387
};
63✔
388

1✔
389
const drawActorTypeActor = function (elem, actor, conf, isFooter) {
1✔
390
  const center = actor.x + actor.width / 2;
×
391
  const centerY = actor.y + 80;
×
392

×
393
  if (!isFooter) {
×
394
    actorCnt++;
×
395
    elem
×
396
      .append('line')
×
397
      .attr('id', 'actor' + actorCnt)
×
398
      .attr('x1', center)
×
399
      .attr('y1', centerY)
×
400
      .attr('x2', center)
×
401
      .attr('y2', 2000)
×
402
      .attr('class', 'actor-line')
×
403
      .attr('stroke-width', '0.5px')
×
404
      .attr('stroke', '#999');
×
405
  }
×
406
  const actElem = elem.append('g');
×
407
  actElem.attr('class', 'actor-man');
×
408

×
409
  const rect = svgDrawCommon.getNoteRect();
×
410
  rect.x = actor.x;
×
411
  rect.y = actor.y;
×
412
  rect.fill = '#eaeaea';
×
413
  rect.width = actor.width;
×
414
  rect.height = actor.height;
×
415
  rect.class = 'actor';
×
416
  rect.rx = 3;
×
417
  rect.ry = 3;
×
418

×
419
  actElem
×
420
    .append('line')
×
421
    .attr('id', 'actor-man-torso' + actorCnt)
×
422
    .attr('x1', center)
×
423
    .attr('y1', actor.y + 25)
×
424
    .attr('x2', center)
×
425
    .attr('y2', actor.y + 45);
×
426

×
427
  actElem
×
428
    .append('line')
×
429
    .attr('id', 'actor-man-arms' + actorCnt)
×
430
    .attr('x1', center - 18)
×
431
    .attr('y1', actor.y + 33)
×
432
    .attr('x2', center + 18)
×
433
    .attr('y2', actor.y + 33);
×
434
  actElem
×
435
    .append('line')
×
436
    .attr('x1', center - 18)
×
437
    .attr('y1', actor.y + 60)
×
438
    .attr('x2', center)
×
439
    .attr('y2', actor.y + 45);
×
440
  actElem
×
441
    .append('line')
×
442
    .attr('x1', center)
×
443
    .attr('y1', actor.y + 45)
×
444
    .attr('x2', center + 16)
×
445
    .attr('y2', actor.y + 60);
×
446

×
447
  const circle = actElem.append('circle');
×
448
  circle.attr('cx', actor.x + actor.width / 2);
×
449
  circle.attr('cy', actor.y + 10);
×
450
  circle.attr('r', 15);
×
451
  circle.attr('width', actor.width);
×
452
  circle.attr('height', actor.height);
×
453

×
454
  const bounds = actElem.node().getBBox();
×
455
  actor.height = bounds.height;
×
456

×
457
  _drawTextCandidateFunc(conf)(
×
458
    actor.description,
×
459
    actElem,
×
460
    rect.x,
×
461
    rect.y + 35,
×
462
    rect.width,
×
463
    rect.height,
×
464
    { class: 'actor' },
×
465
    conf
×
466
  );
×
467

×
468
  return actor.height;
×
469
};
×
470

1✔
471
export const drawActor = function (elem, actor, conf, isFooter) {
1✔
472
  switch (actor.type) {
63✔
473
    case 'actor':
63!
474
      return drawActorTypeActor(elem, actor, conf, isFooter);
×
475
    case 'participant':
63✔
476
      return drawActorTypeParticipant(elem, actor, conf, isFooter);
63✔
477
  }
63✔
478
};
63✔
479

1✔
480
export const drawBox = function (elem, box, conf) {
1✔
481
  const boxplustextGroup = elem.append('g');
1✔
482
  const g = boxplustextGroup;
1✔
483
  drawBackgroundRect(g, box);
1✔
484
  if (box.name) {
1✔
485
    _drawTextCandidateFunc(conf)(
1✔
486
      box.name,
1✔
487
      g,
1✔
488
      box.x,
1✔
489
      box.y + (box.textMaxHeight || 0) / 2,
1✔
490
      box.width,
1✔
491
      0,
1✔
492
      { class: 'text' },
1✔
493
      conf
1✔
494
    );
1✔
495
  }
1✔
496
  g.lower();
1✔
497
};
1✔
498

1✔
499
export const anchorElement = function (elem) {
1✔
500
  return elem.append('g');
×
501
};
×
502

1✔
503
/**
1✔
504
 * Draws an activation in the diagram
1✔
505
 *
1✔
506
 * @param {any} elem - Element to append activation rect.
1✔
507
 * @param {any} bounds - Activation box bounds.
1✔
508
 * @param {any} verticalPos - Precise y coordinate of bottom activation box edge.
1✔
509
 * @param {any} conf - Sequence diagram config object.
1✔
510
 * @param {any} actorActivations - Number of activations on the actor.
1✔
511
 */
1✔
512
export const drawActivation = function (elem, bounds, verticalPos, conf, actorActivations) {
1✔
513
  const rect = svgDrawCommon.getNoteRect();
×
514
  const g = bounds.anchored;
×
515
  rect.x = bounds.startx;
×
516
  rect.y = bounds.starty;
×
517
  rect.class = 'activation' + (actorActivations % 3); // Will evaluate to 0, 1 or 2
×
518
  rect.width = bounds.stopx - bounds.startx;
×
519
  rect.height = verticalPos - bounds.starty;
×
520
  drawRect(g, rect);
×
521
};
×
522

1✔
523
/**
1✔
524
 * Draws a loop in the diagram
1✔
525
 *
1✔
526
 * @param {any} elem - Element to append the loop to.
1✔
527
 * @param {any} loopModel - LoopModel of the given loop.
1✔
528
 * @param {any} labelText - Text within the loop.
1✔
529
 * @param {any} conf - Diagram configuration
1✔
530
 * @returns {any}
1✔
531
 */
1✔
532
export const drawLoop = function (elem, loopModel, labelText, conf) {
1✔
533
  const {
1✔
534
    boxMargin,
1✔
535
    boxTextMargin,
1✔
536
    labelBoxHeight,
1✔
537
    labelBoxWidth,
1✔
538
    messageFontFamily: fontFamily,
1✔
539
    messageFontSize: fontSize,
1✔
540
    messageFontWeight: fontWeight,
1✔
541
  } = conf;
1✔
542
  const g = elem.append('g');
1✔
543
  const drawLoopLine = function (startx, starty, stopx, stopy) {
1✔
544
    return g
4✔
545
      .append('line')
4✔
546
      .attr('x1', startx)
4✔
547
      .attr('y1', starty)
4✔
548
      .attr('x2', stopx)
4✔
549
      .attr('y2', stopy)
4✔
550
      .attr('class', 'loopLine');
4✔
551
  };
1✔
552
  drawLoopLine(loopModel.startx, loopModel.starty, loopModel.stopx, loopModel.starty);
1✔
553
  drawLoopLine(loopModel.stopx, loopModel.starty, loopModel.stopx, loopModel.stopy);
1✔
554
  drawLoopLine(loopModel.startx, loopModel.stopy, loopModel.stopx, loopModel.stopy);
1✔
555
  drawLoopLine(loopModel.startx, loopModel.starty, loopModel.startx, loopModel.stopy);
1✔
556
  if (loopModel.sections !== undefined) {
1!
557
    loopModel.sections.forEach(function (item) {
×
558
      drawLoopLine(loopModel.startx, item.y, loopModel.stopx, item.y).style(
×
559
        'stroke-dasharray',
×
560
        '3, 3'
×
561
      );
×
562
    });
×
563
  }
×
564

1✔
565
  let txt = svgDrawCommon.getTextObj();
1✔
566
  txt.text = labelText;
1✔
567
  txt.x = loopModel.startx;
1✔
568
  txt.y = loopModel.starty;
1✔
569
  txt.fontFamily = fontFamily;
1✔
570
  txt.fontSize = fontSize;
1✔
571
  txt.fontWeight = fontWeight;
1✔
572
  txt.anchor = 'middle';
1✔
573
  txt.valign = 'middle';
1✔
574
  txt.tspan = false;
1✔
575
  txt.width = labelBoxWidth || 50;
1!
576
  txt.height = labelBoxHeight || 20;
1!
577
  txt.textMargin = boxTextMargin;
1✔
578
  txt.class = 'labelText';
1✔
579

1✔
580
  drawLabel(g, txt);
1✔
581
  txt = svgDrawCommon.getTextObj();
1✔
582
  txt.text = loopModel.title;
1✔
583
  txt.x = loopModel.startx + labelBoxWidth / 2 + (loopModel.stopx - loopModel.startx) / 2;
1✔
584
  txt.y = loopModel.starty + boxMargin + boxTextMargin;
1✔
585
  txt.anchor = 'middle';
1✔
586
  txt.valign = 'middle';
1✔
587
  txt.textMargin = boxTextMargin;
1✔
588
  txt.class = 'loopText';
1✔
589
  txt.fontFamily = fontFamily;
1✔
590
  txt.fontSize = fontSize;
1✔
591
  txt.fontWeight = fontWeight;
1✔
592
  txt.wrap = true;
1✔
593

1✔
594
  let textElem = drawText(g, txt);
1✔
595

1✔
596
  if (loopModel.sectionTitles !== undefined) {
1!
597
    loopModel.sectionTitles.forEach(function (item, idx) {
×
598
      if (item.message) {
×
599
        txt.text = item.message;
×
600
        txt.x = loopModel.startx + (loopModel.stopx - loopModel.startx) / 2;
×
601
        txt.y = loopModel.sections[idx].y + boxMargin + boxTextMargin;
×
602
        txt.class = 'loopText';
×
603
        txt.anchor = 'middle';
×
604
        txt.valign = 'middle';
×
605
        txt.tspan = false;
×
606
        txt.fontFamily = fontFamily;
×
607
        txt.fontSize = fontSize;
×
608
        txt.fontWeight = fontWeight;
×
609
        txt.wrap = loopModel.wrap;
×
610
        textElem = drawText(g, txt);
×
611
        let sectionHeight = Math.round(
×
612
          textElem
×
613
            .map((te) => (te._groups || te)[0][0].getBBox().height)
×
614
            .reduce((acc, curr) => acc + curr)
×
615
        );
×
616
        loopModel.sections[idx].height += sectionHeight - (boxMargin + boxTextMargin);
×
617
      }
×
618
    });
×
619
  }
×
620

1✔
621
  loopModel.height = Math.round(loopModel.stopy - loopModel.starty);
1✔
622
  return g;
1✔
623
};
1✔
624

1✔
625
/**
1✔
626
 * Draws a background rectangle
1✔
627
 *
1✔
628
 * @param {any} elem Diagram (reference for bounds)
1✔
629
 * @param {any} bounds Shape of the rectangle
1✔
630
 */
1✔
631
export const drawBackgroundRect = function (elem, bounds) {
1✔
632
  svgDrawCommon.drawBackgroundRect(elem, bounds);
3✔
633
};
3✔
634

1✔
635
export const insertDatabaseIcon = function (elem) {
1✔
636
  elem
31✔
637
    .append('defs')
31✔
638
    .append('symbol')
31✔
639
    .attr('id', 'database')
31✔
640
    .attr('fill-rule', 'evenodd')
31✔
641
    .attr('clip-rule', 'evenodd')
31✔
642
    .append('path')
31✔
643
    .attr('transform', 'scale(.5)')
31✔
644
    .attr(
31✔
645
      'd',
31✔
646
      'M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z'
31✔
647
    );
31✔
648
};
31✔
649

1✔
650
export const insertComputerIcon = function (elem) {
1✔
651
  elem
31✔
652
    .append('defs')
31✔
653
    .append('symbol')
31✔
654
    .attr('id', 'computer')
31✔
655
    .attr('width', '24')
31✔
656
    .attr('height', '24')
31✔
657
    .append('path')
31✔
658
    .attr('transform', 'scale(.5)')
31✔
659
    .attr(
31✔
660
      'd',
31✔
661
      'M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z'
31✔
662
    );
31✔
663
};
31✔
664

1✔
665
export const insertClockIcon = function (elem) {
1✔
666
  elem
31✔
667
    .append('defs')
31✔
668
    .append('symbol')
31✔
669
    .attr('id', 'clock')
31✔
670
    .attr('width', '24')
31✔
671
    .attr('height', '24')
31✔
672
    .append('path')
31✔
673
    .attr('transform', 'scale(.5)')
31✔
674
    .attr(
31✔
675
      'd',
31✔
676
      'M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z'
31✔
677
    );
31✔
678
};
31✔
679

1✔
680
/**
1✔
681
 * Setup arrow head and define the marker. The result is appended to the svg.
1✔
682
 *
1✔
683
 * @param elem
1✔
684
 */
1✔
685
export const insertArrowHead = function (elem) {
1✔
686
  elem
31✔
687
    .append('defs')
31✔
688
    .append('marker')
31✔
689
    .attr('id', 'arrowhead')
31✔
690
    .attr('refX', 9)
31✔
691
    .attr('refY', 5)
31✔
692
    .attr('markerUnits', 'userSpaceOnUse')
31✔
693
    .attr('markerWidth', 12)
31✔
694
    .attr('markerHeight', 12)
31✔
695
    .attr('orient', 'auto')
31✔
696
    .append('path')
31✔
697
    .attr('d', 'M 0 0 L 10 5 L 0 10 z'); // this is actual shape for arrowhead
31✔
698
};
31✔
699

1✔
700
/**
1✔
701
 * Setup arrow head and define the marker. The result is appended to the svg.
1✔
702
 *
1✔
703
 * @param {any} elem
1✔
704
 */
1✔
705
export const insertArrowFilledHead = function (elem) {
1✔
706
  elem
31✔
707
    .append('defs')
31✔
708
    .append('marker')
31✔
709
    .attr('id', 'filled-head')
31✔
710
    .attr('refX', 18)
31✔
711
    .attr('refY', 7)
31✔
712
    .attr('markerWidth', 20)
31✔
713
    .attr('markerHeight', 28)
31✔
714
    .attr('orient', 'auto')
31✔
715
    .append('path')
31✔
716
    .attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
31✔
717
};
31✔
718

1✔
719
/**
1✔
720
 * Setup node number. The result is appended to the svg.
1✔
721
 *
1✔
722
 * @param {any} elem
1✔
723
 */
1✔
724
export const insertSequenceNumber = function (elem) {
1✔
725
  elem
31✔
726
    .append('defs')
31✔
727
    .append('marker')
31✔
728
    .attr('id', 'sequencenumber')
31✔
729
    .attr('refX', 15)
31✔
730
    .attr('refY', 15)
31✔
731
    .attr('markerWidth', 60)
31✔
732
    .attr('markerHeight', 40)
31✔
733
    .attr('orient', 'auto')
31✔
734
    .append('circle')
31✔
735
    .attr('cx', 15)
31✔
736
    .attr('cy', 15)
31✔
737
    .attr('r', 6);
31✔
738
  // .style("fill", '#f00');
31✔
739
};
31✔
740

1✔
741
/**
1✔
742
 * Setup cross head and define the marker. The result is appended to the svg.
1✔
743
 *
1✔
744
 * @param {any} elem
1✔
745
 */
1✔
746
export const insertArrowCrossHead = function (elem) {
1✔
747
  const defs = elem.append('defs');
31✔
748
  const marker = defs
31✔
749
    .append('marker')
31✔
750
    .attr('id', 'crosshead')
31✔
751
    .attr('markerWidth', 15)
31✔
752
    .attr('markerHeight', 8)
31✔
753
    .attr('orient', 'auto')
31✔
754
    .attr('refX', 4)
31✔
755
    .attr('refY', 5);
31✔
756
  // The cross
31✔
757
  marker
31✔
758
    .append('path')
31✔
759
    .attr('fill', 'none')
31✔
760
    .attr('stroke', '#000000')
31✔
761
    .style('stroke-dasharray', '0, 0')
31✔
762
    .attr('stroke-width', '1pt')
31✔
763
    .attr('d', 'M 1,2 L 6,7 M 6,2 L 1,7');
31✔
764
  // this is actual shape for arrowhead
31✔
765
};
31✔
766

1✔
767
const _drawTextCandidateFunc = (function () {
1✔
768
  /**
6✔
769
   * @param {any} content
6✔
770
   * @param {any} g
6✔
771
   * @param {any} x
6✔
772
   * @param {any} y
6✔
773
   * @param {any} width
6✔
774
   * @param {any} height
6✔
775
   * @param {any} textAttrs
6✔
776
   */
6✔
777
  function byText(content, g, x, y, width, height, textAttrs) {
6✔
778
    const text = g
2✔
779
      .append('text')
2✔
780
      .attr('x', x + width / 2)
2✔
781
      .attr('y', y + height / 2 + 5)
2✔
782
      .style('text-anchor', 'middle')
2✔
783
      .text(content);
2✔
784
    _setTextAttrs(text, textAttrs);
2✔
785
  }
2✔
786

6✔
787
  /**
6✔
788
   * @param {any} content
6✔
789
   * @param {any} g
6✔
790
   * @param {any} x
6✔
791
   * @param {any} y
6✔
792
   * @param {any} width
6✔
793
   * @param {any} height
6✔
794
   * @param {any} textAttrs
6✔
795
   * @param {any} conf
6✔
796
   */
6✔
797
  function byTspan(content, g, x, y, width, height, textAttrs, conf) {
6✔
798
    const { actorFontSize, actorFontFamily, actorFontWeight } = conf;
62✔
799

62✔
800
    const [_actorFontSize, _actorFontSizePx] = parseFontSize(actorFontSize);
62✔
801

62✔
802
    const lines = content.split(common.lineBreakRegex);
62✔
803
    for (let i = 0; i < lines.length; i++) {
62✔
804
      const dy = i * _actorFontSize - (_actorFontSize * (lines.length - 1)) / 2;
62✔
805
      const text = g
62✔
806
        .append('text')
62✔
807
        .attr('x', x + width / 2)
62✔
808
        .attr('y', y)
62✔
809
        .style('text-anchor', 'middle')
62✔
810
        .style('font-size', _actorFontSizePx)
62✔
811
        .style('font-weight', actorFontWeight)
62✔
812
        .style('font-family', actorFontFamily);
62✔
813
      text
62✔
814
        .append('tspan')
62✔
815
        .attr('x', x + width / 2)
62✔
816
        .attr('dy', dy)
62✔
817
        .text(lines[i]);
62✔
818

62✔
819
      text
62✔
820
        .attr('y', y + height / 2.0)
62✔
821
        .attr('dominant-baseline', 'central')
62✔
822
        .attr('alignment-baseline', 'central');
62✔
823

62✔
824
      _setTextAttrs(text, textAttrs);
62✔
825
    }
62✔
826
  }
62✔
827

6✔
828
  /**
6✔
829
   * @param {any} content
6✔
830
   * @param {any} g
6✔
831
   * @param {any} x
6✔
832
   * @param {any} y
6✔
833
   * @param {any} width
6✔
834
   * @param {any} height
6✔
835
   * @param {any} textAttrs
6✔
836
   * @param {any} conf
6✔
837
   */
6✔
838
  function byFo(content, g, x, y, width, height, textAttrs, conf) {
6✔
839
    const s = g.append('switch');
2✔
840
    const f = s
2✔
841
      .append('foreignObject')
2✔
842
      .attr('x', x)
2✔
843
      .attr('y', y)
2✔
844
      .attr('width', width)
2✔
845
      .attr('height', height);
2✔
846

2✔
847
    const text = f
2✔
848
      .append('xhtml:div')
2✔
849
      .style('display', 'table')
2✔
850
      .style('height', '100%')
2✔
851
      .style('width', '100%');
2✔
852

2✔
853
    text
2✔
854
      .append('div')
2✔
855
      .style('display', 'table-cell')
2✔
856
      .style('text-align', 'center')
2✔
857
      .style('vertical-align', 'middle')
2✔
858
      .text(content);
2✔
859

2✔
860
    byTspan(content, s, x, y, width, height, textAttrs, conf);
2✔
861
    _setTextAttrs(text, textAttrs);
2✔
862
  }
2✔
863

6✔
864
  /**
6✔
865
   * @param {any} toText
6✔
866
   * @param {any} fromTextAttrsDict
6✔
867
   */
6✔
868
  function _setTextAttrs(toText, fromTextAttrsDict) {
6✔
869
    for (const key in fromTextAttrsDict) {
66✔
870
      if (fromTextAttrsDict.hasOwnProperty(key)) {
66✔
871
        toText.attr(key, fromTextAttrsDict[key]);
66✔
872
      }
66✔
873
    }
66✔
874
  }
66✔
875

6✔
876
  return function (conf) {
6✔
877
    return conf.textPlacement === 'fo' ? byFo : conf.textPlacement === 'old' ? byText : byTspan;
64✔
878
  };
6✔
879
})();
1✔
880

1✔
881
const _drawMenuItemTextCandidateFunc = (function () {
1✔
882
  /**
6✔
883
   * @param {any} content
6✔
884
   * @param {any} g
6✔
885
   * @param {any} x
6✔
886
   * @param {any} y
6✔
887
   * @param {any} width
6✔
888
   * @param {any} height
6✔
889
   * @param {any} textAttrs
6✔
890
   */
6✔
891
  function byText(content, g, x, y, width, height, textAttrs) {
6✔
892
    const text = g
×
893
      .append('text')
×
894
      .attr('x', x)
×
895
      .attr('y', y)
×
896
      .style('text-anchor', 'start')
×
897
      .text(content);
×
898
    _setTextAttrs(text, textAttrs);
×
899
  }
×
900

6✔
901
  /**
6✔
902
   * @param {any} content
6✔
903
   * @param {any} g
6✔
904
   * @param {any} x
6✔
905
   * @param {any} y
6✔
906
   * @param {any} width
6✔
907
   * @param {any} height
6✔
908
   * @param {any} textAttrs
6✔
909
   * @param {any} conf
6✔
910
   */
6✔
911
  function byTspan(content, g, x, y, width, height, textAttrs, conf) {
6✔
912
    const { actorFontSize, actorFontFamily, actorFontWeight } = conf;
×
913

×
914
    const lines = content.split(common.lineBreakRegex);
×
915
    for (let i = 0; i < lines.length; i++) {
×
916
      const dy = i * actorFontSize - (actorFontSize * (lines.length - 1)) / 2;
×
917
      const text = g
×
918
        .append('text')
×
919
        .attr('x', x)
×
920
        .attr('y', y)
×
921
        .style('text-anchor', 'start')
×
922
        .style('font-size', actorFontSize)
×
923
        .style('font-weight', actorFontWeight)
×
924
        .style('font-family', actorFontFamily);
×
925
      text.append('tspan').attr('x', x).attr('dy', dy).text(lines[i]);
×
926

×
927
      text
×
928
        .attr('y', y + height / 2.0)
×
929
        .attr('dominant-baseline', 'central')
×
930
        .attr('alignment-baseline', 'central');
×
931

×
932
      _setTextAttrs(text, textAttrs);
×
933
    }
×
934
  }
×
935

6✔
936
  /**
6✔
937
   * @param {any} content
6✔
938
   * @param {any} g
6✔
939
   * @param {any} x
6✔
940
   * @param {any} y
6✔
941
   * @param {any} width
6✔
942
   * @param {any} height
6✔
943
   * @param {any} textAttrs
6✔
944
   * @param {any} conf
6✔
945
   */
6✔
946
  function byFo(content, g, x, y, width, height, textAttrs, conf) {
6✔
947
    const s = g.append('switch');
×
948
    const f = s
×
949
      .append('foreignObject')
×
950
      .attr('x', x)
×
951
      .attr('y', y)
×
952
      .attr('width', width)
×
953
      .attr('height', height);
×
954

×
955
    const text = f
×
956
      .append('xhtml:div')
×
957
      .style('display', 'table')
×
958
      .style('height', '100%')
×
959
      .style('width', '100%');
×
960

×
961
    text
×
962
      .append('div')
×
963
      .style('display', 'table-cell')
×
964
      .style('text-align', 'center')
×
965
      .style('vertical-align', 'middle')
×
966
      .text(content);
×
967

×
968
    byTspan(content, s, x, y, width, height, textAttrs, conf);
×
969
    _setTextAttrs(text, textAttrs);
×
970
  }
×
971

6✔
972
  /**
6✔
973
   * @param {any} toText
6✔
974
   * @param {any} fromTextAttrsDict
6✔
975
   */
6✔
976
  function _setTextAttrs(toText, fromTextAttrsDict) {
6✔
977
    for (const key in fromTextAttrsDict) {
×
978
      if (fromTextAttrsDict.hasOwnProperty(key)) {
×
979
        toText.attr(key, fromTextAttrsDict[key]);
×
980
      }
×
981
    }
×
982
  }
×
983

6✔
984
  return function (conf) {
6✔
985
    return conf.textPlacement === 'fo' ? byFo : conf.textPlacement === 'old' ? byText : byTspan;
×
986
  };
6✔
987
})();
1✔
988

1✔
989
export default {
1✔
990
  drawRect,
1✔
991
  drawText,
1✔
992
  drawLabel,
1✔
993
  drawActor,
1✔
994
  drawBox,
1✔
995
  drawPopup,
1✔
996
  anchorElement,
1✔
997
  drawActivation,
1✔
998
  drawLoop,
1✔
999
  drawBackgroundRect,
1✔
1000
  insertArrowHead,
1✔
1001
  insertArrowFilledHead,
1✔
1002
  insertSequenceNumber,
1✔
1003
  insertArrowCrossHead,
1✔
1004
  insertDatabaseIcon,
1✔
1005
  insertComputerIcon,
1✔
1006
  insertClockIcon,
1✔
1007
  popupMenu,
1✔
1008
  popdownMenu,
1✔
1009
  fixLifeLineHeights,
1✔
1010
  sanitizeUrl,
1✔
1011
};
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