Giter Site home page Giter Site logo

ng-annotate's Introduction

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.

Without annotations:

angular.module("MyMod").controller("MyCtrl", function($scope, $timeout) {
});

With annotations:

angular.module("MyMod").controller("MyCtrl", ["$scope", "$timeout", function($scope, $timeout) {
}]);

Annotations are useful because with them you're able to minify your source code using your favorite JS minifier.

How does ng-annotate compare to ngmin?

If you are currently using ngmin then this is probably your first question. 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".

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 and replacing ngmin with ngAnnotate in their Gruntfile. Scroll down for information about other tools.

Installation and usage

npm install -g ng-annotate

Then run it as ng-annotate OPTIONS <file>. The errors (if any) will go to stderr, the transpiled output to stdout.

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.

Use the -o option to write output to file.

Provide - instead of an input <file> to read input from stdin.

Use the --single_quotes option to output '$scope' instead of "$scope".

Use the --regexp option to restrict matching further or to expand matching. See description further down.

Use the --plugin option to load a user plugin with the provided path (experimental, 0.9.x may change API). See plugin-example.js for more info.

Use the --stats option to print statistics on stderr (experimental).

Highly recommended: enable ng-strict-di in your minified builds

<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. This is an upcoming feature in AngularJS 1.3 (docs).

A future version of ng-annotate may get support for adding the ng-strict-di attribute automatically so you don't have to think about it.

Tools support

Changes

See CHANGES.md.

Why?

  • Keep your code base clutter free from annotations but add them in your build step prior to minimizing
  • De-clutter an existing code base by removing annotations, non-intrusively
  • If you must store annotations in the repo (for any reason) then checkout, remove them, code and refactor without annotations, add them back and commit. Alternatively checkout, code and refactor (ignoring annotations), rebuild them and commit.

Declaration forms

ng-annotate understands the two common declaration forms:

Long form:

angular.module("MyMod").controller("MyCtrl", function($scope, $timeout) {
});

Short form:

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 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) ..) and other methods on provide such as factory.

ng-annotate understands $routeProvider.when("path", { .. }).

ng-annotate understands $httpProvider.interceptors.push(function($scope) ..) and $httpProvider.responseInterceptors.push(function($scope) ..).

ng-annotate understands ui-router ($stateProvider and $urlRouterProvider).

ng-annotate understands $modal.open (angular-ui/bootstrap). experimental

ng-annotate understands chaining.

Explicit annotations

You can prepend a function expression with /* @ngInject */ to explicitly state that this function should get annotated. ng-annotate will leave the comment intact and will thus still be able to also remove or rewrite such annotations. Use /* @ngInject */ as an occasional workaround when ng-annotate doesn't support your code style but feel free to open an issue also.

var x = /* @ngInject */ function($scope) {};
obj = {controller: /*@ngInject*/ function($scope) {}};
obj.bar = /*@ngInject*/ function($scope) {};

=>

var 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:

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:

// @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"];

Issues and compatibility

If ng-annotate does not handle a construct you're using, if there's a bug or if you have a feature request then please file an issue.

Build and test

ng-annotate is written in ES6 constlet style and uses defs.js to transpile to ES5. See BUILD.md for build and test instructions.

License

MIT, see LICENSE file.

ng-annotate is written by Olov Lassus with the kind help by contributors. Follow @olov on Twitter for updates about ng-annotate.

Performance

ng-annotate is designed to be very fast (in general limited by parse speed). It traverses the AST exactly once and transforms it without the need for an AST -> source decompilation step.

Library (API)

ng-annotate can be used as a library. See ng-annotate.js for further info about options and return value.

var ngAnnotate = require("ng-annotate");
var somePlugin = require("./some/path/some-plugin");
var res = ngAnnotate(src, {add: true, plugin: [somePlugin]})
var errorstringArray = res.errors;
var transformedSource = res.src;

ng-annotate's People

Contributors

olov avatar duncanbeevers avatar anotherchrisberry avatar craigburke avatar frapontillo avatar pgilad avatar smrq avatar rubensayshi avatar treymack avatar

Watchers

Jaanek Oja avatar James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.