Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ng-annotate

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ng-annotate - npm Package Compare versions

Comparing version 1.0.2 to 1.1.0

ng-annotate/.travis.yml

71

ng-annotate/build/es5/ng-annotate-main.js

@@ -39,3 +39,3 @@ // ng-annotate-main.js

var matchMethodCalls = (isMethodCall &&
(matchInjectorInvoke(node) || matchProvide(node, ctx) || matchRegular(node, ctx) || matchNgRoute(node) || matchMaterialShowModalOpen(node) || matchNgUi(node) || matchHttpProvider(node)));
(matchInjectorInvoke(node) || matchProvide(node, ctx) || matchRegular(node, ctx) || matchNgRoute(node) || matchMaterialShowModalOpen(node) || matchNgUi(node) || matchHttpProvider(node) || matchControllerProvider(node)));

@@ -61,3 +61,3 @@ return matchMethodCalls ||

if (obj.type === "Identifier" &&
((obj.name === "$modal" && method.name === "open") || (is.someof(obj.name, ["$mdDialog", "$mdToast", "$mdBottomSheet"]) && method.name === "show")) &&
((is.someof(obj.name, ["$modal", "$uibModal"]) && method.name === "open") || (is.someof(obj.name, ["$mdDialog", "$mdToast", "$mdBottomSheet"]) && method.name === "show")) &&
args.length === 1 && args[0].type === "ObjectExpression") {

@@ -151,2 +151,3 @@ var props = args[0].properties;

// $stateProvider.state("myState", {... resolve: {f: function($scope) {}, ..} ..})
// $stateProvider.state("myState", {... params: {params: {simple: function($scope) {}, inValue: { value: function($scope) {} }} ..})
// $stateProvider.state("myState", {... views: {... somename: {... controller: fn, controllerProvider: fn, templateProvider: fn, resolve: {f: fn}}}})

@@ -234,2 +235,14 @@ //

// {params: {simple: function($scope) {}, inValue: { value: function($scope) {} }}
var a = matchProp("params", props);
if (a && a.type === "ObjectExpression") {
a.properties.forEach(function(prop) {
if (prop.value.type === "ObjectExpression") {
res.push(matchProp("value", prop.value.properties));
} else {
res.push(prop.value);
}
});
}
// {view: ...}

@@ -278,2 +291,20 @@ var viewObject = matchProp("views", props);

function matchControllerProvider(node) {
// $controllerProvider.register("foo", function($scope) {});
// we already know that node is a (non-computed) method call
var callee = node.callee;
var obj = callee.object; // identifier or expression
var method = callee.property; // identifier
var args = node.arguments;
var target = obj.type === "Identifier" && obj.name === "$controllerProvider" &&
method.name === "register" && args.length === 2 && args[1];
if (target) {
target.$methodName = method.name;
}
return target;
}
function matchProvide(node, ctx) {

@@ -322,4 +353,10 @@ // $provide.decorator("foo", function($scope) {});

// hardcoded exception: foo.decorator is generally considered a short-form
// declaration but $stateProvider.decorator is not. see https://github.com/olov/ng-annotate/issues/82
if (obj.name === "$stateProvider" && method.name === "decorator") {
return false;
}
var matchAngularModule = (obj.$chained === chainedRegular || isReDef(obj, ctx) || isLongDef(obj)) &&
is.someof(method.name, ["provider", "value", "constant", "bootstrap", "config", "factory", "directive", "filter", "run", "controller", "service", "animation", "invoke", "store"]);
is.someof(method.name, ["provider", "value", "constant", "bootstrap", "config", "factory", "directive", "filter", "run", "controller", "service", "animation", "invoke", "store", "decorator", "component"]);
if (!matchAngularModule) {

@@ -339,2 +376,10 @@ return false;

if (method.name === "component") {
var controllerProp = (target && target.type === "ObjectExpression" && matchProp("controller", target.properties));
if (!controllerProp) {
return false;
}
target = controllerProp;
}
if (target) {

@@ -704,2 +749,17 @@ target.$methodName = method.name;

function firstNonPrologueStatement(body) {
for (var i = 0; i < body.length; i++) {
if (body[i].type !== "ExpressionStatement") {
return body[i];
}
var expr = body[i].expression;
var isStringLiteral = (expr.type === "Literal" && typeof expr.value === "string");
if (!isStringLiteral) {
return body[i];
}
}
return null;
}
function judgeInjectArraySuspect(node, ctx) {

@@ -827,2 +887,5 @@ if (node.type === "VariableDeclaration") {

assert(foundSuspectInBody);
if (onode.type === "FunctionDeclaration") {
troublesomeReturn = firstNonPrologueStatement(onode.$parent.body);
}

@@ -1021,2 +1084,4 @@ if (troublesomeReturn && !existingExpressionStatementWithArray) {

ecmaVersion: 6,
sourceType: "module",
allowReserved: true,
locations: true,

@@ -1023,0 +1088,0 @@ ranges: true,

2

ng-annotate/build/es5/ng-annotate.js

@@ -12,3 +12,3 @@ // ng-annotate.js

var ngAnnotate = require("./ng-annotate-main");
var version = "1.0.2";
var version = "1.1.0";
var optimist = require("optimist")

@@ -15,0 +15,0 @@ .usage("ng-annotate v" + version + "\n\nUsage: ng-annotate OPTIONS <file>\n\n" +

@@ -201,3 +201,2 @@ // See repo/INFO for test code origin

//'should annotate decorators'
//(no it should actually not)
angular.module('myMod', []).

@@ -204,0 +203,0 @@ decorator('myService', function(dep) {

@@ -201,6 +201,5 @@ // See repo/INFO for test code origin

//'should annotate decorators'
//(no it should actually not)
angular.module('myMod', []).
decorator('myService', function(dep) {
});
decorator('myService', ["dep", function(dep) {
}]);

@@ -207,0 +206,0 @@ //'should annotate config'

@@ -28,2 +28,5 @@ "use strict";

});
myMod.decorator("foo", function($scope, $timeout) {
});
myMod.component("foo", {controller: function($scope, $timeout) {}});

@@ -57,2 +60,5 @@ // implicit config function

});
myMod.decorator("foo", function() {
});
myMod.component("foo", {controller: function() {}});

@@ -164,2 +170,10 @@ // run, config don't take names

e;
}).component("foo", {controller: function($scope, $timeout) {
i;
}}).invoke("foo", function($f, $g) {
f;
}).decorator("foo", function($f, $g) {
g;
}).store("foo", function($f, $g) {
h;
});

@@ -185,6 +199,10 @@

e;
}).component("foo", {controller: function($scope, $timeout) {
i;
}}).invoke("foo", function($h, $i) {
f;
}).decorator("foo", function($h, $i) {
g;
}).store("foo", function($f, $g) {
g;
}).invoke("foo", function($h, $i) {
f;
h;
});

@@ -220,2 +238,9 @@

// $controllerProvider
angular.module("myMod").controller("foo", function() {
$controllerProvider.register("foo", function($scope) {});
});
function notInContext() {
$controllerProvider.register("foo", function($scope) {});
}

@@ -254,2 +279,6 @@ // all the patterns below matches only when we're inside a detected angular module

},
params: {
simple: function($scope) {},
inValue: { value: function($scope) {}, notThis: function($scope) {} },
},
views: {

@@ -359,2 +388,12 @@ viewa: {

});
$uibModal.open({
templateUrl: "str",
controller: function($scope) {},
resolve: {
items: function(MyService) {},
data: function(a, b) {},
its: 42,
},
donttouch: function(me) {},
});

@@ -532,2 +571,12 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

});
$uibModal.open({
templateUrl: "str",
controller: function($scope) {},
resolve: {
items: function(MyService) {},
data: function(a, b) {},
its: 42,
},
donttouch: function(me) {},
});

