Modernization, better linting, adjustment after stricter static rules

This commit is contained in:
knsv
2015-10-17 10:39:20 +02:00
parent 8365fcc2f9
commit 632a564158
7 changed files with 564 additions and 7 deletions

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
**/parser/*.js

231
.eslintrc Normal file
View File

@@ -0,0 +1,231 @@
{
"ecmaFeatures": {
"binaryLiterals": false, // enable binary literals
"blockBindings": false, // enable let and const (aka block bindings)
"defaultParams": false, // enable default function parameters
"forOf": false, // enable for-of loops
"generators": false, // enable generators
"objectLiteralComputedProperties": false, // enable computed object literal property names
"objectLiteralDuplicateProperties": false, // enable duplicate object literal properties in strict mode
"objectLiteralShorthandMethods": false, // enable object literal shorthand methods
"objectLiteralShorthandProperties": false, // enable object literal shorthand properties
"octalLiterals": false, // enable octal literals
"regexUFlag": false, // enable the regular expression u flag
"regexYFlag": false, // enable the regular expression y flag
"templateStrings": false, // enable template strings
"unicodeCodePointEscapes": false, // enable code point escapes
"jsx": false // enable JSX
},
// I want to use babel-eslint for parsing!
"parser": "babel-eslint",
"env": {
// I write for browser
"browser": true,
// in CommonJS
"node": true
},
// To give you an idea how to override rule options:
"rules": {
"quotes": [2, "single"],
"eol-last": [0],
"no-mixed-requires": [0],
"no-underscore-dangle": [0],
"no-alert": 0,
"no-array-constructor": 0,
"no-bitwise": 0,
"no-caller": 0,
"no-catch-shadow": 0,
"no-class-assign": 0,
"no-cond-assign": 2,
"no-console": 2,
"no-const-assign": 0,
"no-constant-condition": 2,
"no-continue": 0,
"no-control-regex": 2,
"no-debugger": 2,
"no-delete-var": 2,
"no-div-regex": 0,
"no-dupe-class-members": 0,
"no-dupe-keys": 2,
"no-dupe-args": 2,
"no-duplicate-case": 2,
"no-else-return": 0,
"no-empty": 2,
"no-empty-character-class": 2,
"no-empty-label": 0,
"no-empty-pattern": 0,
"no-eq-null": 0,
"no-eval": 0,
"no-ex-assign": 2,
"no-extend-native": 0,
"no-extra-bind": 0,
"no-extra-boolean-cast": 2,
"no-extra-parens": 0,
"no-extra-semi": 2,
"no-fallthrough": 2,
"no-floating-decimal": 0,
"no-func-assign": 2,
"no-implicit-coercion": 0,
"no-implied-eval": 0,
"no-inline-comments": 0,
"no-inner-declarations": [2, "functions"],
"no-invalid-regexp": 2,
"no-invalid-this": 0,
"no-irregular-whitespace": 2,
"no-iterator": 0,
"no-label-var": 0,
"no-labels": 0,
"no-lone-blocks": 0,
"no-lonely-if": 0,
"no-loop-func": 0,
"no-mixed-requires": [0, false],
"no-mixed-spaces-and-tabs": [2, false],
"linebreak-style": [0, "unix"],
"no-multi-spaces": 0,
"no-multi-str": 0,
"no-multiple-empty-lines": [0, {"max": 2}],
"no-native-reassign": 0,
"no-negated-condition": 0,
"no-negated-in-lhs": 2,
"no-nested-ternary": 0,
"no-new": 0,
"no-new-func": 0,
"no-new-object": 0,
"no-new-require": 0,
"no-new-wrappers": 0,
"no-obj-calls": 2,
"no-octal": 2,
"no-octal-escape": 0,
"no-param-reassign": 0,
"no-path-concat": 0,
"no-plusplus": 0,
"no-process-env": 0,
"no-process-exit": 0,
"no-proto": 0,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-restricted-modules": 0,
"no-restricted-syntax": 0,
"no-return-assign": 0,
"no-script-url": 0,
"no-self-compare": 0,
"no-sequences": 0,
"no-shadow": 0,
"no-shadow-restricted-names": 0,
"no-spaced-func": 0,
"no-sparse-arrays": 2,
"no-sync": 0,
"no-ternary": 0,
"no-trailing-spaces": 0,
"no-this-before-super": 0,
"no-throw-literal": 0,
"no-undef": 2,
"no-undef-init": 0,
"no-undefined": 0,
"no-unexpected-multiline": 0,
"no-underscore-dangle": 0,
"no-unneeded-ternary": 0,
"no-unreachable": 2,
"no-unused-expressions": 0,
"no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
"no-use-before-define": 0,
"no-useless-call": 0,
"no-useless-concat": 0,
"no-void": 0,
"no-var": 0,
"no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
"no-with": 0,
"no-magic-numbers": 0,
"array-bracket-spacing": [0, "never"],
"arrow-parens": 0,
"arrow-spacing": 0,
"accessor-pairs": 0,
"block-scoped-var": 0,
"block-spacing": 0,
"brace-style": [0, "1tbs"],
"callback-return": 0,
"camelcase": 0,
"comma-dangle": [2, "never"],
"comma-spacing": 0,
"comma-style": 0,
"complexity": [0, 11],
"computed-property-spacing": [0, "never"],
"consistent-return": 0,
"consistent-this": [0, "that"],
"constructor-super": 0,
"curly": [0, "all"],
"default-case": 0,
"dot-location": 0,
"dot-notation": [0, { "allowKeywords": true }],
"eol-last": 0,
"eqeqeq": 0,
"func-names": 0,
"func-style": [0, "declaration"],
"generator-star-spacing": 0,
"global-require": 0,
"guard-for-in": 0,
"handle-callback-err": 0,
"id-length": 0,
"indent": 0,
"init-declarations": 0,
"jsx-quotes": [0, "prefer-double"],
"key-spacing": [0, { "beforeColon": false, "afterColon": true }],
"lines-around-comment": 0,
"max-depth": [0, 4],
"max-len": [0, 80, 4],
"max-nested-callbacks": [0, 2],
"max-params": [0, 3],
"max-statements": [0, 10],
"new-cap": 0,
"new-parens": 0,
"newline-after-var": 0,
"object-curly-spacing": [0, "never"],
"object-shorthand": 0,
"one-var": [0, "always"],
"operator-assignment": [0, "always"],
"operator-linebreak": 0,
"padded-blocks": 0,
"prefer-arrow-callback": 0,
"prefer-const": 0,
"prefer-spread": 0,
"prefer-reflect": 0,
"prefer-template": 0,
"quote-props": 0,
"radix": 0,
"id-match": 0,
"require-jsdoc": 0,
"require-yield": 0,
"semi": 0,
"semi-spacing": [0, {"before": false, "after": true}],
"sort-vars": 0,
"space-after-keywords": [0, "always"],
"space-before-keywords": [0, "always"],
"space-before-blocks": [0, "always"],
"space-before-function-paren": [0, "always"],
"space-in-parens": [0, "never"],
"space-infix-ops": 0,
"space-return-throw-case": 0,
"space-unary-ops": [0, { "words": true, "nonwords": false }],
"spaced-comment": 0,
"strict": 0,
"use-isnan": 2,
"valid-jsdoc": 0,
"valid-typeof": 2,
"vars-on-top": 0,
"wrap-iife": 0,
"wrap-regex": 0,
"yoda": [0, "never"]
},
"globals": {
"it": true,
"describe": true,
"expect": true,
"fit": true,
"beforeEach": true,
"fdescribe": true
}
}

View File

@@ -1,6 +1,6 @@
language: node_js
node_js:
- "0.10"
- "4.1"
addons:
code_climate:
repo_token: e87e6bf1c253e0555437ebd23235fdfe2749b889358e7c6d100e4ea5b4f2e091

View File

@@ -1,6 +1,6 @@
{
"name": "mermaid",
"version": "0.5.3-1",
"version": "0.5.3-2",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams and gantt charts.",
"main": "src/mermaid.js",
"keywords": [
@@ -19,10 +19,10 @@
"watch": "source ./scripts/watch.sh",
"doc": "rm -r build;rm -r dist/www;gulp vartree;cp dist/www/all.html ../mermaid-pages/index.html;cp dist/mermaid.js ../mermaid-pages/javascripts/lib;cp dist/mermaid.forest.css ../mermaid-pages/stylesheets",
"test": "npm run dist && ./node_modules/.bin/gulp test",
"dist-slim-mermaid": "browserify src/mermaid.js -s mermaid -o dist/mermaid.slim.js -x d3 && cat dist/mermaid.slim.js | uglifyjs -mc > dist/mermaid.slim.min.js",
"dist-slim-mermaidAPI": "browserify src/mermaidAPI.js -s mermaidAPI -o dist/mermaidAPI.slim.js -x d3 && cat dist/mermaidAPI.slim.js | uglifyjs -mc > dist/mermaidAPI.slim.min.js",
"dist-mermaid": "browserify src/mermaid.js -s mermaid -o dist/mermaid.js && cat dist/mermaid.js | uglifyjs -mc > dist/mermaid.min.js",
"dist-mermaidAPI": "browserify src/mermaidAPI.js -s mermaidAPI -o dist/mermaidAPI.js && cat dist/mermaidAPI.js | uglifyjs -mc > dist/mermaidAPI.min.js",
"dist-slim-mermaid": "node node_modules/browserify/bin/cmd.js src/mermaid.js -t babelify -s mermaid -o dist/mermaid.slim.js -x d3 && cat dist/mermaid.slim.js | uglifyjs -mc > dist/mermaid.slim.min.js",
"dist-slim-mermaidAPI": "node node_modules/browserify/bin/cmd.js src/mermaidAPI.js -t babelify -s mermaidAPI -o dist/mermaidAPI.slim.js -x d3 && cat dist/mermaidAPI.slim.js | uglifyjs -mc > dist/mermaidAPI.slim.min.js",
"dist-mermaid": "node node_modules/browserify/bin/cmd.js src/mermaid.js -t babelify -s mermaid -o dist/mermaid.js && cat dist/mermaid.js | uglifyjs -mc > dist/mermaid.min.js",
"dist-mermaidAPI": "node node_modules/browserify/bin/cmd.js src/mermaidAPI.js -t babelify -s mermaidAPI -o dist/mermaidAPI.js && cat dist/mermaidAPI.js | uglifyjs -mc > dist/mermaidAPI.min.js",
"dist": "npm run dist-slim-mermaid;npm run dist-slim-mermaidAPI; npm run dist-mermaid;npm run dist-mermaidAPI"
},
"repository": {
@@ -86,6 +86,9 @@
"jison": "~0.4.15",
"jsdom": "^6.5.1",
"jshint-stylish": "^2.0.1",
"karma-babel-preprocessor": "^5.2.2",
"karma-browserify": "^4.4.0",
"karma-chrome-launcher": "^0.2.1",
"map-stream": "0.0.6",
"marked": "^0.3.2",
"mock-browser": "^0.91.34",

View File

@@ -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
View 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
View 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; }'
]);
});
});