mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Merge pull request #439 from whyzdev/flowchat_text
adde tests to reproduce #434 in flowchart
This commit is contained in:
commit
dfd9622ce7
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,3 +8,6 @@ bower_components
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
coverage
|
coverage
|
||||||
|
|
||||||
|
test/tmp_*
|
||||||
|
test/fixtures/samples/*.actual.*
|
||||||
|
@ -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."))
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
@ -99,20 +100,20 @@ files.forEach(function(file) {
|
|||||||
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'
|
||||||
)
|
)
|
||||||
|
@ -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) {
|
}
|
||||||
text.attr(key, textAttrs[key]);
|
|
||||||
|
function _setTextAttrs(toText, fromTextAttrsDict) {
|
||||||
|
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 : (
|
||||||
|
@ -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
93
test/cli_test-samples.js
Normal 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()
|
||||||
|
});
|
||||||
|
})
|
4
test/fixtures/samples/flowchart_text.mmd
vendored
Normal file
4
test/fixtures/samples/flowchart_text.mmd
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
graph TD
|
||||||
|
A[label]
|
||||||
|
B[very very very long long long long-long-long text]
|
||||||
|
A--test-->B
|
2
test/fixtures/samples/sequence_err.mmd
vendored
Normal file
2
test/fixtures/samples/sequence_err.mmd
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
sequenceDiagram
|
||||||
|
bad
|
6
test/fixtures/samples/sequence_text.mmd
vendored
Normal file
6
test/fixtures/samples/sequence_text.mmd
vendored
Normal 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
|
3
test/fixtures/samples/sequence_text_fo.cfg
vendored
Normal file
3
test/fixtures/samples/sequence_text_fo.cfg
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"textPlacement": "fo"
|
||||||
|
}
|
3
test/fixtures/samples/sequence_text_old.cfg
vendored
Normal file
3
test/fixtures/samples/sequence_text_old.cfg
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"textPlacement": "old"
|
||||||
|
}
|
3
test/fixtures/samples/sequence_text_tspan.cfg
vendored
Normal file
3
test/fixtures/samples/sequence_text_tspan.cfg
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"textPlacement": "tspan"
|
||||||
|
}
|
10
test/fixtures/sequence.mermaid
vendored
10
test/fixtures/sequence.mermaid
vendored
@ -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!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user