@@ -782,2 +831,7 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

// not a module declaration short-form, see https://github.com/olov/ng-annotate/issues/82
$stateProvider.decorator('parent', function (state, parentFn) {
doStuff();
});
// $get is only valid inside provider

@@ -810,3 +864,3 @@ myMod.service("donttouch", function() {

angular.module("MyMod").directive("foo", function($a, $b) {
$modal.open({
$uibModal.open({
resolve: {

@@ -813,0 +867,0 @@ collection: (function(_this) {

"use strict";
// long form
foo.$inject = ["$scope"];
Foo.$inject = ["$scope"];
foo3.$inject = ["$scope"];
foo4.$inject = ["$scope"];
foo5.$inject = ["$scope"];
foo6.$inject = ["$scope"];
MyCtrl2.$inject = ["z"];
MyDirective2.$inject = ["$stateProvider"];
extprov.$inject = ["x"];
fooget.$inject = ["b"];
fooget2.$inject = ["c"];
Foo2.$inject = ["$scope"];
MyCtrl1.$inject = ["a", "b"];
MyDirective.$inject = ["$stateProvider"];
angular.module("MyMod").controller("MyCtrl", ["$scope", "$timeout", function($scope, $timeout) {

@@ -28,2 +42,5 @@ }]);

}]);
myMod.decorator("foo", ["$scope", "$timeout", function($scope, $timeout) {
}]);
myMod.component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) {}]});

@@ -57,2 +74,5 @@ // implicit config function

});
myMod.decorator("foo", function() {
});
myMod.component("foo", {controller: function() {}});

@@ -138,2 +158,3 @@ // run, config don't take names

function extprov(x) {
inner.$inject = ["c", "d"];
this.$get = ["a", "b", function(a,b) {}];

@@ -145,5 +166,3 @@ this.$get = fooget;

}
inner.$inject = ["c", "d"];
}
extprov.$inject = ["x"];

@@ -153,7 +172,5 @@ function fooget(b) {

}
fooget.$inject = ["b"];
function fooget2(c) {
}
fooget2.$inject = ["c"];

@@ -171,2 +188,10 @@ // chaining

e;
}]).component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) {
i;
}]}).invoke("foo", ["$f", "$g", function($f, $g) {
f;
}]).decorator("foo", ["$f", "$g", function($f, $g) {
g;
}]).store("foo", ["$f", "$g", function($f, $g) {
h;
}]);

@@ -192,6 +217,10 @@

e;
}]).component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) {
i;
}]}).invoke("foo", ["$h", "$i", function($h, $i) {
f;
}]).decorator("foo", ["$h", "$i", function($h, $i) {
g;
}]).store("foo", ["$f", "$g", function($f, $g) {
g;
}]).invoke("foo", ["$h", "$i", function($h, $i) {
f;
h;
}]);

@@ -227,2 +256,9 @@

