mermaid
Version:
Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.
1,416 lines (1,295 loc) • 431 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 21);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/**
* #logger
* logger = require('logger').create()
* logger.info("blah")
* => [2011-3-3T20:24:4.810 info (5021)] blah
* logger.debug("boom")
* =>
* logger.level = Logger.levels.debug
* logger.debug(function() { return "booom" })
* => [2011-3-3T20:24:4.810 error (5021)] booom
*/
function formatTime(timestamp) {
var hh = timestamp.getUTCHours();
var mm = timestamp.getUTCMinutes();
var ss = timestamp.getSeconds();
var ms = timestamp.getMilliseconds();
// If you were building a timestamp instead of a duration, you would uncomment the following line to get 12-hour (not 24) time
// if (hh > 12) {hh = hh % 12;}
// These lines ensure you have two-digits
if (hh < 10) {
hh = '0' + hh;
}
if (mm < 10) {
mm = '0' + mm;
}
if (ss < 10) {
ss = '0' + ss;
}
if (ms < 100) {
ms = '0' + ms;
}
if (ms < 10) {
ms = '00' + ms;
}
// This formats your string to HH:MM:SS
var t = hh + ':' + mm + ':' + ss + ' (' + ms + ')';
return t;
}
function format(level) {
var time = formatTime(new Date());
return '%c ' + time + ' :%c' + level + ': ';
}
var debug = function debug() {};
var info = function info() {};
var warn = function warn() {};
var error = function error() {};
var fatal = function fatal() {};
/**
* logLevel , decides the amount of logging to be used.
* * debug: 1
* * info: 2
* * warn: 3
* * error: 4
* * fatal: 5
*/
exports.setLogLevel = function (level) {
if (level < 6) {
exports.Log.fatal = console.log.bind(console, format('FATAL'), 'color:grey;', 'color: red;');
}
if (level < 5) {
exports.Log.error = console.log.bind(console, format('ERROR'), 'color:grey;', 'color: red;');
}
if (level < 4) {
exports.Log.warn = console.log.bind(console, format('WARN'), 'color:grey;', 'color: orange;');
}
if (level < 3) {
exports.Log.info = console.log.bind(console, format('INFO'), 'color:grey;', 'color: info;');
}
if (level < 2) {
exports.Log.debug = console.log.bind(console, format('DEBUG'), 'color:grey;', 'color: green;');
}
};
exports.Log = {
debug: debug,
info: info,
warn: warn,
error: error,
fatal: fatal
};
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var d3 = __webpack_require__(22);
module.exports = d3;
/*
D3 Text Wrap
By Vijith Assar
http://www.vijithassar.com
http://www.github.com/vijithassar
@vijithassar
Detailed instructions at http://www.github.com/vijithassar/d3textwrap
*/
(function () {
// set this variable to a string value to always force a particular
// wrap method for development purposes, for example to check tspan
// rendering using a foreignobject-enabled browser. set to 'tspan' to
// use tspans and 'foreignobject' to use foreignobject
var forceWrapMethod = false; // by default no wrap method is forced
forceWrapMethod = 'tspans'; // uncomment this statement to force tspans
// force_wrap_method = 'foreignobjects'; // uncomment this statement to force foreignobjects
// exit immediately if something in this location
// has already been defined; the plugin will defer to whatever
// else you're doing in your code
if (d3.selection.prototype.textwrap) {
return false;
}
// double check the force_wrap_method flag
// and reset if someone screwed up the above
// settings
if (typeof forceWrapMethod === 'undefined') {
forceWrapMethod = false;
}
// create the plugin method twice, both for regular use
// and again for use inside the enter() selection
d3.selection.prototype.textwrap = d3.selection.enter.prototype.textwrap = function (bounds, padding) {
// default value of padding is zero if it's undefined
padding = parseInt(padding) || 0;
// save callee into a variable so we can continue to refer to it
// as the function scope changes
var selection = this;
// create a variable to store desired return values in
var returnValue;
// extract wrap boundaries from any d3-selected rect and return them
// in a format that matches the simpler object argument option
var extractBounds = function extractBounds(bounds) {
// discard the nested array wrappers added by d3
var boundingRect = bounds[0][0];
// sanitize the svg element name so we can test against it
var elementType = boundingRect.tagName.toString();
// if it's not a rect, exit
if (elementType !== 'rect') {
return false;
// if it's a rect, proceed to extracting the position attributes
} else {
var boundsExtracted = {};
boundsExtracted.x = d3.select(boundingRect).attr('x') || 0;
boundsExtracted.y = d3.select(boundingRect).attr('y') || 0;
boundsExtracted.width = d3.select(boundingRect).attr('width') || 0;
boundsExtracted.height = d3.select(boundingRect).attr('height') || 0;
// also pass along the getter function
boundsExtracted.attr = bounds.attr;
}
return boundsExtracted;
};
// double check the input argument for the wrapping
// boundaries to make sure it actually contains all
// the information we'll need in order to wrap successfully
var verifyBounds = function verifyBounds(bounds) {
// quickly add a simple getter method so you can use either
// bounds.x or bounds.attr('x') as your notation,
// the latter being a common convention among D3
// developers
if (!bounds.attr) {
bounds.attr = function (property) {
if (this[property]) {
return this[property];
}
};
}
// if it's an associative array, make sure it has all the
// necessary properties represented directly
if ((typeof bounds === 'undefined' ? 'undefined' : _typeof(bounds)) === 'object' && typeof bounds.x !== 'undefined' && typeof bounds.y !== 'undefined' && typeof bounds.width !== 'undefined' && typeof bounds.height !== 'undefined'
// if that's the case, then the bounds are fine
) {
// return the lightly modified bounds
return bounds;
// if it's a numerically indexed array, assume it's a
// d3-selected rect and try to extract the positions
} else if (
// first try to make sure it's an array using Array.isArray
typeof Array.isArray === 'function' && Array.isArray(bounds) ||
// but since Array.isArray isn't always supported, fall
// back to casting to the object to string when it's not
Object.prototype.toString.call(bounds) === '[object Array]') {
// once you're sure it's an array, extract the boundaries
// from the rect
var extractedBounds = extractBounds(bounds);
return extractedBounds;
} else {
// but if the bounds are neither an object nor a numerical
// array, then the bounds argument is invalid and you'll
// need to fix it
return false;
}
};
var applyPadding = function applyPadding(bounds, padding) {
var paddedBounds = bounds;
if (padding !== 0) {
paddedBounds.x = parseInt(paddedBounds.x) + padding;
paddedBounds.y = parseInt(paddedBounds.y) + padding;
paddedBounds.width -= padding * 2;
paddedBounds.height -= padding * 2;
}
return paddedBounds;
};
// verify bounds
var verifiedBounds = verifyBounds(bounds);
// modify bounds if a padding value is provided
if (padding) {
verifiedBounds = applyPadding(verifiedBounds, padding);
}
// check that we have the necessary conditions for this function to operate properly
if (
// selection it's operating on cannot be not empty
selection.length === 0 ||
// d3 must be available
!d3 ||
// desired wrapping bounds must be provided as an input argument
!bounds ||
// input bounds must validate
!verifiedBounds) {
// try to return the calling selection if possible
// so as not to interfere with methods downstream in the
// chain
if (selection) {
return selection;
// if all else fails, just return false. if you hit this point then you're
// almost certainly trying to call the textwrap() method on something that
// doesn't make sense!
} else {
return false;
}
// if we've validated everything then we can finally proceed
// to the meat of this operation
} else {
// reassign the verified bounds as the set we want
// to work with from here on; this ensures that we're
// using the same data structure for our bounds regardless
// of whether the input argument was a simple object or
// a d3 selection
bounds = verifiedBounds;
// wrap using html and foreignObjects if they are supported
var wrapWithForeignobjects = function wrapWithForeignobjects(item) {
// establish variables to quickly reference target nodes later
var parent = d3.select(item[0].parentNode);
var textNode = parent.select('text');
var styledLineHeight = textNode.style('line-height');
// extract our desired content from the single text element
var textToWrap = textNode.text();
// remove the text node and replace with a foreign object
textNode.remove();
var foreignObject = parent.append('foreignObject');
// add foreign object and set dimensions, position, etc
foreignObject.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility').attr('x', bounds.x).attr('y', bounds.y).attr('width', bounds.width).attr('height', bounds.height);
// insert an HTML div
var wrapDiv = foreignObject.append('xhtml:div')
// this class is currently hardcoded
// probably not necessary but easy to
// override using .classed() and for now
// it's nice to avoid a litany of input
// arguments
.attr('class', 'wrapped');
// set div to same dimensions as foreign object
wrapDiv.style('height', bounds.height).style('width', bounds.width)
// insert text content
.html(textToWrap);
if (styledLineHeight) {
wrapDiv.style('line-height', styledLineHeight);
}
returnValue = parent.select('foreignObject');
};
// wrap with tspans if foreignObject is undefined
var wrapWithTspans = function wrapWithTspans(item) {
// operate on the first text item in the selection
var textNode = item[0];
var parent = textNode.parentNode;
var textNodeSelected = d3.select(textNode);
// measure initial size of the text node as rendered
var textNodeHeight = textNode.getBBox().height;
var textNodeWidth = textNode.getBBox().width;
// figure out the line height, either from rendered height
// of the font or attached styling
var lineHeight;
var renderedLineHeight = textNodeHeight;
var styledLineHeight = textNodeSelected.style('line-height');
if (styledLineHeight && parseInt(styledLineHeight)) {
lineHeight = parseInt(styledLineHeight.replace('px', ''));
} else {
lineHeight = renderedLineHeight;
}
// only fire the rest of this if the text content
// overflows the desired dimensions
if (textNodeWidth > bounds.width) {
// store whatever is inside the text node
// in a variable and then zero out the
// initial content; we'll reinsert in a moment
// using tspan elements.
var textToWrap = textNodeSelected.text();
textNodeSelected.text('');
if (textToWrap) {
// keep track of whether we are splitting by spaces
// so we know whether to reinsert those spaces later
var breakDelimiter;
// split at spaces to create an array of individual words
var textToWrapArray;
if (textToWrap.indexOf(' ') !== -1) {
breakDelimiter = ' ';
textToWrapArray = textToWrap.split(' ');
} else {
// if there are no spaces, figure out the split
// points by comparing rendered text width against
// bounds and translating that into character position
// cuts
breakDelimiter = '';
var stringLength = textToWrap.length;
var numberOfSubstrings = Math.ceil(textNodeWidth / bounds.width);
var spliceInterval = Math.floor(stringLength / numberOfSubstrings);
if (!(spliceInterval * numberOfSubstrings >= stringLength)) {
numberOfSubstrings++;
}
textToWrapArray = [];
var substring;
var startPosition;
for (var i = 0; i < numberOfSubstrings; i++) {
startPosition = i * spliceInterval;
substring = textToWrap.substr(startPosition, spliceInterval);
textToWrapArray.push(substring);
}
}
// new array where we'll store the words re-assembled into
// substrings that have been tested against the desired
// maximum wrapping width
var substrings = [];
// computed text length is arguably incorrectly reported for
// all tspans after the first one, in that they will include
// the width of previous separate tspans. to compensate we need
// to manually track the computed text length of all those
// previous tspans and substrings, and then use that to offset
// the miscalculation. this then gives us the actual correct
// position we want to use in rendering the text in the SVG.
var totalOffset = 0;
// object for storing the results of text length computations later
var temp = {};
// loop through the words and test the computed text length
// of the string against the maximum desired wrapping width
for (i = 0; i < textToWrapArray.length; i++) {
var word = textToWrapArray[i];
var previousString = textNodeSelected.text();
var previousWidth = textNode.getComputedTextLength();
// initialize the current word as the first word
// or append to the previous string if one exists
var newstring;
if (previousString) {
newstring = previousString + breakDelimiter + word;
} else {
newstring = word;
}
// add the newest substring back to the text node and
// measure the length
textNodeSelected.text(newstring);
var newWidth = textNode.getComputedTextLength();
// adjust the length by the offset we've tracked
// due to the misreported length discussed above
// if our latest version of the string is too
// big for the bounds, use the previous
// version of the string (without the newest word
// added) and use the latest word to restart the
// process with a new tspan
if (newWidth > bounds.width) {
if (previousString && previousString !== '') {
totalOffset = totalOffset + previousWidth;
temp = { string: previousString, width: previousWidth, offset: totalOffset };
substrings.push(temp);
textNodeSelected.text('');
textNodeSelected.text(word);
// Handle case where there is just one more word to be wrapped
if (i === textToWrapArray.length - 1) {
newstring = word;
textNodeSelected.text(newstring);
newWidth = textNode.getComputedTextLength();
}
}
}
// if we're up to the last word in the array,
// get the computed length as is without
// appending anything further to it
if (i === textToWrapArray.length - 1) {
textNodeSelected.text('');
var finalString = newstring;
if (finalString && finalString !== '') {
if (newWidth - totalOffset > 0) {
newWidth = newWidth - totalOffset;
}
temp = { string: finalString, width: newWidth, offset: totalOffset };
substrings.push(temp);
}
}
}
// append each substring as a tspan
var currentTspan;
// var tspanCount
// double check that the text content has been removed
// before we start appending tspans
textNodeSelected.text('');
for (i = 0; i < substrings.length; i++) {
substring = substrings[i].string;
// only append if we're sure it won't make the tspans
// overflow the bounds.
if (i * lineHeight < bounds.height - lineHeight * 1.5) {
currentTspan = textNodeSelected.append('tspan').text(substring);
// vertical shift to all tspans after the first one
currentTspan.attr('dy', function (d) {
if (i > 0) {
return lineHeight;
}
});
// shift left from default position, which
// is probably based on the full length of the
// text string until we make this adjustment
currentTspan.attr('x', function () {
var xOffset = bounds.x;
if (padding) {
xOffset += padding;
}
return xOffset;
});
}
}
}
}
// position the overall text node, whether wrapped or not
textNodeSelected.attr('y', function () {
var yOffset = bounds.y;
// shift by line-height to move the baseline into
// the bounds – otherwise the text baseline would be
// at the top of the bounds
if (lineHeight) {
yOffset += lineHeight;
}
// shift by padding, if it's there
if (padding) {
yOffset += padding;
}
return yOffset;
});
// shift to the right by the padding value
textNodeSelected.attr('x', function () {
var xOffset = bounds.x;
if (padding) {
xOffset += padding;
}
return xOffset;
});
// assign our modified text node with tspans
// to the return value
returnValue = d3.select(parent).selectAll('text');
};
// variable used to hold the functions that let us
// switch between the wrap methods
var wrapMethod;
// if a wrap method if being forced, assign that
// function
if (forceWrapMethod) {
if (forceWrapMethod === 'foreignobjects') {
wrapMethod = wrapWithForeignobjects;
} else if (forceWrapMethod === 'tspans') {
wrapMethod = wrapWithTspans;
}
}
// if no wrap method is being forced, then instead
// test for browser support of foreignobject and
// use whichever wrap method makes sense accordingly
if (!forceWrapMethod) {
if (typeof SVGForeignObjectElement !== 'undefined') {
wrapMethod = wrapWithForeignobjects;
} else {
wrapMethod = wrapWithTspans;
}
}
// run the desired wrap function for each item
// in the d3 selection that called .textwrap()
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
wrapMethod(item);
}
// return the modified nodes so we can chain other
// methods to them.
return returnValue;
}
};
})();
/***/ }),
/* 2 */
/***/ (function(module, exports) {
module.exports = function(module) {
if(!module.webpackPolyfill) {
module.deprecate = function() {};
module.paths = [];
// module.parent = undefined by default
if(!module.children) module.children = [];
Object.defineProperty(module, "loaded", {
enumerable: true,
get: function() {
return module.l;
}
});
Object.defineProperty(module, "id", {
enumerable: true,
get: function() {
return module.i;
}
});
module.webpackPolyfill = 1;
}
return module;
};
/***/ }),
/* 3 */
/***/ (function(module, exports) {
module.exports = require("fs");
/***/ }),
/* 4 */
/***/ (function(module, exports) {
module.exports = require("path");
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/**
* Created by knut on 14-11-03.
*/
var Logger = __webpack_require__(0);
var log = Logger.Log;
var utils = __webpack_require__(6);
var d3 = __webpack_require__(1);
var vertices = {};
var edges = [];
var classes = [];
var subGraphs = [];
var tooltips = {};
var subCount = 0;
var direction;
// Functions to be run after graph rendering
var funs = [];
/**
* Function called by parser when a node definition has been found
* @param id
* @param text
* @param type
* @param style
*/
exports.addVertex = function (id, text, type, style) {
var txt;
if (typeof id === 'undefined') {
return;
}
if (id.trim().length === 0) {
return;
}
if (typeof vertices[id] === 'undefined') {
vertices[id] = { id: id, styles: [], classes: [] };
}
if (typeof text !== 'undefined') {
txt = text.trim();
// strip quotes if string starts and exnds with a quote
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
txt = txt.substring(1, txt.length - 1);
}
vertices[id].text = txt;
}
if (typeof type !== 'undefined') {
vertices[id].type = type;
}
if (typeof type !== 'undefined') {
vertices[id].type = type;
}
if (typeof style !== 'undefined') {
if (style !== null) {
style.forEach(function (s) {
vertices[id].styles.push(s);
});
}
}
};
/**
* Function called by parser when a link/edge definition has been found
* @param start
* @param end
* @param type
* @param linktext
*/
exports.addLink = function (start, end, type, linktext) {
log.info('Got edge...', start, end);
var edge = { start: start, end: end, type: undefined, text: '' };
linktext = type.text;
if (typeof linktext !== 'undefined') {
edge.text = linktext.trim();
// strip quotes if string starts and exnds with a quote
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
edge.text = edge.text.substring(1, edge.text.length - 1);
}
}
if (typeof type !== 'undefined') {
edge.type = type.type;
edge.stroke = type.stroke;
}
edges.push(edge);
};
/**
* Updates a link's line interpolation algorithm
* @param pos
* @param interpolate
*/
exports.updateLinkInterpolate = function (pos, interp) {
if (pos === 'default') {
edges.defaultInterpolate = interp;
} else {
edges[pos].interpolate = interp;
}
};
/**
* Updates a link with a style
* @param pos
* @param style
*/
exports.updateLink = function (pos, style) {
if (pos === 'default') {
edges.defaultStyle = style;
} else {
if (utils.isSubstringInArray('fill', style) === -1) {
style.push('fill:none');
}
edges[pos].style = style;
}
};
exports.addClass = function (id, style) {
if (typeof classes[id] === 'undefined') {
classes[id] = { id: id, styles: [] };
}
if (typeof style !== 'undefined') {
if (style !== null) {
style.forEach(function (s) {
classes[id].styles.push(s);
});
}
}
};
/**
* Called by parser when a graph definition is found, stores the direction of the chart.
* @param dir
*/
exports.setDirection = function (dir) {
direction = dir;
};
/**
* Called by parser when a graph definition is found, stores the direction of the chart.
* @param dir
*/
exports.setClass = function (id, className) {
if (id.indexOf(',') > 0) {
id.split(',').forEach(function (id2) {
if (typeof vertices[id2] !== 'undefined') {
vertices[id2].classes.push(className);
}
});
} else {
if (typeof vertices[id] !== 'undefined') {
vertices[id].classes.push(className);
}
}
};
var setTooltip = function setTooltip(id, tooltip) {
if (typeof tooltip !== 'undefined') {
tooltips[id] = tooltip;
}
};
var setClickFun = function setClickFun(id, functionName) {
if (typeof functionName === 'undefined') {
return;
}
if (typeof vertices[id] !== 'undefined') {
funs.push(function (element) {
var elem = d3.select(element).select('#' + id);
if (elem !== null) {
elem.on('click', function () {
window[functionName](id);
});
}
});
}
};
var setLink = function setLink(id, linkStr) {
if (typeof linkStr === 'undefined') {
return;
}
if (typeof vertices[id] !== 'undefined') {
funs.push(function (element) {
var elem = d3.select(element).select('#' + id);
if (elem !== null) {
elem.on('click', function () {
window.open(linkStr, 'newTab');
});
}
});
}
};
exports.getTooltip = function (id) {
return tooltips[id];
};
/**
* Called by parser when a graph definition is found, stores the direction of the chart.
* @param dir
*/
exports.setClickEvent = function (id, functionName, link, tooltip) {
if (id.indexOf(',') > 0) {
id.split(',').forEach(function (id2) {
setTooltip(id2, tooltip);
setClickFun(id2, functionName);
setLink(id2, link);
});
} else {
setTooltip(id, tooltip);
setClickFun(id, functionName);
setLink(id, link);
}
};
exports.bindFunctions = function (element) {
funs.forEach(function (fun) {
fun(element);
});
};
exports.getDirection = function () {
return direction;
};
/**
* Retrieval function for fetching the found nodes after parsing has completed.
* @returns {{}|*|vertices}
*/
exports.getVertices = function () {
return vertices;
};
/**
* Retrieval function for fetching the found links after parsing has completed.
* @returns {{}|*|edges}
*/
exports.getEdges = function () {
return edges;
};
/**
* Retrieval function for fetching the found class definitions after parsing has completed.
* @returns {{}|*|classes}
*/
exports.getClasses = function () {
return classes;
};
var setupToolTips = function setupToolTips(element) {
var tooltipElem = d3.select('.mermaidTooltip');
if (tooltipElem[0][0] === null) {
tooltipElem = d3.select('body').append('div').attr('class', 'mermaidTooltip').style('opacity', 0);
}
var svg = d3.select(element).select('svg');
var nodes = svg.selectAll('g.node');
nodes.on('mouseover', function () {
var el = d3.select(this);
var title = el.attr('title');
// Dont try to draw a tooltip if no data is provided
if (title === null) {
return;
}
var rect = this.getBoundingClientRect();
tooltipElem.transition().duration(200).style('opacity', '.9');
tooltipElem.html(el.attr('title')).style('left', rect.left + (rect.right - rect.left) / 2 + 'px').style('top', rect.top - 14 + document.body.scrollTop + 'px');
el.classed('hover', true);
}).on('mouseout', function () {
tooltipElem.transition().duration(500).style('opacity', 0);
var el = d3.select(this);
el.classed('hover', false);
});
};
funs.push(setupToolTips);
/**
* Clears the internal graph db so that a new graph can be parsed.
*/
exports.clear = function () {
vertices = {};
classes = {};
edges = [];
funs = [];
funs.push(setupToolTips);
subGraphs = [];
subCount = 0;
tooltips = [];
};
/**
*
* @returns {string}
*/
exports.defaultStyle = function () {
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;';
};
/**
* Clears the internal graph db so that a new graph can be parsed.
*/
exports.addSubGraph = function (list, title) {
function uniq(a) {
var prims = { 'boolean': {}, 'number': {}, 'string': {} };
var objs = [];
return a.filter(function (item) {
var type = typeof item === 'undefined' ? 'undefined' : _typeof(item);
if (item === ' ') {
return false;
}
if (type in prims) {
return prims[type].hasOwnProperty(item) ? false : prims[type][item] = true;
} else {
return objs.indexOf(item) >= 0 ? false : objs.push(item);
}
});
}
var nodeList = [];
nodeList = uniq(nodeList.concat.apply(nodeList, list));
var subGraph = { id: 'subGraph' + subCount, nodes: nodeList, title: title };
subGraphs.push(subGraph);
subCount = subCount + 1;
return subGraph.id;
};
var getPosForId = function getPosForId(id) {
var i;
for (i = 0; i < subGraphs.length; i++) {
if (subGraphs[i].id === id) {
return i;
}
}
return -1;
};
var secCount = -1;
var posCrossRef = [];
var indexNodes = function indexNodes(id, pos) {
var nodes = subGraphs[pos].nodes;
secCount = secCount + 1;
if (secCount > 2000) {
return;
}
posCrossRef[secCount] = pos;
// Check if match
if (subGraphs[pos].id === id) {
return {
result: true,
count: 0
};
}
var count = 0;
var posCount = 1;
while (count < nodes.length) {
var childPos = getPosForId(nodes[count]);
// Ignore regular nodes (pos will be -1)
if (childPos >= 0) {
var res = indexNodes(id, childPos);
if (res.result) {
return {
result: true,
count: posCount + res.count
};
} else {
posCount = posCount + res.count;
}
}
count = count + 1;
}
return {
result: false,
count: posCount
};
};
exports.getDepthFirstPos = function (pos) {
return posCrossRef[pos];
};
exports.indexNodes = function () {
secCount = -1;
if (subGraphs.length > 0) {
indexNodes('none', subGraphs.length - 1, 0);
}
};
exports.getSubGraphs = function () {
return subGraphs;
};
exports.parseError = function (err, hash) {
global.mermaidAPI.parseError(err, hash);
};
/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/**
* Created by knut on 14-11-23.
*/
var Logger = __webpack_require__(0);
var log = Logger.Log;
/**
* @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
*/
var detectType = function detectType(text) {
text = text.replace(/^\s*%%.*\n/g, '\n');
if (text.match(/^\s*sequenceDiagram/)) {
return 'sequenceDiagram';
}
if (text.match(/^\s*digraph/)) {
return 'dotGraph';
}
if (text.match(/^\s*info/)) {
return 'info';
}
if (text.match(/^\s*gantt/)) {
return 'gantt';
}
if (text.match(/^\s*classDiagram/)) {
log.debug('Detected classDiagram syntax');
return 'classDiagram';
}
if (text.match(/^\s*gitGraph/)) {
log.debug('Detected gitGraph syntax');
return 'gitGraph';
}
return 'graph';
};
exports.detectType = detectType;
/**
* Copies all relevant CSS content into the graph SVG.
* This allows the SVG to be copied as is while keeping class based styling
* @param {element} svg The root element of the SVG
* @param {object} Hash table of class definitions from the graph definition
*/
var cloneCssStyles = function cloneCssStyles(svg, classes) {
var usedStyles = '';
var sheets = document.styleSheets;
var rule;
for (var i = 0; i < sheets.length; i++) {
// Avoid multiple inclusion on pages with multiple graphs
if (sheets[i].title !== 'mermaid-svg-internal-css') {
try {
var rules = sheets[i].cssRules;
if (rules !== null) {
for (var j = 0; j < rules.length; j++) {
rule = rules[j];
if (typeof rule.style !== 'undefined') {
var elems;
elems = svg.querySelectorAll(rule.selectorText);
if (elems.length > 0) {
usedStyles += rule.selectorText + ' { ' + rule.style.cssText + '}\n';
}
}
}
}
} catch (err) {
if (typeof rule !== 'undefined') {
log.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
}
}
}
}
var defaultStyles = '';
var embeddedStyles = '';
for (var className in classes) {
if (classes.hasOwnProperty(className) && typeof className !== 'undefined') {
if (className === 'default') {
if (classes.default.styles instanceof Array) {
defaultStyles += '#' + svg.id.trim() + ' .node' + '>rect { ' + classes[className].styles.join('; ') + '; }\n';
}
if (classes.default.nodeLabelStyles instanceof Array) {
defaultStyles += '#' + svg.id.trim() + ' .node text ' + ' { ' + classes[className].nodeLabelStyles.join('; ') + '; }\n';
}
if (classes.default.edgeLabelStyles instanceof Array) {
defaultStyles += '#' + svg.id.trim() + ' .edgeLabel text ' + ' { ' + classes[className].edgeLabelStyles.join('; ') + '; }\n';
}
if (classes.default.clusterStyles instanceof Array) {
defaultStyles += '#' + svg.id.trim() + ' .cluster rect ' + ' { ' + classes[className].clusterStyles.join('; ') + '; }\n';
}
} else {
if (classes[className].styles instanceof Array) {
embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect, .' + className + '>polygon, .' + className + '>circle, .' + className + '>ellipse { ' + classes[className].styles.join('; ') + '; }\n';
}
}
}
}
if (usedStyles !== '' || defaultStyles !== '' || embeddedStyles !== '') {
var s = document.createElement('style');
s.setAttribute('type', 'text/css');
s.setAttribute('title', 'mermaid-svg-internal-css');
s.innerHTML = '/* <![CDATA[ */\n';
// Make this CSS local to this SVG
if (defaultStyles !== '') {
s.innerHTML += defaultStyles;
}
if (usedStyles !== '') {
s.innerHTML += usedStyles;
}
if (embeddedStyles !== '') {
s.innerHTML += embeddedStyles;
}
s.innerHTML += '/* ]]> */\n';
svg.insertBefore(s, svg.firstChild);
}
};
exports.cloneCssStyles = cloneCssStyles;
/**
* @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
**/
var isSubstringInArray = function isSubstringInArray(str, arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].match(str)) return i;
}
return -1;
};
exports.isSubstringInArray = isSubstringInArray;
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(module) {
/* parser generated by jison 0.4.17 */
/*
Returns a Parser object of the following structure:
Parser: {
yy: {}
}
Parser.prototype: {
yy: {},
trace: function(),
symbols_: {associative list: name ==> number},
terminals_: {associative list: number ==> name},
productions_: [...],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
table: [...],
defaultActions: {...},
parseError: function(str, hash),
parse: function(input),
lexer: {
EOF: 1,
parseError: function(str, hash),
setInput: function(input),
input: function(),
unput: function(str),
more: function(),
less: function(n),
pastInput: function(),
upcomingInput: function(),
showPosition: function(),
test_match: function(regex_match_array, rule_index),
next: function(),
lex: function(),
begin: function(condition),
popState: function(),
_currentRules: function(),
topState: function(),
pushState: function(condition),
options: {
ranges: boolean (optional: true ==> token location info will include a .range[] member)
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
},
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
rules: [...],
conditions: {associative list: name ==> set},
}
}
token location info (@$, _$, etc.): {
first_line: n,
last_line: n,
first_column: n,
last_column: n,
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
}
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
text: (matched text)
token: (the produced terminal token, if any)
line: (yylineno)
}
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
loc: (yylloc)
expected: (string describing the set of expected tokens)
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
}
*/
var parser = function () {
var o = function o(k, v, _o, l) {
for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v) {}return _o;
},
$V0 = [1, 4],
$V1 = [1, 3],
$V2 = [1, 5],
$V3 = [1, 8, 9, 10, 11, 13, 18, 30, 46, 71, 72, 73, 74, 75, 81, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$V4 = [2, 2],
$V5 = [1, 12],
$V6 = [1, 13],
$V7 = [1, 14],
$V8 = [1, 15],
$V9 = [1, 31],
$Va = [1, 33],
$Vb = [1, 22],
$Vc = [1, 34],
$Vd = [1, 24],
$Ve = [1, 25],
$Vf = [1, 26],
$Vg = [1, 27],
$Vh = [1, 28],
$Vi = [1, 38],
$Vj = [1, 40],
$Vk = [1, 35],
$Vl = [1, 39],
$Vm = [1, 45],
$Vn = [1, 44],
$Vo = [1, 36],
$Vp = [1, 37],
$Vq = [1, 41],
$Vr = [1, 42],
$Vs = [1, 43],
$Vt = [1, 8, 9, 10, 11, 13, 18, 30, 32, 46, 71, 72, 73, 74, 75, 81, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$Vu = [1, 53],
$Vv = [1, 52],
$Vw = [1, 54],
$Vx = [1, 72],
$Vy = [1, 80],
$Vz = [1, 81],
$VA = [1, 66],
$VB = [1, 65],
$VC = [1, 85],
$VD = [1, 84],
$VE = [1, 82],
$VF = [1, 83],
$VG = [1, 73],
$VH = [1, 68],
$VI = [1, 67],
$VJ = [1, 63],
$VK = [1, 75],
$VL = [1, 76],
$VM = [1, 77],
$VN = [1, 78],
$VO = [1, 79],
$VP = [1, 70],
$VQ = [1, 69],
$VR = [8, 9, 11],
$VS = [8, 9, 11, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64],
$VT = [1, 115],
$VU = [8, 9, 10, 11, 13, 15, 18, 36, 38, 40, 42, 46, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 81, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$VV = [8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 30, 32, 36, 37, 38, 39, 40, 41, 42, 43, 46, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 71, 72, 73, 74, 75, 78, 81, 84, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$VW = [1, 117],
$VX = [1, 118],
$VY = [8, 9, 10, 11, 13, 18, 30, 32, 46, 71, 72, 73, 74, 75, 81, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$VZ = [8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 30, 32, 37, 39, 41, 43, 46, 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 71, 72, 73, 74, 75, 78, 81, 84, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$V_ = [13, 18, 46, 81, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$V$ = [13, 18, 46, 49, 65, 81, 86, 88, 89, 91, 92, 94, 95, 96, 97, 98],
$V01 = [1, 191],
$V11 = [1, 188],
$V21 = [1, 195],
$V31 = [1, 192],
$V41 = [1, 189],
$V51 = [1, 196],
$V61 = [1, 186],
$V71 = [1, 187],
$V81 = [1, 190],
$V91 = [1, 193],
$Va1 = [1, 194],
$Vb1 = [1, 213],
$Vc1 = [8, 9, 11, 86],
$Vd1 = [8, 9, 10, 11, 46, 71, 80, 81, 84, 86, 88, 89, 90, 91, 92];
var parser = { trace: function trace() {},
yy: {},
symbols_: { "error": 2, "mermaidDoc": 3, "graphConfig": 4, "document": 5, "line": 6, "statement": 7, "SEMI": 8, "NEWLINE": 9, "SPACE": 10, "EOF": 11, "GRAPH": 12, "DIR": 13, "FirstStmtSeperator": 14, "TAGEND": 15, "TAGSTART": 16, "UP": 17, "DOWN": 18, "ending": 19, "endToken": 20, "spaceList": 21, "spaceListNewline": 22, "verticeStatement": 23, "separator": 24, "styleStatement": 25, "linkStyleStatement": 26, "classDefStatement": 27, "classStatement": 28, "clickStatement": 29, "subgraph": 30, "text": 31, "end": 32, "vertex": 33, "link": 34, "alphaNum": 35, "SQS": 36, "SQE": 37, "PS": 38, "PE": 39, "(-": 40, "-)": 41, "DIAMOND_START": 42, "DIAMOND_STOP": 43, "alphaNumStatement": 44, "alphaNumToken": 45, "MINUS": 46, "linkStatement": 47, "arrowText": 48, "TESTSTR": 49, "--": 50, "ARROW_POINT": 51, "ARROW_CIRCLE": 52, "ARROW_CROSS": 53, "ARROW_OPEN": 54, "-.": 55, "DOTTED_ARROW_POINT": 56, "DOTTED_ARROW_CIRCLE": 57, "DOTTED_ARROW_CROSS": 58, "DOTTED_ARROW_OPEN": 59, "==": 60, "THICK_ARROW_POINT": 61, "THICK_ARROW_CIRCLE": 62, "THICK_ARROW_CROSS": 63, "THICK_ARROW_OPEN": 64, "PIPE": 65, "textToken": 66, "STR": 67, "commentText": 68, "commentToken": 69, "keywords": 70, "STYLE": 71, "LINKSTYLE": 72, "CLASSDEF": 73, "CLASS": 74, "CLICK": 75, "textNoTags": 76, "textNoTagsToken": 77, "DEFAULT": 78, "stylesOpt": 79, "HEX": 80, "NUM": 81, "INTERPOLATE": 82, "commentStatement": 83, "PCT": 84, "style": 85, "COMMA": 86, "styleComponent": 87, "ALPHA": 88, "COLON": 89, "UNIT": 90, "BRKT": 91, "DOT": 92, "graphCodeTokens": 93, "PUNCTUATION": 94, "UNICODE_TEXT": 95, "PLUS": 96, "EQUALS": 97, "MULT": 98, "TAG_START": 99, "TAG_END": 100, "QUOTE": 101, "$accept": 0, "$end": 1 },
terminals_: { 2: "error", 8: "SEMI", 9: "NEWLINE", 10: "SPACE", 11: "EOF", 12: "GRAPH", 13: "DIR", 15: "TAGEND", 16: "TAGSTART", 17: "UP", 18: "DOWN", 30: "subgraph", 32: "end", 36: "SQS", 37: "SQE", 38: "PS", 39: "PE", 40: "(-", 41: "-)", 42: "DIAMOND_START", 43: "DIAMOND_STOP", 46: "MINUS", 49: "TESTSTR", 50: "--", 51: "ARROW_POINT", 52: "ARROW_CIRCLE", 53: "ARROW_CROSS", 54: "ARROW_OPEN", 55: "-.", 56: "DOTTED_ARROW_POINT", 57: "DOTTED_ARROW_CIRCLE", 58: "DOTTED_ARROW_CROSS", 59: "DOTTED_ARROW_OPEN", 60: "==", 61: "THICK_ARROW_POINT", 62: "THICK_ARROW_CIRCLE", 63: "THICK_ARROW_CROSS", 64: "THICK_ARROW_OPEN", 65: "PIPE", 67: "STR", 71: "STYLE", 72: "LINKSTYLE", 73: "CLASSDEF", 74: "CLASS", 75: "CLICK", 78: "DEFAULT", 80: "HEX", 81: "NUM", 82: "INTERPOLATE", 84: "PCT", 86: "COMMA", 88: "ALPHA", 89: "COLON", 90: "UNIT", 91: "BRKT", 92: "DOT", 94: "PUNCTUATION", 95: "UNICODE_TEXT", 96: "PLUS", 97: "EQUALS", 98: "MULT", 99: "TAG_START", 100: "TAG_END", 101: "QUOTE" },
productions_: [0, [3, 2], [5, 0], [5, 2], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [4, 2], [4, 2], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [19, 2], [19, 1], [20, 1], [20, 1], [20, 1], [14, 1], [14, 1], [14, 2], [22, 2], [22, 2], [22, 1], [22, 1], [21, 2], [21, 1], [7, 2], [7, 2], [7, 2], [7, 2], [7, 2], [7, 2], [7, 5], [7, 4], [24, 1], [24, 1], [24, 1], [23, 3], [23, 1], [33, 4], [33, 5], [33, 6], [33, 7], [33, 4], [33, 5], [33, 4], [33, 5], [33, 4], [33, 5], [33, 4], [33, 5], [33, 1], [33, 2], [35, 1], [35, 2], [44, 1], [44, 1], [44, 1], [44, 1], [34, 2], [34, 3], [34, 3], [34, 1], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [48, 3], [31, 1], [31, 2], [31, 1], [68, 1], [68, 2], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [76, 1], [76, 2], [27, 5], [27, 5], [28, 5], [29, 5], [29, 7], [29, 5], [29, 7], [25, 5], [25, 5], [26, 5], [26, 5], [26, 9], [26, 9], [26, 7], [26, 7], [83, 3], [79, 1], [79, 3], [85, 1], [85, 2], [87, 1], [87, 1], [87, 1], [87, 1], [87, 1], [87, 1], [87, 1], [87, 1], [87, 1], [87, 1], [87, 1], [69, 1], [69, 1], [66, 1], [66, 1], [66, 1], [66, 1], [66, 1], [66, 1], [66, 1], [77, 1], [77, 1], [77, 1], [77, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1], [93, 1]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
/* this == yyval */
var $0 = $$.length - 1;
switch (yystate) {
case 2:
this.$ = [];
break;
case 3:
if ($$[$0] !== []) {
$$[$0 - 1].push($$[$0]);
}
this.$ = $$[$0 - 1];
break;
case 4:case 57:case 59:case 60:case 92:case 94:case 95:case 108:
this.$ = $$[$0];
break;
case 11:
yy.setDirection($$[$0 - 1]);this.$ = $$[$0 - 1];
break;
case 12:
yy.setDirection("LR");this.$ = $$[$0 - 1];
break;
case 13:
yy.setDirection("RL");this.$ = $$[$0 - 1];
break;
case 14:
yy.setDirection("BT");this.$ = $$[$0 - 1];
break;
case 15:
yy.setDirection("TB");this.$ = $$[$0 - 1];
break;
case 30:
this.$ = $$[$0 - 1];
break;
case 31:case 32:case 33:case 34:case 35:
this.$ = [];
break;
case 36:
this.$ = yy.addSubGraph($$[$0 - 1], $$[$0 - 3]);
break;
case 37:
this.$ = yy.addSubGraph($$[$0 - 1], undefined);
break;
case 41: