2017-09-09 08:46:58 +02:00
|
|
|
import { Log } from './logger'
|
2015-10-17 10:39:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @function detectType
|
|
|
|
* Detects the type of the graph text.
|
|
|
|
* ```mermaid
|
|
|
|
* graph LR
|
|
|
|
* a-->b
|
|
|
|
* b-->c
|
|
|
|
* c-->d
|
|
|
|
* d-->e
|
|
|
|
* e-->f
|
|
|
|
* f-->g
|
|
|
|
* g-->h
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* @param {string} text The text defining the graph
|
|
|
|
* @returns {string} A graph definition key
|
|
|
|
*/
|
2017-09-09 08:46:58 +02:00
|
|
|
export const detectType = function (text) {
|
2017-04-11 16:14:25 +02:00
|
|
|
text = text.replace(/^\s*%%.*\n/g, '\n')
|
|
|
|
if (text.match(/^\s*sequenceDiagram/)) {
|
|
|
|
return 'sequenceDiagram'
|
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*digraph/)) {
|
|
|
|
return 'dotGraph'
|
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*info/)) {
|
|
|
|
return 'info'
|
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*gantt/)) {
|
|
|
|
return 'gantt'
|
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*classDiagram/)) {
|
2017-09-09 08:46:58 +02:00
|
|
|
Log.debug('Detected classDiagram syntax')
|
2017-04-11 16:14:25 +02:00
|
|
|
return 'classDiagram'
|
|
|
|
}
|
2015-10-30 10:47:25 +01:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (text.match(/^\s*gitGraph/)) {
|
2017-09-09 08:46:58 +02:00
|
|
|
Log.debug('Detected gitGraph syntax')
|
2017-04-11 16:14:25 +02:00
|
|
|
return 'gitGraph'
|
|
|
|
}
|
|
|
|
return 'graph'
|
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Copies all relevant CSS content into the graph SVG.
|
|
|
|
* This allows the SVG to be copied as is while keeping class based styling
|
|
|
|
* @param {element} svg The root element of the SVG
|
|
|
|
* @param {object} Hash table of class definitions from the graph definition
|
|
|
|
*/
|
2017-09-09 08:46:58 +02:00
|
|
|
export const cloneCssStyles = function (svg, classes) {
|
|
|
|
let usedStyles = ''
|
|
|
|
const sheets = document.styleSheets
|
|
|
|
let rule
|
|
|
|
for (let i = 0; i < sheets.length; i++) {
|
2017-04-16 17:24:47 +02:00
|
|
|
// Avoid multiple inclusion on pages with multiple graphs
|
2017-04-11 16:14:25 +02:00
|
|
|
if (sheets[i].title !== 'mermaid-svg-internal-css') {
|
|
|
|
try {
|
2017-09-09 08:46:58 +02:00
|
|
|
const rules = sheets[i].cssRules
|
2017-04-11 16:14:25 +02:00
|
|
|
if (rules !== null) {
|
2017-09-09 08:46:58 +02:00
|
|
|
for (let j = 0; j < rules.length; j++) {
|
2017-04-11 16:14:25 +02:00
|
|
|
rule = rules[j]
|
|
|
|
if (typeof (rule.style) !== 'undefined') {
|
2017-09-09 08:46:58 +02:00
|
|
|
const elems = svg.querySelectorAll(rule.selectorText)
|
2017-04-11 16:14:25 +02:00
|
|
|
if (elems.length > 0) {
|
|
|
|
usedStyles += rule.selectorText + ' { ' + rule.style.cssText + '}\n'
|
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2016-03-29 05:03:38 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
} catch (err) {
|
|
|
|
if (typeof (rule) !== 'undefined') {
|
2017-09-09 08:46:58 +02:00
|
|
|
Log.warn('Invalid CSS selector "' + rule.selectorText + '"', err)
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-09-09 08:46:58 +02:00
|
|
|
let defaultStyles = ''
|
|
|
|
let embeddedStyles = ''
|
|
|
|
for (const className in classes) {
|
2017-04-11 16:14:25 +02:00
|
|
|
if (classes.hasOwnProperty(className) && typeof (className) !== 'undefined') {
|
|
|
|
if (className === 'default') {
|
|
|
|
if (classes.default.styles instanceof Array) {
|
|
|
|
defaultStyles += '#' + svg.id.trim() + ' .node' + '>rect { ' + classes[className].styles.join('; ') + '; }\n'
|
2015-10-17 10:39:20 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
if (classes.default.nodeLabelStyles instanceof Array) {
|
|
|
|
defaultStyles += '#' + svg.id.trim() + ' .node text ' + ' { ' + classes[className].nodeLabelStyles.join('; ') + '; }\n'
|
|
|
|
}
|
|
|
|
if (classes.default.edgeLabelStyles instanceof Array) {
|
|
|
|
defaultStyles += '#' + svg.id.trim() + ' .edgeLabel text ' + ' { ' + classes[className].edgeLabelStyles.join('; ') + '; }\n'
|
2015-10-17 10:39:20 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
if (classes.default.clusterStyles instanceof Array) {
|
|
|
|
defaultStyles += '#' + svg.id.trim() + ' .cluster rect ' + ' { ' + classes[className].clusterStyles.join('; ') + '; }\n'
|
2015-10-17 10:39:20 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
} else {
|
|
|
|
if (classes[className].styles instanceof Array) {
|
|
|
|
embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect, .' + className + '>polygon, .' + className + '>circle, .' + className + '>ellipse { ' + classes[className].styles.join('; ') + '; }\n'
|
2015-10-17 10:39:20 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
}
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2017-04-11 16:14:25 +02:00
|
|
|
if (usedStyles !== '' || defaultStyles !== '' || embeddedStyles !== '') {
|
2017-09-09 08:46:58 +02:00
|
|
|
const s = document.createElement('style')
|
2017-04-11 16:14:25 +02:00
|
|
|
s.setAttribute('type', 'text/css')
|
|
|
|
s.setAttribute('title', 'mermaid-svg-internal-css')
|
|
|
|
s.innerHTML = '/* <![CDATA[ */\n'
|
2017-04-16 17:24:47 +02:00
|
|
|
// Make this CSS local to this SVG
|
2017-04-11 16:14:25 +02:00
|
|
|
if (defaultStyles !== '') {
|
|
|
|
s.innerHTML += defaultStyles
|
|
|
|
}
|
|
|
|
if (usedStyles !== '') {
|
|
|
|
s.innerHTML += usedStyles
|
|
|
|
}
|
|
|
|
if (embeddedStyles !== '') {
|
|
|
|
s.innerHTML += embeddedStyles
|
|
|
|
}
|
|
|
|
s.innerHTML += '/* ]]> */\n'
|
|
|
|
svg.insertBefore(s, svg.firstChild)
|
|
|
|
}
|
|
|
|
}
|
2017-01-07 18:53:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @function isSubstringInArray
|
|
|
|
* Detects whether a substring in present in a given array
|
|
|
|
* @param {string} str The substring to detect
|
|
|
|
* @param {array} arr The array to search
|
|
|
|
* @returns {number} the array index containing the substring or -1 if not present
|
|
|
|
**/
|
2017-09-09 08:46:58 +02:00
|
|
|
export const isSubstringInArray = function (str, arr) {
|
|
|
|
for (let i = 0; i < arr.length; i++) {
|
2017-04-11 16:14:25 +02:00
|
|
|
if (arr[i].match(str)) return i
|
2017-01-07 18:53:49 +01:00
|
|
|
}
|
2017-04-11 16:14:25 +02:00
|
|
|
return -1
|
|
|
|
}
|