2019-09-12 21:58:57 +02:00
|
|
|
import * as d3 from 'd3';
|
|
|
|
import { logger } from './logger';
|
2015-10-17 10:39:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @function detectType
|
|
|
|
* Detects the type of the graph text.
|
|
|
|
* ```mermaid
|
|
|
|
* graph LR
|
|
|
|
* a-->b
|
|
|
|
* b-->c
|
|
|
|
* c-->d
|
|
|
|
* d-->e
|
|
|
|
* e-->f
|
|
|
|
* f-->g
|
|
|
|
* g-->h
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* @param {string} text The text defining the graph
|
|
|
|
* @returns {string} A graph definition key
|
|
|
|
*/
|
2019-09-12 21:58:57 +02:00
|
|
|
export const detectType = function(text) {
|
|
|
|
text = text.replace(/^\s*%%.*\n/g, '\n');
|
|
|
|
logger.debug('Detecting diagram type based on the text ' + text);
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*sequenceDiagram/)) {
|
2019-09-12 21:58:57 +02:00
|
|
|
return 'sequence';
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*gantt/)) {
|
2019-09-12 21:58:57 +02:00
|
|
|
return 'gantt';
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*classDiagram/)) {
|
2019-09-12 21:58:57 +02:00
|
|
|
return 'class';
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2015-10-30 10:47:25 +01:00
|
|
|
|
2019-09-25 21:01:21 +02:00
|
|
|
if (text.match(/^\s*stateDiagram/)) {
|
|
|
|
return 'state';
|
|
|
|
}
|
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*gitGraph/)) {
|
2019-09-12 21:58:57 +02:00
|
|
|
return 'git';
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2019-06-15 14:29:26 +02:00
|
|
|
|
|
|
|
if (text.match(/^\s*info/)) {
|
2019-09-12 21:58:57 +02:00
|
|
|
return 'info';
|
2019-06-15 14:29:26 +02:00
|
|
|
}
|
2019-09-11 21:20:28 +02:00
|
|
|
if (text.match(/^\s*pie/)) {
|
2019-09-12 21:58:57 +02:00
|
|
|
return 'pie';
|
2019-09-11 21:20:28 +02:00
|
|
|
}
|
2019-06-15 14:29:26 +02:00
|
|
|
|
2019-09-12 21:58:57 +02:00
|
|
|
return 'flowchart';
|
|
|
|
};
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-01-07 18:53:49 +01:00
|
|
|
/**
|
|
|
|
* @function isSubstringInArray
|
|
|
|
* Detects whether a substring in present in a given array
|
|
|
|
* @param {string} str The substring to detect
|
|
|
|
* @param {array} arr The array to search
|
|
|
|
* @returns {number} the array index containing the substring or -1 if not present
|
|
|
|
**/
|
2019-09-12 21:58:57 +02:00
|
|
|
export const isSubstringInArray = function(str, arr) {
|
2017-09-09 08:46:58 +02:00
|
|
|
for (let i = 0; i < arr.length; i++) {
|
2019-09-12 21:58:57 +02:00
|
|
|
if (arr[i].match(str)) return i;
|
2017-01-07 18:53:49 +01:00
|
|
|
}
|
2019-09-12 21:58:57 +02:00
|
|
|
return -1;
|
|
|
|
};
|
2017-09-10 13:41:34 +02:00
|
|
|
|
2018-03-09 06:33:35 +01:00
|
|
|
export const interpolateToCurve = (interpolate, defaultCurve) => {
|
2018-03-18 02:35:28 +01:00
|
|
|
if (!interpolate) {
|
2019-09-12 21:58:57 +02:00
|
|
|
return defaultCurve;
|
2018-03-18 02:35:28 +01:00
|
|
|
}
|
2019-09-12 21:58:57 +02:00
|
|
|
const curveName = `curve${interpolate.charAt(0).toUpperCase() + interpolate.slice(1)}`;
|
|
|
|
return d3[curveName] || defaultCurve;
|
|
|
|
};
|
2018-03-09 06:33:35 +01:00
|
|
|
|
2019-09-28 13:31:10 +02:00
|
|
|
const distance = (p1, p2) =>
|
|
|
|
p1 && p2 ? Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)) : 0;
|
|
|
|
|
|
|
|
const traverseEdge = points => {
|
|
|
|
let prevPoint;
|
|
|
|
let totalDistance = 0;
|
|
|
|
|
|
|
|
points.forEach(point => {
|
|
|
|
totalDistance += distance(point, prevPoint);
|
|
|
|
prevPoint = point;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Traverse half of total distance along points
|
|
|
|
const distanceToLabel = totalDistance / 2;
|
|
|
|
|
|
|
|
let remainingDistance = distanceToLabel;
|
|
|
|
let center;
|
|
|
|
prevPoint = undefined;
|
|
|
|
points.forEach(point => {
|
|
|
|
if (prevPoint && !center) {
|
|
|
|
const vectorDistance = distance(point, prevPoint);
|
|
|
|
if (vectorDistance < remainingDistance) {
|
|
|
|
remainingDistance -= vectorDistance;
|
|
|
|
} else {
|
|
|
|
// The point is remainingDistance from prevPoint in the vector between prevPoint and point
|
|
|
|
// Calculate the coordinates
|
|
|
|
const distanceRatio = remainingDistance / vectorDistance;
|
|
|
|
if (distanceRatio <= 0) center = prevPoint;
|
|
|
|
if (distanceRatio >= 1) center = { x: point.x, y: point.y };
|
|
|
|
if (distanceRatio > 0 && distanceRatio < 1) {
|
|
|
|
center = {
|
|
|
|
x: (1 - distanceRatio) * prevPoint.x + distanceRatio * point.x,
|
|
|
|
y: (1 - distanceRatio) * prevPoint.y + distanceRatio * point.y
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
prevPoint = point;
|
|
|
|
});
|
|
|
|
return center;
|
|
|
|
};
|
|
|
|
|
|
|
|
const calcLabelPosition = points => {
|
|
|
|
const p = traverseEdge(points);
|
|
|
|
return p;
|
|
|
|
};
|
|
|
|
|
2017-09-10 13:41:34 +02:00
|
|
|
export default {
|
|
|
|
detectType,
|
2018-03-09 06:33:35 +01:00
|
|
|
isSubstringInArray,
|
2019-09-28 13:31:10 +02:00
|
|
|
interpolateToCurve,
|
|
|
|
calcLabelPosition
|
2019-09-12 21:58:57 +02:00
|
|
|
};
|