refactor(CLI): refactoring of CLI code

This commit is contained in:
Estevao Soares dos Santos 2017-01-09 02:08:23 +00:00
parent 2d6cd1e908
commit e3521bd8fa
6 changed files with 172 additions and 90 deletions

BIN
dist/showdown.js vendored

Binary file not shown.

BIN
dist/showdown.min.js vendored

Binary file not shown.

View File

@ -1,6 +0,0 @@
module.exports = exports = function errorExit(e) {
'use strict';
console.error('ERROR: ' + e.message);
console.error('Run \'showdown <command> -h\' for help');
process.exit(1);
};

View File

@ -1,18 +1,20 @@
var yargs = require('yargs'), var yargs = require('yargs'),
fs = require('fs'), fs = require('fs'),
errorExit = require('./errorexit.js'), Messenger = require('./messenger.js'),
showdown = require('../../dist/showdown'); showdown = require('../../dist/showdown'),
showdownOptions = showdown.getDefaultOptions(false);
yargs.reset() yargs.reset()
.usage('Usage: showdown makehtml [options]') .usage('Usage: showdown makehtml [options]')
.example('showdown makehtml -i', 'Reads from stdin and outputs to stdout') .example('showdown makehtml -i', 'Reads from stdin and outputs to stdout')
.example('showdown makehtml -i foo.md -o bar.html', 'Reads \'foo.md\' and writes to \'bar.html\'') .example('showdown makehtml -i foo.md -o bar.html', 'Reads \'foo.md\' and writes to \'bar.html\'')
.example('showdown makehtml -i --flavor="github"', 'Parses stdin using GFM style')
.version()
.alias('v', 'version')
.config('c') .config('c')
.alias('c', 'config') .alias('c', 'config')
.help('h') .help('h')
.alias('h', 'help') .alias('h', 'help')
.version()
.alias('v', 'version')
.option('i', { .option('i', {
alias : 'input', alias : 'input',
describe: 'Input source. Usually a md file. If omitted or empty, reads from stdin', describe: 'Input source. Usually a md file. If omitted or empty, reads from stdin',
@ -32,7 +34,8 @@ yargs.reset()
.option('a', { .option('a', {
alias : 'append', alias : 'append',
describe: 'Append data to output instead of overwriting', describe: 'Append data to output instead of overwriting',
type: 'string' type: 'string',
default: false
}) })
.option('e', { .option('e', {
alias : 'extensions', alias : 'extensions',
@ -45,87 +48,135 @@ yargs.reset()
type: 'string' type: 'string'
}); });
yargs.options(showdown.getDefaultOptions(false)); // load showdown default options
argv = yargs.argv; for (var opt in showdownOptions) {
if (showdownOptions.hasOwnProperty(opt)) {
if (showdownOptions[opt].defaultValue === false) {
showdownOptions[opt].default = null;
} else {
showdownOptions[opt].default = showdownOptions[opt].defaultValue;
}
yargs.option(opt, showdownOptions[opt]);
}
}
function run() { function run() {
'use strict'; 'use strict';
var input = '', var argv = yargs.argv,
enc = 'utf8', readMode = (!argv.i || argv.i === '') ? 'stdin' : 'file',
output; writeMode = (!argv.o || argv.o === '') ? 'stdout' : 'file',
msgMode = (writeMode === 'file') ? 'stdout' : 'stderr',
if (argv.encoding) { /**
enc = argv.encoding; * MSG object
} * @type {Messenger}
*/
// to avoid passing extensions to converter messenger = new Messenger(msgMode),
delete argv.extensions; read = (readMode === 'stdin') ? readFromStdIn : readFromFile,
var converter = new showdown.Converter(argv); write = (writeMode === 'stdout') ? writeToStdOut : writeToFile,
enc = argv.encoding || 'utf8',
flavor = argv.p,
append = argv.a || false,
options = parseOptions(flavor),
converter = new showdown.Converter(options),
md, html;
// Load extensions // Load extensions
if (argv.e) { if (argv.e) {
messenger.printMsg('Loading extensions');
for (var i = 0; i < argv.e.length; ++i) { for (var i = 0; i < argv.e.length; ++i) {
loadExtension(argv.e[i], converter); try {
var ext = require(argv.e[i]);
converter.addExtension(ext, argv.e[i]);
} catch (e) {
messenger.printError('Could not load extension ' + argv.e[i] + '. Reason:');
messenger.errorExit(e);
}
} }
} }
if (!argv.i || argv.i === '') { messenger.printMsg('...');
// 'i' is undefined or empty, read from stdin // read the input
messenger.printMsg('Reading data from ' + readMode + '...');
md = read(enc);
// process the input
messenger.printMsg('Parsing markdown...');
html = converter.makeHtml(md);
// write the output
messenger.printMsg('Writing data to ' + writeMode + '...');
write(html, append);
messenger.printMsg('\n');
messenger.okExit();
function parseOptions(flavor) {
var options = {},
flavorOpts = showdown.getFlavorOptions(flavor) || {};
// if flavor is not undefined, let's tell the user we're loading that preset
if (flavor) {
messenger.printMsg('Loading ' + flavor + ' flavor.');
}
for (var opt in argv) {
if (argv.hasOwnProperty(opt)) {
// first we load the default options
if (showdownOptions.hasOwnProperty(opt) && showdownOptions[opt].default !== null) {
options[opt] = showdownOptions[opt].default;
}
// we now override defaults with flavor, if a flavor was indeed passed
if (flavorOpts.hasOwnProperty(opt)) {
options[opt] = flavorOpts[opt];
}
// lastly we override with explicit passed options
// being careful not to pass CLI specific options, such as -v, -h or --extensions
if (showdownOptions.hasOwnProperty(opt)) {
if (argv[opt] === true) {
messenger.printMsg('Enabling option ' + opt);
options[opt] = argv[opt];
} else if (argv[opt] === false) {
options[opt] = argv[opt];
}
}
}
}
return options;
}
function readFromStdIn() {
try { try {
var size = fs.fstatSync(process.stdin.fd).size; var size = fs.fstatSync(process.stdin.fd).size;
input = size > 0 ? fs.readSync(process.stdin.fd, size)[0] : ''; return size > 0 ? fs.readSync(process.stdin.fd, size)[0] : '';
} catch (e) { } catch (e) {
var err = new Error('Could not read from stdin, reason: ' + e.message); var err = new Error('Could not read from stdin, reason: ' + e.message);
errorExit(err); messenger.errorExit(err);
} }
} else { }
// 'i' has a value, read from file
function readFromFile(encoding) {
try { try {
input = fs.readFileSync(argv.i, enc); return fs.readFileSync(argv.i, encoding);
} catch (err) { } catch (err) {
errorExit(err); messenger.errorExit(err);
} }
} }
// Load flavor function writeToStdOut(html) {
if (argv.p) { return process.stdout.write(html);
converter.setFlavor(argv.p);
} }
// parse and convert file function writeToFile(html, append) {
output = converter.makeHtml(input);
// Write output
if (!argv.o || argv.o === '') {
// o is undefined or empty, write to stdout
process.stdout.write(output);
// we won't print anything since it would conspurcate stdout and,
// consequently, the outputted file
} else {
// o is has a value, presumably a file, write to it.
// If a flag is passed, it means we should append instead of overwriting. // If a flag is passed, it means we should append instead of overwriting.
// Only works with files, obviously // Only works with files, obviously
var write = (argv.a) ? fs.appendFileSync : fs.writeFileSync; var write = (append) ? fs.appendFileSync : fs.writeFileSync;
try { try {
write(argv.o, output); write(argv.o, html);
} catch (err) { } catch (err) {
errorExit(err); messenger.errorExit(err);
} }
console.error('DONE!');
}
}
function loadExtension(path, converter) {
'use strict';
var ext;
try {
ext = require(path);
converter.addExtension(ext, path);
} catch (e) {
console.error('Could not load extension ' + path + '. Reason:');
console.error(e.message);
} }
} }

39
src/cli/messenger.js Normal file
View File

@ -0,0 +1,39 @@
function Messenger(writeMode, supress, mute) {
'use strict';
writeMode = writeMode || 'stderr';
supress = !!supress;
mute = (!!supress || !!mute);
this._print = (writeMode === 'stdout') ? console.log : console.error;
this.errorExit = function (e) {
if (!mute) {
console.error('ERROR: ' + e.message);
console.error('Run \'showdown <command> -h\' for help');
}
process.exit(1);
};
this.okExit = function () {
if (!mute) {
this._print('DONE!');
}
process.exit(0);
};
this.printMsg = function (msg) {
if (supress || mute || !msg) {
return;
}
this._print(msg);
};
this.printError = function (msg) {
if (mute) {
return;
}
console.error(msg);
};
}
module.exports = Messenger;

View File

@ -1,4 +1,3 @@
/*
var semver = require('semver'), var semver = require('semver'),
cmd = 'node bin/showdown.js'; cmd = 'node bin/showdown.js';
@ -15,4 +14,3 @@ describe('showdown cli', function () {
}); });
} }
}); });
*/