Merge pull request #439 from whyzdev/flowchat_text

adde tests to reproduce #434 in flowchart
This commit is contained in:
Knut Sveidqvist 2016-12-19 13:04:36 +01:00 committed by GitHub
commit dfd9622ce7
14 changed files with 155 additions and 33 deletions

5
.gitignore vendored
View File

@ -7,4 +7,7 @@ bower_components
.DS_Store .DS_Store
.idea .idea
coverage coverage
test/tmp_*
test/fixtures/samples/*.actual.*

View File

@ -21,6 +21,7 @@ function cli(options) {
help: 'h' help: 'h'
, png: 'p' , png: 'p'
, outputDir: 'o' , outputDir: 'o'
, outputSuffix: 'O'
, svg: 's' , svg: 's'
, verbose: 'v' , verbose: 'v'
, phantomPath: 'e' , phantomPath: 'e'
@ -30,7 +31,7 @@ function cli(options) {
, width: 'w' , width: 'w'
} }
, 'boolean': ['help', 'png', 'svg', 'verbose'] , 'boolean': ['help', 'png', 'svg', 'verbose']
, 'string': ['outputDir'] , 'string': ['outputDir', 'outputSuffix']
} }
this.errors = [] this.errors = []
@ -45,6 +46,7 @@ function cli(options) {
, " -s --svg Output SVG instead of PNG (experimental)" , " -s --svg Output SVG instead of PNG (experimental)"
, " -p --png If SVG was selected, and you also want PNG, set this flag" , " -p --png If SVG was selected, and you also want PNG, set this flag"
, " -o --outputDir Directory to save files, will be created automatically, defaults to `cwd`" , " -o --outputDir Directory to save files, will be created automatically, defaults to `cwd`"
, " -O --outputSuffix Suffix to output filenames in front of '.svg' or '.png', defaults to ''"
, " -e --phantomPath Specify the path to the phantomjs executable" , " -e --phantomPath Specify the path to the phantomjs executable"
, " -t --css Specify the path to a CSS file to be included when processing output" , " -t --css Specify the path to a CSS file to be included when processing output"
, " -c --sequenceConfig Specify the path to the file with the configuration to be applied in the sequence diagram" , " -c --sequenceConfig Specify the path to the file with the configuration to be applied in the sequence diagram"
@ -79,7 +81,7 @@ cli.prototype.parse = function(argv, next) {
} }
// ensure that parameter-expecting options have parameters // ensure that parameter-expecting options have parameters
;['outputDir', 'phantomPath', 'sequenceConfig', 'ganttConfig', 'css'].forEach(function(i) { ;['outputDir', 'outputSuffix', 'phantomPath', 'sequenceConfig', 'ganttConfig', 'css'].forEach(function(i) {
if(typeof options[i] !== 'undefined') { if(typeof options[i] !== 'undefined') {
if (typeof options[i] !== 'string' || options[i].length < 1) { if (typeof options[i] !== 'string' || options[i].length < 1) {
this.errors.push(new Error(i + " expects a value.")) this.errors.push(new Error(i + " expects a value."))

View File

@ -12,6 +12,7 @@ module.exports = { process: processMermaid }
function processMermaid(files, _options, _next) { function processMermaid(files, _options, _next) {
var options = _options || {} var options = _options || {}
, outputDir = options.outputDir || process.cwd() , outputDir = options.outputDir || process.cwd()
, outputSuffix = options.outputSuffix || ''
, next = _next || function() {} , next = _next || function() {}
, phantomArgs = [ , phantomArgs = [
phantomscript phantomscript
@ -23,6 +24,7 @@ function processMermaid(files, _options, _next) {
, options.ganttConfig , options.ganttConfig
, options.verbose , options.verbose
, options.width , options.width
, outputSuffix
]; ];
files.forEach(function(file) { files.forEach(function(file) {

View File

@ -29,7 +29,7 @@ var system = require('system')
, webpage = require('webpage') , webpage = require('webpage')
var page = webpage.create() var page = webpage.create()
, files = system.args.slice(9, system.args.length) , files = system.args.slice(10, system.args.length)
, width = system.args[8] , width = system.args[8]
if(typeof width === 'undefined' || width==='undefined'){ if(typeof width === 'undefined' || width==='undefined'){
@ -44,6 +44,7 @@ var options = {
, ganttConfig: system.args[6] !== 'null' ? JSON.parse(fs.read(system.args[6])) : {} , ganttConfig: system.args[6] !== 'null' ? JSON.parse(fs.read(system.args[6])) : {}
, verbose: system.args[7] === 'true' ? true : false , verbose: system.args[7] === 'true' ? true : false
, width: width , width: width
, outputSuffix: system.args[9]
} }
, log = logger(options.verbose) , log = logger(options.verbose)
options.sequenceConfig.useMaxWidth = false; options.sequenceConfig.useMaxWidth = false;
@ -98,21 +99,21 @@ files.forEach(function(file) {
for (var i = 0, len = allElements.length; i < len; i++) { for (var i = 0, len = allElements.length; i < len; i++) {
resolveForeignObjects(allElements[i]) resolveForeignObjects(allElements[i])
} }
var outputPath=options.outputDir + fs.separator + filename + options.outputSuffix;
if (options.png) { if (options.png) {
page.viewportSize = { page.viewportSize = {
width: ~~oDOM.documentElement.attributes.getNamedItem('width').value width: ~~oDOM.documentElement.attributes.getNamedItem('width').value
, height: ~~oDOM.documentElement.attributes.getNamedItem('height').value , height: ~~oDOM.documentElement.attributes.getNamedItem('height').value
} }
page.render(options.outputDir + fs.separator + filename + '.png') page.render(outputPath+'.png')
console.log('saved png: ' + filename + '.png') console.log('saved png: ' + filename + '.png')
} }
if (options.svg) { if (options.svg) {
var serialize = new XMLSerializer(); var serialize = new XMLSerializer();
fs.write( fs.write(outputPath+'.svg'
options.outputDir + fs.separator + filename + '.svg'
, serialize.serializeToString(oDOM)+'\n' , serialize.serializeToString(oDOM)+'\n'
, 'w' , 'w'
) )

View File

@ -271,16 +271,14 @@ var _drawTextCandidateFunc = (function() {
.attr('x', x + width / 2).attr('y', y + height / 2 + 5) .attr('x', x + width / 2).attr('y', y + height / 2 + 5)
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.text(content); .text(content);
for (var key in textAttrs) { _setTextAttrs(text, textAttrs);
text.attr(key, textAttrs[key]); }
}
};
function byTspan(content, g, x, y, width, height, textAttrs) { function byTspan(content, g, x, y, width, height, textAttrs) {
var text = g.append('text') var text = g.append('text')
.attr('x', x + width / 2).attr('y', y) .attr('x', x + width / 2).attr('y', y)
.style('text-anchor', 'middle'); .style('text-anchor', 'middle');
var tspan = text.append('tspan') text.append('tspan')
.attr('x', x + width / 2).attr('dy', '0') .attr('x', x + width / 2).attr('dy', '0')
.text(content); .text(content);
@ -293,16 +291,13 @@ var _drawTextCandidateFunc = (function() {
if (tspans.length > 0 && tspans[0].length > 0) { 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 //set y of <text> to the mid y of the first line
text.attr('y', y + (height/2.- text[0][0].getBBox().height*(1 - 1.0/tspans.length)/2.)) text.attr('y', y + (height/2.0 - text[0][0].getBBox().height*(1 - 1.0/tspans.length)/2.0))
.attr("dominant-baseline", "central") .attr("dominant-baseline", "central")
.attr("alignment-baseline", "central") .attr("alignment-baseline", "central");
} }
} }
_setTextAttrs(text, textAttrs);
for (var key in textAttrs) { }
text.attr(key, textAttrs[key]);
}
};
function byFo(content, g, x, y, width, height, textAttrs) { function byFo(content, g, x, y, width, height, textAttrs) {
var s = g.append('switch'); var s = g.append('switch');
@ -315,14 +310,19 @@ var _drawTextCandidateFunc = (function() {
text.append('div').style('display', 'table-cell') text.append('div').style('display', 'table-cell')
.style('text-align', 'center').style('vertical-align', 'middle') .style('text-align', 'center').style('vertical-align', 'middle')
.text(content) .text(content);
byTspan(content, s, x, y, width, height, textAttrs); byTspan(content, s, x, y, width, height, textAttrs);
_setTextAttrs(text, textAttrs);
}
for (var key in textAttrs) { function _setTextAttrs(toText, fromTextAttrsDict) {
text.attr(key, textAttrs[key]); for (var key in fromTextAttrsDict) {
if (fromTextAttrsDict.hasOwnProperty(key)) {
toText.attr(key, fromTextAttrsDict[key]);
} }
}; }
}
return function(conf) { return function(conf) {
return conf.textPlacement==='fo' ? byFo : ( return conf.textPlacement==='fo' ? byFo : (

View File

@ -47,7 +47,7 @@ test('output of single png', function(t) {
var expected = ['test.mermaid.png'] var expected = ['test.mermaid.png']
opt = clone(singleFile) var opt = clone(singleFile)
opt.outputDir += '_png' opt.outputDir += '_png'
opt.png = true opt.png = true
@ -64,7 +64,7 @@ test('output of multiple png', function(t) {
var expected = ['test.mermaid.png', 'test2.mermaid.png', var expected = ['test.mermaid.png', 'test2.mermaid.png',
'gantt.mermaid.png', 'sequence.mermaid.png'] 'gantt.mermaid.png', 'sequence.mermaid.png']
opt = clone(multiFile) var opt = clone(multiFile)
opt.outputDir += '_png' opt.outputDir += '_png'
opt.png = true opt.png = true
@ -80,7 +80,7 @@ test('output of single svg', function(t) {
var expected = ['test.mermaid.svg'] var expected = ['test.mermaid.svg']
opt = clone(singleFile) var opt = clone(singleFile)
opt.outputDir += '_svg' opt.outputDir += '_svg'
opt.svg = true opt.svg = true
@ -97,7 +97,7 @@ test('output of multiple svg', function(t) {
var expected = ['test.mermaid.svg', 'test2.mermaid.svg', var expected = ['test.mermaid.svg', 'test2.mermaid.svg',
'gantt.mermaid.svg', 'sequence.mermaid.svg'] 'gantt.mermaid.svg', 'sequence.mermaid.svg']
opt = clone(multiFile) var opt = clone(multiFile)
opt.outputDir += '_svg' opt.outputDir += '_svg'
opt.svg = true opt.svg = true

93
test/cli_test-samples.js Normal file
View File

@ -0,0 +1,93 @@
'use strict';
var exec = require('child_process').exec;
var path = require('path')
var test = require('tape')
, rimraf = require('rimraf')
var test_dir = 'test/fixtures/samples/'.replace('/',path.sep)
rimraf.sync(test_dir+'*.actual.*');
function exec_mermaid(args, verify) {
exec('bin/mermaid.js ' + args,
{env: {PATH: './node_modules/.bin'+path.delimiter+process.env.PATH}},
function(error, stdout, stderr) {
console.log('error:',error,'\nstdout:\n',stdout,'\nstderr:\n',stderr);
verify(error, stdout, stderr);
});
}
test('mermaid cli help', function(t) {
t.plan(1);
var args = [ '--help' ]
exec_mermaid(args.join(' '), function(error, stdout, stderr) {
t.notOk(stderr, 'no error')
t.end()
});
});
test('mermaid cli help', function(t) {
t.plan(1);
var args = [ '--badopt' ]
exec_mermaid(args.join(' '), function(error, stdout, stderr) {
t.ok(stderr, 'should get error')
t.end()
});
});
//todo
test.skip('sequence syntax error', function(t) {
t.plan(1);
var args = [ '--svg',
'--outputDir=' + test_dir,
'--outputSuffix=.actual',
test_dir+'sequence_err.mmd'
]
exec_mermaid(args.join(' '), function(error, stdout, stderr) {
t.ok(stderr, 'should get error')
t.end()
});
});
['', 'fo', 'tspan', 'old'].forEach(function(textPlacement) {
test('sequence svg text placelment: '+textPlacement, function(t) {
t.plan(1);
var args = [ '--svg',
'--outputDir=' + test_dir,
'--outputSuffix='+(textPlacement ? '_'+textPlacement : '')+'.actual',
textPlacement ? '--sequenceConfig='+test_dir+'sequence_text_'+textPlacement+'.cfg' : '',
test_dir+'sequence_text.mmd'
]
exec_mermaid(args.join(' '), function(error, stdout, stderr) {
t.notOk(stderr, 'no error')
t.end()
});
})
});
test('sequence png', function(t) {
t.plan(1);
var args = [ '--png',
'--outputDir=' + test_dir,
'--outputSuffix=.actual',
test_dir+'sequence_text.mmd'
]
exec_mermaid(args.join(' '), function(error, stdout, stderr) {
t.notOk(stderr, 'no error')
t.end()
});
})
test('flowchart svg text', function(t) {
t.plan(1);
var args = [ '--svg',
'--outputDir=' + test_dir,
'--outputSuffix=.actual',
test_dir+'flowchart_text.mmd'
]
exec_mermaid(args.join(' '), function(error, stdout, stderr) {
t.notOk(stderr, 'no error')
t.end()
});
})

View File

@ -0,0 +1,4 @@
graph TD
A[label]
B[very very very long long long long-long-long text]
A--test-->B

View File

@ -0,0 +1,2 @@
sequenceDiagram
bad

View File

@ -0,0 +1,6 @@
sequenceDiagram
participant A as actor
participant B as very very very long long long long-long-long text
A->>B: hi
B-->A:
B->>A: hello

View File

@ -0,0 +1,3 @@
{
"textPlacement": "fo"
}

View File

@ -0,0 +1,3 @@
{
"textPlacement": "old"
}

View File

@ -0,0 +1,3 @@
{
"textPlacement": "tspan"
}

View File

@ -1,8 +1,8 @@
sequenceDiagram sequenceDiagram
Alice->Bob: Hello Bob, how are you? Alice->>Bob: Hello Bob, how are you?
Note right of Bob: Bob thinks Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks! Bob-->>Alice: I am good thanks!
Bob-->John the Long: How about you John? Bob-->>John the Long: How about you John?
Bob-->Alice: Checking with John... Bob-->>Alice: Checking with John...
Alice->John the Long: Yes... John, how are you? Alice->>John the Long: Yes... John, how are you?
John the Long-->Alice: Better than you! John the Long-->Alice: Better than you!