mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-11-04 04:44:08 +01:00 
			
		
		
		
	#931 Aligning with code standard
This commit is contained in:
		@@ -1,33 +1,33 @@
 | 
			
		||||
import * as d3 from 'd3'
 | 
			
		||||
import { sanitizeUrl } from '@braintree/sanitize-url'
 | 
			
		||||
import { logger } from '../../logger'
 | 
			
		||||
import utils from '../../utils'
 | 
			
		||||
import { getConfig } from '../../config'
 | 
			
		||||
import * as d3 from 'd3';
 | 
			
		||||
import { sanitizeUrl } from '@braintree/sanitize-url';
 | 
			
		||||
import { logger } from '../../logger';
 | 
			
		||||
import utils from '../../utils';
 | 
			
		||||
import { getConfig } from '../../config';
 | 
			
		||||
 | 
			
		||||
const config = getConfig()
 | 
			
		||||
let vertices = {}
 | 
			
		||||
let edges = []
 | 
			
		||||
let classes = []
 | 
			
		||||
let subGraphs = []
 | 
			
		||||
let subGraphLookup = {}
 | 
			
		||||
let tooltips = {}
 | 
			
		||||
let subCount = 0
 | 
			
		||||
let direction
 | 
			
		||||
const config = getConfig();
 | 
			
		||||
let vertices = {};
 | 
			
		||||
let edges = [];
 | 
			
		||||
let classes = [];
 | 
			
		||||
let subGraphs = [];
 | 
			
		||||
let subGraphLookup = {};
 | 
			
		||||
let tooltips = {};
 | 
			
		||||
let subCount = 0;
 | 
			
		||||
let direction;
 | 
			
		||||
// Functions to be run after graph rendering
 | 
			
		||||
let funs = []
 | 
			
		||||
let funs = [];
 | 
			
		||||
 | 
			
		||||