// $controllerProvider
angular.module("myMod").controller("foo", function() {
$controllerProvider.register("foo", ["$scope", function($scope) {}]);
});
function notInContext() {
$controllerProvider.register("foo", function($scope) {});
}

@@ -261,2 +297,6 @@ // all the patterns below matches only when we're inside a detected angular module

},
params: {
simple: ["$scope", function($scope) {}],
inValue: { value: ["$scope", function($scope) {}], notThis: function($scope) {} },
},
views: {

@@ -366,2 +406,12 @@ viewa: {

});
$uibModal.open({
templateUrl: "str",
controller: ["$scope", function($scope) {}],
resolve: {
items: ["MyService", function(MyService) {}],
data: ["a", "b", function(a, b) {}],
its: 42,
},
donttouch: function(me) {},
});

@@ -539,2 +589,12 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

});
$uibModal.open({
templateUrl: "str",
controller: function($scope) {},
resolve: {
items: function(MyService) {},
data: function(a, b) {},
its: 42,
},
donttouch: function(me) {},
});

@@ -632,3 +692,2 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

}
foo.$inject = ["$scope"];

@@ -639,3 +698,2 @@ // @ngInject

}
Foo.$inject = ["$scope"];

@@ -669,12 +727,8 @@ // @ngInject

function foo3($scope) {}
foo3.$inject = ["$scope"];
// @ngInject
function foo4($scope) {
}
foo4.$inject = ["$scope"];
/* @ngInject */ function foo5($scope) {}
foo5.$inject = ["$scope"];
/* @ngInject */ function foo6($scope) {
}
foo6.$inject = ["$scope"];

@@ -715,4 +769,4 @@ // @ngInject

