-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
executable file
·339 lines (300 loc) · 13.2 KB
/
index.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#!/usr/bin/env node
// yesno makes command-line dialogs a lot simpler
var yesno = require('yesno');
// we require in the module that we created, docode.
var docode = require('./docode.js').docode;
// These variables are helpers for later on when we want to timestamp
var currentTime = new Date();
var timeStamp = "-" + (currentTime.getMonth()+1) + '-' + currentTime.getDate() + '-' + currentTime.getFullYear() + '-' + currentTime.getHours() + '-' + currentTime.getMinutes() + '-' + currentTime.getSeconds();
// More helper variables for accessing the path
var sketchFolder = process.cwd();
var docodeFolder = sketchFolder + "/docode";
// To get the sketchFolderName we have to pick apart the path by splitting it on the '/'
var _sketchPath = sketchFolder.split("/");
// We can find the sketch's folder name then by looking at the last member of the split
// we then append the timeStamp to make this sketch unique.
var sketchFolderName = _sketchPath[_sketchPath.length - 1] + timeStamp;
// pretty-prints the `message` and allows for an array of `additionals` which are treated as errors to be reported,.
function formattedOutput(message, additionals) {
var clc = require('cli-color');
if(message){
console.warn("-------------------------------------------------------------------");
console.warn(message);
}
if (additionals) {
console.warn("-------------------------------------------------------------------");
console.warn("| |");
console.warn("| The following arguments do not match doCode's command list: |");
console.warn("| |");
var icns = ["😫", "😱", "❌", "🙁", "🤕"];
var randomIcn = icns[Math.floor(icns.length * Math.random())];
console.warn("| " + randomIcn + " " + clc.red(additionals) + (" ".repeat(57 - additionals.length)) + "|");
console.warn("| |");
}
console.warn("-------------------------------------------------------------------");
}
// This function is used to find the default browser used by the operating system
function getDefaultBrowser (){
var browser;
switch(process.platform){
case 'darwin':
var execSync = require('child_process').execSync;
browser = execSync("grep 'https' -b3 ~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist | head -2 | tail -1;").toString().replace(/[0-9]+-.*<string>/, "").replace("</string>", "").trim();
// Then we return the string in a format that the `open` command will like
switch(browser){
case 'com.apple.safari':
return("Safari");
case 'com.google.chrome':
return('Google Chrome');
case 'com.mozilla.firefox':
return("Firefox");
}
break;
case 'freebsd':
console.log('Sorry, preview has not yet been implemented for freebsd.');
break;
case 'linux':
console.log('Sorry, preview has not yet been implemented for linux.');
break;
case 'sunos':
console.log('Sorry, preview has not yet been implemented for sunos.');
break;
case 'win32':
console.log('Sorry, preview has not yet been implemented for windows.');
break;
}
}
// Check if a file exists, run callback if it does and spit out some errors if it doesn't
// basically re-implements the fs.exists function which got deprecated from nod,e
function exists(filename, cb){
var fs = require('fs');
var clc = require('cli-color');
fs.stat(filename, function(err, stat) {
if(err == null) {
cb();
} else if(err.code == 'ENOENT') {
// ENOENT == it does not exist
var msg = " 🤔 Hmmm, it seems there's no `" + filename + "` here!";
var msg2 = " 🤔 Are you sure you're in a p5 sketch folder? ";
formattedOutput("|" + clc.cyanBright(msg) + (" ".repeat(65 - msg.length)) + " |");
formattedOutput("|" + clc.cyanBright(msg2) + (" ".repeat(63 - msg.length)) + " |");
process.exit();
} else {
console.warn('Some other error: ', err.code);
}
});
}
// message to output when creating documentation in one of the `outputType`s is successfu,l
function success(outputType){
var clc = require('cli-color');
// this is where we'll store the message to output
var msg;
// storing the differet success messages here
var gifMsg = " 🖼 👍 💯 Yay! The gif was created successfully";
var videoMsg = " 📽 👍 💯 Yay! The video was created successfully!";
var screenshotsMsg = " 🖼 👍 💯 Yay! The screenshots were created successfully!";
// setting the `msg` based upon the outputType
switch(outputType){
case 'gif':
msg = gifMsg;
break;
case 'video':
msg = videoMsg;
break;
case 'screenshots':
msg = screenshotsMsg;
break;
}
// outputting the formatted message using the msg as our text
formattedOutput("|" + clc.cyanBright(msg) + (" ".repeat(66 - msg.length)) + " |");
}
// Checks to see if commandName is available on the user's $PATH environment variable.
// If the command is not found, urlToCommandWebsite is provided to the user so they
// can download and install the dependency.
// example: checkDependency('ImageMagick', 'convert', 'https://www.imagemagick.org/script/download.php');
function checkDependency(dependencyName, commandName, urlToCommandWebsite) {
var clc = require('cli-color');
var exec = require('child_process').exec;
var isDependencyFound = exec("which " + commandName, function(err, res){
if(err){
var lineOne = '👉 Please make sure that you have ' + dependencyName + ' installed on you machine.';
var url = urlToCommandWebsite;
var lineTwo = ' To install ' + dependencyName + ' go to: ';
var repeat = 85 - lineTwo.length - url.length;
console.warn(clc.yellow("---------------------------------------------------------------------------------------"));
console.warn(clc.yellow("| ") + lineOne + (" ".repeat(86 - lineOne.length)) + clc.yellow("|"));
console.warn(clc.yellow("| ") + lineTwo + clc.cyan(url) + (" ".repeat(repeat)) + clc.yellow("|"));
console.warn(clc.yellow("---------------------------------------------------------------------------------------"));
}
});
}
// Make Functions
// These are the higher level functions that comprise the API of docode,
function makeScreenshots(numberOfScreenshots, interval, quiet){
var exec = require('child_process').exec;
// Ensure that docode and screenshots directory exist, delete and recreate the temp dir
exec("mkdir docode; rm -fr docode/_temp; mkdir docode/_temp; mkdir docode/screenshots;");
var target = docodeFolder + '/screenshots/' + timeStamp.slice(1) + '/' + sketchFolderName + '.png';
var source = sketchFolder + '/index.html';
if(!quiet){
console.warn("🎬 Generating " + numberOfScreenshots + " screenshots.");
}
// create screenshots in a timestamped folder
docode.renderScreenshots(numberOfScreenshots, source, target, interval);
var screenshotsFile = docodeFolder + '/screenshots/' + sketchFolderName + '/';
// delete the temp files
exec("rm -fr docode/_temp");
if(quiet){
console.log(screenshotsFile);
} else {
success("screenshots");
}
}
function makeGif(numberOfScreenshots, interval, quiet){
var exec = require('child_process').exec;
// Ensure that docode and gif directory exist, delete and recreate the temp dir
exec("mkdir docode; rm -fr docode/_temp; mkdir docode/_temp; mkdir docode/gif;");
if(!quiet){
console.warn("🎬 Generating animated gif.");
}
var gifsource = docodeFolder + '/_temp/*.png';
var target = docodeFolder + '/_temp/sketch.png';
var source = sketchFolder + '/index.html';
var gifTarget = docodeFolder+ '/gif/' + sketchFolderName + '.gif';
// create screenshots to use for making the gif
docode.renderScreenshots(numberOfScreenshots, source, target, interval);
// make the gif using the screenshots
docode.renderGif(sketchFolderName, gifsource, gifTarget, interval);
// delete the temp files
exec("rm -fr docode/_temp");
if(quiet){
// In quiet Mode, Only output the path to the new file
console.log(docodeFolder + '/gif/' + sketchFolderName + '.gif');
} else {
success("gif");
}
}
function makeVideo(length, interval, preview, quiet, pathToSketchIndexHtml, pathToVideoOutputFile){
var exec = require('child_process').exec;
exec("mkdir docode; rm -fr docode/_temp; mkdir docode/_temp; mkdir docode/video;");
if(!quiet){
console.warn("🎬 Generating video...");
}
var target = docodeFolder + '/_temp/sketch.png';
var videoSource = "'docode/_temp/*.png'";
var videoFile = pathToVideoOutputFile;
docode.renderScreenshots(length*24, pathToSketchIndexHtml, target, interval);
docode.renderVideo(sketchFolderName, videoSource, sketchFolderName, interval);
if(preview){
var open = require("open");
// Sets the default browser to something that is appropriate to pass to `open`
var defaultBrowser = docode.getDefaultBrowser();
success("video");
console.warn('🌎 Trying to preview the video using Google Chrome.');
open(videoFile, defaultBrowser);
} else {
if(quiet){
console.log(videoFile);
} else {
success("video");
}
}
exec("rm -fr docode/_temp");
}
// MAIN SECTION
// We need these, so we check for them and if not we help them to find them
checkDependency('ImageMagick', 'convert', 'https://www.imagemagick.org/script/download.php');
checkDependency('FFMpeg', 'ffmpeg', 'http://ffmpeg.org/download.html');
// yargonaut gives us a little more control over the styling of the CLI
var yargonaut = require('yargonaut')
.helpStyle('green')
.style('blue');
// Yargs is a very lightweight framework for creating command-line applications with Node
// Here is where we definte the structure of docode's user interface
var yargs = require('yargs')
.showHelpOnFail(false, "Specify --help for available options")
.usage('Usage: $0 <cmd> [options]\n\nAll parameters are optional.\n\nRunning `docode` without any parameters defaults to generating all forms of documentation (screenshots, gif, video).\n\nOptions in square brackets can be set from the command-line by putting a double-dash in front of the option name.\n\nExamples:\n`docode screenshots --total=20` => Creates 20 screenshots with all other settings using the defaults.\n`docode video --length=5 --preview` => Creates a 5 second mp4 and opens the new video when finished.\n\nFor more information about these options, refer to the README')
.command('screenshots [total] [interval] [quiet]', 'generate screenshots.', {
total: {
default: 100
},
quiet: {
default: false
},
interval: {
default: 6
}
}, function(argv){
exists('index.html', function() {
makeScreenshots(argv.total, argv.interval, argv.quiet);
});
})
.command('gif [frames] [interval] [quiet]', 'generates an animated gif', {
frames: {
default: 100
},
quiet: {
default: false
},
interval: {
default: 2
}
}, function(argv){
exists('index.html', function() {
makeGif(argv.frames, argv.interval, argv.quiet);
});
})
.command('video [length] [interval] [preview] [quiet] [input] [output]',
'generates an mp4 video of the sketch.', {
lengthInSeconds: {
default: 10
},
quiet: {
default: false
},
interval: {
default: 5
},
preview: {
default: false
},
input: {
default: sketchFolder + '/index.html'
},
output: {
default: docodeFolder + '/video/' + sketchFolderName + '.mp4'
}
}, function(argv){
exists('index.html', function() {
makeVideo(argv.lengthInSeconds, argv.interval, argv.preview, argv.quiet, argv.input, argv.output);
});
})
.command('clean', 'Removes all docode files from sketch.', {}, function(argv){
var exec = require('child_process').exec;
exists('docode', function() {
yesno.ask('Are you sure you want to delete all docode files for this sketch?', true, function(ok) {
if(ok) {
console.warn("docode folder deleted.");
exec("rm -fr docode");
process.exit();
} else {
console.warn("Keeping docode folder.");
process.exit();
}
});
});
})
.help('help');
// Wrap text at the max width for the current terminal
yargs.wrap(yargs.terminalWidth());
var cmd = yargs.argv._[0];
// If no arguments are provided, generated all forms of documentation using the defaults.
if(yargs.argv._.length === 0){
exists('index.html', function() {
makeScreenshots(100, 6, false);
makeGif(100, 20, false);
makeVideo(10, 5, false, false, docodeFolder + '/video/' + sketchFolderName + '.mp4', sketchFolder + '/index.html');
});
} else if (cmd !== 'gif' && cmd !== 'video' && cmd !== 'clean' && cmd !== 'screenshots' && cmd !== 'help') {
formattedOutput(undefined,cmd);
}