const sanitize = text => {
 | 
			
		||||
  let txt = text
 | 
			
		||||
  let txt = text;
 | 
			
		||||
  if (config.securityLevel !== 'loose') {
 | 
			
		||||
    txt = txt.replace(/<br>/g, '#br#')
 | 
			
		||||
    txt = txt.replace(/<br\S*?\/>/g, '#br#')
 | 
			
		||||
    txt = txt.replace(/</g, '<').replace(/>/g, '>')
 | 
			
		||||
    txt = txt.replace(/=/g, '=')
 | 
			
		||||
    txt = txt.replace(/#br#/g, '<br/>')
 | 
			
		||||
    txt = txt.replace(/<br>/g, '#br#');
 | 
			
		||||
    txt = txt.replace(/<br\S*?\/>/g, '#br#');
 | 
			
		||||
    txt = txt.replace(/</g, '<').replace(/>/g, '>');
 | 
			
		||||
    txt = txt.replace(/=/g, '=');
 | 
			
		||||
    txt = txt.replace(/#br#/g, '<br/>');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return txt
 | 
			
		||||
}
 | 
			
		||||
  return txt;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Function called by parser when a node definition has been found
 | 
			
		||||
@@ -37,53 +37,53 @@ const sanitize = text => {
 | 
			
		||||
 * @param style
 | 
			
		||||
 * @param classes
 | 
			
		||||
 */
 | 
			
		||||
export const addVertex = function (_id, text, type, style, classes) {
 | 
			
		||||
  let txt
 | 
			
		||||
  let id = _id
 | 
			
		||||
export const addVertex = function(_id, text, type, style, classes) {
 | 
			
		||||
  let txt;
 | 
			
		||||
  let id = _id;
 | 
			
		||||
  if (typeof id === 'undefined') {
 | 
			
		||||
    return
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (id.trim().length === 0) {
 | 
			
		||||
    return
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (id[0].match(/\d/)) id = 's' + id
 | 
			
		||||
  if (id[0].match(/\d/)) id = 's' + id;
 | 
			
		||||
 | 
			
		||||
  if (typeof vertices[id] === 'undefined') {
 | 
			
		||||
    vertices[id] = { id: id, styles: [], classes: [] }
 | 
			
		||||
    vertices[id] = { id: id, styles: [], classes: [] };
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof text !== 'undefined') {
 | 
			
		||||
    txt = sanitize(text.trim())
 | 
			
		||||
    txt = sanitize(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)
 | 
			
		||||
      txt = txt.substring(1, txt.length - 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vertices[id].text = txt
 | 
			
		||||
    vertices[id].text = txt;
 | 
			
		||||
  } else {
 | 
			
		||||
    if (!vertices[id].text) {
 | 
			
		||||
      vertices[id].text = _id
 | 
			
		||||
      vertices[id].text = _id;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof type !== 'undefined') {
 | 
			
		||||
    vertices[id].type = type
 | 
			
		||||
    vertices[id].type = type;
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof style !== 'undefined') {
 | 
			
		||||
    if (style !== null) {
 | 
			
		||||
      style.forEach(function (s) {
 | 
			
		||||
        vertices[id].styles.push(s)
 | 
			
		||||
      })
 | 
			
		||||
      style.forEach(function(s) {
 | 
			
		||||
        vertices[id].styles.push(s);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof classes !== 'undefined') {
 | 
			
		||||
    if (classes !== null) {
 | 
			
		||||
      classes.forEach(function (s) {
 | 
			
		||||
        vertices[id].classes.push(s)
 | 
			
		||||
      })
 | 
			
		||||
      classes.forEach(function(s) {
 | 
			
		||||
        vertices[id].classes.push(s);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Function called by parser when a link/edge definition has been found
 | 
			
		||||
@@ -92,134 +92,138 @@ export const addVertex = function (_id, text, type, style, classes) {
 | 
			
		||||
 * @param type
 | 
			
		||||
 * @param linktext
 | 
			
		||||
 */
 | 
			
		||||
export const addLink = function (_start, _end, type, linktext) {
 | 
			
		||||
  let start = _start
 | 
			
		||||
  let end = _end
 | 
			
		||||
  if (start[0].match(/\d/)) start = 's' + start
 | 
			
		||||
  if (end[0].match(/\d/)) end = 's' + end
 | 
			
		||||
  logger.info('Got edge...', start, end)
 | 
			
		||||
export const addLink = function(_start, _end, type, linktext) {
 | 
			
		||||
  let start = _start;
 | 
			
		||||
  let end = _end;
 | 
			
		||||
  if (start[0].match(/\d/)) start = 's' + start;
 | 
			
		||||
  if (end[0].match(/\d/)) end = 's' + end;
 | 
			
		||||
  logger.info('Got edge...', start, end);
 | 
			
		||||
 | 
			
		||||
  const edge = { start: start, end: end, type: undefined, text: '' }
 | 
			
		||||
  linktext = type.text
 | 
			
		||||
  const edge = { start: start, end: end, type: undefined, text: '' };
 | 
			
		||||
  linktext = type.text;
 | 
			
		||||
 | 
			
		||||
  if (typeof linktext !== 'undefined') {
 | 
			
		||||
    edge.text = sanitize(linktext.trim())
 | 
			
		||||
    edge.text = sanitize(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)
 | 
			
		||||
      edge.text = edge.text.substring(1, edge.text.length - 1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (typeof type !== 'undefined') {
 | 
			
		||||
    edge.type = type.type
 | 
			
		||||
    edge.stroke = type.stroke
 | 
			
		||||
    edge.type = type.type;
 | 
			
		||||
    edge.stroke = type.stroke;
 | 
			
		||||
  }
 | 
			
		||||
  edges.push(edge)
 | 
			
		||||
}
 | 
			
		||||
  edges.push(edge);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Updates a link's line interpolation algorithm
 | 
			
		||||
 * @param pos
 | 
			
		||||
 * @param interpolate
 | 
			
		||||
 */
 | 
			
		||||
export const updateLinkInterpolate = function (positions, interp) {
 | 
			
		||||
  positions.forEach(function (pos) {
 | 
			
		||||
export const updateLinkInterpolate = function(positions, interp) {
 | 
			
		||||
  positions.forEach(function(pos) {
 | 
			
		||||
    if (pos === 'default') {
 | 
			
		||||
      edges.defaultInterpolate = interp
 | 
			
		||||
      edges.defaultInterpolate = interp;
 | 
			
		||||
    } else {
 | 
			
		||||
      edges[pos].interpolate = interp
 | 
			
		||||
      edges[pos].interpolate = interp;
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Updates a link with a style
 | 
			
		||||
 * @param pos
 | 
			
		||||
 * @param style
 | 
			
		||||
 */
 | 
			
		||||
export const updateLink = function (positions, style) {
 | 
			
		||||
  positions.forEach(function (pos) {
 | 
			
		||||
export const updateLink = function(positions, style) {
 | 
			
		||||
  positions.forEach(function(pos) {
 | 
			
		||||
    if (pos === 'default') {
 | 
			
		||||
      edges.defaultStyle = style
 | 
			
		||||
      edges.defaultStyle = style;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (utils.isSubstringInArray('fill', style) === -1) {
 | 
			
		||||
        style.push('fill:none')
 | 
			
		||||
        style.push('fill:none');
 | 
			
		||||
      }
 | 
			
		||||
      edges[pos].style = style
 | 
			
		||||
      edges[pos].style = style;
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const addClass = function (id, style) {
 | 
			
		||||
export const addClass = function(id, style) {
 | 
			
		||||
  if (typeof classes[id] === 'undefined') {
 | 
			
		||||
    classes[id] = { id: id, styles: [] }
 | 
			
		||||
    classes[id] = { id: id, styles: [] };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (typeof style !== 'undefined') {
 | 
			
		||||
    if (style !== null) {
 | 
			
		||||
      style.forEach(function (s) {
 | 
			
		||||
        classes[id].styles.push(s)
 | 
			
		||||
      })
 | 
			
		||||
      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
 | 
			
		||||
 */
 | 
			
		||||
export const setDirection = function (dir) {
 | 
			
		||||
  direction = dir
 | 
			
		||||
}
 | 
			
		||||
export const setDirection = function(dir) {
 | 
			
		||||
  direction = dir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called by parser when a special node is found, e.g. a clickable element.
 | 
			
		||||
 * @param ids Comma separated list of ids
 | 
			
		||||
 * @param className Class to add
 | 
			
		||||
 */
 | 
			
		||||
export const setClass = function (ids, className) {
 | 
			
		||||
  ids.split(',').forEach(function (_id) {
 | 
			
		||||
    let id = _id
 | 
			
		||||
    if (_id[0].match(/\d/)) id = 's' + id
 | 
			
		||||
export const setClass = function(ids, className) {
 | 
			
		||||
  ids.split(',').forEach(function(_id) {
 | 
			
		||||
    let id = _id;
 | 
			
		||||
    if (_id[0].match(/\d/)) id = 's' + id;
 | 
			
		||||
    if (typeof vertices[id] !== 'undefined') {
 | 
			
		||||
      vertices[id].classes.push(className)
 | 
			
		||||
      vertices[id].classes.push(className);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof subGraphLookup[id] !== 'undefined') {
 | 
			
		||||
      subGraphLookup[id].classes.push(className)
 | 
			
		||||
      subGraphLookup[id].classes.push(className);
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const setTooltip = function (ids, tooltip) {
 | 
			
		||||
  ids.split(',').forEach(function (id) {
 | 
			
		||||
const setTooltip = function(ids, tooltip) {
 | 
			
		||||
  ids.split(',').forEach(function(id) {
 | 
			
		||||
    if (typeof tooltip !== 'undefined') {
 | 
			
		||||
      tooltips[id] = sanitize(tooltip)
 | 
			
		||||
      tooltips[id] = sanitize(tooltip);
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const setClickFun = function (_id, functionName) {
 | 
			
		||||
  let id = _id
 | 
			
		||||
  if (_id[0].match(/\d/)) id = 's' + id
 | 
			
		||||
const setClickFun = function(_id, functionName) {
 | 
			
		||||
  let id = _id;
 | 
			
		||||
  if (_id[0].match(/\d/)) id = 's' + id;
 | 
			
		||||
  if (config.securityLevel !== 'loose') {
 | 
			
		||||
    return
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof functionName === 'undefined') {
 | 
			
		||||
    return
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof vertices[id] !== 'undefined') {
 | 
			
		||||
    funs.push(function (element) {
 | 
			
		||||
      const elem = document.querySelector(`[id="${id}"]`)
 | 
			
		||||
    funs.push(function(element) {
 | 
			
		||||
      const elem = document.querySelector(`[id="${id}"]`);
 | 
			
		||||
      if (elem !== null) {
 | 
			
		||||
        elem.addEventListener('click', function () {
 | 
			
		||||
          window[functionName](id)
 | 
			
		||||
        }, false)
 | 
			
		||||
        elem.addEventListener(
 | 
			
		||||
          'click',
 | 
			
		||||
          function() {
 | 
			
		||||
            window[functionName](id);
 | 
			
		||||
          },
 | 
			
		||||
          false
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called by parser when a link is found. Adds the URL to the vertex data.
 | 
			
		||||
@@ -227,24 +231,24 @@ const setClickFun = function (_id, functionName) {
 | 
			
		||||
 * @param linkStr URL to create a link for
 | 
			
		||||
 * @param tooltip Tooltip for the clickable element
 | 
			
		||||
 */
 | 
			
		||||
export const setLink = function (ids, linkStr, tooltip) {
 | 
			
		||||
  ids.split(',').forEach(function (_id) {
 | 
			
		||||
    let id = _id
 | 
			
		||||
    if (_id[0].match(/\d/)) id = 's' + id
 | 
			
		||||
export const setLink = function(ids, linkStr, tooltip) {
 | 
			
		||||
  ids.split(',').forEach(function(_id) {
 | 
			
		||||
    let id = _id;
 | 
			
		||||
    if (_id[0].match(/\d/)) id = 's' + id;
 | 
			
		||||
    if (typeof vertices[id] !== 'undefined') {
 | 
			
		||||
      if (config.securityLevel !== 'loose') {
 | 
			
		||||
        vertices[id].link = sanitizeUrl(linkStr) // .replace(/javascript:.*/g, '')
 | 
			
		||||
        vertices[id].link = sanitizeUrl(linkStr); // .replace(/javascript:.*/g, '')
 | 
			
		||||
      } else {
 | 
			
		||||
        vertices[id].link = linkStr
 | 
			
		||||
        vertices[id].link = linkStr;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
  setTooltip(ids, tooltip)
 | 
			
		||||
  setClass(ids, 'clickable')
 | 
			
		||||
}
 | 
			
		||||
export const getTooltip = function (id) {
 | 
			
		||||
  return tooltips[id]
 | 
			
		||||
}
 | 
			
		||||
  });
 | 
			
		||||
  setTooltip(ids, tooltip);
 | 
			
		||||
  setClass(ids, 'clickable');
 | 
			
		||||
};
 | 
			
		||||
export const getTooltip = function(id) {
 | 
			
		||||
  return tooltips[id];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called by parser when a click definition is found. Registers an event handler.
 | 
			
		||||
@@ -252,209 +256,219 @@ export const getTooltip = function (id) {
 | 
			
		||||
 * @param functionName Function to be called on click
 | 
			
		||||
 * @param tooltip Tooltip for the clickable element
 | 
			
		||||
 */
 | 
			
		||||
export const setClickEvent = function (ids, functionName, tooltip) {
 | 
			
		||||
  ids.split(',').forEach(function (id) { setClickFun(id, functionName) })
 | 
			
		||||
  setTooltip(ids, tooltip)
 | 
			
		||||
  setClass(ids, 'clickable')
 | 
			
		||||
}
 | 
			
		||||
export const setClickEvent = function(ids, functionName, tooltip) {
 | 
			
		||||
  ids.split(',').forEach(function(id) {
 | 
			
		||||
    setClickFun(id, functionName);
 | 
			
		||||
  });
 | 
			
		||||
  setTooltip(ids, tooltip);
 | 
			
		||||
  setClass(ids, 'clickable');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const bindFunctions = function (element) {
 | 
			
		||||
  funs.forEach(function (fun) {
 | 
			
		||||
    fun(element)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
export const getDirection = function () {
 | 
			
		||||
  return direction
 | 
			
		||||
}
 | 
			
		||||
export const bindFunctions = function(element) {
 | 
			
		||||
  funs.forEach(function(fun) {
 | 
			
		||||
    fun(element);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
export const getDirection = function() {
 | 
			
		||||
  return direction;
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieval function for fetching the found nodes after parsing has completed.
 | 
			
		||||
 * @returns {{}|*|vertices}
 | 
			
		||||
 */
 | 
			
		||||
export const getVertices = function () {
 | 
			
		||||
  return vertices
 | 
			
		||||
}
 | 
			
		||||
export const getVertices = function() {
 | 
			
		||||
  return vertices;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieval function for fetching the found links after parsing has completed.
 | 
			
		||||
 * @returns {{}|*|edges}
 | 
			
		||||
 */
 | 
			
		||||
export const getEdges = function () {
 | 
			
		||||
  return edges
 | 
			
		||||
}
 | 
			
		||||
export const getEdges = function() {
 | 
			
		||||
  return edges;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieval function for fetching the found class definitions after parsing has completed.
 | 
			
		||||
 * @returns {{}|*|classes}
 | 
			
		||||
 */
 | 
			
		||||
export const getClasses = function () {
 | 
			
		||||
  return classes
 | 
			
		||||
}
 | 
			
		||||
export const getClasses = function() {
 | 
			
		||||
  return classes;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const setupToolTips = function (element) {
 | 
			
		||||
  let tooltipElem = d3.select('.mermaidTooltip')
 | 
			
		||||
const setupToolTips = function(element) {
 | 
			
		||||
  let tooltipElem = d3.select('.mermaidTooltip');
 | 
			
		||||
  if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
 | 
			
		||||
    tooltipElem = d3.select('body')
 | 
			
		||||
    tooltipElem = d3
 | 
			
		||||
      .select('body')
 | 
			
		||||
      .append('div')
 | 
			
		||||
      .attr('class', 'mermaidTooltip')
 | 
			
		||||
      .style('opacity', 0)
 | 
			
		||||
      .style('opacity', 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const svg = d3.select(element).select('svg')
 | 
			
		||||
  const svg = d3.select(element).select('svg');
 | 
			
		||||
 | 
			
		||||
  const nodes = svg.selectAll('g.node')
 | 
			
		||||
  const nodes = svg.selectAll('g.node');
 | 
			
		||||
  nodes
 | 
			
		||||
    .on('mouseover', function () {
 | 
			
		||||
      const el = d3.select(this)
 | 
			
		||||
      const title = el.attr('title')
 | 
			
		||||
    .on('mouseover', function() {
 | 
			
		||||
      const el = d3.select(this);
 | 
			
		||||
      const title = el.attr('title');
 | 
			
		||||
      // Dont try to draw a tooltip if no data is provided
 | 
			
		||||
      if (title === null) {
 | 
			
		||||
        return
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      const rect = this.getBoundingClientRect()
 | 
			
		||||
      const rect = this.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
      tooltipElem.transition()
 | 
			
		||||
      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)
 | 
			
		||||
        .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()
 | 
			
		||||
    .on('mouseout', function() {
 | 
			
		||||
      tooltipElem
 | 
			
		||||
        .transition()
 | 
			
		||||
        .duration(500)
 | 
			
		||||
        .style('opacity', 0)
 | 
			
		||||
      const el = d3.select(this)
 | 
			
		||||
      el.classed('hover', false)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
funs.push(setupToolTips)
 | 
			
		||||
        .style('opacity', 0);
 | 
			
		||||
      const el = d3.select(this);
 | 
			
		||||
      el.classed('hover', false);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
funs.push(setupToolTips);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clears the internal graph db so that a new graph can be parsed.
 | 
			
		||||
 */
 | 
			
		||||
export const clear = function () {
 | 
			
		||||
  vertices = {}
 | 
			
		||||
  classes = {}
 | 
			
		||||
  edges = []
 | 
			
		||||
  funs = []
 | 
			
		||||
  funs.push(setupToolTips)
 | 
			
		||||
  subGraphs = []
 | 
			
		||||
  subGraphLookup = {}
 | 
			
		||||
  subCount = 0
 | 
			
		||||
  tooltips = []
 | 
			
		||||
}
 | 
			
		||||
export const clear = function() {
 | 
			
		||||
  vertices = {};
 | 
			
		||||
  classes = {};
 | 
			
		||||
  edges = [];
 | 
			
		||||
  funs = [];
 | 
			
		||||
  funs.push(setupToolTips);
 | 
			
		||||
  subGraphs = [];
 | 
			
		||||
  subGraphLookup = {};
 | 
			
		||||
  subCount = 0;
 | 
			
		||||
  tooltips = [];
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @returns {string}
 | 
			
		||||
 */
 | 
			
		||||
export const defaultStyle = function () {
 | 
			
		||||
  return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;'
 | 
			
		||||
}
 | 
			
		||||
export const 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.
 | 
			
		||||
 */
 | 
			
		||||
export const addSubGraph = function (_id, list, _title) {
 | 
			
		||||
  let id = _id
 | 
			
		||||
  let title = _title
 | 
			
		||||
export const addSubGraph = function(_id, list, _title) {
 | 
			
		||||
  let id = _id;
 | 
			
		||||
  let title = _title;
 | 
			
		||||
  if (_id === _title && _title.match(/\s/)) {
 | 
			
		||||
    id = undefined
 | 
			
		||||
    id = undefined;
 | 
			
		||||
  }
 | 
			
		||||
  function uniq (a) {
 | 
			
		||||
    const prims = { 'boolean': {}, 'number': {}, 'string': {} }
 | 
			
		||||
    const objs = []
 | 
			
		||||
  function uniq(a) {
 | 
			
		||||
    const prims = { boolean: {}, number: {}, string: {} };
 | 
			
		||||
    const objs = [];
 | 
			
		||||
 | 
			
		||||
    return a.filter(function (item) {
 | 
			
		||||
      const type = typeof item
 | 
			
		||||
    return a.filter(function(item) {
 | 
			
		||||
      const type = typeof item;
 | 
			
		||||
      if (item.trim() === '') {
 | 
			
		||||
        return false
 | 
			
		||||
        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) }
 | 
			
		||||
    })
 | 
			
		||||
      if (type in prims) {
 | 
			
		||||
        return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
 | 
			
		||||
      } else {
 | 
			
		||||
        return objs.indexOf(item) >= 0 ? false : objs.push(item);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let nodeList = []
 | 
			
		||||
  let nodeList = [];
 | 
			
		||||
 | 
			
		||||
  nodeList = uniq(nodeList.concat.apply(nodeList, list))
 | 
			
		||||
  nodeList = uniq(nodeList.concat.apply(nodeList, list));
 | 
			
		||||
  for (let i = 0; i < nodeList.length; i++) {
 | 
			
		||||
    if (nodeList[i][0].match(/\d/)) nodeList[i] = 's' + nodeList[i]
 | 
			
		||||
    if (nodeList[i][0].match(/\d/)) nodeList[i] = 's' + nodeList[i];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  id = id || ('subGraph' + subCount)
 | 
			
		||||
  if (id[0].match(/\d/)) id = 's' + id
 | 
			
		||||
  title = title || ''
 | 
			
		||||
  title = sanitize(title)
 | 
			
		||||
  subCount = subCount + 1
 | 
			
		||||
  const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] }
 | 
			
		||||
  subGraphs.push(subGraph)
 | 
			
		||||
  subGraphLookup[id] = subGraph
 | 
			
		||||
  return id
 | 
			
		||||
}
 | 
			
		||||
  id = id || 'subGraph' + subCount;
 | 
			
		||||
  if (id[0].match(/\d/)) id = 's' + id;
 | 
			
		||||
  title = title || '';
 | 
			
		||||
  title = sanitize(title);
 | 
			
		||||
  subCount = subCount + 1;
 | 
			
		||||
  const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] };
 | 
			
		||||
  subGraphs.push(subGraph);
 | 
			
		||||
  subGraphLookup[id] = subGraph;
 | 
			
		||||
  return id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getPosForId = function (id) {
 | 
			
		||||
const getPosForId = function(id) {
 | 
			
		||||
  for (let i = 0; i < subGraphs.length; i++) {
 | 
			
		||||
    if (subGraphs[i].id === id) {
 | 
			
		||||
      return i
 | 
			
		||||
      return i;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return -1
 | 
			
		||||
}
 | 
			
		||||
let secCount = -1
 | 
			
		||||
const posCrossRef = []
 | 
			
		||||
const indexNodes2 = function (id, pos) {
 | 
			
		||||
  const nodes = subGraphs[pos].nodes
 | 
			
		||||
  secCount = secCount + 1
 | 
			
		||||
  return -1;
 | 
			
		||||
};
 | 
			
		||||
let secCount = -1;
 | 
			
		||||
const posCrossRef = [];
 | 
			
		||||
const indexNodes2 = function(id, pos) {
 | 
			
		||||
  const nodes = subGraphs[pos].nodes;
 | 
			
		||||
  secCount = secCount + 1;
 | 
			
		||||
  if (secCount > 2000) {
 | 
			
		||||
    return
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  posCrossRef[secCount] = pos
 | 
			
		||||
  posCrossRef[secCount] = pos;
 | 
			
		||||
  // Check if match
 | 
			
		||||
  if (subGraphs[pos].id === id) {
 | 
			
		||||
    return {
 | 
			
		||||
      result: true,
 | 
			
		||||
      count: 0
 | 
			
		||||
    }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let count = 0
 | 
			
		||||
  let posCount = 1
 | 
			
		||||
  let count = 0;
 | 
			
		||||
  let posCount = 1;
 | 
			
		||||
  while (count < nodes.length) {
 | 
			
		||||
    const childPos = getPosForId(nodes[count])
 | 
			
		||||
    const childPos = getPosForId(nodes[count]);
 | 
			
		||||
    // Ignore regular nodes (pos will be -1)
 | 
			
		||||
    if (childPos >= 0) {
 | 
			
		||||
      const res = indexNodes2(id, childPos)
 | 
			
		||||
      const res = indexNodes2(id, childPos);
 | 
			
		||||
      if (res.result) {
 | 
			
		||||
        return {
 | 
			
		||||
          result: true,
 | 
			
		||||
          count: posCount + res.count
 | 
			
		||||
        }
 | 
			
		||||
        };
 | 
			
		||||
      } else {
 | 
			
		||||
        posCount = posCount + res.count
 | 
			
		||||
        posCount = posCount + res.count;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    count = count + 1
 | 
			
		||||
    count = count + 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    result: false,
 | 
			
		||||
    count: posCount
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getDepthFirstPos = function (pos) {
 | 
			
		||||
  return posCrossRef[pos]
 | 
			
		||||
}
 | 
			
		||||
export const indexNodes = function () {
 | 
			
		||||
  secCount = -1
 | 
			
		||||
export const getDepthFirstPos = function(pos) {
 | 
			
		||||
  return posCrossRef[pos];
 | 
			
		||||
};
 | 
			
		||||
export const indexNodes = function() {
 | 
			
		||||
  secCount = -1;
 | 
			
		||||
  if (subGraphs.length > 0) {
 | 
			
		||||
    indexNodes2('none', subGraphs.length - 1, 0)
 | 
			
		||||
    indexNodes2('none', subGraphs.length - 1, 0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getSubGraphs = function () {
 | 
			
		||||
  return subGraphs
 | 
			
		||||
}
 | 
			
		||||
export const getSubGraphs = function() {
 | 
			
		||||
  return subGraphs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  addVertex,
 | 
			
		||||
@@ -478,4 +492,4 @@ export default {
 | 
			
		||||
  getDepthFirstPos,
 | 
			
		||||
  indexNodes,
 | 
			
		||||
  getSubGraphs
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,274 +1,288 @@
 | 
			
		||||
import graphlib from 'graphlibrary'
 | 
			
		||||
import * as d3 from 'd3'
 | 
			
		||||
import graphlib from 'graphlibrary';
 | 
			
		||||
import * as d3 from 'd3';
 | 
			
		||||
 | 
			
		||||
import flowDb from './flowDb'
 | 
			
		||||
import flow from './parser/flow'
 | 
			
		||||
import { getConfig } from '../../config'
 | 
			
		||||
import dagreD3 from 'dagre-d3-renderer'
 | 
			
		||||
import addHtmlLabel from 'dagre-d3-renderer/lib/label/add-html-label.js'
 | 
			
		||||
import { logger } from '../../logger'
 | 
			
		||||
import { interpolateToCurve } from '../../utils'
 | 
			
		||||
import flowDb from './flowDb';
 | 
			
		||||
import flow from './parser/flow';
 | 
			
		||||
import { getConfig } from '../../config';
 | 
			
		||||
import dagreD3 from 'dagre-d3-renderer';
 | 
			
		||||
import addHtmlLabel from 'dagre-d3-renderer/lib/label/add-html-label.js';
 | 
			
		||||
import { logger } from '../../logger';
 | 
			
		||||
import { interpolateToCurve } from '../../utils';
 | 
			
		||||
 | 
			
		||||
const conf = {
 | 
			
		||||
}
 | 
			
		||||
export const setConf = function (cnf) {
 | 
			
		||||
  const keys = Object.keys(cnf)
 | 
			
		||||
const conf = {};
 | 
			
		||||
export const setConf = function(cnf) {
 | 
			
		||||
  const keys = Object.keys(cnf);
 | 
			
		||||
  for (let i = 0; i < keys.length; i++) {
 | 
			
		||||
    conf[keys[i]] = cnf[keys[i]]
 | 
			
		||||
    conf[keys[i]] = cnf[keys[i]];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Function that adds the vertices found in the graph definition to the graph to be rendered.
 | 
			
		||||
 * @param vert Object containing the vertices.
 | 
			
		||||
 * @param g The graph that is to be drawn.
 | 
			
		||||
 */
 | 
			
		||||
export const addVertices = function (vert, g, svgId) {
 | 
			
		||||
  const svg = d3.select(`[id="${svgId}"]`)
 | 
			
		||||
  const keys = Object.keys(vert)
 | 
			
		||||
export const addVertices = function(vert, g, svgId) {
 | 
			
		||||
  const svg = d3.select(`[id="${svgId}"]`);
 | 
			
		||||
  const keys = Object.keys(vert);
 | 
			
		||||
 | 
			
		||||
  const styleFromStyleArr = function (styleStr, arr, { label }) {
 | 
			
		||||
  const styleFromStyleArr = function(styleStr, arr, { label }) {
 | 
			
		||||
    if (!label) {
 | 
			
		||||
    // Create a compound style definition from the style definitions found for the node in the graph definition
 | 
			
		||||
      // Create a compound style definition from the style definitions found for the node in the graph definition
 | 
			
		||||
      for (let i = 0; i < arr.length; i++) {
 | 
			
		||||
        if (typeof arr[i] !== 'undefined') {
 | 
			
		||||
          styleStr = styleStr + arr[i] + ';'
 | 
			
		||||
          styleStr = styleStr + arr[i] + ';';
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      for (let i = 0; i < arr.length; i++) {
 | 
			
		||||
        if (typeof arr[i] !== 'undefined') {
 | 
			
		||||
          if (arr[i].match('^color:')) styleStr = styleStr + arr[i] + ';'
 | 
			
		||||
          if (arr[i].match('^color:')) styleStr = styleStr + arr[i] + ';';
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return styleStr
 | 
			
		||||
  }
 | 
			
		||||
    return styleStr;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
 | 
			
		||||
  keys.forEach(function (id) {
 | 
			
		||||
    const vertex = vert[id]
 | 
			
		||||
  keys.forEach(function(id) {
 | 
			
		||||
    const vertex = vert[id];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Variable for storing the classes for the vertex
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     */
 | 
			
		||||
    let classStr = ''
 | 
			
		||||
    let classStr = '';
 | 
			
		||||
    if (vertex.classes.length > 0) {
 | 
			
		||||
      classStr = vertex.classes.join(' ')
 | 
			
		||||
      classStr = vertex.classes.join(' ');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Variable for storing the extracted style for the vertex
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     */
 | 
			
		||||
    let style = ''
 | 
			
		||||
    let style = '';
 | 
			
		||||
    // Create a compound style definition from the style definitions found for the node in the graph definition
 | 
			
		||||
    style = styleFromStyleArr(style, vertex.styles, { label: false })
 | 
			
		||||
    let labelStyle = ''
 | 
			
		||||
    labelStyle = styleFromStyleArr(labelStyle, vertex.styles, { label: true })
 | 
			
		||||
    style = styleFromStyleArr(style, vertex.styles, { label: false });
 | 
			
		||||
    let labelStyle = '';
 | 
			
		||||
    labelStyle = styleFromStyleArr(labelStyle, vertex.styles, { label: true });
 | 
			
		||||
 | 
			
		||||
    // Use vertex id as text in the box if no text is provided by the graph definition
 | 
			
		||||
    let vertexText = vertex.text !== undefined ? vertex.text : vertex.id
 | 
			
		||||
    let vertexText = vertex.text !== undefined ? vertex.text : vertex.id;
 | 
			
		||||
 | 
			
		||||
    // We create a SVG label, either by delegating to addHtmlLabel or manually
 | 
			
		||||
    let vertexNode
 | 
			
		||||
    let vertexNode;
 | 
			
		||||
    if (getConfig().flowchart.htmlLabels) {
 | 
			
		||||
      // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
 | 
			
		||||
      const node = { label: vertexText.replace(/fa[lrsb]?:fa-[\w-]+/g, s => `<i class='${s.replace(':', ' ')}'></i>`) }
 | 
			
		||||
      vertexNode = addHtmlLabel(svg, node).node()
 | 
			
		||||
      vertexNode.parentNode.removeChild(vertexNode)
 | 
			
		||||
      const node = {
 | 
			
		||||
        label: vertexText.replace(
 | 
			
		||||
          /fa[lrsb]?:fa-[\w-]+/g,
 | 
			
		||||
          s => `<i class='${s.replace(':', ' ')}'></i>`
 | 
			
		||||
        )
 | 
			
		||||
      };
 | 
			
		||||
      vertexNode = addHtmlLabel(svg, node).node();
 | 
			
		||||
      vertexNode.parentNode.removeChild(vertexNode);
 | 
			
		||||
    } else {
 | 
			
		||||
      const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text')
 | 
			
		||||
      const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
 | 
			
		||||
 | 
			
		||||
      const rows = vertexText.split(/<br[/]{0,1}>/)
 | 
			
		||||
      const rows = vertexText.split(/<br[/]{0,1}>/);
 | 
			
		||||
 | 
			
		||||
      for (let j = 0; j < rows.length; j++) {
 | 
			
		||||
        const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan')
 | 
			
		||||
        tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve')
 | 
			
		||||
        tspan.setAttribute('dy', '1em')
 | 
			
		||||
        tspan.setAttribute('x', '1')
 | 
			
		||||
        tspan.textContent = rows[j]
 | 
			
		||||
        svgLabel.appendChild(tspan)
 | 
			
		||||
        const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
 | 
			
		||||
        tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
 | 
			
		||||
        tspan.setAttribute('dy', '1em');
 | 
			
		||||
        tspan.setAttribute('x', '1');
 | 
			
		||||
        tspan.textContent = rows[j];
 | 
			
		||||
        svgLabel.appendChild(tspan);
 | 
			
		||||
      }
 | 
			
		||||
      vertexNode = svgLabel
 | 
			
		||||
      vertexNode = svgLabel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If the node has a link, we wrap it in a SVG link
 | 
			
		||||
    if (vertex.link) {
 | 
			
		||||
      const link = document.createElementNS('http://www.w3.org/2000/svg', 'a')
 | 
			
		||||
      link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link)
 | 
			
		||||
      link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener')
 | 
			
		||||
      link.appendChild(vertexNode)
 | 
			
		||||
      vertexNode = link
 | 
			
		||||
      const link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
 | 
			
		||||
      link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link);
 | 
			
		||||
      link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener');
 | 
			
		||||
      link.appendChild(vertexNode);
 | 
			
		||||
      vertexNode = link;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let radious = 0
 | 
			
		||||
    let _shape = ''
 | 
			
		||||
    let radious = 0;
 | 
			
		||||
    let _shape = '';
 | 
			
		||||
    // Set the shape based parameters
 | 
			
		||||
    switch (vertex.type) {
 | 
			
		||||
      case 'round':
 | 
			
		||||
        radious = 5
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
        break
 | 
			
		||||
        radious = 5;
 | 
			
		||||
        _shape = 'rect';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'square':
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'rect';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'diamond':
 | 
			
		||||
        _shape = 'question'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'question';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'odd':
 | 
			
		||||
        _shape = 'rect_left_inv_arrow'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'rect_left_inv_arrow';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'lean_right':
 | 
			
		||||
        _shape = 'lean_right'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'lean_right';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'lean_left':
 | 
			
		||||
        _shape = 'lean_left'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'lean_left';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'trapezoid':
 | 
			
		||||
        _shape = 'trapezoid'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'trapezoid';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'inv_trapezoid':
 | 
			
		||||
        _shape = 'inv_trapezoid'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'inv_trapezoid';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'odd_right':
 | 
			
		||||
        _shape = 'rect_left_inv_arrow'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'rect_left_inv_arrow';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'circle':
 | 
			
		||||
        _shape = 'circle'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'circle';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'ellipse':
 | 
			
		||||
        _shape = 'ellipse'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'ellipse';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'group':
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
        break
 | 
			
		||||
        _shape = 'rect';
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        _shape = 'rect'
 | 
			
		||||
        _shape = 'rect';
 | 
			
		||||
    }
 | 
			
		||||
    // Add the node
 | 
			
		||||
    g.setNode(vertex.id, { labelType: 'svg', labelStyle: labelStyle, shape: _shape, label: vertexNode, rx: radious, ry: radious, 'class': classStr, style: style, id: vertex.id })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
    g.setNode(vertex.id, {
 | 
			
		||||
      labelType: 'svg',
 | 
			
		||||
      labelStyle: labelStyle,
 | 
			
		||||
      shape: _shape,
 | 
			
		||||
      label: vertexNode,
 | 
			
		||||
      rx: radious,
 | 
			
		||||
      ry: radious,
 | 
			
		||||
      class: classStr,
 | 
			
		||||
      style: style,
 | 
			
		||||
      id: vertex.id
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add edges to graph based on parsed graph defninition
 | 
			
		||||
 * @param {Object} edges The edges to add to the graph
 | 
			
		||||
 * @param {Object} g The graph object
 | 
			
		||||
 */
 | 
			
		||||
export const addEdges = function (edges, g) {
 | 
			
		||||
  let cnt = 0
 | 
			
		||||
export const addEdges = function(edges, g) {
 | 
			
		||||
  let cnt = 0;
 | 
			
		||||
 | 
			
		||||
  let defaultStyle
 | 
			
		||||
  let defaultStyle;
 | 
			
		||||
  if (typeof edges.defaultStyle !== 'undefined') {
 | 
			
		||||
    defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';')
 | 
			
		||||
    defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  edges.forEach(function (edge) {
 | 
			
		||||
    cnt++
 | 
			
		||||
    const edgeData = {}
 | 
			
		||||
  edges.forEach(function(edge) {
 | 
			
		||||
    cnt++;
 | 
			
		||||
    const edgeData = {};
 | 
			
		||||
 | 
			
		||||
    // Set link type for rendering
 | 
			
		||||
    if (edge.type === 'arrow_open') {
 | 
			
		||||
      edgeData.arrowhead = 'none'
 | 
			
		||||
      edgeData.arrowhead = 'none';
 | 
			
		||||
    } else {
 | 
			
		||||
      edgeData.arrowhead = 'normal'
 | 
			
		||||
      edgeData.arrowhead = 'normal';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let style = ''
 | 
			
		||||
    let style = '';
 | 
			
		||||
    if (typeof edge.style !== 'undefined') {
 | 
			
		||||
      edge.style.forEach(function (s) {
 | 
			
		||||
        style = style + s + ';'
 | 
			
		||||
      })
 | 
			
		||||
      edge.style.forEach(function(s) {
 | 
			
		||||
        style = style + s + ';';
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      switch (edge.stroke) {
 | 
			
		||||
        case 'normal':
 | 
			
		||||
          style = 'fill:none'
 | 
			
		||||
          style = 'fill:none';
 | 
			
		||||
          if (typeof defaultStyle !== 'undefined') {
 | 
			
		||||
            style = defaultStyle
 | 
			
		||||
            style = defaultStyle;
 | 
			
		||||
          }
 | 
			
		||||
          break
 | 
			
		||||
          break;
 | 
			
		||||
        case 'dotted':
 | 
			
		||||
          style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;'
 | 
			
		||||
          break
 | 
			
		||||
          style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;';
 | 
			
		||||
          break;
 | 
			
		||||
        case 'thick':
 | 
			
		||||
          style = 'stroke: #333; stroke-width: 3.5px;fill:none'
 | 
			
		||||
          break
 | 
			
		||||
          style = 'stroke: #333; stroke-width: 3.5px;fill:none';
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    edgeData.style = style
 | 
			
		||||
    edgeData.style = style;
 | 
			
		||||
 | 
			
		||||
    if (typeof edge.interpolate !== 'undefined') {
 | 
			
		||||
      edgeData.curve = interpolateToCurve(edge.interpolate, d3.curveLinear)
 | 
			
		||||
      edgeData.curve = interpolateToCurve(edge.interpolate, d3.curveLinear);
 | 
			
		||||
    } else if (typeof edges.defaultInterpolate !== 'undefined') {
 | 
			
		||||
      edgeData.curve = interpolateToCurve(edges.defaultInterpolate, d3.curveLinear)
 | 
			
		||||
      edgeData.curve = interpolateToCurve(edges.defaultInterpolate, d3.curveLinear);
 | 
			
		||||
    } else {
 | 
			
		||||
      edgeData.curve = interpolateToCurve(conf.curve, d3.curveLinear)
 | 
			
		||||
      edgeData.curve = interpolateToCurve(conf.curve, d3.curveLinear);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof edge.text === 'undefined') {
 | 
			
		||||
      if (typeof edge.style !== 'undefined') {
 | 
			
		||||
        edgeData.arrowheadStyle = 'fill: #333'
 | 
			
		||||
        edgeData.arrowheadStyle = 'fill: #333';
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      edgeData.arrowheadStyle = 'fill: #333'
 | 
			
		||||
      edgeData.arrowheadStyle = 'fill: #333';
 | 
			
		||||
      if (typeof edge.style === 'undefined') {
 | 
			
		||||
        edgeData.labelpos = 'c'
 | 
			
		||||
        edgeData.labelpos = 'c';
 | 
			
		||||
        if (getConfig().flowchart.htmlLabels) {
 | 
			
		||||
          edgeData.labelType = 'html'
 | 
			
		||||
          edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>'
 | 
			
		||||
          edgeData.labelType = 'html';
 | 
			
		||||
          edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
 | 
			
		||||
        } else {
 | 
			
		||||
          edgeData.labelType = 'text'
 | 
			
		||||
          edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'
 | 
			
		||||
          edgeData.label = edge.text.replace(/<br>/g, '\n')
 | 
			
		||||
          edgeData.labelType = 'text';
 | 
			
		||||
          edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none';
 | 
			
		||||
          edgeData.label = edge.text.replace(/<br>/g, '\n');
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        edgeData.label = edge.text.replace(/<br>/g, '\n')
 | 
			
		||||
        edgeData.label = edge.text.replace(/<br>/g, '\n');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // Add the edge to the graph
 | 
			
		||||
    g.setEdge(edge.start, edge.end, edgeData, cnt)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
    g.setEdge(edge.start, edge.end, edgeData, cnt);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the all the styles from classDef statements in the graph definition.
 | 
			
		||||
 * @returns {object} classDef styles
 | 
			
		||||
 */
 | 
			
		||||
export const getClasses = function (text) {
 | 
			
		||||
  logger.info('Extracting classes')
 | 
			
		||||
  flowDb.clear()
 | 
			
		||||
  const parser = flow.parser
 | 
			
		||||
  parser.yy = flowDb
 | 
			
		||||
export const getClasses = function(text) {
 | 
			
		||||
  logger.info('Extracting classes');
 | 
			
		||||
  flowDb.clear();
 | 
			
		||||
  const parser = flow.parser;
 | 
			
		||||
  parser.yy = flowDb;
 | 
			
		||||
 | 
			
		||||
  // Parse the graph definition
 | 
			
		||||
  parser.parse(text)
 | 
			
		||||
  return flowDb.getClasses()
 | 
			
		||||
}
 | 
			
		||||
  parser.parse(text);
 | 
			
		||||
  return flowDb.getClasses();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draws a flowchart in the tag with id: id based on the graph definition in text.
 | 
			
		||||
 * @param text
 | 
			
		||||
 * @param id
 | 
			
		||||
 */
 | 
			
		||||
export const draw = function (text, id) {
 | 
			
		||||
  logger.info('Drawing flowchart')
 | 
			
		||||
  flowDb.clear()
 | 
			
		||||
  const parser = flow.parser
 | 
			
		||||
  parser.yy = flowDb
 | 
			
		||||
export const draw = function(text, id) {
 | 
			
		||||
  logger.info('Drawing flowchart');
 | 
			
		||||
  flowDb.clear();
 | 
			
		||||
  const parser = flow.parser;
 | 
			
		||||
  parser.yy = flowDb;
 | 
			
		||||
 | 
			
		||||
  // Parse the graph definition
 | 
			
		||||
  try {
 | 
			
		||||
    parser.parse(text)
 | 
			
		||||
    parser.parse(text);
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    logger.debug('Parsing failed')
 | 
			
		||||
    logger.debug('Parsing failed');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Fetch the default direction, use TD if none was found
 | 
			
		||||
  let dir = flowDb.getDirection()
 | 
			
		||||
  let dir = flowDb.getDirection();
 | 
			
		||||
  if (typeof dir === 'undefined') {
 | 
			
		||||
    dir = 'TD'
 | 
			
		||||
    dir = 'TD';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Create the input mermaid.graph
 | 
			
		||||
@@ -280,196 +294,238 @@ export const draw = function (text, id) {
 | 
			
		||||
      rankdir: dir,
 | 
			
		||||
      marginx: 20,
 | 
			
		||||
      marginy: 20
 | 
			
		||||
 | 
			
		||||
    })
 | 
			
		||||
    .setDefaultEdgeLabel(function () {
 | 
			
		||||
      return {}
 | 
			
		||||
    })
 | 
			
		||||
    .setDefaultEdgeLabel(function() {
 | 
			
		||||
      return {};
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  let subG
 | 
			
		||||
  const subGraphs = flowDb.getSubGraphs()
 | 
			
		||||
  let subG;
 | 
			
		||||
  const subGraphs = flowDb.getSubGraphs();
 | 
			
		||||
  for (let i = subGraphs.length - 1; i >= 0; i--) {
 | 
			
		||||
    subG = subGraphs[i]
 | 
			
		||||
    flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes)
 | 
			
		||||
    subG = subGraphs[i];
 | 
			
		||||
    flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Fetch the verices/nodes and edges/links from the parsed graph definition
 | 
			
		||||
  const vert = flowDb.getVertices()
 | 
			
		||||
  const vert = flowDb.getVertices();
 | 
			
		||||
 | 
			
		||||
  const edges = flowDb.getEdges()
 | 
			
		||||
  const edges = flowDb.getEdges();
 | 
			
		||||
 | 
			
		||||
  let i = 0
 | 
			
		||||
  let i = 0;
 | 
			
		||||
  for (i = subGraphs.length - 1; i >= 0; i--) {
 | 
			
		||||
    subG = subGraphs[i]
 | 
			
		||||
    subG = subGraphs[i];
 | 
			
		||||
 | 
			
		||||
    d3.selectAll('cluster').append('text')
 | 
			
		||||
    d3.selectAll('cluster').append('text');
 | 
			
		||||
 | 
			
		||||
    for (let j = 0; j < subG.nodes.length; j++) {
 | 
			
		||||
      g.setParent(subG.nodes[j], subG.id)
 | 
			
		||||
      g.setParent(subG.nodes[j], subG.id);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  addVertices(vert, g, id)
 | 
			
		||||
  addEdges(edges, g)
 | 
			
		||||
  addVertices(vert, g, id);
 | 
			
		||||
  addEdges(edges, g);
 | 
			
		||||
 | 
			
		||||
  // Create the renderer
 | 
			
		||||
  const Render = dagreD3.render
 | 
			
		||||
  const render = new Render()
 | 
			
		||||
  const Render = dagreD3.render;
 | 
			
		||||
  const render = new Render();
 | 
			
		||||
 | 
			
		||||
  // Add custom shape for rhombus type of boc (decision)
 | 
			
		||||
  render.shapes().question = function (parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width
 | 
			
		||||
    const h = bbox.height
 | 
			
		||||
    const s = (w + h) * 0.9
 | 
			
		||||
  render.shapes().question = function(parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width;
 | 
			
		||||
    const h = bbox.height;
 | 
			
		||||
    const s = (w + h) * 0.9;
 | 
			
		||||
    const points = [
 | 
			
		||||
      { x: s / 2, y: 0 },
 | 
			
		||||
      { x: s, y: -s / 2 },
 | 
			
		||||
      { x: s / 2, y: -s },
 | 
			
		||||
      { x: 0, y: -s / 2 }
 | 
			
		||||
    ]
 | 
			
		||||
    const shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      .attr('points', points.map(function (d) {
 | 
			
		||||
        return d.x + ',' + d.y
 | 
			
		||||
      }).join(' '))
 | 
			
		||||
    ];
 | 
			
		||||
    const shapeSvg = parent
 | 
			
		||||
      .insert('polygon', ':first-child')
 | 
			
		||||
      .attr(
 | 
			
		||||
        'points',
 | 
			
		||||
        points
 | 
			
		||||
          .map(function(d) {
 | 
			
		||||
            return d.x + ',' + d.y;
 | 
			
		||||
          })
 | 
			
		||||
          .join(' ')
 | 
			
		||||
      )
 | 
			
		||||
      .attr('rx', 5)
 | 
			
		||||
      .attr('ry', 5)
 | 
			
		||||
      .attr('transform', 'translate(' + (-s / 2) + ',' + (s * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
      .attr('transform', 'translate(' + -s / 2 + ',' + (s * 2) / 4 + ')');
 | 
			
		||||
    node.intersect = function(point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
    };
 | 
			
		||||
    return shapeSvg;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Add custom shape for box with inverted arrow on left side
 | 
			
		||||
  render.shapes().rect_left_inv_arrow = function (parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width
 | 
			
		||||
    const h = bbox.height
 | 
			
		||||
  render.shapes().rect_left_inv_arrow = function(parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width;
 | 
			
		||||
    const h = bbox.height;
 | 
			
		||||
    const points = [
 | 
			
		||||
      { x: -h / 2, y: 0 },
 | 
			
		||||
      { x: w, y: 0 },
 | 
			
		||||
      { x: w, y: -h },
 | 
			
		||||
      { x: -h / 2, y: -h },
 | 
			
		||||
      { x: 0, y: -h / 2 }
 | 
			
		||||
    ]
 | 
			
		||||
    const shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      .attr('points', points.map(function (d) {
 | 
			
		||||
        return d.x + ',' + d.y
 | 
			
		||||
      }).join(' '))
 | 
			
		||||
      .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
    ];
 | 
			
		||||
    const shapeSvg = parent
 | 
			
		||||
      .insert('polygon', ':first-child')
 | 
			
		||||
      .attr(
 | 
			
		||||
        'points',
 | 
			
		||||
        points
 | 
			
		||||
          .map(function(d) {
 | 
			
		||||
            return d.x + ',' + d.y;
 | 
			
		||||
          })
 | 
			
		||||
          .join(' ')
 | 
			
		||||
      )
 | 
			
		||||
      .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
 | 
			
		||||
    node.intersect = function(point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
    };
 | 
			
		||||
    return shapeSvg;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Add custom shape for box with inverted arrow on left side
 | 
			
		||||
  render.shapes().lean_right = function (parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width
 | 
			
		||||
    const h = bbox.height
 | 
			
		||||
  render.shapes().lean_right = function(parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width;
 | 
			
		||||
    const h = bbox.height;
 | 
			
		||||
    const points = [
 | 
			
		||||
      { x: -2 * h / 6, y: 0 },
 | 
			
		||||
      { x: (-2 * h) / 6, y: 0 },
 | 
			
		||||
      { x: w - h / 6, y: 0 },
 | 
			
		||||
      { x: w + 2 * h / 6, y: -h },
 | 
			
		||||
      { x: w + (2 * h) / 6, y: -h },
 | 
			
		||||
      { x: h / 6, y: -h }
 | 
			
		||||
    ]
 | 
			
		||||
    const shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      .attr('points', points.map(function (d) {
 | 
			
		||||
        return d.x + ',' + d.y
 | 
			
		||||
      }).join(' '))
 | 
			
		||||
      .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
    ];
 | 
			
		||||
    const shapeSvg = parent
 | 
			
		||||
      .insert('polygon', ':first-child')
 | 
			
		||||
      .attr(
 | 
			
		||||
        'points',
 | 
			
		||||
        points
 | 
			
		||||
          .map(function(d) {
 | 
			
		||||
            return d.x + ',' + d.y;
 | 
			
		||||
          })
 | 
			
		||||
          .join(' ')
 | 
			
		||||
      )
 | 
			
		||||
      .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
 | 
			
		||||
    node.intersect = function(point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
    };
 | 
			
		||||
    return shapeSvg;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Add custom shape for box with inverted arrow on left side
 | 
			
		||||
  render.shapes().lean_left = function (parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width
 | 
			
		||||
    const h = bbox.height
 | 
			
		||||
  render.shapes().lean_left = function(parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width;
 | 
			
		||||
    const h = bbox.height;
 | 
			
		||||
    const points = [
 | 
			
		||||
      { x: 2 * h / 6, y: 0 },
 | 
			
		||||
      { x: (2 * h) / 6, y: 0 },
 | 
			
		||||
      { x: w + h / 6, y: 0 },
 | 
			
		||||
      { x: w - 2 * h / 6, y: -h },
 | 
			
		||||
      { x: w - (2 * h) / 6, y: -h },
 | 
			
		||||
      { x: -h / 6, y: -h }
 | 
			
		||||
    ]
 | 
			
		||||
    const shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      .attr('points', points.map(function (d) {
 | 
			
		||||
        return d.x + ',' + d.y
 | 
			
		||||
      }).join(' '))
 | 
			
		||||
      .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
    ];
 | 
			
		||||
    const shapeSvg = parent
 | 
			
		||||
      .insert('polygon', ':first-child')
 | 
			
		||||
      .attr(
 | 
			
		||||
        'points',
 | 
			
		||||
        points
 | 
			
		||||
          .map(function(d) {
 | 
			
		||||
            return d.x + ',' + d.y;
 | 
			
		||||
          })
 | 
			
		||||
          .join(' ')
 | 
			
		||||
      )
 | 
			
		||||
      .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
 | 
			
		||||
    node.intersect = function(point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
    };
 | 
			
		||||
    return shapeSvg;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Add custom shape for box with inverted arrow on left side
 | 
			
		||||
  render.shapes().trapezoid = function (parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width
 | 
			
		||||
    const h = bbox.height
 | 
			
		||||
  render.shapes().trapezoid = function(parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width;
 | 
			
		||||
    const h = bbox.height;
 | 
			
		||||
    const points = [
 | 
			
		||||
      { x: -2 * h / 6, y: 0 },
 | 
			
		||||
      { x: w + 2 * h / 6, y: 0 },
 | 
			
		||||
      { x: (-2 * h) / 6, y: 0 },
 | 
			
		||||
      { x: w + (2 * h) / 6, y: 0 },
 | 
			
		||||
      { x: w - h / 6, y: -h },
 | 
			
		||||
      { x: h / 6, y: -h }
 | 
			
		||||
    ]
 | 
			
		||||
    const shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      .attr('points', points.map(function (d) {
 | 
			
		||||
        return d.x + ',' + d.y
 | 
			
		||||
      }).join(' '))
 | 
			
		||||
      .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
    ];
 | 
			
		||||
    const shapeSvg = parent
 | 
			
		||||
      .insert('polygon', ':first-child')
 | 
			
		||||
      .attr(
 | 
			
		||||
        'points',
 | 
			
		||||
        points
 | 
			
		||||
          .map(function(d) {
 | 
			
		||||
            return d.x + ',' + d.y;
 | 
			
		||||
          })
 | 
			
		||||
          .join(' ')
 | 
			
		||||
      )
 | 
			
		||||
      .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
 | 
			
		||||
    node.intersect = function(point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
    };
 | 
			
		||||
    return shapeSvg;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Add custom shape for box with inverted arrow on left side
 | 
			
		||||
  render.shapes().inv_trapezoid = function (parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width
 | 
			
		||||
    const h = bbox.height
 | 
			
		||||
  render.shapes().inv_trapezoid = function(parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width;
 | 
			
		||||
    const h = bbox.height;
 | 
			
		||||
    const points = [
 | 
			
		||||
      { x: h / 6, y: 0 },
 | 
			
		||||
      { x: w - h / 6, y: 0 },
 | 
			
		||||
      { x: w + 2 * h / 6, y: -h },
 | 
			
		||||
      { x: -2 * h / 6, y: -h }
 | 
			
		||||
    ]
 | 
			
		||||
    const shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      .attr('points', points.map(function (d) {
 | 
			
		||||
        return d.x + ',' + d.y
 | 
			
		||||
      }).join(' '))
 | 
			
		||||
      .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
      { x: w + (2 * h) / 6, y: -h },
 | 
			
		||||
      { x: (-2 * h) / 6, y: -h }
 | 
			
		||||
    ];
 | 
			
		||||
    const shapeSvg = parent
 | 
			
		||||
      .insert('polygon', ':first-child')
 | 
			
		||||
      .attr(
 | 
			
		||||
        'points',
 | 
			
		||||
        points
 | 
			
		||||
          .map(function(d) {
 | 
			
		||||
            return d.x + ',' + d.y;
 | 
			
		||||
          })
 | 
			
		||||
          .join(' ')
 | 
			
		||||
      )
 | 
			
		||||
      .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
 | 
			
		||||
    node.intersect = function(point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
    };
 | 
			
		||||
    return shapeSvg;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Add custom shape for box with inverted arrow on right side
 | 
			
		||||
  render.shapes().rect_right_inv_arrow = function (parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width
 | 
			
		||||
    const h = bbox.height
 | 
			
		||||
  render.shapes().rect_right_inv_arrow = function(parent, bbox, node) {
 | 
			
		||||
    const w = bbox.width;
 | 
			
		||||
    const h = bbox.height;
 | 
			
		||||
    const points = [
 | 
			
		||||
      { x: 0, y: 0 },
 | 
			
		||||
      { x: w + h / 2, y: 0 },
 | 
			
		||||
      { x: w, y: -h / 2 },
 | 
			
		||||
      { x: w + h / 2, y: -h },
 | 
			
		||||
      { x: 0, y: -h }
 | 
			
		||||
    ]
 | 
			
		||||
    const shapeSvg = parent.insert('polygon', ':first-child')
 | 
			
		||||
      .attr('points', points.map(function (d) {
 | 
			
		||||
        return d.x + ',' + d.y
 | 
			
		||||
      }).join(' '))
 | 
			
		||||
      .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
 | 
			
		||||
    node.intersect = function (point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point)
 | 
			
		||||
    }
 | 
			
		||||
    return shapeSvg
 | 
			
		||||
  }
 | 
			
		||||
    ];
 | 
			
		||||
    const shapeSvg = parent
 | 
			
		||||
      .insert('polygon', ':first-child')
 | 
			
		||||
      .attr(
 | 
			
		||||
        'points',
 | 
			
		||||
        points
 | 
			
		||||
          .map(function(d) {
 | 
			
		||||
            return d.x + ',' + d.y;
 | 
			
		||||
          })
 | 
			
		||||
          .join(' ')
 | 
			
		||||
      )
 | 
			
		||||
      .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')');
 | 
			
		||||
    node.intersect = function(point) {
 | 
			
		||||
      return dagreD3.intersect.polygon(node, points, point);
 | 
			
		||||
    };
 | 
			
		||||
    return shapeSvg;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Add our custom arrow - an empty arrowhead
 | 
			
		||||
  render.arrows().none = function normal (parent, id, edge, type) {
 | 
			
		||||
    const marker = parent.append('marker')
 | 
			
		||||
  render.arrows().none = function normal(parent, id, edge, type) {
 | 
			
		||||
    const marker = parent
 | 
			
		||||
      .append('marker')
 | 
			
		||||
      .attr('id', id)
 | 
			
		||||
      .attr('viewBox', '0 0 10 10')
 | 
			
		||||
      .attr('refX', 9)
 | 
			
		||||
@@ -477,16 +533,16 @@ export const draw = function (text, id) {
 | 
			
		||||
      .attr('markerUnits', 'strokeWidth')
 | 
			
		||||
      .attr('markerWidth', 8)
 | 
			
		||||
      .attr('markerHeight', 6)
 | 
			
		||||
      .attr('orient', 'auto')
 | 
			
		||||
      .attr('orient', 'auto');
 | 
			
		||||
 | 
			
		||||
    const path = marker.append('path')
 | 
			
		||||
      .attr('d', 'M 0 0 L 0 0 L 0 0 z')
 | 
			
		||||
    dagreD3.util.applyStyle(path, edge[type + 'Style'])
 | 
			
		||||
  }
 | 
			
		||||
    const path = marker.append('path').attr('d', 'M 0 0 L 0 0 L 0 0 z');
 | 
			
		||||
    dagreD3.util.applyStyle(path, edge[type + 'Style']);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Override normal arrowhead defined in d3. Remove style & add class to allow css styling.
 | 
			
		||||
  render.arrows().normal = function normal (parent, id, edge, type) {
 | 
			
		||||
    const marker = parent.append('marker')
 | 
			
		||||
  render.arrows().normal = function normal(parent, id, edge, type) {
 | 
			
		||||
    const marker = parent
 | 
			
		||||
      .append('marker')
 | 
			
		||||
      .attr('id', id)
 | 
			
		||||
      .attr('viewBox', '0 0 10 10')
 | 
			
		||||
      .attr('refX', 9)
 | 
			
		||||
@@ -494,76 +550,76 @@ export const draw = function (text, id) {
 | 
			
		||||
      .attr('markerUnits', 'strokeWidth')
 | 
			
		||||
      .attr('markerWidth', 8)
 | 
			
		||||
      .attr('markerHeight', 6)
 | 
			
		||||
      .attr('orient', 'auto')
 | 
			
		||||
      .attr('orient', 'auto');
 | 
			
		||||
 | 
			
		||||
    marker.append('path')
 | 
			
		||||
    marker
 | 
			
		||||
      .append('path')
 | 
			
		||||
      .attr('d', 'M 0 0 L 10 5 L 0 10 z')
 | 
			
		||||
      .attr('class', 'arrowheadPath')
 | 
			
		||||
      .style('stroke-width', 1)
 | 
			
		||||
      .style('stroke-dasharray', '1,0')
 | 
			
		||||
  }
 | 
			
		||||
      .style('stroke-dasharray', '1,0');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Set up an SVG group so that we can translate the final graph.
 | 
			
		||||
  const svg = d3.select(`[id="${id}"]`)
 | 
			
		||||
  const svg = d3.select(`[id="${id}"]`);
 | 
			
		||||
 | 
			
		||||
  // Run the renderer. This is what draws the final graph.
 | 
			
		||||
  const element = d3.select('#' + id + ' g')
 | 
			
		||||
  render(element, g)
 | 
			
		||||
  const element = d3.select('#' + id + ' g');
 | 
			
		||||
  render(element, g);
 | 
			
		||||
 | 
			
		||||
  element.selectAll('g.node')
 | 
			
		||||
    .attr('title', function () {
 | 
			
		||||
      return flowDb.getTooltip(this.id)
 | 
			
		||||
    })
 | 
			
		||||
  element.selectAll('g.node').attr('title', function() {
 | 
			
		||||
    return flowDb.getTooltip(this.id);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const padding = 8
 | 
			
		||||
  const width = g.maxX - g.minX + padding * 2
 | 
			
		||||
  const height = g.maxY - g.minY + padding * 2
 | 
			
		||||
  svg.attr('width', '100%')
 | 
			
		||||
  svg.attr('style', `max-width: ${width}px;`)
 | 
			
		||||
  svg.attr('viewBox', `0 0 ${width} ${height}`)
 | 
			
		||||
  svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`)
 | 
			
		||||
  const padding = 8;
 | 
			
		||||
  const width = g.maxX - g.minX + padding * 2;
 | 
			
		||||
  const height = g.maxY - g.minY + padding * 2;
 | 
			
		||||
  svg.attr('width', '100%');
 | 
			
		||||
  svg.attr('style', `max-width: ${width}px;`);
 | 
			
		||||
  svg.attr('viewBox', `0 0 ${width} ${height}`);
 | 
			
		||||
  svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`);
 | 
			
		||||
 | 
			
		||||
  // Index nodes
 | 
			
		||||
  flowDb.indexNodes('subGraph' + i)
 | 
			
		||||
  flowDb.indexNodes('subGraph' + i);
 | 
			
		||||
 | 
			
		||||
  // reposition labels
 | 
			
		||||
  for (i = 0; i < subGraphs.length; i++) {
 | 
			
		||||
    subG = subGraphs[i]
 | 
			
		||||
    subG = subGraphs[i];
 | 
			
		||||
 | 
			
		||||
    if (subG.title !== 'undefined') {
 | 
			
		||||
      const clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect')
 | 
			
		||||
      const clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id)
 | 
			
		||||
      const clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect');
 | 
			
		||||
      const clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id);
 | 
			
		||||
 | 
			
		||||
      const xPos = clusterRects[0].x.baseVal.value
 | 
			
		||||
      const yPos = clusterRects[0].y.baseVal.value
 | 
			
		||||
      const width = clusterRects[0].width.baseVal.value
 | 
			
		||||
      const cluster = d3.select(clusterEl[0])
 | 
			
		||||
      const te = cluster.select('.label')
 | 
			
		||||
      te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`)
 | 
			
		||||
      te.attr('id', id + 'Text')
 | 
			
		||||
      const xPos = clusterRects[0].x.baseVal.value;
 | 
			
		||||
      const yPos = clusterRects[0].y.baseVal.value;
 | 
			
		||||
      const width = clusterRects[0].width.baseVal.value;
 | 
			
		||||
      const cluster = d3.select(clusterEl[0]);
 | 
			
		||||
      const te = cluster.select('.label');
 | 
			
		||||
      te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`);
 | 
			
		||||
      te.attr('id', id + 'Text');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Add label rects for non html labels
 | 
			
		||||
  if (!getConfig().flowchart.htmlLabels) {
 | 
			
		||||
    const labels = document.querySelectorAll('#' + id + ' .edgeLabel .label')
 | 
			
		||||
    const labels = document.querySelectorAll('#' + id + ' .edgeLabel .label');
 | 
			
		||||
    for (let k = 0; k < labels.length; k++) {
 | 
			
		||||
      const label = labels[k]
 | 
			
		||||
      const label = labels[k];
 | 
			
		||||
 | 
			
		||||
      // Get dimensions of label
 | 
			
		||||
      const dim = label.getBBox()
 | 
			
		||||
      const dim = label.getBBox();
 | 
			
		||||
 | 
			
		||||
      const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
 | 
			
		||||
      rect.setAttribute('rx', 0)
 | 
			
		||||
      rect.setAttribute('ry', 0)
 | 
			
		||||
      rect.setAttribute('width', dim.width)
 | 
			
		||||
      rect.setAttribute('height', dim.height)
 | 
			
		||||
      rect.setAttribute('style', 'fill:#e8e8e8;')
 | 
			
		||||
      const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
 | 
			
		||||
      rect.setAttribute('rx', 0);
 | 
			
		||||
      rect.setAttribute('ry', 0);
 | 
			
		||||
      rect.setAttribute('width', dim.width);
 | 
			
		||||
      rect.setAttribute('height', dim.height);
 | 
			
		||||
      rect.setAttribute('style', 'fill:#e8e8e8;');
 | 
			
		||||
 | 
			
		||||
      label.insertBefore(rect, label.firstChild)
 | 
			
		||||
      label.insertBefore(rect, label.firstChild);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  setConf,
 | 
			
		||||
@@ -571,4 +627,4 @@ export default {
 | 
			
		||||
  addEdges,
 | 
			
		||||
  getClasses,
 | 
			
		||||
  draw
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,38 +1,37 @@
 | 
			
		||||
import flowDb from '../flowDb'
 | 
			
		||||
import flow from './flow'
 | 
			
		||||
import { setConfig } from '../../../config'
 | 
			
		||||
import flowDb from '../flowDb';
 | 
			
		||||
import flow from './flow';
 | 
			
		||||
import { setConfig } from '../../../config';
 | 
			
		||||
 | 
			
		||||
setConfig({
 | 
			
		||||
  securityLevel: 'strict',
 | 
			
		||||
})
 | 
			
		||||
  securityLevel: 'strict'
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
describe('when parsing flowcharts', function () {
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    flow.parser.yy = flowDb
 | 
			
		||||
    flow.parser.yy.clear()
 | 
			
		||||
  })
 | 
			
		||||
describe('when parsing flowcharts', function() {
 | 
			
		||||
  beforeEach(function() {
 | 
			
		||||
    flow.parser.yy = flowDb;
 | 
			
		||||
    flow.parser.yy.clear();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle chaining of vertices', function () {
 | 
			
		||||
  it('should handle chaining of vertices', function() {
 | 
			
		||||
    const res = flow.parser.parse(`
 | 
			
		||||
    graph TD
 | 
			
		||||
      A-->B-->C;
 | 
			
		||||
    `);
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    expect(vert['A'].id).toBe('A')
 | 
			
		||||
    expect(vert['B'].id).toBe('B')
 | 
			
		||||
    expect(vert['C'].id).toBe('C')
 | 
			
		||||
    expect(edges.length).toBe(2)
 | 
			
		||||
    expect(edges[0].start).toBe('A')
 | 
			
		||||
    expect(edges[0].end).toBe('B')
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
    expect(edges[0].text).toBe('')
 | 
			
		||||
    expect(edges[1].start).toBe('B')
 | 
			
		||||
    expect(edges[1].end).toBe('C')
 | 
			
		||||
    expect(edges[1].type).toBe('arrow')
 | 
			
		||||
    expect(edges[1].text).toBe('')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
    expect(vert['A'].id).toBe('A');
 | 
			
		||||
    expect(vert['B'].id).toBe('B');
 | 
			
		||||
    expect(vert['C'].id).toBe('C');
 | 
			
		||||
    expect(edges.length).toBe(2);
 | 
			
		||||
    expect(edges[0].start).toBe('A');
 | 
			
		||||
    expect(edges[0].end).toBe('B');
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
    expect(edges[0].text).toBe('');
 | 
			
		||||
    expect(edges[1].start).toBe('B');
 | 
			
		||||
    expect(edges[1].end).toBe('C');
 | 
			
		||||
    expect(edges[1].type).toBe('arrow');
 | 
			
		||||
    expect(edges[1].text).toBe('');
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,223 +1,223 @@
 | 
			
		||||
import flowDb from '../flowDb'
 | 
			
		||||
import flow from './flow'
 | 
			
		||||
import { setConfig } from '../../../config'
 | 
			
		||||
import flowDb from '../flowDb';
 | 
			
		||||
import flow from './flow';
 | 
			
		||||
import { setConfig } from '../../../config';
 | 
			
		||||
 | 
			
		||||
setConfig({
 | 
			
		||||
  securityLevel: 'strict',
 | 
			
		||||
})
 | 
			
		||||
  securityLevel: 'strict'
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
describe('when parsing subgraphs', function () {
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    flow.parser.yy = flowDb
 | 
			
		||||
    flow.parser.yy.clear()
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraph with tab indentation', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2\nend')
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2)
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a2')
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a1')
 | 
			
		||||
    expect(subgraph.title).toBe('One')
 | 
			
		||||
    expect(subgraph.id).toBe('One')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraph with chaining nodes indentation', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2-->a3\nend')
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(3)
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a3')
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a2')
 | 
			
		||||
    expect(subgraph.nodes[2]).toBe('a1')
 | 
			
		||||
    expect(subgraph.title).toBe('One')
 | 
			
		||||
    expect(subgraph.id).toBe('One')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraph with multiple words in title', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph "Some Title"\n\ta1-->a2\nend')
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2)
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a2')
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a1')
 | 
			
		||||
    expect(subgraph.title).toBe('Some Title')
 | 
			
		||||
    expect(subgraph.id).toBe('subGraph0')
 | 
			
		||||
describe('when parsing subgraphs', function() {
 | 
			
		||||
  beforeEach(function() {
 | 
			
		||||
    flow.parser.yy = flowDb;
 | 
			
		||||
    flow.parser.yy.clear();
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraph with tab indentation', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2\nend');
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2);
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a2');
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a1');
 | 
			
		||||
    expect(subgraph.title).toBe('One');
 | 
			
		||||
    expect(subgraph.id).toBe('One');
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraph with chaining nodes indentation', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2-->a3\nend');
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(3);
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a3');
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a2');
 | 
			
		||||
    expect(subgraph.nodes[2]).toBe('a1');
 | 
			
		||||
    expect(subgraph.title).toBe('One');
 | 
			
		||||
    expect(subgraph.id).toBe('One');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraph with id and title notation', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph some-id[Some Title]\n\ta1-->a2\nend')
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2)
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a2')
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a1')
 | 
			
		||||
    expect(subgraph.title).toBe('Some Title')
 | 
			
		||||
    expect(subgraph.id).toBe('some-id')
 | 
			
		||||
  it('should handle subgraph with multiple words in title', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph "Some Title"\n\ta1-->a2\nend');
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2);
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a2');
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a1');
 | 
			
		||||
    expect(subgraph.title).toBe('Some Title');
 | 
			
		||||
    expect(subgraph.id).toBe('subGraph0');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  xit('should handle subgraph without id and space in title', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph Some Title\n\ta1-->a2\nend')
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2)
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a1')
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a2')
 | 
			
		||||
    expect(subgraph.title).toBe('Some Title')
 | 
			
		||||
    expect(subgraph.id).toBe('some-id')
 | 
			
		||||
  it('should handle subgraph with id and title notation', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph some-id[Some Title]\n\ta1-->a2\nend');
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2);
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a2');
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a1');
 | 
			
		||||
    expect(subgraph.title).toBe('Some Title');
 | 
			
		||||
    expect(subgraph.id).toBe('some-id');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraph id starting with a number', function () {
 | 
			
		||||
  xit('should handle subgraph without id and space in title', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TB\nsubgraph Some Title\n\ta1-->a2\nend');
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(2);
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('a1');
 | 
			
		||||
    expect(subgraph.nodes[1]).toBe('a2');
 | 
			
		||||
    expect(subgraph.title).toBe('Some Title');
 | 
			
		||||
    expect(subgraph.id).toBe('some-id');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraph id starting with a number', function() {
 | 
			
		||||
    const res = flow.parser.parse(`graph TD
 | 
			
		||||
    A[Christmas] -->|Get money| B(Go shopping)
 | 
			
		||||
    subgraph 1test
 | 
			
		||||
    A
 | 
			
		||||
    end`)
 | 
			
		||||
    end`);
 | 
			
		||||
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(1)
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('A')
 | 
			
		||||
    expect(subgraph.id).toBe('s1test')
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
    expect(subgraph.nodes.length).toBe(1);
 | 
			
		||||
    expect(subgraph.nodes[0]).toBe('A');
 | 
			
		||||
    expect(subgraph.id).toBe('s1test');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraphs1', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph myTitle;c-->d;end;')
 | 
			
		||||
  it('should handle subgraphs1', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph myTitle;c-->d;end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraphs with title in quotes', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph "title in quotes";c-->d;end;')
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraphs with title in quotes', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph "title in quotes";c-->d;end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
 | 
			
		||||
    expect(subgraph.title).toBe('title in quotes')
 | 
			
		||||
    expect(subgraph.title).toBe('title in quotes');
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraphs in old style that was broken', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph old style that is broken;c-->d;end;')
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraphs in old style that was broken', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph old style that is broken;c-->d;end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
 | 
			
		||||
    expect(subgraph.title).toBe('old style that is broken')
 | 
			
		||||
    expect(subgraph.title).toBe('old style that is broken');
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraphs with dashes in the title', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph a-b-c;c-->d;end;')
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraphs with dashes in the title', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph a-b-c;c-->d;end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
 | 
			
		||||
    expect(subgraph.title).toBe('a-b-c')
 | 
			
		||||
    expect(subgraph.title).toBe('a-b-c');
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraphs with id and title in brackets', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph uid1[text of doom];c-->d;end;')
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraphs with id and title in brackets', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph uid1[text of doom];c-->d;end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
 | 
			
		||||
    expect(subgraph.title).toBe('text of doom')
 | 
			
		||||
    expect(subgraph.id).toBe('uid1')
 | 
			
		||||
    expect(subgraph.title).toBe('text of doom');
 | 
			
		||||
    expect(subgraph.id).toBe('uid1');
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraphs with id and title in brackets and quotes', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph uid2["text of doom"];c-->d;end;')
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraphs with id and title in brackets and quotes', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph uid2["text of doom"];c-->d;end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
 | 
			
		||||
    expect(subgraph.title).toBe('text of doom')
 | 
			
		||||
    expect(subgraph.id).toBe('uid2')
 | 
			
		||||
    expect(subgraph.title).toBe('text of doom');
 | 
			
		||||
    expect(subgraph.id).toBe('uid2');
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle subgraphs with id and title in brackets without spaces', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph uid2[textofdoom];c-->d;end;')
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
  it('should handle subgraphs with id and title in brackets without spaces', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD;A-->B;subgraph uid2[textofdoom];c-->d;end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs()
 | 
			
		||||
    expect(subgraphs.length).toBe(1)
 | 
			
		||||
    const subgraph = subgraphs[0]
 | 
			
		||||
    const subgraphs = flow.parser.yy.getSubGraphs();
 | 
			
		||||
    expect(subgraphs.length).toBe(1);
 | 
			
		||||
    const subgraph = subgraphs[0];
 | 
			
		||||
 | 
			
		||||
    expect(subgraph.title).toBe('textofdoom')
 | 
			
		||||
    expect(subgraph.id).toBe('uid2')
 | 
			
		||||
    expect(subgraph.title).toBe('textofdoom');
 | 
			
		||||
    expect(subgraph.id).toBe('uid2');
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraphs2', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\n\n c-->d \nend\n')
 | 
			
		||||
  it('should handle subgraphs2', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\n\n c-->d \nend\n');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle nested subgraphs', function () {
 | 
			
		||||
    const str = 'graph TD\n' +
 | 
			
		||||
            'A-->B\n' +
 | 
			
		||||
            'subgraph myTitle\n\n' +
 | 
			
		||||
            ' c-->d \n\n' +
 | 
			
		||||
            ' subgraph inner\n\n   e-->f \n end \n\n' +
 | 
			
		||||
            ' subgraph inner\n\n   h-->i \n end \n\n' +
 | 
			
		||||
            'end\n'
 | 
			
		||||
    const res = flow.parser.parse(str)
 | 
			
		||||
  })
 | 
			
		||||
  it('should handle nested subgraphs', function() {
 | 
			
		||||
    const str =
 | 
			
		||||
      'graph TD\n' +
 | 
			
		||||
      'A-->B\n' +
 | 
			
		||||
      'subgraph myTitle\n\n' +
 | 
			
		||||
      ' c-->d \n\n' +
 | 
			
		||||
      ' subgraph inner\n\n   e-->f \n end \n\n' +
 | 
			
		||||
      ' subgraph inner\n\n   h-->i \n end \n\n' +
 | 
			
		||||
      'end\n';
 | 
			
		||||
    const res = flow.parser.parse(str);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraphs4', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-->d\nend;')
 | 
			
		||||
  it('should handle subgraphs4', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-->d\nend;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should handle subgraphs5', function () {
 | 
			
		||||
    const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-- text -->d\nd-->e\n end;')
 | 
			
		||||
  it('should handle subgraphs5', function() {
 | 
			
		||||
    const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-- text -->d\nd-->e\n end;');
 | 
			
		||||
 | 
			
		||||
    const vert = flow.parser.yy.getVertices()
 | 
			
		||||
    const edges = flow.parser.yy.getEdges()
 | 
			
		||||
    const vert = flow.parser.yy.getVertices();
 | 
			
		||||
    const edges = flow.parser.yy.getEdges();
 | 
			
		||||
 | 
			
		||||
    expect(edges[0].type).toBe('arrow')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
    expect(edges[0].type).toBe('arrow');
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user