mermaid/lib/cli.js

197 lines
5.4 KiB
JavaScript
Raw Normal View History

2017-04-13 20:50:22 +08:00
var fs = require('fs')
var exec = require('child_process').exec
var chalk = require('chalk')
var which = require('which')
var parseArgs = require('minimist')
var semver = require('semver')
var path = require('path')
2014-12-20 17:18:38 -08:00
2017-04-11 21:52:19 +08:00
var PHANTOM_VERSION = '^2.1.0'
2014-12-20 17:18:38 -08:00
2017-04-13 20:50:22 +08:00
var info = chalk.blue.bold
2014-12-20 17:18:38 -08:00
2017-04-11 21:52:19 +08:00
module.exports = (function () {
2017-04-13 20:50:22 +08:00
return new Cli()
2017-04-11 21:52:19 +08:00
}())
2017-04-13 20:50:22 +08:00
function Cli (options) {
2014-12-20 17:18:38 -08:00
this.options = {
2017-04-11 21:52:19 +08:00
alias: {
help: 'h',
png: 'p',
outputDir: 'o',
outputSuffix: 'O',
svg: 's',
verbose: 'v',
phantomPath: 'e',
sequenceConfig: 'c',
ganttConfig: 'g',
css: 't',
width: 'w'
},
'boolean': ['help', 'png', 'svg', 'verbose'],
'string': ['outputDir', 'outputSuffix']
2014-12-20 17:18:38 -08:00
}
this.errors = []
this.message = null
2017-04-13 20:50:22 +08:00
this.helpMessage = [
2017-04-11 21:52:19 +08:00
info('Usage: mermaid [options] <file>...'),
'',
'file The mermaid description file to be rendered',
'',
'Options:',
' -s --svg Output SVG instead of PNG (experimental)',
' -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 --outputSuffix Suffix to output filenames in front of '.svg' or '.png', defaults to ''",
' -e --phantomPath Specify the path to the phantomjs executable',
' -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',
' -g --ganttConfig Specify the path to the file with the configuration to be applied in the gantt diagram',
' -h --help Show this message',
' -v --verbose Show logging',
' -w --width width of the generated png (number)',
' --version Print version and quit'
2014-12-20 17:18:38 -08:00
]
return this
}
2017-04-13 20:50:22 +08:00
Cli.prototype.parse = function (argv, next) {
2017-04-11 21:52:19 +08:00
this.errors = [] // clear errors
2017-04-13 20:50:22 +08:00
var options = parseArgs(argv, this.options)
2014-12-20 17:18:38 -08:00
if (options.version) {
var pkg = require('../package.json')
2017-04-11 21:52:19 +08:00
this.message = '' + pkg.version
next(null, this.message)
2017-04-11 21:52:19 +08:00
} else if (options.help) {
2014-12-20 17:18:38 -08:00
this.message = this.helpMessage.join('\n')
next(null, this.message)
2017-04-11 21:52:19 +08:00
} else {
2014-12-20 17:18:38 -08:00
options.files = options._
if (!options.files.length) {
2017-04-11 21:52:19 +08:00
this.errors.push(new Error('You must specify at least one source file.'))
2014-12-20 17:18:38 -08:00
}
// ensure that parameter-expecting options have parameters
2017-04-11 21:52:19 +08:00
;['outputDir', 'outputSuffix', 'phantomPath', 'sequenceConfig', 'ganttConfig', 'css'].forEach(function (i) {
if (typeof options[i] !== 'undefined') {
2014-12-20 17:18:38 -08:00
if (typeof options[i] !== 'string' || options[i].length < 1) {
2017-04-11 21:52:19 +08:00
this.errors.push(new Error(i + ' expects a value.'))
2014-12-20 17:18:38 -08:00
}
}
}.bind(this))
// set svg/png flags appropriately
if (options.svg && !options.png) {
options.png = false
2017-04-11 21:52:19 +08:00
} else {
options.png = true
}
2017-04-11 21:52:19 +08:00
if (options.sequenceConfig) {
try {
fs.accessSync(options.sequenceConfig, fs.R_OK)
} catch (err) {
this.errors.push(err)
}
} else {
options.sequenceConfig = null
}
2017-04-11 21:52:19 +08:00
2015-04-20 21:21:17 +02:00
if (options.ganttConfig) {
try {
fs.accessSync(options.ganttConfig, fs.R_OK)
} catch (err) {
this.errors.push(err)
}
} else {
options.ganttConfig = null
2015-04-20 21:21:17 +02:00
}
2015-02-02 19:02:45 -08:00
if (options.css) {
try {
fs.accessSync(options.css, fs.R_OK)
2015-02-02 19:02:45 -08:00
} catch (err) {
this.errors.push(err)
}
} else {
2017-04-11 21:52:19 +08:00
options.css = path.join(__dirname, '..', 'dist', 'mermaid.css')
2015-02-02 19:02:45 -08:00
}
// set svg/png flags appropriately
2017-04-11 21:52:19 +08:00
if (!options.width) {
options.width = 1200
}
this.checkPhantom = createCheckPhantom(options.phantomPath)
2017-04-11 21:52:19 +08:00
this.checkPhantom(function (err, path) {
if (err) {
this.errors.push(err)
}
options.phantomPath = path
next(
2017-04-13 20:50:22 +08:00
this.errors.length > 0 ? this.errors : null
, this.message
, options
)
}.bind(this))
2014-12-20 17:18:38 -08:00
}
}
2017-04-11 21:52:19 +08:00
function createCheckPhantom (_phantomPath) {
2017-04-13 20:50:22 +08:00
var phantomPath = _phantomPath
2014-12-20 17:18:38 -08:00
2017-04-11 21:52:19 +08:00
return function checkPhantom (_next) {
2017-04-13 20:50:22 +08:00
var next = _next || function () { }
var err
if (typeof phantomPath === 'undefined') {
2014-12-20 17:18:38 -08:00
try {
var phantom = require('phantomjs')
phantomPath = phantom.path
2014-12-20 17:18:38 -08:00
} catch (e) {
try {
phantomPath = which.sync('phantomjs')
} catch (e) {
if (!phantomPath) {
phantomPath = null
err = new Error(
[
2017-04-11 21:52:19 +08:00
'Cannot find phantomjs in your PATH. If phantomjs is installed',
"you may need to specify its path manually with the '-e' option.",
"Run this executable with '--help' or view the README for more",
'details.'
].join('\n')
)
next(err)
return
}
2014-12-20 17:18:38 -08:00
}
}
}
// If we have phantompath, see if its version satisfies our requirements
2017-04-11 21:52:19 +08:00
exec('"' + phantomPath + '" --version', function (err, stdout, stderr) {
if (err) {
2017-04-11 21:52:19 +08:00
next(new Error('Could not find phantomjs at the specified path.'))
} else if (!semver.satisfies(stdout, PHANTOM_VERSION)) {
next(new Error(
2017-04-13 20:50:22 +08:00
'mermaid requires phantomjs ' +
2017-04-11 21:52:19 +08:00
PHANTOM_VERSION +
' to be installed, found version ' +
stdout
))
2017-04-11 21:52:19 +08:00
} else {
next(null, phantomPath)
}
})
}
2014-12-20 17:18:38 -08:00
}