-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathcli.js
172 lines (153 loc) · 5.35 KB
/
cli.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/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;