function outer() {
MyCtrl.$inject = ["a"];
foo;
MyCtrl.$inject = ["a"];
return {

@@ -748,3 +802,2 @@ controller: MyCtrl,

}
Foo2.$inject = ["$scope"];

@@ -818,2 +871,7 @@ var foos3 = function($scope) {

// not a module declaration short-form, see https://github.com/olov/ng-annotate/issues/82
$stateProvider.decorator('parent', function (state, parentFn) {
doStuff();
});
// $get is only valid inside provider

@@ -840,4 +898,4 @@ myMod.service("donttouch", function() {

myMod.directive("donttouch", function() {
foo.decorator("me", function($scope) {
});
foo.decorator("me", ["$scope", function($scope) {
}]);
});

@@ -847,3 +905,3 @@

angular.module("MyMod").directive("foo", ["$a", "$b", function($a, $b) {
$modal.open({
$uibModal.open({
resolve: {

@@ -905,3 +963,2 @@ collection: (function(_this) {

}
MyCtrl1.$inject = ["a", "b"];
if (true) {

@@ -917,3 +974,2 @@ // proper scope analysis including shadowing

}
MyCtrl2.$inject = ["z"];
funcall(/*@ngInject*/ MyCtrl2); // explicit annotation on reference flows back to definition

@@ -931,3 +987,2 @@

}
MyDirective.$inject = ["$stateProvider"];

@@ -943,3 +998,2 @@ /* @ngInject */

}
MyDirective2.$inject = ["$stateProvider"];

@@ -974,5 +1028,5 @@ // issue 84

/*@ngInject*/
MyCtrl.$inject = ["a"];
function MyCtrl(a) {
}
MyCtrl.$inject = ["a"];

@@ -979,0 +1033,0 @@ return MyCtrl;

@@ -0,1 +1,9 @@

## v1.1.0 2015-12-19
* bugfix $inject arrays for function definitions not being hoisted
* match angular.module("MyMod").component("foo", {controller: function ..})
* match angular.module("MyMod").decorator("foo", function ..)
* match $controllerProvider.register
* match $uibModal.open from angular-ui (recently renamed from $modal.open)
* ui-router declarations improvements
## v1.0.2 2015-07-17

@@ -2,0 +10,0 @@ * bugfix reference-following crash

@@ -39,3 +39,3 @@ // ng-annotate-main.js

const matchMethodCalls = (isMethodCall &&
(matchInjectorInvoke(node) || matchProvide(node, ctx) || matchRegular(node, ctx) || matchNgRoute(node) || matchMaterialShowModalOpen(node) || matchNgUi(node) || matchHttpProvider(node)));
(matchInjectorInvoke(node) || matchProvide(node, ctx) || matchRegular(node, ctx) || matchNgRoute(node) || matchMaterialShowModalOpen(node) || matchNgUi(node) || matchHttpProvider(node) || matchControllerProvider(node)));

@@ -61,3 +61,3 @@ return matchMethodCalls ||

if (obj.type === "Identifier" &&
((obj.name === "$modal" && method.name === "open") || (is.someof(obj.name, ["$mdDialog", "$mdToast", "$mdBottomSheet"]) && method.name === "show")) &&
((is.someof(obj.name, ["$modal", "$uibModal"]) && method.name === "open") || (is.someof(obj.name, ["$mdDialog", "$mdToast", "$mdBottomSheet"]) && method.name === "show")) &&
args.length === 1 && args[0].type === "ObjectExpression") {

@@ -151,2 +151,3 @@ const props = args[0].properties;

// $stateProvider.state("myState", {... resolve: {f: function($scope) {}, ..} ..})
// $stateProvider.state("myState", {... params: {params: {simple: function($scope) {}, inValue: { value: function($scope) {} }} ..})
// $stateProvider.state("myState", {... views: {... somename: {... controller: fn, controllerProvider: fn, templateProvider: fn, resolve: {f: fn}}}})

@@ -234,2 +235,14 @@ //

// {params: {simple: function($scope) {}, inValue: { value: function($scope) {} }}
const a = matchProp("params", props);
if (a && a.type === "ObjectExpression") {
a.properties.forEach(function(prop) {
if (prop.value.type === "ObjectExpression") {
res.push(matchProp("value", prop.value.properties));
} else {
res.push(prop.value);
}
});
}
// {view: ...}

@@ -278,2 +291,20 @@ const viewObject = matchProp("views", props);

function matchControllerProvider(node) {
// $controllerProvider.register("foo", function($scope) {});
// we already know that node is a (non-computed) method call
const callee = node.callee;
const obj = callee.object; // identifier or expression
const method = callee.property; // identifier
const args = node.arguments;
const target = obj.type === "Identifier" && obj.name === "$controllerProvider" &&
method.name === "register" && args.length === 2 && args[1];
if (target) {
target.$methodName = method.name;
}
return target;
}
function matchProvide(node, ctx) {

@@ -322,4 +353,10 @@ // $provide.decorator("foo", function($scope) {});

// hardcoded exception: foo.decorator is generally considered a short-form
// declaration but $stateProvider.decorator is not. see https://github.com/olov/ng-annotate/issues/82
if (obj.name === "$stateProvider" && method.name === "decorator") {
return false;
}
const matchAngularModule = (obj.$chained === chainedRegular || isReDef(obj, ctx) || isLongDef(obj)) &&
is.someof(method.name, ["provider", "value", "constant", "bootstrap", "config", "factory", "directive", "filter", "run", "controller", "service", "animation", "invoke", "store"]);
is.someof(method.name, ["provider", "value", "constant", "bootstrap", "config", "factory", "directive", "filter", "run", "controller", "service", "animation", "invoke", "store", "decorator", "component"]);
if (!matchAngularModule) {

@@ -335,6 +372,14 @@ return false;

const args = node.arguments;
const target = (is.someof(method.name, ["config", "run"]) ?
let target = (is.someof(method.name, ["config", "run"]) ?
args.length === 1 && args[0] :
args.length === 2 && args[0].type === "Literal" && is.string(args[0].value) && args[1]);
if (method.name === "component") {
const controllerProp = (target && target.type === "ObjectExpression" && matchProp("controller", target.properties));
if (!controllerProp) {
return false;
}
target = controllerProp;
}
if (target) {

@@ -704,2 +749,17 @@ target.$methodName = method.name;

function firstNonPrologueStatement(body) {
for (let i = 0; i < body.length; i++) {
if (body[i].type !== "ExpressionStatement") {
return body[i];
}
const expr = body[i].expression;
const isStringLiteral = (expr.type === "Literal" && typeof expr.value === "string");
if (!isStringLiteral) {
return body[i];
}
}
return null;
}
function judgeInjectArraySuspect(node, ctx) {

@@ -827,2 +887,5 @@ if (node.type === "VariableDeclaration") {

assert(foundSuspectInBody);
if (onode.type === "FunctionDeclaration") {
troublesomeReturn = firstNonPrologueStatement(onode.$parent.body);
}

@@ -1021,2 +1084,4 @@ if (troublesomeReturn && !existingExpressionStatementWithArray) {

ecmaVersion: 6,
sourceType: "module",
allowReserved: true,
locations: true,

@@ -1023,0 +1088,0 @@ ranges: true,

{
"name": "ng-annotate",
"version": "1.0.2",
"version": "1.1.0",
"description": "add, remove and rebuild angularjs dependency injection annotations",

@@ -11,5 +11,5 @@ "main": "build/es5/ng-annotate-main.js",

"dependencies": {
"acorn": "~2.1.0",
"acorn": "~2.6.4",
"alter": "~0.2.0",
"convert-source-map": "~1.0.0",
"convert-source-map": "~1.1.2",
"optimist": "~0.6.1",

@@ -19,3 +19,3 @@ "ordered-ast-traverse": "~1.1.1",

"simple-is": "~0.2.0",
"source-map": "~0.4.2",
"source-map": "~0.5.3",
"stable": "~0.1.5",

@@ -27,5 +27,5 @@ "stringmap": "~0.2.2",

"devDependencies": {
"coffee-script": "~1.9.1",
"defs": "~1.1.0",
"diff": "~1.3.1",
"coffee-script": "~1.10.0",
"defs": "~1.1.1",
"diff": "~2.2.1",
"find-line-column": "~0.5.2"

@@ -32,0 +32,0 @@ },

@@ -1,22 +0,30 @@

# ng-annotate
# ng-annotate [![Build Status](https://travis-ci.org/olov/ng-annotate.svg?branch=master)](https://travis-ci.org/olov/ng-annotate)
ng-annotate adds and removes AngularJS dependency injection annotations.
It is non-intrusive so your source code stays exactly the same otherwise.
No lost comments or moved lines. Annotations are useful because with them
you're able to minify your source code using your favorite JS minifier.
You write your code without annotations, like this:
Write your code without annotations and mark-up functions to be annotated
with the `"ngInject"` directive prologue, just like you would
`"use strict"`. This must be at the beginning of your function.
```js
$ cat source.js
angular.module("MyMod").controller("MyCtrl", function($scope, $timeout) {
"ngInject";
...
});
```
You then run ng-annotate as a build-step to produce this intermediary,
annotated, result (later sent to the minifier):
Then run ng-annotate as a build-step to produce this intermediary,
annotated, result (later sent to the minifier of choice):
```js
$ ng-annotate -a source.js
angular.module("MyMod").controller("MyCtrl", ["$scope", "$timeout", function($scope, $timeout) {
"ngInject";
...
}]);
```
Your minifier will most likely retain the `"ngInject;"` prologues so use `sed`
or a regexp in your build toolchain to get rid of those.
You can also use ng-annotate to rebuild or remove existing annotations.

@@ -28,7 +36,3 @@ Rebuilding is useful if you like to check-in the annotated version of your

**ng-annotate works by using static analysis to identify common code patterns.
There are patterns it does not and never will understand and for those you
can use an explicit `ngInject` annotation instead, see section further down.**
## Installation and usage

@@ -43,33 +47,32 @@

Use the `--add` (`-a`) option to add annotations where non-existing,
use `--remove` (`-r`) to remove all existing annotations,
use `--add --remove` (`-ar`) to rebuild all annotations.
The simplest usage is `ng-annotate -a infile.js > outfile.js`.
See [OPTIONS.md](OPTIONS.md) for command-line documentation.
Use the `-o` option to write output to file.
ng-annotate can be used as a library, see [OPTIONS.md](OPTIONS.md) for its API.
Provide `-` instead of an input `<file>` to read input from stdin.
Use the `--sourcemap` option to generate an inline sourcemap.
## Implicit matching of common code forms
ng-annotate uses static analysis to detect common AngularJS code patterns. When
this works it means that you do not need to mark-up functions with `"ngInject"`.
For a lot of code bases this works very well (use `ng-strict-di` to simplify
debugging when it doesn't) but for others it is less reliable and you may prefer
to use `"ngInject"` instead. For more information about implicit matching see
[IMPLICIT.md](IMPLICIT.md).
Use the `--sourceroot` option to set the sourceRoot property of the generated sourcemap.
Use the `--single_quotes` option to output `'$scope'` instead of `"$scope"`.
## Explicit annotations with ngInject
The recommended `function foo($scope) { "ngInject"; ... }` can be exchanged
for `/*@ngInject*/ function foo($scope) { ... }` or
`ngInject(function foo($scope) { ... })`. If you use the latter form then
then add `function ngInject(v) { return v }` somewhere in your codebase or process
away the `ngInject` function call in your build step.
Use the `--regexp` option to restrict matching further or to expand matching.
See description further down.
Use the `--list` option to list optional matchers.
### Suppressing false positives with ngNoInject
The `/*@ngInject*/`, `ngInject(..)` and `"ngInject"` siblings have three cousins that
are used for the opposite purpose, suppressing an annotation that ng-annotate added
incorrectly (a "false positive"). They are called `/*@ngNoInject*/`, `ngNoInject(..)`
and `"ngNoInject"` and do exactly what you think they do.
Use the `--enable` option to enable optional matcher.
*experimental* Use the `--rename` option to rename providers (services, factories,
controllers, etc.) with a new name when declared and referenced through annotation.
Use it like this: `--rename oldname1 newname1 oldname2 newname2`
*experimental* Use the `--plugin` option to load a user plugin with the provided path,
1.x may change API). See [plugin-example.js](plugin-example.js) for more info.
*experimental* Use the `--stats` option to print statistics on stderr.
## ES6 and TypeScript support

@@ -81,8 +84,9 @@ ng-annotate supports ES5 as input so run it with the output from Babel, Traceur,

## Highly recommended: enable ng-strict-di in your minified builds
## Highly recommended: enable ng-strict-di
`<div ng-app="myApp" ng-strict-di>`
Do that in your ng-annotate processed builds and AngularJS will let you know if there are
any missing dependency injection annotations. [ng-strict-di](https://docs.angularjs.org/api/ng/directive/ngApp)
is available in AngularJS 1.3 or later.
Do that in your ng-annotate processed (but not minified) builds and AngularJS will
let you know if there are any missing dependency injection annotations.
[ng-strict-di](https://docs.angularjs.org/api/ng/directive/ngApp) is available in
AngularJS 1.3 or later.

@@ -101,3 +105,2 @@

* [ENB](http://enb-make.info/) (Russian): [enb-ng-techs](https://www.npmjs.org/package/enb-ng-techs#ng-annotate) by [Alexey Gurianov](https://github.com/guria)
* Something missing? Contributions welcome - create plugin and submit a README pull request!

@@ -109,183 +112,2 @@

## Declaration forms
ng-annotate understands the two common declaration forms:
Long form:
```js
angular.module("MyMod").controller("MyCtrl", function($scope, $timeout) {
});
```
Short form:
```js
myMod.controller("MyCtrl", function($scope, $timeout) {
});
```
It's not limited to `.controller` of course. It understands `.config`, `.factory`,
`.directive`, `.filter`, `.run`, `.controller`, `.provider`, `.service`, `.animation` and
`.invoke`.
For short forms it does not need to see the declaration of `myMod` so you can run it
on your individual source files without concatenating. If ng-annotate detects a short form
false positive then you can use the `--regexp` option to limit the module identifier.
Examples: `--regexp "^myMod$"` (match only `myMod`) or `--regexp "^$"` (ignore short forms).
You can also use `--regexp` to opt-in for more advanced method callee matching, for
example `--regexp "^require(.*)$"` to detect and transform
`require('app-module').controller(..)`. Not using the option is the same as passing
`--regexp "^[a-zA-Z0-9_\$\.\s]+$"`, which means that the callee can be a (non-unicode)
identifier (`foo`), possibly with dot notation (`foo.bar`).
ng-annotate understands `angular.module("MyMod", function(dep) ..)` as an alternative to
`angular.module("MyMod").config(function(dep) ..)`.
ng-annotate understands `this.$get = function($scope) ..` and
`{.., $get: function($scope) ..}` inside a `provider`. `self` and `that` can be used as
aliases for `this`.
ng-annotate understands `return {.., controller: function($scope) ..}` inside a
`directive`.
ng-annotate understands `$provide.decorator("bar", function($scope) ..)`, `$provide.service`,
`$provide.factory` and `$provide.provider`.
ng-annotate understands `$routeProvider.when("path", { .. })`.
ng-annotate understands `$httpProvider.interceptors.push(function($scope) ..)` and
`$httpProvider.responseInterceptors.push(function($scope) ..)`.
ng-annotate understands `$injector.invoke(function ..)`.
ng-annotate understands [ui-router](https://github.com/angular-ui/ui-router) (`$stateProvider` and
`$urlRouterProvider`).
ng-annotate understands `$modal.open` ([angular-ui/bootstrap](http://angular-ui.github.io/bootstrap/)).
ng-annotate understands `$mdDialog.show`, `$mdToast.show` and `$mdBottomSheet.show`
([angular material design](https://material.angularjs.org/#/api/material.components.dialog/service/$mdDialog)).
ng-annotate understands `myMod.store("MyCtrl", function ..)`
([flux-angular](https://github.com/christianalfoni/flux-angular)).
ng-annotate understands chaining.
ng-annotate understands IIFE's and attempts to match through them, so
`(function() { return function($scope) .. })()` works anywhere
`function($scope) ..` does (for any IIFE args and params).
ng-annotate understands [angular-dashboard-framework](https://github.com/sdorra/angular-dashboard-framework)
via optional `--enable angular-dashboard-framework`.
## Reference-following
ng-annotate follows references. This works iff the referenced declaration is
a) a function declaration or
b) a variable declaration with an initializer.
Modifications to a reference outside of its declaration site are ignored by ng-annotate.
These examples will get annotated:
```js
function MyCtrl($scope, $timeout) {
}
var MyCtrl2 = function($scope) {};
angular.module("MyMod").controller("MyCtrl", MyCtrl);
angular.module("MyMod").controller("MyCtrl", MyCtrl2);
```
## Explicit annotations with ngInject
You can prepend a function with `/*@ngInject*/` to explicitly state that the function
should get annotated. ng-annotate will leave the comment intact and will thus still
be able to also remove or rewrite such annotations.
You can also wrap an expression inside an `ngInject(..)` function call. If you use this
syntax then add `function ngInject(v) { return v }` somewhere in your codebase, or process
away the `ngInject` function call in your build step.
You can also add the `"ngInject"` directive prologue at the beginning of a function,
similar to how `"use strict"` is used, to state that the surrounding function should get
annotated.
Use `ngInject` to support your code style when it's not in a form ng-annotate understands
natively. Remember that the intention of ng-annotate is to reduce stuttering for you,
and `ngInject` does this just as well. You don't need to keep two lists in sync. Use it!
`ngInject` may be particularly useful if you use a compile-to-JS language that doesn't
preserve comments.
### Suppressing false positives with ngNoInject
The `/*@ngInject*/`, `ngInject(..)` and `"ngInject"` siblings have three cousins that
are used for the opposite purpose, suppressing an annotation that ng-annotate added
incorrectly (a "false positive"). They are called `/*@ngNoInject*/`, `ngNoInject(..)`
and `"ngNoInject"` and do exactly what you think they do.
### ngInject examples
Here follows some ngInject examples using the `/*@ngInject*/` syntax. Most examples
works fine using the `ngInject(..)` or `"ngInject"` syntax as well.
```js
x = /*@ngInject*/ function($scope) {};
obj = {controller: /*@ngInject*/ function($scope) {}};
obj.bar = /*@ngInject*/ function($scope) {};
=>
x = /*@ngInject*/ ["$scope", function($scope) {}];
obj = {controller: /*@ngInject*/ ["$scope", function($scope) {}]};
obj.bar = /*@ngInject*/ ["$scope", function($scope) {}];
```
Prepended to an object literal, `/*@ngInject*/` will annotate all of its contained
function expressions, recursively:
```js
obj = /*@ngInject*/ {
controller: function($scope) {},
resolve: { data: function(Service) {} },
};
=>
obj = /*@ngInject*/ {
controller: ["$scope", function($scope) {}],
resolve: { data: ["Service", function(Service) {}] },
};
```
Prepended to a function statement, to a single variable declaration initialized with a
function expression or to an assignment where the rvalue is a function expression,
`/*@ngInject*/` will attach an `$inject` array to the function:
```js
// @ngInject
function Foo($scope) {}
// @ngInject
var foo = function($scope) {}
// @ngInject
module.exports = function($scope) {}
=>
// @ngInject
function Foo($scope) {}
Foo.$inject = ["$scope"];
// @ngInject
var foo = function($scope) {}
foo.$inject = ["$scope"];
// @ngInject
module.exports = function($scope) {}
module.exports.$inject = ["$scope"];
```
## Build and test

@@ -296,2 +118,8 @@ ng-annotate is written in ES6 constlet style and uses [defs.js](https://github.com/olov/defs)

## Issues and contributions
Please provide issues in the form of input, expected output, actual output. Include
the version of ng-annotate and node that you are using. With pull requests, please
include changes to the tests as well (tests/original.js, tests/with_annotations.js).
## License

@@ -303,36 +131,1 @@ `MIT`, see [LICENSE](LICENSE) file.

[Follow @olov](https://twitter.com/olov) on Twitter for updates about ng-annotate.
## How does ng-annotate compare to ngmin?
ngmin has been deprecated in favor of ng-annotate. In short:
ng-annotate is much faster, finds more declarations to annotate (including ui-router),
treats your source code better, is actively maintained and has a bunch of extra features
on top of that. A much more elaborated answer can be found in
["The future of ngmin and ng-annotate"](https://github.com/btford/ngmin/issues/93).
*Migrating from ngmin*:
`ng-annotate -a -` is similar to `ngmin` (use stdin and
stdout). `ng-annotate -a in.js -o out.js` is similar to `ngmin in.js out.js`. Grunt users
can migrate easily by installing
[grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) and replacing `ngmin`
with `ngAnnotate` in their Gruntfile. Scroll down for information about other tools.
## Library (API)
ng-annotate can be used as a library. See [ng-annotate.js](ng-annotate.js) for further info about
options and return value.
```js
var ngAnnotate = require("ng-annotate");
var somePlugin = require("./some/path/some-plugin");
var res = ngAnnotate(src, {
add: true,
plugin: [somePlugin],
rename: [{from: "generalname", to: "uniquename"}, {from: "alpha", to: "beta"}],
map: { inline: false, inFile: "source.js", sourceRoot: "/path/to/source/root" },
enable: ["angular-dashboard-framework"],
});
var errorstringArray = res.errors;
var transformedSource = res.src;
var transformedSourceMap = res.map;
```

@@ -201,3 +201,2 @@ // See repo/INFO for test code origin

//'should annotate decorators'
//(no it should actually not)
angular.module('myMod', []).

@@ -204,0 +203,0 @@ decorator('myService', function(dep) {

@@ -201,6 +201,5 @@ // See repo/INFO for test code origin

//'should annotate decorators'
//(no it should actually not)
angular.module('myMod', []).
decorator('myService', function(dep) {
});
decorator('myService', ["dep", function(dep) {
}]);

@@ -207,0 +206,0 @@ //'should annotate config'

@@ -28,2 +28,5 @@ "use strict";

});
myMod.decorator("foo", function($scope, $timeout) {
});
myMod.component("foo", {controller: function($scope, $timeout) {}});

@@ -57,2 +60,5 @@ // implicit config function

});
myMod.decorator("foo", function() {
});
myMod.component("foo", {controller: function() {}});

@@ -164,2 +170,10 @@ // run, config don't take names

e;
}).component("foo", {controller: function($scope, $timeout) {
i;
}}).invoke("foo", function($f, $g) {
f;
}).decorator("foo", function($f, $g) {
g;
}).store("foo", function($f, $g) {
h;
});

@@ -185,6 +199,10 @@

e;
}).component("foo", {controller: function($scope, $timeout) {
i;
}}).invoke("foo", function($h, $i) {
f;
}).decorator("foo", function($h, $i) {
g;
}).store("foo", function($f, $g) {
g;
}).invoke("foo", function($h, $i) {
f;
h;
});

@@ -220,2 +238,9 @@

// $controllerProvider
angular.module("myMod").controller("foo", function() {
$controllerProvider.register("foo", function($scope) {});
});
function notInContext() {
$controllerProvider.register("foo", function($scope) {});
}

@@ -254,2 +279,6 @@ // all the patterns below matches only when we're inside a detected angular module

},
params: {
simple: function($scope) {},
inValue: { value: function($scope) {}, notThis: function($scope) {} },
},
views: {

@@ -359,2 +388,12 @@ viewa: {

});
$uibModal.open({
templateUrl: "str",
controller: function($scope) {},
resolve: {
items: function(MyService) {},
data: function(a, b) {},
its: 42,
},
donttouch: function(me) {},
});

@@ -532,2 +571,12 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

});
$uibModal.open({
templateUrl: "str",
controller: function($scope) {},
resolve: {
items: function(MyService) {},
data: function(a, b) {},
its: 42,
},
donttouch: function(me) {},
});

@@ -782,2 +831,7 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

// not a module declaration short-form, see https://github.com/olov/ng-annotate/issues/82
$stateProvider.decorator('parent', function (state, parentFn) {
doStuff();
});
// $get is only valid inside provider

@@ -810,3 +864,3 @@ myMod.service("donttouch", function() {

angular.module("MyMod").directive("foo", function($a, $b) {
$modal.open({
$uibModal.open({
resolve: {

@@ -813,0 +867,0 @@ collection: (function(_this) {

"use strict";
// long form
foo.$inject = ["$scope"];
Foo.$inject = ["$scope"];
foo3.$inject = ["$scope"];
foo4.$inject = ["$scope"];
foo5.$inject = ["$scope"];
foo6.$inject = ["$scope"];
MyCtrl2.$inject = ["z"];
MyDirective2.$inject = ["$stateProvider"];
extprov.$inject = ["x"];
fooget.$inject = ["b"];
fooget2.$inject = ["c"];
Foo2.$inject = ["$scope"];
MyCtrl1.$inject = ["a", "b"];
MyDirective.$inject = ["$stateProvider"];
angular.module("MyMod").controller("MyCtrl", ["$scope", "$timeout", function($scope, $timeout) {

@@ -28,2 +42,5 @@ }]);

}]);
myMod.decorator("foo", ["$scope", "$timeout", function($scope, $timeout) {
}]);
myMod.component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) {}]});

@@ -57,2 +74,5 @@ // implicit config function

});
myMod.decorator("foo", function() {
});
myMod.component("foo", {controller: function() {}});

@@ -138,2 +158,3 @@ // run, config don't take names

function extprov(x) {
inner.$inject = ["c", "d"];
this.$get = ["a", "b", function(a,b) {}];

@@ -145,5 +166,3 @@ this.$get = fooget;

}
inner.$inject = ["c", "d"];
}
extprov.$inject = ["x"];

@@ -153,7 +172,5 @@ function fooget(b) {

}
fooget.$inject = ["b"];
function fooget2(c) {
}
fooget2.$inject = ["c"];

@@ -171,2 +188,10 @@ // chaining

e;
}]).component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) {
i;
}]}).invoke("foo", ["$f", "$g", function($f, $g) {
f;
}]).decorator("foo", ["$f", "$g", function($f, $g) {
g;
}]).store("foo", ["$f", "$g", function($f, $g) {
h;
}]);

@@ -192,6 +217,10 @@

e;
}]).component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) {
i;
}]}).invoke("foo", ["$h", "$i", function($h, $i) {
f;
}]).decorator("foo", ["$h", "$i", function($h, $i) {
g;
}]).store("foo", ["$f", "$g", function($f, $g) {
g;
}]).invoke("foo", ["$h", "$i", function($h, $i) {
f;
h;
}]);

@@ -227,2 +256,9 @@

// $controllerProvider
angular.module("myMod").controller("foo", function() {
$controllerProvider.register("foo", ["$scope", function($scope) {}]);
});
function notInContext() {
$controllerProvider.register("foo", function($scope) {});
}

@@ -261,2 +297,6 @@ // all the patterns below matches only when we're inside a detected angular module

},
params: {
simple: ["$scope", function($scope) {}],
inValue: { value: ["$scope", function($scope) {}], notThis: function($scope) {} },
},
views: {

@@ -366,2 +406,12 @@ viewa: {

});
$uibModal.open({
templateUrl: "str",
controller: ["$scope", function($scope) {}],
resolve: {
items: ["MyService", function(MyService) {}],
data: ["a", "b", function(a, b) {}],
its: 42,
},
donttouch: function(me) {},
});

@@ -539,2 +589,12 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

});
$uibModal.open({
templateUrl: "str",
controller: function($scope) {},
resolve: {
items: function(MyService) {},
data: function(a, b) {},
its: 42,
},
donttouch: function(me) {},
});

@@ -632,3 +692,2 @@ // angular material design $mdBottomSheet, $mdDialog, $mdToast

}
foo.$inject = ["$scope"];

@@ -639,3 +698,2 @@ // @ngInject

}
Foo.$inject = ["$scope"];

@@ -669,12 +727,8 @@ // @ngInject

function foo3($scope) {}
foo3.$inject = ["$scope"];
// @ngInject
function foo4($scope) {
}
foo4.$inject = ["$scope"];
/* @ngInject */ function foo5($scope) {}
foo5.$inject = ["$scope"];
/* @ngInject */ function foo6($scope) {
}
foo6.$inject = ["$scope"];

@@ -715,4 +769,4 @@ // @ngInject

function outer() {
MyCtrl.$inject = ["a"];
foo;
MyCtrl.$inject = ["a"];
return {

@@ -748,3 +802,2 @@ controller: MyCtrl,

}
Foo2.$inject = ["$scope"];

@@ -818,2 +871,7 @@ var foos3 = function($scope) {

// not a module declaration short-form, see https://github.com/olov/ng-annotate/issues/82
$stateProvider.decorator('parent', function (state, parentFn) {
doStuff();
});
// $get is only valid inside provider

@@ -840,4 +898,4 @@ myMod.service("donttouch", function() {

myMod.directive("donttouch", function() {
foo.decorator("me", function($scope) {
});
foo.decorator("me", ["$scope", function($scope) {
}]);
});

@@ -847,3 +905,3 @@

angular.module("MyMod").directive("foo", ["$a", "$b", function($a, $b) {
$modal.open({
$uibModal.open({
resolve: {

@@ -905,3 +963,2 @@ collection: (function(_this) {

}
MyCtrl1.$inject = ["a", "b"];
if (true) {

@@ -917,3 +974,2 @@ // proper scope analysis including shadowing

}
MyCtrl2.$inject = ["z"];
funcall(/*@ngInject*/ MyCtrl2); // explicit annotation on reference flows back to definition

@@ -931,3 +987,2 @@

}
MyDirective.$inject = ["$stateProvider"];

@@ -943,3 +998,2 @@ /* @ngInject */

}
MyDirective2.$inject = ["$stateProvider"];

@@ -974,5 +1028,5 @@ // issue 84

/*@ngInject*/
MyCtrl.$inject = ["a"];
function MyCtrl(a) {
}
MyCtrl.$inject = ["a"];

@@ -979,0 +1033,0 @@ return MyCtrl;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc