1 | #!/usr/bin/env node
|
2 | var CoffeeScript, CookieParser, Generate, about, build, buildAutoImport, buildProduction, capitalizeFirstLetter, clean, colors, compileFile, create, deleteFolderRecursive, dirCheck, fs, getDirectories, indent, launch, makeID, mkdirp, openurl, path, program, prompt, reload, reloadServer, reorderFiles, restify, uglify, walk, watch, watcher;
|
3 |
|
4 | console.error = function() {};
|
5 |
|
6 | prompt = require('prompt');
|
7 |
|
8 | program = require('commander');
|
9 |
|
10 | colors = require('colors');
|
11 |
|
12 | fs = require('fs-extra');
|
13 |
|
14 | walk = require('walk');
|
15 |
|
16 | path = require('path');
|
17 |
|
18 | watcher = require('node-watch');
|
19 |
|
20 | Generate = require('./lib/Generate');
|
21 |
|
22 | CoffeeScript = require('coffee-script');
|
23 |
|
24 | uglify = require('uglify-js');
|
25 |
|
26 | restify = require('restify');
|
27 |
|
28 | CookieParser = require('restify-cookies');
|
29 |
|
30 | mkdirp = require('mkdirp');
|
31 |
|
32 | openurl = require('openurl');
|
33 |
|
34 | reload = require('reload');
|
35 |
|
36 | prompt.message = 'MagiX';
|
37 |
|
38 | reloadServer = void 0;
|
39 |
|
40 | Array.prototype.move = function(old_index, new_index) {
|
41 | var k;
|
42 | if (new_index >= this.length) {
|
43 | k = new_index - this.length;
|
44 | while (k-- + 1) {
|
45 | this.push(void 0);
|
46 | }
|
47 | }
|
48 | this.splice(new_index, 0, this.splice(old_index, 1)[0]);
|
49 | return this;
|
50 | };
|
51 |
|
52 | reorderFiles = function(files) {
|
53 | var id, index, item, item2, new_files, no_match, _i, _len;
|
54 | new_files = JSON.parse(JSON.stringify(files));
|
55 | no_match = [];
|
56 | for (item in files) {
|
57 | index = -1;
|
58 | for (item2 in new_files) {
|
59 | if (new_files[item2].name === files[item]["extends"]) {
|
60 | index = item2;
|
61 | }
|
62 | }
|
63 | if (index > -1) {
|
64 | if (index > item) {
|
65 | new_files = new_files.move(index, item);
|
66 | }
|
67 | } else {
|
68 | no_match.push(files[item].id);
|
69 | }
|
70 | }
|
71 | for (_i = 0, _len = no_match.length; _i < _len; _i++) {
|
72 | id = no_match[_i];
|
73 | if (id !== void 0) {
|
74 | for (item in new_files) {
|
75 | if (new_files[item].id === id) {
|
76 | new_files.move(item, 0);
|
77 | }
|
78 | }
|
79 | }
|
80 | }
|
81 | return new_files;
|
82 | };
|
83 |
|
84 | capitalizeFirstLetter = function(string) {
|
85 | return string.charAt(0).toUpperCase() + string.slice(1);
|
86 | };
|
87 |
|
88 | getDirectories = function(srcpath) {
|
89 | return fs.readdirSync(srcpath).filter(function(file) {
|
90 | return fs.statSync(path.join(srcpath, file)).isDirectory();
|
91 | });
|
92 | };
|
93 |
|
94 | indent = function(str, numOfIndents, opt_spacesPerIndent) {
|
95 | str = str.replace(/^(?=.)/gm, new Array(numOfIndents + 1).join('\t'));
|
96 | numOfIndents = new Array(opt_spacesPerIndent + 1 || 0).join(' ');
|
97 | if (opt_spacesPerIndent) {
|
98 | return str.replace(/^\t+/g, (function(tabs) {
|
99 | return tabs.replace(/./g, numOfIndents);
|
100 | }));
|
101 | } else {
|
102 | return str;
|
103 | }
|
104 | };
|
105 |
|
106 | deleteFolderRecursive = function(path) {
|
107 | if (fs.existsSync(path)) {
|
108 | fs.readdirSync(path).forEach(function(file, index) {
|
109 | var curPath;
|
110 | curPath = path + '/' + file;
|
111 | if (fs.lstatSync(curPath).isDirectory()) {
|
112 | deleteFolderRecursive(curPath);
|
113 | } else {
|
114 | fs.unlinkSync(curPath);
|
115 | }
|
116 | });
|
117 | fs.rmdirSync(path);
|
118 | }
|
119 | };
|
120 |
|
121 | makeID = function() {
|
122 | var i, possible, text;
|
123 | text = '';
|
124 | possible = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
125 | i = 0;
|
126 | while (i < 8) {
|
127 | text += possible.charAt(Math.floor(Math.random() * possible.length));
|
128 | i++;
|
129 | }
|
130 | return text;
|
131 | };
|
132 |
|
133 | about = function() {
|
134 | console.log('\n');
|
135 | console.log(' d8bY88b d88P ');
|
136 | console.log(' Y8P Y88b d88P ');
|
137 | console.log(' Y88o88P ');
|
138 | console.log('88888b.d88b. 8888b. .d88b. 888 Y888P ');
|
139 | console.log('888 "888 "88b "88bd88P"88b888 d888b ');
|
140 | console.log('888 888 888.d888888888 888888 d88888b ');
|
141 | console.log('888 888 888888 888Y88b 888888 d88P Y88b ');
|
142 | console.log('888 888 888"Y888888 "Y88888888d88P Y88b ');
|
143 | console.log(' 888 ');
|
144 | console.log(' Y8b d88P ');
|
145 | console.log(' "Y88P" ');
|
146 | console.log('MagiX | magixjs.com'.green);
|
147 | console.log('Beyond magical.'.green);
|
148 | console.log('Created by Etienne Pinchon (@etiennepinchon)'.green);
|
149 | console.log('Copyright ©2016'.green);
|
150 | console.log('\n');
|
151 | console.log('Usage:'.green);
|
152 | console.log('* create [name] | Create a new project.');
|
153 | console.log('* launch [dir] [port] | Create a new project.');
|
154 | console.log('* build [dir] [env] | Build a project.');
|
155 | console.log('* clean [dir] | Clear the build of a project.');
|
156 | console.log('* watch [dir] | Observe change on a project and compile on the fly.');
|
157 | console.log('\n');
|
158 | };
|
159 |
|
160 | create = function(name) {
|
161 | var appCS, appJS, appNameCS, createCatalog, createIndexJS, createJSON, dirBuild, dirSources, dir_project, done, htmlContent;
|
162 | if (!name || !/^[a-zA-Z0-9\_\s\-]{1,100}$/.test(name)) {
|
163 | console.log('MagiX: [ERR] Name must be only letters, numbers, underscores, spaces or dashes.'.red);
|
164 | return;
|
165 | }
|
166 | dir_project = './' + name;
|
167 | if (!fs.existsSync(dir_project)) {
|
168 | fs.mkdirSync(dir_project);
|
169 | }
|
170 | appJS = Generate.JS();
|
171 | appCS = Generate.CS();
|
172 | done = function() {
|
173 | process.chdir(dir_project);
|
174 | return console.log('MagiX: Project created successfully.'.green);
|
175 | };
|
176 | createJSON = function() {
|
177 | var packageFile;
|
178 | packageFile = {
|
179 | name: name,
|
180 | version: '0.1.0',
|
181 | description: '',
|
182 | tags: '',
|
183 | created_at: new Date
|
184 | };
|
185 | return fs.writeFile(dir_project + '/package.json', JSON.stringify(packageFile, null, 2), function(err) {
|
186 | if (err) {
|
187 | return console.log(err);
|
188 | }
|
189 | return done();
|
190 | });
|
191 | };
|
192 | createIndexJS = function() {
|
193 | var indexJS;
|
194 | indexJS = Generate.indexJS();
|
195 | return fs.writeFile(dir_project + '/build/index.js', indexJS, function(err) {
|
196 | if (err) {
|
197 | return console.log(err);
|
198 | }
|
199 | return createCatalog();
|
200 | });
|
201 | };
|
202 | createCatalog = function() {
|
203 | var catalog;
|
204 | catalog = Generate.catalog();
|
205 | return fs.writeFile(dir_project + '/build/catalog.js', catalog, function(err) {
|
206 | if (err) {
|
207 | return console.log(err);
|
208 | }
|
209 | return createJSON();
|
210 | });
|
211 | };
|
212 | dirBuild = dir_project + '/build';
|
213 | dirSources = dir_project + '/documents';
|
214 | if (!fs.existsSync(dir_project)) {
|
215 | fs.mkdirSync(dir_project);
|
216 | }
|
217 | if (!fs.existsSync(dirBuild)) {
|
218 | fs.mkdirSync(dirBuild);
|
219 | }
|
220 | if (!fs.existsSync(dirSources)) {
|
221 | fs.mkdirSync(dirSources);
|
222 | }
|
223 | htmlContent = Generate.HTML(name, '', '', false);
|
224 | appNameCS = '/App.coffee';
|
225 | appJS = Generate.appRunJS(indent(appJS, 1));
|
226 | fs.writeFile(dir_project + '/index.html', htmlContent, function(err) {
|
227 | if (err) {
|
228 | return console.log(err);
|
229 | }
|
230 | fs.writeFile(dirBuild + '/App.js', appJS, function(err) {
|
231 | if (err) {
|
232 | return console.log(err);
|
233 | }
|
234 | fs.writeFile(dirSources + appNameCS, appCS, function(err) {
|
235 | if (err) {
|
236 | return console.log(err);
|
237 | }
|
238 | createIndexJS();
|
239 | });
|
240 | });
|
241 | });
|
242 | };
|
243 |
|
244 | launch = function(dir, server_port, env) {
|
245 | var i, isProd, prod, server;
|
246 | prod = ['production', 'prod', 'p'];
|
247 | isProd = false;
|
248 | if (!env) {
|
249 | if (prod.indexOf(dir) > -1) {
|
250 | isProd = true;
|
251 | dir = void 0;
|
252 | } else if (prod.indexOf(server_port) > -1) {
|
253 | isProd = true;
|
254 | server_port = void 0;
|
255 | }
|
256 | } else {
|
257 | if (prod.indexOf(env) > -1) {
|
258 | isProd = true;
|
259 | }
|
260 | }
|
261 | if (!dir) {
|
262 | dir = void 0;
|
263 | }
|
264 | i = parseInt(dir);
|
265 | if (Number.isInteger(i) && i > 0) {
|
266 | server_port = dir;
|
267 | dir = void 0;
|
268 | }
|
269 | if (!dir) {
|
270 | dir = process.cwd();
|
271 | }
|
272 | if (!fs.existsSync(dir)) {
|
273 | console.log('MagiX: [ERR] Given folder does not exist.'.red);
|
274 | return;
|
275 | }
|
276 | if (dir.endsWith('/')) {
|
277 | dir = dir.slice(0, -1);
|
278 | }
|
279 | if (!server_port) {
|
280 | server_port = 9000;
|
281 | }
|
282 | server = restify.createServer({
|
283 | name: 'server',
|
284 | version: '1.0.0'
|
285 | });
|
286 | server.use(restify.acceptParser(server.acceptable));
|
287 | server.use(restify.queryParser());
|
288 | server.use(restify.bodyParser());
|
289 | server.use(CookieParser.parse);
|
290 | server.use(restify.gzipResponse());
|
291 | server.get(/^\/build\/?.*/, restify.serveStatic({
|
292 | directory: dir
|
293 | }));
|
294 | server.get(/^\/documents\/?.*/, restify.serveStatic({
|
295 | directory: dir
|
296 | }));
|
297 | server.get(/\/?/, function(req, res, next) {
|
298 | res.writeHead(200);
|
299 | fs.createReadStream(dir + '/index.html').pipe(res);
|
300 | return next();
|
301 | });
|
302 | if (!isProd) {
|
303 | reloadServer = reload(server, server, false);
|
304 | }
|
305 | server.__port = server_port;
|
306 | server.start = function(message) {
|
307 | return server.listen(server.__port, 'localhost', function() {
|
308 | var url;
|
309 | if (message) {
|
310 | url = server.url.replace('127.0.0.1', 'localhost');
|
311 | if (!isProd) {
|
312 | console.log(('MagiX: Project launched! Running! Address ' + url).green);
|
313 | openurl.open(url);
|
314 | } else {
|
315 | console.log(('MagiX: Project launched in Production mode! Running! Address ' + url).green);
|
316 | }
|
317 | }
|
318 | });
|
319 | };
|
320 | server.start(true);
|
321 | if (!isProd) {
|
322 | if (fs.existsSync(dir + '/documents')) {
|
323 | return watch(dir, server);
|
324 | }
|
325 | }
|
326 | };
|
327 |
|
328 | build = function(dir, env) {
|
329 | var files, isProd, prod, startA, walker;
|
330 | prod = ['production', 'prod', 'p'];
|
331 | isProd = false;
|
332 | if (!env) {
|
333 | if (prod.indexOf(dir) > -1) {
|
334 | isProd = true;
|
335 | dir = void 0;
|
336 | }
|
337 | } else {
|
338 | if (prod.indexOf(env) > -1) {
|
339 | isProd = true;
|
340 | }
|
341 | }
|
342 | if (!dir) {
|
343 | dir = '.';
|
344 | }
|
345 | if (!dirCheck(dir)) {
|
346 | return;
|
347 | }
|
348 | files = [];
|
349 | startA = +new Date();
|
350 | walker = walk.walk(dir + '/documents', {
|
351 | followLinks: false
|
352 | });
|
353 | walker.on('file', function(root, stat, next) {
|
354 | var file, file_build, filename, name;
|
355 | filename = stat.name;
|
356 | if (filename.endsWith('.coffee')) {
|
357 | files.push(root + '/' + filename);
|
358 | name = filename.split('/');
|
359 | name = name[name.length - 1];
|
360 | name = name.replace('.coffee', '');
|
361 | compileFile(name, root, next);
|
362 | } else if (filename && (filename.endsWith('.js') || filename.endsWith('.css'))) {
|
363 | file = root + '/' + filename;
|
364 | file_build = file.replace('documents', 'build');
|
365 | files.push(file);
|
366 | console.log(('MagiX: Copy ' + filename).magenta);
|
367 | fs.copy(file, file_build, function(err) {
|
368 | if (err) {
|
369 | return console.error(err);
|
370 | }
|
371 | return next();
|
372 | });
|
373 | } else {
|
374 | next();
|
375 | }
|
376 | });
|
377 | return walker.on('end', function() {
|
378 | var endA;
|
379 | buildAutoImport(dir);
|
380 | endA = +new Date();
|
381 | console.log(("MagiX: Done: " + files.length + " files built in " + (endA - startA) + " ms.").green);
|
382 | if (isProd) {
|
383 | buildProduction(dir);
|
384 | }
|
385 | });
|
386 | };
|
387 |
|
388 | watch = function(dir, server) {
|
389 | if (!dir) {
|
390 | dir = '.';
|
391 | }
|
392 | if (!dirCheck(dir)) {
|
393 | return;
|
394 | }
|
395 | console.log('MagiX: Now observing changes in your project..'.green);
|
396 | return watcher(dir + '/documents', function(filename) {
|
397 | var file_build, name;
|
398 | if (reloadServer) {
|
399 | reloadServer.reload();
|
400 | }
|
401 | if (filename && filename.endsWith('.coffee')) {
|
402 | name = filename.split('/');
|
403 | name = name[name.length - 1];
|
404 | name = name.replace('.coffee', '');
|
405 | path = filename.split('/');
|
406 | path.pop();
|
407 | path = path.join('/');
|
408 | if (fs.existsSync(filename)) {
|
409 | compileFile(name, path, void 0, true);
|
410 | buildAutoImport(dir);
|
411 | }
|
412 | } else if (filename && (filename.endsWith('.js') || filename.endsWith('.css'))) {
|
413 | name = filename.split('/');
|
414 | name = name[name.length - 1];
|
415 | file_build = filename.replace('documents', 'build');
|
416 | if (fs.existsSync(filename)) {
|
417 | console.log(('MagiX: Updating ' + name).magenta);
|
418 | fs.copy(filename, file_build, function(err) {
|
419 | if (err) {
|
420 | return console.error(err);
|
421 | }
|
422 | });
|
423 | } else if (fs.existsSync(file_build)) {
|
424 | name = file_build.split('/');
|
425 | name = name[name.length - 1];
|
426 | console.log(('MagiX: Removing ' + name).magenta);
|
427 | fs.unlink(file_build, function(err) {
|
428 | if (err) {
|
429 | return console.log(err);
|
430 | }
|
431 | });
|
432 | }
|
433 | }
|
434 | if (server && server.close) {
|
435 | server.close();
|
436 | server.start(false);
|
437 | }
|
438 | });
|
439 | };
|
440 |
|
441 | clean = function(dir) {
|
442 | var pathBuild;
|
443 | if (!dir) {
|
444 | dir = '.';
|
445 | }
|
446 | if (!dirCheck(dir)) {
|
447 | return;
|
448 | }
|
449 | console.log('MagiX: Cleaning..'.magenta);
|
450 | pathBuild = dir + '/build';
|
451 | deleteFolderRecursive(pathBuild);
|
452 | build(dir);
|
453 | console.log("MagiX: Done: build cleaned.".green);
|
454 | };
|
455 |
|
456 | dirCheck = function(dir) {
|
457 | var dirBuild, dir_build_check, dir_documents_check, directories, directory, _i, _len;
|
458 | if (!dir) {
|
459 | dir = '.';
|
460 | }
|
461 | dir_build_check = false;
|
462 | dir_documents_check = false;
|
463 | if (!fs.existsSync(dir)) {
|
464 | console.log('MagiX: [ERR] Given folder does not exist.'.red);
|
465 | return;
|
466 | }
|
467 | directories = getDirectories(dir);
|
468 | for (_i = 0, _len = directories.length; _i < _len; _i++) {
|
469 | directory = directories[_i];
|
470 | if (directory === 'build') {
|
471 | dir_build_check = true;
|
472 | } else if (directory === 'documents') {
|
473 | dir_documents_check = true;
|
474 | }
|
475 | }
|
476 | if (!dir_build_check || !dir_documents_check) {
|
477 | if (!dir_build_check && !dir_documents_check) {
|
478 | console.log('MagiX: [ERR] Cannot find the "documents" directory.'.red);
|
479 | console.log('MagiX: [HELP] Are you sure you are in the right folder? (cd magix-yourProjectName ;) ).'.magenta);
|
480 | } else {
|
481 | if (!dir_build_check) {
|
482 | dirBuild = __dirname + '/build';
|
483 | if (!fs.existsSync(dirBuild)) {
|
484 | fs.mkdirSync(dirBuild);
|
485 | }
|
486 | return true;
|
487 | }
|
488 | if (!dir_documents_check) {
|
489 | console.log('MagiX: [ERR] Cannot find the "documents" directory.'.red);
|
490 | }
|
491 | }
|
492 | return false;
|
493 | }
|
494 | return true;
|
495 | };
|
496 |
|
497 | compileFile = function(name, dir, next, notification) {
|
498 | console.log(('MagiX: Processing ' + name + ' ..').magenta);
|
499 | return fs.readFile(dir + '/' + name + '.coffee', 'utf8', function(err, data) {
|
500 | var addClass, classFile, classes, contentCopy, convert_error, converted, dirBuild, file, nextStep;
|
501 | if (err) {
|
502 | return console.log(err);
|
503 | }
|
504 | contentCopy = data;
|
505 | file = {};
|
506 | if (name !== 'App') {
|
507 | if (/(Extends )\w+[ ]*\n/.test(contentCopy)) {
|
508 | contentCopy = contentCopy.replace(/(Extends )\w+[ ]*\n/, function(match) {
|
509 | file.type = match.replace('Extends ', '');
|
510 | file.type = file.type.replace(/[ ]*\n/, '');
|
511 | return '';
|
512 | });
|
513 | if (/(Kind )([-a-zA-Z0-9])*\n/.test(contentCopy)) {
|
514 | contentCopy = params.contentCopy.replace(/(Kind )([-a-zA-Z0-9])*\n/, function(match) {
|
515 | file.kind = match.replace('Kind ', '');
|
516 | file.kind = file.kind.replace(/\n/, '');
|
517 | return '';
|
518 | });
|
519 | }
|
520 | if (/(Element )([-a-zA-Z0-9])*\n/.test(contentCopy)) {
|
521 | contentCopy = contentCopy.replace(/(Element )([-a-zA-Z0-9])*\n/, function(match) {
|
522 | file.element = match.replace('Element ', '');
|
523 | file.element = file.element.replace(/\n/, '');
|
524 | return '';
|
525 | });
|
526 | }
|
527 | addClass = true;
|
528 | contentCopy = indent(contentCopy, 2);
|
529 | classes = ['Page', 'View', 'Text', 'Button', 'Link', 'CheckBox', 'Dropdown', 'RadioButton', 'Image', 'List', 'ListItem', 'TextInput', 'SpeechRecognition', 'Say', 'FileInput', 'Player', 'Slider', 'ProgressBar', 'Canvas', 'WebView'];
|
530 | if (classes.indexOf(file.type) > -1) {
|
531 | classFile = 'class ' + name + ' extends ' + file.type + '\n\t';
|
532 | if (file.kind) {
|
533 | classFile += '_kind : "' + file.kind + '"\n\t';
|
534 | }
|
535 | if (file.element) {
|
536 | classFile += '_elementType : "' + file.element + '"\n\t';
|
537 | }
|
538 | classFile += 'constructor: (options) ->\n\t\tsuper\n' + contentCopy + '\n\t\tif not @_didAppear and @parent and @didAppear\n\t\t\t@_didAppear = true\n\t\t\t@didAppear(@__options)';
|
539 | } else {
|
540 | if (file.type === 'None') {
|
541 | classFile = "class " + name + "\n\t";
|
542 | if (file.kind) {
|
543 | classFile += '_kind : "' + file.kind + '"\n\t';
|
544 | }
|
545 | if (file.element) {
|
546 | classFile += '_elementType : "' + file.element + '"\n\t';
|
547 | }
|
548 | classFile += "constructor: (options) ->\n\t\tsuper\n" + contentCopy;
|
549 | } else {
|
550 | classFile = 'class ' + name + ' extends ' + file.type + '\n\t';
|
551 | if (file.kind) {
|
552 | classFile += '_kind : "' + file.kind + '"\n\t';
|
553 | }
|
554 | if (file.element) {
|
555 | classFile += '_elementType : "' + file.element + '"\n\t';
|
556 | }
|
557 | classFile += 'constructor: (options) ->\n\t\tsuper\n' + contentCopy + '\n\t\tif not @_didAppear and @parent and @didAppear\n\t\t\t@_didAppear = true\n\t\t\t@didAppear(@__options)';
|
558 | }
|
559 | }
|
560 | } else if (/(class)\s+\w+\s+(extends)\s+\w+/.test(contentCopy)) {
|
561 | file.element = contentCopy.match(/(class)\s+\w+\s+(extends)\s+\w+/)[0].replace(/(class)\s+\w+\s+(extends)\s+/, '');
|
562 | classFile = contentCopy;
|
563 | } else {
|
564 | classFile = contentCopy;
|
565 | }
|
566 | } else {
|
567 | classFile = contentCopy;
|
568 | }
|
569 | converted = null;
|
570 | try {
|
571 | converted = CoffeeScript.compile(classFile, {
|
572 | 'bare': true
|
573 | });
|
574 | } catch (_error) {
|
575 | err = _error;
|
576 | convert_error = err;
|
577 | }
|
578 | dirBuild = dir.replace('documents', 'build');
|
579 | nextStep = function() {
|
580 | var convertedFinal, error, filePathBuild, lines_info, notifier;
|
581 | filePathBuild = dirBuild + '/' + name + '.js';
|
582 | if (converted) {
|
583 | if (name === 'App') {
|
584 | convertedFinal = Generate.appRunJS(indent(converted, 1));
|
585 | } else {
|
586 | convertedFinal = converted;
|
587 | }
|
588 | return fs.writeFile(filePathBuild, convertedFinal, function(err) {
|
589 | console.log('MagiX: ↳ success'.green);
|
590 | if (next) {
|
591 | return next();
|
592 | }
|
593 | });
|
594 | } else {
|
595 | lines_info = String(convert_error).replace('[stdin]:', '').split(':');
|
596 | error = capitalizeFirstLetter("" + convert_error.message + " at line " + lines_info[0] + " column " + lines_info[1]);
|
597 | console.log(("MagiX: ↳ " + error).red);
|
598 | if (notification) {
|
599 | notifier = require('node-notifier');
|
600 | path = require('path');
|
601 | return notifier.notify({
|
602 | title: 'MagiX | Error on ' + name,
|
603 | message: error,
|
604 | icon: path.join(__dirname, 'images/icon.png'),
|
605 | sound: false,
|
606 | wait: false
|
607 | }, function(err, response) {});
|
608 | }
|
609 | }
|
610 | };
|
611 | if (!fs.existsSync(dirBuild)) {
|
612 | return mkdirp(dirBuild, function(err) {
|
613 | if (err) {
|
614 | return console.error(err);
|
615 | } else {
|
616 | return nextStep();
|
617 | }
|
618 | });
|
619 | } else {
|
620 | return nextStep();
|
621 | }
|
622 | });
|
623 | };
|
624 |
|
625 | buildAutoImport = function(dir) {
|
626 | var autoImport, catalog, documents, walker;
|
627 | autoImport = [];
|
628 | catalog = [];
|
629 | documents = [];
|
630 | walker = walk.walk(dir + '/documents', {
|
631 | followLinks: false
|
632 | });
|
633 | walker.on('file', function(root, stat, next) {
|
634 | var doc;
|
635 | if (stat.name.endsWith('.coffee')) {
|
636 | doc = {};
|
637 | doc.name = stat.name.split('/');
|
638 | doc.name = doc.name[doc.name.length - 1];
|
639 | doc.name = doc.name.replace('.coffee', '');
|
640 | fs.readFile(root + '/' + doc.name + '.coffee', 'utf8', function(err, data) {
|
641 | if (err) {
|
642 | return console.log(err);
|
643 | }
|
644 | if (data[0] !== '!') {
|
645 | root = root.substring(root.indexOf("/documents") + 1);
|
646 | path = '/' + root.replace('documents', 'build') + '/' + stat.name.replace('coffee', 'js');
|
647 | if (path !== '/build/App.js') {
|
648 | if (/(Element )([-a-zA-Z0-9])*\n/.test(data)) {
|
649 | doc["extends"] = data.match(/(Element )([-a-zA-Z0-9])*\n/)[0].replace('Element ', '');
|
650 | doc["extends"] = doc["extends"].replace(/\n/, '');
|
651 | } else if (/(class)\s+\w+\s+(extends)\s+\w+/.test(data)) {
|
652 | doc["extends"] = data.match(/(class)\s+\w+\s+(extends)\s+\w+/)[0].replace(/(class)\s+\w+\s+(extends)\s+/, '');
|
653 | } else {
|
654 | doc["extends"] = null;
|
655 | }
|
656 | doc.path = path;
|
657 | doc.id = makeID();
|
658 | documents.push(doc);
|
659 | }
|
660 | }
|
661 | return next();
|
662 | });
|
663 | } else if (stat.name.endsWith('.png') || stat.name.endsWith('.svg') || stat.name.endsWith('.jpg') || stat.name.endsWith('.jpeg') || stat.name.endsWith('.gif') || stat.name.endsWith('.webm') || stat.name.endsWith('.ogg') || stat.name.endsWith('.mpeg') || stat.name.endsWith('.mp3') || stat.name.endsWith('.wav') || stat.name.endsWith('.webm') || stat.name.endsWith('.mp4') || stat.name.endsWith('.ogg')) {
|
664 | catalog.push((root.substring(root.indexOf("/documents") + 1)).replace('documents/', '') + '/' + stat.name);
|
665 | next();
|
666 | } else {
|
667 | next();
|
668 | }
|
669 | });
|
670 | return walker.on('end', function() {
|
671 | var file, indexJS, _i, _len;
|
672 | documents = reorderFiles(documents);
|
673 | for (_i = 0, _len = documents.length; _i < _len; _i++) {
|
674 | file = documents[_i];
|
675 | autoImport.push(file.path);
|
676 | }
|
677 | autoImport.push('/build/App.js');
|
678 | indexJS = Generate.indexJS(JSON.stringify(autoImport));
|
679 | fs.writeFile(dir + '/build/index.js', indexJS, function(err) {
|
680 | if (err) {
|
681 | return console.log(err);
|
682 | }
|
683 | return fs.writeFile(dir + '/build/catalog.js', Generate.catalog(catalog), function(err) {
|
684 | if (err) {
|
685 | return console.log(err);
|
686 | }
|
687 | });
|
688 | });
|
689 | });
|
690 | };
|
691 |
|
692 | buildProduction = function(dir) {
|
693 | var cleaning, config, dirName, files, folder, magixJSON, minify, paths_to_remove, prodFolder, scriptID;
|
694 | if (!dir) {
|
695 | dir = process.cwd();
|
696 | }
|
697 | dirName = dir.split('/');
|
698 | dirName = dirName[dirName.length - 1];
|
699 | files = [];
|
700 | folder = path.dirname(dir) + '/' + dirName;
|
701 | paths_to_remove = [];
|
702 | magixJSON = fs.readFileSync(folder + '/package.json', 'utf8');
|
703 | config = JSON.parse(magixJSON);
|
704 | if (!config.name) {
|
705 | console.log('MagiX: [ERR] Invalid JSON project file, name missing.'.red);
|
706 | return;
|
707 | }
|
708 | prodFolder = folder + ("/../magix-" + config.name + "-production");
|
709 | scriptID = makeID();
|
710 | if (!fs.existsSync(prodFolder)) {
|
711 | console.log('MagiX: Cloning working project..'.magenta);
|
712 | fs.mkdirSync(prodFolder);
|
713 | }
|
714 | if (fs.existsSync(prodFolder + '/build')) {
|
715 | deleteFolderRecursive(prodFolder + '/build');
|
716 | }
|
717 | fs.copy(folder, prodFolder, function(err) {
|
718 | if (err) {
|
719 | return console.error(err);
|
720 | }
|
721 | console.log(('MagiX: Production path: ' + prodFolder).green);
|
722 | fs.writeFile(prodFolder + '/build/index.js', Generate.indexJS(JSON.stringify('/build/' + scriptID + '.js')), function(err) {
|
723 | if (err) {
|
724 | return console.log(err);
|
725 | }
|
726 | minify();
|
727 | });
|
728 | });
|
729 | minify = function() {
|
730 | var walker;
|
731 | walker = walk.walk(prodFolder + '/documents', {
|
732 | followLinks: false
|
733 | });
|
734 | walker.on('file', function(root, stat, next) {
|
735 | var name;
|
736 | name = stat.name.split('/');
|
737 | name = name[name.length - 1];
|
738 | if (stat.name.endsWith('.DS_Store')) {
|
739 | fs.unlinkSync(root + '/' + stat.name);
|
740 | }
|
741 | if (stat.name.endsWith('.coffee') || stat.name.endsWith('.js') || stat.name.endsWith('.css')) {
|
742 | name = name.replace('.coffee', '').replace('.js', '').replace('.css', '');
|
743 | if (name !== 'App') {
|
744 | paths_to_remove.push(root + '/' + stat.name);
|
745 | }
|
746 | }
|
747 | if (stat.name.endsWith('.coffee')) {
|
748 | name = name.replace('.coffee', '');
|
749 | fs.readFile(root + '/' + name + '.coffee', 'utf8', function(err, data) {
|
750 | var uglified;
|
751 | if (err) {
|
752 | return console.log(err);
|
753 | }
|
754 | path = root.replace('documents', 'build') + '/' + stat.name.replace('coffee', 'js');
|
755 | if (data[0] !== '!') {
|
756 | if (path !== prodFolder + '/build/App.js') {
|
757 | files.push(path);
|
758 | return next();
|
759 | } else {
|
760 | return next();
|
761 | }
|
762 | } else {
|
763 | uglified = uglify.minify([path]).code;
|
764 | return fs.writeFile(path, uglified, 'utf8', function(err) {
|
765 | if (err) {
|
766 | return console.log(err);
|
767 | }
|
768 | return next();
|
769 | });
|
770 | }
|
771 | });
|
772 | } else {
|
773 | next();
|
774 | }
|
775 | });
|
776 | return walker.on('end', function() {
|
777 | var appPath, uglified;
|
778 | files.push(prodFolder + '/build/App.js');
|
779 | uglified = '/* Made with MagiX (magixjs.com) and a smile :) */ ' + uglify.minify(files).code;
|
780 | console.log('MagiX: Minify script..'.magenta);
|
781 | appPath = prodFolder + '/build/' + scriptID + '.js';
|
782 | fs.writeFile(appPath, uglified, function(err) {
|
783 | console.log('MagiX: Cleaning..'.magenta);
|
784 | return cleaning(function() {
|
785 | return console.log("MagiX: Done: project built for production.".green);
|
786 | });
|
787 | });
|
788 | });
|
789 | };
|
790 | return cleaning = function(cb) {
|
791 | var cleanEmptyFoldersRecursively, e, item, _i, _len;
|
792 | paths_to_remove = paths_to_remove.concat(files);
|
793 | try {
|
794 | for (_i = 0, _len = paths_to_remove.length; _i < _len; _i++) {
|
795 | item = paths_to_remove[_i];
|
796 | if (fs.existsSync(item)) {
|
797 | fs.unlinkSync(item);
|
798 | }
|
799 | }
|
800 | } catch (_error) {
|
801 | e = _error;
|
802 | console.log(e);
|
803 | }
|
804 | cleanEmptyFoldersRecursively = function(folder) {
|
805 | var isDir;
|
806 | fs = require('fs');
|
807 | path = require('path');
|
808 | isDir = fs.statSync(folder).isDirectory();
|
809 | if (!isDir) {
|
810 | return;
|
811 | }
|
812 | files = fs.readdirSync(folder);
|
813 | if (files.length > 0) {
|
814 | files.forEach(function(file) {
|
815 | var fullPath;
|
816 | fullPath = path.join(folder, file);
|
817 | cleanEmptyFoldersRecursively(fullPath);
|
818 | });
|
819 | files = fs.readdirSync(folder);
|
820 | }
|
821 | if (files.length === 0) {
|
822 | console.log(('MagiX: removing: ' + folder).magenta);
|
823 | fs.rmdirSync(folder);
|
824 | return;
|
825 | }
|
826 | };
|
827 | cleanEmptyFoldersRecursively(prodFolder + '/documents/');
|
828 | cleanEmptyFoldersRecursively(prodFolder + '/build/');
|
829 | if (cb) {
|
830 | return cb();
|
831 | }
|
832 | };
|
833 | };
|
834 |
|
835 | program.command('about', {
|
836 | isDefault: true
|
837 | }).description('About magiX.').action(about);
|
838 |
|
839 | program.command('create [name]').description('Create a new project.').action(create);
|
840 |
|
841 | program.command('launch [dir] [port] [env]').description('Launch a local server to help you code an magix project.').action(launch);
|
842 |
|
843 |
|
844 |
|
845 |
|
846 |
|
847 |
|
848 |
|
849 |
|
850 |
|
851 |
|
852 |
|
853 |
|
854 |
|
855 | program.command('build [dir] [env]').description('Build a project.').action(build);
|
856 |
|
857 | program.command('clean [dir]').description('Clear the build of a project.').action(clean);
|
858 |
|
859 | program.command('watch [dir]').description('Observe change on a project and compile on the fly.').action(watch);
|
860 |
|
861 | program.parse(process.argv);
|