mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-12-04 03:24:13 +01:00
Modernization, better linting, adjustment after stricter static rules
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
var graph = require('./diagrams/flowchart/graphDb');
|
||||
|
||||
var flow = require('./diagrams/flowchart/parser/flow');
|
||||
var utils = require('./utils-es6');
|
||||
var utils = require('./utils');
|
||||
var flowRenderer = require('./diagrams/flowchart/flowRenderer');
|
||||
var seq = require('./diagrams/sequenceDiagram/sequenceRenderer');
|
||||
var info = require('./diagrams/example/exampleRenderer');
|
||||
|
||||
139
src/utils.js
Normal file
139
src/utils.js
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
import * as Log from './logger';
|
||||
var log = Log.create();
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param {string} text The second text defining the graph
|
||||
* @returns {string} A graph definition key
|
||||
*/
|
||||
var detectType = function(text,a){
|
||||
text = text.replace(/^\s*%%.*\n/g,'\n');
|
||||
if(text.match(/^\s*sequenceDiagram/)){
|
||||
return 'sequenceDiagram';
|
||||
}
|
||||
|
||||
if(text.match(/^\s*digraph/)) {
|
||||
//log.debug('Detected dot syntax');
|
||||
return 'dotGraph';
|
||||
}
|
||||
|
||||
if(text.match(/^\s*info/)) {
|
||||
//log.debug('Detected info syntax');
|
||||
return 'info';
|
||||
}
|
||||
|
||||
if(text.match(/^\s*gantt/)) {
|
||||
//log.debug('Detected info syntax');
|
||||
return 'gantt';
|
||||
}
|
||||
|
||||
console.warn('detecting type!');
|
||||
|
||||
return 'graph';
|
||||
};
|
||||
export {detectType};
|
||||
|
||||
/**
|
||||
* Copies all relevant CSS content into the graph SVG.
|
||||
* This allows the SVG to be copied as is while keeping class based styling
|
||||
* @param {element} svg The root element of the SVG
|
||||
* @param {object} Hash table of class definitions from the graph definition
|
||||
*/
|
||||
var cloneCssStyles = function(svg, classes){
|
||||
console.warn('cloneCssStyles ----');
|
||||
var usedStyles = '';
|
||||
var sheets = document.styleSheets;
|
||||
for (var i = 0; i < sheets.length; i++) {
|
||||
// Avoid multiple inclusion on pages with multiple graphs
|
||||
if (sheets[i].title !== 'mermaid-svg-internal-css') {
|
||||
try {
|
||||
|
||||
var rules = sheets[i].cssRules;
|
||||
if (rules !== null) {
|
||||
for (var j = 0; j < rules.length; j++) {
|
||||
var rule = rules[j];
|
||||
if (typeof(rule.style) !== 'undefined') {
|
||||
var elems;
|
||||
elems = svg.querySelectorAll(rule.selectorText);
|
||||
if (elems.length > 0) {
|
||||
usedStyles += rule.selectorText + ' { ' + rule.style.cssText + ' }\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
if(typeof console !== 'undefined'){
|
||||
if(console.warn !== 'undefined'){
|
||||
if(rule !== 'undefined'){
|
||||
console.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var defaultStyles = '';
|
||||
var embeddedStyles = '';
|
||||
|
||||
for (var className in classes) {
|
||||
if (classes.hasOwnProperty(className) && typeof(className) != 'undefined') {
|
||||
if (className === 'default') {
|
||||
if (classes.default.styles instanceof Array) {
|
||||
defaultStyles += '#' + svg.id.trim() + ' .node' + '>rect { ' + classes[className].styles.join('; ') + '; }\n';
|
||||
}
|
||||
if (classes.default.nodeLabelStyles instanceof Array) {
|
||||
defaultStyles += '#' + svg.id.trim() + ' .node text ' + ' { ' + classes[className].nodeLabelStyles.join('; ') + '; }\n';
|
||||
}
|
||||
if (classes.default.edgeLabelStyles instanceof Array) {
|
||||
defaultStyles += '#' + svg.id.trim() + ' .edgeLabel text ' + ' { ' + classes[className].edgeLabelStyles.join('; ') + '; }\n';
|
||||
}
|
||||
if (classes.default.clusterStyles instanceof Array) {
|
||||
defaultStyles += '#' + svg.id.trim() + ' .cluster rect ' + ' { ' + classes[className].clusterStyles.join('; ') + '; }\n';
|
||||
}
|
||||
} else {
|
||||
if (classes[className].styles instanceof Array) {
|
||||
embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect { ' + classes[className].styles.join('; ') + '; }\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usedStyles !== '' || defaultStyles !== '' || embeddedStyles !== '') {
|
||||
var s = document.createElement('style');
|
||||
s.setAttribute('type', 'text/css');
|
||||
s.setAttribute('title', 'mermaid-svg-internal-css');
|
||||
s.innerHTML = '/* <![CDATA[ */\n';
|
||||
// Make this CSS local to this SVG
|
||||
if (defaultStyles !== '') {
|
||||
s.innerHTML += defaultStyles;
|
||||
}
|
||||
if (usedStyles !== '') {
|
||||
s.innerHTML += usedStyles;
|
||||
}
|
||||
if (embeddedStyles !== '') {
|
||||
s.innerHTML += embeddedStyles;
|
||||
}
|
||||
s.innerHTML += '/* ]]> */\n';
|
||||
svg.insertBefore(s, svg.firstChild);
|
||||
}
|
||||
};
|
||||
|
||||
export {cloneCssStyles};
|
||||
183
src/utils.spec.js
Normal file
183
src/utils.spec.js
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
import * as utils from './utils';
|
||||
|
||||
//var log = require('./logger').create();
|
||||
describe('when detecting chart type ', function () {
|
||||
var str;
|
||||
beforeEach(function () {
|
||||
|
||||
});
|
||||
|
||||
it('should handle a graph defintion', function () {
|
||||
str = 'graph TB\nbfs1:queue';
|
||||
|
||||
var type = utils.detectType(str);
|
||||
expect(type).toBe('graph');
|
||||
});
|
||||
it('should handle a graph defintion with leading spaces', function () {
|
||||
str = ' graph TB\nbfs1:queue';
|
||||
|
||||
var type = utils.detectType(str);
|
||||
expect(type).toBe('graph');
|
||||
});
|
||||
|
||||
it('should handle a graph defintion with leading spaces and newline', function () {
|
||||
str = ' \n graph TB\nbfs1:queue';
|
||||
|
||||
var type = utils.detectType(str);
|
||||
expect(type).toBe('graph');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when cloning CSS ', function () {
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
var MockBrowser = require('mock-browser').mocks.MockBrowser;
|
||||
var mock = new MockBrowser();
|
||||
|
||||
// and in the run-code inside some object
|
||||
global.document = mock.getDocument();
|
||||
//document.body.innerHTML = '';
|
||||
//document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
function stylesToArray(svg) {
|
||||
var styleSheets = svg.getElementsByTagName('style');
|
||||
expect(styleSheets.length).toBe(1);
|
||||
var styleSheet = styleSheets[0];
|
||||
|
||||
var innerStyle = styleSheet.innerHTML;
|
||||
var styleArr = innerStyle.split('\n');
|
||||
|
||||
// Remove first and last two lines to remove the CDATA
|
||||
expect(styleArr.length).toBeGreaterThan(2);
|
||||
var styleArrTrim = styleArr.slice(1, -2);
|
||||
|
||||
// Remove all empty lines
|
||||
for (var i = 0; i < styleArrTrim.length; i++) {
|
||||
if (styleArrTrim[i].trim() === '') {
|
||||
styleArrTrim.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return styleArrTrim;
|
||||
}
|
||||
|
||||
function addStyleToDocument() {
|
||||
var s = document.createElement('style');
|
||||
s.innerHTML = '.node { stroke:#eee; }\n.node-square { stroke:#bbb; }\n';
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
|
||||
function addSecondStyleToDocument() {
|
||||
var s = document.createElement('style');
|
||||
s.innerHTML = '.node2 { stroke:#eee; }\n.node-square { stroke:#beb; }\n';
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
|
||||
function generateSVG() {
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-01');
|
||||
var g1 = document.createElement('g');
|
||||
g1.setAttribute('class', 'node');
|
||||
svg.appendChild(g1);
|
||||
var g2 = document.createElement('g');
|
||||
g2.setAttribute('class', 'node-square');
|
||||
svg.appendChild(g2);
|
||||
return svg;
|
||||
}
|
||||
|
||||
function addMermaidSVGwithStyleToDocument() {
|
||||
var styleSheetCount = document.styleSheets.length;
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-03');
|
||||
var s = document.createElement('style');
|
||||
s.setAttribute('type', 'text/css');
|
||||
s.setAttribute('title', 'mermaid-svg-internal-css');
|
||||
s.innerHTML = '#mermaid-05 .node2 { stroke:#eee; }\n.node-square { stroke:#bfe; }\n';
|
||||
svg.appendChild(s);
|
||||
document.body.appendChild(svg);
|
||||
document.styleSheets[styleSheetCount].title = 'mermaid-svg-internal-css';
|
||||
}
|
||||
|
||||
it('should handle an empty set of classes', function () {
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-01');
|
||||
|
||||
utils.cloneCssStyles(svg, {});
|
||||
// Should not create style element if not needed
|
||||
expect(svg.innerHTML).toBe('');
|
||||
});
|
||||
|
||||
it('should handle a default class', function () {
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-01');
|
||||
|
||||
utils.cloneCssStyles(svg, {'default': {'styles': ['stroke:#fff', 'stroke-width:1.5px']}});
|
||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }']);
|
||||
// Also verify the elements around the styling
|
||||
expect(svg.innerHTML).toBe('<style type="text/css" title="mermaid-svg-internal-css">/* <![CDATA[ */\n#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }\n/* ]]> */\n</style>');
|
||||
});
|
||||
|
||||
it('should handle stylesheet in document with no classes in SVG', function () {
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-01');
|
||||
|
||||
addStyleToDocument('mermaid');
|
||||
utils.cloneCssStyles(svg, {});
|
||||
// Should not create style element if not needed
|
||||
expect(svg.innerHTML).toBe('');
|
||||
});
|
||||
|
||||
it('should handle stylesheet in document with classes in SVG', function () {
|
||||
var svg = generateSVG();
|
||||
addStyleToDocument();
|
||||
utils.cloneCssStyles(svg, {});
|
||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: #eee; }', '.node-square { stroke: #bbb; }']);
|
||||
});
|
||||
|
||||
it('should handle multiple stylesheets in document with classes in SVG', function () {
|
||||
var svg = generateSVG();
|
||||
addStyleToDocument();
|
||||
addSecondStyleToDocument();
|
||||
utils.cloneCssStyles(svg, {});
|
||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: #eee; }', '.node-square { stroke: #bbb; }', '.node-square { stroke: #beb; }']);
|
||||
});
|
||||
|
||||
it('should handle multiple stylesheets + ignore styles in other mermaid SVG', function () {
|
||||
var svg = generateSVG();
|
||||
addStyleToDocument();
|
||||
addSecondStyleToDocument();
|
||||
addMermaidSVGwithStyleToDocument();
|
||||
utils.cloneCssStyles(svg, {});
|
||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: #eee; }', '.node-square { stroke: #bbb; }', '.node-square { stroke: #beb; }']);
|
||||
});
|
||||
|
||||
it('should handle a default class together with stylesheet in document with classes in SVG', function () {
|
||||
var svg = generateSVG();
|
||||
addStyleToDocument();
|
||||
utils.cloneCssStyles(svg, {'default': {'styles': ['stroke:#fff', 'stroke-width:1.5px']}});
|
||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }', '.node { stroke: #eee; }', '.node-square { stroke: #bbb; }']);
|
||||
});
|
||||
|
||||
it('should handle a default class together with stylesheet in document and classDefs', function () {
|
||||
var svg = generateSVG();
|
||||
addStyleToDocument();
|
||||
utils.cloneCssStyles(svg, {
|
||||
'default': {'styles': ['stroke:#fff', 'stroke-width:1.5px']},
|
||||
'node-square': {'styles': ['fill:#eee', 'stroke:#aaa']},
|
||||
'node-circle': {'styles': ['fill:#444', 'stroke:#111']}
|
||||
});
|
||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }',
|
||||
'.node { stroke: #eee; }',
|
||||
'.node-square { stroke: #bbb; }',
|
||||
'#mermaid-01 .node-square>rect { fill:#eee; stroke:#aaa; }',
|
||||
'#mermaid-01 .node-circle>rect { fill:#444; stroke:#111; }'
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user