UNPKG

ng-annotate

Version:

add, remove and rebuild angularjs dependency injection annotations

221 lines (191 loc) 6.24 kB
// ng-annotate.js // MIT licensed, see LICENSE file // Copyright (c) 2013-2016 Olov Lassus <olov.lassus@gmail.com> "use strict"; var t0 = Date.now(); var fs = require("fs"); var fmt = require("simple-fmt"); var tryor = require("tryor"); var ngAnnotate = require("./ng-annotate-main"); var version = "1.2.2"; var optimist = require("optimist") .usage("ng-annotate v" + version + "\n\nUsage: ng-annotate OPTIONS <file>\n\n" + "provide - instead of <file> to read from stdin\n" + "use -a and -r together to remove and add (rebuild) annotations in one go") .options("a", { alias: "add", boolean: true, describe: "add dependency injection annotations where non-existing", }) .options("r", { alias: "remove", boolean: true, describe: "remove all existing dependency injection annotations", }) .options("o", { describe: "write output to <file>. output is written to stdout by default", }) .options("sourcemap", { boolean: true, describe: "generate an inline sourcemap" }) .options("sourceroot", { describe: "set the sourceRoot property of the generated sourcemap" }) .options("single_quotes", { boolean: true, describe: "use single quotes (') instead of double quotes (\")", }) .options("regexp", { describe: "detect short form myMod.controller(...) iff myMod matches regexp", }) .options("rename", { describe: "rename declarations and annotated references\n" + "oldname1 newname1 oldname2 newname2 ...", default: "" }) .options("plugin", { describe: "use plugin with path (experimental)", }) .options("enable", { describe: "enable optional with name", }) .options("list", { describe: "list all optional names", boolean: true, }) .options("stats", { boolean: true, describe: "print statistics on stderr (experimental)", }); var argv = optimist.argv; function exit(msg) { if (msg) { process.stderr.write(msg); process.stderr.write("\n"); } process.exit(-1); } // special-case for --list if (argv.list) { var list = ngAnnotate("", {list: true}).list; if (list.length >= 1) { process.stdout.write(list.join("\n") + "\n"); } process.exit(0); } // validate options if (argv._.length !== 1) { optimist.showHelp(); exit("error: no input file provided"); } if (!argv.add && !argv.remove) { optimist.showHelp(); exit("error: missing option --add and/or --remove"); } var filename = argv._.shift(); (filename === "-" ? slurpStdin : slurpFile)(runAnnotate); function slurpStdin(cb) { var buf = ""; process.stdin.setEncoding("utf8"); process.stdin.on("data", function(d) { buf += d; }); process.stdin.on("end", function() { cb(null, buf); }); process.stdin.resume(); } function slurpFile(cb) { if (!fs.existsSync(filename)) { cb(new Error(fmt('error: file not found {0}', filename))); } fs.readFile(filename, cb); } function runAnnotate(err, src) { if (err) { exit(err.message); } src = String(src); var config = tryor(function() { return JSON.parse(String(fs.readFileSync("ng-annotate-config.json"))); }, {}); if (filename !== "-") { config.inFile = filename; } ["add", "remove", "o", "regexp", "rename", "single_quotes", "plugin", "enable", "stats"].forEach(function(opt) { if (opt in argv) { config[opt] = argv[opt]; } }); if (argv.sourcemap) { config.map = { inline: true, sourceRoot: argv.sourceroot }; if (filename !== "-") { config.map.inFile = filename; } }; if (config.enable && !Array.isArray(config.enable)) { config.enable = [config.enable]; } if (config.plugin) { if (!Array.isArray(config.plugin)) { config.plugin = [config.plugin]; } config.plugin = config.plugin.map(function(path) { var absPath = tryor(fs.realpathSync.bind(fs, path), null); if (!absPath) { exit(fmt('error: plugin file not found {0}', path)); } // the require below may throw an exception on parse-error try { return require(absPath); } catch (e) { // node will already print file:line and offending line to stderr exit(fmt("error: couldn't require(\"{0}\")", absPath)); } }); } var trimmedRename = config.rename && config.rename.trim(); if (trimmedRename) { var flattenRename = trimmedRename.split(" "); var renameArray = []; for (var i = 0; i < flattenRename.length; i = i + 2) { renameArray.push({ "from": flattenRename[i], "to": flattenRename[i + 1], }); } config.rename = renameArray; } else { config.rename = null; } var run_t0 = Date.now(); var ret = ngAnnotate(src, config); var run_t1 = Date.now(); if (ret.errors) { exit(ret.errors.join("\n")); } var stats = ret._stats; if (config.stats && stats) { var t1 = Date.now(); var all = t1 - t0; var run_parser = stats.parser_parse_t1 - stats.parser_parse_t0; var all_parser = run_parser + (stats.parser_require_t1 - stats.parser_require_t0); var nga_run = (run_t1 - run_t0) - run_parser; var nga_init = all - all_parser - nga_run; var pct = function(n) { return Math.round(100 * n / all); } process.stderr.write(fmt("[{0} ms] parser: {1}, nga init: {2}, nga run: {3}\n", all, all_parser, nga_init, nga_run)); process.stderr.write(fmt("[%] parser: {0}, nga init: {1}, nga run: {2}\n", pct(all_parser), pct(nga_init), pct(nga_run))); } if (ret.src && config.o) { try { fs.writeFileSync(config.o, ret.src); } catch (e) { exit(e.message); } } else if (ret.src) { process.stdout.write(ret.src); } }