123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- #!/usr/bin/env node
- var fs = require('fs'),
- path = require('path'),
- commander = require('commander'),
- async = require('async'),
- glob = require('glob'),
- mkdirp = require('mkdirp'),
- typogr = require('./typogr');
- function isDirectory(pathString) {
- try {
- // Query the entry
- return fs.statSync(pathString).isDirectory();
- }
- catch (error) {
- // if file doesn't exist, statSync throws an error instead of just returning false
- return false;
- }
- }
- // path.dirname and path.basename don't always work right, so we have to create our own functions
- function dirname(pathString) {
- return pathString.substring(0, pathString.lastIndexOf('/') + 1);
- }
- function basename(pathString) {
- return pathString.substring(pathString.lastIndexOf('/') + 1);
- }
- function readRenderWrite(input, output, force) {
- input = path.normalize(input);
- output = path.normalize(output);
- if(isDirectory(input))
- input = input + '/**'; // add glob to get all files under directory
- var inputDirectory = dirname(input),
- inputGlob = basename(input),
- after,
- outputString;
- // process input
- glob(inputGlob, { cwd: inputDirectory }, function (error, files) {
- async.eachSeries(files, function (file, eachCallback) {
- // only process files; other types such as directories or links are ignored
- fs.stat(inputDirectory + '/' + file, function (error, stats) {
- if(stats.isFile()) {
- // read file
- fs.readFile(inputDirectory + '/' + file, 'utf8', function (error, before) {
- // process the html
- after = typogr.typogrify(before);
- // write file
- if(output === '/dev/stdout') // writeFile doesn't like /dev/stdout even though readFile works with /dev/stdin
- console.log(after);
- else {
- if(files.length > 1) {
- // multiple input files means we are dealing with a directory or a glob,
- // so make sure directory exists
- mkdirp.sync(output + '/' + dirname(file));
- outputString = path.normalize(output + '/' + file);
- }
- else // one input file means we are only writing one file
- outputString = output;
- if(force) {
- fs.writeFile(outputString, after, function (error) {
- eachCallback(error);
- });
- }
- else {
- confirmOverwrite(outputString, function (ok) {
- if(ok)
- fs.writeFile(outputString, after, function (error) {
- eachCallback(error);
- });
- });
- }
- }
- });
- }
- else
- eachCallback(null);
- });
- }, function (error) {
- if(error) throw error;
- });
- });
- }
- function confirmOverwrite(fileName, callback) {
- fs.stat(fileName, function(error, stats) {
- if(stats) {
- if(stats.isFile()) {
- commander.confirm('Confirm: overwrite file (' + fileName + ')? ', function(ok) {
- // work around bug in commander.js
- // see (https://github.com/visionmedia/commander.js/issues/109)
- // also see (https://github.com/visionmedia/commander.js/pull/133)
- process.stdin.pause();
- if(ok)
- callback(true);
- else {
- console.log(" Cancelling action, file wasn't modified.");
- callback(false);
- }
- });
- }
- else {
- // fileName is not of type 'file' (close our eyes and assume it's a directory)
- callback(true);
- }
- }
- else {
- // fileName doesn't exist
- callback(true);
- }
- });
- }
- function main() {
- // specify cli options
- commander
- .version('0.6.8')
- .usage('[options] [input] [output]')
- .option('-i, --inplace', 'Use single path as both input and output')
- .option('-f, --force', 'Do not prompt to verify file overwrites');
- // specify example help text
- commander.on('--help', function() {
- console.log(' reads input from stdin, individual files, directories, or globs');
- console.log(' writes ouput to stdout, individual files, or directories');
- console.log('');
- console.log(' Examples:');
- console.log('');
- console.log(' $ typogr inputFile.html outputFile.html');
- console.log(' $ typogr < inputFile.html > outputFile.html');
- console.log(' $ typogr -i singleFile.html');
- console.log(' $ typogr inputDirectory outputDirectory');
- console.log(' $ typogr inputDirectory/*.html outputDirectory');
- console.log('');
- });
- // parse arguments and generate object mappings in the *commander* object
- commander.parse(process.argv);
- switch (commander.args.length) {
- case 0:
- // get input from stdin and send output to stdout
- readRenderWrite('/dev/stdin', '/dev/stdout');
- break;
- case 1:
- if (commander.inplace) {
- // modify the file in place
- readRenderWrite(commander.args[0], commander.args[0], commander.force);
- }
- else {
- // get input from file specified and send output to stdout
- readRenderWrite(commander.args[0], '/dev/stdout');
- }
- break;
- case 2:
- // get input from first parameter and send output to second parameter
- readRenderWrite(commander.args[0], commander.args[1], commander.force);
- break;
- }
- }
- module.exports.main = main;
|