mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-26 01:14:09 +02:00
Auto fix standard style voilations
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs')
|
||||
, chalk = require('chalk')
|
||||
, error = chalk.bold.red
|
||||
, cli = require('../lib/cli.js')
|
||||
, lib = require('../lib');
|
||||
var fs = require('fs'),
|
||||
chalk = require('chalk'),
|
||||
error = chalk.bold.red,
|
||||
cli = require('../lib/cli.js'),
|
||||
lib = require('../lib')
|
||||
|
||||
cli.parse(process.argv.slice(2), function (err, message, options) {
|
||||
if (err) {
|
||||
@@ -16,12 +16,11 @@ cli.parse(process.argv.slice(2), function(err, message, options) {
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
else if (message) {
|
||||
} else if (message) {
|
||||
console.log(message)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
lib.process(options.files, options, process.exit)
|
||||
});
|
||||
})
|
||||
|
||||
41
dist/www/javascripts/all.js
vendored
41
dist/www/javascripts/all.js
vendored
File diff suppressed because one or more lines are too long
13
dist/www/javascripts/all_nosearch.js
vendored
13
dist/www/javascripts/all_nosearch.js
vendored
File diff suppressed because one or more lines are too long
2
dist/www/javascripts/highlight.pack.js
vendored
2
dist/www/javascripts/highlight.pack.js
vendored
File diff suppressed because one or more lines are too long
37868
dist/www/javascripts/lib/mermaid.js
vendored
37868
dist/www/javascripts/lib/mermaid.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
294
editor/main.js
294
editor/main.js
File diff suppressed because one or more lines are too long
@@ -1,27 +1,26 @@
|
||||
'use strict';
|
||||
'use strict'
|
||||
|
||||
var Stream = require('stream');
|
||||
var Path = require('path');
|
||||
var Stream = require('stream')
|
||||
var Path = require('path')
|
||||
|
||||
function gulpRename (obj) {
|
||||
|
||||
var stream = new Stream.Transform({objectMode: true});
|
||||
var stream = new Stream.Transform({objectMode: true})
|
||||
|
||||
function parsePath (path) {
|
||||
var extname = Path.extname(path);
|
||||
var extname = Path.extname(path)
|
||||
return {
|
||||
dirname: Path.dirname(path),
|
||||
basename: Path.basename(path, extname),
|
||||
extname: extname
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
stream._transform = function (file, unused, callback) {
|
||||
console.log('a file');
|
||||
callback(null, file);
|
||||
};
|
||||
|
||||
return stream;
|
||||
console.log('a file')
|
||||
callback(null, file)
|
||||
}
|
||||
|
||||
module.exports = gulpRename;
|
||||
return stream
|
||||
}
|
||||
|
||||
module.exports = gulpRename
|
||||
|
||||
@@ -1,36 +1,33 @@
|
||||
/**
|
||||
* Created by knut on 2015-12-26.
|
||||
*/
|
||||
var gulp = require('gulp');
|
||||
var shell = require('gulp-shell');
|
||||
var liveServer = require("live-server");
|
||||
var gulp = require('gulp')
|
||||
var shell = require('gulp-shell')
|
||||
var liveServer = require('live-server')
|
||||
|
||||
var params = {
|
||||
port: 8080, // Set the server port. Defaults to 8080.
|
||||
host: "0.0.0.0", // Set the address to bind to. Defaults to 0.0.0.0.
|
||||
root: "./test/examples", // Set root directory that's being server. Defaults to cwd.
|
||||
host: '0.0.0.0', // Set the address to bind to. Defaults to 0.0.0.0.
|
||||
root: './test/examples', // Set root directory that's being server. Defaults to cwd.
|
||||
open: true, // When false, it won't load your browser by default.
|
||||
ignore: 'scss,my/templates', // comma-separated string for paths to ignore
|
||||
// file: "index.html", // When set, serve this file for every 404 (useful for single-page applications)
|
||||
wait: 1000, // Waits for all changes, before reloading. Defaults to 0 sec.
|
||||
mount: [['/dist', './dist']] // Mount a directory to a route.
|
||||
};
|
||||
}
|
||||
gulp.task('live-server', function () {
|
||||
liveServer.start(params);
|
||||
});
|
||||
|
||||
liveServer.start(params)
|
||||
})
|
||||
|
||||
gulp.task('watch2', ['live-server'], function () {
|
||||
return shell.task([
|
||||
'watchify src/mermaid.js -s mermaid -o dist/mermaid.js',
|
||||
'node node_modules/eslint-watch/bin/esw src -w'
|
||||
]);
|
||||
});
|
||||
|
||||
])
|
||||
})
|
||||
|
||||
// Basic usage
|
||||
gulp.task('watch-mermaid', function () {
|
||||
|
||||
return gulp.src('src/mermaid.js')
|
||||
.pipe(browserify({
|
||||
entry: 'src/mermaid.js',
|
||||
@@ -40,8 +37,8 @@ gulp.task('watch-mermaid',function() {
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
.pipe(uglify())
|
||||
.pipe(extReplace('.min.js'))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
})
|
||||
|
||||
// var bg = require("gulp-bg");
|
||||
//
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
var gulp = require('gulp');
|
||||
var browserify = require('gulp-browserify');
|
||||
var shell = require('gulp-shell');
|
||||
var gulp = require('gulp')
|
||||
var browserify = require('gulp-browserify')
|
||||
var shell = require('gulp-shell')
|
||||
|
||||
|
||||
var concat = require('gulp-concat');
|
||||
var uglify = require('gulp-uglify');
|
||||
var extReplace = require('gulp-ext-replace');
|
||||
var rename = require('gulp-rename');
|
||||
var istanbul = require('gulp-istanbul');
|
||||
var insert = require('gulp-insert');
|
||||
var concat = require('gulp-concat')
|
||||
var uglify = require('gulp-uglify')
|
||||
var extReplace = require('gulp-ext-replace')
|
||||
var rename = require('gulp-rename')
|
||||
var istanbul = require('gulp-istanbul')
|
||||
var insert = require('gulp-insert')
|
||||
|
||||
/**
|
||||
* dist targets
|
||||
@@ -37,20 +36,19 @@ gulp.task('slimDist', function() {
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
.pipe(uglify())
|
||||
.pipe(extReplace('.min.js'))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
})
|
||||
|
||||
// Basic usage
|
||||
gulp.task('fullDist', ['slimDist'], function () {
|
||||
// Single entry point to browserify
|
||||
gulp.src(['node_modules/d3/d3.min.js', 'node_modules/dagre-d3/dist/dagre-d3.min.js', 'dist/mermaid.slim.js'])
|
||||
.pipe(concat('mermaid-legacy.full.js'))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
return gulp.src(['node_modules/d3/d3.min.js', 'node_modules/dagre-d3/dist/dagre-d3.min.js', 'dist/mermaid.slim.min.js'])
|
||||
.pipe(concat('mermaid.full.min.js'))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
})
|
||||
|
||||
// Basic usage
|
||||
// gulp.task('api', shell.task([
|
||||
@@ -63,7 +61,7 @@ gulp.task('fullDist', ['slimDist'], function() {
|
||||
// Basic usage
|
||||
gulp.task('mermaid.slim', function () {
|
||||
// Single entry point to browserify
|
||||
var EXTERNALS = ['d3'];
|
||||
var EXTERNALS = ['d3']
|
||||
|
||||
return gulp.src('src/mermaid.js')
|
||||
.pipe(browserify({
|
||||
@@ -85,12 +83,11 @@ gulp.task('mermaid.slim',function() {
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
.pipe(uglify())
|
||||
.pipe(extReplace('.min.js'))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
})
|
||||
|
||||
// Basic usage
|
||||
gulp.task('mermaid', function () {
|
||||
|
||||
return gulp.src('src/mermaid.js')
|
||||
.pipe(browserify({
|
||||
entry: 'src/mermaid.js',
|
||||
@@ -100,19 +97,19 @@ gulp.task('mermaid',function() {
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
.pipe(uglify())
|
||||
.pipe(extReplace('.min.js'))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
})
|
||||
|
||||
// Basic usage
|
||||
gulp.task('mermaidAPI', function () {
|
||||
return gulp.src('src/mermaidAPI.js')
|
||||
.pipe(browserify({
|
||||
}))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
// .pipe(uglify())
|
||||
// .pipe(extReplace('.min.js'))
|
||||
// .pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
})
|
||||
|
||||
// Basic usage
|
||||
gulp.task('mermaidAPI.slim', function () {
|
||||
@@ -125,8 +122,8 @@ gulp.task('mermaidAPI.slim',function() {
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
.pipe(uglify())
|
||||
.pipe(extReplace('.min.js'))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
})
|
||||
|
||||
// Build editor
|
||||
gulp.task('editor', function () {
|
||||
@@ -136,10 +133,10 @@ gulp.task('editor', function() {
|
||||
.pipe(gulp.dest('./editor/')); */
|
||||
return gulp.src(['node_modules/d3/d3.min.js', 'node_modules/dagre-d3/dist/dagre-d3.min.js', 'dist/mermaid.slim.js', 'src/editor.js'])
|
||||
.pipe(concat('build.js'))
|
||||
.pipe(gulp.dest('./editor/'));
|
||||
});
|
||||
.pipe(gulp.dest('./editor/'))
|
||||
})
|
||||
|
||||
// gulp.task('dist', ['slimDist', 'fullDist','jasmine']);
|
||||
gulp.task('legacy', ['slimDist', 'fullDist']);
|
||||
gulp.task('legacy', ['slimDist', 'fullDist'])
|
||||
|
||||
gulp.task('dist', ['mermaidAPI', 'mermaidAPI.slim','mermaid.slim','mermaid']);
|
||||
gulp.task('dist', ['mermaidAPI', 'mermaidAPI.slim', 'mermaid.slim', 'mermaid'])
|
||||
|
||||
@@ -1,44 +1,43 @@
|
||||
var gulp = require('gulp');
|
||||
var mdvars = require('gulp-mdvars');
|
||||
var vartree = require('gulp-vartree');
|
||||
var gmarked = require('gulp-marked');
|
||||
var marked = require('marked');
|
||||
var concat = require('gulp-concat');
|
||||
var frontMatter = require('gulp-front-matter');
|
||||
var hogan = require('hogan.js');
|
||||
var es = require('event-stream');
|
||||
var fs = require('fs');
|
||||
var gulp = require('gulp')
|
||||
var mdvars = require('gulp-mdvars')
|
||||
var vartree = require('gulp-vartree')
|
||||
var gmarked = require('gulp-marked')
|
||||
var marked = require('marked')
|
||||
var concat = require('gulp-concat')
|
||||
var frontMatter = require('gulp-front-matter')
|
||||
var hogan = require('hogan.js')
|
||||
var es = require('event-stream')
|
||||
var fs = require('fs')
|
||||
|
||||
// Compile a template for rendering each page
|
||||
var template = hogan.compile(String(fs.readFileSync('docs/tpl/slate.html')));
|
||||
var template = hogan.compile(String(fs.readFileSync('docs/tpl/slate.html')))
|
||||
|
||||
var root = {};
|
||||
var filelist = [];
|
||||
var root = {}
|
||||
var filelist = []
|
||||
var iterator = function (obj) {
|
||||
var i;
|
||||
var i
|
||||
for (i = 0; i < obj.childs.length; i++) {
|
||||
var item = obj.childs[i];
|
||||
var item = obj.childs[i]
|
||||
if (item.folder) {
|
||||
iterator(item);
|
||||
iterator(item)
|
||||
} else {
|
||||
console.log(item.path + item.name);
|
||||
filelist.push('build/www' + '/' + item.path + item.name + '.html');
|
||||
console.log(item.path + item.name)
|
||||
filelist.push('build/www' + '/' + item.path + item.name + '.html')
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var renderer = {
|
||||
code: function (code, language) {
|
||||
if (language === 'mermaid') {
|
||||
|
||||
return '<div class="mermaid">' + code + '</div>';
|
||||
return '<div class="mermaid">' + code + '</div>'
|
||||
} else {
|
||||
language='css';
|
||||
return '<pre class="'+language+'"><code>' + code + '</code></pre>';
|
||||
language = 'css'
|
||||
return '<pre class="' + language + '"><code>' + code + '</code></pre>'
|
||||
}
|
||||
}
|
||||
};
|
||||
var filelog = require('gulp-filelog');
|
||||
}
|
||||
var filelog = require('gulp-filelog')
|
||||
|
||||
gulp.task('vartree', ['dox', 'copyContent', 'copySite'], function () {
|
||||
gulp.src(['build/content/**/*.md'])
|
||||
@@ -57,39 +56,37 @@ gulp.task('vartree',['dox','copyContent','copySite'], function() {
|
||||
sanitize: false
|
||||
})) // Do whatever you want with the files later
|
||||
.pipe(gulp.dest('build/www')).on('end', function () {
|
||||
iterator(root);
|
||||
iterator(root)
|
||||
|
||||
// console.log('filelist');
|
||||
// console.log(filelist);
|
||||
gulp.src(filelist)
|
||||
.pipe(concat('all.html'))
|
||||
.pipe(gulp.dest('./build/www')).on('end', function () {
|
||||
filelist.push('build/www' + '/all.html');
|
||||
|
||||
filelist.push('build/www' + '/all.html')
|
||||
|
||||
gulp.src(filelist)
|
||||
.pipe(filelog('html files'))
|
||||
// Run each file through a template
|
||||
.pipe(es.map(function (file, cb) {
|
||||
// console.log('file:',fileList);
|
||||
file.contents = new Buffer(template.render(file));
|
||||
file.contents = new Buffer(template.render(file))
|
||||
|
||||
cb(null, file);
|
||||
cb(null, file)
|
||||
}))
|
||||
// Output to build directory
|
||||
.pipe(gulp.dest('./dist/www'));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
var dox = require('gulp-dox')
|
||||
|
||||
var dox = require("gulp-dox");
|
||||
var doxJson2Md = require('../plugins/doxJson2Md')
|
||||
var map = require('map-stream')
|
||||
var ext_replace = require('gulp-ext-replace')
|
||||
|
||||
var doxJson2Md = require('../plugins/doxJson2Md');
|
||||
var map = require('map-stream');
|
||||
var ext_replace = require('gulp-ext-replace');
|
||||
|
||||
gulp.task("dox",function(){
|
||||
gulp.task('dox', function () {
|
||||
// return gulp.src(['src/**/*.js','!src/**/parser/*.js','!src/**/*.spec.js'])
|
||||
|
||||
return gulp.src(['./src/**/mermaidAPI.js'])
|
||||
@@ -98,51 +95,51 @@ gulp.task("dox",function(){
|
||||
'raw': true
|
||||
}))
|
||||
.pipe(map(function (file, done) {
|
||||
var json = JSON.parse(file.contents.toString());
|
||||
var i;
|
||||
var str = '';
|
||||
var json = JSON.parse(file.contents.toString())
|
||||
var i
|
||||
var str = ''
|
||||
for (i = 0; i < json.length; i++) {
|
||||
// console.log(json[i].description.full);
|
||||
str = str + json[i].description.full + '\n';
|
||||
str = str + json[i].description.full + '\n'
|
||||
}
|
||||
file.contents = new Buffer(str);
|
||||
done(null, file);
|
||||
file.contents = new Buffer(str)
|
||||
done(null, file)
|
||||
}))
|
||||
.pipe(ext_replace('.md'))
|
||||
.pipe(gulp.dest("./build/content"))
|
||||
});
|
||||
.pipe(gulp.dest('./build/content'))
|
||||
})
|
||||
|
||||
gulp.task("copyContent",function() {
|
||||
gulp.task('copyContent', function () {
|
||||
return gulp.src(['./docs/content/**/*.md'])
|
||||
.pipe(gulp.dest("./build/content"));
|
||||
});
|
||||
.pipe(gulp.dest('./build/content'))
|
||||
})
|
||||
|
||||
gulp.task("copyContent",function() {
|
||||
gulp.task('copyContent', function () {
|
||||
return gulp.src(['./docs/content/**/*.md'])
|
||||
.pipe(gulp.dest("./build/content"));
|
||||
});
|
||||
.pipe(gulp.dest('./build/content'))
|
||||
})
|
||||
|
||||
gulp.task("copySite",function() {
|
||||
gulp.task('copySite', function () {
|
||||
gulp.src(['./dist/mermaid.js'])
|
||||
.pipe(filelog())
|
||||
.pipe(gulp.dest("./dist/www/javascripts/lib"));
|
||||
.pipe(gulp.dest('./dist/www/javascripts/lib'))
|
||||
gulp.src(['./docs/site/**/*.css'])
|
||||
.pipe(filelog())
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
gulp.src(['./docs/site/**/*.eot'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
gulp.src(['./docs/site/**/*.svg'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
gulp.src(['./docs/site/**/*.png'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
gulp.src(['./docs/site/**/*.jpg'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
gulp.src(['./docs/site/**/*.ttf'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
gulp.src(['./docs/site/**/*.woff'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
gulp.src(['./docs/site/**/*.woff2'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
return gulp.src(['./docs/site/**/*.js'])
|
||||
.pipe(gulp.dest("./dist/www"));
|
||||
});
|
||||
.pipe(gulp.dest('./dist/www'))
|
||||
})
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
var gulp = require('gulp');
|
||||
var shell = require('gulp-shell');
|
||||
var jison = require('gulp-jison');
|
||||
var filelog = require('gulp-filelog');
|
||||
var gulp = require('gulp')
|
||||
var shell = require('gulp-shell')
|
||||
var jison = require('gulp-jison')
|
||||
var filelog = require('gulp-filelog')
|
||||
|
||||
gulp.task('jison', function () {
|
||||
return gulp.src('./src/**/*.jison')
|
||||
.pipe(filelog('Jison file:'))
|
||||
.pipe(jison({ moduleType: 'commonjs' }))
|
||||
.pipe(gulp.dest('./src/'));
|
||||
});
|
||||
.pipe(gulp.dest('./src/'))
|
||||
})
|
||||
|
||||
gulp.task('jison_legacy', function () {
|
||||
shell.task([
|
||||
@@ -19,6 +19,5 @@ gulp.task('jison_legacy', function(){
|
||||
'node node_modules/jison/lib/cli.js src/diagrams/flowchart/parser/dot.jison -o src/diagrams/flowchart/parser/dot.js',
|
||||
'node node_modules/jison/lib/cli.js src/diagrams/gitGraph/parser/gitGraph.jison -o src/diagrams/gitGraph/parser/gitGraph.js',
|
||||
'node node_modules/jison/lib/cli.js src/diagrams/gantt/parser/gantt.jison -o src/diagrams/gantt/parser/gantt.js'
|
||||
]);
|
||||
});
|
||||
|
||||
])
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
var gulp = require('gulp');
|
||||
var path = require('path');
|
||||
var less = require('gulp-less');
|
||||
var rename = require('gulp-rename');
|
||||
var concat = require('gulp-concat');
|
||||
var gulp = require('gulp')
|
||||
var path = require('path')
|
||||
var less = require('gulp-less')
|
||||
var rename = require('gulp-rename')
|
||||
var concat = require('gulp-concat')
|
||||
|
||||
gulp.task('editor-less', function () {
|
||||
gulp.src(['./editor/css/editor.less'])
|
||||
@@ -11,8 +11,8 @@ gulp.task('editor-less', function () {
|
||||
paths: [ path.join(__dirname, 'less', 'includes') ]
|
||||
}))
|
||||
.pipe(concat('editor.css'))
|
||||
.pipe(gulp.dest('./editor/css/'));
|
||||
});
|
||||
.pipe(gulp.dest('./editor/css/'))
|
||||
})
|
||||
|
||||
gulp.task('mermaid-less', function () {
|
||||
gulp.src(['./src/less/*/mermaid.less'])
|
||||
@@ -22,14 +22,13 @@ gulp.task('mermaid-less', function () {
|
||||
}))
|
||||
.pipe(rename(function (path) {
|
||||
if (path.dirname === 'default') {
|
||||
path.basename = 'mermaid';
|
||||
path.basename = 'mermaid'
|
||||
} else {
|
||||
path.basename = 'mermaid.' + path.dirname;
|
||||
path.basename = 'mermaid.' + path.dirname
|
||||
}
|
||||
path.dirname = '';
|
||||
path.dirname = ''
|
||||
}))
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
.pipe(gulp.dest('./dist/'))
|
||||
})
|
||||
|
||||
|
||||
gulp.task('less',['mermaid-less', 'editor-less']);
|
||||
gulp.task('less', ['mermaid-less', 'editor-less'])
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
var gulp = require('gulp');
|
||||
var bump = require('gulp-bump');
|
||||
var gulp = require('gulp')
|
||||
var bump = require('gulp-bump')
|
||||
|
||||
gulp.task('bump', function () {
|
||||
gulp.src('./bw.json')
|
||||
.pipe(bump({key: "version"}))
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
.pipe(bump({key: 'version'}))
|
||||
.pipe(gulp.dest('./'))
|
||||
})
|
||||
|
||||
// Assuming there's "version: 1.2.3" in package.json,
|
||||
// tag the last commit as "v1.2.3"//
|
||||
gulp.task('tag', function () {
|
||||
return gulp.src(['./package.json']).pipe(tag_version());
|
||||
});
|
||||
return gulp.src(['./package.json']).pipe(tag_version())
|
||||
})
|
||||
|
||||
/**
|
||||
* Bumping version number and tagging the repository with it.
|
||||
@@ -33,7 +33,7 @@ function inc(importance) {
|
||||
// bump the version number in those files
|
||||
.pipe(bump({type: importance}))
|
||||
// save it back to filesystem
|
||||
.pipe(gulp.dest('./'));
|
||||
.pipe(gulp.dest('./'))
|
||||
// commit the changed version number
|
||||
// .pipe(git.commit('bumps package version'))
|
||||
|
||||
@@ -43,6 +43,6 @@ function inc(importance) {
|
||||
// .pipe(tag_version());
|
||||
}
|
||||
|
||||
gulp.task('patch', function() { return inc('patch'); })
|
||||
gulp.task('feature', function() { return inc('minor'); })
|
||||
gulp.task('release', function() { return inc('major'); })
|
||||
gulp.task('patch', function () { return inc('patch') })
|
||||
gulp.task('feature', function () { return inc('minor') })
|
||||
gulp.task('release', function () { return inc('major') })
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
var gulp = require('gulp');
|
||||
var jasmine = require('gulp-jasmine');
|
||||
var gulp = require('gulp');
|
||||
var browserify = require('gulp-browserify');
|
||||
var shell = require('gulp-shell');
|
||||
var jison = require('gulp-jison');
|
||||
var gulp = require('gulp')
|
||||
var jasmine = require('gulp-jasmine')
|
||||
var gulp = require('gulp')
|
||||
var browserify = require('gulp-browserify')
|
||||
var shell = require('gulp-shell')
|
||||
var jison = require('gulp-jison')
|
||||
|
||||
var concat = require('gulp-concat');
|
||||
var uglify = require('gulp-uglify');
|
||||
var extReplace = require('gulp-ext-replace');
|
||||
var rename = require('gulp-rename');
|
||||
var istanbul = require('gulp-istanbul');
|
||||
var insert = require('gulp-insert');
|
||||
var jshint = require('gulp-jshint');
|
||||
var stylish = require('jshint-stylish');
|
||||
var concat = require('gulp-concat')
|
||||
var uglify = require('gulp-uglify')
|
||||
var extReplace = require('gulp-ext-replace')
|
||||
var rename = require('gulp-rename')
|
||||
var istanbul = require('gulp-istanbul')
|
||||
var insert = require('gulp-insert')
|
||||
var jshint = require('gulp-jshint')
|
||||
var stylish = require('jshint-stylish')
|
||||
|
||||
var qunit = require('gulp-qunit');
|
||||
var bower = require('gulp-bower');
|
||||
var qunit = require('gulp-qunit')
|
||||
var bower = require('gulp-bower')
|
||||
|
||||
// Using gulp-jshint and jshint-stylish
|
||||
gulp.task('lint', function () {
|
||||
return gulp.src(['./src/**/*.js', '!**/parser/*.js'])
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter(stylish));
|
||||
});
|
||||
.pipe(jshint.reporter(stylish))
|
||||
})
|
||||
|
||||
gulp.task('test',['coverage','tape','jasmine','qunit']);
|
||||
gulp.task('test', ['coverage', 'tape', 'jasmine', 'qunit'])
|
||||
|
||||
gulp.task('jasmine', ['jison', 'lint'], function () {
|
||||
return gulp.src(['src/**/*.spec.js'])
|
||||
.pipe(jasmine({includeStackTrace:true}));
|
||||
});
|
||||
.pipe(jasmine({includeStackTrace: true}))
|
||||
})
|
||||
|
||||
gulp.task('jas', function () {
|
||||
return gulp.src(['src/**/*.spec.js'])
|
||||
.pipe(jasmine({includeStackTrace:true}));
|
||||
});
|
||||
.pipe(jasmine({includeStackTrace: true}))
|
||||
})
|
||||
|
||||
gulp.task('tape', shell.task(['node_modules/.bin/tape ./test/cli_test-*.js']));
|
||||
gulp.task('tape', shell.task(['node_modules/.bin/tape ./test/cli_test-*.js']))
|
||||
|
||||
gulp.task('coverage', function (cb) {
|
||||
gulp.src(['src/**/*.js', '!src/**/*.spec.js'])
|
||||
@@ -45,24 +45,24 @@ gulp.task('coverage', function (cb) {
|
||||
gulp.src(['src/**/*.spec.js'])
|
||||
.pipe(jasmine())
|
||||
.pipe(istanbul.writeReports()) // Creating the reports after tests runned
|
||||
.on('end', cb);
|
||||
});
|
||||
});
|
||||
.on('end', cb)
|
||||
})
|
||||
})
|
||||
|
||||
gulp.task('qunit', ['usageTestsBower'], function () {
|
||||
return gulp.src('test/usageTests/requireTest.html')
|
||||
.pipe(qunit());
|
||||
});
|
||||
.pipe(qunit())
|
||||
})
|
||||
|
||||
gulp.task('usageTestsBower', function () {
|
||||
return bower({cwd: 'test/usageTests'})
|
||||
.pipe(gulp.dest('test/usageTests/bower_components'));
|
||||
});
|
||||
.pipe(gulp.dest('test/usageTests/bower_components'))
|
||||
})
|
||||
|
||||
var jasmineBrowser = require('gulp-jasmine-browser');
|
||||
var jasmineBrowser = require('gulp-jasmine-browser')
|
||||
|
||||
gulp.task('jasmine2', function () {
|
||||
return gulp.src(['src/**/*.js'])
|
||||
.pipe(jasmineBrowser.specRunner({console: true}))
|
||||
.pipe(jasmineBrowser.headless());
|
||||
});
|
||||
.pipe(jasmineBrowser.headless())
|
||||
})
|
||||
|
||||
28
gulpfile.js
28
gulpfile.js
@@ -1,21 +1,19 @@
|
||||
var gulp = require('gulp');
|
||||
var gulp = require('gulp')
|
||||
|
||||
var shell = require('gulp-shell')
|
||||
var concat = require('gulp-concat')
|
||||
var uglify = require('gulp-uglify')
|
||||
var extReplace = require('gulp-ext-replace')
|
||||
var rename = require('gulp-rename')
|
||||
var istanbul = require('gulp-istanbul')
|
||||
var bump = require('gulp-bump')
|
||||
var tag_version = require('gulp-tag-version')
|
||||
|
||||
var shell = require('gulp-shell');
|
||||
var concat = require('gulp-concat');
|
||||
var uglify = require('gulp-uglify');
|
||||
var extReplace = require('gulp-ext-replace');
|
||||
var rename = require('gulp-rename');
|
||||
var istanbul = require('gulp-istanbul');
|
||||
var bump = require('gulp-bump');
|
||||
var tag_version = require('gulp-tag-version');
|
||||
|
||||
var insert = require('gulp-insert');
|
||||
|
||||
var requireDir = require('require-dir');
|
||||
var tasks = requireDir('./gulp/tasks');
|
||||
var insert = require('gulp-insert')
|
||||
|
||||
var requireDir = require('require-dir')
|
||||
var tasks = requireDir('./gulp/tasks')
|
||||
|
||||
var paths = {
|
||||
scripts: ['./src/**/*.js', '!**/parser/*.js']
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ module.exports = function (config) {
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['browserify', 'jasmine'],
|
||||
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'./src/*.spec.js',
|
||||
@@ -38,36 +37,30 @@ module.exports = function (config) {
|
||||
bundle.on('prebundle', function () {
|
||||
bundle
|
||||
.plugin('proxyquire-universal')
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ['dots'],
|
||||
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: true,
|
||||
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: ['PhantomJS'],
|
||||
@@ -80,5 +73,5 @@ module.exports = function (config) {
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: false
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
41
lib/index.js
41
lib/index.js
@@ -1,7 +1,7 @@
|
||||
var os = require('os')
|
||||
, fs = require('fs')
|
||||
, path = require('path')
|
||||
, spawn = require('child_process').spawn
|
||||
var os = require('os'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
spawn = require('child_process').spawn
|
||||
|
||||
var mkdirp = require('mkdirp')
|
||||
|
||||
@@ -10,22 +10,22 @@ var phantomscript = path.join(__dirname, 'phantomscript.js')
|
||||
module.exports = { process: processMermaid }
|
||||
|
||||
function processMermaid (files, _options, _next) {
|
||||
var options = _options || {}
|
||||
, outputDir = options.outputDir || process.cwd()
|
||||
, outputSuffix = options.outputSuffix || ''
|
||||
, next = _next || function() {}
|
||||
, phantomArgs = [
|
||||
phantomscript
|
||||
, outputDir
|
||||
, options.png
|
||||
, options.svg
|
||||
, options.css
|
||||
, options.sequenceConfig
|
||||
, options.ganttConfig
|
||||
, options.verbose
|
||||
, options.width
|
||||
, outputSuffix
|
||||
];
|
||||
var options = _options || {},
|
||||
outputDir = options.outputDir || process.cwd(),
|
||||
outputSuffix = options.outputSuffix || '',
|
||||
next = _next || function () {},
|
||||
phantomArgs = [
|
||||
phantomscript,
|
||||
outputDir,
|
||||
options.png,
|
||||
options.svg,
|
||||
options.css,
|
||||
options.sequenceConfig,
|
||||
options.ganttConfig,
|
||||
options.verbose,
|
||||
options.width,
|
||||
outputSuffix
|
||||
]
|
||||
|
||||
files.forEach(function (file) {
|
||||
phantomArgs.push(file)
|
||||
@@ -34,7 +34,6 @@ function processMermaid(files, _options, _next) {
|
||||
mkdirp(outputDir, function (err) {
|
||||
if (err) {
|
||||
throw err
|
||||
return
|
||||
}
|
||||
phantom = spawn(options.phantomPath, phantomArgs)
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ phantom.onError = function(msg, trace) {
|
||||
msgStack.push('TRACE:')
|
||||
trace.forEach(function (t) {
|
||||
msgStack.push(
|
||||
' -> '
|
||||
+ (t.file || t.sourceURL)
|
||||
+ ': '
|
||||
+ t.line
|
||||
+ (t.function ? ' (in function ' + t.function +')' : '')
|
||||
' -> ' +
|
||||
(t.file || t.sourceURL) +
|
||||
': ' +
|
||||
t.line +
|
||||
(t.function ? ' (in function ' + t.function + ')' : '')
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -24,58 +24,57 @@ phantom.onError = function(msg, trace) {
|
||||
phantom.exit(1)
|
||||
}
|
||||
|
||||
var system = require('system')
|
||||
, fs = require('fs')
|
||||
, webpage = require('webpage')
|
||||
var system = require('system'),
|
||||
fs = require('fs'),
|
||||
webpage = require('webpage')
|
||||
|
||||
var page = webpage.create()
|
||||
, files = system.args.slice(10, system.args.length)
|
||||
, width = system.args[8]
|
||||
var page = webpage.create(),
|
||||
files = system.args.slice(10, system.args.length),
|
||||
width = system.args[8]
|
||||
|
||||
if (typeof width === 'undefined' || width === 'undefined') {
|
||||
width = 1200;
|
||||
width = 1200
|
||||
}
|
||||
var options = {
|
||||
outputDir: system.args[1]
|
||||
, png: system.args[2] === 'true' ? true : false
|
||||
, svg: system.args[3] === 'true' ? true : false
|
||||
, css: fs.read(system.args[4])
|
||||
, sequenceConfig: system.args[5] !== 'null' ? JSON.parse(fs.read(system.args[5])) : {}
|
||||
, ganttConfig: system.args[6] !== 'null' ? JSON.parse(fs.read(system.args[6])) : {}
|
||||
, verbose: system.args[7] === 'true' ? true : false
|
||||
, width: width
|
||||
, outputSuffix: system.args[9]
|
||||
}
|
||||
, log = logger(options.verbose)
|
||||
options.sequenceConfig.useMaxWidth = false;
|
||||
outputDir: system.args[1],
|
||||
png: system.args[2] === 'true',
|
||||
svg: system.args[3] === 'true',
|
||||
css: fs.read(system.args[4]),
|
||||
sequenceConfig: system.args[5] !== 'null' ? JSON.parse(fs.read(system.args[5])) : {},
|
||||
ganttConfig: system.args[6] !== 'null' ? JSON.parse(fs.read(system.args[6])) : {},
|
||||
verbose: system.args[7] === 'true',
|
||||
width: width,
|
||||
outputSuffix: system.args[9]
|
||||
},
|
||||
log = logger(options.verbose)
|
||||
options.sequenceConfig.useMaxWidth = false
|
||||
|
||||
page.content = [
|
||||
'<html>'
|
||||
, '<head>'
|
||||
, '<style type="text/css">body {background:white;font-family: Arial;}'
|
||||
, options.css
|
||||
, '</style>'
|
||||
, '</head>'
|
||||
, '<body>'
|
||||
, '</body>'
|
||||
, '</html>'
|
||||
'<html>',
|
||||
'<head>',
|
||||
'<style type="text/css">body {background:white;font-family: Arial;}',
|
||||
options.css,
|
||||
'</style>',
|
||||
'</head>',
|
||||
'<body>',
|
||||
'</body>',
|
||||
'</html>'
|
||||
].join('\n')
|
||||
|
||||
|
||||
page.injectJs('../dist/mermaid.js')
|
||||
page.onConsoleMessage = function (msg, lineNum, sourceId) {
|
||||
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
|
||||
};
|
||||
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")')
|
||||
}
|
||||
|
||||
console.log('Num files to execute : ' + files.length)
|
||||
|
||||
files.forEach(function (file) {
|
||||
var contents = fs.read(file)
|
||||
, filename = file.split(fs.separator).slice(-1)
|
||||
, oParser = new DOMParser()
|
||||
, oDOM
|
||||
, svgContent
|
||||
, allElements;
|
||||
var contents = fs.read(file),
|
||||
filename = file.split(fs.separator).slice(-1),
|
||||
oParser = new DOMParser(),
|
||||
oDOM,
|
||||
svgContent,
|
||||
allElements
|
||||
|
||||
console.log('ready to execute png: ' + filename + '.png ')
|
||||
|
||||
@@ -89,7 +88,7 @@ files.forEach(function(file) {
|
||||
confWidth: options.width
|
||||
})
|
||||
|
||||
oDOM = oParser.parseFromString(svgContent, "text/xml")
|
||||
oDOM = oParser.parseFromString(svgContent, 'text/xml')
|
||||
|
||||
resolveSVGElement(oDOM.firstChild)
|
||||
setSVGStyle(oDOM.firstChild, options.css)
|
||||
@@ -101,11 +100,11 @@ files.forEach(function(file) {
|
||||
resolveForeignObjects(allElements[i])
|
||||
}
|
||||
|
||||
var outputPath=options.outputDir + fs.separator + filename + options.outputSuffix;
|
||||
var outputPath = options.outputDir + fs.separator + filename + options.outputSuffix
|
||||
if (options.png) {
|
||||
page.viewportSize = {
|
||||
width: ~~oDOM.documentElement.attributes.getNamedItem('width').value
|
||||
, height: ~~oDOM.documentElement.attributes.getNamedItem('height').value
|
||||
width: ~~oDOM.documentElement.attributes.getNamedItem('width').value,
|
||||
height: ~~oDOM.documentElement.attributes.getNamedItem('height').value
|
||||
}
|
||||
|
||||
page.render(outputPath + '.png')
|
||||
@@ -113,7 +112,7 @@ files.forEach(function(file) {
|
||||
}
|
||||
|
||||
if (options.svg) {
|
||||
var serialize = new XMLSerializer();
|
||||
var serialize = new XMLSerializer()
|
||||
fs.write(outputPath + '.svg'
|
||||
, serialize.serializeToString(oDOM) + '\n'
|
||||
, 'w'
|
||||
@@ -128,9 +127,9 @@ function logger(_verbose) {
|
||||
var verbose = _verbose
|
||||
|
||||
return function (_message, _level) {
|
||||
var level = level
|
||||
, message = _message
|
||||
, log
|
||||
var level = level,
|
||||
message = _message,
|
||||
log
|
||||
|
||||
log = level === 'error' ? system.stderr : system.stdout
|
||||
|
||||
@@ -164,39 +163,39 @@ function traverse(obj){
|
||||
|
||||
function resolveSVGElement (element) {
|
||||
var prefix = {
|
||||
xmlns: "http://www.w3.org/2000/xmlns/"
|
||||
, xlink: "http://www.w3.org/1999/xlink"
|
||||
, svg: "http://www.w3.org/2000/svg"
|
||||
}
|
||||
, doctype = '<!DOCTYPE svg:svg PUBLIC'
|
||||
+ ' "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"'
|
||||
+ ' "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">'
|
||||
xmlns: 'http://www.w3.org/2000/xmlns/',
|
||||
xlink: 'http://www.w3.org/1999/xlink',
|
||||
svg: 'http://www.w3.org/2000/svg'
|
||||
},
|
||||
doctype = '<!DOCTYPE svg:svg PUBLIC' +
|
||||
' "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"' +
|
||||
' "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">'
|
||||
|
||||
element.setAttribute("version", "1.1")
|
||||
element.setAttribute('version', '1.1')
|
||||
// removing attributes so they aren't doubled up
|
||||
element.removeAttribute("xmlns")
|
||||
element.removeAttribute("xlink")
|
||||
element.removeAttribute('xmlns')
|
||||
element.removeAttribute('xlink')
|
||||
// These are needed for the svg
|
||||
if (!element.hasAttributeNS(prefix.xmlns, "xmlns")) {
|
||||
element.setAttributeNS(prefix.xmlns, "xmlns", prefix.svg)
|
||||
if (!element.hasAttributeNS(prefix.xmlns, 'xmlns')) {
|
||||
element.setAttributeNS(prefix.xmlns, 'xmlns', prefix.svg)
|
||||
}
|
||||
if (!element.hasAttributeNS(prefix.xmlns, "xmlns:xlink")) {
|
||||
element.setAttributeNS(prefix.xmlns, "xmlns:xlink", prefix.xlink)
|
||||
if (!element.hasAttributeNS(prefix.xmlns, 'xmlns:xlink')) {
|
||||
element.setAttributeNS(prefix.xmlns, 'xmlns:xlink', prefix.xlink)
|
||||
}
|
||||
}
|
||||
|
||||
function setSVGStyle (svg, css) {
|
||||
if (!css || !svg) { return }
|
||||
var styles=svg.getElementsByTagName('style');
|
||||
var styles = svg.getElementsByTagName('style')
|
||||
if (!styles || styles.length == 0) { return }
|
||||
styles[0].textContent = css;
|
||||
styles[0].textContent = css
|
||||
}
|
||||
|
||||
function resolveForeignObjects (element) {
|
||||
return;
|
||||
var children
|
||||
, textElement
|
||||
, textSpan
|
||||
return
|
||||
var children,
|
||||
textElement,
|
||||
textSpan
|
||||
|
||||
if (element.tagName === 'foreignObject') {
|
||||
textElement = document.createElement('text')
|
||||
@@ -217,19 +216,19 @@ function resolveForeignObjects(element) {
|
||||
|
||||
// The sandboxed function that's executed in-page by phantom
|
||||
function executeInPage (data) {
|
||||
var xmlSerializer = new XMLSerializer()
|
||||
, contents = data.contents
|
||||
, sequenceConfig = JSON.stringify(data.sequenceConfig)
|
||||
, ganttConfig = JSON.stringify(data.ganttConfig).replace(/"(function.*})"/, "$1")
|
||||
, toRemove
|
||||
, el
|
||||
, elContent
|
||||
, svg
|
||||
, svgValue
|
||||
, boundingBox
|
||||
, width
|
||||
, height
|
||||
, confWidth = data.confWidth
|
||||
var xmlSerializer = new XMLSerializer(),
|
||||
contents = data.contents,
|
||||
sequenceConfig = JSON.stringify(data.sequenceConfig),
|
||||
ganttConfig = JSON.stringify(data.ganttConfig).replace(/"(function.*})"/, '$1'),
|
||||
toRemove,
|
||||
el,
|
||||
elContent,
|
||||
svg,
|
||||
svgValue,
|
||||
boundingBox,
|
||||
width,
|
||||
height,
|
||||
confWidth = data.confWidth
|
||||
|
||||
var toRemove = document.getElementsByClassName('mermaid')
|
||||
if (toRemove && toRemove.length) {
|
||||
@@ -238,7 +237,7 @@ function executeInPage(data) {
|
||||
}
|
||||
}
|
||||
|
||||
var el = document.createElement("div")
|
||||
var el = document.createElement('div')
|
||||
el.className = 'mermaid'
|
||||
el.appendChild(document.createTextNode(contents))
|
||||
document.body.appendChild(el)
|
||||
@@ -247,24 +246,23 @@ function executeInPage(data) {
|
||||
sequenceDiagram: JSON.parse(sequenceConfig),
|
||||
flowchart: {useMaxWidth: false},
|
||||
logLevel: 1
|
||||
};
|
||||
}
|
||||
|
||||
mermaid.initialize(config);
|
||||
mermaid.initialize(config)
|
||||
|
||||
var sc = document.createElement("script")
|
||||
var sc = document.createElement('script')
|
||||
sc.appendChild(document.createTextNode('mermaid.ganttConfig = ' + ganttConfig + ';'))
|
||||
document.body.appendChild(sc)
|
||||
|
||||
mermaid.init();
|
||||
mermaid.init()
|
||||
|
||||
svg = document.querySelector('svg')
|
||||
|
||||
boundingBox = svg.getBoundingClientRect(); // the initial bonding box of the svg
|
||||
width = boundingBox.width * 1.5; // adding the scale factor for consistency with output in chrome browser
|
||||
height = boundingBox.height * 1.5; // adding the scale factor for consistency with output in chrome browser
|
||||
boundingBox = svg.getBoundingClientRect() // the initial bonding box of the svg
|
||||
width = boundingBox.width * 1.5 // adding the scale factor for consistency with output in chrome browser
|
||||
height = boundingBox.height * 1.5 // adding the scale factor for consistency with output in chrome browser
|
||||
|
||||
|
||||
var scalefactor = confWidth/(width-8);
|
||||
var scalefactor = confWidth / (width - 8)
|
||||
|
||||
// resizing the body to fit the svg
|
||||
document.body.setAttribute(
|
||||
@@ -287,7 +285,7 @@ function executeInPage(data) {
|
||||
, height * scalefactor
|
||||
)
|
||||
|
||||
svgValue = xmlSerializer.serializeToString(svg)+"\n";
|
||||
svgValue = xmlSerializer.serializeToString(svg) + '\n'
|
||||
// console.log('confWidth: '+document.head.outerHTML);
|
||||
return svgValue
|
||||
}
|
||||
|
||||
272
src/d3.js
vendored
272
src/d3.js
vendored
@@ -1,10 +1,10 @@
|
||||
/* global window */
|
||||
// log.debug('Setting up d3');
|
||||
var d3;
|
||||
var d3
|
||||
|
||||
if (typeof require !== 'undefined') {
|
||||
try {
|
||||
d3 = require('d3');
|
||||
d3 = require('d3')
|
||||
} catch (e) {
|
||||
// log.debug('Exception ... but ok');
|
||||
// log.debug(e);
|
||||
@@ -15,7 +15,7 @@ if (typeof require!=='undefined') {
|
||||
|
||||
if (!d3) {
|
||||
// if(typeof window !== 'undefined')
|
||||
d3 = window.d3;
|
||||
d3 = window.d3
|
||||
}
|
||||
|
||||
// if(typeof window === 'undefined'){
|
||||
@@ -39,64 +39,62 @@ module.exports = d3;
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
// set this variable to a string value to always force a particular
|
||||
// wrap method for development purposes, for example to check tspan
|
||||
// rendering using a foreignobject-enabled browser. set to 'tspan' to
|
||||
// use tspans and 'foreignobject' to use foreignobject
|
||||
var force_wrap_method = false; // by default no wrap method is forced
|
||||
force_wrap_method = 'tspans'; // uncomment this statement to force tspans
|
||||
var force_wrap_method = false // by default no wrap method is forced
|
||||
force_wrap_method = 'tspans' // uncomment this statement to force tspans
|
||||
// force_wrap_method = 'foreignobjects'; // uncomment this statement to force foreignobjects
|
||||
|
||||
// exit immediately if something in this location
|
||||
// has already been defined; the plugin will defer to whatever
|
||||
// else you're doing in your code
|
||||
if (d3.selection.prototype.textwrap) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
// double check the force_wrap_method flag
|
||||
// and reset if someone screwed up the above
|
||||
// settings
|
||||
if(typeof force_wrap_method == 'undefined') {
|
||||
var force_wrap_method = false;
|
||||
if (typeof force_wrap_method === 'undefined') {
|
||||
var force_wrap_method = false
|
||||
}
|
||||
|
||||
// create the plugin method twice, both for regular use
|
||||
// and again for use inside the enter() selection
|
||||
d3.selection.prototype.textwrap = d3.selection.enter.prototype.textwrap = function (bounds, padding) {
|
||||
|
||||
// default value of padding is zero if it's undefined
|
||||
var padding = parseInt(padding) || 0;
|
||||
var padding = parseInt(padding) || 0
|
||||
|
||||
// save callee into a variable so we can continue to refer to it
|
||||
// as the function scope changes
|
||||
var selection = this;
|
||||
var selection = this
|
||||
|
||||
// create a variable to store desired return values in
|
||||
var return_value;
|
||||
var return_value
|
||||
|
||||
// extract wrap boundaries from any d3-selected rect and return them
|
||||
// in a format that matches the simpler object argument option
|
||||
var extract_bounds = function (bounds) {
|
||||
// discard the nested array wrappers added by d3
|
||||
var bounding_rect = bounds[0][0];
|
||||
var bounding_rect = bounds[0][0]
|
||||
// sanitize the svg element name so we can test against it
|
||||
var element_type = bounding_rect.tagName.toString();
|
||||
var element_type = bounding_rect.tagName.toString()
|
||||
// if it's not a rect, exit
|
||||
if (element_type !== 'rect') {
|
||||
return false;
|
||||
return false
|
||||
// if it's a rect, proceed to extracting the position attributes
|
||||
} else {
|
||||
var bounds_extracted = {};
|
||||
bounds_extracted.x = d3.select(bounding_rect).attr('x') || 0;
|
||||
bounds_extracted.y = d3.select(bounding_rect).attr('y') || 0;
|
||||
bounds_extracted.width = d3.select(bounding_rect).attr('width') || 0;
|
||||
bounds_extracted.height = d3.select(bounding_rect).attr('height') || 0;
|
||||
var bounds_extracted = {}
|
||||
bounds_extracted.x = d3.select(bounding_rect).attr('x') || 0
|
||||
bounds_extracted.y = d3.select(bounding_rect).attr('y') || 0
|
||||
bounds_extracted.width = d3.select(bounding_rect).attr('width') || 0
|
||||
bounds_extracted.height = d3.select(bounding_rect).attr('height') || 0
|
||||
// also pass along the getter function
|
||||
bounds_extracted.attr = bounds.attr;
|
||||
bounds_extracted.attr = bounds.attr
|
||||
}
|
||||
return bounds_extracted;
|
||||
return bounds_extracted
|
||||
}
|
||||
|
||||
// double check the input argument for the wrapping
|
||||
@@ -110,14 +108,14 @@ module.exports = d3;
|
||||
if (!bounds.attr) {
|
||||
bounds.attr = function (property) {
|
||||
if (this[property]) {
|
||||
return this[property];
|
||||
return this[property]
|
||||
}
|
||||
}
|
||||
}
|
||||
// if it's an associative array, make sure it has all the
|
||||
// necessary properties represented directly
|
||||
if (
|
||||
(typeof bounds == 'object') &&
|
||||
(typeof bounds === 'object') &&
|
||||
(typeof bounds.x !== 'undefined') &&
|
||||
(typeof bounds.y !== 'undefined') &&
|
||||
(typeof bounds.width !== 'undefined') &&
|
||||
@@ -125,13 +123,13 @@ module.exports = d3;
|
||||
// if that's the case, then the bounds are fine
|
||||
) {
|
||||
// return the lightly modified bounds
|
||||
return bounds;
|
||||
return bounds
|
||||
// if it's a numerically indexed array, assume it's a
|
||||
// d3-selected rect and try to extract the positions
|
||||
} else if (
|
||||
// first try to make sure it's an array using Array.isArray
|
||||
(
|
||||
(typeof Array.isArray == 'function') &&
|
||||
(typeof Array.isArray === 'function') &&
|
||||
(Array.isArray(bounds))
|
||||
) ||
|
||||
// but since Array.isArray isn't always supported, fall
|
||||
@@ -140,33 +138,33 @@ module.exports = d3;
|
||||
) {
|
||||
// once you're sure it's an array, extract the boundaries
|
||||
// from the rect
|
||||
var extracted_bounds = extract_bounds(bounds);
|
||||
return extracted_bounds;
|
||||
var extracted_bounds = extract_bounds(bounds)
|
||||
return extracted_bounds
|
||||
} else {
|
||||
// but if the bounds are neither an object nor a numerical
|
||||
// array, then the bounds argument is invalid and you'll
|
||||
// need to fix it
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var apply_padding = function (bounds, padding) {
|
||||
var padded_bounds = bounds;
|
||||
var padded_bounds = bounds
|
||||
if (padding !== 0) {
|
||||
padded_bounds.x = parseInt(padded_bounds.x) + padding;
|
||||
padded_bounds.y = parseInt(padded_bounds.y) + padding;
|
||||
padded_bounds.width -= padding * 2;
|
||||
padded_bounds.height -= padding * 2;
|
||||
padded_bounds.x = parseInt(padded_bounds.x) + padding
|
||||
padded_bounds.y = parseInt(padded_bounds.y) + padding
|
||||
padded_bounds.width -= padding * 2
|
||||
padded_bounds.height -= padding * 2
|
||||
}
|
||||
return padded_bounds;
|
||||
return padded_bounds
|
||||
}
|
||||
|
||||
// verify bounds
|
||||
var verified_bounds = verify_bounds(bounds);
|
||||
var verified_bounds = verify_bounds(bounds)
|
||||
|
||||
// modify bounds if a padding value is provided
|
||||
if (padding) {
|
||||
verified_bounds = apply_padding(verified_bounds, padding);
|
||||
verified_bounds = apply_padding(verified_bounds, padding)
|
||||
}
|
||||
|
||||
// check that we have the necessary conditions for this function to operate properly
|
||||
@@ -184,42 +182,41 @@ module.exports = d3;
|
||||
// so as not to interfere with methods downstream in the
|
||||
// chain
|
||||
if (selection) {
|
||||
return selection;
|
||||
return selection
|
||||
// if all else fails, just return false. if you hit this point then you're
|
||||
// almost certainly trying to call the textwrap() method on something that
|
||||
// doesn't make sense!
|
||||
} else {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
// if we've validated everything then we can finally proceed
|
||||
// to the meat of this operation
|
||||
} else {
|
||||
|
||||
// reassign the verified bounds as the set we want
|
||||
// to work with from here on; this ensures that we're
|
||||
// using the same data structure for our bounds regardless
|
||||
// of whether the input argument was a simple object or
|
||||
// a d3 selection
|
||||
bounds = verified_bounds;
|
||||
bounds = verified_bounds
|
||||
|
||||
// wrap using html and foreignObjects if they are supported
|
||||
var wrap_with_foreignobjects = function (item) {
|
||||
// establish variables to quickly reference target nodes later
|
||||
var parent = d3.select(item[0].parentNode);
|
||||
var text_node = parent.select('text');
|
||||
var styled_line_height = text_node.style('line-height');
|
||||
var parent = d3.select(item[0].parentNode)
|
||||
var text_node = parent.select('text')
|
||||
var styled_line_height = text_node.style('line-height')
|
||||
// extract our desired content from the single text element
|
||||
var text_to_wrap = text_node.text();
|
||||
var text_to_wrap = text_node.text()
|
||||
// remove the text node and replace with a foreign object
|
||||
text_node.remove();
|
||||
var foreign_object = parent.append('foreignObject');
|
||||
text_node.remove()
|
||||
var foreign_object = parent.append('foreignObject')
|
||||
// add foreign object and set dimensions, position, etc
|
||||
foreign_object
|
||||
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
|
||||
.attr('x', bounds.x)
|
||||
.attr('y', bounds.y)
|
||||
.attr('width', bounds.width)
|
||||
.attr('height', bounds.height);
|
||||
.attr('height', bounds.height)
|
||||
// insert an HTML div
|
||||
var wrap_div = foreign_object
|
||||
.append('xhtml:div')
|
||||
@@ -228,41 +225,40 @@ module.exports = d3;
|
||||
// override using .classed() and for now
|
||||
// it's nice to avoid a litany of input
|
||||
// arguments
|
||||
.attr('class', 'wrapped');
|
||||
.attr('class', 'wrapped')
|
||||
// set div to same dimensions as foreign object
|
||||
wrap_div
|
||||
.style('height', bounds.height)
|
||||
.style('width', bounds.width)
|
||||
// insert text content
|
||||
.html(text_to_wrap);
|
||||
.html(text_to_wrap)
|
||||
if (styled_line_height) {
|
||||
wrap_div.style('line-height', styled_line_height);
|
||||
wrap_div.style('line-height', styled_line_height)
|
||||
}
|
||||
return_value = parent.select('foreignObject');
|
||||
return_value = parent.select('foreignObject')
|
||||
}
|
||||
|
||||
|
||||
// wrap with tspans if foreignObject is undefined
|
||||
var wrap_with_tspans = function (item) {
|
||||
// operate on the first text item in the selection
|
||||
var text_node = item[0];
|
||||
var parent = text_node.parentNode;
|
||||
var text_node_selected = d3.select(text_node);
|
||||
var text_node = item[0]
|
||||
var parent = text_node.parentNode
|
||||
var text_node_selected = d3.select(text_node)
|
||||
// measure initial size of the text node as rendered
|
||||
var text_node_height = text_node.getBBox().height;
|
||||
var text_node_width = text_node.getBBox().width;
|
||||
var text_node_height = text_node.getBBox().height
|
||||
var text_node_width = text_node.getBBox().width
|
||||
// figure out the line height, either from rendered height
|
||||
// of the font or attached styling
|
||||
var line_height;
|
||||
var rendered_line_height = text_node_height;
|
||||
var styled_line_height = text_node_selected.style('line-height');
|
||||
var line_height
|
||||
var rendered_line_height = text_node_height
|
||||
var styled_line_height = text_node_selected.style('line-height')
|
||||
if (
|
||||
(styled_line_height) &&
|
||||
(parseInt(styled_line_height))
|
||||
) {
|
||||
line_height = parseInt(styled_line_height.replace('px', ''));
|
||||
line_height = parseInt(styled_line_height.replace('px', ''))
|
||||
} else {
|
||||
line_height = rendered_line_height;
|
||||
line_height = rendered_line_height
|
||||
}
|
||||
// only fire the rest of this if the text content
|
||||
// overflows the desired dimensions
|
||||
@@ -271,45 +267,45 @@ module.exports = d3;
|
||||
// in a variable and then zero out the
|
||||
// initial content; we'll reinsert in a moment
|
||||
// using tspan elements.
|
||||
var text_to_wrap = text_node_selected.text();
|
||||
text_node_selected.text('');
|
||||
var text_to_wrap = text_node_selected.text()
|
||||
text_node_selected.text('')
|
||||
if (text_to_wrap) {
|
||||
// keep track of whether we are splitting by spaces
|
||||
// so we know whether to reinsert those spaces later
|
||||
var break_delimiter;
|
||||
var break_delimiter
|
||||
// split at spaces to create an array of individual words
|
||||
var text_to_wrap_array;
|
||||
var text_to_wrap_array
|
||||
if (text_to_wrap.indexOf(' ') !== -1) {
|
||||
var break_delimiter = ' ';
|
||||
text_to_wrap_array = text_to_wrap.split(' ');
|
||||
var break_delimiter = ' '
|
||||
text_to_wrap_array = text_to_wrap.split(' ')
|
||||
} else {
|
||||
// if there are no spaces, figure out the split
|
||||
// points by comparing rendered text width against
|
||||
// bounds and translating that into character position
|
||||
// cuts
|
||||
break_delimiter = '';
|
||||
var string_length = text_to_wrap.length;
|
||||
var number_of_substrings = Math.ceil(text_node_width / bounds.width);
|
||||
var splice_interval = Math.floor(string_length / number_of_substrings);
|
||||
break_delimiter = ''
|
||||
var string_length = text_to_wrap.length
|
||||
var number_of_substrings = Math.ceil(text_node_width / bounds.width)
|
||||
var splice_interval = Math.floor(string_length / number_of_substrings)
|
||||
if (
|
||||
!(splice_interval * number_of_substrings >= string_length)
|
||||
) {
|
||||
number_of_substrings++;
|
||||
number_of_substrings++
|
||||
}
|
||||
var text_to_wrap_array = [];
|
||||
var substring;
|
||||
var start_position;
|
||||
var text_to_wrap_array = []
|
||||
var substring
|
||||
var start_position
|
||||
for (var i = 0; i < number_of_substrings; i++) {
|
||||
start_position = i * splice_interval;
|
||||
substring = text_to_wrap.substr(start_position, splice_interval);
|
||||
text_to_wrap_array.push(substring);
|
||||
start_position = i * splice_interval
|
||||
substring = text_to_wrap.substr(start_position, splice_interval)
|
||||
text_to_wrap_array.push(substring)
|
||||
}
|
||||
}
|
||||
|
||||
// new array where we'll store the words re-assembled into
|
||||
// substrings that have been tested against the desired
|
||||
// maximum wrapping width
|
||||
var substrings = [];
|
||||
var substrings = []
|
||||
// computed text length is arguably incorrectly reported for
|
||||
// all tspans after the first one, in that they will include
|
||||
// the width of previous separate tspans. to compensate we need
|
||||
@@ -317,30 +313,30 @@ module.exports = d3;
|
||||
// previous tspans and substrings, and then use that to offset
|
||||
// the miscalculation. this then gives us the actual correct
|
||||
// position we want to use in rendering the text in the SVG.
|
||||
var total_offset = 0;
|
||||
var total_offset = 0
|
||||
// object for storing the results of text length computations later
|
||||
var temp = {};
|
||||
var temp = {}
|
||||
// loop through the words and test the computed text length
|
||||
// of the string against the maximum desired wrapping width
|
||||
for (var i = 0; i < text_to_wrap_array.length; i++) {
|
||||
var word = text_to_wrap_array[i];
|
||||
var previous_string = text_node_selected.text();
|
||||
var previous_width = text_node.getComputedTextLength();
|
||||
var word = text_to_wrap_array[i]
|
||||
var previous_string = text_node_selected.text()
|
||||
var previous_width = text_node.getComputedTextLength()
|
||||
// initialize the current word as the first word
|
||||
// or append to the previous string if one exists
|
||||
var new_string;
|
||||
var new_string
|
||||
if (previous_string) {
|
||||
new_string = previous_string + break_delimiter + word;
|
||||
new_string = previous_string + break_delimiter + word
|
||||
} else {
|
||||
new_string = word;
|
||||
new_string = word
|
||||
}
|
||||
// add the newest substring back to the text node and
|
||||
// measure the length
|
||||
text_node_selected.text(new_string);
|
||||
var new_width = text_node.getComputedTextLength();
|
||||
text_node_selected.text(new_string)
|
||||
var new_width = text_node.getComputedTextLength()
|
||||
// adjust the length by the offset we've tracked
|
||||
// due to the misreported length discussed above
|
||||
var test_width = new_width - total_offset;
|
||||
var test_width = new_width - total_offset
|
||||
// if our latest version of the string is too
|
||||
// big for the bounds, use the previous
|
||||
// version of the string (without the newest word
|
||||
@@ -351,16 +347,16 @@ module.exports = d3;
|
||||
(previous_string) &&
|
||||
(previous_string !== '')
|
||||
) {
|
||||
total_offset = total_offset + previous_width;
|
||||
temp = {string: previous_string, width: previous_width, offset: total_offset};
|
||||
substrings.push(temp);
|
||||
text_node_selected.text('');
|
||||
text_node_selected.text(word);
|
||||
total_offset = total_offset + previous_width
|
||||
temp = {string: previous_string, width: previous_width, offset: total_offset}
|
||||
substrings.push(temp)
|
||||
text_node_selected.text('')
|
||||
text_node_selected.text(word)
|
||||
// Handle case where there is just one more word to be wrapped
|
||||
if (i == text_to_wrap_array.length - 1) {
|
||||
new_string = word;
|
||||
text_node_selected.text(new_string);
|
||||
new_width = text_node.getComputedTextLength();
|
||||
new_string = word
|
||||
text_node_selected.text(new_string)
|
||||
new_width = text_node.getComputedTextLength()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,51 +364,51 @@ module.exports = d3;
|
||||
// get the computed length as is without
|
||||
// appending anything further to it
|
||||
if (i == text_to_wrap_array.length - 1) {
|
||||
text_node_selected.text('');
|
||||
var final_string = new_string;
|
||||
text_node_selected.text('')
|
||||
var final_string = new_string
|
||||
if (
|
||||
(final_string) &&
|
||||
(final_string !== '')
|
||||
) {
|
||||
if ((new_width - total_offset) > 0) { new_width = new_width - total_offset }
|
||||
temp = {string: final_string, width: new_width, offset: total_offset};
|
||||
substrings.push(temp);
|
||||
temp = {string: final_string, width: new_width, offset: total_offset}
|
||||
substrings.push(temp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append each substring as a tspan
|
||||
var current_tspan;
|
||||
var tspan_count;
|
||||
var current_tspan
|
||||
var tspan_count
|
||||
// double check that the text content has been removed
|
||||
// before we start appending tspans
|
||||
text_node_selected.text('');
|
||||
text_node_selected.text('')
|
||||
for (var i = 0; i < substrings.length; i++) {
|
||||
var substring = substrings[i].string;
|
||||
var substring = substrings[i].string
|
||||
if (i > 0) {
|
||||
var previous_substring = substrings[i - 1];
|
||||
var previous_substring = substrings[i - 1]
|
||||
}
|
||||
// only append if we're sure it won't make the tspans
|
||||
// overflow the bounds.
|
||||
if ((i) * line_height < bounds.height - (line_height * 1.5)) {
|
||||
current_tspan = text_node_selected.append('tspan')
|
||||
.text(substring);
|
||||
.text(substring)
|
||||
// vertical shift to all tspans after the first one
|
||||
current_tspan
|
||||
.attr('dy', function (d) {
|
||||
if (i > 0) {
|
||||
return line_height;
|
||||
return line_height
|
||||
}
|
||||
});
|
||||
})
|
||||
// shift left from default position, which
|
||||
// is probably based on the full length of the
|
||||
// text string until we make this adjustment
|
||||
current_tspan
|
||||
.attr('x', function () {
|
||||
var x_offset = bounds.x;
|
||||
if(padding) {x_offset += padding;}
|
||||
return x_offset;
|
||||
});
|
||||
var x_offset = bounds.x
|
||||
if (padding) { x_offset += padding }
|
||||
return x_offset
|
||||
})
|
||||
// .attr('dx', function() {
|
||||
// if(i == 0) {
|
||||
// var render_offset = 0;
|
||||
@@ -428,39 +424,38 @@ module.exports = d3;
|
||||
}
|
||||
// position the overall text node, whether wrapped or not
|
||||
text_node_selected.attr('y', function () {
|
||||
var y_offset = bounds.y;
|
||||
var y_offset = bounds.y
|
||||
// shift by line-height to move the baseline into
|
||||
// the bounds – otherwise the text baseline would be
|
||||
// at the top of the bounds
|
||||
if(line_height) {y_offset += line_height;}
|
||||
if (line_height) { y_offset += line_height }
|
||||
// shift by padding, if it's there
|
||||
if(padding) {y_offset += padding;}
|
||||
return y_offset;
|
||||
});
|
||||
if (padding) { y_offset += padding }
|
||||
return y_offset
|
||||
})
|
||||
// shift to the right by the padding value
|
||||
text_node_selected.attr('x', function () {
|
||||
var x_offset = bounds.x;
|
||||
if(padding) {x_offset += padding;}
|
||||
return x_offset;
|
||||
});
|
||||
|
||||
var x_offset = bounds.x
|
||||
if (padding) { x_offset += padding }
|
||||
return x_offset
|
||||
})
|
||||
|
||||
// assign our modified text node with tspans
|
||||
// to the return value
|
||||
return_value = d3.select(parent).selectAll('text');
|
||||
return_value = d3.select(parent).selectAll('text')
|
||||
}
|
||||
|
||||
// variable used to hold the functions that let us
|
||||
// switch between the wrap methods
|
||||
var wrap_method;
|
||||
var wrap_method
|
||||
|
||||
// if a wrap method if being forced, assign that
|
||||
// function
|
||||
if (force_wrap_method) {
|
||||
if (force_wrap_method == 'foreignobjects') {
|
||||
wrap_method = wrap_with_foreignobjects;
|
||||
wrap_method = wrap_with_foreignobjects
|
||||
} else if (force_wrap_method == 'tspans') {
|
||||
wrap_method = wrap_with_tspans;
|
||||
wrap_method = wrap_with_tspans
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,26 +464,23 @@ module.exports = d3;
|
||||
// use whichever wrap method makes sense accordingly
|
||||
if (!force_wrap_method) {
|
||||
if (typeof SVGForeignObjectElement !== 'undefined') {
|
||||
wrap_method = wrap_with_foreignobjects;
|
||||
wrap_method = wrap_with_foreignobjects
|
||||
} else {
|
||||
wrap_method = wrap_with_tspans;
|
||||
wrap_method = wrap_with_tspans
|
||||
}
|
||||
}
|
||||
|
||||
// run the desired wrap function for each item
|
||||
// in the d3 selection that called .textwrap()
|
||||
for (var i = 0; i < selection.length; i++) {
|
||||
var item = selection[i];
|
||||
wrap_method(item);
|
||||
var item = selection[i]
|
||||
wrap_method(item)
|
||||
}
|
||||
|
||||
// return the modified nodes so we can chain other
|
||||
// methods to them.
|
||||
return return_value;
|
||||
|
||||
return return_value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
})()
|
||||
/* jshint ignore:end */
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var relations = [];
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
var relations = []
|
||||
|
||||
var classes;
|
||||
var idCache;
|
||||
var classes
|
||||
var idCache
|
||||
classes = {
|
||||
};
|
||||
}
|
||||
|
||||
// Functions to be run after graph rendering
|
||||
var funs = [];
|
||||
var funs = []
|
||||
/**
|
||||
* Function called by parser when a node definition has been found.
|
||||
* @param id
|
||||
@@ -23,64 +23,61 @@ exports.addClass = function (id) {
|
||||
id: id,
|
||||
methods: [],
|
||||
members: []
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
exports.clear = function () {
|
||||
relations = [];
|
||||
classes = {};
|
||||
};
|
||||
relations = []
|
||||
classes = {}
|
||||
}
|
||||
|
||||
module.exports.getClass = function (id) {
|
||||
return classes[id];
|
||||
};
|
||||
return classes[id]
|
||||
}
|
||||
module.exports.getClasses = function () {
|
||||
return classes;
|
||||
};
|
||||
return classes
|
||||
}
|
||||
|
||||
module.exports.getRelations = function () {
|
||||
return relations;
|
||||
};
|
||||
return relations
|
||||
}
|
||||
|
||||
exports.addRelation = function (relation) {
|
||||
log.warn('Adding relation: ' + JSON.stringify(relation));
|
||||
exports.addClass(relation.id1);
|
||||
exports.addClass(relation.id2);
|
||||
log.warn('Adding relation: ' + JSON.stringify(relation))
|
||||
exports.addClass(relation.id1)
|
||||
exports.addClass(relation.id2)
|
||||
|
||||
relations.push(relation);
|
||||
};
|
||||
relations.push(relation)
|
||||
}
|
||||
|
||||
exports.addMembers = function (className, MembersArr) {
|
||||
var theClass = classes[className];
|
||||
var theClass = classes[className]
|
||||
if (typeof MembersArr === 'string') {
|
||||
if (MembersArr.substr(-1) === ')') {
|
||||
theClass.methods.push(MembersArr);
|
||||
}
|
||||
else{
|
||||
theClass.members.push(MembersArr);
|
||||
theClass.methods.push(MembersArr)
|
||||
} else {
|
||||
theClass.members.push(MembersArr)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.cleanupLabel = function (label) {
|
||||
|
||||
if (label.substring(0, 1) === ':') {
|
||||
return label.substr(2).trim();
|
||||
return label.substr(2).trim()
|
||||
} else {
|
||||
return label.trim()
|
||||
}
|
||||
else{
|
||||
return label.trim();
|
||||
}
|
||||
};
|
||||
|
||||
exports.lineType = {
|
||||
LINE: 0,
|
||||
DOTTED_LINE: 1
|
||||
};
|
||||
}
|
||||
|
||||
exports.relationType = {
|
||||
AGGREGATION: 0,
|
||||
EXTENSION: 1,
|
||||
COMPOSITION: 2,
|
||||
DEPENDENCY: 3
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
*/
|
||||
describe('class diagram, ', function () {
|
||||
describe('when parsing an info graph it', function () {
|
||||
var cd, cDDb;
|
||||
var cd, cDDb
|
||||
beforeEach(function () {
|
||||
cd = require('./parser/classDiagram').parser;
|
||||
cDDb = require('./classDb');
|
||||
cd.yy = cDDb;
|
||||
});
|
||||
cd = require('./parser/classDiagram').parser
|
||||
cDDb = require('./classDb')
|
||||
cd.yy = cDDb
|
||||
})
|
||||
|
||||
it('should handle relation definitions', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
@@ -16,48 +16,48 @@ describe('class diagram, ', function () {
|
||||
'Class03 *-- Class04\n' +
|
||||
'Class05 o-- Class06\n' +
|
||||
'Class07 .. Class08\n' +
|
||||
'Class09 -- Class1';
|
||||
'Class09 -- Class1'
|
||||
|
||||
cd.parse(str);
|
||||
});
|
||||
cd.parse(str)
|
||||
})
|
||||
it('should handle relation definition of different types and directions', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class11 <|.. Class12\n' +
|
||||
'Class13 --> Class14\n' +
|
||||
'Class15 ..> Class16\n' +
|
||||
'Class17 ..|> Class18\n' +
|
||||
'Class19 <--* Class20';
|
||||
'Class19 <--* Class20'
|
||||
|
||||
cd.parse(str);
|
||||
});
|
||||
cd.parse(str)
|
||||
})
|
||||
|
||||
it('should handle cardinality and labels', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class01 "1" *-- "many" Class02 : contains\n' +
|
||||
'Class03 o-- Class04 : aggregation\n' +
|
||||
'Class05 --> "1" Class06';
|
||||
'Class05 --> "1" Class06'
|
||||
|
||||
cd.parse(str);
|
||||
});
|
||||
cd.parse(str)
|
||||
})
|
||||
it('should handle class definitions', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'class Car\n' +
|
||||
'Driver -- Car : drives >\n' +
|
||||
'Car *-- Wheel : have 4 >\n' +
|
||||
'Car -- Person : < owns';
|
||||
'Car -- Person : < owns'
|
||||
|
||||
cd.parse(str);
|
||||
});
|
||||
cd.parse(str)
|
||||
})
|
||||
|
||||
it('should handle method statements', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Object <|-- ArrayList\n' +
|
||||
'Object : equals()\n' +
|
||||
'ArrayList : Object[] elementData\n' +
|
||||
'ArrayList : size()';
|
||||
'ArrayList : size()'
|
||||
|
||||
cd.parse(str);
|
||||
});
|
||||
cd.parse(str)
|
||||
})
|
||||
it('should handle parsing of method statements grouped by brackets', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'class Dummy {\n' +
|
||||
@@ -68,10 +68,10 @@ describe('class diagram, ', function () {
|
||||
'class Flight {\n' +
|
||||
' flightNumber : Integer\n' +
|
||||
' departureTime : Date\n' +
|
||||
'}';
|
||||
'}'
|
||||
|
||||
cd.parse(str);
|
||||
});
|
||||
cd.parse(str)
|
||||
})
|
||||
|
||||
it('should handle parsing of separators', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
@@ -100,91 +100,90 @@ describe('class diagram, ', function () {
|
||||
'int age\n' +
|
||||
'-- encrypted --\n' +
|
||||
'String password\n' +
|
||||
'}';
|
||||
'}'
|
||||
|
||||
cd.parse(str);
|
||||
});
|
||||
|
||||
});
|
||||
cd.parse(str)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when fetching data from an classDiagram graph it', function () {
|
||||
var cd, cDDb;
|
||||
var cd, cDDb
|
||||
beforeEach(function () {
|
||||
cd = require('./parser/classDiagram').parser;
|
||||
cDDb = require('./classDb');
|
||||
cd.yy = cDDb;
|
||||
cd.yy.clear();
|
||||
});
|
||||
cd = require('./parser/classDiagram').parser
|
||||
cDDb = require('./classDb')
|
||||
cd.yy = cDDb
|
||||
cd.yy.clear()
|
||||
})
|
||||
it('should handle relation definitions EXTENSION', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class01 <|-- Class02';
|
||||
'Class01 <|-- Class02'
|
||||
|
||||
cd.parse(str);
|
||||
cd.parse(str)
|
||||
|
||||
var relations = cd.yy.getRelations();
|
||||
var relations = cd.yy.getRelations()
|
||||
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01');
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
|
||||
});
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01')
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02')
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION)
|
||||
expect(relations[0].relation.type2).toBe('none')
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
|
||||
})
|
||||
it('should handle relation definitions AGGREGATION and dotted line', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class01 o.. Class02';
|
||||
'Class01 o.. Class02'
|
||||
|
||||
cd.parse(str);
|
||||
cd.parse(str)
|
||||
|
||||
var relations = cd.yy.getRelations();
|
||||
var relations = cd.yy.getRelations()
|
||||
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01');
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.AGGREGATION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE);
|
||||
});
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01')
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02')
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.AGGREGATION)
|
||||
expect(relations[0].relation.type2).toBe('none')
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE)
|
||||
})
|
||||
it('should handle relation definitions COMPOSITION on both sides', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class01 *--* Class02';
|
||||
'Class01 *--* Class02'
|
||||
|
||||
cd.parse(str);
|
||||
cd.parse(str)
|
||||
|
||||
var relations = cd.yy.getRelations();
|
||||
var relations = cd.yy.getRelations()
|
||||
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01');
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.COMPOSITION);
|
||||
expect(relations[0].relation.type2).toBe(cDDb.relationType.COMPOSITION);
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
|
||||
});
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01')
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02')
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.COMPOSITION)
|
||||
expect(relations[0].relation.type2).toBe(cDDb.relationType.COMPOSITION)
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
|
||||
})
|
||||
it('should handle relation definitions no types', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class01 -- Class02';
|
||||
'Class01 -- Class02'
|
||||
|
||||
cd.parse(str);
|
||||
cd.parse(str)
|
||||
|
||||
var relations = cd.yy.getRelations();
|
||||
var relations = cd.yy.getRelations()
|
||||
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01');
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe('none');
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
|
||||
});
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01')
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02')
|
||||
expect(relations[0].relation.type1).toBe('none')
|
||||
expect(relations[0].relation.type2).toBe('none')
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
|
||||
})
|
||||
it('should handle relation definitions with type only on right side', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class01 --|> Class02';
|
||||
'Class01 --|> Class02'
|
||||
|
||||
cd.parse(str);
|
||||
cd.parse(str)
|
||||
|
||||
var relations = cd.yy.getRelations();
|
||||
var relations = cd.yy.getRelations()
|
||||
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01');
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02');
|
||||
expect(relations[0].relation.type1).toBe('none');
|
||||
expect(relations[0].relation.type2).toBe(cDDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
|
||||
});
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01')
|
||||
expect(cd.yy.getClass('Class02').id).toBe('Class02')
|
||||
expect(relations[0].relation.type1).toBe('none')
|
||||
expect(relations[0].relation.type2).toBe(cDDb.relationType.EXTENSION)
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
|
||||
})
|
||||
|
||||
it('should handle multiple classes and relation definitions', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
@@ -192,23 +191,23 @@ describe('class diagram, ', function () {
|
||||
'Class03 *-- Class04\n' +
|
||||
'Class05 o-- Class06\n' +
|
||||
'Class07 .. Class08\n' +
|
||||
'Class09 -- Class10';
|
||||
'Class09 -- Class10'
|
||||
|
||||
cd.parse(str);
|
||||
cd.parse(str)
|
||||
|
||||
var relations = cd.yy.getRelations();
|
||||
var relations = cd.yy.getRelations()
|
||||
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01');
|
||||
expect(cd.yy.getClass('Class10').id).toBe('Class10');
|
||||
expect(cd.yy.getClass('Class01').id).toBe('Class01')
|
||||
expect(cd.yy.getClass('Class10').id).toBe('Class10')
|
||||
|
||||
expect(relations.length).toBe(5);
|
||||
expect(relations.length).toBe(5)
|
||||
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION);
|
||||
expect(relations[0].relation.type2).toBe('none');
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
|
||||
expect(relations[3].relation.type1).toBe('none');
|
||||
expect(relations[3].relation.type2).toBe('none');
|
||||
expect(relations[3].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE);
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION)
|
||||
expect(relations[0].relation.type2).toBe('none')
|
||||
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE)
|
||||
expect(relations[3].relation.type1).toBe('none')
|
||||
expect(relations[3].relation.type2).toBe('none')
|
||||
expect(relations[3].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,36 +2,36 @@
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
|
||||
var cd = require('./parser/classDiagram').parser;
|
||||
var cDDb = require('./classDb');
|
||||
cd.yy = cDDb;
|
||||
var d3 = require('../../d3');
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var dagre = require('dagre');
|
||||
var cd = require('./parser/classDiagram').parser
|
||||
var cDDb = require('./classDb')
|
||||
cd.yy = cDDb
|
||||
var d3 = require('../../d3')
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
var dagre = require('dagre')
|
||||
|
||||
var idCache;
|
||||
idCache = {};
|
||||
var idCache
|
||||
idCache = {}
|
||||
|
||||
var classCnt = 0;
|
||||
var classCnt = 0
|
||||
var conf = {
|
||||
dividerMargin: 10,
|
||||
padding: 5,
|
||||
textHeight: 14
|
||||
};
|
||||
}
|
||||
|
||||
// Todo optimize
|
||||
var getGraphId = function (label) {
|
||||
var keys = Object.keys(idCache);
|
||||
var keys = Object.keys(idCache)
|
||||
|
||||
var i;
|
||||
var i
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
if (idCache[keys[i]].label === label) {
|
||||
return keys[i];
|
||||
return keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return undefined
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,7 +47,7 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 240)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 1,7 L18,13 V 1 Z');
|
||||
.attr('d', 'M 1,7 L18,13 V 1 Z')
|
||||
|
||||
elem.append('defs').append('marker')
|
||||
.attr('id', 'extensionEnd')
|
||||
@@ -57,7 +57,7 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 28)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 1,1 V 13 L18,7 Z'); //this is actual shape for arrowhead
|
||||
.attr('d', 'M 1,1 V 13 L18,7 Z') // this is actual shape for arrowhead
|
||||
|
||||
elem.append('defs').append('marker')
|
||||
.attr('id', 'compositionStart')
|
||||
@@ -68,7 +68,7 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 240)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
|
||||
|
||||
elem.append('defs').append('marker')
|
||||
.attr('id', 'compositionEnd')
|
||||
@@ -78,8 +78,7 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 28)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||||
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
|
||||
|
||||
elem.append('defs').append('marker')
|
||||
.attr('id', 'aggregationStart')
|
||||
@@ -90,7 +89,7 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 240)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
|
||||
|
||||
elem.append('defs').append('marker')
|
||||
.attr('id', 'aggregationEnd')
|
||||
@@ -100,7 +99,7 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 28)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||||
.attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z')
|
||||
|
||||
elem.append('defs').append('marker')
|
||||
.attr('id', 'dependencyStart')
|
||||
@@ -111,7 +110,7 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 240)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 5,7 L9,13 L1,7 L9,1 Z');
|
||||
.attr('d', 'M 5,7 L9,13 L1,7 L9,1 Z')
|
||||
|
||||
elem.append('defs').append('marker')
|
||||
.attr('id', 'dependencyEnd')
|
||||
@@ -121,253 +120,245 @@ var insertMarkers = function (elem) {
|
||||
.attr('markerHeight', 28)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
|
||||
};
|
||||
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z')
|
||||
}
|
||||
|
||||
var edgeCount = 0;
|
||||
var edgeCount = 0
|
||||
var drawEdge = function (elem, path, relation) {
|
||||
var getRelationType = function (type) {
|
||||
switch (type) {
|
||||
case cDDb.relationType.AGGREGATION:
|
||||
return 'aggregation';
|
||||
return 'aggregation'
|
||||
case cDDb.relationType.EXTENSION:
|
||||
return 'extension';
|
||||
return 'extension'
|
||||
case cDDb.relationType.COMPOSITION:
|
||||
return 'composition';
|
||||
return 'composition'
|
||||
case cDDb.relationType.DEPENDENCY:
|
||||
return 'dependency';
|
||||
return 'dependency'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// The data for our line
|
||||
var lineData = path.points;
|
||||
var lineData = path.points
|
||||
|
||||
// This is the accessor function we talked about above
|
||||
var lineFunction = d3.svg.line()
|
||||
.x(function (d) {
|
||||
return d.x;
|
||||
return d.x
|
||||
})
|
||||
.y(function (d) {
|
||||
return d.y;
|
||||
return d.y
|
||||
})
|
||||
// .interpolate('cardinal');
|
||||
.interpolate('basis');
|
||||
.interpolate('basis')
|
||||
|
||||
var svgPath = elem.append('path')
|
||||
.attr('d', lineFunction(lineData))
|
||||
.attr('id', 'edge' + edgeCount)
|
||||
.attr('class', 'relation');
|
||||
var url = '';
|
||||
.attr('class', 'relation')
|
||||
var url = ''
|
||||
if (conf.arrowMarkerAbsolute) {
|
||||
url = window.location.protocol+'//'+window.location.host+window.location.pathname +window.location.search;
|
||||
url = url.replace(/\(/g,'\\(');
|
||||
url = url.replace(/\)/g,'\\)');
|
||||
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search
|
||||
url = url.replace(/\(/g, '\\(')
|
||||
url = url.replace(/\)/g, '\\)')
|
||||
}
|
||||
|
||||
// console.log(relation.relation.type1);
|
||||
if (relation.relation.type1 !== 'none') {
|
||||
svgPath.attr('marker-start', 'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')');
|
||||
svgPath.attr('marker-start', 'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')')
|
||||
}
|
||||
if (relation.relation.type2 !== 'none') {
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')');
|
||||
svgPath.attr('marker-end', 'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')')
|
||||
}
|
||||
|
||||
// var bbox = svgPath[0][0].getBBox();
|
||||
// var x = Math.floor(bbox.x + bbox.width/2.0);
|
||||
// var y = Math.floor(bbox.y + bbox.height/2.0);
|
||||
var x, y;
|
||||
var l = path.points.length;
|
||||
var x, y
|
||||
var l = path.points.length
|
||||
if ((l % 2) !== 0) {
|
||||
var p1 = path.points[Math.floor(l / 2)];
|
||||
var p2 = path.points[Math.ceil(l / 2)];
|
||||
x = (p1.x + p2.x) / 2;
|
||||
y = (p1.y + p2.y) / 2;
|
||||
}
|
||||
else {
|
||||
var p = path.points[Math.floor(l / 2)];
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
var p1 = path.points[Math.floor(l / 2)]
|
||||
var p2 = path.points[Math.ceil(l / 2)]
|
||||
x = (p1.x + p2.x) / 2
|
||||
y = (p1.y + p2.y) / 2
|
||||
} else {
|
||||
var p = path.points[Math.floor(l / 2)]
|
||||
x = p.x
|
||||
y = p.y
|
||||
}
|
||||
|
||||
if (typeof relation.title !== 'undefined') {
|
||||
var g = elem.append('g').
|
||||
attr('class','classLabel');
|
||||
var g = elem.append('g')
|
||||
.attr('class', 'classLabel')
|
||||
var label = g.append('text')
|
||||
.attr('class', 'label')
|
||||
.attr('x', x)
|
||||
.attr('y', y)
|
||||
.attr('fill', 'red')
|
||||
.attr('text-anchor', 'middle')
|
||||
.text(relation.title);
|
||||
.text(relation.title)
|
||||
|
||||
window.label = label;
|
||||
var bounds = label.node().getBBox();
|
||||
window.label = label
|
||||
var bounds = label.node().getBBox()
|
||||
|
||||
g.insert('rect', ':first-child')
|
||||
.attr('class', 'box')
|
||||
.attr('x', bounds.x - conf.padding / 2)
|
||||
.attr('y', bounds.y - conf.padding / 2)
|
||||
.attr('width', bounds.width + 2 * conf.padding / 2)
|
||||
.attr('height', bounds.height + 2 * conf.padding/2);
|
||||
.attr('height', bounds.height + 2 * conf.padding / 2)
|
||||
// .append('textpath')
|
||||
// .attr('xlink:href','#edge'+edgeCount)
|
||||
// .attr('text-anchor','middle')
|
||||
// .attr('startOffset','50%')
|
||||
|
||||
}
|
||||
|
||||
edgeCount++;
|
||||
edgeCount++
|
||||
}
|
||||
|
||||
var drawClass = function (elem, classDef) {
|
||||
log.info('Rendering class ' + classDef);
|
||||
log.info('Rendering class ' + classDef)
|
||||
|
||||
var addTspan = function (textEl, txt, isFirst) {
|
||||
var tSpan = textEl.append('tspan')
|
||||
.attr('x', conf.padding)
|
||||
.text(txt);
|
||||
.text(txt)
|
||||
if (!isFirst) {
|
||||
tSpan.attr('dy', conf.textHeight);
|
||||
tSpan.attr('dy', conf.textHeight)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var id = 'classId' + classCnt;
|
||||
var id = 'classId' + classCnt
|
||||
var classInfo = {
|
||||
id: id,
|
||||
label: classDef.id,
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
}
|
||||
|
||||
var g = elem.append('g')
|
||||
.attr('id', id)
|
||||
.attr('class', 'classGroup');
|
||||
.attr('class', 'classGroup')
|
||||
var title = g.append('text')
|
||||
.attr('x', conf.padding)
|
||||
.attr('y', conf.textHeight + conf.padding)
|
||||
.text(classDef.id);
|
||||
.text(classDef.id)
|
||||
|
||||
var titleHeight = title.node().getBBox().height;
|
||||
var titleHeight = title.node().getBBox().height
|
||||
|
||||
var membersLine = g.append('line') // text label for the x axis
|
||||
.attr('x1', 0)
|
||||
.attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2)
|
||||
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2);
|
||||
.attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2)
|
||||
|
||||
var members = g.append('text') // text label for the x axis
|
||||
.attr('x', conf.padding)
|
||||
.attr('y', titleHeight + (conf.dividerMargin) + conf.textHeight)
|
||||
.attr('fill', 'white')
|
||||
.attr('class', 'classText');
|
||||
.attr('class', 'classText')
|
||||
|
||||
var isFirst = true;
|
||||
var isFirst = true
|
||||
|
||||
classDef.members.forEach(function (member) {
|
||||
addTspan(members, member, isFirst);
|
||||
isFirst = false;
|
||||
});
|
||||
addTspan(members, member, isFirst)
|
||||
isFirst = false
|
||||
})
|
||||
// for (var member of classDef.members) {
|
||||
// addTspan(members, member, isFirst);
|
||||
// isFirst = false;
|
||||
// }
|
||||
|
||||
var membersBox = members.node().getBBox();
|
||||
var membersBox = members.node().getBBox()
|
||||
|
||||
var methodsLine = g.append('line') // text label for the x axis
|
||||
.attr('x1', 0)
|
||||
.attr('y1', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height)
|
||||
.attr('y2', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height);
|
||||
|
||||
.attr('y2', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height)
|
||||
|
||||
var methods = g.append('text') // text label for the x axis
|
||||
.attr('x', conf.padding)
|
||||
.attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight)
|
||||
.attr('fill', 'white')
|
||||
.attr('class', 'classText');
|
||||
.attr('class', 'classText')
|
||||
|
||||
isFirst = true;
|
||||
isFirst = true
|
||||
|
||||
classDef.methods.forEach(function (method) {
|
||||
addTspan(methods, method, isFirst);
|
||||
isFirst = false;
|
||||
});
|
||||
addTspan(methods, method, isFirst)
|
||||
isFirst = false
|
||||
})
|
||||
// for (var method of classDef.methods) {
|
||||
// addTspan(methods, method, isFirst);
|
||||
// isFirst = false;
|
||||
// }
|
||||
|
||||
var classBox = g.node().getBBox();
|
||||
var classBox = g.node().getBBox()
|
||||
g.insert('rect', ':first-child')
|
||||
.attr('x', 0)
|
||||
.attr('y', 0)
|
||||
.attr('width', classBox.width + 2 * conf.padding)
|
||||
.attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin);
|
||||
.attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin)
|
||||
|
||||
membersLine.attr('x2', classBox.width + 2 * conf.padding)
|
||||
methodsLine.attr('x2', classBox.width + 2 * conf.padding)
|
||||
|
||||
membersLine.attr('x2', classBox.width + 2 * conf.padding);
|
||||
methodsLine.attr('x2', classBox.width + 2 * conf.padding);
|
||||
|
||||
|
||||
classInfo.width = classBox.width + 2 * conf.padding;
|
||||
classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin;
|
||||
|
||||
idCache[id] = classInfo;
|
||||
classCnt++;
|
||||
return classInfo;
|
||||
};
|
||||
classInfo.width = classBox.width + 2 * conf.padding
|
||||
classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin
|
||||
|
||||
idCache[id] = classInfo
|
||||
classCnt++
|
||||
return classInfo
|
||||
}
|
||||
|
||||
module.exports.setConf = function (cnf) {
|
||||
var keys = Object.keys(cnf);
|
||||
var keys = Object.keys(cnf)
|
||||
|
||||
keys.forEach(function (key) {
|
||||
conf[key] = cnf[key];
|
||||
});
|
||||
};
|
||||
conf[key] = cnf[key]
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||||
* @param text
|
||||
* @param id
|
||||
*/
|
||||
module.exports.draw = function (text, id) {
|
||||
cd.yy.clear();
|
||||
cd.parse(text);
|
||||
|
||||
log.info('Rendering diagram ' + text);
|
||||
cd.yy.clear()
|
||||
cd.parse(text)
|
||||
|
||||
log.info('Rendering diagram ' + text)
|
||||
|
||||
/// / Fetch the default direction, use TD if none was found
|
||||
var diagram = d3.select('#' + id);
|
||||
insertMarkers(diagram);
|
||||
var diagram = d3.select('#' + id)
|
||||
insertMarkers(diagram)
|
||||
// var svg = diagram.append('svg');
|
||||
|
||||
// Layout graph, Create a new directed graph
|
||||
var g = new dagre.graphlib.Graph({
|
||||
multigraph: true
|
||||
});
|
||||
})
|
||||
|
||||
// Set an object for the graph label
|
||||
g.setGraph({
|
||||
isMultiGraph: true
|
||||
});
|
||||
})
|
||||
|
||||
// Default to assigning a new object as a label for each new edge.
|
||||
g.setDefaultEdgeLabel(function () {
|
||||
return {};
|
||||
});
|
||||
return {}
|
||||
})
|
||||
|
||||
var classes = cDDb.getClasses();
|
||||
var keys = Object.keys(classes);
|
||||
var i;
|
||||
var classes = cDDb.getClasses()
|
||||
var keys = Object.keys(classes)
|
||||
var i
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
var classDef = classes[keys[i]];
|
||||
var node = drawClass(diagram, classDef);
|
||||
var classDef = classes[keys[i]]
|
||||
var node = drawClass(diagram, classDef)
|
||||
// Add nodes to the graph. The first argument is the node id. The second is
|
||||
// metadata about the node. In this case we're going to add labels to each of
|
||||
// our nodes.
|
||||
g.setNode(node.id, node);
|
||||
log.info('Org height: ' + node.height);
|
||||
g.setNode(node.id, node)
|
||||
log.info('Org height: ' + node.height)
|
||||
// g.setNode("swilliams", { label: "Saul Williams", width: 160, height: 100 });
|
||||
// g.setNode("bpitt", { label: "Brad Pitt", width: 108, height: 100 });
|
||||
// g.setNode("hford", { label: "Harrison Ford", width: 168, height: 100 });
|
||||
@@ -375,37 +366,36 @@ module.exports.draw = function (text, id) {
|
||||
// g.setNode("kbacon", { label: "Kevin Bacon", width: 121, height: 100 });
|
||||
}
|
||||
|
||||
var relations = cDDb.getRelations();
|
||||
var i = 0;
|
||||
var relations = cDDb.getRelations()
|
||||
var i = 0
|
||||
relations.forEach(function (relation) {
|
||||
i = i + 1;
|
||||
log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation));
|
||||
g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), {relation: relation});
|
||||
});
|
||||
i = i + 1
|
||||
log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation))
|
||||
g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), {relation: relation})
|
||||
})
|
||||
// for (var relation of relations) {
|
||||
// i = i + 1;
|
||||
// log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation));
|
||||
// g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), {relation: relation});
|
||||
// }
|
||||
dagre.layout(g);
|
||||
dagre.layout(g)
|
||||
g.nodes().forEach(function (v) {
|
||||
if (typeof v !== 'undefined') {
|
||||
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
||||
d3.select('#' + v).attr('transform', 'translate(' + (g.node(v).x - (g.node(v).width / 2)) + ',' + (g.node(v).y - (g.node(v).height / 2)) + ' )');
|
||||
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)))
|
||||
d3.select('#' + v).attr('transform', 'translate(' + (g.node(v).x - (g.node(v).width / 2)) + ',' + (g.node(v).y - (g.node(v).height / 2)) + ' )')
|
||||
// d3.select('#' +v +' rect').attr('x',(g.node(v).x-(g.node(v).width/2)))
|
||||
// .attr('y',(g.node(v).y-(g.node(v).height/2)));
|
||||
}
|
||||
});
|
||||
})
|
||||
g.edges().forEach(function (e) {
|
||||
log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
|
||||
drawEdge(diagram, g.edge(e), g.edge(e).relation);
|
||||
});
|
||||
|
||||
log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)))
|
||||
drawEdge(diagram, g.edge(e), g.edge(e).relation)
|
||||
})
|
||||
|
||||
//
|
||||
diagram.attr('height', '100%');
|
||||
diagram.attr('width', '100%');
|
||||
diagram.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
|
||||
diagram.attr('height', '100%')
|
||||
diagram.attr('width', '100%')
|
||||
diagram.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -419,4 +409,4 @@ module.exports.draw = function (text, id) {
|
||||
// diagram.attr('width', width );
|
||||
// }
|
||||
// diagram.attr('viewBox', (box.startx-conf.diagramMarginX) + ' -' +conf.diagramMarginY + ' ' + width + ' ' + height);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
// var classRenderer = proxyquire('./classRenderer', { '../../d3': d3 });
|
||||
// var testDom = require('testdom')('<html><body><div id="tst"></div></body></html>');
|
||||
|
||||
var classRenderer = require('./classRenderer');
|
||||
var parser = require('./parser/classDiagram').parser;
|
||||
|
||||
var classRenderer = require('./classRenderer')
|
||||
var parser = require('./parser/classDiagram').parser
|
||||
|
||||
describe('class diagram, ', function () {
|
||||
describe('when rendering a classDiagram', function () {
|
||||
var conf;
|
||||
var conf
|
||||
beforeEach(function () {
|
||||
/// /parser.yy = require('./classDb');
|
||||
/// /parser.yy.clear();
|
||||
@@ -84,30 +83,29 @@ describe('class diagram, ', function () {
|
||||
// }
|
||||
Object.defineProperties(window.HTMLElement.prototype, {
|
||||
getBBox: {
|
||||
get : function() {return {x:10,y:10,width:100,height:100}; }
|
||||
get: function () { return {x: 10, y: 10, width: 100, height: 100} }
|
||||
},
|
||||
offsetLeft: {
|
||||
get: function() { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
|
||||
get: function () { return parseFloat(window.getComputedStyle(this).marginLeft) || 0 }
|
||||
},
|
||||
offsetTop: {
|
||||
get: function() { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
|
||||
get: function () { return parseFloat(window.getComputedStyle(this).marginTop) || 0 }
|
||||
},
|
||||
offsetHeight: {
|
||||
get: function() { return parseFloat(window.getComputedStyle(this).height) || 0; }
|
||||
get: function () { return parseFloat(window.getComputedStyle(this).height) || 0 }
|
||||
},
|
||||
offsetWidth: {
|
||||
get: function() { return parseFloat(window.getComputedStyle(this).width) || 0; }
|
||||
get: function () { return parseFloat(window.getComputedStyle(this).width) || 0 }
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
it('it should handle one actor', function () {
|
||||
var str = 'classDiagram\n' +
|
||||
'Class01 --|> Class02';
|
||||
'Class01 --|> Class02'
|
||||
|
||||
// classRenderer.draw(str,'tst');
|
||||
|
||||
// console.log(document.body.innerHTML);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
token location info (@$, _$, etc.): {
|
||||
first_line: n,
|
||||
last_line: n,
|
||||
@@ -59,7 +58,6 @@
|
||||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||||
}
|
||||
|
||||
|
||||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||||
text: (matched text)
|
||||
token: (the produced terminal token, if any)
|
||||
@@ -72,170 +70,170 @@
|
||||
}
|
||||
*/
|
||||
var parser = (function () {
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,11],$V1=[1,12],$V2=[1,13],$V3=[1,15],$V4=[1,16],$V5=[1,17],$V6=[6,8],$V7=[1,26],$V8=[1,27],$V9=[1,28],$Va=[1,29],$Vb=[1,30],$Vc=[1,31],$Vd=[6,8,13,17,23,26,27,28,29,30,31],$Ve=[6,8,13,17,23,26,27,28,29,30,31,45,46,47],$Vf=[23,45,46,47],$Vg=[23,30,31,45,46,47],$Vh=[23,26,27,28,29,45,46,47],$Vi=[6,8,13],$Vj=[1,46];
|
||||
var o = function (k, v, o, l) { for (o = o || {}, l = k.length; l--; o[k[l]] = v);return o }, $V0 = [1, 11], $V1 = [1, 12], $V2 = [1, 13], $V3 = [1, 15], $V4 = [1, 16], $V5 = [1, 17], $V6 = [6, 8], $V7 = [1, 26], $V8 = [1, 27], $V9 = [1, 28], $Va = [1, 29], $Vb = [1, 30], $Vc = [1, 31], $Vd = [6, 8, 13, 17, 23, 26, 27, 28, 29, 30, 31], $Ve = [6, 8, 13, 17, 23, 26, 27, 28, 29, 30, 31, 45, 46, 47], $Vf = [23, 45, 46, 47], $Vg = [23, 30, 31, 45, 46, 47], $Vh = [23, 26, 27, 28, 29, 45, 46, 47], $Vi = [6, 8, 13], $Vj = [1, 46]
|
||||
var parser = {trace: function trace () { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"mermaidDoc":3,"graphConfig":4,"CLASS_DIAGRAM":5,"NEWLINE":6,"statements":7,"EOF":8,"statement":9,"className":10,"alphaNumToken":11,"relationStatement":12,"LABEL":13,"classStatement":14,"methodStatement":15,"CLASS":16,"STRUCT_START":17,"members":18,"STRUCT_STOP":19,"MEMBER":20,"SEPARATOR":21,"relation":22,"STR":23,"relationType":24,"lineType":25,"AGGREGATION":26,"EXTENSION":27,"COMPOSITION":28,"DEPENDENCY":29,"LINE":30,"DOTTED_LINE":31,"commentToken":32,"textToken":33,"graphCodeTokens":34,"textNoTagsToken":35,"TAGSTART":36,"TAGEND":37,"==":38,"--":39,"PCT":40,"DEFAULT":41,"SPACE":42,"MINUS":43,"keywords":44,"UNICODE_TEXT":45,"NUM":46,"ALPHA":47,"$accept":0,"$end":1},
|
||||
terminals_: {2:"error",5:"CLASS_DIAGRAM",6:"NEWLINE",8:"EOF",13:"LABEL",16:"CLASS",17:"STRUCT_START",19:"STRUCT_STOP",20:"MEMBER",21:"SEPARATOR",23:"STR",26:"AGGREGATION",27:"EXTENSION",28:"COMPOSITION",29:"DEPENDENCY",30:"LINE",31:"DOTTED_LINE",34:"graphCodeTokens",36:"TAGSTART",37:"TAGEND",38:"==",39:"--",40:"PCT",41:"DEFAULT",42:"SPACE",43:"MINUS",44:"keywords",45:"UNICODE_TEXT",46:"NUM",47:"ALPHA"},
|
||||
symbols_: {'error': 2, 'mermaidDoc': 3, 'graphConfig': 4, 'CLASS_DIAGRAM': 5, 'NEWLINE': 6, 'statements': 7, 'EOF': 8, 'statement': 9, 'className': 10, 'alphaNumToken': 11, 'relationStatement': 12, 'LABEL': 13, 'classStatement': 14, 'methodStatement': 15, 'CLASS': 16, 'STRUCT_START': 17, 'members': 18, 'STRUCT_STOP': 19, 'MEMBER': 20, 'SEPARATOR': 21, 'relation': 22, 'STR': 23, 'relationType': 24, 'lineType': 25, 'AGGREGATION': 26, 'EXTENSION': 27, 'COMPOSITION': 28, 'DEPENDENCY': 29, 'LINE': 30, 'DOTTED_LINE': 31, 'commentToken': 32, 'textToken': 33, 'graphCodeTokens': 34, 'textNoTagsToken': 35, 'TAGSTART': 36, 'TAGEND': 37, '==': 38, '--': 39, 'PCT': 40, 'DEFAULT': 41, 'SPACE': 42, 'MINUS': 43, 'keywords': 44, 'UNICODE_TEXT': 45, 'NUM': 46, 'ALPHA': 47, '$accept': 0, '$end': 1},
|
||||
terminals_: {2: 'error', 5: 'CLASS_DIAGRAM', 6: 'NEWLINE', 8: 'EOF', 13: 'LABEL', 16: 'CLASS', 17: 'STRUCT_START', 19: 'STRUCT_STOP', 20: 'MEMBER', 21: 'SEPARATOR', 23: 'STR', 26: 'AGGREGATION', 27: 'EXTENSION', 28: 'COMPOSITION', 29: 'DEPENDENCY', 30: 'LINE', 31: 'DOTTED_LINE', 34: 'graphCodeTokens', 36: 'TAGSTART', 37: 'TAGEND', 38: '==', 39: '--', 40: 'PCT', 41: 'DEFAULT', 42: 'SPACE', 43: 'MINUS', 44: 'keywords', 45: 'UNICODE_TEXT', 46: 'NUM', 47: 'ALPHA'},
|
||||
productions_: [0, [3, 1], [4, 4], [7, 1], [7, 3], [10, 2], [10, 1], [9, 1], [9, 2], [9, 1], [9, 1], [14, 2], [14, 5], [18, 1], [18, 2], [15, 1], [15, 2], [15, 1], [15, 1], [12, 3], [12, 4], [12, 4], [12, 5], [22, 3], [22, 2], [22, 2], [22, 1], [24, 1], [24, 1], [24, 1], [24, 1], [25, 1], [25, 1], [32, 1], [32, 1], [33, 1], [33, 1], [33, 1], [33, 1], [33, 1], [33, 1], [33, 1], [35, 1], [35, 1], [35, 1], [35, 1], [11, 1], [11, 1], [11, 1]],
|
||||
performAction: function anonymous (yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
var $0 = $$.length - 1
|
||||
switch (yystate) {
|
||||
case 5:
|
||||
this.$=$$[$0-1]+$$[$0];
|
||||
break;
|
||||
this.$ = $$[$0 - 1] + $$[$0]
|
||||
break
|
||||
case 6:
|
||||
this.$=$$[$0];
|
||||
break;
|
||||
this.$ = $$[$0]
|
||||
break
|
||||
case 7:
|
||||
yy.addRelation($$[$0]);
|
||||
break;
|
||||
yy.addRelation($$[$0])
|
||||
break
|
||||
case 8:
|
||||
$$[$0-1].title = yy.cleanupLabel($$[$0]); yy.addRelation($$[$0-1]);
|
||||
break;
|
||||
$$[$0 - 1].title = yy.cleanupLabel($$[$0]); yy.addRelation($$[$0 - 1])
|
||||
break
|
||||
case 12:
|
||||
/*console.log($$[$0-3],JSON.stringify($$[$0-1]));*/yy.addMembers($$[$0-3],$$[$0-1]);
|
||||
break;
|
||||
/* console.log($$[$0-3],JSON.stringify($$[$0-1])); */yy.addMembers($$[$0 - 3], $$[$0 - 1])
|
||||
break
|
||||
case 13:
|
||||
this.$ = [$$[$0]];
|
||||
break;
|
||||
this.$ = [$$[$0]]
|
||||
break
|
||||
case 14:
|
||||
$$[$0].push($$[$0-1]);this.$=$$[$0];
|
||||
break;
|
||||
$$[$0].push($$[$0 - 1]); this.$ = $$[$0]
|
||||
break
|
||||
case 15:
|
||||
/* console.log('Rel found',$$[$0]); */
|
||||
break;
|
||||
break
|
||||
case 16:
|
||||
yy.addMembers($$[$0-1],yy.cleanupLabel($$[$0]));
|
||||
break;
|
||||
yy.addMembers($$[$0 - 1], yy.cleanupLabel($$[$0]))
|
||||
break
|
||||
case 17:
|
||||
console.warn('Member',$$[$0]);
|
||||
break;
|
||||
console.warn('Member', $$[$0])
|
||||
break
|
||||
case 18:
|
||||
/* console.log('sep found',$$[$0]); */
|
||||
break;
|
||||
break
|
||||
case 19:
|
||||
this.$ = {'id1':$$[$0-2],'id2':$$[$0], relation:$$[$0-1], relationTitle1:'none', relationTitle2:'none'};
|
||||
break;
|
||||
this.$ = {'id1': $$[$0 - 2], 'id2': $$[$0], relation: $$[$0 - 1], relationTitle1: 'none', relationTitle2: 'none'}
|
||||
break
|
||||
case 20:
|
||||
this.$ = {id1: $$[$0 - 3], id2: $$[$0], relation: $$[$0 - 1], relationTitle1: $$[$0 - 2], relationTitle2: 'none'}
|
||||
break;
|
||||
break
|
||||
case 21:
|
||||
this.$ = {id1:$$[$0-3], id2:$$[$0], relation:$$[$0-2], relationTitle1:'none', relationTitle2:$$[$0-1]};
|
||||
break;
|
||||
this.$ = {id1: $$[$0 - 3], id2: $$[$0], relation: $$[$0 - 2], relationTitle1: 'none', relationTitle2: $$[$0 - 1]}
|
||||
break
|
||||
case 22:
|
||||
this.$ = {id1: $$[$0 - 4], id2: $$[$0], relation: $$[$0 - 2], relationTitle1: $$[$0 - 3], relationTitle2: $$[$0 - 1]}
|
||||
break;
|
||||
break
|
||||
case 23:
|
||||
this.$={type1:$$[$0-2],type2:$$[$0],lineType:$$[$0-1]};
|
||||
break;
|
||||
this.$ = {type1: $$[$0 - 2], type2: $$[$0], lineType: $$[$0 - 1]}
|
||||
break
|
||||
case 24:
|
||||
this.$={type1:'none',type2:$$[$0],lineType:$$[$0-1]};
|
||||
break;
|
||||
this.$ = {type1: 'none', type2: $$[$0], lineType: $$[$0 - 1]}
|
||||
break
|
||||
case 25:
|
||||
this.$={type1:$$[$0-1],type2:'none',lineType:$$[$0]};
|
||||
break;
|
||||
this.$ = {type1: $$[$0 - 1], type2: 'none', lineType: $$[$0]}
|
||||
break
|
||||
case 26:
|
||||
this.$={type1:'none',type2:'none',lineType:$$[$0]};
|
||||
break;
|
||||
this.$ = {type1: 'none', type2: 'none', lineType: $$[$0]}
|
||||
break
|
||||
case 27:
|
||||
this.$=yy.relationType.AGGREGATION;
|
||||
break;
|
||||
this.$ = yy.relationType.AGGREGATION
|
||||
break
|
||||
case 28:
|
||||
this.$=yy.relationType.EXTENSION;
|
||||
break;
|
||||
this.$ = yy.relationType.EXTENSION
|
||||
break
|
||||
case 29:
|
||||
this.$=yy.relationType.COMPOSITION;
|
||||
break;
|
||||
this.$ = yy.relationType.COMPOSITION
|
||||
break
|
||||
case 30:
|
||||
this.$=yy.relationType.DEPENDENCY;
|
||||
break;
|
||||
this.$ = yy.relationType.DEPENDENCY
|
||||
break
|
||||
case 31:
|
||||
this.$=yy.lineType.LINE;
|
||||
break;
|
||||
this.$ = yy.lineType.LINE
|
||||
break
|
||||
case 32:
|
||||
this.$=yy.lineType.DOTTED_LINE;
|
||||
break;
|
||||
this.$ = yy.lineType.DOTTED_LINE
|
||||
break
|
||||
}
|
||||
},
|
||||
table: [{3: 1, 4: 2, 5: [1, 3]}, {1: [3]}, {1: [2, 1]}, {6: [1, 4]}, {7: 5, 9: 6, 10: 10, 11: 14, 12: 7, 14: 8, 15: 9, 16: $V0, 20: $V1, 21: $V2, 45: $V3, 46: $V4, 47: $V5}, {8: [1, 18]}, {6: [1, 19], 8: [2, 3]}, o($V6, [2, 7], {13: [1, 20]}), o($V6, [2, 9]), o($V6, [2, 10]), o($V6, [2, 15], {22: 21, 24: 24, 25: 25, 13: [1, 23], 23: [1, 22], 26: $V7, 27: $V8, 28: $V9, 29: $Va, 30: $Vb, 31: $Vc}), {10: 32, 11: 14, 45: $V3, 46: $V4, 47: $V5}, o($V6, [2, 17]), o($V6, [2, 18]), o($Vd, [2, 6], {11: 14, 10: 33, 45: $V3, 46: $V4, 47: $V5}), o($Ve, [2, 46]), o($Ve, [2, 47]), o($Ve, [2, 48]), {1: [2, 2]}, {7: 34, 9: 6, 10: 10, 11: 14, 12: 7, 14: 8, 15: 9, 16: $V0, 20: $V1, 21: $V2, 45: $V3, 46: $V4, 47: $V5}, o($V6, [2, 8]), {10: 35, 11: 14, 23: [1, 36], 45: $V3, 46: $V4, 47: $V5}, {22: 37, 24: 24, 25: 25, 26: $V7, 27: $V8, 28: $V9, 29: $Va, 30: $Vb, 31: $Vc}, o($V6, [2, 16]), {25: 38, 30: $Vb, 31: $Vc}, o($Vf, [2, 26], {24: 39, 26: $V7, 27: $V8, 28: $V9, 29: $Va}), o($Vg, [2, 27]), o($Vg, [2, 28]), o($Vg, [2, 29]), o($Vg, [2, 30]), o($Vh, [2, 31]), o($Vh, [2, 32]), o($V6, [2, 11], {17: [1, 40]}), o($Vd, [2, 5]), {8: [2, 4]}, o($Vi, [2, 19]), {10: 41, 11: 14, 45: $V3, 46: $V4, 47: $V5}, {10: 42, 11: 14, 23: [1, 43], 45: $V3, 46: $V4, 47: $V5}, o($Vf, [2, 25], {24: 44, 26: $V7, 27: $V8, 28: $V9, 29: $Va}), o($Vf, [2, 24]), {18: 45, 20: $Vj}, o($Vi, [2, 21]), o($Vi, [2, 20]), {10: 47, 11: 14, 45: $V3, 46: $V4, 47: $V5}, o($Vf, [2, 23]), {19: [1, 48]}, {18: 49, 19: [2, 13], 20: $Vj}, o($Vi, [2, 22]), o($V6, [2, 12]), {19: [2, 14]}],
|
||||
defaultActions: {2: [2, 1], 18: [2, 2], 34: [2, 4], 49: [2, 14]},
|
||||
parseError: function parseError (str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
this.trace(str)
|
||||
} else {
|
||||
function _parseError (msg, hash) {
|
||||
this.message = msg;
|
||||
this.hash = hash;
|
||||
this.message = msg
|
||||
this.hash = hash
|
||||
}
|
||||
_parseError.prototype = Error;
|
||||
_parseError.prototype = Error
|
||||
|
||||
throw new _parseError(str, hash);
|
||||
throw new _parseError(str, hash)
|
||||
}
|
||||
},
|
||||
parse: function parse (input) {
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1
|
||||
var args = lstack.slice.call(arguments, 1)
|
||||
var lexer = Object.create(this.lexer)
|
||||
var sharedState = { yy: {} }
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
sharedState.yy[k] = this.yy[k]
|
||||
}
|
||||
}
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
lexer.setInput(input, sharedState.yy)
|
||||
sharedState.yy.lexer = lexer
|
||||
sharedState.yy.parser = this
|
||||
if (typeof lexer.yylloc === 'undefined') {
|
||||
lexer.yylloc = {}
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
var yyloc = lexer.yylloc
|
||||
lstack.push(yyloc)
|
||||
var ranges = lexer.options && lexer.options.ranges
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
this.parseError = sharedState.yy.parseError
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
this.parseError = Object.getPrototypeOf(this).parseError
|
||||
}
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
stack.length = stack.length - 2 * n
|
||||
vstack.length = vstack.length - n
|
||||
lstack.length = lstack.length - n
|
||||
}
|
||||
_token_stack:
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
var token
|
||||
token = lexer.lex() || EOF
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
token = self.symbols_[token] || token
|
||||
}
|
||||
return token;
|
||||
};
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
return token
|
||||
}
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected
|
||||
while (true) {
|
||||
state = stack[stack.length - 1];
|
||||
state = stack[stack.length - 1]
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
action = this.defaultActions[state]
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
if (symbol === null || typeof symbol === 'undefined') {
|
||||
symbol = lex()
|
||||
}
|
||||
action = table[state] && table[state][symbol];
|
||||
action = table[state] && table[state][symbol]
|
||||
}
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var errStr = '';
|
||||
expected = [];
|
||||
var errStr = ''
|
||||
expected = []
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push('\'' + this.terminals_[p] + '\'');
|
||||
expected.push('\'' + this.terminals_[p] + '\'')
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''
|
||||
} else {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'')
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
@@ -243,45 +241,45 @@ parse: function parse(input) {
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected
|
||||
});
|
||||
})
|
||||
}
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol)
|
||||
}
|
||||
switch (action[0]) {
|
||||
case 1:
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]);
|
||||
symbol = null;
|
||||
stack.push(symbol)
|
||||
vstack.push(lexer.yytext)
|
||||
lstack.push(lexer.yylloc)
|
||||
stack.push(action[1])
|
||||
symbol = null
|
||||
if (!preErrorSymbol) {
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
yyleng = lexer.yyleng
|
||||
yytext = lexer.yytext
|
||||
yylineno = lexer.yylineno
|
||||
yyloc = lexer.yylloc
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
recovering--
|
||||
}
|
||||
} else {
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
symbol = preErrorSymbol
|
||||
preErrorSymbol = null
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 2:
|
||||
len = this.productions_[action[1]][1];
|
||||
yyval.$ = vstack[vstack.length - len];
|
||||
len = this.productions_[action[1]][1]
|
||||
yyval.$ = vstack[vstack.length - len]
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||||
last_line: lstack[lstack.length - 1].last_line,
|
||||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||||
last_column: lstack[lstack.length - 1].last_column
|
||||
};
|
||||
}
|
||||
if (ranges) {
|
||||
yyval._$.range = [
|
||||
lstack[lstack.length - (len || 1)].range[0],
|
||||
lstack[lstack.length - 1].range[1]
|
||||
];
|
||||
]
|
||||
}
|
||||
r = this.performAction.apply(yyval, [
|
||||
yytext,
|
||||
@@ -291,27 +289,27 @@ parse: function parse(input) {
|
||||
action[1],
|
||||
vstack,
|
||||
lstack
|
||||
].concat(args));
|
||||
].concat(args))
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
return r
|
||||
}
|
||||
if (len) {
|
||||
stack = stack.slice(0, -1 * len * 2);
|
||||
vstack = vstack.slice(0, -1 * len);
|
||||
lstack = lstack.slice(0, -1 * len);
|
||||
stack = stack.slice(0, -1 * len * 2)
|
||||
vstack = vstack.slice(0, -1 * len)
|
||||
lstack = lstack.slice(0, -1 * len)
|
||||
}
|
||||
stack.push(this.productions_[action[1]][0]);
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
stack.push(this.productions_[action[1]][0])
|
||||
vstack.push(yyval.$)
|
||||
lstack.push(yyval._$)
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]]
|
||||
stack.push(newState)
|
||||
break
|
||||
case 3:
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}};
|
||||
return true
|
||||
}}
|
||||
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function () {
|
||||
@@ -321,144 +319,143 @@ EOF:1,
|
||||
|
||||
parseError: function parseError (str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
this.yy.parser.parseError(str, hash)
|
||||
} else {
|
||||
throw new Error(str);
|
||||
throw new Error(str)
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput: function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yy = yy || this.yy || {}
|
||||
this._input = input
|
||||
this._more = this._backtrack = this.done = false
|
||||
this.yylineno = this.yyleng = 0
|
||||
this.yytext = this.matched = this.match = ''
|
||||
this.conditionStack = ['INITIAL']
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0, 0]
|
||||
}
|
||||
this.offset = 0
|
||||
return this
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input: function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
var ch = this._input[0]
|
||||
this.yytext += ch
|
||||
this.yyleng++
|
||||
this.offset++
|
||||
this.match += ch
|
||||
this.matched += ch
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
this.yylineno++
|
||||
this.yylloc.last_line++
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
this.yylloc.last_column++
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
this.yylloc.range[1]++
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
this._input = this._input.slice(1)
|
||||
return ch
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput: function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
var len = ch.length
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g)
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
this._input = ch + this._input
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len)
|
||||
// this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
this.offset -= len
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g)
|
||||
this.match = this.match.substr(0, this.match.length - 1)
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1)
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
this.yylineno -= lines.length - 1
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
var r = this.yylloc.range
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
last_column: lines
|
||||
? (lines.length === oldLines.length ? this.yylloc.first_column : 0) +
|
||||
oldLines[oldLines.length - lines.length].length - lines[0].length
|
||||
: this.yylloc.first_column - len
|
||||
}
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len]
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
this.yyleng = this.yytext.length
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more: function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
this._more = true
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject: function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
this._backtrack = true
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
return this;
|
||||
return this
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less: function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
this.unput(this.match.slice(n))
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput: function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length)
|
||||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput: function () {
|
||||
var next = this.match;
|
||||
var next = this.match
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
next += this._input.substr(0, 20 - next.length)
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition: function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
var pre = this.pastInput()
|
||||
var c = new Array(pre.length + 1).join('-')
|
||||
return pre + this.upcomingInput() + '\n' + c + '^'
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match: function (match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
backup
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
@@ -481,261 +478,260 @@ test_match:function (match, indexed_rule) {
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
backup.yylloc.range = this.yylloc.range.slice(0)
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
this.yylineno += lines.length
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
last_column: lines
|
||||
? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length
|
||||
: this.yylloc.last_column + match[0].length
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
this.yytext += match[0]
|
||||
this.match += match[0]
|
||||
this.matches = match
|
||||
this.yyleng = this.yytext.length
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng]
|
||||
}
|
||||
this._more = false
|
||||
this._backtrack = false
|
||||
this._input = this._input.slice(match[0].length)
|
||||
this.matched += match[0]
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1])
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
this.done = false
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
this[k] = backup[k]
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
return false // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next: function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
return this.EOF
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
this.done = true
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
index
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
this.yytext = ''
|
||||
this.match = ''
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
var rules = this._currentRules()
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
tempMatch = this._input.match(this.rules[rules[i]])
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
match = tempMatch
|
||||
index = i
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
token = this.test_match(tempMatch, rules[i])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
match = false
|
||||
continue // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
token = this.test_match(match, rules[index])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
if (this._input === '') {
|
||||
return this.EOF
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex: function lex () {
|
||||
var r = this.next();
|
||||
var r = this.next()
|
||||
if (r) {
|
||||
return r;
|
||||
return r
|
||||
} else {
|
||||
return this.lex();
|
||||
return this.lex()
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin: function begin (condition) {
|
||||
this.conditionStack.push(condition);
|
||||
this.conditionStack.push(condition)
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState: function popState () {
|
||||
var n = this.conditionStack.length - 1;
|
||||
var n = this.conditionStack.length - 1
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
return this.conditionStack.pop()
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
return this.conditionStack[0]
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules: function _currentRules () {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
return this.conditions['INITIAL'].rules
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState: function topState (n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0)
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
return this.conditionStack[n]
|
||||
} else {
|
||||
return "INITIAL";
|
||||
return 'INITIAL'
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState: function pushState (condition) {
|
||||
this.begin(condition);
|
||||
this.begin(condition)
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize: function stateStackSize () {
|
||||
return this.conditionStack.length;
|
||||
return this.conditionStack.length
|
||||
},
|
||||
options: {},
|
||||
performAction: function anonymous (yy, yy_, $avoiding_name_collisions, YY_START) {
|
||||
var YYSTATE=YY_START;
|
||||
var YYSTATE = YY_START
|
||||
switch ($avoiding_name_collisions) {
|
||||
case 0:/* do nothing */
|
||||
break;
|
||||
case 1:return 6;
|
||||
break;
|
||||
break
|
||||
case 1:return 6
|
||||
break
|
||||
case 2:/* skip whitespace */
|
||||
break;
|
||||
case 3:return 5;
|
||||
break;
|
||||
case 4: this.begin("struct"); /*console.log('Starting struct');*/return 17;
|
||||
break;
|
||||
case 5: /*console.log('Ending struct');*/this.popState(); return 19;
|
||||
break;
|
||||
break
|
||||
case 3:return 5
|
||||
break
|
||||
case 4: this.begin('struct'); /* console.log('Starting struct'); */return 17
|
||||
break
|
||||
case 5: /* console.log('Ending struct'); */this.popState(); return 19
|
||||
break
|
||||
case 6:/* nothing */
|
||||
break;
|
||||
case 7: /*console.log('lex-member: ' + yy_.yytext);*/ return "MEMBER";
|
||||
break;
|
||||
case 8:return 16;
|
||||
break;
|
||||
case 9:this.begin("string");
|
||||
break;
|
||||
case 10:this.popState();
|
||||
break;
|
||||
case 11:return "STR";
|
||||
break;
|
||||
case 12:return 27;
|
||||
break;
|
||||
case 13:return 27;
|
||||
break;
|
||||
case 14:return 29;
|
||||
break;
|
||||
case 15:return 29;
|
||||
break;
|
||||
case 16:return 28;
|
||||
break;
|
||||
case 17:return 26;
|
||||
break;
|
||||
case 18:return 30;
|
||||
break;
|
||||
case 19:return 31;
|
||||
break;
|
||||
case 20:return 13;
|
||||
break;
|
||||
case 21:return 43;
|
||||
break;
|
||||
case 22:return 'DOT';
|
||||
break;
|
||||
case 23:return 'PLUS';
|
||||
break;
|
||||
case 24:return 40;
|
||||
break;
|
||||
case 25:return 'EQUALS';
|
||||
break;
|
||||
case 26:return 'EQUALS';
|
||||
break;
|
||||
case 27:return 47;
|
||||
break;
|
||||
case 28:return 'PUNCTUATION';
|
||||
break;
|
||||
case 29:return 46;
|
||||
break;
|
||||
case 30:return 45;
|
||||
break;
|
||||
case 31:return 42;
|
||||
break;
|
||||
case 32:return 8;
|
||||
break;
|
||||
break
|
||||
case 7: return 'MEMBER'
|
||||
break
|
||||
case 8:return 16
|
||||
break
|
||||
case 9:this.begin('string')
|
||||
break
|
||||
case 10:this.popState()
|
||||
break
|
||||
case 11:return 'STR'
|
||||
break
|
||||
case 12:return 27
|
||||
break
|
||||
case 13:return 27
|
||||
break
|
||||
case 14:return 29
|
||||
break
|
||||
case 15:return 29
|
||||
break
|
||||
case 16:return 28
|
||||
break
|
||||
case 17:return 26
|
||||
break
|
||||
case 18:return 30
|
||||
break
|
||||
case 19:return 31
|
||||
break
|
||||
case 20:return 13
|
||||
break
|
||||
case 21:return 43
|
||||
break
|
||||
case 22:return 'DOT'
|
||||
break
|
||||
case 23:return 'PLUS'
|
||||
break
|
||||
case 24:return 40
|
||||
break
|
||||
case 25:return 'EQUALS'
|
||||
break
|
||||
case 26:return 'EQUALS'
|
||||
break
|
||||
case 27:return 47
|
||||
break
|
||||
case 28:return 'PUNCTUATION'
|
||||
break
|
||||
case 29:return 46
|
||||
break
|
||||
case 30:return 45
|
||||
break
|
||||
case 31:return 42
|
||||
break
|
||||
case 32:return 8
|
||||
break
|
||||
}
|
||||
},
|
||||
rules: [/^(?:%%[^\n]*)/, /^(?:\n+)/, /^(?:\s+)/, /^(?:classDiagram\b)/, /^(?:[\{])/, /^(?:\})/, /^(?:[\n])/, /^(?:[^\{\}\n]*)/, /^(?:class\b)/, /^(?:["])/, /^(?:["])/, /^(?:[^"]*)/, /^(?:\s*<\|)/, /^(?:\s*\|>)/, /^(?:\s*>)/, /^(?:\s*<)/, /^(?:\s*\*)/, /^(?:\s*o\b)/, /^(?:--)/, /^(?:\.\.)/, /^(?::[^#\n;]+)/, /^(?:-)/, /^(?:\.)/, /^(?:\+)/, /^(?:%)/, /^(?:=)/, /^(?:=)/, /^(?:[A-Za-z]+)/, /^(?:[!"#$%&'*+,-.`?\\_\/])/, /^(?:[0-9]+)/, /^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/, /^(?:\s)/, /^(?:$)/],
|
||||
conditions: {"string":{"rules":[10,11],"inclusive":false},"struct":{"rules":[5,6,7],"inclusive":false},"INITIAL":{"rules":[0,1,2,3,4,8,9,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
conditions: {'string': {'rules': [10, 11], 'inclusive': false}, 'struct': {'rules': [5, 6, 7], 'inclusive': false}, 'INITIAL': {'rules': [0, 1, 2, 3, 4, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32], 'inclusive': true}}
|
||||
})
|
||||
return lexer
|
||||
})()
|
||||
parser.lexer = lexer
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
this.yy = {}
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
|
||||
Parser.prototype = parser; parser.Parser = Parser
|
||||
return new Parser()
|
||||
})()
|
||||
|
||||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||||
exports.parser = parser;
|
||||
exports.Parser = parser.Parser;
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments); };
|
||||
exports.parser = parser
|
||||
exports.Parser = parser.Parser
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments) }
|
||||
exports.main = function commonjsMain (args) {
|
||||
if (!args[1]) {
|
||||
console.log('Usage: '+args[0]+' FILE');
|
||||
process.exit(1);
|
||||
console.log('Usage: ' + args[0] + ' FILE')
|
||||
process.exit(1)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), 'utf8')
|
||||
return exports.parser.parse(source)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||||
return exports.parser.parse(source);
|
||||
};
|
||||
if (typeof module !== 'undefined' && require.main === module) {
|
||||
exports.main(process.argv.slice(1));
|
||||
exports.main(process.argv.slice(1))
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,20 @@
|
||||
* Created by knut on 14-11-18.
|
||||
*/
|
||||
describe('when parsing an info graph it', function () {
|
||||
var ex;
|
||||
var ex
|
||||
beforeEach(function () {
|
||||
ex = require('./parser/example').parser;
|
||||
ex.yy = require('./exampleDb');
|
||||
});
|
||||
ex = require('./parser/example').parser
|
||||
ex.yy = require('./exampleDb')
|
||||
})
|
||||
|
||||
it('should handle an info definition', function () {
|
||||
var str = 'info\nsay: hello';
|
||||
var str = 'info\nsay: hello'
|
||||
|
||||
ex.parse(str);
|
||||
});
|
||||
ex.parse(str)
|
||||
})
|
||||
it('should handle an showMessage statement definition', function () {
|
||||
var str = 'info\nshowInfo';
|
||||
var str = 'info\nshowInfo'
|
||||
|
||||
ex.parse(str);
|
||||
});
|
||||
});
|
||||
ex.parse(str)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/**
|
||||
* Created by knut on 15-01-14.
|
||||
*/
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
|
||||
var message = '';
|
||||
var info = false;
|
||||
var message = ''
|
||||
var info = false
|
||||
|
||||
exports.setMessage = function (txt) {
|
||||
log.debug('Setting message to: '+txt);
|
||||
message = txt;
|
||||
};
|
||||
log.debug('Setting message to: ' + txt)
|
||||
message = txt
|
||||
}
|
||||
|
||||
exports.getMessage = function () {
|
||||
return message;
|
||||
};
|
||||
return message
|
||||
}
|
||||
|
||||
exports.setInfo = function (inf) {
|
||||
info = inf;
|
||||
};
|
||||
info = inf
|
||||
}
|
||||
|
||||
exports.getInfo = function () {
|
||||
return info;
|
||||
};
|
||||
return info
|
||||
}
|
||||
|
||||
exports.parseError = function (err, hash) {
|
||||
global.mermaidAPI.parseError(err,hash);
|
||||
};
|
||||
global.mermaidAPI.parseError(err, hash)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Created by knut on 14-12-11.
|
||||
*/
|
||||
var db = require('./exampleDb');
|
||||
var exampleParser = require('./parser/example.js');
|
||||
var d3 = require('../../d3');
|
||||
var db = require('./exampleDb')
|
||||
var exampleParser = require('./parser/example.js')
|
||||
var d3 = require('../../d3')
|
||||
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
// var log = new Logger.Log();
|
||||
|
||||
/**
|
||||
@@ -15,17 +15,17 @@ var log = Logger.Log;
|
||||
* @param id
|
||||
*/
|
||||
exports.draw = function (txt, id, ver) {
|
||||
var parser;
|
||||
parser = exampleParser.parser;
|
||||
parser.yy = db;
|
||||
log.debug('Renering example diagram');
|
||||
var parser
|
||||
parser = exampleParser.parser
|
||||
parser.yy = db
|
||||
log.debug('Renering example diagram')
|
||||
// Parse the graph definition
|
||||
parser.parse(txt);
|
||||
parser.parse(txt)
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
var svg = d3.select('#'+id);
|
||||
var svg = d3.select('#' + id)
|
||||
|
||||
var g = svg.append('g');
|
||||
var g = svg.append('g')
|
||||
|
||||
g.append('text') // text label for the x axis
|
||||
.attr('x', 100)
|
||||
@@ -33,7 +33,7 @@ exports.draw = function (txt, id, ver) {
|
||||
.attr('class', 'version')
|
||||
.attr('font-size', '32px')
|
||||
.style('text-anchor', 'middle')
|
||||
.text('mermaid '+ ver);
|
||||
.text('mermaid ' + ver)
|
||||
|
||||
/*
|
||||
var box = exports.bounds.getBounds();
|
||||
@@ -41,7 +41,7 @@ exports.draw = function (txt, id, ver) {
|
||||
var height = box.stopy-box.starty+2*conf.diagramMarginY;
|
||||
var width = box.stopx-box.startx+2*conf.diagramMarginX; */
|
||||
|
||||
svg.attr('height',100);
|
||||
svg.attr('width', 400 );
|
||||
svg.attr('height', 100)
|
||||
svg.attr('width', 400)
|
||||
// svg.attr('viewBox', '0 0 300 150');
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
token location info (@$, _$, etc.): {
|
||||
first_line: n,
|
||||
last_line: n,
|
||||
@@ -59,7 +58,6 @@
|
||||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||||
}
|
||||
|
||||
|
||||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||||
text: (matched text)
|
||||
token: (the produced terminal token, if any)
|
||||
@@ -72,110 +70,110 @@
|
||||
}
|
||||
*/
|
||||
var parser = (function () {
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[6,9,10,12];
|
||||
var o = function (k, v, o, l) { for (o = o || {}, l = k.length; l--; o[k[l]] = v);return o }, $V0 = [6, 9, 10, 12]
|
||||
var parser = {trace: function trace () { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"start":3,"info":4,"document":5,"EOF":6,"line":7,"statement":8,"NL":9,"showInfo":10,"message":11,"say":12,"TXT":13,"$accept":0,"$end":1},
|
||||
terminals_: {2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo",12:"say",13:"TXT"},
|
||||
symbols_: {'error': 2, 'start': 3, 'info': 4, 'document': 5, 'EOF': 6, 'line': 7, 'statement': 8, 'NL': 9, 'showInfo': 10, 'message': 11, 'say': 12, 'TXT': 13, '$accept': 0, '$end': 1},
|
||||
terminals_: {2: 'error', 4: 'info', 6: 'EOF', 9: 'NL', 10: 'showInfo', 12: 'say', 13: 'TXT'},
|
||||
productions_: [0, [3, 3], [5, 0], [5, 2], [7, 1], [7, 1], [8, 1], [8, 1], [11, 2]],
|
||||
performAction: function anonymous (yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
var $0 = $$.length - 1
|
||||
switch (yystate) {
|
||||
case 1:
|
||||
return yy;
|
||||
break;
|
||||
return yy
|
||||
break
|
||||
case 4:
|
||||
|
||||
break;
|
||||
break
|
||||
case 6:
|
||||
yy.setInfo(true);
|
||||
break;
|
||||
yy.setInfo(true)
|
||||
break
|
||||
case 7:
|
||||
yy.setMessage($$[$0]);
|
||||
break;
|
||||
yy.setMessage($$[$0])
|
||||
break
|
||||
case 8:
|
||||
this.$ = $$[$0-1].substring(1).trim().replace(/\\n/gm, "\n");
|
||||
break;
|
||||
this.$ = $$[$0 - 1].substring(1).trim().replace(/\\n/gm, '\n')
|
||||
break
|
||||
}
|
||||
},
|
||||
table: [{3: 1, 4: [1, 2]}, {1: [3]}, o($V0, [2, 2], {5: 3}), {6: [1, 4], 7: 5, 8: 6, 9: [1, 7], 10: [1, 8], 11: 9, 12: [1, 10]}, {1: [2, 1]}, o($V0, [2, 3]), o($V0, [2, 4]), o($V0, [2, 5]), o($V0, [2, 6]), o($V0, [2, 7]), {13: [1, 11]}, o($V0, [2, 8])],
|
||||
defaultActions: {4: [2, 1]},
|
||||
parseError: function parseError (str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
this.trace(str)
|
||||
} else {
|
||||
function _parseError (msg, hash) {
|
||||
this.message = msg;
|
||||
this.hash = hash;
|
||||
this.message = msg
|
||||
this.hash = hash
|
||||
}
|
||||
_parseError.prototype = Error;
|
||||
_parseError.prototype = Error
|
||||
|
||||
throw new _parseError(str, hash);
|
||||
throw new _parseError(str, hash)
|
||||
}
|
||||
},
|
||||
parse: function parse (input) {
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1
|
||||
var args = lstack.slice.call(arguments, 1)
|
||||
var lexer = Object.create(this.lexer)
|
||||
var sharedState = { yy: {} }
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
sharedState.yy[k] = this.yy[k]
|
||||
}
|
||||
}
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
lexer.setInput(input, sharedState.yy)
|
||||
sharedState.yy.lexer = lexer
|
||||
sharedState.yy.parser = this
|
||||
if (typeof lexer.yylloc === 'undefined') {
|
||||
lexer.yylloc = {}
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
var yyloc = lexer.yylloc
|
||||
lstack.push(yyloc)
|
||||
var ranges = lexer.options && lexer.options.ranges
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
this.parseError = sharedState.yy.parseError
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
this.parseError = Object.getPrototypeOf(this).parseError
|
||||
}
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
stack.length = stack.length - 2 * n
|
||||
vstack.length = vstack.length - n
|
||||
lstack.length = lstack.length - n
|
||||
}
|
||||
_token_stack:
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
var token
|
||||
token = lexer.lex() || EOF
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
token = self.symbols_[token] || token
|
||||
}
|
||||
return token;
|
||||
};
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
return token
|
||||
}
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected
|
||||
while (true) {
|
||||
state = stack[stack.length - 1];
|
||||
state = stack[stack.length - 1]
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
action = this.defaultActions[state]
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
if (symbol === null || typeof symbol === 'undefined') {
|
||||
symbol = lex()
|
||||
}
|
||||
action = table[state] && table[state][symbol];
|
||||
action = table[state] && table[state][symbol]
|
||||
}
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var errStr = '';
|
||||
expected = [];
|
||||
var errStr = ''
|
||||
expected = []
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push('\'' + this.terminals_[p] + '\'');
|
||||
expected.push('\'' + this.terminals_[p] + '\'')
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''
|
||||
} else {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'')
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
@@ -183,45 +181,45 @@ parse: function parse(input) {
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected
|
||||
});
|
||||
})
|
||||
}
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol)
|
||||
}
|
||||
switch (action[0]) {
|
||||
case 1:
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]);
|
||||
symbol = null;
|
||||
stack.push(symbol)
|
||||
vstack.push(lexer.yytext)
|
||||
lstack.push(lexer.yylloc)
|
||||
stack.push(action[1])
|
||||
symbol = null
|
||||
if (!preErrorSymbol) {
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
yyleng = lexer.yyleng
|
||||
yytext = lexer.yytext
|
||||
yylineno = lexer.yylineno
|
||||
yyloc = lexer.yylloc
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
recovering--
|
||||
}
|
||||
} else {
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
symbol = preErrorSymbol
|
||||
preErrorSymbol = null
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 2:
|
||||
len = this.productions_[action[1]][1];
|
||||
yyval.$ = vstack[vstack.length - len];
|
||||
len = this.productions_[action[1]][1]
|
||||
yyval.$ = vstack[vstack.length - len]
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||||
last_line: lstack[lstack.length - 1].last_line,
|
||||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||||
last_column: lstack[lstack.length - 1].last_column
|
||||
};
|
||||
}
|
||||
if (ranges) {
|
||||
yyval._$.range = [
|
||||
lstack[lstack.length - (len || 1)].range[0],
|
||||
lstack[lstack.length - 1].range[1]
|
||||
];
|
||||
]
|
||||
}
|
||||
r = this.performAction.apply(yyval, [
|
||||
yytext,
|
||||
@@ -231,27 +229,27 @@ parse: function parse(input) {
|
||||
action[1],
|
||||
vstack,
|
||||
lstack
|
||||
].concat(args));
|
||||
].concat(args))
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
return r
|
||||
}
|
||||
if (len) {
|
||||
stack = stack.slice(0, -1 * len * 2);
|
||||
vstack = vstack.slice(0, -1 * len);
|
||||
lstack = lstack.slice(0, -1 * len);
|
||||
stack = stack.slice(0, -1 * len * 2)
|
||||
vstack = vstack.slice(0, -1 * len)
|
||||
lstack = lstack.slice(0, -1 * len)
|
||||
}
|
||||
stack.push(this.productions_[action[1]][0]);
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
stack.push(this.productions_[action[1]][0])
|
||||
vstack.push(yyval.$)
|
||||
lstack.push(yyval._$)
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]]
|
||||
stack.push(newState)
|
||||
break
|
||||
case 3:
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}};
|
||||
return true
|
||||
}}
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function () {
|
||||
var lexer = ({
|
||||
@@ -260,144 +258,143 @@ EOF:1,
|
||||
|
||||
parseError: function parseError (str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
this.yy.parser.parseError(str, hash)
|
||||
} else {
|
||||
throw new Error(str);
|
||||
throw new Error(str)
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput: function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yy = yy || this.yy || {}
|
||||
this._input = input
|
||||
this._more = this._backtrack = this.done = false
|
||||
this.yylineno = this.yyleng = 0
|
||||
this.yytext = this.matched = this.match = ''
|
||||
this.conditionStack = ['INITIAL']
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0, 0]
|
||||
}
|
||||
this.offset = 0
|
||||
return this
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input: function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
var ch = this._input[0]
|
||||
this.yytext += ch
|
||||
this.yyleng++
|
||||
this.offset++
|
||||
this.match += ch
|
||||
this.matched += ch
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
this.yylineno++
|
||||
this.yylloc.last_line++
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
this.yylloc.last_column++
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
this.yylloc.range[1]++
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
this._input = this._input.slice(1)
|
||||
return ch
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput: function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
var len = ch.length
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g)
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
this._input = ch + this._input
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len)
|
||||
// this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
this.offset -= len
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g)
|
||||
this.match = this.match.substr(0, this.match.length - 1)
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1)
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
this.yylineno -= lines.length - 1
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
var r = this.yylloc.range
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
last_column: lines
|
||||
? (lines.length === oldLines.length ? this.yylloc.first_column : 0) +
|
||||
oldLines[oldLines.length - lines.length].length - lines[0].length
|
||||
: this.yylloc.first_column - len
|
||||
}
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len]
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
this.yyleng = this.yytext.length
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more: function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
this._more = true
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject: function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
this._backtrack = true
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
return this;
|
||||
return this
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less: function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
this.unput(this.match.slice(n))
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput: function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length)
|
||||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput: function () {
|
||||
var next = this.match;
|
||||
var next = this.match
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
next += this._input.substr(0, 20 - next.length)
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition: function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
var pre = this.pastInput()
|
||||
var c = new Array(pre.length + 1).join('-')
|
||||
return pre + this.upcomingInput() + '\n' + c + '^'
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match: function (match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
backup
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
@@ -420,211 +417,210 @@ test_match:function (match, indexed_rule) {
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
backup.yylloc.range = this.yylloc.range.slice(0)
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
this.yylineno += lines.length
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
last_column: lines
|
||||
? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length
|
||||
: this.yylloc.last_column + match[0].length
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
this.yytext += match[0]
|
||||
this.match += match[0]
|
||||
this.matches = match
|
||||
this.yyleng = this.yytext.length
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng]
|
||||
}
|
||||
this._more = false
|
||||
this._backtrack = false
|
||||
this._input = this._input.slice(match[0].length)
|
||||
this.matched += match[0]
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1])
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
this.done = false
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
this[k] = backup[k]
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
return false // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next: function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
return this.EOF
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
this.done = true
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
index
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
this.yytext = ''
|
||||
this.match = ''
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
var rules = this._currentRules()
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
tempMatch = this._input.match(this.rules[rules[i]])
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
match = tempMatch
|
||||
index = i
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
token = this.test_match(tempMatch, rules[i])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
match = false
|
||||
continue // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
token = this.test_match(match, rules[index])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
if (this._input === '') {
|
||||
return this.EOF
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex: function lex () {
|
||||
var r = this.next();
|
||||
var r = this.next()
|
||||
if (r) {
|
||||
return r;
|
||||
return r
|
||||
} else {
|
||||
return this.lex();
|
||||
return this.lex()
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin: function begin (condition) {
|
||||
this.conditionStack.push(condition);
|
||||
this.conditionStack.push(condition)
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState: function popState () {
|
||||
var n = this.conditionStack.length - 1;
|
||||
var n = this.conditionStack.length - 1
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
return this.conditionStack.pop()
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
return this.conditionStack[0]
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules: function _currentRules () {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
return this.conditions['INITIAL'].rules
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState: function topState (n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0)
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
return this.conditionStack[n]
|
||||
} else {
|
||||
return "INITIAL";
|
||||
return 'INITIAL'
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState: function pushState (condition) {
|
||||
this.begin(condition);
|
||||
this.begin(condition)
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize: function stateStackSize () {
|
||||
return this.conditionStack.length;
|
||||
return this.conditionStack.length
|
||||
},
|
||||
options: {"case-insensitive":true},
|
||||
options: {'case-insensitive': true},
|
||||
performAction: function anonymous (yy, yy_, $avoiding_name_collisions, YY_START) {
|
||||
// Pre-lexer code can go here
|
||||
|
||||
var YYSTATE=YY_START;
|
||||
var YYSTATE = YY_START
|
||||
switch ($avoiding_name_collisions) {
|
||||
case 0:return 9;
|
||||
break;
|
||||
case 1:return 10;
|
||||
break;
|
||||
case 2:return 4;
|
||||
break;
|
||||
case 3:return 12;
|
||||
break;
|
||||
case 4:return 13;
|
||||
break;
|
||||
case 5:return 6;
|
||||
break;
|
||||
case 6:return 'INVALID';
|
||||
break;
|
||||
case 0:return 9
|
||||
break
|
||||
case 1:return 10
|
||||
break
|
||||
case 2:return 4
|
||||
break
|
||||
case 3:return 12
|
||||
break
|
||||
case 4:return 13
|
||||
break
|
||||
case 5:return 6
|
||||
break
|
||||
case 6:return 'INVALID'
|
||||
break
|
||||
}
|
||||
},
|
||||
rules: [/^(?:[\n]+)/i, /^(?:showInfo\b)/i, /^(?:info\b)/i, /^(?:say\b)/i, /^(?::[^#\n;]+)/i, /^(?:$)/i, /^(?:.)/i],
|
||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
conditions: {'INITIAL': {'rules': [0, 1, 2, 3, 4, 5, 6], 'inclusive': true}}
|
||||
})
|
||||
return lexer
|
||||
})()
|
||||
parser.lexer = lexer
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
this.yy = {}
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
|
||||
Parser.prototype = parser; parser.Parser = Parser
|
||||
return new Parser()
|
||||
})()
|
||||
|
||||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||||
exports.parser = parser;
|
||||
exports.Parser = parser.Parser;
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments); };
|
||||
exports.parser = parser
|
||||
exports.Parser = parser.Parser
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments) }
|
||||
exports.main = function commonjsMain (args) {
|
||||
if (!args[1]) {
|
||||
console.log('Usage: '+args[0]+' FILE');
|
||||
process.exit(1);
|
||||
console.log('Usage: ' + args[0] + ' FILE')
|
||||
process.exit(1)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), 'utf8')
|
||||
return exports.parser.parse(source)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||||
return exports.parser.parse(source);
|
||||
};
|
||||
if (typeof module !== 'undefined' && require.main === module) {
|
||||
exports.main(process.argv.slice(1));
|
||||
exports.main(process.argv.slice(1))
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
/* global window */
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
|
||||
var dagreD3;
|
||||
var dagreD3
|
||||
// log.debug('setting up dagre-d3');
|
||||
if (require) {
|
||||
try {
|
||||
dagreD3 = require('dagre-d3');
|
||||
dagreD3 = require('dagre-d3')
|
||||
// log.debug('Got it (dagre-d3)');
|
||||
} catch (e) {log.debug('Could not load dagre-d3');}
|
||||
} catch (e) { log.debug('Could not load dagre-d3') }
|
||||
}
|
||||
|
||||
if (!dagreD3) {
|
||||
dagreD3 = window.dagreD3;
|
||||
dagreD3 = window.dagreD3
|
||||
}
|
||||
|
||||
module.exports = dagreD3;
|
||||
module.exports = dagreD3
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
/**
|
||||
* Created by knut on 14-12-11.
|
||||
*/
|
||||
var graph = require('./graphDb');
|
||||
var flow = require('./parser/flow');
|
||||
var dot = require('./parser/dot');
|
||||
var d3 = require('../../d3');
|
||||
var dagreD3 = require('./dagre-d3');
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
|
||||
var graph = require('./graphDb')
|
||||
var flow = require('./parser/flow')
|
||||
var dot = require('./parser/dot')
|
||||
var d3 = require('../../d3')
|
||||
var dagreD3 = require('./dagre-d3')
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
|
||||
var conf = {
|
||||
};
|
||||
module.exports.setConf = function(cnf){
|
||||
var keys = Object.keys(cnf);
|
||||
var i;
|
||||
for(i=0;i<keys.length;i++){
|
||||
conf[keys[i]] = cnf[keys[i]];
|
||||
}
|
||||
};
|
||||
module.exports.setConf = function (cnf) {
|
||||
var keys = Object.keys(cnf)
|
||||
var i
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
conf[keys[i]] = cnf[keys[i]]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that adds the vertices found in the graph definition to the graph to be rendered.
|
||||
@@ -26,124 +25,119 @@ module.exports.setConf = function(cnf){
|
||||
* @param g The graph that is to be drawn.
|
||||
*/
|
||||
exports.addVertices = function (vert, g) {
|
||||
var keys = Object.keys(vert);
|
||||
var keys = Object.keys(vert)
|
||||
|
||||
var styleFromStyleArr = function (styleStr, arr) {
|
||||
var i;
|
||||
var i
|
||||
// Create a compound style definition from the style definitions found for the node in the graph definition
|
||||
for (i = 0; i < arr.length; i++) {
|
||||
if (typeof arr[i] !== 'undefined') {
|
||||
styleStr = styleStr + arr[i] + ';';
|
||||
styleStr = styleStr + arr[i] + ';'
|
||||
}
|
||||
}
|
||||
|
||||
return styleStr;
|
||||
};
|
||||
return styleStr
|
||||
}
|
||||
|
||||
// Iterate through each item in the vertice object (containing all the vertices found) in the graph definition
|
||||
keys.forEach(function (id) {
|
||||
var vertice = vert[id];
|
||||
var verticeText;
|
||||
var vertice = vert[id]
|
||||
var verticeText
|
||||
|
||||
/**
|
||||
* Variable for storing the classes for the vertice
|
||||
* @type {string}
|
||||
*/
|
||||
var classStr = '';
|
||||
var classStr = ''
|
||||
|
||||
// log.debug(vertice.classes);
|
||||
|
||||
if (vertice.classes.length > 0) {
|
||||
classStr = vertice.classes.join(' ');
|
||||
classStr = vertice.classes.join(' ')
|
||||
}
|
||||
|
||||
/**
|
||||
* Variable for storing the extracted style for the vertice
|
||||
* @type {string}
|
||||
*/
|
||||
var style = '';
|
||||
var style = ''
|
||||
// Create a compound style definition from the style definitions found for the node in the graph definition
|
||||
style = styleFromStyleArr(style, vertice.styles);
|
||||
style = styleFromStyleArr(style, vertice.styles)
|
||||
|
||||
// Use vertice id as text in the box if no text is provided by the graph definition
|
||||
if (typeof vertice.text === 'undefined') {
|
||||
verticeText = vertice.id;
|
||||
}
|
||||
else {
|
||||
verticeText = vertice.text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var labelTypeStr = '';
|
||||
if(conf.htmlLabels) {
|
||||
labelTypeStr = 'html';
|
||||
verticeText = verticeText.replace(/fa:fa[\w\-]+/g,function(s){
|
||||
return '<i class="fa '+ s.substring(3)+'"></i>';
|
||||
});
|
||||
|
||||
verticeText = vertice.id
|
||||
} else {
|
||||
var svg_label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
|
||||
var rows = verticeText.split(/<br>/);
|
||||
|
||||
var j = 0;
|
||||
for(j=0;j<rows.length;j++){
|
||||
var 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];
|
||||
svg_label.appendChild(tspan);
|
||||
verticeText = vertice.text
|
||||
}
|
||||
|
||||
labelTypeStr = 'svg';
|
||||
verticeText = svg_label;
|
||||
var labelTypeStr = ''
|
||||
if (conf.htmlLabels) {
|
||||
labelTypeStr = 'html'
|
||||
verticeText = verticeText.replace(/fa:fa[\w\-]+/g, function (s) {
|
||||
return '<i class="fa ' + s.substring(3) + '"></i>'
|
||||
})
|
||||
} else {
|
||||
var svg_label = document.createElementNS('http://www.w3.org/2000/svg', 'text')
|
||||
|
||||
var rows = verticeText.split(/<br>/)
|
||||
|
||||
var j = 0
|
||||
for (j = 0; j < rows.length; j++) {
|
||||
var 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]
|
||||
svg_label.appendChild(tspan)
|
||||
}
|
||||
|
||||
labelTypeStr = 'svg'
|
||||
verticeText = svg_label
|
||||
|
||||
// verticeText = verticeText.replace(/<br\/>/g, '\n');
|
||||
// labelTypeStr = 'text';
|
||||
}
|
||||
|
||||
var radious = 0;
|
||||
var _shape = '';
|
||||
var radious = 0
|
||||
var _shape = ''
|
||||
|
||||
// Set the shape based parameters
|
||||
switch (vertice.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 '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';
|
||||
_shape = 'rect'
|
||||
// Need to create a text node if using svg labels, see #367
|
||||
verticeText = conf.htmlLabels ? '' : document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
break;
|
||||
verticeText = conf.htmlLabels ? '' : document.createElementNS('http://www.w3.org/2000/svg', 'text')
|
||||
break
|
||||
default:
|
||||
_shape = 'rect';
|
||||
_shape = 'rect'
|
||||
}
|
||||
// Add the node
|
||||
g.setNode(vertice.id, {labelType: labelTypeStr, shape:_shape, label: verticeText, rx: radious, ry: radious, 'class': classStr, style: style, id:vertice.id});
|
||||
});
|
||||
};
|
||||
g.setNode(vertice.id, {labelType: labelTypeStr, shape: _shape, label: verticeText, rx: radious, ry: radious, 'class': classStr, style: style, id: vertice.id})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Add edges to graph based on parsed graph defninition
|
||||
@@ -151,115 +145,111 @@ exports.addVertices = function (vert, g) {
|
||||
* @param {Object} g The graph object
|
||||
*/
|
||||
exports.addEdges = function (edges, g) {
|
||||
var cnt=0;
|
||||
var cnt = 0
|
||||
|
||||
var defaultStyle;
|
||||
var defaultStyle
|
||||
if (typeof edges.defaultStyle !== 'undefined') {
|
||||
defaultStyle = edges.defaultStyle.toString().replace(/,/g , ';');
|
||||
defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';')
|
||||
}
|
||||
|
||||
edges.forEach(function (edge) {
|
||||
cnt++;
|
||||
var edgeData = {};
|
||||
cnt++
|
||||
var edgeData = {}
|
||||
|
||||
// Set link type for rendering
|
||||
if (edge.type === 'arrow_open') {
|
||||
edgeData.arrowhead = 'none';
|
||||
}
|
||||
else{
|
||||
edgeData.arrowhead = 'normal';
|
||||
edgeData.arrowhead = 'none'
|
||||
} else {
|
||||
edgeData.arrowhead = 'normal'
|
||||
}
|
||||
|
||||
var style = '';
|
||||
|
||||
var style = ''
|
||||
|
||||
if (typeof edge.style !== 'undefined') {
|
||||
edge.style.forEach(function (s) {
|
||||
style = style + s +';';
|
||||
});
|
||||
}
|
||||
else{
|
||||
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.lineInterpolate = edge.interpolate;
|
||||
edgeData.lineInterpolate = edge.interpolate
|
||||
} else {
|
||||
if (typeof edges.defaultInterpolate !== 'undefined') {
|
||||
edgeData.lineInterpolate = edges.defaultInterpolate;
|
||||
edgeData.lineInterpolate = edges.defaultInterpolate
|
||||
}
|
||||
}
|
||||
|
||||
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 (conf.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 = 'stroke: #333; stroke-width: 1.5px;fill:none';
|
||||
edgeData.label = edge.text.replace(/<br>/g, '\n');
|
||||
edgeData.labelType = 'text'
|
||||
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
|
||||
*/
|
||||
exports.getClasses = function (text, isDot) {
|
||||
var parser;
|
||||
graph.clear();
|
||||
var parser
|
||||
graph.clear()
|
||||
if (isDot) {
|
||||
parser = dot.parser;
|
||||
|
||||
parser = dot.parser
|
||||
} else {
|
||||
parser = flow.parser;
|
||||
parser = flow.parser
|
||||
}
|
||||
parser.yy = graph;
|
||||
parser.yy = graph
|
||||
|
||||
// Parse the graph definition
|
||||
parser.parse(text);
|
||||
parser.parse(text)
|
||||
|
||||
var classes = graph.getClasses();
|
||||
var classes = graph.getClasses()
|
||||
|
||||
// Add default class if undefined
|
||||
if (typeof (classes.default) === 'undefined') {
|
||||
classes.default = {id:'default'};
|
||||
classes.default = {id: 'default'}
|
||||
// classes.default.styles = ['fill:#ffa','stroke:#666','stroke-width:3px'];
|
||||
classes.default.styles = [];
|
||||
classes.default.clusterStyles = ['rx:4px','fill: rgb(255, 255, 222)','rx: 4px','stroke: rgb(170, 170, 51)','stroke-width: 1px'];
|
||||
classes.default.nodeLabelStyles = ['fill:#000','stroke:none','font-weight:300','font-family:"Helvetica Neue",Helvetica,Arial,sans-serf','font-size:14px'];
|
||||
classes.default.edgeLabelStyles = ['fill:#000','stroke:none','font-weight:300','font-family:"Helvetica Neue",Helvetica,Arial,sans-serf','font-size:14px'];
|
||||
classes.default.styles = []
|
||||
classes.default.clusterStyles = ['rx:4px', 'fill: rgb(255, 255, 222)', 'rx: 4px', 'stroke: rgb(170, 170, 51)', 'stroke-width: 1px']
|
||||
classes.default.nodeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px']
|
||||
classes.default.edgeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px']
|
||||
}
|
||||
return classes
|
||||
}
|
||||
return classes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||||
@@ -267,31 +257,28 @@ exports.getClasses = function (text, isDot) {
|
||||
* @param id
|
||||
*/
|
||||
exports.draw = function (text, id, isDot) {
|
||||
log.debug('Drawing flowchart');
|
||||
var parser;
|
||||
graph.clear();
|
||||
log.debug('Drawing flowchart')
|
||||
var parser
|
||||
graph.clear()
|
||||
if (isDot) {
|
||||
parser = dot.parser;
|
||||
|
||||
parser = dot.parser
|
||||
} else {
|
||||
parser = flow.parser;
|
||||
parser = flow.parser
|
||||
}
|
||||
parser.yy = graph;
|
||||
parser.yy = graph
|
||||
|
||||
// Parse the graph definition
|
||||
try {
|
||||
|
||||
parser.parse(text);
|
||||
}
|
||||
catch(err){
|
||||
log.debug('Parsing failed');
|
||||
parser.parse(text)
|
||||
} catch (err) {
|
||||
log.debug('Parsing failed')
|
||||
}
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
var dir;
|
||||
dir = graph.getDirection();
|
||||
var dir
|
||||
dir = graph.getDirection()
|
||||
if (typeof dir === 'undefined') {
|
||||
dir='TD';
|
||||
dir = 'TD'
|
||||
}
|
||||
|
||||
// Create the input mermaid.graph
|
||||
@@ -306,40 +293,40 @@ exports.draw = function (text, id,isDot) {
|
||||
|
||||
})
|
||||
.setDefaultEdgeLabel(function () {
|
||||
return {};
|
||||
});
|
||||
return {}
|
||||
})
|
||||
|
||||
var subG;
|
||||
var subGraphs = graph.getSubGraphs();
|
||||
var i = 0;
|
||||
var subG
|
||||
var subGraphs = graph.getSubGraphs()
|
||||
var i = 0
|
||||
for (i = subGraphs.length - 1; i >= 0; i--) {
|
||||
subG = subGraphs[i];
|
||||
graph.addVertex(subG.id,subG.title,'group',undefined);
|
||||
subG = subGraphs[i]
|
||||
graph.addVertex(subG.id, subG.title, 'group', undefined)
|
||||
}
|
||||
|
||||
// Fetch the verices/nodes and edges/links from the parsed graph definition
|
||||
var vert = graph.getVertices();
|
||||
var vert = graph.getVertices()
|
||||
|
||||
// log.debug(vert);
|
||||
var edges = graph.getEdges();
|
||||
var edges = graph.getEdges()
|
||||
|
||||
i = 0;
|
||||
var j;
|
||||
i = 0
|
||||
var j
|
||||
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 (j = 0; j < subG.nodes.length; j++) {
|
||||
// log.debug('Setting node',subG.nodes[j],' to subgraph '+id);
|
||||
g.setParent(subG.nodes[j],subG.id);
|
||||
g.setParent(subG.nodes[j], subG.id)
|
||||
}
|
||||
}
|
||||
exports.addVertices(vert, g);
|
||||
exports.addEdges(edges, g);
|
||||
exports.addVertices(vert, g)
|
||||
exports.addEdges(edges, g)
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
var render = new dagreD3.render()
|
||||
|
||||
// Add custom shape for rhombus type of boc (decision)
|
||||
render.shapes().question = function (parent, bbox, node) {
|
||||
@@ -351,19 +338,19 @@ exports.draw = function (text, id,isDot) {
|
||||
{x: s, y: -s / 2},
|
||||
{x: s / 2, y: -s},
|
||||
{x: 0, y: -s / 2}
|
||||
];
|
||||
]
|
||||
var shapeSvg = parent.insert('polygon', ':first-child')
|
||||
.attr('points', points.map(function (d) {
|
||||
return d.x + ',' + d.y;
|
||||
return d.x + ',' + d.y
|
||||
}).join(' '))
|
||||
.attr('rx', 5)
|
||||
.attr('ry', 5)
|
||||
.attr('transform', 'translate(' + (-s / 2) + ',' + (s * 2 / 4) + ')');
|
||||
.attr('transform', 'translate(' + (-s / 2) + ',' + (s * 2 / 4) + ')')
|
||||
node.intersect = function (point) {
|
||||
return dagreD3.intersect.polygon(node, points, point);
|
||||
};
|
||||
return shapeSvg;
|
||||
};
|
||||
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) {
|
||||
@@ -375,17 +362,17 @@ exports.draw = function (text, id,isDot) {
|
||||
{x: w, y: -h},
|
||||
{x: -h / 2, y: -h},
|
||||
{x: 0, y: -h / 2}
|
||||
];
|
||||
]
|
||||
var shapeSvg = parent.insert('polygon', ':first-child')
|
||||
.attr('points', points.map(function (d) {
|
||||
return d.x + ',' + d.y;
|
||||
return d.x + ',' + d.y
|
||||
}).join(' '))
|
||||
.attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')');
|
||||
.attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
|
||||
node.intersect = function (point) {
|
||||
return dagreD3.intersect.polygon(node, points, point);
|
||||
};
|
||||
return shapeSvg;
|
||||
};
|
||||
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) {
|
||||
@@ -397,17 +384,17 @@ exports.draw = function (text, id,isDot) {
|
||||
{x: w, y: -h / 2},
|
||||
{x: w + h / 2, y: -h},
|
||||
{x: 0, y: -h}
|
||||
];
|
||||
]
|
||||
var shapeSvg = parent.insert('polygon', ':first-child')
|
||||
.attr('points', points.map(function (d) {
|
||||
return d.x + ',' + d.y;
|
||||
return d.x + ',' + d.y
|
||||
}).join(' '))
|
||||
.attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')');
|
||||
.attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')')
|
||||
node.intersect = function (point) {
|
||||
return dagreD3.intersect.polygon(node, points, point);
|
||||
};
|
||||
return shapeSvg;
|
||||
};
|
||||
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) {
|
||||
@@ -419,45 +406,45 @@ exports.draw = function (text, id,isDot) {
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto');
|
||||
.attr('orient', 'auto')
|
||||
|
||||
var path = marker.append('path')
|
||||
.attr('d', 'M 0 0 L 0 0 L 0 0 z');
|
||||
dagreD3.util.applyStyle(path, edge[type + 'Style']);
|
||||
};
|
||||
.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) {
|
||||
var marker = parent.append("marker")
|
||||
.attr("id", id)
|
||||
.attr("viewBox", "0 0 10 10")
|
||||
.attr("refX", 9)
|
||||
.attr("refY", 5)
|
||||
.attr("markerUnits", "strokeWidth")
|
||||
.attr("markerWidth", 8)
|
||||
.attr("markerHeight", 6)
|
||||
.attr("orient", "auto")
|
||||
var marker = parent.append('marker')
|
||||
.attr('id', id)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', 9)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto')
|
||||
|
||||
var 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");
|
||||
};
|
||||
var 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')
|
||||
}
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
var svg = d3.select('#' + id);
|
||||
var svg = d3.select('#' + id)
|
||||
// svgGroup = d3.select('#' + id + ' g');
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
var element = d3.select('#' + id + ' g');
|
||||
render(element, g);
|
||||
var element = d3.select('#' + id + ' g')
|
||||
render(element, g)
|
||||
|
||||
// var tip = d3.tip().html(function(d) { return d; });
|
||||
element.selectAll('g.node')
|
||||
.attr('title', function () {
|
||||
return graph.getTooltip(this.id);
|
||||
});
|
||||
return graph.getTooltip(this.id)
|
||||
})
|
||||
|
||||
/*
|
||||
var xPos = document.querySelectorAll('.clusters rect')[0].x.baseVal.value;
|
||||
@@ -473,77 +460,73 @@ exports.draw = function (text, id,isDot) {
|
||||
*/
|
||||
if (conf.useMaxWidth) {
|
||||
// Center the graph
|
||||
svg.attr('height', '100%');
|
||||
svg.attr('width', conf.width);
|
||||
svg.attr('height', '100%')
|
||||
svg.attr('width', conf.width)
|
||||
// svg.attr('viewBox', svgb.getBBox().x + ' 0 '+ g.graph().width+' '+ g.graph().height);
|
||||
svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
|
||||
svg.attr('style', 'max-width:' + (g.graph().width + 20) + 'px;');
|
||||
}
|
||||
else{
|
||||
// Center the graph
|
||||
svg.attr('height', g.graph().height );
|
||||
if(typeof conf.width === 'undefined'){
|
||||
svg.attr('width', g.graph().width );
|
||||
svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
|
||||
svg.attr('style', 'max-width:' + (g.graph().width + 20) + 'px;')
|
||||
} else {
|
||||
svg.attr('width', conf.width );
|
||||
// Center the graph
|
||||
svg.attr('height', g.graph().height)
|
||||
if (typeof conf.width === 'undefined') {
|
||||
svg.attr('width', g.graph().width)
|
||||
} else {
|
||||
svg.attr('width', conf.width)
|
||||
}
|
||||
// svg.attr('viewBox', svgb.getBBox().x + ' 0 '+ g.graph().width+' '+ g.graph().height);
|
||||
svg.attr('viewBox', '0 0 ' + (g.graph().width+20) + ' ' + (g.graph().height+20)); }
|
||||
|
||||
svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20))
|
||||
}
|
||||
|
||||
// Index nodes
|
||||
graph.indexNodes('subGraph'+i);
|
||||
graph.indexNodes('subGraph' + i)
|
||||
|
||||
for (i = 0; i < subGraphs.length; i++) {
|
||||
subG = subGraphs[i];
|
||||
subG = subGraphs[i]
|
||||
|
||||
if (subG.title !== 'undefined') {
|
||||
var clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect');
|
||||
var clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect')
|
||||
// log.debug('looking up: #' + id + ' #' + subG.id)
|
||||
var clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id);
|
||||
var clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id)
|
||||
|
||||
var xPos = clusterRects[0].x.baseVal.value;
|
||||
var yPos = clusterRects[0].y.baseVal.value;
|
||||
var width = clusterRects[0].width.baseVal.value;
|
||||
var cluster = d3.select(clusterEl[0]);
|
||||
var te = cluster.append('text');
|
||||
te.attr('x', xPos + width / 2);
|
||||
te.attr('y', yPos + 14);
|
||||
te.attr('fill', 'black');
|
||||
te.attr('stroke', 'none');
|
||||
te.attr('id', id + 'Text');
|
||||
te.style('text-anchor', 'middle');
|
||||
var xPos = clusterRects[0].x.baseVal.value
|
||||
var yPos = clusterRects[0].y.baseVal.value
|
||||
var width = clusterRects[0].width.baseVal.value
|
||||
var cluster = d3.select(clusterEl[0])
|
||||
var te = cluster.append('text')
|
||||
te.attr('x', xPos + width / 2)
|
||||
te.attr('y', yPos + 14)
|
||||
te.attr('fill', 'black')
|
||||
te.attr('stroke', 'none')
|
||||
te.attr('id', id + 'Text')
|
||||
te.style('text-anchor', 'middle')
|
||||
|
||||
if (typeof subG.title === 'undefined') {
|
||||
te.text('Undef');
|
||||
te.text('Undef')
|
||||
} else {
|
||||
// te.text(subGraphs[subGraphs.length-i-1].title);
|
||||
te.text(subG.title);
|
||||
|
||||
te.text(subG.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf.htmlLabels) {
|
||||
var labels = document.querySelectorAll('#' + id +' .edgeLabel .label');
|
||||
var i;
|
||||
var labels = document.querySelectorAll('#' + id + ' .edgeLabel .label')
|
||||
var i
|
||||
for (i = 0; i < labels.length; i++) {
|
||||
var label = labels[i];
|
||||
var label = labels[i]
|
||||
|
||||
// Get dimensions of label
|
||||
var dim = label.getBBox();
|
||||
var dim = label.getBBox()
|
||||
|
||||
var 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;');
|
||||
var 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/**
|
||||
* Created by knut on 14-11-03.
|
||||
*/
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var utils = require('../../utils');
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
var utils = require('../../utils')
|
||||
|
||||
var d3 = require('../../d3');
|
||||
var vertices = {};
|
||||
var edges = [];
|
||||
var classes = [];
|
||||
var subGraphs = [];
|
||||
var tooltips = {};
|
||||
var subCount=0;
|
||||
var direction;
|
||||
var d3 = require('../../d3')
|
||||
var vertices = {}
|
||||
var edges = []
|
||||
var classes = []
|
||||
var subGraphs = []
|
||||
var tooltips = {}
|
||||
var subCount = 0
|
||||
var direction
|
||||
// Functions to be run after graph rendering
|
||||
var funs = [];
|
||||
var funs = []
|
||||
/**
|
||||
* Function called by parser when a node definition has been found
|
||||
* @param id
|
||||
@@ -23,42 +23,42 @@ var funs = [];
|
||||
* @param style
|
||||
*/
|
||||
exports.addVertex = function (id, text, type, style) {
|
||||
var txt;
|
||||
var txt
|
||||
|
||||
if (typeof id === 'undefined') {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (id.trim().length === 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof vertices[id] === 'undefined') {
|
||||
vertices[id] = {id: id, styles: [], classes:[]};
|
||||
vertices[id] = {id: id, styles: [], classes: []}
|
||||
}
|
||||
if (typeof text !== 'undefined') {
|
||||
txt = text.trim();
|
||||
txt = text.trim()
|
||||
|
||||
// strip quotes if string starts and exnds with a quote
|
||||
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
|
||||
txt = txt.substring(1,txt.length-1);
|
||||
txt = txt.substring(1, txt.length - 1)
|
||||
}
|
||||
|
||||
vertices[id].text = txt;
|
||||
vertices[id].text = txt
|
||||
}
|
||||
if (typeof type !== 'undefined') {
|
||||
vertices[id].type = type;
|
||||
vertices[id].type = type
|
||||
}
|
||||
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);
|
||||
});
|
||||
vertices[id].styles.push(s)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function called by parser when a link/edge definition has been found
|
||||
@@ -68,25 +68,25 @@ exports.addVertex = function (id, text, type, style) {
|
||||
* @param linktext
|
||||
*/
|
||||
exports.addLink = function (start, end, type, linktext) {
|
||||
log.info('Got edge...', start, end);
|
||||
var edge = {start: start, end: end, type: undefined, text: ''};
|
||||
linktext = type.text;
|
||||
log.info('Got edge...', start, end)
|
||||
var edge = {start: start, end: end, type: undefined, text: ''}
|
||||
linktext = type.text
|
||||
|
||||
if (typeof linktext !== 'undefined') {
|
||||
edge.text = linktext.trim();
|
||||
edge.text = linktext.trim()
|
||||
|
||||
// strip quotes if string starts and exnds with a quote
|
||||
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
|
||||
edge.text = edge.text.substring(1,edge.text.length-1);
|
||||
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
|
||||
@@ -95,11 +95,11 @@ exports.addLink = function (start, end, type, linktext) {
|
||||
*/
|
||||
exports.updateLinkInterpolate = function (pos, interp) {
|
||||
if (pos === 'default') {
|
||||
edges.defaultInterpolate = interp;
|
||||
edges.defaultInterpolate = interp
|
||||
} else {
|
||||
edges[pos].interpolate = interp;
|
||||
edges[pos].interpolate = interp
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates a link with a style
|
||||
@@ -108,36 +108,36 @@ exports.updateLinkInterpolate = function (pos, interp) {
|
||||
*/
|
||||
exports.updateLink = function (pos, style) {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
exports.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);
|
||||
});
|
||||
classes[id].styles.push(s)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||||
* @param dir
|
||||
*/
|
||||
exports.setDirection = function (dir) {
|
||||
direction = dir;
|
||||
};
|
||||
direction = dir
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||||
@@ -147,56 +147,56 @@ exports.setClass = function (id,className) {
|
||||
if (id.indexOf(',') > 0) {
|
||||
id.split(',').forEach(function (id2) {
|
||||
if (typeof vertices[id2] !== 'undefined') {
|
||||
vertices[id2].classes.push(className);
|
||||
vertices[id2].classes.push(className)
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
if (typeof vertices[id] !== 'undefined') {
|
||||
vertices[id].classes.push(className);
|
||||
vertices[id].classes.push(className)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var setTooltip = function (id, tooltip) {
|
||||
if (typeof tooltip !== 'undefined') {
|
||||
tooltips[id]=tooltip;
|
||||
tooltips[id] = tooltip
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var setClickFun = function (id, functionName) {
|
||||
if (typeof functionName === 'undefined') {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (typeof vertices[id] !== 'undefined') {
|
||||
funs.push(function (element) {
|
||||
var elem = d3.select(element).select('#'+id);
|
||||
var elem = d3.select(element).select('#' + id)
|
||||
if (elem !== null) {
|
||||
elem.on('click', function () {
|
||||
eval(functionName + '(\'' + id + '\')'); // jshint ignore:line
|
||||
});
|
||||
eval(functionName + '(\'' + id + '\')') // jshint ignore:line
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var setLink = function (id, linkStr) {
|
||||
if (typeof linkStr === 'undefined') {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (typeof vertices[id] !== 'undefined') {
|
||||
funs.push(function (element) {
|
||||
var elem = d3.select(element).select('#'+id);
|
||||
var elem = d3.select(element).select('#' + id)
|
||||
if (elem !== null) {
|
||||
elem.on('click', function () {
|
||||
window.open(linkStr,'newTab'); // jshint ignore:line
|
||||
});
|
||||
window.open(linkStr, 'newTab') // jshint ignore:line
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.getTooltip = function (id) {
|
||||
return tooltips[id];
|
||||
};
|
||||
return tooltips[id]
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||||
@@ -205,217 +205,206 @@ exports.getTooltip = function(id){
|
||||
exports.setClickEvent = function (id, functionName, link, tooltip) {
|
||||
if (id.indexOf(',') > 0) {
|
||||
id.split(',').forEach(function (id2) {
|
||||
setTooltip(id2,tooltip);
|
||||
setClickFun(id2, functionName);
|
||||
setLink(id2, link);
|
||||
});
|
||||
setTooltip(id2, tooltip)
|
||||
setClickFun(id2, functionName)
|
||||
setLink(id2, link)
|
||||
})
|
||||
} else {
|
||||
setTooltip(id,tooltip);
|
||||
setClickFun(id, functionName);
|
||||
setLink(id, link);
|
||||
setTooltip(id, tooltip)
|
||||
setClickFun(id, functionName)
|
||||
setLink(id, link)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.bindFunctions = function (element) {
|
||||
funs.forEach(function (fun) {
|
||||
fun(element);
|
||||
});
|
||||
};
|
||||
fun(element)
|
||||
})
|
||||
}
|
||||
exports.getDirection = function () {
|
||||
return direction;
|
||||
};
|
||||
return direction
|
||||
}
|
||||
/**
|
||||
* Retrieval function for fetching the found nodes after parsing has completed.
|
||||
* @returns {{}|*|vertices}
|
||||
*/
|
||||
exports.getVertices = function () {
|
||||
return vertices;
|
||||
};
|
||||
return vertices
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieval function for fetching the found links after parsing has completed.
|
||||
* @returns {{}|*|edges}
|
||||
*/
|
||||
exports.getEdges = function () {
|
||||
return edges;
|
||||
};
|
||||
return edges
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieval function for fetching the found class definitions after parsing has completed.
|
||||
* @returns {{}|*|classes}
|
||||
*/
|
||||
exports.getClasses = function () {
|
||||
return classes;
|
||||
};
|
||||
return classes
|
||||
}
|
||||
|
||||
var setupToolTips = function (element) {
|
||||
|
||||
var tooltipElem = d3.select('.mermaidTooltip');
|
||||
var tooltipElem = d3.select('.mermaidTooltip')
|
||||
if (tooltipElem[0][0] === null) {
|
||||
tooltipElem = d3.select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
.style('opacity', 0);
|
||||
.style('opacity', 0)
|
||||
}
|
||||
|
||||
var svg = d3.select(element).select('svg');
|
||||
var svg = d3.select(element).select('svg')
|
||||
|
||||
var nodes = svg.selectAll('g.node');
|
||||
var nodes = svg.selectAll('g.node')
|
||||
nodes
|
||||
.on('mouseover', function () {
|
||||
var el = d3.select(this);
|
||||
var title = el.attr('title');
|
||||
var el = d3.select(this)
|
||||
var title = el.attr('title')
|
||||
// Dont try to draw a tooltip if no data is provided
|
||||
if (title === null) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
var rect = this.getBoundingClientRect();
|
||||
var rect = this.getBoundingClientRect()
|
||||
|
||||
tooltipElem.transition()
|
||||
.duration(200)
|
||||
.style('opacity', '.9');
|
||||
.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('top', (rect.top - 14 + document.body.scrollTop) + 'px')
|
||||
el.classed('hover', true)
|
||||
})
|
||||
.on('mouseout', function () {
|
||||
tooltipElem.transition()
|
||||
.duration(500)
|
||||
.style('opacity', 0);
|
||||
var el = d3.select(this);
|
||||
el.classed('hover',false);
|
||||
});
|
||||
};
|
||||
funs.push(setupToolTips);
|
||||
.style('opacity', 0)
|
||||
var el = d3.select(this)
|
||||
el.classed('hover', false)
|
||||
})
|
||||
}
|
||||
funs.push(setupToolTips)
|
||||
|
||||
/**
|
||||
* Clears the internal graph db so that a new graph can be parsed.
|
||||
*/
|
||||
exports.clear = function () {
|
||||
vertices = {};
|
||||
classes = {};
|
||||
edges = [];
|
||||
funs = [];
|
||||
funs.push(setupToolTips);
|
||||
subGraphs = [];
|
||||
subCount = 0;
|
||||
tooltips = [];
|
||||
};
|
||||
vertices = {}
|
||||
classes = {}
|
||||
edges = []
|
||||
funs = []
|
||||
funs.push(setupToolTips)
|
||||
subGraphs = []
|
||||
subCount = 0
|
||||
tooltips = []
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
exports.defaultStyle = function () {
|
||||
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;';
|
||||
};
|
||||
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;'
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the internal graph db so that a new graph can be parsed.
|
||||
*/
|
||||
exports.addSubGraph = function (list, title) {
|
||||
function uniq (a) {
|
||||
var prims = {'boolean':{}, 'number':{}, 'string':{}}, objs = [];
|
||||
var prims = {'boolean': {}, 'number': {}, 'string': {}}, objs = []
|
||||
|
||||
return a.filter(function (item) {
|
||||
var type = typeof item;
|
||||
var type = typeof item
|
||||
if (item === ' ') {
|
||||
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) }
|
||||
})
|
||||
}
|
||||
|
||||
var nodeList = [];
|
||||
var nodeList = []
|
||||
|
||||
nodeList = uniq(nodeList.concat.apply(nodeList,list));
|
||||
nodeList = uniq(nodeList.concat.apply(nodeList, list))
|
||||
|
||||
|
||||
var subGraph = {id:'subGraph'+subCount, nodes:nodeList,title:title};
|
||||
var subGraph = {id: 'subGraph' + subCount, nodes: nodeList, title: title}
|
||||
// log.debug('subGraph:' + subGraph.title + subGraph.id);
|
||||
// log.debug(subGraph.nodes);
|
||||
subGraphs.push(subGraph);
|
||||
subCount = subCount + 1;
|
||||
return subGraph.id;
|
||||
};
|
||||
subGraphs.push(subGraph)
|
||||
subCount = subCount + 1
|
||||
return subGraph.id
|
||||
}
|
||||
|
||||
var getPosForId = function (id) {
|
||||
var i;
|
||||
var i
|
||||
for (i = 0; i < subGraphs.length; i++) {
|
||||
if (subGraphs[i].id === id) {
|
||||
// log.debug('Found pos for ',id,' ',i);
|
||||
return i;
|
||||
return i
|
||||
}
|
||||
}
|
||||
// log.debug('No pos found for ',id,' ',i);
|
||||
return -1;
|
||||
};
|
||||
var secCount = -1;
|
||||
var posCrossRef = [];
|
||||
return -1
|
||||
}
|
||||
var secCount = -1
|
||||
var posCrossRef = []
|
||||
var indexNodes = function (id, pos) {
|
||||
var nodes = subGraphs[pos].nodes;
|
||||
secCount = secCount + 1;
|
||||
var nodes = subGraphs[pos].nodes
|
||||
secCount = secCount + 1
|
||||
if (secCount > 2000) {
|
||||
return;
|
||||
|
||||
return
|
||||
}
|
||||
// var nPos = getPosForId(subGraphs[pos].id);
|
||||
posCrossRef[secCount]=pos;
|
||||
posCrossRef[secCount] = pos
|
||||
// Check if match
|
||||
if (subGraphs[pos].id === id) {
|
||||
return {
|
||||
result: true,
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var count = 0;
|
||||
var posCount = 1;
|
||||
var count = 0
|
||||
var posCount = 1
|
||||
while (count < nodes.length) {
|
||||
var childPos = getPosForId(nodes[count]);
|
||||
var childPos = getPosForId(nodes[count])
|
||||
// Ignore regular nodes (pos will be -1)
|
||||
if (childPos >= 0) {
|
||||
var res = indexNodes(id,childPos);
|
||||
var res = indexNodes(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
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
exports.getDepthFirstPos = function (pos) {
|
||||
return posCrossRef[pos];
|
||||
};
|
||||
exports.indexNodes = function () {
|
||||
secCount = -1;
|
||||
if(subGraphs.length>0){
|
||||
indexNodes('none',subGraphs.length-1,0);
|
||||
return posCrossRef[pos]
|
||||
}
|
||||
exports.indexNodes = function () {
|
||||
secCount = -1
|
||||
if (subGraphs.length > 0) {
|
||||
indexNodes('none', subGraphs.length - 1, 0)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.getSubGraphs = function () {
|
||||
return subGraphs;
|
||||
};
|
||||
return subGraphs
|
||||
}
|
||||
|
||||
exports.parseError = function (err, hash) {
|
||||
global.mermaidAPI.parseError(err,hash);
|
||||
};
|
||||
global.mermaidAPI.parseError(err, hash)
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -2,34 +2,34 @@
|
||||
* Created by knut on 14-11-18.
|
||||
*/
|
||||
describe('when parsing a gantt diagram it', function () {
|
||||
var gantt;
|
||||
var gantt
|
||||
beforeEach(function () {
|
||||
gantt = require('./parser/gantt').parser;
|
||||
gantt.yy = require('./ganttDb');
|
||||
gantt = require('./parser/gantt').parser
|
||||
gantt.yy = require('./ganttDb')
|
||||
|
||||
// ex.yy.parseError = parseError;
|
||||
});
|
||||
})
|
||||
|
||||
it('should handle an dateFormat definition', function () {
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd';
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd'
|
||||
|
||||
gantt.parse(str);
|
||||
});
|
||||
gantt.parse(str)
|
||||
})
|
||||
it('should handle an dateFormat definition', function () {
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid'
|
||||
|
||||
gantt.parse(str);
|
||||
});
|
||||
gantt.parse(str)
|
||||
})
|
||||
it('should handle an dateFormat definition', function () {
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid'
|
||||
|
||||
gantt.parse(str);
|
||||
});
|
||||
gantt.parse(str)
|
||||
})
|
||||
it('should handle an section definition', function () {
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid';
|
||||
var str = 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid'
|
||||
|
||||
gantt.parse(str);
|
||||
});
|
||||
gantt.parse(str)
|
||||
})
|
||||
/**
|
||||
* Beslutsflöde inligt nedan. Obs bla bla bla
|
||||
* ```
|
||||
@@ -46,10 +46,10 @@ describe('when parsing a gantt diagram it',function() {
|
||||
'dateFormat yyyy-mm-dd\n' +
|
||||
'title Adding gantt diagram functionality to mermaid\n' +
|
||||
'section Documentation\n' +
|
||||
'Design jison grammar:des1, 2014-01-01, 2014-01-04';
|
||||
'Design jison grammar:des1, 2014-01-01, 2014-01-04'
|
||||
|
||||
gantt.parse(str);
|
||||
});
|
||||
});
|
||||
gantt.parse(str)
|
||||
})
|
||||
})
|
||||
|
||||
// Ogiltigt id i after id
|
||||
|
||||
@@ -1,59 +1,57 @@
|
||||
/**
|
||||
* Created by knut on 15-01-14.
|
||||
*/
|
||||
var moment = require('moment');
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var moment = require('moment')
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
|
||||
|
||||
var dateFormat = '';
|
||||
var title = '';
|
||||
var sections = [];
|
||||
var tasks = [];
|
||||
var currentSection = '';
|
||||
var dateFormat = ''
|
||||
var title = ''
|
||||
var sections = []
|
||||
var tasks = []
|
||||
var currentSection = ''
|
||||
|
||||
exports.clear = function () {
|
||||
sections = [];
|
||||
tasks = [];
|
||||
currentSection = '';
|
||||
title = '';
|
||||
taskCnt = 0;
|
||||
lastTask = undefined;
|
||||
lastTaskID = undefined;
|
||||
rawTasks = [];
|
||||
};
|
||||
|
||||
exports.setDateFormat = function(txt){
|
||||
dateFormat = txt;
|
||||
};
|
||||
|
||||
exports.getDateFormat = function(){
|
||||
return dateFormat;
|
||||
};
|
||||
exports.setTitle = function(txt){
|
||||
title = txt;
|
||||
};
|
||||
|
||||
exports.getTitle = function(){
|
||||
return title;
|
||||
};
|
||||
|
||||
exports.addSection = function(txt){
|
||||
currentSection = txt;
|
||||
sections.push(txt);
|
||||
};
|
||||
|
||||
|
||||
exports.getTasks=function(){
|
||||
var allItemsPricessed = compileTasks();
|
||||
var maxDepth = 10;
|
||||
var iterationCount = 0;
|
||||
while(!allItemsPricessed && (iterationCount < maxDepth)){
|
||||
allItemsPricessed = compileTasks();
|
||||
iterationCount++;
|
||||
sections = []
|
||||
tasks = []
|
||||
currentSection = ''
|
||||
title = ''
|
||||
taskCnt = 0
|
||||
lastTask = undefined
|
||||
lastTaskID = undefined
|
||||
rawTasks = []
|
||||
}
|
||||
|
||||
tasks = rawTasks;
|
||||
exports.setDateFormat = function (txt) {
|
||||
dateFormat = txt
|
||||
}
|
||||
|
||||
exports.getDateFormat = function () {
|
||||
return dateFormat
|
||||
}
|
||||
exports.setTitle = function (txt) {
|
||||
title = txt
|
||||
}
|
||||
|
||||
exports.getTitle = function () {
|
||||
return title
|
||||
}
|
||||
|
||||
exports.addSection = function (txt) {
|
||||
currentSection = txt
|
||||
sections.push(txt)
|
||||
}
|
||||
|
||||
exports.getTasks = function () {
|
||||
var allItemsPricessed = compileTasks()
|
||||
var maxDepth = 10
|
||||
var iterationCount = 0
|
||||
while (!allItemsPricessed && (iterationCount < maxDepth)) {
|
||||
allItemsPricessed = compileTasks()
|
||||
iterationCount++
|
||||
}
|
||||
|
||||
tasks = rawTasks
|
||||
|
||||
// var i;
|
||||
// for(i=10000;i<tasks.length;i++){
|
||||
@@ -61,92 +59,90 @@ exports.getTasks=function(){
|
||||
// tasks[i].endTime = moment(tasks[i].endTime).format(dateFormat);
|
||||
// }
|
||||
|
||||
return tasks;
|
||||
};
|
||||
|
||||
return tasks
|
||||
}
|
||||
|
||||
var getStartDate = function (prevTime, dateFormat, str) {
|
||||
// console.log('Deciding start date:'+JSON.stringify(str));
|
||||
// log.debug('Deciding start date:'+str);
|
||||
// log.debug('with dateformat:'+dateFormat);
|
||||
|
||||
str = str.trim();
|
||||
str = str.trim()
|
||||
|
||||
// Test for after
|
||||
var re = /^after\s+([\d\w\-]+)/;
|
||||
var afterStatement = re.exec(str.trim());
|
||||
var re = /^after\s+([\d\w\-]+)/
|
||||
var afterStatement = re.exec(str.trim())
|
||||
|
||||
if (afterStatement !== null) {
|
||||
var task = exports.findTaskById(afterStatement[1]);
|
||||
var task = exports.findTaskById(afterStatement[1])
|
||||
|
||||
if (typeof task === 'undefined') {
|
||||
var dt = new Date();
|
||||
dt.setHours(0,0,0,0);
|
||||
return dt;
|
||||
var dt = new Date()
|
||||
dt.setHours(0, 0, 0, 0)
|
||||
return dt
|
||||
// return undefined;
|
||||
}
|
||||
return task.endTime;
|
||||
return task.endTime
|
||||
}
|
||||
|
||||
// Check for actual date set
|
||||
if (moment(str, dateFormat.trim(), true).isValid()) {
|
||||
return moment(str,dateFormat.trim(),true).toDate();
|
||||
return moment(str, dateFormat.trim(), true).toDate()
|
||||
} else {
|
||||
log.debug('Invalid date:'+str);
|
||||
log.debug('With date format:'+dateFormat.trim());
|
||||
log.debug('Invalid date:' + str)
|
||||
log.debug('With date format:' + dateFormat.trim())
|
||||
// log.debug('----');
|
||||
}
|
||||
|
||||
// Default date - now
|
||||
return new Date();
|
||||
};
|
||||
return new Date()
|
||||
}
|
||||
|
||||
var getEndDate = function (prevTime, dateFormat, str) {
|
||||
str = str.trim();
|
||||
str = str.trim()
|
||||
|
||||
// Check for actual date
|
||||
if (moment(str, dateFormat.trim(), true).isValid()) {
|
||||
|
||||
return moment(str,dateFormat.trim()).toDate();
|
||||
return moment(str, dateFormat.trim()).toDate()
|
||||
}
|
||||
|
||||
var d = moment(prevTime);
|
||||
var d = moment(prevTime)
|
||||
// Check for length
|
||||
var re = /^([\d]+)([wdhms])/;
|
||||
var durationStatement = re.exec(str.trim());
|
||||
var re = /^([\d]+)([wdhms])/
|
||||
var durationStatement = re.exec(str.trim())
|
||||
|
||||
if (durationStatement !== null) {
|
||||
switch (durationStatement[2]) {
|
||||
case 's':
|
||||
d.add(durationStatement[1], 'seconds');
|
||||
break;
|
||||
d.add(durationStatement[1], 'seconds')
|
||||
break
|
||||
case 'm':
|
||||
d.add(durationStatement[1], 'minutes');
|
||||
break;
|
||||
d.add(durationStatement[1], 'minutes')
|
||||
break
|
||||
case 'h':
|
||||
d.add(durationStatement[1], 'hours');
|
||||
break;
|
||||
d.add(durationStatement[1], 'hours')
|
||||
break
|
||||
case 'd':
|
||||
d.add(durationStatement[1], 'days');
|
||||
break;
|
||||
d.add(durationStatement[1], 'days')
|
||||
break
|
||||
case 'w':
|
||||
d.add(durationStatement[1], 'weeks');
|
||||
break;
|
||||
d.add(durationStatement[1], 'weeks')
|
||||
break
|
||||
}
|
||||
return d.toDate();
|
||||
return d.toDate()
|
||||
}
|
||||
// Default date - now
|
||||
return d.toDate();
|
||||
};
|
||||
return d.toDate()
|
||||
}
|
||||
|
||||
var taskCnt = 0;
|
||||
var taskCnt = 0
|
||||
var parseId = function (idStr) {
|
||||
if (typeof idStr === 'undefined') {
|
||||
taskCnt = taskCnt + 1;
|
||||
return 'task'+taskCnt;
|
||||
taskCnt = taskCnt + 1
|
||||
return 'task' + taskCnt
|
||||
}
|
||||
return idStr
|
||||
}
|
||||
return idStr;
|
||||
};
|
||||
// id, startDate, endDate
|
||||
// id, startDate, length
|
||||
// id, after x, endDate
|
||||
@@ -159,143 +155,130 @@ var parseId = function(idStr){
|
||||
// length
|
||||
|
||||
var compileData = function (prevTask, dataStr) {
|
||||
var ds;
|
||||
var ds
|
||||
|
||||
if (dataStr.substr(0, 1) === ':') {
|
||||
ds = dataStr.substr(1,dataStr.length);
|
||||
}
|
||||
else{
|
||||
ds=dataStr;
|
||||
ds = dataStr.substr(1, dataStr.length)
|
||||
} else {
|
||||
ds = dataStr
|
||||
}
|
||||
|
||||
var data = ds.split(',');
|
||||
|
||||
|
||||
var task = {};
|
||||
var df = exports.getDateFormat();
|
||||
var data = ds.split(',')
|
||||
|
||||
var task = {}
|
||||
var df = exports.getDateFormat()
|
||||
|
||||
// Get tags like active, done cand crit
|
||||
var matchFound = true;
|
||||
var matchFound = true
|
||||
while (matchFound) {
|
||||
matchFound = false;
|
||||
matchFound = false
|
||||
if (data[0].match(/^\s*active\s*$/)) {
|
||||
task.active = true;
|
||||
data.shift(1);
|
||||
matchFound = true;
|
||||
|
||||
task.active = true
|
||||
data.shift(1)
|
||||
matchFound = true
|
||||
}
|
||||
if (data[0].match(/^\s*done\s*$/)) {
|
||||
task.done = true;
|
||||
data.shift(1);
|
||||
matchFound = true;
|
||||
task.done = true
|
||||
data.shift(1)
|
||||
matchFound = true
|
||||
}
|
||||
if (data[0].match(/^\s*crit\s*$/)) {
|
||||
task.crit = true;
|
||||
data.shift(1);
|
||||
matchFound = true;
|
||||
task.crit = true
|
||||
data.shift(1)
|
||||
matchFound = true
|
||||
}
|
||||
}
|
||||
var i;
|
||||
var i
|
||||
for (i = 0; i < data.length; i++) {
|
||||
data[i] = data[i].trim();
|
||||
data[i] = data[i].trim()
|
||||
}
|
||||
|
||||
|
||||
switch (data.length) {
|
||||
case 1:
|
||||
task.id = parseId();
|
||||
task.startTime = prevTask.endTime;
|
||||
task.endTime = getEndDate(task.startTime, df, data[0]);
|
||||
break;
|
||||
task.id = parseId()
|
||||
task.startTime = prevTask.endTime
|
||||
task.endTime = getEndDate(task.startTime, df, data[0])
|
||||
break
|
||||
case 2:
|
||||
task.id = parseId();
|
||||
task.startTime = getStartDate(undefined, df, data[0]);
|
||||
task.endTime = getEndDate(task.startTime, df, data[1]);
|
||||
break;
|
||||
task.id = parseId()
|
||||
task.startTime = getStartDate(undefined, df, data[0])
|
||||
task.endTime = getEndDate(task.startTime, df, data[1])
|
||||
break
|
||||
case 3:
|
||||
task.id = parseId(data[0]);
|
||||
task.startTime = getStartDate(undefined, df, data[1]);
|
||||
task.endTime = getEndDate(task.startTime, df, data[2]);
|
||||
break;
|
||||
task.id = parseId(data[0])
|
||||
task.startTime = getStartDate(undefined, df, data[1])
|
||||
task.endTime = getEndDate(task.startTime, df, data[2])
|
||||
break
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return task;
|
||||
};
|
||||
return task
|
||||
}
|
||||
|
||||
var parseData = function (prevTaskId, dataStr) {
|
||||
var ds;
|
||||
var ds
|
||||
|
||||
if (dataStr.substr(0, 1) === ':') {
|
||||
ds = dataStr.substr(1,dataStr.length);
|
||||
}
|
||||
else{
|
||||
ds=dataStr;
|
||||
ds = dataStr.substr(1, dataStr.length)
|
||||
} else {
|
||||
ds = dataStr
|
||||
}
|
||||
|
||||
var data = ds.split(',');
|
||||
var data = ds.split(',')
|
||||
|
||||
|
||||
var task = {};
|
||||
var task = {}
|
||||
|
||||
// Get tags like active, done cand crit
|
||||
var matchFound = true;
|
||||
var matchFound = true
|
||||
while (matchFound) {
|
||||
matchFound = false;
|
||||
matchFound = false
|
||||
if (data[0].match(/^\s*active\s*$/)) {
|
||||
task.active = true;
|
||||
data.shift(1);
|
||||
matchFound = true;
|
||||
|
||||
task.active = true
|
||||
data.shift(1)
|
||||
matchFound = true
|
||||
}
|
||||
if (data[0].match(/^\s*done\s*$/)) {
|
||||
task.done = true;
|
||||
data.shift(1);
|
||||
matchFound = true;
|
||||
task.done = true
|
||||
data.shift(1)
|
||||
matchFound = true
|
||||
}
|
||||
if (data[0].match(/^\s*crit\s*$/)) {
|
||||
task.crit = true;
|
||||
data.shift(1);
|
||||
matchFound = true;
|
||||
task.crit = true
|
||||
data.shift(1)
|
||||
matchFound = true
|
||||
}
|
||||
}
|
||||
var i;
|
||||
var i
|
||||
for (i = 0; i < data.length; i++) {
|
||||
data[i] = data[i].trim();
|
||||
data[i] = data[i].trim()
|
||||
}
|
||||
|
||||
|
||||
switch (data.length) {
|
||||
case 1:
|
||||
task.id = parseId();
|
||||
task.startTime = {type: 'prevTaskEnd', id:prevTaskId};
|
||||
task.endTime = {data: data[0]};
|
||||
break;
|
||||
task.id = parseId()
|
||||
task.startTime = {type: 'prevTaskEnd', id: prevTaskId}
|
||||
task.endTime = {data: data[0]}
|
||||
break
|
||||
case 2:
|
||||
task.id = parseId();
|
||||
task.startTime = {type:'getStartDate',startData:data[0]};
|
||||
task.endTime = {data: data[1]};
|
||||
break;
|
||||
task.id = parseId()
|
||||
task.startTime = {type: 'getStartDate', startData: data[0]}
|
||||
task.endTime = {data: data[1]}
|
||||
break
|
||||
case 3:
|
||||
task.id = parseId(data[0]);
|
||||
task.startTime = {type:'getStartDate',startData: data[1]};
|
||||
task.endTime = {data: data[2]};
|
||||
break;
|
||||
task.id = parseId(data[0])
|
||||
task.startTime = {type: 'getStartDate', startData: data[1]}
|
||||
task.endTime = {data: data[2]}
|
||||
break
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return task;
|
||||
};
|
||||
return task
|
||||
}
|
||||
|
||||
|
||||
|
||||
var lastTask;
|
||||
var lastTaskID;
|
||||
var rawTasks = [];
|
||||
var taskDb = {};
|
||||
var lastTask
|
||||
var lastTaskID
|
||||
var rawTasks = []
|
||||
var taskDb = {}
|
||||
exports.addTask = function (descr, data) {
|
||||
var rawTask = {
|
||||
section: currentSection,
|
||||
@@ -303,24 +286,22 @@ exports.addTask = function(descr,data){
|
||||
processed: false,
|
||||
raw: {data: data},
|
||||
task: descr
|
||||
};
|
||||
var taskInfo = parseData(lastTaskID, data);
|
||||
rawTask.raw.startTime = taskInfo.startTime;
|
||||
rawTask.raw.endTime = taskInfo.endTime;
|
||||
rawTask.id = taskInfo.id;
|
||||
rawTask.prevTaskId = lastTaskID;
|
||||
rawTask.active = taskInfo.active;
|
||||
rawTask.done = taskInfo.done;
|
||||
rawTask.crit = taskInfo.crit;
|
||||
}
|
||||
var taskInfo = parseData(lastTaskID, data)
|
||||
rawTask.raw.startTime = taskInfo.startTime
|
||||
rawTask.raw.endTime = taskInfo.endTime
|
||||
rawTask.id = taskInfo.id
|
||||
rawTask.prevTaskId = lastTaskID
|
||||
rawTask.active = taskInfo.active
|
||||
rawTask.done = taskInfo.done
|
||||
rawTask.crit = taskInfo.crit
|
||||
|
||||
var pos = rawTasks.push(rawTask);
|
||||
var pos = rawTasks.push(rawTask)
|
||||
|
||||
lastTaskID = rawTask.id;
|
||||
lastTaskID = rawTask.id
|
||||
// Store cross ref
|
||||
taskDb[rawTask.id]= pos-1;
|
||||
|
||||
};
|
||||
|
||||
taskDb[rawTask.id] = pos - 1
|
||||
}
|
||||
|
||||
exports.findTaskById = function (id) {
|
||||
// var i;
|
||||
@@ -330,69 +311,67 @@ exports.findTaskById = function(id) {
|
||||
// }
|
||||
// }
|
||||
|
||||
var pos = taskDb[id];
|
||||
return rawTasks[pos];
|
||||
};
|
||||
var pos = taskDb[id]
|
||||
return rawTasks[pos]
|
||||
}
|
||||
|
||||
exports.addTaskOrg = function (descr, data) {
|
||||
|
||||
var newTask = {
|
||||
section: currentSection,
|
||||
type: currentSection,
|
||||
description: descr,
|
||||
task: descr
|
||||
};
|
||||
var taskInfo = compileData(lastTask, data);
|
||||
newTask.startTime = taskInfo.startTime;
|
||||
newTask.endTime = taskInfo.endTime;
|
||||
newTask.id = taskInfo.id;
|
||||
newTask.active = taskInfo.active;
|
||||
newTask.done = taskInfo.done;
|
||||
newTask.crit = taskInfo.crit;
|
||||
lastTask = newTask;
|
||||
tasks.push(newTask);
|
||||
};
|
||||
}
|
||||
var taskInfo = compileData(lastTask, data)
|
||||
newTask.startTime = taskInfo.startTime
|
||||
newTask.endTime = taskInfo.endTime
|
||||
newTask.id = taskInfo.id
|
||||
newTask.active = taskInfo.active
|
||||
newTask.done = taskInfo.done
|
||||
newTask.crit = taskInfo.crit
|
||||
lastTask = newTask
|
||||
tasks.push(newTask)
|
||||
}
|
||||
|
||||
var compileTasks = function () {
|
||||
var df = exports.getDateFormat();
|
||||
var df = exports.getDateFormat()
|
||||
|
||||
var compileTask = function (pos) {
|
||||
var task = rawTasks[pos];
|
||||
var startTime = '';
|
||||
var task = rawTasks[pos]
|
||||
var startTime = ''
|
||||
switch (rawTasks[pos].raw.startTime.type) {
|
||||
case 'prevTaskEnd':
|
||||
var prevTask = exports.findTaskById(task.prevTaskId);
|
||||
task.startTime = prevTask.endTime;
|
||||
break;
|
||||
var prevTask = exports.findTaskById(task.prevTaskId)
|
||||
task.startTime = prevTask.endTime
|
||||
break
|
||||
case 'getStartDate':
|
||||
startTime = getStartDate(undefined, df, rawTasks[pos].raw.startTime.startData);
|
||||
startTime = getStartDate(undefined, df, rawTasks[pos].raw.startTime.startData)
|
||||
if (startTime) {
|
||||
rawTasks[pos].startTime = startTime;
|
||||
rawTasks[pos].startTime = startTime
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
|
||||
if (rawTasks[pos].startTime) {
|
||||
rawTasks[pos].endTime = getEndDate(rawTasks[pos].startTime, df, rawTasks[pos].raw.endTime.data);
|
||||
rawTasks[pos].endTime = getEndDate(rawTasks[pos].startTime, df, rawTasks[pos].raw.endTime.data)
|
||||
if (rawTasks[pos].endTime) {
|
||||
rawTasks[pos].processed = true;
|
||||
rawTasks[pos].processed = true
|
||||
}
|
||||
}
|
||||
|
||||
return rawTasks[pos].processed;
|
||||
return rawTasks[pos].processed
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var i;
|
||||
var allProcessed = true;
|
||||
var i
|
||||
var allProcessed = true
|
||||
for (i = 0; i < rawTasks.length; i++) {
|
||||
compileTask(i);
|
||||
compileTask(i)
|
||||
|
||||
allProcessed = allProcessed && rawTasks[i].processed;
|
||||
allProcessed = allProcessed && rawTasks[i].processed
|
||||
}
|
||||
return allProcessed
|
||||
}
|
||||
return allProcessed;
|
||||
};
|
||||
|
||||
exports.parseError = function (err, hash) {
|
||||
global.mermaidAPI.parseError(err,hash);
|
||||
};
|
||||
global.mermaidAPI.parseError(err, hash)
|
||||
}
|
||||
|
||||
@@ -2,183 +2,182 @@
|
||||
* Created by knut on 14-11-18.
|
||||
*/
|
||||
describe('when using the ganttDb', function () {
|
||||
var gDb;
|
||||
var moment = require('moment');
|
||||
var gDb
|
||||
var moment = require('moment')
|
||||
|
||||
beforeEach(function () {
|
||||
// gantt = require('./parser/gantt').parser;
|
||||
|
||||
gDb = require('./ganttDb');
|
||||
gDb.clear();
|
||||
gDb = require('./ganttDb')
|
||||
gDb.clear()
|
||||
// ex.yy.parseError = parseError;
|
||||
});
|
||||
})
|
||||
|
||||
it('should handle an fixed dates', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2013-01-12');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].id ).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2013-01-12')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].id).toEqual('id1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
it('should handle duration (days) instead of fixed date to determine end date', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2d');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-03', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].id ).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2d')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-03', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].id).toEqual('id1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
it('should handle duration (hours) instead of fixed date to determine end date', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2h');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-01 2:00', 'YYYY-MM-DD hh:mm').toDate());
|
||||
expect(tasks[0].id ).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2h')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-01 2:00', 'YYYY-MM-DD hh:mm').toDate())
|
||||
expect(tasks[0].id).toEqual('id1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
it('should handle duration (minutes) instead of fixed date to determine end date', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2m');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-01 00:02', 'YYYY-MM-DD hh:mm').toDate());
|
||||
expect(tasks[0].id ).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2m')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-01 00:02', 'YYYY-MM-DD hh:mm').toDate())
|
||||
expect(tasks[0].id).toEqual('id1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
it('should handle duration (seconds) instead of fixed date to determine end date', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2s');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-01 00:00:02', 'YYYY-MM-DD hh:mm:ss').toDate());
|
||||
expect(tasks[0].id ).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2s')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-01 00:00:02', 'YYYY-MM-DD hh:mm:ss').toDate())
|
||||
expect(tasks[0].id).toEqual('id1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
it('should handle duration (weeks) instead of fixed date to determine end date', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2w');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].id ).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2w')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].id).toEqual('id1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
|
||||
it('should handle relative start date based on id', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2w');
|
||||
gDb.addTask('test2','id2,after id1,1d');
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2w')
|
||||
gDb.addTask('test2', 'id2,after id1,1d')
|
||||
|
||||
var tasks = gDb.getTasks();
|
||||
var tasks = gDb.getTasks()
|
||||
|
||||
expect(tasks[1].startTime ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].id ).toEqual('id2');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
});
|
||||
expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].id).toEqual('id2')
|
||||
expect(tasks[1].task).toEqual('test2')
|
||||
})
|
||||
|
||||
it('should handle relative start date based on id when id is invalid', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2w');
|
||||
gDb.addTask('test2','id2,after id3,1d');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[1].startTime).toEqual(new Date((new Date()).setHours(0,0,0,0)));
|
||||
expect(tasks[1].id ).toEqual('id2');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2w')
|
||||
gDb.addTask('test2', 'id2,after id3,1d')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[1].startTime).toEqual(new Date((new Date()).setHours(0, 0, 0, 0)))
|
||||
expect(tasks[1].id).toEqual('id2')
|
||||
expect(tasks[1].task).toEqual('test2')
|
||||
})
|
||||
|
||||
it('should handle fixed dates without id', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','2013-01-01,2013-01-12');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].id ).toEqual('task1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', '2013-01-01,2013-01-12')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-12', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].id).toEqual('task1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
|
||||
it('should handle duration instead of a fixed date to determine end date without id', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','2013-01-01,4d');
|
||||
var tasks = gDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime ).toEqual(moment('2013-01-05', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].id ).toEqual('task1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
});
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', '2013-01-01,4d')
|
||||
var tasks = gDb.getTasks()
|
||||
expect(tasks[0].startTime).toEqual(moment('2013-01-01', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].endTime).toEqual(moment('2013-01-05', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[0].id).toEqual('task1')
|
||||
expect(tasks[0].task).toEqual('test1')
|
||||
})
|
||||
|
||||
it('should handle relative start date of a fixed date to determine end date without id', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2w');
|
||||
gDb.addTask('test2','after id1,1d');
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2w')
|
||||
gDb.addTask('test2', 'after id1,1d')
|
||||
|
||||
var tasks = gDb.getTasks();
|
||||
var tasks = gDb.getTasks()
|
||||
|
||||
expect(tasks[1].startTime ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].id ).toEqual('task1');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
});
|
||||
expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].id).toEqual('task1')
|
||||
expect(tasks[1].task).toEqual('test2')
|
||||
})
|
||||
it('should handle a new task with only an end date as definition', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2w');
|
||||
gDb.addTask('test2','2013-01-26');
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2w')
|
||||
gDb.addTask('test2', '2013-01-26')
|
||||
|
||||
var tasks = gDb.getTasks();
|
||||
var tasks = gDb.getTasks()
|
||||
|
||||
expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime ).toEqual(moment('2013-01-26', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].id ).toEqual('task1');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
});
|
||||
expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].endTime).toEqual(moment('2013-01-26', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].id).toEqual('task1')
|
||||
expect(tasks[1].task).toEqual('test2')
|
||||
})
|
||||
it('should handle a new task with only an end date as definition', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2w');
|
||||
gDb.addTask('test2','2d');
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2w')
|
||||
gDb.addTask('test2', '2d')
|
||||
|
||||
var tasks = gDb.getTasks();
|
||||
var tasks = gDb.getTasks()
|
||||
|
||||
expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime ).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].id ).toEqual('task1');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
});
|
||||
expect(tasks[1].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].endTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].id).toEqual('task1')
|
||||
expect(tasks[1].task).toEqual('test2')
|
||||
})
|
||||
it('should handle relative start date based on id regardless of sections', function () {
|
||||
gDb.setDateFormat('YYYY-MM-DD');
|
||||
gDb.addSection('testa1');
|
||||
gDb.addTask('test1','id1,2013-01-01,2w');
|
||||
gDb.addTask('test2','id2,after id3,1d');
|
||||
gDb.addSection('testa2');
|
||||
gDb.addTask('test3','id3,after id1,2d');
|
||||
gDb.setDateFormat('YYYY-MM-DD')
|
||||
gDb.addSection('testa1')
|
||||
gDb.addTask('test1', 'id1,2013-01-01,2w')
|
||||
gDb.addTask('test2', 'id2,after id3,1d')
|
||||
gDb.addSection('testa2')
|
||||
gDb.addTask('test3', 'id3,after id1,2d')
|
||||
|
||||
var tasks = gDb.getTasks();
|
||||
var tasks = gDb.getTasks()
|
||||
|
||||
expect(tasks[1].startTime ).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime ).toEqual(moment('2013-01-18', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].id ).toEqual('id2');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
expect(tasks[1].startTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].endTime).toEqual(moment('2013-01-18', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[1].id).toEqual('id2')
|
||||
expect(tasks[1].task).toEqual('test2')
|
||||
|
||||
expect(tasks[2].id ).toEqual('id3');
|
||||
expect(tasks[2].task).toEqual('test3');
|
||||
expect(tasks[2].startTime ).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].endTime ).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate());
|
||||
});
|
||||
|
||||
});
|
||||
expect(tasks[2].id).toEqual('id3')
|
||||
expect(tasks[2].task).toEqual('test3')
|
||||
expect(tasks[2].startTime).toEqual(moment('2013-01-15', 'YYYY-MM-DD').toDate())
|
||||
expect(tasks[2].endTime).toEqual(moment('2013-01-17', 'YYYY-MM-DD').toDate())
|
||||
})
|
||||
})
|
||||
|
||||
// Ogiltigt id i after id
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
var gantt = require('./parser/gantt').parser;
|
||||
gantt.yy = require('./ganttDb');
|
||||
var d3 = require('../../d3');
|
||||
var moment = require('moment');
|
||||
var gantt = require('./parser/gantt').parser
|
||||
gantt.yy = require('./ganttDb')
|
||||
var d3 = require('../../d3')
|
||||
var moment = require('moment')
|
||||
// var log = require('../../logger').create();
|
||||
|
||||
var daysInChart;
|
||||
var daysInChart
|
||||
var conf = {
|
||||
titleTopMargin: 25,
|
||||
barHeight: 20,
|
||||
@@ -15,111 +15,101 @@ var conf = {
|
||||
gridLineStartPadding: 35,
|
||||
fontSize: 11,
|
||||
fontFamily: '"Open-Sans", "sans-serif"'
|
||||
};
|
||||
}
|
||||
module.exports.setConf = function (cnf) {
|
||||
var keys = Object.keys(cnf);
|
||||
var keys = Object.keys(cnf)
|
||||
|
||||
keys.forEach(function (key) {
|
||||
conf[key] = cnf[key];
|
||||
});
|
||||
};
|
||||
var w;
|
||||
conf[key] = cnf[key]
|
||||
})
|
||||
}
|
||||
var w
|
||||
module.exports.draw = function (text, id) {
|
||||
gantt.yy.clear();
|
||||
gantt.parse(text);
|
||||
gantt.yy.clear()
|
||||
gantt.parse(text)
|
||||
|
||||
var elem = document.getElementById(id);
|
||||
w = elem.parentElement.offsetWidth;
|
||||
var elem = document.getElementById(id)
|
||||
w = elem.parentElement.offsetWidth
|
||||
|
||||
if (typeof w === 'undefined') {
|
||||
w = 1200;
|
||||
w = 1200
|
||||
}
|
||||
|
||||
if (typeof conf.useWidth !== 'undefined') {
|
||||
w = conf.useWidth;
|
||||
w = conf.useWidth
|
||||
}
|
||||
|
||||
var taskArray = gantt.yy.getTasks();
|
||||
var taskArray = gantt.yy.getTasks()
|
||||
|
||||
// Set height based on number of tasks
|
||||
var h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding;
|
||||
var h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding
|
||||
|
||||
elem.setAttribute('height', '100%');
|
||||
elem.setAttribute('height', '100%')
|
||||
// Set viewBox
|
||||
elem.setAttribute('viewBox','0 0 '+w+' '+h);
|
||||
var svg = d3.select('#' + id);
|
||||
|
||||
|
||||
|
||||
elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h)
|
||||
var svg = d3.select('#' + id)
|
||||
|
||||
// var dateFormat = d3.time.format('%Y-%m-%d');
|
||||
|
||||
var startDate = d3.min(taskArray, function (d) {
|
||||
return d.startTime;
|
||||
});
|
||||
return d.startTime
|
||||
})
|
||||
var endDate = d3.max(taskArray, function (d) {
|
||||
return d.endTime;
|
||||
});
|
||||
return d.endTime
|
||||
})
|
||||
|
||||
// Set timescale
|
||||
var timeScale = d3.time.scale()
|
||||
.domain([d3.min(taskArray, function (d) {
|
||||
return d.startTime;
|
||||
return d.startTime
|
||||
}),
|
||||
d3.max(taskArray, function (d) {
|
||||
return d.endTime;
|
||||
return d.endTime
|
||||
})])
|
||||
.rangeRound([0, w - conf.leftPadding - conf.rightPadding]);
|
||||
.rangeRound([0, w - conf.leftPadding - conf.rightPadding])
|
||||
// .nice(d3.time.monday);
|
||||
|
||||
var categories = [];
|
||||
var categories = []
|
||||
|
||||
daysInChart = moment.duration(endDate-startDate).asDays();
|
||||
daysInChart = moment.duration(endDate - startDate).asDays()
|
||||
|
||||
for (var i = 0; i < taskArray.length; i++) {
|
||||
categories.push(taskArray[i].type);
|
||||
categories.push(taskArray[i].type)
|
||||
}
|
||||
|
||||
var catsUnfiltered = categories; //for vert labels
|
||||
var catsUnfiltered = categories // for vert labels
|
||||
|
||||
categories = checkUnique(categories);
|
||||
categories = checkUnique(categories)
|
||||
|
||||
|
||||
makeGant(taskArray, w, h);
|
||||
makeGant(taskArray, w, h)
|
||||
if (typeof conf.useWidth !== 'undefined') {
|
||||
elem.setAttribute('width', w);
|
||||
|
||||
elem.setAttribute('width', w)
|
||||
}
|
||||
|
||||
svg.append('text')
|
||||
.text(gantt.yy.getTitle())
|
||||
.attr('x', w / 2)
|
||||
.attr('y', conf.titleTopMargin)
|
||||
.attr('class', 'titleText');
|
||||
|
||||
.attr('class', 'titleText')
|
||||
|
||||
function makeGant (tasks, pageWidth, pageHeight) {
|
||||
|
||||
var barHeight = conf.barHeight;
|
||||
var gap = barHeight + conf.barGap;
|
||||
var topPadding = conf.topPadding;
|
||||
var leftPadding = conf.leftPadding;
|
||||
var barHeight = conf.barHeight
|
||||
var gap = barHeight + conf.barGap
|
||||
var topPadding = conf.topPadding
|
||||
var leftPadding = conf.leftPadding
|
||||
|
||||
var colorScale = d3.scale.linear()
|
||||
.domain([0, categories.length])
|
||||
.range(['#00B9FA', '#F95002'])
|
||||
.interpolate(d3.interpolateHcl);
|
||||
|
||||
makeGrid(leftPadding, topPadding, pageWidth, pageHeight);
|
||||
drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight);
|
||||
vertLabels(gap, topPadding, leftPadding, barHeight, colorScale);
|
||||
drawToday(leftPadding, topPadding, pageWidth, pageHeight);
|
||||
.interpolate(d3.interpolateHcl)
|
||||
|
||||
makeGrid(leftPadding, topPadding, pageWidth, pageHeight)
|
||||
drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight)
|
||||
vertLabels(gap, topPadding, leftPadding, barHeight, colorScale)
|
||||
drawToday(leftPadding, topPadding, pageWidth, pageHeight)
|
||||
}
|
||||
|
||||
|
||||
function drawRects (theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w, h) { // eslint-disable-line no-unused-vars
|
||||
|
||||
svg.append('g')
|
||||
.selectAll('rect')
|
||||
.data(theArray)
|
||||
@@ -127,210 +117,200 @@ module.exports.draw = function (text, id) {
|
||||
.append('rect')
|
||||
.attr('x', 0)
|
||||
.attr('y', function (d, i) {
|
||||
return i * theGap + theTopPad - 2;
|
||||
return i * theGap + theTopPad - 2
|
||||
})
|
||||
.attr('width', function () {
|
||||
return w - conf.rightPadding / 2;
|
||||
return w - conf.rightPadding / 2
|
||||
})
|
||||
.attr('height', theGap)
|
||||
.attr('class', function (d) { // eslint-disable-line no-unused-vars
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d.type === categories[i]) {
|
||||
return 'section section' + (i % conf.numberSectionStyles);
|
||||
return 'section section' + (i % conf.numberSectionStyles)
|
||||
}
|
||||
}
|
||||
return 'section section0';
|
||||
});
|
||||
|
||||
return 'section section0'
|
||||
})
|
||||
|
||||
var rectangles = svg.append('g')
|
||||
.selectAll('rect')
|
||||
.data(theArray)
|
||||
.enter();
|
||||
|
||||
.enter()
|
||||
|
||||
rectangles.append('rect')
|
||||
.attr('rx', 3)
|
||||
.attr('ry', 3)
|
||||
.attr('x', function (d) {
|
||||
return timeScale(d.startTime) + theSidePad;
|
||||
return timeScale(d.startTime) + theSidePad
|
||||
})
|
||||
.attr('y', function (d, i) {
|
||||
return i * theGap + theTopPad;
|
||||
return i * theGap + theTopPad
|
||||
})
|
||||
.attr('width', function (d) {
|
||||
return (timeScale(d.endTime) - timeScale(d.startTime));
|
||||
return (timeScale(d.endTime) - timeScale(d.startTime))
|
||||
})
|
||||
.attr('height', theBarHeight)
|
||||
.attr('class', function (d) {
|
||||
var res = 'task ';
|
||||
var res = 'task '
|
||||
|
||||
|
||||
var secNum = 0;
|
||||
var secNum = 0
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d.type === categories[i]) {
|
||||
secNum = (i % conf.numberSectionStyles);
|
||||
secNum = (i % conf.numberSectionStyles)
|
||||
}
|
||||
}
|
||||
|
||||
if (d.active) {
|
||||
if (d.crit) {
|
||||
return res + ' activeCrit'+secNum;
|
||||
return res + ' activeCrit' + secNum
|
||||
} else {
|
||||
return res + ' active'+secNum;
|
||||
return res + ' active' + secNum
|
||||
}
|
||||
}
|
||||
|
||||
if (d.done) {
|
||||
if (d.crit) {
|
||||
return res + ' doneCrit'+secNum;
|
||||
return res + ' doneCrit' + secNum
|
||||
} else {
|
||||
return res + ' done'+secNum;
|
||||
return res + ' done' + secNum
|
||||
}
|
||||
}
|
||||
|
||||
if (d.crit) {
|
||||
return res + ' crit'+secNum;
|
||||
return res + ' crit' + secNum
|
||||
}
|
||||
|
||||
|
||||
return res + ' task'+secNum;
|
||||
return res + ' task' + secNum
|
||||
})
|
||||
;
|
||||
|
||||
|
||||
rectangles.append('text')
|
||||
.text(function (d) {
|
||||
return d.task;
|
||||
return d.task
|
||||
})
|
||||
.attr('font-size', conf.fontSize)
|
||||
// .attr('font-family',conf.fontFamily)
|
||||
.attr('x', function (d) {
|
||||
var startX = timeScale(d.startTime),
|
||||
endX = timeScale(d.endTime),
|
||||
textWidth = this.getBBox().width;
|
||||
textWidth = this.getBBox().width
|
||||
|
||||
// Check id text width > width of rectangle
|
||||
if (textWidth > (endX - startX)) {
|
||||
if (endX + textWidth + 1.5 * conf.leftPadding > w) {
|
||||
return startX + theSidePad - 5;
|
||||
return startX + theSidePad - 5
|
||||
} else {
|
||||
return endX + theSidePad + 5;
|
||||
return endX + theSidePad + 5
|
||||
}
|
||||
} else {
|
||||
return (endX - startX) / 2 + startX + theSidePad;
|
||||
return (endX - startX) / 2 + startX + theSidePad
|
||||
}
|
||||
})
|
||||
.attr('y', function (d, i) {
|
||||
return i * theGap + (conf.barHeight / 2) + (conf.fontSize / 2 - 2) + theTopPad;
|
||||
return i * theGap + (conf.barHeight / 2) + (conf.fontSize / 2 - 2) + theTopPad
|
||||
})
|
||||
// .attr('text-anchor', 'middle')
|
||||
.attr('text-height', theBarHeight)
|
||||
.attr('class', function (d) {
|
||||
var startX = timeScale(d.startTime),
|
||||
endX = timeScale(d.endTime),
|
||||
textWidth = this.getBBox().width;
|
||||
var secNum = 0;
|
||||
textWidth = this.getBBox().width
|
||||
var secNum = 0
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d.type === categories[i]) {
|
||||
secNum = (i % conf.numberSectionStyles);
|
||||
secNum = (i % conf.numberSectionStyles)
|
||||
}
|
||||
}
|
||||
|
||||
var taskType = '';
|
||||
var taskType = ''
|
||||
if (d.active) {
|
||||
if (d.crit) {
|
||||
taskType = 'activeCritText'+secNum;
|
||||
taskType = 'activeCritText' + secNum
|
||||
} else {
|
||||
taskType = 'activeText'+secNum;
|
||||
taskType = 'activeText' + secNum
|
||||
}
|
||||
}
|
||||
|
||||
if (d.done) {
|
||||
if (d.crit) {
|
||||
taskType = taskType + ' doneCritText'+secNum;
|
||||
taskType = taskType + ' doneCritText' + secNum
|
||||
} else {
|
||||
taskType = taskType + ' doneText'+secNum;
|
||||
taskType = taskType + ' doneText' + secNum
|
||||
}
|
||||
} else {
|
||||
if (d.crit) {
|
||||
taskType = taskType + ' critText'+secNum;
|
||||
taskType = taskType + ' critText' + secNum
|
||||
}
|
||||
}
|
||||
|
||||
// Check id text width > width of rectangle
|
||||
if (textWidth > (endX - startX)) {
|
||||
if (endX + textWidth + 1.5 * conf.leftPadding > w) {
|
||||
return 'taskTextOutsideLeft taskTextOutside' + secNum + ' ' + taskType;
|
||||
return 'taskTextOutsideLeft taskTextOutside' + secNum + ' ' + taskType
|
||||
} else {
|
||||
return 'taskTextOutsideRight taskTextOutside' + secNum+ ' ' + taskType;
|
||||
return 'taskTextOutsideRight taskTextOutside' + secNum + ' ' + taskType
|
||||
}
|
||||
} else {
|
||||
return 'taskText taskText' + secNum+ ' ' + taskType;
|
||||
return 'taskText taskText' + secNum + ' ' + taskType
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function makeGrid (theSidePad, theTopPad, w, h) {
|
||||
|
||||
var pre = [
|
||||
['.%L', function (d) {
|
||||
return d.getMilliseconds();
|
||||
return d.getMilliseconds()
|
||||
}],
|
||||
[':%S', function (d) {
|
||||
return d.getSeconds();
|
||||
return d.getSeconds()
|
||||
}],
|
||||
// Within a hour
|
||||
['h1 %I:%M', function (d) {
|
||||
return d.getMinutes();
|
||||
}]];
|
||||
return d.getMinutes()
|
||||
}]]
|
||||
var post = [
|
||||
['%Y', function () {
|
||||
return true;
|
||||
}]];
|
||||
return true
|
||||
}]]
|
||||
|
||||
var mid = [
|
||||
// Within a day
|
||||
['%I:%M', function (d) {
|
||||
return d.getHours();
|
||||
return d.getHours()
|
||||
}],
|
||||
// Day within a week (not monday)
|
||||
['%a %d', function (d) {
|
||||
// return d.getDay() ==1;
|
||||
return d.getDay() && d.getDate() != 1;
|
||||
return d.getDay() && d.getDate() != 1
|
||||
}],
|
||||
// within a month
|
||||
['%b %d', function (d) {
|
||||
return d.getDate() != 1;
|
||||
return d.getDate() != 1
|
||||
}],
|
||||
// Month
|
||||
['%B', function (d) {
|
||||
return d.getMonth();
|
||||
return d.getMonth()
|
||||
}]
|
||||
];
|
||||
var formatter;
|
||||
]
|
||||
var formatter
|
||||
if (typeof conf.axisFormatter !== 'undefined') {
|
||||
mid = [];
|
||||
mid = []
|
||||
conf.axisFormatter.forEach(function (item) {
|
||||
var n = [];
|
||||
n[0] = item[0];
|
||||
n[1] = item[1];
|
||||
mid.push(n);
|
||||
});
|
||||
var n = []
|
||||
n[0] = item[0]
|
||||
n[1] = item[1]
|
||||
mid.push(n)
|
||||
})
|
||||
}
|
||||
formatter = pre.concat(mid).concat(post);
|
||||
formatter = pre.concat(mid).concat(post)
|
||||
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(timeScale)
|
||||
.orient('bottom')
|
||||
.tickSize(-h + theTopPad + conf.gridLineStartPadding, 0, 0)
|
||||
.tickFormat(d3.time.format.multi(formatter))
|
||||
;
|
||||
|
||||
if (daysInChart > 7 && daysInChart < 230) {
|
||||
xAxis = xAxis.ticks(d3.time.monday.range);
|
||||
xAxis = xAxis.ticks(d3.time.monday.range)
|
||||
}
|
||||
|
||||
svg.append('g')
|
||||
@@ -342,15 +322,15 @@ module.exports.draw = function (text, id) {
|
||||
.attr('fill', '#000')
|
||||
.attr('stroke', 'none')
|
||||
.attr('font-size', 10)
|
||||
.attr('dy', '1em');
|
||||
.attr('dy', '1em')
|
||||
}
|
||||
|
||||
function vertLabels (theGap, theTopPad) {
|
||||
var numOccurances = [];
|
||||
var prevGap = 0;
|
||||
var numOccurances = []
|
||||
var prevGap = 0
|
||||
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
numOccurances[i] = [categories[i], getCount(categories[i], catsUnfiltered)];
|
||||
numOccurances[i] = [categories[i], getCount(categories[i], catsUnfiltered)]
|
||||
}
|
||||
|
||||
svg.append('g') // without doing this, impossible to put grid lines behind text
|
||||
@@ -359,36 +339,35 @@ module.exports.draw = function (text, id) {
|
||||
.enter()
|
||||
.append('text')
|
||||
.text(function (d) {
|
||||
return d[0];
|
||||
return d[0]
|
||||
})
|
||||
.attr('x', 10)
|
||||
.attr('y', function (d, i) {
|
||||
if (i > 0) {
|
||||
for (var j = 0; j < i; j++) {
|
||||
prevGap += numOccurances[i - 1][1];
|
||||
prevGap += numOccurances[i - 1][1]
|
||||
// log.debug(prevGap);
|
||||
return d[1] * theGap / 2 + prevGap * theGap + theTopPad;
|
||||
return d[1] * theGap / 2 + prevGap * theGap + theTopPad
|
||||
}
|
||||
} else {
|
||||
return d[1] * theGap / 2 + theTopPad;
|
||||
return d[1] * theGap / 2 + theTopPad
|
||||
}
|
||||
})
|
||||
.attr('class', function (d) {
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d[0] === categories[i]) {
|
||||
return 'sectionTitle sectionTitle' + (i % conf.numberSectionStyles);
|
||||
return 'sectionTitle sectionTitle' + (i % conf.numberSectionStyles)
|
||||
}
|
||||
}
|
||||
return 'sectionTitle';
|
||||
});
|
||||
|
||||
return 'sectionTitle'
|
||||
})
|
||||
}
|
||||
|
||||
function drawToday (theSidePad, theTopPad, w, h) {
|
||||
var todayG = svg.append('g')
|
||||
.attr('class', 'today');
|
||||
.attr('class', 'today')
|
||||
|
||||
var today = new Date();
|
||||
var today = new Date()
|
||||
|
||||
todayG.append('line')
|
||||
.attr('x1', timeScale(today) + theSidePad)
|
||||
@@ -396,33 +375,32 @@ module.exports.draw = function (text, id) {
|
||||
.attr('y1', conf.titleTopMargin)
|
||||
.attr('y2', h - conf.titleTopMargin)
|
||||
.attr('class', 'today')
|
||||
;
|
||||
}
|
||||
|
||||
// from this stackexchange question: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
|
||||
function checkUnique (arr) {
|
||||
var hash = {}, result = [];
|
||||
var hash = {}, result = []
|
||||
for (var i = 0, l = arr.length; i < l; ++i) {
|
||||
if (!hash.hasOwnProperty(arr[i])) { // it works with objects! in FF, at least
|
||||
hash[arr[i]] = true;
|
||||
result.push(arr[i]);
|
||||
hash[arr[i]] = true
|
||||
result.push(arr[i])
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
|
||||
// from this stackexchange question: http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array
|
||||
function getCounts (arr) {
|
||||
var i = arr.length, // var to loop over
|
||||
obj = {}; // obj to store results
|
||||
obj = {} // obj to store results
|
||||
while (i) {
|
||||
obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
|
||||
obj[arr[--i]] = (obj[arr[i]] || 0) + 1 // count occurrences
|
||||
}
|
||||
return obj;
|
||||
return obj
|
||||
}
|
||||
|
||||
// get specific from everything
|
||||
function getCount (word, arr) {
|
||||
return getCounts(arr)[word] || 0;
|
||||
return getCounts(arr)[word] || 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
token location info (@$, _$, etc.): {
|
||||
first_line: n,
|
||||
last_line: n,
|
||||
@@ -59,7 +58,6 @@
|
||||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||||
}
|
||||
|
||||
|
||||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||||
text: (matched text)
|
||||
token: (the produced terminal token, if any)
|
||||
@@ -72,122 +70,122 @@
|
||||
}
|
||||
*/
|
||||
var parser = (function () {
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[6,8,10,11,12,13,14],$V1=[1,9],$V2=[1,10],$V3=[1,11],$V4=[1,12];
|
||||
var o = function (k, v, o, l) { for (o = o || {}, l = k.length; l--; o[k[l]] = v);return o }, $V0 = [6, 8, 10, 11, 12, 13, 14], $V1 = [1, 9], $V2 = [1, 10], $V3 = [1, 11], $V4 = [1, 12]
|
||||
var parser = {trace: function trace () { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"start":3,"gantt":4,"document":5,"EOF":6,"line":7,"SPACE":8,"statement":9,"NL":10,"dateFormat":11,"title":12,"section":13,"taskTxt":14,"taskData":15,"$accept":0,"$end":1},
|
||||
terminals_: {2:"error",4:"gantt",6:"EOF",8:"SPACE",10:"NL",11:"dateFormat",12:"title",13:"section",14:"taskTxt",15:"taskData"},
|
||||
symbols_: {'error': 2, 'start': 3, 'gantt': 4, 'document': 5, 'EOF': 6, 'line': 7, 'SPACE': 8, 'statement': 9, 'NL': 10, 'dateFormat': 11, 'title': 12, 'section': 13, 'taskTxt': 14, 'taskData': 15, '$accept': 0, '$end': 1},
|
||||
terminals_: {2: 'error', 4: 'gantt', 6: 'EOF', 8: 'SPACE', 10: 'NL', 11: 'dateFormat', 12: 'title', 13: 'section', 14: 'taskTxt', 15: 'taskData'},
|
||||
productions_: [0, [3, 3], [5, 0], [5, 2], [7, 2], [7, 1], [7, 1], [7, 1], [9, 1], [9, 1], [9, 1], [9, 2]],
|
||||
performAction: function anonymous (yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
var $0 = $$.length - 1
|
||||
switch (yystate) {
|
||||
case 1:
|
||||
return $$[$0-1];
|
||||
break;
|
||||
return $$[$0 - 1]
|
||||
break
|
||||
case 2:
|
||||
this.$ = []
|
||||
break;
|
||||
break
|
||||
case 3:
|
||||
$$[$0 - 1].push($$[$0]); this.$ = $$[$0 - 1]
|
||||
break;
|
||||
break
|
||||
case 4: case 5:
|
||||
this.$ = $$[$0]
|
||||
break;
|
||||
break
|
||||
case 6: case 7:
|
||||
this.$=[];
|
||||
break;
|
||||
this.$ = []
|
||||
break
|
||||
case 8:
|
||||
yy.setDateFormat($$[$0].substr(11));this.$=$$[$0].substr(11);
|
||||
break;
|
||||
yy.setDateFormat($$[$0].substr(11)); this.$ = $$[$0].substr(11)
|
||||
break
|
||||
case 9:
|
||||
yy.setTitle($$[$0].substr(6));this.$=$$[$0].substr(6);
|
||||
break;
|
||||
yy.setTitle($$[$0].substr(6)); this.$ = $$[$0].substr(6)
|
||||
break
|
||||
case 10:
|
||||
yy.addSection($$[$0].substr(8));this.$=$$[$0].substr(8);
|
||||
break;
|
||||
yy.addSection($$[$0].substr(8)); this.$ = $$[$0].substr(8)
|
||||
break
|
||||
case 11:
|
||||
yy.addTask($$[$0-1],$$[$0]);this.$='task';
|
||||
break;
|
||||
yy.addTask($$[$0 - 1], $$[$0]); this.$ = 'task'
|
||||
break
|
||||
}
|
||||
},
|
||||
table: [{3: 1, 4: [1, 2]}, {1: [3]}, o($V0, [2, 2], {5: 3}), {6: [1, 4], 7: 5, 8: [1, 6], 9: 7, 10: [1, 8], 11: $V1, 12: $V2, 13: $V3, 14: $V4}, o($V0, [2, 7], {1: [2, 1]}), o($V0, [2, 3]), {9: 13, 11: $V1, 12: $V2, 13: $V3, 14: $V4}, o($V0, [2, 5]), o($V0, [2, 6]), o($V0, [2, 8]), o($V0, [2, 9]), o($V0, [2, 10]), {15: [1, 14]}, o($V0, [2, 4]), o($V0, [2, 11])],
|
||||
defaultActions: {},
|
||||
parseError: function parseError (str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
this.trace(str)
|
||||
} else {
|
||||
function _parseError (msg, hash) {
|
||||
this.message = msg;
|
||||
this.hash = hash;
|
||||
this.message = msg
|
||||
this.hash = hash
|
||||
}
|
||||
_parseError.prototype = Error;
|
||||
_parseError.prototype = Error
|
||||
|
||||
throw new _parseError(str, hash);
|
||||
throw new _parseError(str, hash)
|
||||
}
|
||||
},
|
||||
parse: function parse (input) {
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1
|
||||
var args = lstack.slice.call(arguments, 1)
|
||||
var lexer = Object.create(this.lexer)
|
||||
var sharedState = { yy: {} }
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
sharedState.yy[k] = this.yy[k]
|
||||
}
|
||||
}
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
lexer.setInput(input, sharedState.yy)
|
||||
sharedState.yy.lexer = lexer
|
||||
sharedState.yy.parser = this
|
||||
if (typeof lexer.yylloc === 'undefined') {
|
||||
lexer.yylloc = {}
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
var yyloc = lexer.yylloc
|
||||
lstack.push(yyloc)
|
||||
var ranges = lexer.options && lexer.options.ranges
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
this.parseError = sharedState.yy.parseError
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
this.parseError = Object.getPrototypeOf(this).parseError
|
||||
}
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
stack.length = stack.length - 2 * n
|
||||
vstack.length = vstack.length - n
|
||||
lstack.length = lstack.length - n
|
||||
}
|
||||
_token_stack:
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
var token
|
||||
token = lexer.lex() || EOF
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
token = self.symbols_[token] || token
|
||||
}
|
||||
return token;
|
||||
};
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
return token
|
||||
}
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected
|
||||
while (true) {
|
||||
state = stack[stack.length - 1];
|
||||
state = stack[stack.length - 1]
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
action = this.defaultActions[state]
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
if (symbol === null || typeof symbol === 'undefined') {
|
||||
symbol = lex()
|
||||
}
|
||||
action = table[state] && table[state][symbol];
|
||||
action = table[state] && table[state][symbol]
|
||||
}
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var errStr = '';
|
||||
expected = [];
|
||||
var errStr = ''
|
||||
expected = []
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push('\'' + this.terminals_[p] + '\'');
|
||||
expected.push('\'' + this.terminals_[p] + '\'')
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''
|
||||
} else {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'')
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
@@ -195,45 +193,45 @@ parse: function parse(input) {
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected
|
||||
});
|
||||
})
|
||||
}
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol)
|
||||
}
|
||||
switch (action[0]) {
|
||||
case 1:
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]);
|
||||
symbol = null;
|
||||
stack.push(symbol)
|
||||
vstack.push(lexer.yytext)
|
||||
lstack.push(lexer.yylloc)
|
||||
stack.push(action[1])
|
||||
symbol = null
|
||||
if (!preErrorSymbol) {
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
yyleng = lexer.yyleng
|
||||
yytext = lexer.yytext
|
||||
yylineno = lexer.yylineno
|
||||
yyloc = lexer.yylloc
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
recovering--
|
||||
}
|
||||
} else {
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
symbol = preErrorSymbol
|
||||
preErrorSymbol = null
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 2:
|
||||
len = this.productions_[action[1]][1];
|
||||
yyval.$ = vstack[vstack.length - len];
|
||||
len = this.productions_[action[1]][1]
|
||||
yyval.$ = vstack[vstack.length - len]
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||||
last_line: lstack[lstack.length - 1].last_line,
|
||||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||||
last_column: lstack[lstack.length - 1].last_column
|
||||
};
|
||||
}
|
||||
if (ranges) {
|
||||
yyval._$.range = [
|
||||
lstack[lstack.length - (len || 1)].range[0],
|
||||
lstack[lstack.length - 1].range[1]
|
||||
];
|
||||
]
|
||||
}
|
||||
r = this.performAction.apply(yyval, [
|
||||
yytext,
|
||||
@@ -243,27 +241,27 @@ parse: function parse(input) {
|
||||
action[1],
|
||||
vstack,
|
||||
lstack
|
||||
].concat(args));
|
||||
].concat(args))
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
return r
|
||||
}
|
||||
if (len) {
|
||||
stack = stack.slice(0, -1 * len * 2);
|
||||
vstack = vstack.slice(0, -1 * len);
|
||||
lstack = lstack.slice(0, -1 * len);
|
||||
stack = stack.slice(0, -1 * len * 2)
|
||||
vstack = vstack.slice(0, -1 * len)
|
||||
lstack = lstack.slice(0, -1 * len)
|
||||
}
|
||||
stack.push(this.productions_[action[1]][0]);
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
stack.push(this.productions_[action[1]][0])
|
||||
vstack.push(yyval.$)
|
||||
lstack.push(yyval._$)
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]]
|
||||
stack.push(newState)
|
||||
break
|
||||
case 3:
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}};
|
||||
return true
|
||||
}}
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function () {
|
||||
var lexer = ({
|
||||
@@ -272,144 +270,143 @@ EOF:1,
|
||||
|
||||
parseError: function parseError (str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
this.yy.parser.parseError(str, hash)
|
||||
} else {
|
||||
throw new Error(str);
|
||||
throw new Error(str)
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput: function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yy = yy || this.yy || {}
|
||||
this._input = input
|
||||
this._more = this._backtrack = this.done = false
|
||||
this.yylineno = this.yyleng = 0
|
||||
this.yytext = this.matched = this.match = ''
|
||||
this.conditionStack = ['INITIAL']
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0, 0]
|
||||
}
|
||||
this.offset = 0
|
||||
return this
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input: function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
var ch = this._input[0]
|
||||
this.yytext += ch
|
||||
this.yyleng++
|
||||
this.offset++
|
||||
this.match += ch
|
||||
this.matched += ch
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
this.yylineno++
|
||||
this.yylloc.last_line++
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
this.yylloc.last_column++
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
this.yylloc.range[1]++
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
this._input = this._input.slice(1)
|
||||
return ch
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput: function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
var len = ch.length
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g)
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
this._input = ch + this._input
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len)
|
||||
// this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
this.offset -= len
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g)
|
||||
this.match = this.match.substr(0, this.match.length - 1)
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1)
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
this.yylineno -= lines.length - 1
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
var r = this.yylloc.range
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
last_column: lines
|
||||
? (lines.length === oldLines.length ? this.yylloc.first_column : 0) +
|
||||
oldLines[oldLines.length - lines.length].length - lines[0].length
|
||||
: this.yylloc.first_column - len
|
||||
}
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len]
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
this.yyleng = this.yytext.length
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more: function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
this._more = true
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject: function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
this._backtrack = true
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
return this;
|
||||
return this
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less: function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
this.unput(this.match.slice(n))
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput: function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length)
|
||||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput: function () {
|
||||
var next = this.match;
|
||||
var next = this.match
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
next += this._input.substr(0, 20 - next.length)
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition: function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
var pre = this.pastInput()
|
||||
var c = new Array(pre.length + 1).join('-')
|
||||
return pre + this.upcomingInput() + '\n' + c + '^'
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match: function (match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
backup
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
@@ -432,225 +429,224 @@ test_match:function (match, indexed_rule) {
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
backup.yylloc.range = this.yylloc.range.slice(0)
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
this.yylineno += lines.length
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
last_column: lines
|
||||
? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length
|
||||
: this.yylloc.last_column + match[0].length
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
this.yytext += match[0]
|
||||
this.match += match[0]
|
||||
this.matches = match
|
||||
this.yyleng = this.yytext.length
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng]
|
||||
}
|
||||
this._more = false
|
||||
this._backtrack = false
|
||||
this._input = this._input.slice(match[0].length)
|
||||
this.matched += match[0]
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1])
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
this.done = false
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
this[k] = backup[k]
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
return false // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next: function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
return this.EOF
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
this.done = true
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
index
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
this.yytext = ''
|
||||
this.match = ''
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
var rules = this._currentRules()
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
tempMatch = this._input.match(this.rules[rules[i]])
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
match = tempMatch
|
||||
index = i
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
token = this.test_match(tempMatch, rules[i])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
match = false
|
||||
continue // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
token = this.test_match(match, rules[index])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
if (this._input === '') {
|
||||
return this.EOF
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex: function lex () {
|
||||
var r = this.next();
|
||||
var r = this.next()
|
||||
if (r) {
|
||||
return r;
|
||||
return r
|
||||
} else {
|
||||
return this.lex();
|
||||
return this.lex()
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin: function begin (condition) {
|
||||
this.conditionStack.push(condition);
|
||||
this.conditionStack.push(condition)
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState: function popState () {
|
||||
var n = this.conditionStack.length - 1;
|
||||
var n = this.conditionStack.length - 1
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
return this.conditionStack.pop()
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
return this.conditionStack[0]
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules: function _currentRules () {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
return this.conditions['INITIAL'].rules
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState: function topState (n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0)
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
return this.conditionStack[n]
|
||||
} else {
|
||||
return "INITIAL";
|
||||
return 'INITIAL'
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState: function pushState (condition) {
|
||||
this.begin(condition);
|
||||
this.begin(condition)
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize: function stateStackSize () {
|
||||
return this.conditionStack.length;
|
||||
return this.conditionStack.length
|
||||
},
|
||||
options: {"case-insensitive":true},
|
||||
options: {'case-insensitive': true},
|
||||
performAction: function anonymous (yy, yy_, $avoiding_name_collisions, YY_START) {
|
||||
// Pre-lexer code can go here
|
||||
|
||||
var YYSTATE=YY_START;
|
||||
var YYSTATE = YY_START
|
||||
switch ($avoiding_name_collisions) {
|
||||
case 0:return 10;
|
||||
break;
|
||||
case 0:return 10
|
||||
break
|
||||
case 1:/* skip whitespace */
|
||||
break;
|
||||
break
|
||||
case 2:/* skip comments */
|
||||
break;
|
||||
break
|
||||
case 3:/* skip comments */
|
||||
break;
|
||||
case 4:return 4;
|
||||
break;
|
||||
case 5:return 11;
|
||||
break;
|
||||
case 6:return 'date';
|
||||
break;
|
||||
case 7:return 12;
|
||||
break;
|
||||
case 8:return 13;
|
||||
break;
|
||||
case 9:return 14;
|
||||
break;
|
||||
case 10:return 15;
|
||||
break;
|
||||
case 11:return ':';
|
||||
break;
|
||||
case 12:return 6;
|
||||
break;
|
||||
case 13:return 'INVALID';
|
||||
break;
|
||||
break
|
||||
case 4:return 4
|
||||
break
|
||||
case 5:return 11
|
||||
break
|
||||
case 6:return 'date'
|
||||
break
|
||||
case 7:return 12
|
||||
break
|
||||
case 8:return 13
|
||||
break
|
||||
case 9:return 14
|
||||
break
|
||||
case 10:return 15
|
||||
break
|
||||
case 11:return ':'
|
||||
break
|
||||
case 12:return 6
|
||||
break
|
||||
case 13:return 'INVALID'
|
||||
break
|
||||
}
|
||||
},
|
||||
rules: [/^(?:[\n]+)/i, /^(?:\s+)/i, /^(?:#[^\n]*)/i, /^(?:%[^\n]*)/i, /^(?:gantt\b)/i, /^(?:dateFormat\s[^#\n;]+)/i, /^(?:\d\d\d\d-\d\d-\d\d\b)/i, /^(?:title\s[^#\n;]+)/i, /^(?:section\s[^#:\n;]+)/i, /^(?:[^#:\n;]+)/i, /^(?::[^#\n;]+)/i, /^(?::)/i, /^(?:$)/i, /^(?:.)/i],
|
||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
conditions: {'INITIAL': {'rules': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 'inclusive': true}}
|
||||
})
|
||||
return lexer
|
||||
})()
|
||||
parser.lexer = lexer
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
this.yy = {}
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
|
||||
Parser.prototype = parser; parser.Parser = Parser
|
||||
return new Parser()
|
||||
})()
|
||||
|
||||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||||
exports.parser = parser;
|
||||
exports.Parser = parser.Parser;
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments); };
|
||||
exports.parser = parser
|
||||
exports.Parser = parser.Parser
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments) }
|
||||
exports.main = function commonjsMain (args) {
|
||||
if (!args[1]) {
|
||||
console.log('Usage: '+args[0]+' FILE');
|
||||
process.exit(1);
|
||||
console.log('Usage: ' + args[0] + ' FILE')
|
||||
process.exit(1)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), 'utf8')
|
||||
return exports.parser.parse(source)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||||
return exports.parser.parse(source);
|
||||
};
|
||||
if (typeof module !== 'undefined' && require.main === module) {
|
||||
exports.main(process.argv.slice(1));
|
||||
exports.main(process.argv.slice(1))
|
||||
}
|
||||
}
|
||||
@@ -1,98 +1,96 @@
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var _ = require('lodash');
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
var _ = require('lodash')
|
||||
|
||||
|
||||
var commits = {};
|
||||
var head = null;
|
||||
var branches = { 'master' : head };
|
||||
var curBranch = 'master';
|
||||
var direction = 'LR';
|
||||
var seq = 0;
|
||||
var commits = {}
|
||||
var head = null
|
||||
var branches = { 'master': head }
|
||||
var curBranch = 'master'
|
||||
var direction = 'LR'
|
||||
var seq = 0
|
||||
|
||||
function getRandomInt (min, max) {
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
return Math.floor(Math.random() * (max - min)) + min
|
||||
}
|
||||
|
||||
function getId () {
|
||||
var pool='0123456789abcdef';
|
||||
var id = '';
|
||||
var pool = '0123456789abcdef'
|
||||
var id = ''
|
||||
for (var i = 0; i < 7; i++) {
|
||||
id += pool[getRandomInt(0, 16)]
|
||||
}
|
||||
return id;
|
||||
return id
|
||||
}
|
||||
|
||||
|
||||
function isfastforwardable (currentCommit, otherCommit) {
|
||||
log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id);
|
||||
log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id)
|
||||
while (currentCommit.seq <= otherCommit.seq && currentCommit != otherCommit) {
|
||||
// only if other branch has more commits
|
||||
if (otherCommit.parent == null) break;
|
||||
if (otherCommit.parent == null) break
|
||||
if (Array.isArray(otherCommit.parent)) {
|
||||
log.debug('In merge commit:', otherCommit.parent);
|
||||
log.debug('In merge commit:', otherCommit.parent)
|
||||
return isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) ||
|
||||
isfastforwardable(currentCommit, commits[otherCommit.parent[1]])
|
||||
} else {
|
||||
otherCommit = commits[otherCommit.parent];
|
||||
otherCommit = commits[otherCommit.parent]
|
||||
}
|
||||
}
|
||||
log.debug(currentCommit.id, otherCommit.id);
|
||||
return currentCommit.id == otherCommit.id;
|
||||
log.debug(currentCommit.id, otherCommit.id)
|
||||
return currentCommit.id == otherCommit.id
|
||||
}
|
||||
|
||||
function isReachableFrom (currentCommit, otherCommit) {
|
||||
var currentSeq = currentCommit.seq;
|
||||
var otherSeq = otherCommit.seq;
|
||||
if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit);
|
||||
return false;
|
||||
var currentSeq = currentCommit.seq
|
||||
var otherSeq = otherCommit.seq
|
||||
if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit)
|
||||
return false
|
||||
}
|
||||
|
||||
exports.setDirection = function (dir) {
|
||||
direction = dir;
|
||||
direction = dir
|
||||
}
|
||||
var options = {};
|
||||
var options = {}
|
||||
exports.setOptions = function (rawOptString) {
|
||||
log.debug('options str', rawOptString);
|
||||
rawOptString = rawOptString && rawOptString.trim();
|
||||
rawOptString = rawOptString || '{}';
|
||||
log.debug('options str', rawOptString)
|
||||
rawOptString = rawOptString && rawOptString.trim()
|
||||
rawOptString = rawOptString || '{}'
|
||||
try {
|
||||
options = JSON.parse(rawOptString)
|
||||
} catch (e) {
|
||||
log.error('error while parsing gitGraph options', e.message);
|
||||
log.error('error while parsing gitGraph options', e.message)
|
||||
}
|
||||
}
|
||||
|
||||
exports.getOptions = function () {
|
||||
return options;
|
||||
return options
|
||||
}
|
||||
|
||||
exports.commit = function (msg) {
|
||||
var commit = { id: getId(),
|
||||
message: msg,
|
||||
seq: seq++,
|
||||
parent: head == null ? null : head.id};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
log.debug('in pushCommit ' + commit.id);
|
||||
parent: head == null ? null : head.id}
|
||||
head = commit
|
||||
commits[commit.id] = commit
|
||||
branches[curBranch] = commit.id
|
||||
log.debug('in pushCommit ' + commit.id)
|
||||
}
|
||||
|
||||
exports.branch = function (name) {
|
||||
branches[name] = head != null ? head.id: null;
|
||||
log.debug('in createBranch');
|
||||
branches[name] = head != null ? head.id : null
|
||||
log.debug('in createBranch')
|
||||
}
|
||||
|
||||
exports.merge = function (otherBranch) {
|
||||
var currentCommit = commits[branches[curBranch]];
|
||||
var otherCommit = commits[branches[otherBranch]];
|
||||
var currentCommit = commits[branches[curBranch]]
|
||||
var otherCommit = commits[branches[otherBranch]]
|
||||
if (isReachableFrom(currentCommit, otherCommit)) {
|
||||
log.debug('Already merged');
|
||||
return;
|
||||
log.debug('Already merged')
|
||||
return
|
||||
}
|
||||
if (isfastforwardable(currentCommit, otherCommit)) {
|
||||
branches[curBranch] = branches[otherBranch];
|
||||
head = commits[branches[curBranch]];
|
||||
branches[curBranch] = branches[otherBranch]
|
||||
head = commits[branches[curBranch]]
|
||||
} else {
|
||||
// create merge commit
|
||||
var commit = {
|
||||
@@ -100,115 +98,114 @@ exports.merge = function(otherBranch) {
|
||||
message: 'merged branch ' + otherBranch + ' into ' + curBranch,
|
||||
seq: seq++,
|
||||
parent: [head == null ? null : head.id, branches[otherBranch]]
|
||||
};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
}
|
||||
log.debug(branches);
|
||||
log.debug('in mergeBranch');
|
||||
head = commit
|
||||
commits[commit.id] = commit
|
||||
branches[curBranch] = commit.id
|
||||
}
|
||||
log.debug(branches)
|
||||
log.debug('in mergeBranch')
|
||||
}
|
||||
|
||||
exports.checkout = function (branch) {
|
||||
log.debug('in checkout');
|
||||
curBranch = branch;
|
||||
var id = branches[curBranch];
|
||||
head = commits[id];
|
||||
log.debug('in checkout')
|
||||
curBranch = branch
|
||||
var id = branches[curBranch]
|
||||
head = commits[id]
|
||||
}
|
||||
|
||||
exports.reset = function (commitRef) {
|
||||
log.debug('in reset', commitRef);
|
||||
var ref = commitRef.split(':')[0];
|
||||
var parentCount = parseInt(commitRef.split(':')[1]);
|
||||
var commit = ref == 'HEAD' ? head : commits[branches[ref]];
|
||||
log.debug(commit, parentCount);
|
||||
log.debug('in reset', commitRef)
|
||||
var ref = commitRef.split(':')[0]
|
||||
var parentCount = parseInt(commitRef.split(':')[1])
|
||||
var commit = ref == 'HEAD' ? head : commits[branches[ref]]
|
||||
log.debug(commit, parentCount)
|
||||
while (parentCount > 0) {
|
||||
commit = commits[commit.parent];
|
||||
parentCount--;
|
||||
commit = commits[commit.parent]
|
||||
parentCount--
|
||||
if (!commit) {
|
||||
var err = 'Critical error - unique parent commit not found during reset';
|
||||
log.error(err);
|
||||
throw err;
|
||||
var err = 'Critical error - unique parent commit not found during reset'
|
||||
log.error(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
head = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
head = commit
|
||||
branches[curBranch] = commit.id
|
||||
}
|
||||
|
||||
function upsert (arr, key, newval) {
|
||||
var match = _.find(arr, key);
|
||||
var match = _.find(arr, key)
|
||||
if (match) {
|
||||
var index = _.indexOf(arr, _.find(arr, key));
|
||||
arr.splice(index, 1, newval);
|
||||
var index = _.indexOf(arr, _.find(arr, key))
|
||||
arr.splice(index, 1, newval)
|
||||
} else {
|
||||
arr.push(newval);
|
||||
arr.push(newval)
|
||||
}
|
||||
// console.log(arr);
|
||||
}
|
||||
|
||||
function prettyPrintCommitHistory (commitArr) {
|
||||
var commit = _.maxBy(commitArr, 'seq');
|
||||
var line = '';
|
||||
var commit = _.maxBy(commitArr, 'seq')
|
||||
var line = ''
|
||||
_.each(commitArr, function (c) {
|
||||
if (c == commit) {
|
||||
line += '\t*'
|
||||
} else {
|
||||
line += '\t|'
|
||||
}
|
||||
});
|
||||
var label = [line, commit.id, commit.seq];
|
||||
})
|
||||
var label = [line, commit.id, commit.seq]
|
||||
_.each(branches, function (v, k) {
|
||||
if (v == commit.id) label.push(k);
|
||||
});
|
||||
log.debug(label.join(' '));
|
||||
if (v == commit.id) label.push(k)
|
||||
})
|
||||
log.debug(label.join(' '))
|
||||
if (Array.isArray(commit.parent)) {
|
||||
// console.log("here", commit.parent);
|
||||
var newCommit = commits[commit.parent[0]];
|
||||
upsert(commitArr, commit, newCommit);
|
||||
commitArr.push(commits[commit.parent[1]]);
|
||||
var newCommit = commits[commit.parent[0]]
|
||||
upsert(commitArr, commit, newCommit)
|
||||
commitArr.push(commits[commit.parent[1]])
|
||||
// console.log("shoudl have 2", commitArr);
|
||||
} else if (commit.parent == null) {
|
||||
return;
|
||||
return
|
||||
} else {
|
||||
var nextCommit = commits[commit.parent];
|
||||
upsert(commitArr, commit, nextCommit);
|
||||
var nextCommit = commits[commit.parent]
|
||||
upsert(commitArr, commit, nextCommit)
|
||||
}
|
||||
commitArr = _.uniqBy(commitArr, 'id');
|
||||
prettyPrintCommitHistory(commitArr);
|
||||
|
||||
commitArr = _.uniqBy(commitArr, 'id')
|
||||
prettyPrintCommitHistory(commitArr)
|
||||
}
|
||||
|
||||
exports.prettyPrint = function () {
|
||||
log.debug(commits);
|
||||
var node = exports.getCommitsArray()[0];
|
||||
prettyPrintCommitHistory([node]);
|
||||
log.debug(commits)
|
||||
var node = exports.getCommitsArray()[0]
|
||||
prettyPrintCommitHistory([node])
|
||||
}
|
||||
|
||||
exports.clear = function () {
|
||||
commits = {};
|
||||
head = null;
|
||||
branches = { 'master' : head };
|
||||
curBranch = 'master';
|
||||
seq =0;
|
||||
commits = {}
|
||||
head = null
|
||||
branches = { 'master': head }
|
||||
curBranch = 'master'
|
||||
seq = 0
|
||||
}
|
||||
|
||||
exports.getBranchesAsObjArray = function () {
|
||||
var branchArr = _.map(branches, function (v, k) {
|
||||
return {'name': k, 'commit': commits[v]};
|
||||
});
|
||||
return {'name': k, 'commit': commits[v]}
|
||||
})
|
||||
// return _.orderBy(branchArr, [function(b) { return b.commit.seq}], ['desc']);
|
||||
return branchArr;
|
||||
return branchArr
|
||||
}
|
||||
|
||||
exports.getBranches = function() { return branches; }
|
||||
exports.getCommits = function() { return commits; }
|
||||
exports.getBranches = function () { return branches }
|
||||
exports.getCommits = function () { return commits }
|
||||
exports.getCommitsArray = function () {
|
||||
var commitArr = Object.keys(commits).map(function (key) {
|
||||
return commits[key];
|
||||
});
|
||||
_.each(commitArr, function(o) { log.debug(o.id) });
|
||||
return _.orderBy(commitArr, ['seq'], ['desc']);
|
||||
return commits[key]
|
||||
})
|
||||
_.each(commitArr, function (o) { log.debug(o.id) })
|
||||
return _.orderBy(commitArr, ['seq'], ['desc'])
|
||||
}
|
||||
exports.getCurrentBranch = function() { return curBranch; }
|
||||
exports.getDirection = function() { return direction; }
|
||||
exports.getHead = function() { return head; }
|
||||
exports.getCurrentBranch = function () { return curBranch }
|
||||
exports.getDirection = function () { return direction }
|
||||
exports.getHead = function () { return head }
|
||||
|
||||
@@ -1,103 +1,103 @@
|
||||
var parser = require('./parser/gitGraph').parser;
|
||||
var ast = require('./gitGraphAst.js');
|
||||
var parser = require('./parser/gitGraph').parser
|
||||
var ast = require('./gitGraphAst.js')
|
||||
describe('when parsing a gitGraph', function () {
|
||||
'use strict';
|
||||
'use strict'
|
||||
beforeEach(function () {
|
||||
console.log('ast',ast);
|
||||
console.log('parser',parser);
|
||||
parser.yy = ast;
|
||||
parser.yy.clear();
|
||||
});
|
||||
console.log('ast', ast)
|
||||
console.log('parser', parser)
|
||||
parser.yy = ast
|
||||
parser.yy.clear()
|
||||
})
|
||||
it('should handle a gitGraph defintion', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
'commit\n';
|
||||
'commit\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(1)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
expect(parser.yy.getDirection()).toBe('LR')
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
|
||||
})
|
||||
|
||||
it('should handle a gitGraph defintion with empty options', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
'options\n' +
|
||||
'end\n' +
|
||||
'commit\n';
|
||||
'commit\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
|
||||
expect(parser.yy.getOptions()).toEqual({});
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
});
|
||||
expect(parser.yy.getOptions()).toEqual({})
|
||||
expect(Object.keys(commits).length).toBe(1)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
expect(parser.yy.getDirection()).toBe('LR')
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
|
||||
})
|
||||
|
||||
it('should handle a gitGraph defintion with valid options', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
'options\n' +
|
||||
'{"key": "value"}\n' +
|
||||
'end\n' +
|
||||
'commit\n';
|
||||
'commit\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
// console.log('options object', parser.yy.getOptions());
|
||||
expect(parser.yy.getOptions()['key']).toBe('value');
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
});
|
||||
expect(parser.yy.getOptions()['key']).toBe('value')
|
||||
expect(Object.keys(commits).length).toBe(1)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
expect(parser.yy.getDirection()).toBe('LR')
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
|
||||
})
|
||||
|
||||
it('should not fail on a gitGraph with malformed json', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
'options\n' +
|
||||
'{"key": "value"\n' +
|
||||
'end\n' +
|
||||
'commit\n';
|
||||
'commit\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
expect(parser.yy.getDirection()).toBe('LR');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(1)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
expect(parser.yy.getDirection()).toBe('LR')
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
|
||||
})
|
||||
|
||||
it('should handle set direction', function () {
|
||||
var str = 'gitGraph BT:\n' +
|
||||
'commit\n';
|
||||
'commit\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
expect(parser.yy.getDirection()).toBe('BT');
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(1)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
expect(parser.yy.getDirection()).toBe('BT')
|
||||
expect(Object.keys(parser.yy.getBranches()).length).toBe(1)
|
||||
})
|
||||
|
||||
it('should checkout a branch', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
'branch new\n' +
|
||||
'checkout new\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
|
||||
expect(Object.keys(commits).length).toBe(0);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('new');
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(0)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('new')
|
||||
})
|
||||
|
||||
it('should add commits to checked out branch', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
@@ -106,28 +106,28 @@ describe('when parsing a gitGraph',function() {
|
||||
'commit\n' +
|
||||
'commit\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
|
||||
expect(Object.keys(commits).length).toBe(2);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('new');
|
||||
var branchCommit = parser.yy.getBranches()['new'];
|
||||
expect(branchCommit).not.toBeNull();
|
||||
expect(commits[branchCommit].parent).not.toBeNull();
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(2)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('new')
|
||||
var branchCommit = parser.yy.getBranches()['new']
|
||||
expect(branchCommit).not.toBeNull()
|
||||
expect(commits[branchCommit].parent).not.toBeNull()
|
||||
})
|
||||
it('should handle commit with args', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
'commit "a commit"\n';
|
||||
'commit "a commit"\n'
|
||||
|
||||
parser.parse(str);
|
||||
var commits = parser.yy.getCommits();
|
||||
parser.parse(str)
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
|
||||
expect(Object.keys(commits).length).toBe(1);
|
||||
var key = Object.keys(commits)[0];
|
||||
expect(commits[key].message).toBe('a commit');
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(1)
|
||||
var key = Object.keys(commits)[0]
|
||||
expect(commits[key].message).toBe('a commit')
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
})
|
||||
|
||||
it('it should reset a branch', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
@@ -136,16 +136,16 @@ describe('when parsing a gitGraph',function() {
|
||||
'branch newbranch\n' +
|
||||
'checkout newbranch\n' +
|
||||
'commit\n' +
|
||||
'reset master\n';
|
||||
'reset master\n'
|
||||
|
||||
parser.parse(str);
|
||||
parser.parse(str)
|
||||
|
||||
var commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(3);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch');
|
||||
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']);
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
|
||||
});
|
||||
var commits = parser.yy.getCommits()
|
||||
expect(Object.keys(commits).length).toBe(3)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch')
|
||||
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch'])
|
||||
})
|
||||
|
||||
it('reset can take an argument', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
@@ -154,15 +154,15 @@ describe('when parsing a gitGraph',function() {
|
||||
'branch newbranch\n' +
|
||||
'checkout newbranch\n' +
|
||||
'commit\n' +
|
||||
'reset master^\n';
|
||||
'reset master^\n'
|
||||
|
||||
parser.parse(str);
|
||||
parser.parse(str)
|
||||
|
||||
var commits = parser.yy.getCommits();
|
||||
expect(Object.keys(commits).length).toBe(3);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch');
|
||||
var master = commits[parser.yy.getBranches()['master']];
|
||||
expect(parser.yy.getHead().id).toEqual(master.parent);
|
||||
var commits = parser.yy.getCommits()
|
||||
expect(Object.keys(commits).length).toBe(3)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch')
|
||||
var master = commits[parser.yy.getBranches()['master']]
|
||||
expect(parser.yy.getHead().id).toEqual(master.parent)
|
||||
})
|
||||
|
||||
it('it should handle fast forwardable merges', function () {
|
||||
@@ -173,17 +173,17 @@ describe('when parsing a gitGraph',function() {
|
||||
'commit\n' +
|
||||
'commit\n' +
|
||||
'checkout master\n' +
|
||||
'merge newbranch\n';
|
||||
'merge newbranch\n'
|
||||
|
||||
parser.parse(str);
|
||||
parser.parse(str)
|
||||
|
||||
var commits = parser.yy.getCommits();
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
expect(Object.keys(commits).length).toBe(3);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']);
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(3)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch'])
|
||||
})
|
||||
|
||||
it('it should handle cases when merge is a noop', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
@@ -192,17 +192,17 @@ describe('when parsing a gitGraph',function() {
|
||||
'checkout newbranch\n' +
|
||||
'commit\n' +
|
||||
'commit\n' +
|
||||
'merge master\n';
|
||||
'merge master\n'
|
||||
|
||||
parser.parse(str);
|
||||
parser.parse(str)
|
||||
|
||||
var commits = parser.yy.getCommits();
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
expect(Object.keys(commits).length).toBe(3);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch');
|
||||
expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master']);
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(3)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch')
|
||||
expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master'])
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch'])
|
||||
})
|
||||
|
||||
it('it should handle merge with 2 parents', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
@@ -213,17 +213,17 @@ describe('when parsing a gitGraph',function() {
|
||||
'commit\n' +
|
||||
'checkout master\n' +
|
||||
'commit\n' +
|
||||
'merge newbranch\n';
|
||||
'merge newbranch\n'
|
||||
|
||||
parser.parse(str);
|
||||
parser.parse(str)
|
||||
|
||||
var commits = parser.yy.getCommits();
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
expect(Object.keys(commits).length).toBe(5);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master']);
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master']);
|
||||
});
|
||||
expect(Object.keys(commits).length).toBe(5)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master')
|
||||
expect(parser.yy.getBranches()['newbranch']).not.toEqual(parser.yy.getBranches()['master'])
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master'])
|
||||
})
|
||||
|
||||
it('it should handle ff merge when history walk has two parents (merge commit)', function () {
|
||||
var str = 'gitGraph:\n' +
|
||||
@@ -237,17 +237,17 @@ describe('when parsing a gitGraph',function() {
|
||||
'merge newbranch\n' +
|
||||
'commit\n' +
|
||||
'checkout newbranch\n' +
|
||||
'merge master\n' ;
|
||||
'merge master\n'
|
||||
|
||||
parser.parse(str);
|
||||
parser.parse(str)
|
||||
|
||||
var commits = parser.yy.getCommits();
|
||||
var commits = parser.yy.getCommits()
|
||||
// console.log(commits);
|
||||
expect(Object.keys(commits).length).toBe(6);
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch');
|
||||
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master']);
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master']);
|
||||
expect(Object.keys(commits).length).toBe(6)
|
||||
expect(parser.yy.getCurrentBranch()).toBe('newbranch')
|
||||
expect(parser.yy.getBranches()['newbranch']).toEqual(parser.yy.getBranches()['master'])
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master'])
|
||||
|
||||
parser.yy.prettyPrint();
|
||||
});
|
||||
});
|
||||
parser.yy.prettyPrint()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
var db = require('./gitGraphAst');
|
||||
var _ = require('lodash');
|
||||
var gitGraphParser = require('./parser/gitGraph');
|
||||
var d3 = require('../../d3');
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var db = require('./gitGraphAst')
|
||||
var _ = require('lodash')
|
||||
var gitGraphParser = require('./parser/gitGraph')
|
||||
var d3 = require('../../d3')
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
|
||||
var allCommitsDict = {};
|
||||
var branchNum;
|
||||
var allCommitsDict = {}
|
||||
var branchNum
|
||||
var config = {
|
||||
nodeSpacing: 75,
|
||||
nodeFillColor: 'yellow',
|
||||
@@ -25,12 +25,11 @@ var config = {
|
||||
y: 15
|
||||
}
|
||||
}
|
||||
var apiConfig = {};
|
||||
var apiConfig = {}
|
||||
exports.setConf = function (c) {
|
||||
apiConfig = c;
|
||||
apiConfig = c
|
||||
}
|
||||
|
||||
|
||||
function svgCreateDefs (svg) {
|
||||
svg
|
||||
.append('defs')
|
||||
@@ -39,7 +38,7 @@ function svgCreateDefs(svg) {
|
||||
.append('circle')
|
||||
.attr('r', config.nodeRadius)
|
||||
.attr('cx', 0)
|
||||
.attr('cy', 0);
|
||||
.attr('cy', 0)
|
||||
svg.select('#def-commit')
|
||||
.append('foreignObject')
|
||||
.attr('width', config.nodeLabel.width)
|
||||
@@ -49,13 +48,12 @@ function svgCreateDefs(svg) {
|
||||
.attr('class', 'node-label')
|
||||
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
|
||||
.append('xhtml:p')
|
||||
.html('');
|
||||
.html('')
|
||||
}
|
||||
|
||||
|
||||
function svgDrawLine (svg, points, colorIdx, interpolate) {
|
||||
interpolate = interpolate || 'basis';
|
||||
var color = config.branchColors[colorIdx % config.branchColors.length];
|
||||
interpolate = interpolate || 'basis'
|
||||
var color = config.branchColors[colorIdx % config.branchColors.length]
|
||||
var lineGen = d3.svg.line()
|
||||
.x(function (d) {
|
||||
return Math.round(d.x)
|
||||
@@ -63,34 +61,34 @@ function svgDrawLine(svg, points, colorIdx, interpolate) {
|
||||
.y(function (d) {
|
||||
return Math.round(d.y)
|
||||
})
|
||||
.interpolate(interpolate);
|
||||
.interpolate(interpolate)
|
||||
|
||||
svg
|
||||
.append('svg:path')
|
||||
.attr('d', lineGen(points))
|
||||
.style('stroke', color)
|
||||
.style('stroke-width', config.lineStrokeWidth)
|
||||
.style('fill', 'none');
|
||||
.style('fill', 'none')
|
||||
}
|
||||
// Pass in the element and its pre-transform coords
|
||||
function getElementCoords (element, coords) {
|
||||
coords = coords || element.node().getBBox();
|
||||
coords = coords || element.node().getBBox()
|
||||
var ctm = element.node().getCTM(),
|
||||
xn = ctm.e + coords.x * ctm.a,
|
||||
yn = ctm.f + coords.y * ctm.d;
|
||||
yn = ctm.f + coords.y * ctm.d
|
||||
// log.debug(ctm, coords);
|
||||
return {
|
||||
left: xn,
|
||||
top: yn,
|
||||
width: coords.width,
|
||||
height: coords.height
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function svgDrawLineForCommits (svg, fromId, toId, direction, color) {
|
||||
log.debug('svgDrawLineForCommits: ', fromId, toId);
|
||||
var fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'));
|
||||
var toBbox = getElementCoords(svg.select('#node-' + toId + ' circle'));
|
||||
log.debug('svgDrawLineForCommits: ', fromId, toId)
|
||||
var fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'))
|
||||
var toBbox = getElementCoords(svg.select('#node-' + toId + ' circle'))
|
||||
// log.debug('svgDrawLineForCommits: ', fromBbox, toBbox);
|
||||
switch (direction) {
|
||||
case 'LR':
|
||||
@@ -98,14 +96,14 @@ function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
|
||||
// +--------
|
||||
// + (fromBbox)
|
||||
if (fromBbox.left - toBbox.left > config.nodeSpacing) {
|
||||
var lineStart = { x: fromBbox.left - config.nodeSpacing, y: toBbox.top + toBbox.height/2};
|
||||
var lineEnd ={ x: toBbox.left + toBbox.width, y: toBbox.top + toBbox.height/2 };
|
||||
var lineStart = { x: fromBbox.left - config.nodeSpacing, y: toBbox.top + toBbox.height / 2}
|
||||
var lineEnd = { x: toBbox.left + toBbox.width, y: toBbox.top + toBbox.height / 2 }
|
||||
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear')
|
||||
svgDrawLine(svg, [
|
||||
{x: fromBbox.left, y: fromBbox.top + fromBbox.height / 2},
|
||||
{x: fromBbox.left - config.nodeSpacing / 2, y: fromBbox.top + fromBbox.height / 2},
|
||||
{x: fromBbox.left - config.nodeSpacing / 2, y: lineStart.y},
|
||||
lineStart], color);
|
||||
lineStart], color)
|
||||
} else {
|
||||
svgDrawLine(svg, [{
|
||||
'x': fromBbox.left,
|
||||
@@ -119,23 +117,23 @@ function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
|
||||
}, {
|
||||
'x': toBbox.left + toBbox.width,
|
||||
'y': toBbox.top + toBbox.height / 2
|
||||
}], color);
|
||||
}], color)
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'BT':
|
||||
// + (fromBbox)
|
||||
// |
|
||||
// |
|
||||
// + (toBbox)
|
||||
if (toBbox.top - fromBbox.top > config.nodeSpacing) {
|
||||
lineStart = { x: toBbox.left + toBbox.width/2, y: fromBbox.top + fromBbox.height + config.nodeSpacing};
|
||||
lineEnd ={ x: toBbox.left + toBbox.width/2, y: toBbox.top };
|
||||
lineStart = { x: toBbox.left + toBbox.width / 2, y: fromBbox.top + fromBbox.height + config.nodeSpacing}
|
||||
lineEnd = { x: toBbox.left + toBbox.width / 2, y: toBbox.top }
|
||||
svgDrawLine(svg, [lineStart, lineEnd], color, 'linear')
|
||||
svgDrawLine(svg, [
|
||||
{x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height},
|
||||
{x: fromBbox.left + fromBbox.width / 2, y: fromBbox.top + fromBbox.height + config.nodeSpacing / 2},
|
||||
{x: toBbox.left + toBbox.width / 2, y: lineStart.y - config.nodeSpacing / 2},
|
||||
lineStart], color);
|
||||
lineStart], color)
|
||||
} else {
|
||||
svgDrawLine(svg, [{
|
||||
'x': fromBbox.left + fromBbox.width / 2,
|
||||
@@ -149,134 +147,134 @@ function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
|
||||
}, {
|
||||
'x': toBbox.left + toBbox.width / 2,
|
||||
'y': toBbox.top
|
||||
}], color);
|
||||
}], color)
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function cloneNode (svg, selector) {
|
||||
return svg.select(selector).node().cloneNode(true);
|
||||
return svg.select(selector).node().cloneNode(true)
|
||||
}
|
||||
|
||||
function renderCommitHistory (svg, commitid, branches, direction) {
|
||||
var commit;
|
||||
var numCommits = Object.keys(allCommitsDict).length;
|
||||
var commit
|
||||
var numCommits = Object.keys(allCommitsDict).length
|
||||
if (_.isString(commitid)) {
|
||||
do {
|
||||
commit = allCommitsDict[commitid];
|
||||
log.debug('in renderCommitHistory', commit.id, commit.seq);
|
||||
commit = allCommitsDict[commitid]
|
||||
log.debug('in renderCommitHistory', commit.id, commit.seq)
|
||||
if (svg.select('#node-' + commitid).size() > 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
svg
|
||||
.append(function () {
|
||||
return cloneNode(svg, '#def-commit');
|
||||
return cloneNode(svg, '#def-commit')
|
||||
})
|
||||
.attr('class', 'commit')
|
||||
.attr('id', function () {
|
||||
return 'node-' + commit.id;
|
||||
return 'node-' + commit.id
|
||||
})
|
||||
.attr('transform', function () {
|
||||
switch (direction) {
|
||||
case 'LR':
|
||||
return 'translate(' + (commit.seq * config.nodeSpacing + config.leftMargin) + ', '
|
||||
+ (branchNum * config.branchOffset) + ')';
|
||||
return 'translate(' + (commit.seq * config.nodeSpacing + config.leftMargin) + ', ' +
|
||||
(branchNum * config.branchOffset) + ')'
|
||||
case 'BT':
|
||||
return 'translate(' + (branchNum * config.branchOffset + config.leftMargin) + ', '
|
||||
+ ((numCommits - commit.seq) * config.nodeSpacing) + ')';
|
||||
return 'translate(' + (branchNum * config.branchOffset + config.leftMargin) + ', ' +
|
||||
((numCommits - commit.seq) * config.nodeSpacing) + ')'
|
||||
}
|
||||
})
|
||||
.attr('fill', config.nodeFillColor)
|
||||
.attr('stroke', config.nodeStrokeColor)
|
||||
.attr('stroke-width', config.nodeStrokeWidth);
|
||||
.attr('stroke-width', config.nodeStrokeWidth)
|
||||
|
||||
var branch = _.find(branches, ['commit', commit]);
|
||||
var branch = _.find(branches, ['commit', commit])
|
||||
if (branch) {
|
||||
log.debug('found branch ', branch.name);
|
||||
log.debug('found branch ', branch.name)
|
||||
svg.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'branch-label')
|
||||
.text(branch.name + ', ');
|
||||
.text(branch.name + ', ')
|
||||
}
|
||||
svg.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'commit-id')
|
||||
.text(commit.id);
|
||||
.text(commit.id)
|
||||
if (commit.message !== '' && direction === 'BT') {
|
||||
svg.select('#node-' + commit.id + ' p')
|
||||
.append('xhtml:span')
|
||||
.attr('class', 'commit-msg')
|
||||
.text( ', ' + commit.message);
|
||||
.text(', ' + commit.message)
|
||||
}
|
||||
commitid = commit.parent
|
||||
} while (commitid && allCommitsDict[commitid]);
|
||||
} while (commitid && allCommitsDict[commitid])
|
||||
}
|
||||
|
||||
if (_.isArray(commitid)) {
|
||||
log.debug('found merge commmit', commitid);
|
||||
renderCommitHistory(svg, commitid[0], branches, direction);
|
||||
branchNum++;
|
||||
renderCommitHistory(svg, commitid[1], branches, direction);
|
||||
branchNum--;
|
||||
log.debug('found merge commmit', commitid)
|
||||
renderCommitHistory(svg, commitid[0], branches, direction)
|
||||
branchNum++
|
||||
renderCommitHistory(svg, commitid[1], branches, direction)
|
||||
branchNum--
|
||||
}
|
||||
}
|
||||
|
||||
function renderLines (svg, commit, direction, branchColor) {
|
||||
branchColor = branchColor || 0;
|
||||
branchColor = branchColor || 0
|
||||
while (commit.seq > 0 && !commit.lineDrawn) {
|
||||
if (_.isString(commit.parent)) {
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent, direction, branchColor);
|
||||
commit.lineDrawn = true;
|
||||
commit = allCommitsDict[commit.parent];
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent, direction, branchColor)
|
||||
commit.lineDrawn = true
|
||||
commit = allCommitsDict[commit.parent]
|
||||
} else if (_.isArray(commit.parent)) {
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent[0], direction, branchColor)
|
||||
svgDrawLineForCommits(svg, commit.id, commit.parent[1], direction, branchColor + 1)
|
||||
renderLines(svg, allCommitsDict[commit.parent[1]], direction, branchColor + 1);
|
||||
commit.lineDrawn = true;
|
||||
commit = allCommitsDict[commit.parent[0]];
|
||||
renderLines(svg, allCommitsDict[commit.parent[1]], direction, branchColor + 1)
|
||||
commit.lineDrawn = true
|
||||
commit = allCommitsDict[commit.parent[0]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.draw = function (txt, id, ver) {
|
||||
try {
|
||||
var parser;
|
||||
parser = gitGraphParser.parser;
|
||||
parser.yy = db;
|
||||
var parser
|
||||
parser = gitGraphParser.parser
|
||||
parser.yy = db
|
||||
|
||||
log.debug('in gitgraph renderer', txt, id, ver);
|
||||
log.debug('in gitgraph renderer', txt, id, ver)
|
||||
// Parse the graph definition
|
||||
parser.parse(txt + '\n');
|
||||
parser.parse(txt + '\n')
|
||||
|
||||
config = _.extend(config, apiConfig, db.getOptions());
|
||||
log.debug('effective options', config);
|
||||
var direction = db.getDirection();
|
||||
allCommitsDict = db.getCommits();
|
||||
var branches = db.getBranchesAsObjArray();
|
||||
config = _.extend(config, apiConfig, db.getOptions())
|
||||
log.debug('effective options', config)
|
||||
var direction = db.getDirection()
|
||||
allCommitsDict = db.getCommits()
|
||||
var branches = db.getBranchesAsObjArray()
|
||||
if (direction === 'BT') {
|
||||
config.nodeLabel.x = branches.length * config.branchOffset;
|
||||
config.nodeLabel.width = '100%';
|
||||
config.nodeLabel.y = -1 * 2* config.nodeRadius;
|
||||
config.nodeLabel.x = branches.length * config.branchOffset
|
||||
config.nodeLabel.width = '100%'
|
||||
config.nodeLabel.y = -1 * 2 * config.nodeRadius
|
||||
}
|
||||
var svg = d3.select('#' + id);
|
||||
svgCreateDefs(svg);
|
||||
branchNum = 1;
|
||||
var svg = d3.select('#' + id)
|
||||
svgCreateDefs(svg)
|
||||
branchNum = 1
|
||||
_.each(branches, function (v) {
|
||||
renderCommitHistory(svg, v.commit.id, branches, direction);
|
||||
renderLines(svg, v.commit, direction);
|
||||
branchNum++;
|
||||
});
|
||||
renderCommitHistory(svg, v.commit.id, branches, direction)
|
||||
renderLines(svg, v.commit, direction)
|
||||
branchNum++
|
||||
})
|
||||
svg.attr('height', function () {
|
||||
if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing;
|
||||
return (branches.length + 1) * config.branchOffset;
|
||||
});
|
||||
if (direction === 'BT') return Object.keys(allCommitsDict).length * config.nodeSpacing
|
||||
return (branches.length + 1) * config.branchOffset
|
||||
})
|
||||
// svg.attr('width', function() {
|
||||
// if (direction === 'LR') return Object.keys(allCommitsDict).length * config.nodeSpacing + config.leftMargin;
|
||||
// return (branches.length + 1) * config.branchOffset;
|
||||
// });
|
||||
} catch (e) {
|
||||
log.error('Error while rendering gitgraph');
|
||||
log.error(e.message);
|
||||
log.error('Error while rendering gitgraph')
|
||||
log.error(e.message)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
token location info (@$, _$, etc.): {
|
||||
first_line: n,
|
||||
last_line: n,
|
||||
@@ -59,7 +58,6 @@
|
||||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||||
}
|
||||
|
||||
|
||||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||||
text: (matched text)
|
||||
token: (the produced terminal token, if any)
|
||||
@@ -72,149 +70,149 @@
|
||||
}
|
||||
*/
|
||||
var parser = (function () {
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[2,3],$V1=[1,7],$V2=[7,12,15,17,19,20,21],$V3=[7,11,12,15,17,19,20,21],$V4=[2,20],$V5=[1,32];
|
||||
var o = function (k, v, o, l) { for (o = o || {}, l = k.length; l--; o[k[l]] = v);return o }, $V0 = [2, 3], $V1 = [1, 7], $V2 = [7, 12, 15, 17, 19, 20, 21], $V3 = [7, 11, 12, 15, 17, 19, 20, 21], $V4 = [2, 20], $V5 = [1, 32]
|
||||
var parser = {trace: function trace () { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"start":3,"GG":4,":":5,"document":6,"EOF":7,"DIR":8,"options":9,"body":10,"OPT":11,"NL":12,"line":13,"statement":14,"COMMIT":15,"commit_arg":16,"BRANCH":17,"ID":18,"CHECKOUT":19,"MERGE":20,"RESET":21,"reset_arg":22,"STR":23,"HEAD":24,"reset_parents":25,"CARET":26,"$accept":0,"$end":1},
|
||||
terminals_: {2:"error",4:"GG",5:":",7:"EOF",8:"DIR",11:"OPT",12:"NL",15:"COMMIT",17:"BRANCH",18:"ID",19:"CHECKOUT",20:"MERGE",21:"RESET",23:"STR",24:"HEAD",26:"CARET"},
|
||||
symbols_: {'error': 2, 'start': 3, 'GG': 4, ':': 5, 'document': 6, 'EOF': 7, 'DIR': 8, 'options': 9, 'body': 10, 'OPT': 11, 'NL': 12, 'line': 13, 'statement': 14, 'COMMIT': 15, 'commit_arg': 16, 'BRANCH': 17, 'ID': 18, 'CHECKOUT': 19, 'MERGE': 20, 'RESET': 21, 'reset_arg': 22, 'STR': 23, 'HEAD': 24, 'reset_parents': 25, 'CARET': 26, '$accept': 0, '$end': 1},
|
||||
terminals_: {2: 'error', 4: 'GG', 5: ':', 7: 'EOF', 8: 'DIR', 11: 'OPT', 12: 'NL', 15: 'COMMIT', 17: 'BRANCH', 18: 'ID', 19: 'CHECKOUT', 20: 'MERGE', 21: 'RESET', 23: 'STR', 24: 'HEAD', 26: 'CARET'},
|
||||
productions_: [0, [3, 4], [3, 5], [6, 0], [6, 2], [9, 2], [9, 1], [10, 0], [10, 2], [13, 2], [13, 1], [14, 2], [14, 2], [14, 2], [14, 2], [14, 2], [16, 0], [16, 1], [22, 2], [22, 2], [25, 0], [25, 2]],
|
||||
performAction: function anonymous (yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
var $0 = $$.length - 1
|
||||
switch (yystate) {
|
||||
case 1:
|
||||
return $$[$0-1];
|
||||
break;
|
||||
return $$[$0 - 1]
|
||||
break
|
||||
case 2:
|
||||
yy.setDirection($$[$0-3]); return $$[$0-1];
|
||||
break;
|
||||
yy.setDirection($$[$0 - 3]); return $$[$0 - 1]
|
||||
break
|
||||
case 4:
|
||||
yy.setOptions($$[$0 - 1]); this.$ = $$[$0]
|
||||
break;
|
||||
break
|
||||
case 5:
|
||||
$$[$0 - 1] += $$[$0]; this.$ = $$[$0 - 1]
|
||||
break;
|
||||
break
|
||||
case 7:
|
||||
this.$ = []
|
||||
break;
|
||||
break
|
||||
case 8:
|
||||
$$[$0-1].push($$[$0]); this.$=$$[$0-1];
|
||||
break;
|
||||
$$[$0 - 1].push($$[$0]); this.$ = $$[$0 - 1]
|
||||
break
|
||||
case 9:
|
||||
this.$ = $$[$0 - 1]
|
||||
break;
|
||||
break
|
||||
case 11:
|
||||
yy.commit($$[$0])
|
||||
break;
|
||||
break
|
||||
case 12:
|
||||
yy.branch($$[$0])
|
||||
break;
|
||||
break
|
||||
case 13:
|
||||
yy.checkout($$[$0])
|
||||
break;
|
||||
break
|
||||
case 14:
|
||||
yy.merge($$[$0])
|
||||
break;
|
||||
break
|
||||
case 15:
|
||||
yy.reset($$[$0])
|
||||
break;
|
||||
break
|
||||
case 16:
|
||||
this.$ = ""
|
||||
break;
|
||||
this.$ = ''
|
||||
break
|
||||
case 17:
|
||||
this.$ = $$[$0]
|
||||
break;
|
||||
break
|
||||
case 18:
|
||||
this.$ = $$[$0-1]+ ":" + $$[$0]
|
||||
break;
|
||||
this.$ = $$[$0 - 1] + ':' + $$[$0]
|
||||
break
|
||||
case 19:
|
||||
this.$ = $$[$0-1]+ ":" + yy.count; yy.count = 0
|
||||
break;
|
||||
this.$ = $$[$0 - 1] + ':' + yy.count; yy.count = 0
|
||||
break
|
||||
case 20:
|
||||
yy.count = 0
|
||||
break;
|
||||
break
|
||||
case 21:
|
||||
yy.count += 1
|
||||
break;
|
||||
break
|
||||
}
|
||||
},
|
||||
table: [{3: 1, 4: [1, 2]}, {1: [3]}, {5: [1, 3], 8: [1, 4]}, {6: 5, 7: $V0, 9: 6, 12: $V1}, {5: [1, 8]}, {7: [1, 9]}, o($V2, [2, 7], {10: 10, 11: [1, 11]}), o($V3, [2, 6]), {6: 12, 7: $V0, 9: 6, 12: $V1}, {1: [2, 1]}, {7: [2, 4], 12: [1, 15], 13: 13, 14: 14, 15: [1, 16], 17: [1, 17], 19: [1, 18], 20: [1, 19], 21: [1, 20]}, o($V3, [2, 5]), {7: [1, 21]}, o($V2, [2, 8]), {12: [1, 22]}, o($V2, [2, 10]), {12: [2, 16], 16: 23, 23: [1, 24]}, {18: [1, 25]}, {18: [1, 26]}, {18: [1, 27]}, {18: [1, 30], 22: 28, 24: [1, 29]}, {1: [2, 2]}, o($V2, [2, 9]), {12: [2, 11]}, {12: [2, 17]}, {12: [2, 12]}, {12: [2, 13]}, {12: [2, 14]}, {12: [2, 15]}, {12: $V4, 25: 31, 26: $V5}, {12: $V4, 25: 33, 26: $V5}, {12: [2, 18]}, {12: $V4, 25: 34, 26: $V5}, {12: [2, 19]}, {12: [2, 21]}],
|
||||
defaultActions: {9: [2, 1], 21: [2, 2], 23: [2, 11], 24: [2, 17], 25: [2, 12], 26: [2, 13], 27: [2, 14], 28: [2, 15], 31: [2, 18], 33: [2, 19], 34: [2, 21]},
|
||||
parseError: function parseError (str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
this.trace(str)
|
||||
} else {
|
||||
function _parseError (msg, hash) {
|
||||
this.message = msg;
|
||||
this.hash = hash;
|
||||
this.message = msg
|
||||
this.hash = hash
|
||||
}
|
||||
_parseError.prototype = Error;
|
||||
_parseError.prototype = Error
|
||||
|
||||
throw new _parseError(str, hash);
|
||||
throw new _parseError(str, hash)
|
||||
}
|
||||
},
|
||||
parse: function parse (input) {
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1
|
||||
var args = lstack.slice.call(arguments, 1)
|
||||
var lexer = Object.create(this.lexer)
|
||||
var sharedState = { yy: {} }
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
sharedState.yy[k] = this.yy[k]
|
||||
}
|
||||
}
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
lexer.setInput(input, sharedState.yy)
|
||||
sharedState.yy.lexer = lexer
|
||||
sharedState.yy.parser = this
|
||||
if (typeof lexer.yylloc === 'undefined') {
|
||||
lexer.yylloc = {}
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
var yyloc = lexer.yylloc
|
||||
lstack.push(yyloc)
|
||||
var ranges = lexer.options && lexer.options.ranges
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
this.parseError = sharedState.yy.parseError
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
this.parseError = Object.getPrototypeOf(this).parseError
|
||||
}
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
stack.length = stack.length - 2 * n
|
||||
vstack.length = vstack.length - n
|
||||
lstack.length = lstack.length - n
|
||||
}
|
||||
_token_stack:
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
var token
|
||||
token = lexer.lex() || EOF
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
token = self.symbols_[token] || token
|
||||
}
|
||||
return token;
|
||||
};
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
return token
|
||||
}
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected
|
||||
while (true) {
|
||||
state = stack[stack.length - 1];
|
||||
state = stack[stack.length - 1]
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
action = this.defaultActions[state]
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
if (symbol === null || typeof symbol === 'undefined') {
|
||||
symbol = lex()
|
||||
}
|
||||
action = table[state] && table[state][symbol];
|
||||
action = table[state] && table[state][symbol]
|
||||
}
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var errStr = '';
|
||||
expected = [];
|
||||
var errStr = ''
|
||||
expected = []
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push('\'' + this.terminals_[p] + '\'');
|
||||
expected.push('\'' + this.terminals_[p] + '\'')
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''
|
||||
} else {
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'')
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
@@ -222,45 +220,45 @@ parse: function parse(input) {
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected
|
||||
});
|
||||
})
|
||||
}
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol)
|
||||
}
|
||||
switch (action[0]) {
|
||||
case 1:
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]);
|
||||
symbol = null;
|
||||
stack.push(symbol)
|
||||
vstack.push(lexer.yytext)
|
||||
lstack.push(lexer.yylloc)
|
||||
stack.push(action[1])
|
||||
symbol = null
|
||||
if (!preErrorSymbol) {
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
yyleng = lexer.yyleng
|
||||
yytext = lexer.yytext
|
||||
yylineno = lexer.yylineno
|
||||
yyloc = lexer.yylloc
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
recovering--
|
||||
}
|
||||
} else {
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
symbol = preErrorSymbol
|
||||
preErrorSymbol = null
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 2:
|
||||
len = this.productions_[action[1]][1];
|
||||
yyval.$ = vstack[vstack.length - len];
|
||||
len = this.productions_[action[1]][1]
|
||||
yyval.$ = vstack[vstack.length - len]
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||||
last_line: lstack[lstack.length - 1].last_line,
|
||||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||||
last_column: lstack[lstack.length - 1].last_column
|
||||
};
|
||||
}
|
||||
if (ranges) {
|
||||
yyval._$.range = [
|
||||
lstack[lstack.length - (len || 1)].range[0],
|
||||
lstack[lstack.length - 1].range[1]
|
||||
];
|
||||
]
|
||||
}
|
||||
r = this.performAction.apply(yyval, [
|
||||
yytext,
|
||||
@@ -270,27 +268,27 @@ parse: function parse(input) {
|
||||
action[1],
|
||||
vstack,
|
||||
lstack
|
||||
].concat(args));
|
||||
].concat(args))
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
return r
|
||||
}
|
||||
if (len) {
|
||||
stack = stack.slice(0, -1 * len * 2);
|
||||
vstack = vstack.slice(0, -1 * len);
|
||||
lstack = lstack.slice(0, -1 * len);
|
||||
stack = stack.slice(0, -1 * len * 2)
|
||||
vstack = vstack.slice(0, -1 * len)
|
||||
lstack = lstack.slice(0, -1 * len)
|
||||
}
|
||||
stack.push(this.productions_[action[1]][0]);
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
stack.push(this.productions_[action[1]][0])
|
||||
vstack.push(yyval.$)
|
||||
lstack.push(yyval._$)
|
||||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]]
|
||||
stack.push(newState)
|
||||
break
|
||||
case 3:
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}};
|
||||
return true
|
||||
}}
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function () {
|
||||
var lexer = ({
|
||||
@@ -299,144 +297,143 @@ EOF:1,
|
||||
|
||||
parseError: function parseError (str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
this.yy.parser.parseError(str, hash)
|
||||
} else {
|
||||
throw new Error(str);
|
||||
throw new Error(str)
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput: function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yy = yy || this.yy || {}
|
||||
this._input = input
|
||||
this._more = this._backtrack = this.done = false
|
||||
this.yylineno = this.yyleng = 0
|
||||
this.yytext = this.matched = this.match = ''
|
||||
this.conditionStack = ['INITIAL']
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0, 0]
|
||||
}
|
||||
this.offset = 0
|
||||
return this
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input: function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
var ch = this._input[0]
|
||||
this.yytext += ch
|
||||
this.yyleng++
|
||||
this.offset++
|
||||
this.match += ch
|
||||
this.matched += ch
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
this.yylineno++
|
||||
this.yylloc.last_line++
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
this.yylloc.last_column++
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
this.yylloc.range[1]++
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
this._input = this._input.slice(1)
|
||||
return ch
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput: function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
var len = ch.length
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g)
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
this._input = ch + this._input
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len)
|
||||
// this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
this.offset -= len
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g)
|
||||
this.match = this.match.substr(0, this.match.length - 1)
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1)
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
this.yylineno -= lines.length - 1
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
var r = this.yylloc.range
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
last_column: lines
|
||||
? (lines.length === oldLines.length ? this.yylloc.first_column : 0) +
|
||||
oldLines[oldLines.length - lines.length].length - lines[0].length
|
||||
: this.yylloc.first_column - len
|
||||
}
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len]
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
this.yyleng = this.yytext.length
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more: function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
this._more = true
|
||||
return this
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject: function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
this._backtrack = true
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
return this;
|
||||
return this
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less: function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
this.unput(this.match.slice(n))
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput: function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length)
|
||||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput: function () {
|
||||
var next = this.match;
|
||||
var next = this.match
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
next += this._input.substr(0, 20 - next.length)
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, '')
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition: function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
var pre = this.pastInput()
|
||||
var c = new Array(pre.length + 1).join('-')
|
||||
return pre + this.upcomingInput() + '\n' + c + '^'
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match: function (match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
backup
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
@@ -459,239 +456,238 @@ test_match:function (match, indexed_rule) {
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
backup.yylloc.range = this.yylloc.range.slice(0)
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g)
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
this.yylineno += lines.length
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
last_column: lines
|
||||
? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length
|
||||
: this.yylloc.last_column + match[0].length
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
this.yytext += match[0]
|
||||
this.match += match[0]
|
||||
this.matches = match
|
||||
this.yyleng = this.yytext.length
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng]
|
||||
}
|
||||
this._more = false
|
||||
this._backtrack = false
|
||||
this._input = this._input.slice(match[0].length)
|
||||
this.matched += match[0]
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1])
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
this.done = false
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
this[k] = backup[k]
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
return false // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next: function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
return this.EOF
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
this.done = true
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
index
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
this.yytext = ''
|
||||
this.match = ''
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
var rules = this._currentRules()
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
tempMatch = this._input.match(this.rules[rules[i]])
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
match = tempMatch
|
||||
index = i
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
token = this.test_match(tempMatch, rules[i])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
match = false
|
||||
continue // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
token = this.test_match(match, rules[index])
|
||||
if (token !== false) {
|
||||
return token;
|
||||
return token
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
if (this._input === '') {
|
||||
return this.EOF
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
text: '',
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex: function lex () {
|
||||
var r = this.next();
|
||||
var r = this.next()
|
||||
if (r) {
|
||||
return r;
|
||||
return r
|
||||
} else {
|
||||
return this.lex();
|
||||
return this.lex()
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin: function begin (condition) {
|
||||
this.conditionStack.push(condition);
|
||||
this.conditionStack.push(condition)
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState: function popState () {
|
||||
var n = this.conditionStack.length - 1;
|
||||
var n = this.conditionStack.length - 1
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
return this.conditionStack.pop()
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
return this.conditionStack[0]
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules: function _currentRules () {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
return this.conditions['INITIAL'].rules
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState: function topState (n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0)
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
return this.conditionStack[n]
|
||||
} else {
|
||||
return "INITIAL";
|
||||
return 'INITIAL'
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState: function pushState (condition) {
|
||||
this.begin(condition);
|
||||
this.begin(condition)
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize: function stateStackSize () {
|
||||
return this.conditionStack.length;
|
||||
return this.conditionStack.length
|
||||
},
|
||||
options: {"case-insensitive":true},
|
||||
options: {'case-insensitive': true},
|
||||
performAction: function anonymous (yy, yy_, $avoiding_name_collisions, YY_START) {
|
||||
var YYSTATE=YY_START;
|
||||
var YYSTATE = YY_START
|
||||
switch ($avoiding_name_collisions) {
|
||||
case 0:return 12;
|
||||
break;
|
||||
case 0:return 12
|
||||
break
|
||||
case 1:/* skip all whitespace */
|
||||
break;
|
||||
break
|
||||
case 2:/* skip comments */
|
||||
break;
|
||||
break
|
||||
case 3:/* skip comments */
|
||||
break;
|
||||
case 4:return 4;
|
||||
break;
|
||||
case 5:return 15;
|
||||
break;
|
||||
case 6:return 17;
|
||||
break;
|
||||
case 7:return 20;
|
||||
break;
|
||||
case 8:return 21;
|
||||
break;
|
||||
case 9:return 19;
|
||||
break;
|
||||
case 10:return 8;
|
||||
break;
|
||||
case 11:return 8;
|
||||
break;
|
||||
case 12:return 5;
|
||||
break;
|
||||
break
|
||||
case 4:return 4
|
||||
break
|
||||
case 5:return 15
|
||||
break
|
||||
case 6:return 17
|
||||
break
|
||||
case 7:return 20
|
||||
break
|
||||
case 8:return 21
|
||||
break
|
||||
case 9:return 19
|
||||
break
|
||||
case 10:return 8
|
||||
break
|
||||
case 11:return 8
|
||||
break
|
||||
case 12:return 5
|
||||
break
|
||||
case 13:return 26
|
||||
break;
|
||||
case 14:this.begin("options");
|
||||
break;
|
||||
case 15:this.popState();
|
||||
break;
|
||||
case 16:return 11;
|
||||
break;
|
||||
case 17:this.begin("string");
|
||||
break;
|
||||
case 18:this.popState();
|
||||
break;
|
||||
case 19:return 23;
|
||||
break;
|
||||
case 20:return 18;
|
||||
break;
|
||||
case 21:return 7;
|
||||
break;
|
||||
break
|
||||
case 14:this.begin('options')
|
||||
break
|
||||
case 15:this.popState()
|
||||
break
|
||||
case 16:return 11
|
||||
break
|
||||
case 17:this.begin('string')
|
||||
break
|
||||
case 18:this.popState()
|
||||
break
|
||||
case 19:return 23
|
||||
break
|
||||
case 20:return 18
|
||||
break
|
||||
case 21:return 7
|
||||
break
|
||||
}
|
||||
},
|
||||
rules: [/^(?:(\r?\n)+)/i, /^(?:\s+)/i, /^(?:#[^\n]*)/i, /^(?:%[^\n]*)/i, /^(?:gitGraph\b)/i, /^(?:commit\b)/i, /^(?:branch\b)/i, /^(?:merge\b)/i, /^(?:reset\b)/i, /^(?:checkout\b)/i, /^(?:LR\b)/i, /^(?:BT\b)/i, /^(?::)/i, /^(?:\^)/i, /^(?:options\r?\n)/i, /^(?:end\r?\n)/i, /^(?:[^\n]+\r?\n)/i, /^(?:["])/i, /^(?:["])/i, /^(?:[^"]*)/i, /^(?:[a-zA-Z][a-zA-Z0-9_]+)/i, /^(?:$)/i],
|
||||
conditions: {"options":{"rules":[15,16],"inclusive":false},"string":{"rules":[18,19],"inclusive":false},"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,20,21],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
conditions: {'options': {'rules': [15, 16], 'inclusive': false}, 'string': {'rules': [18, 19], 'inclusive': false}, 'INITIAL': {'rules': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 20, 21], 'inclusive': true}}
|
||||
})
|
||||
return lexer
|
||||
})()
|
||||
parser.lexer = lexer
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
this.yy = {}
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
|
||||
Parser.prototype = parser; parser.Parser = Parser
|
||||
return new Parser()
|
||||
})()
|
||||
|
||||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||||
exports.parser = parser;
|
||||
exports.Parser = parser.Parser;
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments); };
|
||||
exports.parser = parser
|
||||
exports.Parser = parser.Parser
|
||||
exports.parse = function () { return parser.parse.apply(parser, arguments) }
|
||||
exports.main = function commonjsMain (args) {
|
||||
if (!args[1]) {
|
||||
console.log('Usage: '+args[0]+' FILE');
|
||||
process.exit(1);
|
||||
console.log('Usage: ' + args[0] + ' FILE')
|
||||
process.exit(1)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), 'utf8')
|
||||
return exports.parser.parse(source)
|
||||
}
|
||||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||||
return exports.parser.parse(source);
|
||||
};
|
||||
if (typeof module !== 'undefined' && require.main === module) {
|
||||
exports.main(process.argv.slice(1));
|
||||
exports.main(process.argv.slice(1))
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,59 +1,57 @@
|
||||
/**
|
||||
* Created by knut on 14-11-19.
|
||||
*/
|
||||
var actors = {};
|
||||
var messages = [];
|
||||
var notes = [];
|
||||
var title = '';
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
|
||||
|
||||
var actors = {}
|
||||
var messages = []
|
||||
var notes = []
|
||||
var title = ''
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
|
||||
exports.addActor = function (id, name, description) {
|
||||
// Don't allow description nulling
|
||||
var old = actors[id];
|
||||
if ( old && name === old.name && description == null ) return;
|
||||
var old = actors[id]
|
||||
if (old && name === old.name && description == null) return
|
||||
|
||||
// Don't allow null descriptions, either
|
||||
if ( description == null ) description = name;
|
||||
if (description == null) description = name
|
||||
|
||||
actors[id] = {name:name, description:description};
|
||||
};
|
||||
actors[id] = {name: name, description: description}
|
||||
}
|
||||
|
||||
exports.addMessage = function (idFrom, idTo, message, answer) {
|
||||
messages.push({from:idFrom, to:idTo, message:message, answer:answer});
|
||||
};
|
||||
messages.push({from: idFrom, to: idTo, message: message, answer: answer})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
exports.addSignal = function (idFrom, idTo, message, messageType) {
|
||||
log.debug('Adding message from='+idFrom+' to='+idTo+' message='+message+' type='+messageType);
|
||||
messages.push({from:idFrom, to:idTo, message:message, type:messageType});
|
||||
};
|
||||
log.debug('Adding message from=' + idFrom + ' to=' + idTo + ' message=' + message + ' type=' + messageType)
|
||||
messages.push({from: idFrom, to: idTo, message: message, type: messageType})
|
||||
}
|
||||
|
||||
exports.getMessages = function () {
|
||||
return messages;
|
||||
};
|
||||
return messages
|
||||
}
|
||||
|
||||
exports.getActors = function () {
|
||||
return actors;
|
||||
};
|
||||
return actors
|
||||
}
|
||||
exports.getActor = function (id) {
|
||||
return actors[id];
|
||||
};
|
||||
return actors[id]
|
||||
}
|
||||
exports.getActorKeys = function () {
|
||||
return Object.keys(actors);
|
||||
};
|
||||
return Object.keys(actors)
|
||||
}
|
||||
exports.getTitle = function () {
|
||||
return title;
|
||||
return title
|
||||
}
|
||||
|
||||
exports.clear = function () {
|
||||
actors = {};
|
||||
messages = [];
|
||||
};
|
||||
actors = {}
|
||||
messages = []
|
||||
}
|
||||
|
||||
exports.LINETYPE = {
|
||||
SOLID: 0,
|
||||
@@ -75,100 +73,99 @@ exports.LINETYPE = {
|
||||
PAR_START: 19,
|
||||
PAR_AND: 20,
|
||||
PAR_END: 21
|
||||
};
|
||||
}
|
||||
|
||||
exports.ARROWTYPE = {
|
||||
FILLED: 0,
|
||||
OPEN: 1
|
||||
};
|
||||
}
|
||||
|
||||
exports.PLACEMENT = {
|
||||
LEFTOF: 0,
|
||||
RIGHTOF: 1,
|
||||
OVER: 2
|
||||
};
|
||||
|
||||
exports.addNote = function (actor, placement, message){
|
||||
var note = {actor:actor, placement: placement, message:message};
|
||||
|
||||
// Coerce actor into a [to, from, ...] array
|
||||
var actors = [].concat(actor, actor);
|
||||
|
||||
notes.push(note);
|
||||
messages.push({from:actors[0], to:actors[1], message:message, type:exports.LINETYPE.NOTE, placement: placement});
|
||||
};
|
||||
|
||||
exports.setTitle = function(titleText){
|
||||
title = titleText;
|
||||
}
|
||||
|
||||
exports.addNote = function (actor, placement, message) {
|
||||
var note = {actor: actor, placement: placement, message: message}
|
||||
|
||||
// Coerce actor into a [to, from, ...] array
|
||||
var actors = [].concat(actor, actor)
|
||||
|
||||
notes.push(note)
|
||||
messages.push({from: actors[0], to: actors[1], message: message, type: exports.LINETYPE.NOTE, placement: placement})
|
||||
}
|
||||
|
||||
exports.setTitle = function (titleText) {
|
||||
title = titleText
|
||||
}
|
||||
|
||||
exports.parseError = function (err, hash) {
|
||||
global.mermaidAPI.parseError(err,hash);
|
||||
};
|
||||
global.mermaidAPI.parseError(err, hash)
|
||||
}
|
||||
|
||||
exports.apply = function (param) {
|
||||
if (param instanceof Array) {
|
||||
param.forEach(function (item) {
|
||||
exports.apply(item);
|
||||
});
|
||||
exports.apply(item)
|
||||
})
|
||||
} else {
|
||||
// console.info(param);
|
||||
switch (param.type) {
|
||||
case 'addActor':
|
||||
exports.addActor(param.actor, param.actor, param.description);
|
||||
break;
|
||||
exports.addActor(param.actor, param.actor, param.description)
|
||||
break
|
||||
case 'activeStart':
|
||||
exports.addSignal(param.actor, undefined, undefined, param.signalType);
|
||||
break;
|
||||
exports.addSignal(param.actor, undefined, undefined, param.signalType)
|
||||
break
|
||||
case 'activeEnd':
|
||||
exports.addSignal(param.actor, undefined, undefined, param.signalType);
|
||||
break;
|
||||
exports.addSignal(param.actor, undefined, undefined, param.signalType)
|
||||
break
|
||||
case 'addNote':
|
||||
exports.addNote(param.actor,param.placement, param.text);
|
||||
break;
|
||||
exports.addNote(param.actor, param.placement, param.text)
|
||||
break
|
||||
case 'addMessage':
|
||||
exports.addSignal(param.from, param.to, param.msg, param.signalType);
|
||||
break;
|
||||
exports.addSignal(param.from, param.to, param.msg, param.signalType)
|
||||
break
|
||||
case 'loopStart':
|
||||
// log.debug('Loop text: ',param.loopText);
|
||||
exports.addSignal(undefined, undefined, param.loopText, param.signalType);
|
||||
exports.addSignal(undefined, undefined, param.loopText, param.signalType)
|
||||
// yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
|
||||
break;
|
||||
break
|
||||
case 'loopEnd':
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType);
|
||||
break;
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType)
|
||||
break
|
||||
case 'optStart':
|
||||
// log.debug('Loop text: ',param.loopText);
|
||||
exports.addSignal(undefined, undefined, param.optText, param.signalType);
|
||||
exports.addSignal(undefined, undefined, param.optText, param.signalType)
|
||||
// yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
|
||||
break;
|
||||
break
|
||||
case 'optEnd':
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType);
|
||||
break;
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType)
|
||||
break
|
||||
case 'altStart':
|
||||
// log.debug('Loop text: ',param.loopText);
|
||||
exports.addSignal(undefined, undefined, param.altText, param.signalType);
|
||||
exports.addSignal(undefined, undefined, param.altText, param.signalType)
|
||||
// yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
|
||||
break;
|
||||
break
|
||||
case 'else':
|
||||
exports.addSignal(undefined, undefined, param.altText, param.signalType);
|
||||
break;
|
||||
exports.addSignal(undefined, undefined, param.altText, param.signalType)
|
||||
break
|
||||
case 'altEnd':
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType);
|
||||
break;
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType)
|
||||
break
|
||||
case 'setTitle':
|
||||
exports.setTitle(param.text);
|
||||
break;
|
||||
exports.setTitle(param.text)
|
||||
break
|
||||
case 'parStart':
|
||||
exports.addSignal(undefined, undefined, param.parText, param.signalType);
|
||||
break;
|
||||
exports.addSignal(undefined, undefined, param.parText, param.signalType)
|
||||
break
|
||||
case 'and':
|
||||
exports.addSignal(undefined, undefined, param.parText, param.signalType);
|
||||
break;
|
||||
exports.addSignal(undefined, undefined, param.parText, param.signalType)
|
||||
break
|
||||
case 'parEnd':
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType);
|
||||
break;
|
||||
exports.addSignal(undefined, undefined, undefined, param.signalType)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,12 @@
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
|
||||
var sq = require('./parser/sequenceDiagram').parser;
|
||||
sq.yy = require('./sequenceDb');
|
||||
var svgDraw = require('./svgDraw');
|
||||
var d3 = require('../../d3');
|
||||
var Logger = require('../../logger');
|
||||
var log = Logger.Log;
|
||||
var sq = require('./parser/sequenceDiagram').parser
|
||||
sq.yy = require('./sequenceDb')
|
||||
var svgDraw = require('./svgDraw')
|
||||
var d3 = require('../../d3')
|
||||
var Logger = require('../../logger')
|
||||
var log = Logger.Log
|
||||
|
||||
var conf = {
|
||||
|
||||
@@ -35,8 +35,8 @@ var conf = {
|
||||
activationWidth: 10,
|
||||
|
||||
// text placement as: tspan | fo | old only text as before
|
||||
textPlacement: 'tspan',
|
||||
};
|
||||
textPlacement: 'tspan'
|
||||
}
|
||||
|
||||
exports.bounds = {
|
||||
data: {
|
||||
@@ -50,109 +50,112 @@ exports.bounds = {
|
||||
sequenceItems: [],
|
||||
activations: [],
|
||||
init: function () {
|
||||
this.sequenceItems = [];
|
||||
this.activations = [];
|
||||
this.sequenceItems = []
|
||||
this.activations = []
|
||||
this.data = {
|
||||
startx: undefined,
|
||||
stopx: undefined,
|
||||
starty: undefined,
|
||||
stopy: undefined
|
||||
};
|
||||
this.verticalPos =0;
|
||||
}
|
||||
this.verticalPos = 0
|
||||
},
|
||||
updateVal: function (obj, key, val, fun) {
|
||||
if (typeof obj[key] === 'undefined') {
|
||||
obj[key] = val;
|
||||
obj[key] = val
|
||||
} else {
|
||||
obj[key] = fun(val,obj[key]);
|
||||
obj[key] = fun(val, obj[key])
|
||||
}
|
||||
},
|
||||
updateBounds: function (startx, starty, stopx, stopy) {
|
||||
var _self = this;
|
||||
var cnt = 0;
|
||||
function updateFn(type) { return function updateItemBounds(item) {
|
||||
cnt++;
|
||||
var _self = this
|
||||
var cnt = 0
|
||||
function updateFn (type) {
|
||||
return function updateItemBounds (item) {
|
||||
cnt++
|
||||
// The loop sequenceItems is a stack so the biggest margins in the beginning of the sequenceItems
|
||||
var n = _self.sequenceItems.length-cnt+1;
|
||||
var n = _self.sequenceItems.length - cnt + 1
|
||||
|
||||
_self.updateVal(item, 'starty',starty - n*conf.boxMargin, Math.min);
|
||||
_self.updateVal(item, 'stopy' ,stopy + n*conf.boxMargin, Math.max);
|
||||
_self.updateVal(item, 'starty', starty - n * conf.boxMargin, Math.min)
|
||||
_self.updateVal(item, 'stopy', stopy + n * conf.boxMargin, Math.max)
|
||||
|
||||
_self.updateVal(exports.bounds.data, 'startx', startx - n * conf.boxMargin, Math.min);
|
||||
_self.updateVal(exports.bounds.data, 'stopx', stopx + n * conf.boxMargin, Math.max);
|
||||
_self.updateVal(exports.bounds.data, 'startx', startx - n * conf.boxMargin, Math.min)
|
||||
_self.updateVal(exports.bounds.data, 'stopx', stopx + n * conf.boxMargin, Math.max)
|
||||
|
||||
if (!(type == 'activation')) {
|
||||
_self.updateVal(item, 'startx',startx - n*conf.boxMargin, Math.min);
|
||||
_self.updateVal(item, 'stopx' ,stopx + n*conf.boxMargin, Math.max);
|
||||
_self.updateVal(item, 'startx', startx - n * conf.boxMargin, Math.min)
|
||||
_self.updateVal(item, 'stopx', stopx + n * conf.boxMargin, Math.max)
|
||||
|
||||
_self.updateVal(exports.bounds.data, 'starty', starty - n * conf.boxMargin, Math.min);
|
||||
_self.updateVal(exports.bounds.data, 'stopy', stopy + n * conf.boxMargin, Math.max);
|
||||
_self.updateVal(exports.bounds.data, 'starty', starty - n * conf.boxMargin, Math.min)
|
||||
_self.updateVal(exports.bounds.data, 'stopy', stopy + n * conf.boxMargin, Math.max)
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
this.sequenceItems.forEach(updateFn());
|
||||
this.activations.forEach(updateFn('activation'));
|
||||
this.sequenceItems.forEach(updateFn())
|
||||
this.activations.forEach(updateFn('activation'))
|
||||
},
|
||||
insert: function (startx, starty, stopx, stopy) {
|
||||
var _startx, _starty, _stopx, _stopy
|
||||
|
||||
var _startx, _starty, _stopx, _stopy;
|
||||
_startx = Math.min(startx, stopx)
|
||||
_stopx = Math.max(startx, stopx)
|
||||
_starty = Math.min(starty, stopy)
|
||||
_stopy = Math.max(starty, stopy)
|
||||
|
||||
_startx = Math.min(startx,stopx);
|
||||
_stopx = Math.max(startx,stopx);
|
||||
_starty = Math.min(starty,stopy);
|
||||
_stopy = Math.max(starty,stopy);
|
||||
|
||||
this.updateVal(exports.bounds.data,'startx',_startx,Math.min);
|
||||
this.updateVal(exports.bounds.data,'starty',_starty,Math.min);
|
||||
this.updateVal(exports.bounds.data,'stopx' ,_stopx ,Math.max);
|
||||
this.updateVal(exports.bounds.data,'stopy' ,_stopy ,Math.max);
|
||||
|
||||
this.updateBounds(_startx,_starty,_stopx,_stopy);
|
||||
this.updateVal(exports.bounds.data, 'startx', _startx, Math.min)
|
||||
this.updateVal(exports.bounds.data, 'starty', _starty, Math.min)
|
||||
this.updateVal(exports.bounds.data, 'stopx', _stopx, Math.max)
|
||||
this.updateVal(exports.bounds.data, 'stopy', _stopy, Math.max)
|
||||
|
||||
this.updateBounds(_startx, _starty, _stopx, _stopy)
|
||||
},
|
||||
newActivation: function (message, diagram) {
|
||||
var actorRect = sq.yy.getActors()[message.from.actor];
|
||||
var stackedSize = actorActivations(message.from.actor).length;
|
||||
var x = actorRect.x + conf.width/2 + (stackedSize-1)*conf.activationWidth/2;
|
||||
this.activations.push({startx:x,starty:this.verticalPos+2,stopx:x+conf.activationWidth,stopy:undefined,
|
||||
var actorRect = sq.yy.getActors()[message.from.actor]
|
||||
var stackedSize = actorActivations(message.from.actor).length
|
||||
var x = actorRect.x + conf.width / 2 + (stackedSize - 1) * conf.activationWidth / 2
|
||||
this.activations.push({startx: x,
|
||||
starty: this.verticalPos + 2,
|
||||
stopx: x + conf.activationWidth,
|
||||
stopy: undefined,
|
||||
actor: message.from.actor,
|
||||
anchored: svgDraw.anchorElement(diagram)
|
||||
});
|
||||
})
|
||||
},
|
||||
endActivation: function (message) {
|
||||
// find most recent activation for given actor
|
||||
var lastActorActivationIdx = this.activations
|
||||
.map(function (activation) { return activation.actor })
|
||||
.lastIndexOf(message.from.actor);
|
||||
var activation = this.activations.splice(lastActorActivationIdx, 1)[0];
|
||||
return activation;
|
||||
.lastIndexOf(message.from.actor)
|
||||
var activation = this.activations.splice(lastActorActivationIdx, 1)[0]
|
||||
return activation
|
||||
},
|
||||
newLoop: function (title) {
|
||||
this.sequenceItems.push({startx:undefined,starty:this.verticalPos,stopx:undefined,stopy:undefined, title:title});
|
||||
this.sequenceItems.push({startx: undefined, starty: this.verticalPos, stopx: undefined, stopy: undefined, title: title})
|
||||
},
|
||||
endLoop: function () {
|
||||
var loop = this.sequenceItems.pop();
|
||||
return loop;
|
||||
var loop = this.sequenceItems.pop()
|
||||
return loop
|
||||
},
|
||||
addSectionToLoop: function (message) {
|
||||
var loop = this.sequenceItems.pop();
|
||||
loop.sections = loop.sections || [];
|
||||
loop.sectionTitles = loop.sectionTitles || [];
|
||||
loop.sections.push(exports.bounds.getVerticalPos());
|
||||
loop.sectionTitles.push(message);
|
||||
this.sequenceItems.push(loop);
|
||||
var loop = this.sequenceItems.pop()
|
||||
loop.sections = loop.sections || []
|
||||
loop.sectionTitles = loop.sectionTitles || []
|
||||
loop.sections.push(exports.bounds.getVerticalPos())
|
||||
loop.sectionTitles.push(message)
|
||||
this.sequenceItems.push(loop)
|
||||
},
|
||||
bumpVerticalPos: function (bump) {
|
||||
this.verticalPos = this.verticalPos + bump;
|
||||
this.data.stopy = this.verticalPos;
|
||||
this.verticalPos = this.verticalPos + bump
|
||||
this.data.stopy = this.verticalPos
|
||||
},
|
||||
getVerticalPos: function () {
|
||||
return this.verticalPos;
|
||||
return this.verticalPos
|
||||
},
|
||||
getBounds: function () {
|
||||
return this.data;
|
||||
return this.data
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws an actor in the diagram with the attaced line
|
||||
@@ -161,42 +164,41 @@ exports.bounds = {
|
||||
* @param description The text in the box
|
||||
*/
|
||||
var drawNote = function (elem, startx, verticalPos, msg, forceWidth) {
|
||||
var rect = svgDraw.getNoteRect();
|
||||
rect.x = startx;
|
||||
rect.y = verticalPos;
|
||||
rect.width = forceWidth || conf.width;
|
||||
rect.class = 'note';
|
||||
var rect = svgDraw.getNoteRect()
|
||||
rect.x = startx
|
||||
rect.y = verticalPos
|
||||
rect.width = forceWidth || conf.width
|
||||
rect.class = 'note'
|
||||
|
||||
var g = elem.append('g');
|
||||
var rectElem = svgDraw.drawRect(g, rect);
|
||||
var g = elem.append('g')
|
||||
var rectElem = svgDraw.drawRect(g, rect)
|
||||
|
||||
var textObj = svgDraw.getTextObj();
|
||||
textObj.x = startx-4;
|
||||
textObj.y = verticalPos-13;
|
||||
textObj.textMargin = conf.noteMargin;
|
||||
textObj.dy = '1em';
|
||||
textObj.text = msg.message;
|
||||
textObj.class = 'noteText';
|
||||
var textObj = svgDraw.getTextObj()
|
||||
textObj.x = startx - 4
|
||||
textObj.y = verticalPos - 13
|
||||
textObj.textMargin = conf.noteMargin
|
||||
textObj.dy = '1em'
|
||||
textObj.text = msg.message
|
||||
textObj.class = 'noteText'
|
||||
|
||||
var textElem = svgDraw.drawText(g,textObj, rect.width-conf.noteMargin);
|
||||
var textElem = svgDraw.drawText(g, textObj, rect.width - conf.noteMargin)
|
||||
|
||||
var textHeight = textElem[0][0].getBBox().height;
|
||||
var textHeight = textElem[0][0].getBBox().height
|
||||
if (!forceWidth && textHeight > conf.width) {
|
||||
textElem.remove();
|
||||
g = elem.append('g');
|
||||
textElem.remove()
|
||||
g = elem.append('g')
|
||||
|
||||
textElem = svgDraw.drawText(g,textObj, 2*rect.width-conf.noteMargin);
|
||||
textHeight = textElem[0][0].getBBox().height;
|
||||
rectElem.attr('width',2*rect.width);
|
||||
exports.bounds.insert(startx, verticalPos, startx + 2*rect.width, verticalPos + 2*conf.noteMargin + textHeight);
|
||||
textElem = svgDraw.drawText(g, textObj, 2 * rect.width - conf.noteMargin)
|
||||
textHeight = textElem[0][0].getBBox().height
|
||||
rectElem.attr('width', 2 * rect.width)
|
||||
exports.bounds.insert(startx, verticalPos, startx + 2 * rect.width, verticalPos + 2 * conf.noteMargin + textHeight)
|
||||
} else {
|
||||
exports.bounds.insert(startx, verticalPos, startx + rect.width, verticalPos + 2*conf.noteMargin + textHeight);
|
||||
exports.bounds.insert(startx, verticalPos, startx + rect.width, verticalPos + 2 * conf.noteMargin + textHeight)
|
||||
}
|
||||
|
||||
rectElem.attr('height',textHeight+ 2*conf.noteMargin);
|
||||
exports.bounds.bumpVerticalPos(textHeight+ 2*conf.noteMargin);
|
||||
};
|
||||
|
||||
rectElem.attr('height', textHeight + 2 * conf.noteMargin)
|
||||
exports.bounds.bumpVerticalPos(textHeight + 2 * conf.noteMargin)
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a message
|
||||
@@ -208,123 +210,117 @@ var drawNote = function(elem, startx, verticalPos, msg, forceWidth){
|
||||
* @param msg
|
||||
*/
|
||||
var drawMessage = function (elem, startx, stopx, verticalPos, msg) {
|
||||
var g = elem.append('g');
|
||||
var txtCenter = startx + (stopx-startx)/2;
|
||||
var g = elem.append('g')
|
||||
var txtCenter = startx + (stopx - startx) / 2
|
||||
|
||||
var textElem = g.append('text') // text label for the x axis
|
||||
.attr('x', txtCenter)
|
||||
.attr('y', verticalPos - 7)
|
||||
.style('text-anchor', 'middle')
|
||||
.attr('class', 'messageText')
|
||||
.text(msg.message);
|
||||
.text(msg.message)
|
||||
|
||||
var textWidth;
|
||||
var textWidth
|
||||
|
||||
if (typeof textElem[0][0].getBBox !== 'undefined') {
|
||||
textWidth = textElem[0][0].getBBox().width;
|
||||
}
|
||||
else{
|
||||
textWidth = textElem[0][0].getBBox().width
|
||||
} else {
|
||||
// textWidth = getBBox(textElem).width; //.getComputedTextLength()
|
||||
textWidth = textElem[0][0].getBoundingClientRect();
|
||||
textWidth = textElem[0][0].getBoundingClientRect()
|
||||
// textWidth = textElem[0][0].getComputedTextLength();
|
||||
}
|
||||
|
||||
var line;
|
||||
var line
|
||||
|
||||
if (startx === stopx) {
|
||||
line = g.append('path')
|
||||
.attr('d', 'M ' + startx + ',' + verticalPos + ' C ' + (startx + 60) + ',' + (verticalPos - 10) + ' ' + (startx + 60) + ',' +
|
||||
(verticalPos+30)+' ' +startx+ ','+(verticalPos+20));
|
||||
(verticalPos + 30) + ' ' + startx + ',' + (verticalPos + 20))
|
||||
|
||||
exports.bounds.bumpVerticalPos(30);
|
||||
var dx = Math.max(textWidth/2,100);
|
||||
exports.bounds.insert(startx-dx, exports.bounds.getVerticalPos() -10, stopx+dx, exports.bounds.getVerticalPos());
|
||||
exports.bounds.bumpVerticalPos(30)
|
||||
var dx = Math.max(textWidth / 2, 100)
|
||||
exports.bounds.insert(startx - dx, exports.bounds.getVerticalPos() - 10, stopx + dx, exports.bounds.getVerticalPos())
|
||||
} else {
|
||||
line = g.append('line');
|
||||
line.attr('x1', startx);
|
||||
line.attr('y1', verticalPos);
|
||||
line.attr('x2', stopx);
|
||||
line.attr('y2', verticalPos);
|
||||
exports.bounds.insert(startx, exports.bounds.getVerticalPos() -10, stopx, exports.bounds.getVerticalPos());
|
||||
line = g.append('line')
|
||||
line.attr('x1', startx)
|
||||
line.attr('y1', verticalPos)
|
||||
line.attr('x2', stopx)
|
||||
line.attr('y2', verticalPos)
|
||||
exports.bounds.insert(startx, exports.bounds.getVerticalPos() - 10, stopx, exports.bounds.getVerticalPos())
|
||||
}
|
||||
// Make an SVG Container
|
||||
// Draw the line
|
||||
if (msg.type === sq.yy.LINETYPE.DOTTED || msg.type === sq.yy.LINETYPE.DOTTED_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_OPEN) {
|
||||
line.style('stroke-dasharray', ('3, 3'));
|
||||
line.attr('class', 'messageLine1');
|
||||
}
|
||||
else {
|
||||
line.attr('class', 'messageLine0');
|
||||
line.style('stroke-dasharray', ('3, 3'))
|
||||
line.attr('class', 'messageLine1')
|
||||
} else {
|
||||
line.attr('class', 'messageLine0')
|
||||
}
|
||||
|
||||
var url = '';
|
||||
var url = ''
|
||||
if (conf.arrowMarkerAbsolute) {
|
||||
url = window.location.protocol+'//'+window.location.host+window.location.pathname +window.location.search;
|
||||
url = url.replace(/\(/g,'\\(');
|
||||
url = url.replace(/\)/g,'\\)');
|
||||
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search
|
||||
url = url.replace(/\(/g, '\\(')
|
||||
url = url.replace(/\)/g, '\\)')
|
||||
}
|
||||
|
||||
line.attr('stroke-width', 2);
|
||||
line.attr('stroke', 'black');
|
||||
line.style('fill', 'none'); // remove any fill colour
|
||||
line.attr('stroke-width', 2)
|
||||
line.attr('stroke', 'black')
|
||||
line.style('fill', 'none') // remove any fill colour
|
||||
if (msg.type === sq.yy.LINETYPE.SOLID || msg.type === sq.yy.LINETYPE.DOTTED) {
|
||||
line.attr('marker-end', 'url(' + url + '#arrowhead)');
|
||||
line.attr('marker-end', 'url(' + url + '#arrowhead)')
|
||||
}
|
||||
|
||||
if (msg.type === sq.yy.LINETYPE.SOLID_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_CROSS) {
|
||||
line.attr('marker-end', 'url(' + url + '#crosshead)');
|
||||
line.attr('marker-end', 'url(' + url + '#crosshead)')
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
module.exports.drawActors = function (diagram, actors, actorKeys, verticalPos) {
|
||||
var i;
|
||||
var i
|
||||
// Draw the actors
|
||||
for (i = 0; i < actorKeys.length; i++) {
|
||||
var key = actorKeys[i];
|
||||
var key = actorKeys[i]
|
||||
|
||||
// Add some rendering data to the object
|
||||
actors[key].x = i*conf.actorMargin +i*conf.width;
|
||||
actors[key].y = verticalPos;
|
||||
actors[key].width = conf.diagramMarginX;
|
||||
actors[key].height = conf.diagramMarginY;
|
||||
actors[key].x = i * conf.actorMargin + i * conf.width
|
||||
actors[key].y = verticalPos
|
||||
actors[key].width = conf.diagramMarginX
|
||||
actors[key].height = conf.diagramMarginY
|
||||
|
||||
// Draw the box with the attached line
|
||||
svgDraw.drawActor(diagram, actors[key].x, verticalPos, actors[key].description, conf);
|
||||
exports.bounds.insert(actors[key].x, verticalPos, actors[key].x + conf.width, conf.height);
|
||||
|
||||
svgDraw.drawActor(diagram, actors[key].x, verticalPos, actors[key].description, conf)
|
||||
exports.bounds.insert(actors[key].x, verticalPos, actors[key].x + conf.width, conf.height)
|
||||
}
|
||||
|
||||
// Add a margin between the actor boxes and the first arrow
|
||||
// exports.bounds.bumpVerticalPos(conf.height+conf.messageMargin);
|
||||
exports.bounds.bumpVerticalPos(conf.height);
|
||||
};
|
||||
|
||||
exports.bounds.bumpVerticalPos(conf.height)
|
||||
}
|
||||
|
||||
module.exports.setConf = function (cnf) {
|
||||
var keys = Object.keys(cnf);
|
||||
var keys = Object.keys(cnf)
|
||||
|
||||
keys.forEach(function (key) {
|
||||
conf[key] = cnf[key];
|
||||
});
|
||||
};
|
||||
conf[key] = cnf[key]
|
||||
})
|
||||
}
|
||||
|
||||
var actorActivations = function (actor) {
|
||||
return module.exports.bounds.activations.filter(function (activation) {
|
||||
return activation.actor == actor;
|
||||
});
|
||||
};
|
||||
return activation.actor == actor
|
||||
})
|
||||
}
|
||||
|
||||
var actorFlowVerticaBounds = function (actor) {
|
||||
// handle multiple stacked activations for same actor
|
||||
var actors = sq.yy.getActors();
|
||||
var activations = actorActivations(actor);
|
||||
var actors = sq.yy.getActors()
|
||||
var activations = actorActivations(actor)
|
||||
|
||||
var left = activations.reduce(function(acc,activation) { return Math.min(acc,activation.startx)}, actors[actor].x + conf.width/2);
|
||||
var right = activations.reduce(function(acc,activation) { return Math.max(acc,activation.stopx)}, actors[actor].x + conf.width/2);
|
||||
return [left,right];
|
||||
};
|
||||
var left = activations.reduce(function (acc, activation) { return Math.min(acc, activation.startx) }, actors[actor].x + conf.width / 2)
|
||||
var right = activations.reduce(function (acc, activation) { return Math.max(acc, activation.stopx) }, actors[actor].x + conf.width / 2)
|
||||
return [left, right]
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||||
@@ -332,184 +328,181 @@ var actorFlowVerticaBounds = function(actor) {
|
||||
* @param id
|
||||
*/
|
||||
module.exports.draw = function (text, id) {
|
||||
sq.yy.clear();
|
||||
sq.parse(text+'\n');
|
||||
sq.yy.clear()
|
||||
sq.parse(text + '\n')
|
||||
|
||||
exports.bounds.init();
|
||||
var diagram = d3.select('#'+id);
|
||||
exports.bounds.init()
|
||||
var diagram = d3.select('#' + id)
|
||||
|
||||
var startx;
|
||||
var stopx;
|
||||
var forceWidth;
|
||||
var startx
|
||||
var stopx
|
||||
var forceWidth
|
||||
|
||||
// Fetch data from the parsing
|
||||
var actors = sq.yy.getActors();
|
||||
var actorKeys = sq.yy.getActorKeys();
|
||||
var messages = sq.yy.getMessages();
|
||||
var title = sq.yy.getTitle();
|
||||
module.exports.drawActors(diagram, actors, actorKeys, 0);
|
||||
var actors = sq.yy.getActors()
|
||||
var actorKeys = sq.yy.getActorKeys()
|
||||
var messages = sq.yy.getMessages()
|
||||
var title = sq.yy.getTitle()
|
||||
module.exports.drawActors(diagram, actors, actorKeys, 0)
|
||||
|
||||
// The arrow head definition is attached to the svg once
|
||||
svgDraw.insertArrowHead(diagram);
|
||||
svgDraw.insertArrowCrossHead(diagram);
|
||||
svgDraw.insertArrowHead(diagram)
|
||||
svgDraw.insertArrowCrossHead(diagram)
|
||||
|
||||
function activeEnd (msg, verticalPos) {
|
||||
var activationData = exports.bounds.endActivation(msg);
|
||||
var activationData = exports.bounds.endActivation(msg)
|
||||
if (activationData.starty + 18 > verticalPos) {
|
||||
activationData.starty = verticalPos - 6;
|
||||
verticalPos += 12;
|
||||
activationData.starty = verticalPos - 6
|
||||
verticalPos += 12
|
||||
}
|
||||
svgDraw.drawActivation(diagram, activationData, verticalPos, conf);
|
||||
svgDraw.drawActivation(diagram, activationData, verticalPos, conf)
|
||||
|
||||
exports.bounds.insert(activationData.startx, verticalPos -10, activationData.stopx, verticalPos);
|
||||
exports.bounds.insert(activationData.startx, verticalPos - 10, activationData.stopx, verticalPos)
|
||||
}
|
||||
|
||||
var lastMsg;
|
||||
var lastMsg
|
||||
|
||||
// Draw the messages/signals
|
||||
messages.forEach(function (msg) {
|
||||
var loopData;
|
||||
var loopData
|
||||
|
||||
switch (msg.type) {
|
||||
case sq.yy.LINETYPE.NOTE:
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
|
||||
startx = actors[msg.from].x;
|
||||
stopx = actors[msg.to].x;
|
||||
startx = actors[msg.from].x
|
||||
stopx = actors[msg.to].x
|
||||
|
||||
if (msg.placement === sq.yy.PLACEMENT.RIGHTOF) {
|
||||
drawNote(diagram, startx + (conf.width + conf.actorMargin)/2, exports.bounds.getVerticalPos(), msg);
|
||||
|
||||
drawNote(diagram, startx + (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg)
|
||||
} else if (msg.placement === sq.yy.PLACEMENT.LEFTOF) {
|
||||
drawNote(diagram, startx - (conf.width + conf.actorMargin)/2, exports.bounds.getVerticalPos(), msg);
|
||||
drawNote(diagram, startx - (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg)
|
||||
} else if (msg.to === msg.from) {
|
||||
// Single-actor over
|
||||
drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg);
|
||||
drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg)
|
||||
} else {
|
||||
// Multi-actor over
|
||||
forceWidth = Math.abs(startx - stopx) + conf.actorMargin;
|
||||
forceWidth = Math.abs(startx - stopx) + conf.actorMargin
|
||||
drawNote(diagram, (startx + stopx + conf.width - forceWidth) / 2, exports.bounds.getVerticalPos(), msg,
|
||||
forceWidth);
|
||||
forceWidth)
|
||||
}
|
||||
break;
|
||||
break
|
||||
case sq.yy.LINETYPE.ACTIVE_START:
|
||||
exports.bounds.newActivation(msg, diagram);
|
||||
break;
|
||||
exports.bounds.newActivation(msg, diagram)
|
||||
break
|
||||
case sq.yy.LINETYPE.ACTIVE_END:
|
||||
activeEnd(msg, exports.bounds.getVerticalPos());
|
||||
break;
|
||||
activeEnd(msg, exports.bounds.getVerticalPos())
|
||||
break
|
||||
case sq.yy.LINETYPE.LOOP_START:
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
exports.bounds.newLoop(msg.message);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
|
||||
break;
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
exports.bounds.newLoop(msg.message)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.LOOP_END:
|
||||
loopData = exports.bounds.endLoop();
|
||||
loopData = exports.bounds.endLoop()
|
||||
|
||||
svgDraw.drawLoop(diagram, loopData,'loop', conf);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
svgDraw.drawLoop(diagram, loopData, 'loop', conf)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.OPT_START:
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
exports.bounds.newLoop(msg.message);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
|
||||
break;
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
exports.bounds.newLoop(msg.message)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.OPT_END:
|
||||
loopData = exports.bounds.endLoop();
|
||||
loopData = exports.bounds.endLoop()
|
||||
|
||||
svgDraw.drawLoop(diagram, loopData, 'opt', conf);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
svgDraw.drawLoop(diagram, loopData, 'opt', conf)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.ALT_START:
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
exports.bounds.newLoop(msg.message);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
|
||||
break;
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
exports.bounds.newLoop(msg.message)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.ALT_ELSE:
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
loopData = exports.bounds.addSectionToLoop(msg.message);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
loopData = exports.bounds.addSectionToLoop(msg.message)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.ALT_END:
|
||||
loopData = exports.bounds.endLoop();
|
||||
loopData = exports.bounds.endLoop()
|
||||
|
||||
svgDraw.drawLoop(diagram, loopData,'alt', conf);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
svgDraw.drawLoop(diagram, loopData, 'alt', conf)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.PAR_START:
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
exports.bounds.newLoop(msg.message);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
|
||||
break;
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
exports.bounds.newLoop(msg.message)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.PAR_AND:
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
loopData = exports.bounds.addSectionToLoop(msg.message);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
loopData = exports.bounds.addSectionToLoop(msg.message)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
break
|
||||
case sq.yy.LINETYPE.PAR_END:
|
||||
loopData = exports.bounds.endLoop();
|
||||
svgDraw.drawLoop(diagram, loopData, 'par', conf);
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||||
break;
|
||||
loopData = exports.bounds.endLoop()
|
||||
svgDraw.drawLoop(diagram, loopData, 'par', conf)
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin)
|
||||
break
|
||||
default:
|
||||
try {
|
||||
lastMsg = msg;
|
||||
exports.bounds.bumpVerticalPos(conf.messageMargin);
|
||||
var fromBounds = actorFlowVerticaBounds(msg.from);
|
||||
var toBounds = actorFlowVerticaBounds(msg.to);
|
||||
var fromIdx = fromBounds[0] <= toBounds[0]?1:0;
|
||||
var toIdx = fromBounds[0] < toBounds[0]?0:1;
|
||||
startx = fromBounds[fromIdx];
|
||||
stopx = toBounds[toIdx];
|
||||
lastMsg = msg
|
||||
exports.bounds.bumpVerticalPos(conf.messageMargin)
|
||||
var fromBounds = actorFlowVerticaBounds(msg.from)
|
||||
var toBounds = actorFlowVerticaBounds(msg.to)
|
||||
var fromIdx = fromBounds[0] <= toBounds[0] ? 1 : 0
|
||||
var toIdx = fromBounds[0] < toBounds[0] ? 0 : 1
|
||||
startx = fromBounds[fromIdx]
|
||||
stopx = toBounds[toIdx]
|
||||
|
||||
var verticalPos = exports.bounds.getVerticalPos();
|
||||
drawMessage(diagram, startx, stopx, verticalPos, msg);
|
||||
var allBounds = fromBounds.concat(toBounds);
|
||||
exports.bounds.insert(Math.min.apply(null, allBounds), verticalPos, Math.max.apply(null, allBounds), verticalPos);
|
||||
var verticalPos = exports.bounds.getVerticalPos()
|
||||
drawMessage(diagram, startx, stopx, verticalPos, msg)
|
||||
var allBounds = fromBounds.concat(toBounds)
|
||||
exports.bounds.insert(Math.min.apply(null, allBounds), verticalPos, Math.max.apply(null, allBounds), verticalPos)
|
||||
} catch (e) {
|
||||
console.error('error while drawing message', e);
|
||||
console.error('error while drawing message', e)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
if (conf.mirrorActors) {
|
||||
// Draw actors below diagram
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin*2);
|
||||
module.exports.drawActors(diagram, actors, actorKeys, exports.bounds.getVerticalPos());
|
||||
exports.bounds.bumpVerticalPos(conf.boxMargin * 2)
|
||||
module.exports.drawActors(diagram, actors, actorKeys, exports.bounds.getVerticalPos())
|
||||
}
|
||||
|
||||
var box = exports.bounds.getBounds();
|
||||
var box = exports.bounds.getBounds()
|
||||
|
||||
// Adjust line height of actor lines now that the height of the diagram is known
|
||||
log.debug('For line height fix Querying: #' + id + ' .actor-line');
|
||||
var actorLines = d3.selectAll('#' + id + ' .actor-line');
|
||||
actorLines.attr('y2',box.stopy);
|
||||
log.debug('For line height fix Querying: #' + id + ' .actor-line')
|
||||
var actorLines = d3.selectAll('#' + id + ' .actor-line')
|
||||
actorLines.attr('y2', box.stopy)
|
||||
|
||||
|
||||
var height = box.stopy - box.starty + 2*conf.diagramMarginY;
|
||||
var height = box.stopy - box.starty + 2 * conf.diagramMarginY
|
||||
|
||||
if (conf.mirrorActors) {
|
||||
height = height - conf.boxMargin + conf.bottomMarginAdj;
|
||||
height = height - conf.boxMargin + conf.bottomMarginAdj
|
||||
}
|
||||
|
||||
var width = (box.stopx - box.startx) + (2 * conf.diagramMarginX);
|
||||
var width = (box.stopx - box.startx) + (2 * conf.diagramMarginX)
|
||||
|
||||
if (title) {
|
||||
diagram.append('text')
|
||||
.text(title)
|
||||
.attr('x', ((box.stopx - box.startx) / 2) - (2 * conf.diagramMarginX))
|
||||
.attr('y', -25);
|
||||
.attr('y', -25)
|
||||
}
|
||||
|
||||
if (conf.useMaxWidth) {
|
||||
diagram.attr('height', '100%');
|
||||
diagram.attr('width', '100%');
|
||||
diagram.attr('style', 'max-width:' + (width) + 'px;');
|
||||
diagram.attr('height', '100%')
|
||||
diagram.attr('width', '100%')
|
||||
diagram.attr('style', 'max-width:' + (width) + 'px;')
|
||||
} else {
|
||||
diagram.attr('height',height);
|
||||
diagram.attr('width', width );
|
||||
diagram.attr('height', height)
|
||||
diagram.attr('width', width)
|
||||
}
|
||||
var extraVertForTitle = title ? 40 : 0
|
||||
diagram.attr('viewBox', (box.startx - conf.diagramMarginX) + ' -' + (conf.diagramMarginY + extraVertForTitle) + ' ' + width + ' ' + (height + extraVertForTitle))
|
||||
}
|
||||
var extraVertForTitle = title ? 40 : 0;
|
||||
diagram.attr('viewBox', (box.startx - conf.diagramMarginX) + ' -' + (conf.diagramMarginY + extraVertForTitle) + ' ' + width + ' ' + (height + extraVertForTitle));
|
||||
};
|
||||
|
||||
@@ -3,34 +3,34 @@
|
||||
*/
|
||||
// var log = require('../../logger').create();
|
||||
exports.drawRect = function (elem, rectData) {
|
||||
var rectElem = elem.append('rect');
|
||||
rectElem.attr('x', rectData.x);
|
||||
rectElem.attr('y', rectData.y);
|
||||
rectElem.attr('fill', rectData.fill);
|
||||
rectElem.attr('stroke', rectData.stroke);
|
||||
rectElem.attr('width', rectData.width);
|
||||
rectElem.attr('height', rectData.height);
|
||||
rectElem.attr('rx', rectData.rx);
|
||||
rectElem.attr('ry', rectData.ry);
|
||||
var rectElem = elem.append('rect')
|
||||
rectElem.attr('x', rectData.x)
|
||||
rectElem.attr('y', rectData.y)
|
||||
rectElem.attr('fill', rectData.fill)
|
||||
rectElem.attr('stroke', rectData.stroke)
|
||||
rectElem.attr('width', rectData.width)
|
||||
rectElem.attr('height', rectData.height)
|
||||
rectElem.attr('rx', rectData.rx)
|
||||
rectElem.attr('ry', rectData.ry)
|
||||
|
||||
if (typeof rectData.class !== 'undefined') {
|
||||
rectElem.attr('class', rectData.class);
|
||||
rectElem.attr('class', rectData.class)
|
||||
}
|
||||
|
||||
return rectElem;
|
||||
};
|
||||
return rectElem
|
||||
}
|
||||
|
||||
exports.drawText = function (elem, textData, width) {
|
||||
// Remove and ignore br:s
|
||||
var nText = textData.text.replace(/<br\/?>/ig,' ');
|
||||
var nText = textData.text.replace(/<br\/?>/ig, ' ')
|
||||
|
||||
var textElem = elem.append('text');
|
||||
textElem.attr('x', textData.x);
|
||||
textElem.attr('y', textData.y);
|
||||
textElem.style('text-anchor', textData.anchor);
|
||||
textElem.attr('fill', textData.fill);
|
||||
var textElem = elem.append('text')
|
||||
textElem.attr('x', textData.x)
|
||||
textElem.attr('y', textData.y)
|
||||
textElem.style('text-anchor', textData.anchor)
|
||||
textElem.attr('fill', textData.fill)
|
||||
if (typeof textData.class !== 'undefined') {
|
||||
textElem.attr('class', textData.class);
|
||||
textElem.attr('class', textData.class)
|
||||
}
|
||||
/* textData.text.split(/<br\/?>/ig).forEach(function(rowText){
|
||||
var span = textElem.append('tspan');
|
||||
@@ -39,46 +39,44 @@ exports.drawText = function(elem, textData, width) {
|
||||
span.text(rowText);
|
||||
}); */
|
||||
|
||||
|
||||
var span = textElem.append('tspan');
|
||||
var span = textElem.append('tspan')
|
||||
// span.attr('x', textData.x);
|
||||
span.attr('x', textData.x+textData.textMargin*2);
|
||||
span.attr('x', textData.x + textData.textMargin * 2)
|
||||
// span.attr('dy', textData.dy);
|
||||
span.attr("fill", textData.fill);
|
||||
span.text(nText);
|
||||
span.attr('fill', textData.fill)
|
||||
span.text(nText)
|
||||
if (typeof textElem.textwrap !== 'undefined') {
|
||||
|
||||
textElem.textwrap({
|
||||
x: textData.x, // bounding box is 300 pixels from the left
|
||||
y: textData.y, // bounding box is 400 pixels from the top
|
||||
width: width, // bounding box is 500 pixels across
|
||||
height: 1800 // bounding box is 600 pixels tall
|
||||
}, textData.textMargin);
|
||||
}, textData.textMargin)
|
||||
}
|
||||
|
||||
return textElem;
|
||||
};
|
||||
return textElem
|
||||
}
|
||||
|
||||
exports.drawLabel = function (elem, txtObject) {
|
||||
function genPoints (x, y, width, height, cut) {
|
||||
return x + "," + y + " " +
|
||||
(x + width) + "," + y + " " +
|
||||
(x + width) + "," + (y + height - cut) + " " +
|
||||
(x + width - cut * 1.2) + "," + (y + height) + " " +
|
||||
(x) + "," + (y + height);
|
||||
return x + ',' + y + ' ' +
|
||||
(x + width) + ',' + y + ' ' +
|
||||
(x + width) + ',' + (y + height - cut) + ' ' +
|
||||
(x + width - cut * 1.2) + ',' + (y + height) + ' ' +
|
||||
(x) + ',' + (y + height)
|
||||
}
|
||||
var polygon = elem.append("polygon");
|
||||
polygon.attr("points" , genPoints(txtObject.x, txtObject.y, 50, 20, 7));
|
||||
polygon.attr("style", "fill:#526e52;stroke:none");
|
||||
var polygon = elem.append('polygon')
|
||||
polygon.attr('points', genPoints(txtObject.x, txtObject.y, 50, 20, 7))
|
||||
polygon.attr('style', 'fill:#526e52;stroke:none')
|
||||
|
||||
txtObject.y = txtObject.y + txtObject.labelMargin;
|
||||
txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin;
|
||||
txtObject.fill = 'white';
|
||||
exports.drawText(elem, txtObject);
|
||||
txtObject.y = txtObject.y + txtObject.labelMargin
|
||||
txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin
|
||||
txtObject.fill = 'white'
|
||||
exports.drawText(elem, txtObject)
|
||||
|
||||
// return textElem;
|
||||
};
|
||||
var actorCnt = -1;
|
||||
}
|
||||
var actorCnt = -1
|
||||
/**
|
||||
* Draws an actor in the diagram with the attaced line
|
||||
* @param center - The center of the the actor
|
||||
@@ -86,10 +84,10 @@ var actorCnt = -1;
|
||||
* @param description The text in the box
|
||||
*/
|
||||
exports.drawActor = function (elem, left, verticalPos, description, conf) {
|
||||
var center = left + (conf.width/2);
|
||||
var g = elem.append('g');
|
||||
var center = left + (conf.width / 2)
|
||||
var g = elem.append('g')
|
||||
if (verticalPos === 0) {
|
||||
actorCnt++;
|
||||
actorCnt++
|
||||
g.append('line')
|
||||
.attr('id', 'actor' + actorCnt)
|
||||
.attr('x1', center)
|
||||
@@ -98,27 +96,27 @@ exports.drawActor = function(elem, left, verticalPos, description,conf){
|
||||
.attr('y2', 2000)
|
||||
.attr('class', 'actor-line')
|
||||
.attr('stroke-width', '0.5px')
|
||||
.attr('stroke', '#999');
|
||||
.attr('stroke', '#999')
|
||||
}
|
||||
|
||||
var rect = exports.getNoteRect();
|
||||
rect.x = left;
|
||||
rect.y = verticalPos;
|
||||
rect.fill = '#eaeaea';
|
||||
rect.width = conf.width;
|
||||
rect.height = conf.height;
|
||||
rect.class = 'actor';
|
||||
rect.rx = 3;
|
||||
rect.ry = 3;
|
||||
exports.drawRect(g, rect);
|
||||
var rect = exports.getNoteRect()
|
||||
rect.x = left
|
||||
rect.y = verticalPos
|
||||
rect.fill = '#eaeaea'
|
||||
rect.width = conf.width
|
||||
rect.height = conf.height
|
||||
rect.class = 'actor'
|
||||
rect.rx = 3
|
||||
rect.ry = 3
|
||||
exports.drawRect(g, rect)
|
||||
|
||||
_drawTextCandidateFunc(conf)(description, g,
|
||||
rect.x, rect.y, rect.width, rect.height, {'class':'actor'});
|
||||
};
|
||||
rect.x, rect.y, rect.width, rect.height, {'class': 'actor'})
|
||||
}
|
||||
|
||||
exports.anchorElement = function (elem) {
|
||||
return elem.append('g');
|
||||
};
|
||||
return elem.append('g')
|
||||
}
|
||||
/**
|
||||
* Draws an actor in the diagram with the attaced line
|
||||
* @param elem - element to append activation rect
|
||||
@@ -126,15 +124,15 @@ exports.anchorElement = function(elem) {
|
||||
* @param verticalPos - precise y cooridnate of bottom activation box edge
|
||||
*/
|
||||
exports.drawActivation = function (elem, bounds, verticalPos) {
|
||||
var rect = exports.getNoteRect();
|
||||
var g = bounds.anchored;
|
||||
rect.x = bounds.startx;
|
||||
rect.y = bounds.starty;
|
||||
rect.fill = '#f4f4f4';
|
||||
rect.width = bounds.stopx - bounds.startx;
|
||||
rect.height = verticalPos - bounds.starty;
|
||||
exports.drawRect(g, rect);
|
||||
};
|
||||
var rect = exports.getNoteRect()
|
||||
var g = bounds.anchored
|
||||
rect.x = bounds.startx
|
||||
rect.y = bounds.starty
|
||||
rect.fill = '#f4f4f4'
|
||||
rect.width = bounds.stopx - bounds.startx
|
||||
rect.height = verticalPos - bounds.starty
|
||||
exports.drawRect(g, rect)
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws an actor in the diagram with the attaced line
|
||||
@@ -143,7 +141,7 @@ exports.drawActivation = function(elem,bounds,verticalPos){
|
||||
* @param description The text in the box
|
||||
*/
|
||||
exports.drawLoop = function (elem, bounds, labelText, conf) {
|
||||
var g = elem.append('g');
|
||||
var g = elem.append('g')
|
||||
var drawLoopLine = function (startx, starty, stopx, stopy) {
|
||||
return g.append('line')
|
||||
.attr('x1', startx)
|
||||
@@ -152,47 +150,47 @@ exports.drawLoop = function(elem,bounds,labelText, conf){
|
||||
.attr('y2', stopy)
|
||||
.attr('stroke-width', 2)
|
||||
.attr('stroke', '#526e52')
|
||||
.attr('class','loopLine');
|
||||
};
|
||||
drawLoopLine(bounds.startx, bounds.starty, bounds.stopx , bounds.starty);
|
||||
drawLoopLine(bounds.stopx , bounds.starty, bounds.stopx , bounds.stopy );
|
||||
drawLoopLine(bounds.startx, bounds.stopy , bounds.stopx , bounds.stopy );
|
||||
drawLoopLine(bounds.startx, bounds.starty, bounds.startx, bounds.stopy );
|
||||
.attr('class', 'loopLine')
|
||||
}
|
||||
drawLoopLine(bounds.startx, bounds.starty, bounds.stopx, bounds.starty)
|
||||
drawLoopLine(bounds.stopx, bounds.starty, bounds.stopx, bounds.stopy)
|
||||
drawLoopLine(bounds.startx, bounds.stopy, bounds.stopx, bounds.stopy)
|
||||
drawLoopLine(bounds.startx, bounds.starty, bounds.startx, bounds.stopy)
|
||||
if (typeof bounds.sections !== 'undefined') {
|
||||
bounds.sections.forEach(function (item) {
|
||||
drawLoopLine(bounds.startx, item, bounds.stopx, item).style('stroke-dasharray', '3, 3');
|
||||
});
|
||||
drawLoopLine(bounds.startx, item, bounds.stopx, item).style('stroke-dasharray', '3, 3')
|
||||
})
|
||||
}
|
||||
|
||||
var txt = exports.getTextObj();
|
||||
txt.text = labelText;
|
||||
txt.x = bounds.startx;
|
||||
txt.y = bounds.starty;
|
||||
txt.labelMargin = 1.5 * 10; // This is the small box that says "loop"
|
||||
txt.class = 'labelText'; // Its size & position are fixed.
|
||||
txt.fill = 'white';
|
||||
var txt = exports.getTextObj()
|
||||
txt.text = labelText
|
||||
txt.x = bounds.startx
|
||||
txt.y = bounds.starty
|
||||
txt.labelMargin = 1.5 * 10 // This is the small box that says "loop"
|
||||
txt.class = 'labelText' // Its size & position are fixed.
|
||||
txt.fill = 'white'
|
||||
|
||||
exports.drawLabel(g,txt);
|
||||
exports.drawLabel(g, txt)
|
||||
|
||||
txt = exports.getTextObj();
|
||||
txt.text = '[ ' + bounds.title + ' ]';
|
||||
txt.x = bounds.startx + (bounds.stopx - bounds.startx)/2;
|
||||
txt.y = bounds.starty + 1.5 * conf.boxMargin;
|
||||
txt.anchor = 'middle';
|
||||
txt.class = 'loopText';
|
||||
txt = exports.getTextObj()
|
||||
txt.text = '[ ' + bounds.title + ' ]'
|
||||
txt.x = bounds.startx + (bounds.stopx - bounds.startx) / 2
|
||||
txt.y = bounds.starty + 1.5 * conf.boxMargin
|
||||
txt.anchor = 'middle'
|
||||
txt.class = 'loopText'
|
||||
|
||||
exports.drawText(g,txt);
|
||||
exports.drawText(g, txt)
|
||||
|
||||
if (typeof bounds.sectionTitles !== 'undefined') {
|
||||
bounds.sectionTitles.forEach(function (item, idx) {
|
||||
if (item !== '') {
|
||||
txt.text = '[ ' + item + ' ]';
|
||||
txt.y = bounds.sections[idx] + 1.5 * conf.boxMargin;
|
||||
exports.drawText(g, txt);
|
||||
txt.text = '[ ' + item + ' ]'
|
||||
txt.y = bounds.sections[idx] + 1.5 * conf.boxMargin
|
||||
exports.drawText(g, txt)
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup arrow head and define the marker. The result is appended to the svg.
|
||||
@@ -206,20 +204,20 @@ exports.insertArrowHead = function(elem){
|
||||
.attr('markerHeight', 4)
|
||||
.attr('orient', 'auto')
|
||||
.append('path')
|
||||
.attr('d', 'M 0,0 V 4 L6,2 Z'); //this is actual shape for arrowhead
|
||||
};
|
||||
.attr('d', 'M 0,0 V 4 L6,2 Z') // this is actual shape for arrowhead
|
||||
}
|
||||
/**
|
||||
* Setup arrow head and define the marker. The result is appended to the svg.
|
||||
*/
|
||||
exports.insertArrowCrossHead = function (elem) {
|
||||
var defs = elem.append('defs');
|
||||
var defs = elem.append('defs')
|
||||
var marker = defs.append('marker')
|
||||
.attr('id', 'crosshead')
|
||||
.attr('markerWidth', 15)
|
||||
.attr('markerHeight', 8)
|
||||
.attr('orient', 'auto')
|
||||
.attr('refX', 16)
|
||||
.attr('refY', 4);
|
||||
.attr('refY', 4)
|
||||
|
||||
// The arrow
|
||||
marker.append('path')
|
||||
@@ -227,7 +225,7 @@ exports.insertArrowCrossHead = function(elem){
|
||||
.attr('stroke', '#000000')
|
||||
.style('stroke-dasharray', ('0, 0'))
|
||||
.attr('stroke-width', '1px')
|
||||
.attr('d', 'M 9,2 V 6 L16,4 Z');
|
||||
.attr('d', 'M 9,2 V 6 L16,4 Z')
|
||||
|
||||
// The cross
|
||||
marker.append('path')
|
||||
@@ -236,9 +234,8 @@ exports.insertArrowCrossHead = function(elem){
|
||||
.style('stroke-dasharray', ('0, 0'))
|
||||
.attr('stroke-width', '1px')
|
||||
.attr('d', 'M 0,1 L 6,7 M 6,1 L 0,7')
|
||||
; //this is actual shape for arrowhead
|
||||
|
||||
};
|
||||
// this is actual shape for arrowhead
|
||||
}
|
||||
|
||||
exports.getTextObj = function () {
|
||||
var txt = {
|
||||
@@ -252,9 +249,9 @@ exports.getTextObj = function(){
|
||||
textMargin: 0,
|
||||
rx: 0,
|
||||
ry: 0
|
||||
};
|
||||
return txt;
|
||||
};
|
||||
}
|
||||
return txt
|
||||
}
|
||||
|
||||
exports.getNoteRect = function () {
|
||||
var rect = {
|
||||
@@ -267,71 +264,71 @@ exports.getNoteRect = function(){
|
||||
height: 100,
|
||||
rx: 0,
|
||||
ry: 0
|
||||
};
|
||||
return rect;
|
||||
};
|
||||
}
|
||||
return rect
|
||||
}
|
||||
|
||||
var _drawTextCandidateFunc = (function () {
|
||||
function byText (content, g, x, y, width, height, textAttrs) {
|
||||
var text = g.append('text')
|
||||
.attr('x', x + width / 2).attr('y', y + height / 2 + 5)
|
||||
.style('text-anchor', 'middle')
|
||||
.text(content);
|
||||
_setTextAttrs(text, textAttrs);
|
||||
.text(content)
|
||||
_setTextAttrs(text, textAttrs)
|
||||
}
|
||||
|
||||
function byTspan (content, g, x, y, width, height, textAttrs) {
|
||||
var text = g.append('text')
|
||||
.attr('x', x + width / 2).attr('y', y)
|
||||
.style('text-anchor', 'middle');
|
||||
.style('text-anchor', 'middle')
|
||||
text.append('tspan')
|
||||
.attr('x', x + width / 2).attr('dy', '0')
|
||||
.text(content);
|
||||
.text(content)
|
||||
|
||||
if (typeof (text.textwrap) !== 'undefined') {
|
||||
text.textwrap({ // d3textwrap
|
||||
x: x + width / 2, y: y, width: width, height: height
|
||||
}, 0);
|
||||
}, 0)
|
||||
// vertical aligment after d3textwrap expans tspan to multiple tspans
|
||||
var tspans = text.selectAll('tspan');
|
||||
var tspans = text.selectAll('tspan')
|
||||
if (tspans.length > 0 && tspans[0].length > 0) {
|
||||
tspans = tspans[0];
|
||||
tspans = tspans[0]
|
||||
// set y of <text> to the mid y of the first line
|
||||
text.attr('y', y + (height / 2.0 - text[0][0].getBBox().height * (1 - 1.0 / tspans.length) / 2.0))
|
||||
.attr("dominant-baseline", "central")
|
||||
.attr("alignment-baseline", "central");
|
||||
.attr('dominant-baseline', 'central')
|
||||
.attr('alignment-baseline', 'central')
|
||||
}
|
||||
}
|
||||
_setTextAttrs(text, textAttrs);
|
||||
_setTextAttrs(text, textAttrs)
|
||||
}
|
||||
|
||||
function byFo (content, g, x, y, width, height, textAttrs) {
|
||||
var s = g.append('switch');
|
||||
var f = s.append("foreignObject")
|
||||
var s = g.append('switch')
|
||||
var f = s.append('foreignObject')
|
||||
.attr('x', x).attr('y', y)
|
||||
.attr('width', width).attr('height', height);
|
||||
.attr('width', width).attr('height', height)
|
||||
|
||||
var text = f.append('div').style('display', 'table')
|
||||
.style('height', '100%').style('width', '100%');
|
||||
.style('height', '100%').style('width', '100%')
|
||||
|
||||
text.append('div').style('display', 'table-cell')
|
||||
.style('text-align', 'center').style('vertical-align', 'middle')
|
||||
.text(content);
|
||||
.text(content)
|
||||
|
||||
byTspan(content, s, x, y, width, height, textAttrs);
|
||||
_setTextAttrs(text, textAttrs);
|
||||
byTspan(content, s, x, y, width, height, textAttrs)
|
||||
_setTextAttrs(text, textAttrs)
|
||||
}
|
||||
|
||||
function _setTextAttrs (toText, fromTextAttrsDict) {
|
||||
for (var key in fromTextAttrsDict) {
|
||||
if (fromTextAttrsDict.hasOwnProperty(key)) {
|
||||
toText.attr(key, fromTextAttrsDict[key]);
|
||||
toText.attr(key, fromTextAttrsDict[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return function (conf) {
|
||||
return conf.textPlacement === 'fo' ? byFo : (
|
||||
conf.textPlacement==='old' ? byText: byTspan);
|
||||
};
|
||||
})();
|
||||
conf.textPlacement === 'old' ? byText : byTspan)
|
||||
}
|
||||
})()
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
function decodeHTMLEntities (str) {
|
||||
if (str && typeof str === 'string') {
|
||||
// strip script/html tags
|
||||
var element = document.querySelector('.editor');
|
||||
var element = document.querySelector('.editor')
|
||||
|
||||
str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
|
||||
str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
|
||||
element.innerHTML = str;
|
||||
str = element.textContent;
|
||||
element.textContent = '';
|
||||
str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '')
|
||||
str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '')
|
||||
element.innerHTML = str
|
||||
str = element.textContent
|
||||
element.textContent = ''
|
||||
}
|
||||
|
||||
return str;
|
||||
return str
|
||||
}
|
||||
|
||||
var mermaidEditor = {
|
||||
@@ -20,28 +20,25 @@ var mermaidEditor = {
|
||||
graph: '',
|
||||
|
||||
init: function () {
|
||||
|
||||
document.querySelector('.button').addEventListener('click', function () {
|
||||
mermaidEditor.update();
|
||||
}.bind(this));
|
||||
mermaidEditor.update()
|
||||
})
|
||||
},
|
||||
|
||||
update: function () {
|
||||
var txt = document.querySelector('.editor').value;
|
||||
txt = txt.replace(/>/g,'>');
|
||||
txt = txt.replace(/</g,'<');
|
||||
txt = decodeHTMLEntities(txt).trim();
|
||||
var txt = document.querySelector('.editor').value
|
||||
txt = txt.replace(/>/g, '>')
|
||||
txt = txt.replace(/</g, '<')
|
||||
txt = decodeHTMLEntities(txt).trim()
|
||||
|
||||
document.querySelector('.mermaid').innerHTML = txt;
|
||||
global.mermaid.init();
|
||||
document.querySelector('.editor').value = txt;
|
||||
document.querySelector('.mermaid').innerHTML = txt
|
||||
global.mermaid.init()
|
||||
document.querySelector('.editor').value = txt
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
mermaidEditor.init()
|
||||
}, false)
|
||||
|
||||
mermaidEditor.init();
|
||||
|
||||
}, false);
|
||||
|
||||
exports = mermaidEditor;
|
||||
exports = mermaidEditor
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Created by knut on 2015-06-06.
|
||||
*/
|
||||
module.exports.mermaid = require('./mermaid.js');
|
||||
module.exports.mermaidAPI = require('./mermaidAPI.js');
|
||||
module.exports.mermaid = require('./mermaid.js')
|
||||
module.exports.mermaidAPI = require('./mermaidAPI.js')
|
||||
|
||||
@@ -17,52 +17,52 @@ const LEVELS = {
|
||||
error: 4,
|
||||
fatal: 5,
|
||||
default: 5
|
||||
};
|
||||
}
|
||||
|
||||
var defaultLevel = LEVELS.error;
|
||||
var defaultLevel = LEVELS.error
|
||||
|
||||
// exports.setLogLevel = function (level) {
|
||||
// defaultLevel = level;
|
||||
// };
|
||||
|
||||
function formatTime (timestamp) {
|
||||
var hh = timestamp.getUTCHours();
|
||||
var mm = timestamp.getUTCMinutes();
|
||||
var ss = timestamp.getSeconds();
|
||||
var ms = timestamp.getMilliseconds();
|
||||
var hh = timestamp.getUTCHours()
|
||||
var mm = timestamp.getUTCMinutes()
|
||||
var ss = timestamp.getSeconds()
|
||||
var ms = timestamp.getMilliseconds()
|
||||
// If you were building a timestamp instead of a duration, you would uncomment the following line to get 12-hour (not 24) time
|
||||
// if (hh > 12) {hh = hh % 12;}
|
||||
// These lines ensure you have two-digits
|
||||
if (hh < 10) {
|
||||
hh = '0' + hh;
|
||||
hh = '0' + hh
|
||||
}
|
||||
if (mm < 10) {
|
||||
mm = '0' + mm;
|
||||
mm = '0' + mm
|
||||
}
|
||||
if (ss < 10) {
|
||||
ss = '0' + ss;
|
||||
ss = '0' + ss
|
||||
}
|
||||
if (ms < 100) {
|
||||
ms = '0' + ms;
|
||||
ms = '0' + ms
|
||||
}
|
||||
if (ms < 10) {
|
||||
ms = '00' + ms;
|
||||
ms = '00' + ms
|
||||
}
|
||||
// This formats your string to HH:MM:SS
|
||||
var t = hh + ':' + mm + ':' + ss + ' (' + ms + ')';
|
||||
return t;
|
||||
var t = hh + ':' + mm + ':' + ss + ' (' + ms + ')'
|
||||
return t
|
||||
}
|
||||
|
||||
function format (level) {
|
||||
const time = formatTime(new Date());
|
||||
return '%c ' + time +' :%c' + level + ': ';
|
||||
const time = formatTime(new Date())
|
||||
return '%c ' + time + ' :%c' + level + ': '
|
||||
}
|
||||
|
||||
var debug = function(){};
|
||||
var info = function(){};
|
||||
var warn = function(){};
|
||||
var error = function(){};
|
||||
var fatal = function(){};
|
||||
var debug = function () {}
|
||||
var info = function () {}
|
||||
var warn = function () {}
|
||||
var error = function () {}
|
||||
var fatal = function () {}
|
||||
|
||||
/**
|
||||
* logLevel , decides the amount of logging to be used.
|
||||
@@ -75,15 +75,15 @@ var fatal = function(){};
|
||||
exports.setLogLevel = function (level) {
|
||||
switch (level) {
|
||||
case 1:
|
||||
exports.Log.debug = window.console.debug.bind(window.console, format('DEBUG', name), 'color:grey;', 'color: green;');
|
||||
exports.Log.debug = window.console.debug.bind(window.console, format('DEBUG', name), 'color:grey;', 'color: green;')
|
||||
case 2:
|
||||
exports.Log.info = window.console.debug.bind(window.console, format('INFO', name), 'color:grey;', 'color: info;');
|
||||
exports.Log.info = window.console.debug.bind(window.console, format('INFO', name), 'color:grey;', 'color: info;')
|
||||
case 3:
|
||||
exports.Log.warn = window.console.debug.bind(window.console, format('INFO', name), 'color:grey;', 'color: orange;');
|
||||
exports.Log.warn = window.console.debug.bind(window.console, format('INFO', name), 'color:grey;', 'color: orange;')
|
||||
case 4:
|
||||
exports.Log.error = window.console.debug.bind(window.console, format('ERROR', name), 'color:grey;', 'color: red;');
|
||||
exports.Log.error = window.console.debug.bind(window.console, format('ERROR', name), 'color:grey;', 'color: red;')
|
||||
case 5:
|
||||
exports.Log.fatal = window.console.debug.bind(window.console, format('FATAL', name), 'color:grey;', 'color: red;');
|
||||
exports.Log.fatal = window.console.debug.bind(window.console, format('FATAL', name), 'color:grey;', 'color: red;')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,5 +92,5 @@ exports.Log = {
|
||||
info: info,
|
||||
warn: warn,
|
||||
error: error,
|
||||
fatal: fatal,
|
||||
};
|
||||
fatal: fatal
|
||||
}
|
||||
|
||||
155
src/mermaid.js
155
src/mermaid.js
@@ -3,14 +3,14 @@
|
||||
* the diagrams to svg code.
|
||||
*/
|
||||
|
||||
var Logger = require('./logger');
|
||||
var log = Logger.Log;
|
||||
var mermaidAPI = require('./mermaidAPI');
|
||||
var nextId = 0;
|
||||
var Logger = require('./logger')
|
||||
var log = Logger.Log
|
||||
var mermaidAPI = require('./mermaidAPI')
|
||||
var nextId = 0
|
||||
|
||||
var he = require('he');
|
||||
var he = require('he')
|
||||
|
||||
module.exports.mermaidAPI = mermaidAPI;
|
||||
module.exports.mermaidAPI = mermaidAPI
|
||||
/**
|
||||
* ## init
|
||||
* Function that goes through the document to find the chart definitions in there and render them.
|
||||
@@ -33,104 +33,101 @@ module.exports.mermaidAPI = mermaidAPI;
|
||||
* @param nodes a css selector or an array of nodes
|
||||
*/
|
||||
var init = function () {
|
||||
var conf= mermaidAPI.getConfig();
|
||||
log.debug('Starting rendering diagrams');
|
||||
var nodes;
|
||||
var conf = mermaidAPI.getConfig()
|
||||
log.debug('Starting rendering diagrams')
|
||||
var nodes
|
||||
if (arguments.length >= 2) {
|
||||
/*! sequence config was passed as #1 */
|
||||
if (typeof arguments[0] !== 'undefined') {
|
||||
global.mermaid.sequenceConfig = arguments[0];
|
||||
global.mermaid.sequenceConfig = arguments[0]
|
||||
}
|
||||
|
||||
nodes = arguments[1];
|
||||
}
|
||||
else{
|
||||
nodes = arguments[0];
|
||||
nodes = arguments[1]
|
||||
} else {
|
||||
nodes = arguments[0]
|
||||
}
|
||||
|
||||
// if last argument is a function this is the callback function
|
||||
var callback;
|
||||
var callback
|
||||
if (typeof arguments[arguments.length - 1] === 'function') {
|
||||
callback = arguments[arguments.length-1];
|
||||
log.debug('Callback function found');
|
||||
callback = arguments[arguments.length - 1]
|
||||
log.debug('Callback function found')
|
||||
} else {
|
||||
if (typeof conf.mermaid !== 'undefined') {
|
||||
if (typeof conf.mermaid.callback === 'function') {
|
||||
callback = conf.mermaid.callback;
|
||||
log.debug('Callback function found');
|
||||
callback = conf.mermaid.callback
|
||||
log.debug('Callback function found')
|
||||
} else {
|
||||
log.debug('No Callback function found');
|
||||
log.debug('No Callback function found')
|
||||
}
|
||||
}
|
||||
}
|
||||
nodes = nodes === undefined ? document.querySelectorAll('.mermaid')
|
||||
: typeof nodes === 'string' ? document.querySelectorAll(nodes)
|
||||
: nodes instanceof Node ? [nodes]
|
||||
: nodes; // Last case - sequence config was passed pick next
|
||||
: nodes // Last case - sequence config was passed pick next
|
||||
|
||||
var i;
|
||||
var i
|
||||
|
||||
if (typeof mermaid_config !== 'undefined') {
|
||||
mermaidAPI.initialize(global.mermaid_config);
|
||||
mermaidAPI.initialize(global.mermaid_config)
|
||||
}
|
||||
log.debug('Start On Load before: '+global.mermaid.startOnLoad);
|
||||
log.debug('Start On Load before: ' + global.mermaid.startOnLoad)
|
||||
if (typeof global.mermaid.startOnLoad !== 'undefined') {
|
||||
log.debug('Start On Load inner: '+global.mermaid.startOnLoad);
|
||||
mermaidAPI.initialize({startOnLoad:global.mermaid.startOnLoad});
|
||||
|
||||
log.debug('Start On Load inner: ' + global.mermaid.startOnLoad)
|
||||
mermaidAPI.initialize({startOnLoad: global.mermaid.startOnLoad})
|
||||
}
|
||||
|
||||
|
||||
if (typeof global.mermaid.ganttConfig !== 'undefined') {
|
||||
mermaidAPI.initialize({gantt:global.mermaid.ganttConfig});
|
||||
mermaidAPI.initialize({gantt: global.mermaid.ganttConfig})
|
||||
}
|
||||
|
||||
var txt;
|
||||
var txt
|
||||
var insertSvg = function (svgCode, bindFunctions) {
|
||||
element.innerHTML = svgCode;
|
||||
element.innerHTML = svgCode
|
||||
if (typeof callback !== 'undefined') {
|
||||
callback(id);
|
||||
callback(id)
|
||||
}
|
||||
bindFunctions(element)
|
||||
}
|
||||
bindFunctions(element);
|
||||
};
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
var element = nodes[i];
|
||||
var element = nodes[i]
|
||||
|
||||
/*! Check if previously processed */
|
||||
if (!element.getAttribute('data-processed')) {
|
||||
element.setAttribute('data-processed', true);
|
||||
element.setAttribute('data-processed', true)
|
||||
} else {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
var id = 'mermaidChart' + nextId++;
|
||||
var id = 'mermaidChart' + nextId++
|
||||
|
||||
// Fetch the graph definition including tags
|
||||
txt = element.innerHTML;
|
||||
txt = element.innerHTML
|
||||
|
||||
// console.warn('delivererd from the browser: ');
|
||||
// console.warn(txt);
|
||||
|
||||
// transforms the html to pure text
|
||||
txt = he.decode(txt).trim();
|
||||
txt = he.decode(txt).trim()
|
||||
// console.warn('he decode: ');
|
||||
// console.warn(txt);
|
||||
|
||||
mermaidAPI.render(id,txt,insertSvg, element);
|
||||
mermaidAPI.render(id, txt, insertSvg, element)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.init = init;
|
||||
exports.parse = mermaidAPI.parse;
|
||||
exports.init = init
|
||||
exports.parse = mermaidAPI.parse
|
||||
/**
|
||||
* ## version
|
||||
* Function returning version information
|
||||
* @returns {string} A string containing the version info
|
||||
*/
|
||||
exports.version = function () {
|
||||
return 'v'+require('../package.json').version;
|
||||
};
|
||||
return 'v' + require('../package.json').version
|
||||
}
|
||||
|
||||
/**
|
||||
* ## initialize
|
||||
@@ -138,27 +135,25 @@ exports.version = function(){
|
||||
* @param config
|
||||
*/
|
||||
exports.initialize = function (config) {
|
||||
log.debug('Initializing mermaid');
|
||||
log.debug('Initializing mermaid')
|
||||
if (typeof config.mermaid !== 'undefined') {
|
||||
if (typeof config.mermaid.startOnLoad !== 'undefined') {
|
||||
global.mermaid.startOnLoad = config.mermaid.startOnLoad;
|
||||
global.mermaid.startOnLoad = config.mermaid.startOnLoad
|
||||
}
|
||||
if (typeof config.mermaid.htmlLabels !== 'undefined') {
|
||||
global.mermaid.htmlLabels = config.mermaid.htmlLabels;
|
||||
global.mermaid.htmlLabels = config.mermaid.htmlLabels
|
||||
}
|
||||
}
|
||||
mermaidAPI.initialize(config);
|
||||
};
|
||||
|
||||
mermaidAPI.initialize(config)
|
||||
}
|
||||
|
||||
var equals = function (val, variable) {
|
||||
if (typeof variable === 'undefined') {
|
||||
return false;
|
||||
return false
|
||||
} else {
|
||||
return (val === variable)
|
||||
}
|
||||
else{
|
||||
return (val === variable);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Global mermaid object. Contains the functions:
|
||||
@@ -174,32 +169,32 @@ global.mermaid = {
|
||||
htmlLabels: true,
|
||||
|
||||
init: function () {
|
||||
init.apply(null, arguments);
|
||||
init.apply(null, arguments)
|
||||
},
|
||||
initialize: function (config) {
|
||||
exports.initialize(config);
|
||||
exports.initialize(config)
|
||||
},
|
||||
version: function () {
|
||||
return mermaidAPI.version();
|
||||
return mermaidAPI.version()
|
||||
},
|
||||
parse: function (text) {
|
||||
return mermaidAPI.parse(text);
|
||||
return mermaidAPI.parse(text)
|
||||
},
|
||||
parseError: function (err) {
|
||||
log.debug('Mermaid Syntax error:');
|
||||
log.debug(err);
|
||||
log.debug('Mermaid Syntax error:')
|
||||
log.debug(err)
|
||||
},
|
||||
render: function (id, text, callback, element) {
|
||||
return mermaidAPI.render(id, text,callback, element);
|
||||
return mermaidAPI.render(id, text, callback, element)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ## parseError
|
||||
* This function overrides the default configuration.
|
||||
* @param config
|
||||
*/
|
||||
exports.parseError = global.mermaid.parseError;
|
||||
exports.parseError = global.mermaid.parseError
|
||||
|
||||
/**
|
||||
* ##contentLoaded
|
||||
@@ -207,11 +202,11 @@ exports.parseError = global.mermaid.parseError;
|
||||
* calls init for rendering the mermaid diagrams on the page.
|
||||
*/
|
||||
exports.contentLoaded = function () {
|
||||
var config;
|
||||
var config
|
||||
// Check state of start config mermaid namespace
|
||||
if (typeof mermaid_config !== 'undefined') {
|
||||
if (equals(false, global.mermaid_config.htmlLabels)) {
|
||||
global.mermaid.htmlLabels = false;
|
||||
global.mermaid.htmlLabels = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,43 +215,37 @@ exports.contentLoaded = function(){
|
||||
if (typeof global.mermaid_config !== 'undefined') {
|
||||
// Check if property startOnLoad is set
|
||||
if (equals(true, global.mermaid_config.startOnLoad)) {
|
||||
global.mermaid.init();
|
||||
global.mermaid.init()
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// No config found, do check API config
|
||||
config = mermaidAPI.getConfig();
|
||||
config = mermaidAPI.getConfig()
|
||||
if (config.startOnLoad) {
|
||||
global.mermaid.init();
|
||||
global.mermaid.init()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if(typeof global.mermaid === 'undefined' ){
|
||||
if (typeof global.mermaid.startOnLoad === 'undefined') {
|
||||
log.debug('In start, no config');
|
||||
config = mermaidAPI.getConfig();
|
||||
log.debug('In start, no config')
|
||||
config = mermaidAPI.getConfig()
|
||||
if (config.startOnLoad) {
|
||||
global.mermaid.init();
|
||||
global.mermaid.init()
|
||||
}
|
||||
// }else{
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
/*!
|
||||
* Wait for document loaded before starting the execution
|
||||
*/
|
||||
window.addEventListener('load', function () {
|
||||
exports.contentLoaded();
|
||||
}, false);
|
||||
exports.contentLoaded()
|
||||
}, false)
|
||||
}
|
||||
|
||||
// // Your actual module
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
// var rewire = require('rewire');
|
||||
var mermaid = require('./mermaid');
|
||||
var mermaid = require('./mermaid')
|
||||
// var log = require('./logger').create();
|
||||
|
||||
describe('when using mermaid and ', function () {
|
||||
@@ -23,233 +23,231 @@ describe('when using mermaid and ',function() {
|
||||
// global.document = mock.getDocument();
|
||||
// global.window = mock.getWindow();
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
it('should not start rendering with mermaid_config.startOnLoad set to false', function () {
|
||||
// mermaid = rewire('./mermaid');
|
||||
global.mermaid_config ={startOnLoad : false};
|
||||
global.mermaid_config = {startOnLoad: false}
|
||||
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||
spyOn(global.mermaid,'init');
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
||||
spyOn(global.mermaid, 'init')
|
||||
// log.debug(mermaid);
|
||||
mermaid.contentLoaded();
|
||||
expect(global.mermaid.init).not.toHaveBeenCalled();
|
||||
});
|
||||
mermaid.contentLoaded()
|
||||
expect(global.mermaid.init).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not start rendering with mermaid.startOnLoad set to false', function () {
|
||||
// mermaid = rewire('./mermaid');
|
||||
global.mermaid.startOnLoad = false;
|
||||
global.mermaid_config ={startOnLoad : true};
|
||||
global.mermaid.startOnLoad = false
|
||||
global.mermaid_config = {startOnLoad: true}
|
||||
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||
spyOn(global.mermaid,'init');
|
||||
mermaid.contentLoaded();
|
||||
expect(global.mermaid.init).not.toHaveBeenCalled();
|
||||
});
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
||||
spyOn(global.mermaid, 'init')
|
||||
mermaid.contentLoaded()
|
||||
expect(global.mermaid.init).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should start rendering with both startOnLoad set', function () {
|
||||
// mermaid = rewire('./mermaid');
|
||||
global.mermaid.startOnLoad = true;
|
||||
global.mermaid_config ={startOnLoad : true};
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||
spyOn(global.mermaid,'init');
|
||||
mermaid.contentLoaded();
|
||||
expect(global.mermaid.init).toHaveBeenCalled();
|
||||
});
|
||||
global.mermaid.startOnLoad = true
|
||||
global.mermaid_config = {startOnLoad: true}
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
||||
spyOn(global.mermaid, 'init')
|
||||
mermaid.contentLoaded()
|
||||
expect(global.mermaid.init).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should start rendering with mermaid.startOnLoad set and no mermaid_config defined', function () {
|
||||
// mermaid = rewire('./mermaid');
|
||||
global.mermaid.startOnLoad = true;
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||
spyOn(global.mermaid,'init');
|
||||
mermaid.contentLoaded();
|
||||
expect(global.mermaid.init).toHaveBeenCalled();
|
||||
});
|
||||
global.mermaid.startOnLoad = true
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
||||
spyOn(global.mermaid, 'init')
|
||||
mermaid.contentLoaded()
|
||||
expect(global.mermaid.init).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should start rendering as a default with no changes performed', function () {
|
||||
// mermaid = rewire('./mermaid');
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>';
|
||||
spyOn(global.mermaid,'init');
|
||||
mermaid.contentLoaded();
|
||||
expect(global.mermaid.init).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
document.body.innerHTML = '<div class="mermaid">graph TD;\na;</div>'
|
||||
spyOn(global.mermaid, 'init')
|
||||
mermaid.contentLoaded()
|
||||
expect(global.mermaid.init).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('when calling addEdges ', function () {
|
||||
var graph = require('./diagrams/flowchart/graphDb');
|
||||
var flow = require('./diagrams/flowchart/parser/flow');
|
||||
var flowRend = require('./diagrams/flowchart/flowRenderer');
|
||||
var graph = require('./diagrams/flowchart/graphDb')
|
||||
var flow = require('./diagrams/flowchart/parser/flow')
|
||||
var flowRend = require('./diagrams/flowchart/flowRenderer')
|
||||
|
||||
beforeEach(function () {
|
||||
global.mermaid_config ={startOnLoad : false};
|
||||
global.mermaid_config = {startOnLoad: false}
|
||||
// var MockBrowser = require('mock-browser').mocks.MockBrowser;
|
||||
// var mock = new MockBrowser();
|
||||
flow.parser.yy =graph;
|
||||
graph.clear();
|
||||
flow.parser.yy = graph
|
||||
graph.clear()
|
||||
// global.document = mock.getDocument();
|
||||
// mermaid = rewire('./mermaid');
|
||||
});
|
||||
})
|
||||
it('it should handle edges with text', function () {
|
||||
flow.parser.parse('graph TD;A-->|text ex|B;');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A-->|text ex|B;')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('normal');
|
||||
expect(options.label.match('text ex')).toBeTruthy();
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('normal')
|
||||
expect(options.label.match('text ex')).toBeTruthy()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
|
||||
it('should handle edges without text', function () {
|
||||
flow.parser.parse('graph TD;A-->B;');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A-->B;')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('normal');
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('normal')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
|
||||
it('should handle open-ended edges', function () {
|
||||
flow.parser.parse('graph TD;A---B;');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A---B;')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('none');
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('none')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
|
||||
it('should handle edges with styles defined', function () {
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('none');
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;');
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('none')
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
it('should handle edges with interpolation defined', function () {
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 interpolate basis');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 interpolate basis')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('none');
|
||||
expect(options.lineInterpolate).toBe('basis');
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('none')
|
||||
expect(options.lineInterpolate).toBe('basis')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
it('should handle edges with text and styles defined', function () {
|
||||
flow.parser.parse('graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('none');
|
||||
expect(options.label.match('the text')).toBeTruthy();
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;');
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('none')
|
||||
expect(options.label.match('the text')).toBeTruthy()
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
|
||||
it('should set fill to "none" by default when handling edges', function () {
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('none');
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;');
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('none')
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
|
||||
it('should not set fill to none if fill is set in linkStyle', function () {
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;');
|
||||
flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
flow.parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;')
|
||||
flow.parser.yy.getVertices()
|
||||
var edges = flow.parser.yy.getEdges()
|
||||
var mockG = {
|
||||
setEdge: function (start, end, options) {
|
||||
expect(start).toBe('A');
|
||||
expect(end).toBe('B');
|
||||
expect(options.arrowhead).toBe('none');
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;');
|
||||
expect(start).toBe('A')
|
||||
expect(end).toBe('B')
|
||||
expect(options.arrowhead).toBe('none')
|
||||
expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flowRend.addEdges(edges,mockG);
|
||||
});
|
||||
});
|
||||
flowRend.addEdges(edges, mockG)
|
||||
})
|
||||
})
|
||||
|
||||
describe('checking validity of input ', function () {
|
||||
it('it should return false for an invalid definiton', function () {
|
||||
spyOn(global.mermaid,'parseError');
|
||||
var res = mermaid.parse('this is not a mermaid diagram definition');
|
||||
spyOn(global.mermaid, 'parseError')
|
||||
var res = mermaid.parse('this is not a mermaid diagram definition')
|
||||
|
||||
expect(res).toBe(false);
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled();
|
||||
});
|
||||
expect(res).toBe(false)
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('it should return true for a valid flow definition', function () {
|
||||
spyOn(global.mermaid,'parseError');
|
||||
var res = mermaid.parse('graph TD;A--x|text including URL space|B;');
|
||||
spyOn(global.mermaid, 'parseError')
|
||||
var res = mermaid.parse('graph TD;A--x|text including URL space|B;')
|
||||
|
||||
expect(res).toBe(true);
|
||||
expect(global.mermaid.parseError).not.toHaveBeenCalled();
|
||||
});
|
||||
expect(res).toBe(true)
|
||||
expect(global.mermaid.parseError).not.toHaveBeenCalled()
|
||||
})
|
||||
it('it should return false for an invalid flow definition', function () {
|
||||
spyOn(global.mermaid,'parseError');
|
||||
var res = mermaid.parse('graph TQ;A--x|text including URL space|B;');
|
||||
spyOn(global.mermaid, 'parseError')
|
||||
var res = mermaid.parse('graph TQ;A--x|text including URL space|B;')
|
||||
|
||||
expect(res).toBe(false);
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled();
|
||||
});
|
||||
expect(res).toBe(false)
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('it should return true for a valid sequenceDiagram definition', function () {
|
||||
spyOn(global.mermaid,'parseError');
|
||||
spyOn(global.mermaid, 'parseError')
|
||||
var str = 'sequenceDiagram\n' +
|
||||
'Alice->Bob: Hello Bob, how are you?\n\n' +
|
||||
'%% Comment\n' +
|
||||
@@ -258,15 +256,15 @@ describe('when using mermaid and ',function() {
|
||||
'Bob-->Alice: I am good thanks!\n' +
|
||||
'else isSick\n' +
|
||||
'Bob-->Alice: Feel sick...\n' +
|
||||
'end';
|
||||
var res = mermaid.parse(str);
|
||||
'end'
|
||||
var res = mermaid.parse(str)
|
||||
|
||||
expect(res).toBe(true);
|
||||
expect(global.mermaid.parseError).not.toHaveBeenCalled();
|
||||
});
|
||||
expect(res).toBe(true)
|
||||
expect(global.mermaid.parseError).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('it should return false for an invalid sequenceDiagram definition', function () {
|
||||
spyOn(global.mermaid,'parseError');
|
||||
spyOn(global.mermaid, 'parseError')
|
||||
var str = 'sequenceDiagram\n' +
|
||||
'Alice:->Bob: Hello Bob, how are you?\n\n' +
|
||||
'%% Comment\n' +
|
||||
@@ -275,36 +273,34 @@ describe('when using mermaid and ',function() {
|
||||
'Bob-->Alice: I am good thanks!\n' +
|
||||
'else isSick\n' +
|
||||
'Bob-->Alice: Feel sick...\n' +
|
||||
'end';
|
||||
var res = mermaid.parse(str);
|
||||
'end'
|
||||
var res = mermaid.parse(str)
|
||||
|
||||
expect(res).toBe(false);
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled();
|
||||
});
|
||||
expect(res).toBe(false)
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('it should return true for a valid dot definition', function () {
|
||||
spyOn(global.mermaid,'parseError');
|
||||
spyOn(global.mermaid, 'parseError')
|
||||
var res = mermaid.parse('digraph\n' +
|
||||
'{\n' +
|
||||
' a -> b -> c -- d -> e;\n' +
|
||||
' a -- e;\n' +
|
||||
'}');
|
||||
'}')
|
||||
|
||||
expect(res).toBe(true);
|
||||
expect(global.mermaid.parseError).not.toHaveBeenCalled();
|
||||
});
|
||||
expect(res).toBe(true)
|
||||
expect(global.mermaid.parseError).not.toHaveBeenCalled()
|
||||
})
|
||||
it('it should return false for an invalid dot definition', function () {
|
||||
spyOn(global.mermaid,'parseError');
|
||||
spyOn(global.mermaid, 'parseError')
|
||||
var res = mermaid.parse('digraph\n' +
|
||||
'{\n' +
|
||||
'a -:> b -> c -- d -> e;\n' +
|
||||
'a -- e;\n' +
|
||||
'}');
|
||||
'}')
|
||||
|
||||
expect(res).toBe(false);
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
expect(res).toBe(false)
|
||||
expect(global.mermaid.parseError).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -11,34 +11,34 @@
|
||||
* returns a svg element for the graph. It is is then up to the user of the API to make use of the svg, either insert it
|
||||
* somewhere in the page or something completely different.
|
||||
*/
|
||||
var Logger = require('./logger');
|
||||
var log = Logger.Log;
|
||||
var Logger = require('./logger')
|
||||
var log = Logger.Log
|
||||
|
||||
var graph = require('./diagrams/flowchart/graphDb');
|
||||
var utils = require('./utils');
|
||||
var flowRenderer = require('./diagrams/flowchart/flowRenderer');
|
||||
var seq = require('./diagrams/sequenceDiagram/sequenceRenderer');
|
||||
var info = require('./diagrams/example/exampleRenderer');
|
||||
var infoParser = require('./diagrams/example/parser/example');
|
||||
var flowParser = require('./diagrams/flowchart/parser/flow');
|
||||
var dotParser = require('./diagrams/flowchart/parser/dot');
|
||||
var sequenceParser = require('./diagrams/sequenceDiagram/parser/sequenceDiagram');
|
||||
var sequenceDb = require('./diagrams/sequenceDiagram/sequenceDb');
|
||||
var infoDb = require('./diagrams/example/exampleDb');
|
||||
var gantt = require('./diagrams/gantt/ganttRenderer');
|
||||
var ganttParser = require('./diagrams/gantt/parser/gantt');
|
||||
var ganttDb = require('./diagrams/gantt/ganttDb');
|
||||
var classParser = require('./diagrams/classDiagram/parser/classDiagram');
|
||||
var classRenderer = require('./diagrams/classDiagram/classRenderer');
|
||||
var classDb = require('./diagrams/classDiagram/classDb');
|
||||
var gitGraphParser = require('./diagrams/gitGraph/parser/gitGraph');
|
||||
var gitGraphRenderer = require('./diagrams/gitGraph/gitGraphRenderer');
|
||||
var gitGraphAst = require('./diagrams/gitGraph/gitGraphAst');
|
||||
var d3 = require('./d3');
|
||||
var graph = require('./diagrams/flowchart/graphDb')
|
||||
var utils = require('./utils')
|
||||
var flowRenderer = require('./diagrams/flowchart/flowRenderer')
|
||||
var seq = require('./diagrams/sequenceDiagram/sequenceRenderer')
|
||||
var info = require('./diagrams/example/exampleRenderer')
|
||||
var infoParser = require('./diagrams/example/parser/example')
|
||||
var flowParser = require('./diagrams/flowchart/parser/flow')
|
||||
var dotParser = require('./diagrams/flowchart/parser/dot')
|
||||
var sequenceParser = require('./diagrams/sequenceDiagram/parser/sequenceDiagram')
|
||||
var sequenceDb = require('./diagrams/sequenceDiagram/sequenceDb')
|
||||
var infoDb = require('./diagrams/example/exampleDb')
|
||||
var gantt = require('./diagrams/gantt/ganttRenderer')
|
||||
var ganttParser = require('./diagrams/gantt/parser/gantt')
|
||||
var ganttDb = require('./diagrams/gantt/ganttDb')
|
||||
var classParser = require('./diagrams/classDiagram/parser/classDiagram')
|
||||
var classRenderer = require('./diagrams/classDiagram/classRenderer')
|
||||
var classDb = require('./diagrams/classDiagram/classDb')
|
||||
var gitGraphParser = require('./diagrams/gitGraph/parser/gitGraph')
|
||||
var gitGraphRenderer = require('./diagrams/gitGraph/gitGraphRenderer')
|
||||
var gitGraphAst = require('./diagrams/gitGraph/gitGraphAst')
|
||||
var d3 = require('./d3')
|
||||
|
||||
SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function (toElement) {
|
||||
return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
|
||||
};
|
||||
return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM())
|
||||
}
|
||||
/**
|
||||
* ## Configuration
|
||||
* These are the default options which can be overridden with the initialization call as in the example below:
|
||||
@@ -218,33 +218,32 @@ var config = {
|
||||
|
||||
// Within a day
|
||||
['%I:%M', function (d) {
|
||||
return d.getHours();
|
||||
return d.getHours()
|
||||
}],
|
||||
// Monday a week
|
||||
['w. %U', function (d) {
|
||||
return d.getDay() == 1;
|
||||
return d.getDay() == 1
|
||||
}],
|
||||
// Day within a week (not monday)
|
||||
['%a %d', function (d) {
|
||||
return d.getDay() && d.getDate() != 1;
|
||||
return d.getDay() && d.getDate() != 1
|
||||
}],
|
||||
// within a month
|
||||
['%b %d', function (d) {
|
||||
return d.getDate() != 1;
|
||||
return d.getDate() != 1
|
||||
}],
|
||||
// Month
|
||||
['%m-%y', function (d) {
|
||||
return d.getMonth();
|
||||
return d.getMonth()
|
||||
}]
|
||||
]
|
||||
},
|
||||
classDiagram: {},
|
||||
gitGraph: {},
|
||||
info: {}
|
||||
};
|
||||
|
||||
Logger.setLogLevel(config.logLevel);
|
||||
}
|
||||
|
||||
Logger.setLogLevel(config.logLevel)
|
||||
|
||||
/**
|
||||
* ## parse
|
||||
@@ -253,49 +252,48 @@ Logger.setLogLevel(config.logLevel);
|
||||
* @param text
|
||||
*/
|
||||
var parse = function (text) {
|
||||
var graphType = utils.detectType(text);
|
||||
var parser;
|
||||
var graphType = utils.detectType(text)
|
||||
var parser
|
||||
|
||||
switch (graphType) {
|
||||
case 'gitGraph':
|
||||
parser = gitGraphParser;
|
||||
parser.parser.yy = gitGraphAst;
|
||||
break;
|
||||
parser = gitGraphParser
|
||||
parser.parser.yy = gitGraphAst
|
||||
break
|
||||
case 'graph':
|
||||
parser = flowParser;
|
||||
parser.parser.yy = graph;
|
||||
break;
|
||||
parser = flowParser
|
||||
parser.parser.yy = graph
|
||||
break
|
||||
case 'dotGraph':
|
||||
parser = dotParser;
|
||||
parser.parser.yy = graph;
|
||||
break;
|
||||
parser = dotParser
|
||||
parser.parser.yy = graph
|
||||
break
|
||||
case 'sequenceDiagram':
|
||||
parser = sequenceParser;
|
||||
parser.parser.yy = sequenceDb;
|
||||
break;
|
||||
parser = sequenceParser
|
||||
parser.parser.yy = sequenceDb
|
||||
break
|
||||
case 'info':
|
||||
parser = infoParser;
|
||||
parser.parser.yy = infoDb;
|
||||
break;
|
||||
parser = infoParser
|
||||
parser.parser.yy = infoDb
|
||||
break
|
||||
case 'gantt':
|
||||
parser = ganttParser;
|
||||
parser.parser.yy = ganttDb;
|
||||
break;
|
||||
parser = ganttParser
|
||||
parser.parser.yy = ganttDb
|
||||
break
|
||||
case 'classDiagram':
|
||||
parser = classParser;
|
||||
parser.parser.yy = classDb;
|
||||
break;
|
||||
parser = classParser
|
||||
parser.parser.yy = classDb
|
||||
break
|
||||
}
|
||||
|
||||
try {
|
||||
parser.parse(text);
|
||||
return true;
|
||||
parser.parse(text)
|
||||
return true
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
catch(err){
|
||||
return false;
|
||||
}
|
||||
};
|
||||
exports.parse = parse;
|
||||
exports.parse = parse
|
||||
|
||||
/**
|
||||
* ## version
|
||||
@@ -303,51 +301,50 @@ exports.parse = parse;
|
||||
* @returns {string} A string containing the version info
|
||||
*/
|
||||
exports.version = function () {
|
||||
return require('../package.json').version;
|
||||
};
|
||||
|
||||
exports.encodeEntities = function(text){
|
||||
var txt = text;
|
||||
|
||||
txt = txt.replace(/style.*:\S*#.*;/g,function(s){
|
||||
var innerTxt = s.substring(0,s.length-1);
|
||||
return innerTxt;
|
||||
});
|
||||
txt = txt.replace(/classDef.*:\S*#.*;/g,function(s){
|
||||
var innerTxt = s.substring(0,s.length-1);
|
||||
return innerTxt;
|
||||
});
|
||||
|
||||
txt = txt.replace(/#\w+\;/g,function(s){
|
||||
var innerTxt = s.substring(1,s.length-1);
|
||||
|
||||
var isInt = /^\+?\d+$/.test(innerTxt);
|
||||
if(isInt){
|
||||
return 'fl°°'+innerTxt+'¶ß';
|
||||
}else{
|
||||
return 'fl°'+innerTxt+'¶ß';
|
||||
return require('../package.json').version
|
||||
}
|
||||
|
||||
});
|
||||
exports.encodeEntities = function (text) {
|
||||
var txt = text
|
||||
|
||||
return txt;
|
||||
};
|
||||
txt = txt.replace(/style.*:\S*#.*;/g, function (s) {
|
||||
var innerTxt = s.substring(0, s.length - 1)
|
||||
return innerTxt
|
||||
})
|
||||
txt = txt.replace(/classDef.*:\S*#.*;/g, function (s) {
|
||||
var innerTxt = s.substring(0, s.length - 1)
|
||||
return innerTxt
|
||||
})
|
||||
|
||||
txt = txt.replace(/#\w+\;/g, function (s) {
|
||||
var innerTxt = s.substring(1, s.length - 1)
|
||||
|
||||
var isInt = /^\+?\d+$/.test(innerTxt)
|
||||
if (isInt) {
|
||||
return 'fl°°' + innerTxt + '¶ß'
|
||||
} else {
|
||||
return 'fl°' + innerTxt + '¶ß'
|
||||
}
|
||||
})
|
||||
|
||||
return txt
|
||||
}
|
||||
|
||||
exports.decodeEntities = function (text) {
|
||||
var txt = text;
|
||||
var txt = text
|
||||
|
||||
txt = txt.replace(/\fl\°\°/g, function () {
|
||||
return '&#';
|
||||
});
|
||||
return '&#'
|
||||
})
|
||||
txt = txt.replace(/\fl\°/g, function () {
|
||||
return '&';
|
||||
});
|
||||
return '&'
|
||||
})
|
||||
txt = txt.replace(/¶ß/g, function () {
|
||||
return ';';
|
||||
});
|
||||
return ';'
|
||||
})
|
||||
|
||||
return txt;
|
||||
};
|
||||
return txt
|
||||
}
|
||||
/**
|
||||
* ##render
|
||||
* Function that renders an svg with a graph from a chart definition. Usage example below.
|
||||
@@ -372,9 +369,8 @@ exports.decodeEntities = function(text){
|
||||
* completed.
|
||||
*/
|
||||
var render = function (id, txt, cb, container) {
|
||||
|
||||
if (typeof container !== 'undefined') {
|
||||
container.innerHTML = '';
|
||||
container.innerHTML = ''
|
||||
|
||||
d3.select(container).append('div')
|
||||
.attr('id', 'd' + id)
|
||||
@@ -382,12 +378,11 @@ var render = function(id, txt, cb, container){
|
||||
.attr('id', id)
|
||||
.attr('width', '100%')
|
||||
.attr('xmlns', 'http://www.w3.org/2000/svg')
|
||||
.append('g');
|
||||
}
|
||||
else{
|
||||
var element = document.querySelector('#' + 'd'+id);
|
||||
.append('g')
|
||||
} else {
|
||||
var element = document.querySelector('#' + 'd' + id)
|
||||
if (element) {
|
||||
element.innerHTML = '';
|
||||
element.innerHTML = ''
|
||||
}
|
||||
|
||||
d3.select('body').append('div')
|
||||
@@ -396,177 +391,171 @@ var render = function(id, txt, cb, container){
|
||||
.attr('id', id)
|
||||
.attr('width', '100%')
|
||||
.attr('xmlns', 'http://www.w3.org/2000/svg')
|
||||
.append('g');
|
||||
.append('g')
|
||||
}
|
||||
|
||||
window.txt = txt;
|
||||
txt = exports.encodeEntities(txt);
|
||||
window.txt = txt
|
||||
txt = exports.encodeEntities(txt)
|
||||
// console.warn('mermaid encode: ');
|
||||
// console.warn(txt);
|
||||
|
||||
var element = d3.select('#d'+id).node();
|
||||
var graphType = utils.detectType(txt);
|
||||
var classes = {};
|
||||
var element = d3.select('#d' + id).node()
|
||||
var graphType = utils.detectType(txt)
|
||||
var classes = {}
|
||||
switch (graphType) {
|
||||
case 'gitGraph':
|
||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
gitGraphRenderer.setConf(config.gitGraph);
|
||||
gitGraphRenderer.draw(txt, id, false);
|
||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||
gitGraphRenderer.setConf(config.gitGraph)
|
||||
gitGraphRenderer.draw(txt, id, false)
|
||||
// if(config.cloneCssStyles){
|
||||
// classes = gitGraphRenderer.getClasses(txt, false);
|
||||
// utils.cloneCssStyles(element.firstChild, classes);
|
||||
// }
|
||||
break;
|
||||
break
|
||||
case 'graph':
|
||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
flowRenderer.setConf(config.flowchart);
|
||||
flowRenderer.draw(txt, id, false);
|
||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||
flowRenderer.setConf(config.flowchart)
|
||||
flowRenderer.draw(txt, id, false)
|
||||
if (config.cloneCssStyles) {
|
||||
classes = flowRenderer.getClasses(txt, false);
|
||||
utils.cloneCssStyles(element.firstChild, classes);
|
||||
classes = flowRenderer.getClasses(txt, false)
|
||||
utils.cloneCssStyles(element.firstChild, classes)
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'dotGraph':
|
||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
flowRenderer.setConf(config.flowchart);
|
||||
flowRenderer.draw(txt, id, true);
|
||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||
flowRenderer.setConf(config.flowchart)
|
||||
flowRenderer.draw(txt, id, true)
|
||||
if (config.cloneCssStyles) {
|
||||
classes = flowRenderer.getClasses(txt, true);
|
||||
utils.cloneCssStyles(element.firstChild, classes);
|
||||
classes = flowRenderer.getClasses(txt, true)
|
||||
utils.cloneCssStyles(element.firstChild, classes)
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'sequenceDiagram':
|
||||
config.sequenceDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
seq.setConf(config.sequenceDiagram);
|
||||
seq.draw(txt,id);
|
||||
config.sequenceDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||
seq.setConf(config.sequenceDiagram)
|
||||
seq.draw(txt, id)
|
||||
if (config.cloneCssStyles) {
|
||||
utils.cloneCssStyles(element.firstChild, []);
|
||||
utils.cloneCssStyles(element.firstChild, [])
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'gantt':
|
||||
config.gantt.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
gantt.setConf(config.gantt);
|
||||
gantt.draw(txt,id);
|
||||
config.gantt.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||
gantt.setConf(config.gantt)
|
||||
gantt.draw(txt, id)
|
||||
if (config.cloneCssStyles) {
|
||||
utils.cloneCssStyles(element.firstChild, []);
|
||||
utils.cloneCssStyles(element.firstChild, [])
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'classDiagram':
|
||||
config.classDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
classRenderer.setConf(config.classDiagram);
|
||||
classRenderer.draw(txt,id);
|
||||
config.classDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||
classRenderer.setConf(config.classDiagram)
|
||||
classRenderer.draw(txt, id)
|
||||
if (config.cloneCssStyles) {
|
||||
utils.cloneCssStyles(element.firstChild, []);
|
||||
utils.cloneCssStyles(element.firstChild, [])
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'info':
|
||||
config.info.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
info.draw(txt,id,exports.version());
|
||||
config.info.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||
info.draw(txt, id, exports.version())
|
||||
if (config.cloneCssStyles) {
|
||||
utils.cloneCssStyles(element.firstChild, []);
|
||||
utils.cloneCssStyles(element.firstChild, [])
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
|
||||
d3.select('#d'+id).selectAll('foreignobject div').attr('xmlns','http://www.w3.org/1999/xhtml');
|
||||
d3.select('#d' + id).selectAll('foreignobject div').attr('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
|
||||
var url = '';
|
||||
var url = ''
|
||||
if (config.arrowMarkerAbsolute) {
|
||||
url = window.location.protocol+'//'+window.location.host+window.location.pathname +window.location.search;
|
||||
url = url.replace(/\(/g,'\\(');
|
||||
url = url.replace(/\)/g,'\\)');
|
||||
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search
|
||||
url = url.replace(/\(/g, '\\(')
|
||||
url = url.replace(/\)/g, '\\)')
|
||||
}
|
||||
|
||||
// Fix for when the base tag is used
|
||||
var svgCode = d3.select('#d'+id).node().innerHTML.replace(/url\(#arrowhead/g,'url('+url +'#arrowhead','g');
|
||||
var svgCode = d3.select('#d' + id).node().innerHTML.replace(/url\(#arrowhead/g, 'url(' + url + '#arrowhead', 'g')
|
||||
|
||||
svgCode = exports.decodeEntities(svgCode);
|
||||
svgCode = exports.decodeEntities(svgCode)
|
||||
|
||||
// console.warn('mermaid decode: ');
|
||||
// console.warn(svgCode);
|
||||
// var he = require('he');
|
||||
// svgCode = he.decode(svgCode);
|
||||
if (typeof cb !== 'undefined') {
|
||||
cb(svgCode,graph.bindFunctions);
|
||||
cb(svgCode, graph.bindFunctions)
|
||||
} else {
|
||||
log.warn('CB = undefined!');
|
||||
log.warn('CB = undefined!')
|
||||
}
|
||||
|
||||
var node = d3.select('#d'+id).node();
|
||||
var node = d3.select('#d' + id).node()
|
||||
if (node !== null && typeof node.remove === 'function') {
|
||||
d3.select('#d'+id).node().remove();
|
||||
d3.select('#d' + id).node().remove()
|
||||
}
|
||||
|
||||
return svgCode;
|
||||
};
|
||||
return svgCode
|
||||
}
|
||||
|
||||
exports.render = function (id, text, cb, containerElement) {
|
||||
try {
|
||||
if (arguments.length === 1) {
|
||||
text = id;
|
||||
id = 'mermaidId0';
|
||||
text = id
|
||||
id = 'mermaidId0'
|
||||
}
|
||||
|
||||
if (typeof document === 'undefined') {
|
||||
// Todo handle rendering serverside using phantomjs
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// In browser
|
||||
return render(id, text, cb, containerElement);
|
||||
return render(id, text, cb, containerElement)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
log.warn(e);
|
||||
log.warn(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var setConf = function (cnf) {
|
||||
// Top level initially mermaid, gflow, sequenceDiagram and gantt
|
||||
var lvl1Keys = Object.keys(cnf);
|
||||
var i;
|
||||
var lvl1Keys = Object.keys(cnf)
|
||||
var i
|
||||
for (i = 0; i < lvl1Keys.length; i++) {
|
||||
|
||||
if (typeof cnf[lvl1Keys[i]] === 'object') {
|
||||
var lvl2Keys = Object.keys(cnf[lvl1Keys[i]]);
|
||||
var lvl2Keys = Object.keys(cnf[lvl1Keys[i]])
|
||||
|
||||
var j;
|
||||
var j
|
||||
for (j = 0; j < lvl2Keys.length; j++) {
|
||||
log.debug('Setting conf ',lvl1Keys[i],'-',lvl2Keys[j]);
|
||||
log.debug('Setting conf ', lvl1Keys[i], '-', lvl2Keys[j])
|
||||
if (typeof config[lvl1Keys[i]] === 'undefined') {
|
||||
|
||||
config[lvl1Keys[i]] = {};
|
||||
config[lvl1Keys[i]] = {}
|
||||
}
|
||||
log.debug('Setting config: '+lvl1Keys[i]+' '+lvl2Keys[j]+' to '+cnf[lvl1Keys[i]][lvl2Keys[j]]);
|
||||
config[lvl1Keys[i]][lvl2Keys[j]] = cnf[lvl1Keys[i]][lvl2Keys[j]];
|
||||
log.debug('Setting config: ' + lvl1Keys[i] + ' ' + lvl2Keys[j] + ' to ' + cnf[lvl1Keys[i]][lvl2Keys[j]])
|
||||
config[lvl1Keys[i]][lvl2Keys[j]] = cnf[lvl1Keys[i]][lvl2Keys[j]]
|
||||
}
|
||||
} else {
|
||||
config[lvl1Keys[i]] = cnf[lvl1Keys[i]];
|
||||
config[lvl1Keys[i]] = cnf[lvl1Keys[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.initialize = function (options) {
|
||||
log.debug('Initializing mermaidAPI');
|
||||
log.debug('Initializing mermaidAPI')
|
||||
// Update default config with options supplied at initialization
|
||||
if (typeof options === 'object') {
|
||||
setConf(options);
|
||||
setConf(options)
|
||||
}
|
||||
Logger.setLogLevel(config.logLevel)
|
||||
}
|
||||
Logger.setLogLevel(config.logLevel);
|
||||
|
||||
};
|
||||
exports.getConfig = function () {
|
||||
return config;
|
||||
};
|
||||
return config
|
||||
}
|
||||
|
||||
exports.parseError = function (err, hash) {
|
||||
if (typeof mermaid !== 'undefined') {
|
||||
global.mermaid.parseError(err,hash);
|
||||
global.mermaid.parseError(err, hash)
|
||||
} else {
|
||||
log.debug('Mermaid Syntax error:');
|
||||
log.debug(err);
|
||||
log.debug('Mermaid Syntax error:')
|
||||
log.debug(err)
|
||||
}
|
||||
}
|
||||
};
|
||||
global.mermaidAPI = {
|
||||
render: exports.render,
|
||||
parse: exports.parse,
|
||||
@@ -574,4 +563,4 @@ global.mermaidAPI = {
|
||||
detectType: utils.detectType,
|
||||
parseError: exports.parseError,
|
||||
getConfig: exports.getConfig
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
var api = require('./mermaidAPI.js');
|
||||
var api = require('./mermaidAPI.js')
|
||||
// var log = require('./logger').create();
|
||||
|
||||
describe('when using mermaidAPI and ', function () {
|
||||
@@ -16,59 +16,57 @@ describe('when using mermaidAPI and ',function() {
|
||||
// var MockBrowser = require('mock-browser').mocks.MockBrowser;
|
||||
// var mock = new MockBrowser();
|
||||
|
||||
delete global.mermaid_config;
|
||||
delete global.mermaid_config
|
||||
|
||||
// and in the run-code inside some object
|
||||
// global.document = mock.getDocument();
|
||||
// global.window = mock.getWindow();
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
it('should copy a literal into the configuration', function () {
|
||||
var orgConfig = api.getConfig();
|
||||
expect(orgConfig.testLiteral).toBe(undefined);
|
||||
var orgConfig = api.getConfig()
|
||||
expect(orgConfig.testLiteral).toBe(undefined)
|
||||
|
||||
api.initialize({'testLiteral':true});
|
||||
var config = api.getConfig();
|
||||
api.initialize({'testLiteral': true})
|
||||
var config = api.getConfig()
|
||||
|
||||
expect(config.testLiteral).toBe(true);
|
||||
});
|
||||
expect(config.testLiteral).toBe(true)
|
||||
})
|
||||
it('should copy a an object into the configuration', function () {
|
||||
var orgConfig = api.getConfig();
|
||||
expect(orgConfig.testObject).toBe(undefined);
|
||||
|
||||
var orgConfig = api.getConfig()
|
||||
expect(orgConfig.testObject).toBe(undefined)
|
||||
|
||||
var object = {
|
||||
test1: 1,
|
||||
test2: false
|
||||
};
|
||||
}
|
||||
|
||||
api.initialize({'testObject':object});
|
||||
api.initialize({'testObject':{'test3':true}});
|
||||
var config = api.getConfig();
|
||||
api.initialize({'testObject': object})
|
||||
api.initialize({'testObject': {'test3': true}})
|
||||
var config = api.getConfig()
|
||||
|
||||
expect(config.testObject.test1).toBe(1);
|
||||
expect(config.testObject.test2).toBe(false);
|
||||
expect(config.testObject.test3).toBe(true);
|
||||
expect(config.cloneCssStyles).toBe(orgConfig.cloneCssStyles);
|
||||
});
|
||||
|
||||
});
|
||||
expect(config.testObject.test1).toBe(1)
|
||||
expect(config.testObject.test2).toBe(false)
|
||||
expect(config.testObject.test3).toBe(true)
|
||||
expect(config.cloneCssStyles).toBe(orgConfig.cloneCssStyles)
|
||||
})
|
||||
})
|
||||
describe('checking validity of input ', function () {
|
||||
it('it should return false for an invalid definiton', function () {
|
||||
global.mermaidAPI.parseError= function(){};
|
||||
spyOn(global.mermaidAPI,'parseError');
|
||||
var res = api.parse('this is not a mermaid diagram definition');
|
||||
global.mermaidAPI.parseError = function () {}
|
||||
spyOn(global.mermaidAPI, 'parseError')
|
||||
var res = api.parse('this is not a mermaid diagram definition')
|
||||
|
||||
expect(res).toBe(false);
|
||||
expect(global.mermaidAPI.parseError).toHaveBeenCalled();
|
||||
});
|
||||
expect(res).toBe(false)
|
||||
expect(global.mermaidAPI.parseError).toHaveBeenCalled()
|
||||
})
|
||||
it('it should return true for a valid definiton', function () {
|
||||
spyOn(global.mermaidAPI,'parseError');
|
||||
var res = api.parse('graph TD;A--x|text including URL space|B;');
|
||||
spyOn(global.mermaidAPI, 'parseError')
|
||||
var res = api.parse('graph TD;A--x|text including URL space|B;')
|
||||
|
||||
expect(res).toBe(true);
|
||||
expect(global.mermaidAPI.parseError).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(res).toBe(true)
|
||||
expect(global.mermaidAPI.parseError).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
97
src/utils.js
97
src/utils.js
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
var Logger = require('./logger');
|
||||
var log = Logger.Log;
|
||||
var Logger = require('./logger')
|
||||
var log = Logger.Log
|
||||
|
||||
/**
|
||||
* @function detectType
|
||||
@@ -22,38 +22,38 @@ var log = Logger.Log;
|
||||
* @returns {string} A graph definition key
|
||||
*/
|
||||
var detectType = function (text) {
|
||||
text = text.replace(/^\s*%%.*\n/g,'\n');
|
||||
text = text.replace(/^\s*%%.*\n/g, '\n')
|
||||
if (text.match(/^\s*sequenceDiagram/)) {
|
||||
return 'sequenceDiagram';
|
||||
return 'sequenceDiagram'
|
||||
}
|
||||
|
||||
if (text.match(/^\s*digraph/)) {
|
||||
// log.debug('Detected dot syntax');
|
||||
return 'dotGraph';
|
||||
return 'dotGraph'
|
||||
}
|
||||
|
||||
if (text.match(/^\s*info/)) {
|
||||
// log.debug('Detected info syntax');
|
||||
return 'info';
|
||||
return 'info'
|
||||
}
|
||||
|
||||
if (text.match(/^\s*gantt/)) {
|
||||
// log.debug('Detected info syntax');
|
||||
return 'gantt';
|
||||
return 'gantt'
|
||||
}
|
||||
|
||||
if (text.match(/^\s*classDiagram/)) {
|
||||
log.debug('Detected classDiagram syntax');
|
||||
return 'classDiagram';
|
||||
log.debug('Detected classDiagram syntax')
|
||||
return 'classDiagram'
|
||||
}
|
||||
|
||||
if (text.match(/^\s*gitGraph/)) {
|
||||
log.debug('Detected gitGraph syntax');
|
||||
return 'gitGraph';
|
||||
log.debug('Detected gitGraph syntax')
|
||||
return 'gitGraph'
|
||||
}
|
||||
return 'graph';
|
||||
};
|
||||
exports.detectType= detectType;
|
||||
return 'graph'
|
||||
}
|
||||
exports.detectType = detectType
|
||||
|
||||
/**
|
||||
* Copies all relevant CSS content into the graph SVG.
|
||||
@@ -62,84 +62,81 @@ exports.detectType= detectType;
|
||||
* @param {object} Hash table of class definitions from the graph definition
|
||||
*/
|
||||
var cloneCssStyles = function (svg, classes) {
|
||||
var usedStyles = '';
|
||||
var sheets = document.styleSheets;
|
||||
var rule;
|
||||
var usedStyles = ''
|
||||
var sheets = document.styleSheets
|
||||
var rule
|
||||
for (var i = 0; i < sheets.length; i++) {
|
||||
// Avoid multiple inclusion on pages with multiple graphs
|
||||
if (sheets[i].title !== 'mermaid-svg-internal-css') {
|
||||
try {
|
||||
|
||||
var rules = sheets[i].cssRules;
|
||||
var rules = sheets[i].cssRules
|
||||
if (rules !== null) {
|
||||
for (var j = 0; j < rules.length; j++) {
|
||||
rule = rules[j];
|
||||
rule = rules[j]
|
||||
if (typeof (rule.style) !== 'undefined') {
|
||||
var elems;
|
||||
elems = svg.querySelectorAll(rule.selectorText);
|
||||
var elems
|
||||
elems = svg.querySelectorAll(rule.selectorText)
|
||||
if (elems.length > 0) {
|
||||
usedStyles += rule.selectorText + ' { ' + rule.style.cssText + '}\n';
|
||||
usedStyles += rule.selectorText + ' { ' + rule.style.cssText + '}\n'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
if (typeof (rule) !== 'undefined') {
|
||||
log.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
|
||||
log.warn('Invalid CSS selector "' + rule.selectorText + '"', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var defaultStyles = '';
|
||||
var embeddedStyles = '';
|
||||
var defaultStyles = ''
|
||||
var embeddedStyles = ''
|
||||
|
||||
for (var className in classes) {
|
||||
if (classes.hasOwnProperty(className) && typeof(className) != 'undefined') {
|
||||
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';
|
||||
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';
|
||||
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';
|
||||
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';
|
||||
defaultStyles += '#' + svg.id.trim() + ' .cluster rect ' + ' { ' + classes[className].clusterStyles.join('; ') + '; }\n'
|
||||
}
|
||||
} else {
|
||||
if (classes[className].styles instanceof Array) {
|
||||
embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect, .' + className + '>polygon, .' + className + '>circle, .' + className + '>ellipse { ' + classes[className].styles.join('; ') + '; }\n';
|
||||
embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect, .' + className + '>polygon, .' + className + '>circle, .' + className + '>ellipse { ' + classes[className].styles.join('; ') + '; }\n'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usedStyles !== '' || defaultStyles !== '' || embeddedStyles !== '') {
|
||||
var s = document.createElement('style');
|
||||
s.setAttribute('type', 'text/css');
|
||||
s.setAttribute('title', 'mermaid-svg-internal-css');
|
||||
s.innerHTML = '/* <![CDATA[ */\n';
|
||||
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;
|
||||
s.innerHTML += defaultStyles
|
||||
}
|
||||
if (usedStyles !== '') {
|
||||
s.innerHTML += usedStyles;
|
||||
s.innerHTML += usedStyles
|
||||
}
|
||||
if (embeddedStyles !== '') {
|
||||
s.innerHTML += embeddedStyles;
|
||||
s.innerHTML += embeddedStyles
|
||||
}
|
||||
s.innerHTML += '/* ]]> */\n'
|
||||
svg.insertBefore(s, svg.firstChild)
|
||||
}
|
||||
s.innerHTML += '/* ]]> */\n';
|
||||
svg.insertBefore(s, svg.firstChild);
|
||||
}
|
||||
};
|
||||
|
||||
exports.cloneCssStyles = cloneCssStyles;
|
||||
|
||||
exports.cloneCssStyles = cloneCssStyles
|
||||
|
||||
/**
|
||||
* @function isSubstringInArray
|
||||
@@ -150,9 +147,9 @@ exports.cloneCssStyles = cloneCssStyles;
|
||||
**/
|
||||
var isSubstringInArray = function (str, arr) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i].match(str)) return i;
|
||||
if (arr[i].match(str)) return i
|
||||
}
|
||||
return -1
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
exports.isSubstringInArray = isSubstringInArray;
|
||||
exports.isSubstringInArray = isSubstringInArray
|
||||
|
||||
@@ -1,216 +1,213 @@
|
||||
/**
|
||||
* Created by knut on 14-11-23.
|
||||
*/
|
||||
var utils = require('./utils');
|
||||
var utils = require('./utils')
|
||||
|
||||
// var log = require('./logger').create();
|
||||
describe('when detecting chart type ', function () {
|
||||
var str;
|
||||
var str
|
||||
beforeEach(function () {
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
it('should handle a graph defintion', function () {
|
||||
str = 'graph TB\nbfs1:queue';
|
||||
str = 'graph TB\nbfs1:queue'
|
||||
|
||||
var type = utils.detectType(str);
|
||||
expect(type).toBe('graph');
|
||||
});
|
||||
var type = utils.detectType(str)
|
||||
expect(type).toBe('graph')
|
||||
})
|
||||
it('should handle a graph defintion with leading spaces', function () {
|
||||
str = ' graph TB\nbfs1:queue';
|
||||
str = ' graph TB\nbfs1:queue'
|
||||
|
||||
var type = utils.detectType(str);
|
||||
expect(type).toBe('graph');
|
||||
});
|
||||
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';
|
||||
str = ' \n graph TB\nbfs1:queue'
|
||||
|
||||
var type = utils.detectType(str);
|
||||
expect(type).toBe('graph');
|
||||
});
|
||||
var type = utils.detectType(str)
|
||||
expect(type).toBe('graph')
|
||||
})
|
||||
it('should handle a graph defintion for gitGraph', function () {
|
||||
str = ' \n gitGraph TB:\nbfs1:queue';
|
||||
str = ' \n gitGraph TB:\nbfs1:queue'
|
||||
|
||||
var type = utils.detectType(str);
|
||||
expect(type).toBe('gitGraph');
|
||||
});
|
||||
});
|
||||
var type = utils.detectType(str)
|
||||
expect(type).toBe('gitGraph')
|
||||
})
|
||||
})
|
||||
|
||||
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 styleSheets = svg.getElementsByTagName('style')
|
||||
expect(styleSheets.length).toBe(1)
|
||||
var styleSheet = styleSheets[0]
|
||||
|
||||
var innerStyle = styleSheet.innerHTML;
|
||||
var styleArr = innerStyle.split('\n');
|
||||
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);
|
||||
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--;
|
||||
styleArrTrim.splice(i, 1)
|
||||
i--
|
||||
}
|
||||
styleArrTrim[i] = styleArrTrim[i].trim();
|
||||
styleArrTrim[i] = styleArrTrim[i].trim()
|
||||
}
|
||||
|
||||
return styleArrTrim;
|
||||
return styleArrTrim
|
||||
}
|
||||
|
||||
function addStyleToDocument () {
|
||||
var s = document.createElement('style');
|
||||
s.innerHTML = '.node { stroke:#eeeeee; }\n.node-square { stroke:#bbbbbb; }\n';
|
||||
document.body.appendChild(s);
|
||||
var s = document.createElement('style')
|
||||
s.innerHTML = '.node { stroke:#eeeeee; }\n.node-square { stroke:#bbbbbb; }\n'
|
||||
document.body.appendChild(s)
|
||||
}
|
||||
|
||||
function addSecondStyleToDocument () {
|
||||
var s = document.createElement('style');
|
||||
s.innerHTML = '.node2 { stroke:#eeeeee; }\n.node-square { stroke:#beb; }\n';
|
||||
document.body.appendChild(s);
|
||||
var s = document.createElement('style')
|
||||
s.innerHTML = '.node2 { stroke:#eeeeee; }\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;
|
||||
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';
|
||||
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 errors thrown when accessing CSS rules', function () {
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-01');
|
||||
var svg = document.createElement('svg')
|
||||
svg.setAttribute('id', 'mermaid-01')
|
||||
|
||||
// Firefox throws a SecurityError when trying to access cssRules
|
||||
document.styleSheets[document.styleSheets.length++] = {
|
||||
get cssRules() { throw new Error('SecurityError'); }
|
||||
};
|
||||
get cssRules () { throw new Error('SecurityError') }
|
||||
}
|
||||
|
||||
expect(function () {
|
||||
utils.cloneCssStyles(svg, {});
|
||||
}).not.toThrow();
|
||||
});
|
||||
utils.cloneCssStyles(svg, {})
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('should handle an empty set of classes', function () {
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-01');
|
||||
var svg = document.createElement('svg')
|
||||
svg.setAttribute('id', 'mermaid-01')
|
||||
|
||||
utils.cloneCssStyles(svg, {});
|
||||
utils.cloneCssStyles(svg, {})
|
||||
// Should not create style element if not needed
|
||||
expect(svg.innerHTML).toBe('');
|
||||
});
|
||||
expect(svg.innerHTML).toBe('')
|
||||
})
|
||||
|
||||
it('should handle a default class', function () {
|
||||
var svg = document.createElement('svg');
|
||||
svg.setAttribute('id', 'mermaid-01');
|
||||
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; }']);
|
||||
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>');
|
||||
});
|
||||
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');
|
||||
var svg = document.createElement('svg')
|
||||
svg.setAttribute('id', 'mermaid-01')
|
||||
|
||||
addStyleToDocument('mermaid');
|
||||
utils.cloneCssStyles(svg, {});
|
||||
addStyleToDocument('mermaid')
|
||||
utils.cloneCssStyles(svg, {})
|
||||
// Should not create style element if not needed
|
||||
expect(svg.innerHTML).toBe('');
|
||||
});
|
||||
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: #eeeeee;}', '.node-square { stroke: #bbbbbb;}']);
|
||||
});
|
||||
var svg = generateSVG()
|
||||
addStyleToDocument()
|
||||
utils.cloneCssStyles(svg, {})
|
||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: #eeeeee;}', '.node-square { stroke: #bbbbbb;}'])
|
||||
})
|
||||
|
||||
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: #eeeeee;}', '.node-square { stroke: #bbbbbb;}', '.node-square { stroke: #bbeebb;}']);
|
||||
});
|
||||
var svg = generateSVG()
|
||||
addStyleToDocument()
|
||||
addSecondStyleToDocument()
|
||||
utils.cloneCssStyles(svg, {})
|
||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: #eeeeee;}', '.node-square { stroke: #bbbbbb;}', '.node-square { stroke: #bbeebb;}'])
|
||||
})
|
||||
|
||||
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: #eeeeee;}', '.node-square { stroke: #bbbbbb;}', '.node-square { stroke: #bbeebb;}']);
|
||||
});
|
||||
var svg = generateSVG()
|
||||
addStyleToDocument()
|
||||
addSecondStyleToDocument()
|
||||
addMermaidSVGwithStyleToDocument()
|
||||
utils.cloneCssStyles(svg, {})
|
||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: #eeeeee;}', '.node-square { stroke: #bbbbbb;}', '.node-square { stroke: #bbeebb;}'])
|
||||
})
|
||||
|
||||
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:#ffffff', 'stroke-width:1.5px']}});
|
||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#ffffff; stroke-width:1.5px; }', '.node { stroke: #eeeeee;}', '.node-square { stroke: #bbbbbb;}']);
|
||||
});
|
||||
var svg = generateSVG()
|
||||
addStyleToDocument()
|
||||
utils.cloneCssStyles(svg, {'default': {'styles': ['stroke:#ffffff', 'stroke-width:1.5px']}})
|
||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#ffffff; stroke-width:1.5px; }', '.node { stroke: #eeeeee;}', '.node-square { stroke: #bbbbbb;}'])
|
||||
})
|
||||
|
||||
it('should handle a default class together with stylesheet in document and classDefs', function () {
|
||||
var svg = generateSVG();
|
||||
addStyleToDocument();
|
||||
var svg = generateSVG()
|
||||
addStyleToDocument()
|
||||
utils.cloneCssStyles(svg, {
|
||||
'default': {'styles': ['stroke:#ffffff', 'stroke-width:1.5px']},
|
||||
'node-square': {'styles': ['fill:#eeeeee', 'stroke:#aaaaaa']},
|
||||
'node-circle': {'styles': ['fill:#444444', 'stroke:#111111']}
|
||||
});
|
||||
})
|
||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#ffffff; stroke-width:1.5px; }',
|
||||
'.node { stroke: #eeeeee;}',
|
||||
'.node-square { stroke: #bbbbbb;}',
|
||||
'#mermaid-01 .node-square>rect, .node-square>polygon, .node-square>circle, .node-square>ellipse { fill:#eeeeee; stroke:#aaaaaa; }',
|
||||
'#mermaid-01 .node-circle>rect, .node-circle>polygon, .node-circle>circle, .node-circle>ellipse { fill:#444444; stroke:#111111; }'
|
||||
]);
|
||||
});
|
||||
});
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('when finding substring in array ', function () {
|
||||
it('should return the array index that contains the substring', function () {
|
||||
var arr = ['stroke:val1', 'fill:val2'];
|
||||
var result = utils.isSubstringInArray('fill', arr);
|
||||
expect(result).toEqual(1);
|
||||
});
|
||||
var arr = ['stroke:val1', 'fill:val2']
|
||||
var result = utils.isSubstringInArray('fill', arr)
|
||||
expect(result).toEqual(1)
|
||||
})
|
||||
it('should return -1 if the substring is not found in the array', function () {
|
||||
var arr = ['stroke:val1', 'stroke-width:val2'];
|
||||
var result = utils.isSubstringInArray('fill', arr);
|
||||
expect(result).toEqual(-1);
|
||||
});
|
||||
});
|
||||
var arr = ['stroke:val1', 'stroke-width:val2']
|
||||
var result = utils.isSubstringInArray('fill', arr)
|
||||
expect(result).toEqual(-1)
|
||||
})
|
||||
})
|
||||
|
||||
10
test/nav.js
10
test/nav.js
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Created by knut on 2015-09-15.
|
||||
*/
|
||||
var navApp = angular.module('navApp', []);
|
||||
var navApp = angular.module('navApp', [])
|
||||
|
||||
navApp.controller('NavAppCtrl', function ($scope) {
|
||||
$scope.items = [
|
||||
@@ -9,11 +9,11 @@ navApp.controller('NavAppCtrl', function ($scope) {
|
||||
'url': 'cases/ett.html'},
|
||||
{'name': 'Two',
|
||||
'url': 'cases/two.html'}
|
||||
];
|
||||
]
|
||||
|
||||
$scope.frameUrl = "web.html"
|
||||
$scope.frameUrl = 'web.html'
|
||||
|
||||
$scope.go = function (url) {
|
||||
alert(url);
|
||||
alert(url)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* Created by knut on 14-11-03.
|
||||
*/
|
||||
var tests = [];
|
||||
var tests = []
|
||||
for (var file in window.__karma__.files) {
|
||||
if (window.__karma__.files.hasOwnProperty(file)) {
|
||||
if (/spec\.js$/.test(file)) {
|
||||
var file2 = file.substr(10,file.length-13);
|
||||
console.log('Testing with: '+file2);
|
||||
var file2 = file.substr(10, file.length - 13)
|
||||
console.log('Testing with: ' + file2)
|
||||
|
||||
tests.push(file2);
|
||||
tests.push(file2)
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,4 @@ require.config({
|
||||
|
||||
// start test run, once Require.js is done
|
||||
callback: window.__karma__.start
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Created by knut on 14-12-02.
|
||||
*/
|
||||
mermaid = require('mermaid');
|
||||
mermaid = require('mermaid')
|
||||
|
||||
console.log('Test page! mermaid version'+mermaid.version());
|
||||
console.log('Test page! mermaid version' + mermaid.version())
|
||||
|
||||
@@ -7,23 +7,23 @@ require.config({
|
||||
exports: 'mermaid'
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
require([], function () {
|
||||
QUnit.module('requireTest.html');
|
||||
QUnit.module('requireTest.html')
|
||||
|
||||
QUnit.test('using mermaid in requirejs', function (assert) {
|
||||
var done = assert.async();
|
||||
var done = assert.async()
|
||||
require(['mermaid'], function (mermaid) {
|
||||
assert.ok(mermaid, 'mermaid is not null');
|
||||
console.log(mermaid);
|
||||
mermaid.init();
|
||||
assert.ok(mermaid, 'mermaid is not null')
|
||||
console.log(mermaid)
|
||||
mermaid.init()
|
||||
assert.equal(window.d3.selectAll('path')[0].length, 8,
|
||||
'drew 8 paths');
|
||||
done();
|
||||
});
|
||||
});
|
||||
'drew 8 paths')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.load();
|
||||
QUnit.start();
|
||||
});
|
||||
QUnit.load()
|
||||
QUnit.start()
|
||||
})
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
define('simple', function () {
|
||||
var simple = {
|
||||
data: 'info'
|
||||
};
|
||||
return simple;
|
||||
});
|
||||
}
|
||||
return simple
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user