diff --git a/lib/cli.js b/lib/cli.js index 0b389dc85..df627ff68 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,90 +1,89 @@ -var fs = require('fs') - , exec = require('child_process').exec - , chalk = require('chalk') - , which = require('which') - , parseArgs = require('minimist') - , semver = require('semver') - , path = require('path') +var fs = require('fs'), + exec = require('child_process').exec, + chalk = require('chalk'), + which = require('which'), + parseArgs = require('minimist'), + semver = require('semver'), + path = require('path') -var PHANTOM_VERSION = "^2.1.0" +var PHANTOM_VERSION = '^2.1.0' -var info = chalk.blue.bold - , note = chalk.green.bold +var info = chalk.blue.bold, + note = chalk.green.bold -module.exports = function() { +module.exports = (function () { return new cli() -}() +}()) -function cli(options) { +function cli (options) { this.options = { - 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'] + 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'] } this.errors = [] this.message = null - this.helpMessage = [ - , info('Usage: mermaid [options] ...') - , "" - , "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" + this.helpMessage = [, + info('Usage: mermaid [options] ...'), + '', + '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' ] return this } -cli.prototype.parse = function(argv, next) { - var options = parseArgs(argv, this.options) - , phantom +cli.prototype.parse = function (argv, next) { + this.errors = [] // clear errors + var options = parseArgs(argv, this.options), + phantom if (options.version) { var pkg = require('../package.json') - this.message = "" + pkg.version + this.message = '' + pkg.version next(null, this.message) - } - else if (options.help) { + } else if (options.help) { this.message = this.helpMessage.join('\n') next(null, this.message) - } - else { + } else { options.files = options._ if (!options.files.length) { - this.errors.push(new Error("You must specify at least one source file.")) + this.errors.push(new Error('You must specify at least one source file.')) } // ensure that parameter-expecting options have parameters - ;['outputDir', 'outputSuffix', 'phantomPath', 'sequenceConfig', 'ganttConfig', 'css'].forEach(function(i) { - if(typeof options[i] !== 'undefined') { + ;['outputDir', 'outputSuffix', 'phantomPath', 'sequenceConfig', 'ganttConfig', 'css'].forEach(function (i) { + if (typeof options[i] !== 'undefined') { 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.')) } } }.bind(this)) @@ -92,26 +91,23 @@ cli.prototype.parse = function(argv, next) { // set svg/png flags appropriately if (options.svg && !options.png) { options.png = false - } - else { + } else { options.png = true } - + if (options.sequenceConfig) { try { fs.accessSync(options.sequenceConfig, fs.R_OK) - } catch (err) { this.errors.push(err) } } else { options.sequenceConfig = null } - + if (options.ganttConfig) { try { fs.accessSync(options.ganttConfig, fs.R_OK) - } catch (err) { this.errors.push(err) } @@ -122,23 +118,22 @@ cli.prototype.parse = function(argv, next) { if (options.css) { try { fs.accessSync(options.css, fs.R_OK) - } catch (err) { this.errors.push(err) } } else { - options.css = path.join(__dirname, '..', 'dist', 'mermaid.css') + options.css = path.join(__dirname, '..', 'dist', 'mermaid.css') } // set svg/png flags appropriately - if(!options.width){ - options.width = 1200; + if (!options.width) { + options.width = 1200 } this.checkPhantom = createCheckPhantom(options.phantomPath) - this.checkPhantom(function(err, path) { - if(err) { + this.checkPhantom(function (err, path) { + if (err) { this.errors.push(err) } options.phantomPath = path @@ -151,13 +146,13 @@ cli.prototype.parse = function(argv, next) { } } -function createCheckPhantom(_phantomPath) { - var phantomPath = _phantomPath - , phantomVersion +function createCheckPhantom (_phantomPath) { + var phantomPath = _phantomPath, + phantomVersion - return function checkPhantom(_next) { - var next = _next || function() {} - , err + return function checkPhantom (_next) { + var next = _next || function () {}, + err if (typeof phantomPath === 'undefined') { try { @@ -171,10 +166,10 @@ function createCheckPhantom(_phantomPath) { phantomPath = null err = new Error( [ - "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." + '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') ) @@ -186,19 +181,17 @@ function createCheckPhantom(_phantomPath) { } // If we have phantompath, see if its version satisfies our requirements - exec('"' + phantomPath + '" --version', function(err, stdout, stderr) { + exec('"' + phantomPath + '" --version', function (err, stdout, stderr) { if (err) { - next(new Error("Could not find phantomjs at the specified path.")) - } - else if (!semver.satisfies(stdout, PHANTOM_VERSION)) { + next(new Error('Could not find phantomjs at the specified path.')) + } else if (!semver.satisfies(stdout, PHANTOM_VERSION)) { next(new Error( - 'mermaid requires phantomjs ' - + PHANTOM_VERSION - + ' to be installed, found version ' - + stdout + 'mermaid requires phantomjs ' + + PHANTOM_VERSION + + ' to be installed, found version ' + + stdout )) - } - else { + } else { next(null, phantomPath) } }) diff --git a/test/cli_test-parser.js b/test/cli_test-parser.js index ade3ad9a0..542e826ec 100644 --- a/test/cli_test-parser.js +++ b/test/cli_test-parser.js @@ -102,6 +102,19 @@ test('setting a css source file succeeds', function (t) { }) }) +test('setting an output directory incorrectly causes an error', function (t) { + t.plan(1) + + const cli = require(cliPath) + const argv = ['-o'] + + cli.parse(argv, function (err) { + t.ok(err, 'an error is raised') + + t.end() + }) +}) + test('a callback function is called after parsing', function (t) { t.plan(3) @@ -116,16 +129,3 @@ test('a callback function is called after parsing', function (t) { t.end() }) }) - -test('setting an output directory incorrectly causes an error', function (t) { - t.plan(1) - - const cli = require(cliPath) - const argv = ['-o'] - - cli.parse(argv, function (err) { - t.ok(err, 'an error is raised') - - t.end() - }) -}) diff --git a/test/cli_test-samples.js b/test/cli_test-samples.js index fa21a20e3..2c958bdca 100644 --- a/test/cli_test-samples.js +++ b/test/cli_test-samples.js @@ -37,6 +37,7 @@ function execCmd (cmd, verify) { function verifyNoError (t) { return function (error, stdout, stderr) { + t.ok(!error, 'no error') t.notOk(stderr, 'no stderr') t.end() } @@ -44,25 +45,26 @@ function verifyNoError (t) { function verifyError (t) { return function (error, stdout, stderr) { - t.ok(stderr, 'should get error') + t.ok(!error, 'no error') + t.ok(stderr, 'should get stderr') t.end() } } test('mermaid cli help', function (t) { - t.plan(1) + t.plan(2) const args = ['--help'] execMermaid(args.join(' '), verifyNoError(t)) }) test('mermaid cli help', function (t) { - t.plan(1) + t.plan(2) const args = ['--badopt'] execMermaid(args.join(' '), verifyError(t)) }) test.skip('sequence syntax error', function (t) { - t.plan(1) + t.plan(2) const args = ['--svg', testDir + 'sequence_err.mmd' ] @@ -71,7 +73,7 @@ test.skip('sequence syntax error', function (t) { ['', 'fo', 'tspan', 'old'].forEach(function (textPlacement) { test('sequence svg text placelment: ' + textPlacement, function (t) { - t.plan(1) + t.plan(2) const args = ['--svg', '--outputDir=' + testDir, '--outputSuffix=' + (textPlacement ? '_' + textPlacement : '') + '.actual', @@ -83,7 +85,7 @@ test.skip('sequence syntax error', function (t) { }) test('sequence png', function (t) { - t.plan(1) + t.plan(2) const args = ['--png', testDir + 'sequence_text.mmd' ] @@ -91,7 +93,7 @@ test('sequence png', function (t) { }) test('flowchart svg text', function (t) { - t.plan(1) + t.plan(2) const args = ['--svg', '--css=dist/mermaid.css', '--width=500', @@ -102,7 +104,7 @@ test('flowchart svg text', function (t) { ['svg', 'png'].forEach(function (format) { test('flowchart ' + format + 'text2', function (t) { - t.plan(1) + t.plan(2) const args = ['--' + format, '--css=dist/mermaid.forest.css', '--width=500', @@ -113,7 +115,7 @@ test('flowchart svg text', function (t) { }) test('gantt axis formatter svg', function (t) { - t.plan(1) + t.plan(2) const args = ['--svg', '--css=dist/mermaid.css', '--width=500', @@ -124,7 +126,7 @@ test('gantt axis formatter svg', function (t) { }) test('gitgraph sample svg', function (t) { - t.plan(1) + t.plan(2) const args = ['-s', '-v', '--width=500', testDir + 'gitgraph.mmd' @@ -133,7 +135,7 @@ test('gitgraph sample svg', function (t) { }) test('load sample.html in phantomjs and save screenshot png', function (t) { - t.plan(1) + t.plan(2) execPhantomjsToLoadHtmlSaveScreenshotPng(testDir + 'samples.html', verifyNoError(t)) })