UNPKG

asterx

Version:

Javascript continuos-passing-style callback transformations.

452 lines (429 loc) 15 kB
// Generated by CoffeeScript 1.10.0 (function() { var _, asterx, async, chokidar, coffeescript, commander, config, fs, fs_tools, info, log4js, path, stats, string, uglify; commander = require("commander"); fs = require("fs"); fs_tools = require("fs-tools"); path = require("path"); string = require("string"); async = require("async"); _ = require("lodash"); _.mixin(require("underscore.string").exports()); log4js = require("log4js"); coffeescript = require("coffee-script"); chokidar = require("chokidar"); uglify = require("uglify-js"); asterx = require("./asterx.js"); info = require("../package.json"); config = { input: "test", output: "bin/test", map: "", cache: "", watch: false, log: "DEBUG", callback_value: "!!", callback_error_value: "!!!", inject_try_catch: true, compression: false }; stats = { processed: 0, skipped: 0, failures: 0, successes: 0, started: null, ended: null, duration: 0 }; exports["info"] = function() { return { name: info.name, version: info.version, author: info.author, description: info.description, license: info.license, repository: info.repository.url, bugs: info.bugs.url }; }; exports["api"] = { transform: asterx.transform }; exports["setup"] = function(options) { var err, error, user_config, user_dir; try { user_dir = path.resolve(process.cwd()); if (fs.existsSync(user_dir + "\\asterx.json")) { user_config = fs.readFileSync(user_dir + "\\asterx.json", "utf8"); user_config = user_config.replace(/\/\*([\s\S]*?)\*\//igm, ""); user_config = user_config.replace(/\/\/.+/igm, ""); user_config = JSON.parse(user_config); config = _.merge(config, user_config); } } catch (error) { err = error; throw new Error + " asterx.json: " + err; } config = _.merge(config, options || {}); return log4js.configure({ appenders: [ { type: "logLevelFilter", level: config.log, appender: { type: "console", layout: { type: "pattern", pattern: "%[[%p]%] %m" } } } ] }); }; exports["run"] = function(input, done) { var args, logger, self; self = this; commander.version(this.info().version); commander.usage("[options]"); commander.option("-i, --input <dir>", "defines input directory for processing files."); commander.option("-o, --output <dir>", "defines output directory for procesed files."); commander.option("-m, --map [dir]", "enables source maps generation and defines their directory."); commander.option("-c, --cache [dir]", "enables files caching and defines directory."); commander.option("-w, --watch", "enables files watching."); commander.option("-p, --compression", "enables output compression."); commander.option("-l, --log", "defines logging level [ALL, TRACE, DEBUG, INFO, WARNING, ERROR, FATAL]."); commander.parse(process.argv); args = {}; if (_.isString(commander.input)) { args.input = path.normalize(commander.input); } if (_.isString(commander.output)) { args.output = path.normalize(commander.output); } if (_.isString(commander.map)) { args.map = path.normalize(commander.map); } if (_.isString(commander.cache)) { args.cache = path.normalize(commander.cache); } if (commander.watch) { args.watch = true; } if (commander.compression) { args.compression = true; } if (_.isString(commander.log)) { args.log = commander.log; } this.setup(args); stats.processed = 0; stats.skipped = 0; stats.failures = 0; stats.successes = 0; stats.started = Date.now(); logger = log4js.getDefaultLogger(); logger.info("*********** ASTERX " + info.version + " **********"); logger.debug("[input: " + config.input + ", output: " + config.output + "]\n"); return fs_tools.walk(config.input, function(file, info, next) { return self.process_file(file, next); }, function(err) { var watcher; if (config.watch === true) { watcher = chokidar.watch(config.input, { persistent: true }); watcher.on("add", function(file) { return self.process_file(file, function() {}); }); watcher.on("change", function(file) { return self.process_file(file, function() {}); }); } stats.ended = Date.now(); stats.duration = ((stats.ended - stats.started) / 1000) + "s"; logger.debug("[processed: " + stats.processed + ", skipped: " + stats.skipped + "]"); logger.debug("[successes: " + stats.successes + ", failures: " + stats.failures + "]"); logger.debug("[duration: " + stats.duration + "]"); if (config.watch === false) { logger.info("********** ASTERX DONE! **********\n"); } if (done) { return done(err, stats); } }); }; exports["process_file"] = function(file, done) { var cache, failed, input, log, output, source_map; input = {}; input.extension = path.extname(file).replace(".", "").toLowerCase(); input.file = path.normalize(file); input.directory = path.normalize(path.dirname(input.file)); input.code = ""; output = {}; output.extension = "js"; output.file = path.normalize(config.output + "/" + path.basename(input.file, path.extname(input.file)) + "." + output.extension); output.directory = path.normalize(path.dirname(output.file)); output.code = ""; source_map = {}; source_map.is_enabled = config.map !== "" && config.map !== null; if (source_map.is_enabled) { source_map.extension = "map"; source_map.file = path.normalize(config.map + "/" + path.basename(input.file, path.extname(input.file)) + "." + output.extension + "." + source_map.extension); source_map.directory = path.normalize(path.dirname(source_map.file)); source_map.link = '/*# sourceMappingURL=' + path.normalize(path.relative(output.directory, source_map.directory) + "/" + path.basename(source_map.file)) + " */"; source_map.code = { file: path.normalize(path.relative(source_map.directory, output.file)), sources: [path.normalize(path.relative(source_map.directory, input.file))] }; } cache = {}; cache.is_enabled = config.cache !== "" && config.cache !== null; if (cache.is_enabled) { cache.extension = "cache"; cache.file = path.normalize(config.cache + "/" + path.basename(input.file, path.extname(input.file)) + "." + cache.extension); cache.directory = path.normalize(path.dirname(cache.file)); cache.code = ""; } if (input.extension.toLowerCase() !== "coffee" && input.extension.toLowerCase() !== "js") { stats.skipped++; return done(); } if (cache.is_enabled && fs.existsSync(cache.file) && (fs.lstatSync(input.file).mtime <= fs.lstatSync(cache.file).mtime)) { stats.skipped++; return done(); } stats.processed++; log = log4js.getBufferedLogger(""); log.info("processing file: " + input.file); failed = false; return async.series([ function(back) { return fs.readFile(input.file, function(err, result) { if (err) { failed = true; log.error(err.message); log.trace(err.stack); log.error("reading input: FAILED!"); } else { output.code = result; log.debug("reading input: DONE!"); } return back(); }); }, function(back) { if (failed === true) { return back(); } if (input.extension === "coffee") { output.code = string(output.code).replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//igm, "").replace(/^\s*#{3}(?:(?!#)[\s\S])*#{3}/igm, "").replace(/^#{1}[^#{2,}][^\n|\r]*/igm, "").replace(/\/\/[^\n|\r]*/igm, "").toString(); } if (input.extension === "js") { output.code = string(output.code).replace(/\/\*([\s\S]*?)\*\//igm, "").replace(/\/\/.+/igm, "").toString(); } output.code = string(output.code).replaceAll(config.callback_error_value, "$BACK_ERR").replaceAll(config.callback_value, "$BACK").toString(); return back(); }, function(back) { var compiled, err, error, options; if (failed === true) { return back(); } if (input.extension.toLowerCase() !== "coffee") { return back(); } try { options = {}; options.filename = input.file; if (source_map.is_enabled) { options.sourceMap = true; options.sourceRoot = ""; options.sourceFiles = source_map.sources; options.generatedFile = source_map.file; } compiled = coffeescript.compile(output.code, options); output.code = compiled.js || compiled; if (compiled.v3SourceMap) { compiled.v3SourceMap = JSON.parse(compiled.v3SourceMap); compiled.v3SourceMap.sources = source_map.code.sources; compiled.v3SourceMap.file = source_map.code.file; source_map.code = compiled.v3SourceMap; } log.debug("coffee-script compilation: DONE!"); return back(); } catch (error) { err = error; failed = true; log.error(err.message); log.trace(err.stack); log.error("coffee-script compilation: FAILED!"); return back(); } }, function(back) { var options; if (failed === true) { return back(); } if (!(string(output.code).contains("$BACK_ERR") || string(output.code).contains("$BACK"))) { return back(); } options = {}; if (source_map.is_enabled) { options.source_map = source_map.code; } options.callback_value = "$BACK"; options.callback_error_value = "$BACK_ERR"; options.inject_try_catch = config.inject_try_catch; return asterx.transform(output.code, options, function(err, result) { if (err) { failed = true; log.error(err.message); log.trace(err.stack); log.error("callback transformation: FAILED!"); } else { output.code = result.code; source_map.code = result.source_map; log.debug("callback transformation: DONE!"); } return back(); }); }, function(back) { var ast, compressor, err, error, options, stream; try { if (failed === true) { return back(); } if (config.compression !== true) { return back(); } ast = uglify.parse(output.code); ast.figure_out_scope(); compressor = uglify.Compressor({ warnings: false }); ast = ast.transform(compressor); ast.figure_out_scope(); ast.compute_char_frequency(); ast.mangle_names(); options = {}; if (source_map.is_enabled === true) { options.source_map = uglify.SourceMap({ file: source_map.code.file || "", root: source_map.code.sourceRoot || "", orig: _.has(source_map.code, "mappings") ? source_map.code : void 0 }); } stream = uglify.OutputStream(options); ast.print(stream); output.code = stream.toString(); if (source_map.is_enabled === true) { options.source_map = JSON.parse(options.source_map.toString()); options.source_map.sources = source_map.code.sources || []; source_map.code = options.source_map; } log.debug("compression: DONE!"); return back(); } catch (error) { err = error; failed = true; log.error(err.message); log.trace(err.stack); log.error("compression: FAILED!"); return back(); } }, function(back) { if (failed === true) { return back(); } if (_.has(source_map.code, "mappings")) { output.code += "\n" + source_map.link; } return async.series([ function(back) { return fs_tools.mkdir(output.directory, back); }, function(back) { return fs.writeFile(output.file, output.code, back); } ], function(err) { if (err) { failed = true; log.error(err.message); log.trace(err.stack); log.error("writing output: FAILED!"); } else { log.debug("writing output: DONE!"); } return back(); }); }, function(back) { if (failed === true) { return back(); } if (source_map.is_enabled !== true) { return back(); } if (!_.has(source_map.code, 'mappings')) { return back(); } if (_.isObject(source_map.code)) { source_map.code = JSON.stringify(source_map.code, null, 4); } return async.series([ function(back) { return fs_tools.mkdir(source_map.directory, back); }, function(back) { return fs.writeFile(source_map.file, source_map.code, back); } ], function(err) { if (err) { failed = failed; log.error(err.message); log.trace(err.stack); log.warn("source mapping: FAILED!"); } else { log.debug("source mapping: DONE!"); } return back(); }); }, function(back) { if (failed === true) { return back(); } if (cache.is_enabled !== true) { return back(); } return async.series([ function(back) { return fs_tools.mkdir(cache.directory, back); }, function(back) { return fs.writeFile(cache.file, cache.code, back); } ], function(err) { if (err) { failed = failed; log.error(err.message); log.trace(err.stack); log.warn("caching: FAILED!"); } else { log.debug("caching: DONE!"); } return back(); }); }, function(back) { if (failed === true) { stats.failures++; log.error("processing file: FAILED!\n"); } else { stats.successes++; log.info("processing file: DONE!\n"); } log.flush(); return back(); } ], function(err) { if (done) { return done(err, stats); } }); }; }).call(this);