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 0.14.1 to 0.15.0

2

ng-annotate/build/es5/lut.js
// lut.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

// ng-annotate-main.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -17,3 +17,5 @@ "use strict";

var stringmap = require("stringmap");
var parser = null; // will be lazy-loaded to esprima or acorn
var require_acorn_t0 = Date.now();
var parser = require("acorn").parse;
var require_acorn_t1 = Date.now();

@@ -519,2 +521,3 @@ var chainedRouteProvider = 1;

var quot = ctx.quot;
var blocked = ctx.blocked;

@@ -532,3 +535,3 @@ var suspects = makeUnique(ctx.suspects, 1);

// create final suspects by jumping, following, uniq'ing
// create final suspects by jumping, following, uniq'ing, blocking
var finalSuspects = makeUnique(suspects.map(function(target) {

@@ -542,2 +545,6 @@ var jumped = jumpOverIife(target);

if (blocked.indexOf(jumpedAndFollowed) >= 0) {
return null;
}
return jumpedAndFollowed;

@@ -911,3 +918,21 @@ }).filter(Boolean), 2);

function isAnnotatedArray(node) {
return node.type === "ArrayExpression" && node.elements.length >= 1 && last(node.elements).type === "FunctionExpression";
if (node.type !== "ArrayExpression") {
return false;
}
var elements = node.elements;
// last should be a function expression
if (elements.length === 0 || last(elements).type !== "FunctionExpression") {
return false;
}
// all but last should be string literals
for (var i = 0; i < elements.length - 1; i++) {
var n = elements[i];
if (n.type !== "Literal" || !is.string(n.value)) {
return false;
}
}
return true;
}

@@ -947,38 +972,13 @@ function isFunctionExpressionWithArgs(node) {

stats.parser_require_t0 = Date.now();
if (!options.es6) {
parser = require("esprima").parse;
} else {
parser = require("acorn").parse;
}
stats.parser_require_t1 = Date.now();
try {
stats.parser_require_t0 = require_acorn_t0;
stats.parser_require_t1 = require_acorn_t1;
stats.parser_parse_t0 = Date.now();
if (!options.es6) {
// esprima
ast = parser(src, {
range: true,
comment: true,
loc: true,
});
// Fix Program node range (https://code.google.com/p/esprima/issues/detail?id=541)
ast.range[0] = 0;
// detach comments from ast
comments = ast.comments;
ast.comments = null;
} else {
// acorn
ast = parser(src, {
ecmaVersion: 6,
locations: true,
ranges: true,
onComment: comments,
});
}
// acorn
ast = parser(src, {
ecmaVersion: 6,
locations: true,
ranges: true,
onComment: comments,
});
stats.parser_parse_t1 = Date.now();

@@ -1012,2 +1012,7 @@ } catch(e) {

// blocked is an array of blocked suspects. Any target node
// (final, i.e. IIFE-jumped, reference-followed and such) included
// in blocked will be ignored by judgeSuspects
var blocked = [];
// Position information for all nodes in the AST,

@@ -1033,2 +1038,3 @@ // used for sourcemap generation

suspects: suspects,
blocked: blocked,
lut: lut,

@@ -1062,5 +1068,3 @@ isFunctionExpressionWithArgs: isFunctionExpressionWithArgs,

traverse(ast, {pre: function(node) {
if (node.type === "CallExpression") {
ngInject.inspectCallExpression(node, ctx);
}
ngInject.inspectNode(node, ctx);

@@ -1067,0 +1071,0 @@ }, post: function(node) {

// ng-annotate.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -12,3 +12,3 @@ "use strict";

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

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

@@ -1,4 +0,4 @@

// nginject-comments.js
// nginject.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -11,11 +11,73 @@ "use strict";

inspectComments: inspectComments,
inspectCallExpression: inspectCallExpression,
inspectNode: inspectNode,
};
function inspectNode(node, ctx) {
if (node.type === "CallExpression") {
inspectCallExpression(node, ctx);
} else if (node.type === "FunctionExpression" || node.type === "FunctionDeclaration") {
inspectFunction(node, ctx);
}
}
function inspectCallExpression(node, ctx) {
if (node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "ngInject" && node.arguments.length === 1) {
addSuspect(node.arguments[0], ctx);
var name = node.callee.name;
if (node.callee.type === "Identifier" && (name === "ngInject" || name === "ngNoInject") && node.arguments.length === 1) {
var block = (name === "ngNoInject");
addSuspect(node.arguments[0], ctx, block);
}
}
var ngAnnotatePrologueDirectives = ["ngInject", "ngNoInject"];
function inspectFunction(node, ctx) {
var str = matchPrologueDirectives(ngAnnotatePrologueDirectives, node);
if (!str) {
return;
}
var block = (str === "ngNoInject");
// which node that is the correct suspect in the case of a "ngInject" prologue directive varies
// between adding and removing annotations. when adding, the function (declaration or expression)
// is always the suspect. when removing, the function declaration is the suspect but in the case
// of a function expression, its parent is (because it may be an annotated array). when rebuilding,
// both may be suspects.
// add function node as a suspect, unconditionally (false suspect won't cause a problem here)
addSuspect(node, ctx, block);
if (ctx.mode !== "add") {
// remove or rebuild
// isAnnotatedArray check is there as an extra false-positives safety net
var maybeArrayExpression = node.$parent;
if (ctx.isAnnotatedArray(maybeArrayExpression)) {
addSuspect(maybeArrayExpression, ctx, block);
}
}
}
function matchPrologueDirectives(prologueDirectives, node) {
var body = node.body.body;
var found = null;
for (var i = 0; i < body.length; i++) {
if (body[i].type !== "ExpressionStatement") {
break;
}
var expr = body[i].expression;
var isStringLiteral = (expr.type === "Literal" && typeof expr.value === "string");
if (!isStringLiteral) {
break;
}
if (prologueDirectives.indexOf(expr.value) >= 0) {
found = expr.value;
break;
}
}
return found;
}
function inspectComments(ctx) {

@@ -25,4 +87,5 @@ var comments = ctx.comments;

var comment = comments[i];
var pos = comment.value.indexOf("@ngInject");
if (pos === -1) {
var yesPos = comment.value.indexOf("@ngInject");
var noPos = (yesPos === -1 ? comment.value.indexOf("@ngNoInject") : -1);
if (yesPos === -1 && noPos === -1) {
continue;

@@ -36,7 +99,7 @@ }

addSuspect(target, ctx);
addSuspect(target, ctx, noPos >= 0);
}
}
function addSuspect(target, ctx) {
function addSuspect(target, ctx, block) {
if (target.type === "ObjectExpression") {

@@ -57,15 +120,24 @@ // /*@ngInject*/ {f1: function(a), .., {f2: function(b)}}

target.value.$limitToMethodName = "*never*";
ctx.addModuleContextIndependentSuspect(target.value, ctx);
addOrBlock(target.value, ctx);
} else {
// /*@ngInject*/ function(a) {}
target.$limitToMethodName = "*never*";
ctx.addModuleContextIndependentSuspect(target, ctx);
addOrBlock(target, ctx);
}
}
function addObjectExpression(node, ctx) {
nestedObjectValues(node).forEach(function(n) {
n.$limitToMethodName = "*never*";
ctx.addModuleContextIndependentSuspect(n, ctx);
});
function addObjectExpression(node, ctx) {
nestedObjectValues(node).forEach(function(n) {
n.$limitToMethodName = "*never*";
addOrBlock(n, ctx);
});
}
function addOrBlock(node, ctx) {
if (block) {
ctx.blocked.push(node);
} else {
ctx.addModuleContextIndependentSuspect(node, ctx)
}
}
}

@@ -72,0 +144,0 @@

// run-tests.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -102,6 +102,2 @@ "use strict";

console.log("testing adding annotations using single quotes");
var annotatedSingleQuotes = ngAnnotate(original, {add: true, single_quotes: true}).src;
test(slurp("tests/with_annotations_single.js"), annotatedSingleQuotes, "with_annotations_single.js");
var rename = slurp("tests/rename.js");

@@ -108,0 +104,0 @@

// scope.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

// scopetools.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

@@ -700,3 +700,47 @@ "use strict";

// explicit annotations using "ngInject" Directive Prologue
function Foo2($scope) {
"ngInject";
}
var foo3 = function($scope) {
// comments are ok before the Directive Prologues
// and there may be multiple Prologues
"use strict"; "ngInject";
};
var foo4 = function($scope) {
// not first in function => not Directive Prologues
// so this function won't get annotated
1;
"ngInject";
};
// suppress false positives with /*@ngNoInject*/, ngNoInject() and "ngNoInject"
myMod.controller("suppressed", /*@ngNoInject*/function($scope) {
});
myMod.controller("suppressed", ngNoInject(function($scope) {
}));
myMod.controller("suppressed", function($scope) {
"ngNoInject";
});
// works the same as ngInject i.e. reference-following, IIFE-jumping and so on
/*@ngNoInject*/
myMod.controller("suppressed", SupFoo1);
myMod.controller("suppressed", SupFoo2);
myMod.controller("suppressed", SupFoo3);
function SupFoo1($scope) {
"ngNoInject";
}
/*@ngNoInject*/
function SupFoo2($scope) {
}
var SupFoo3 = ngNoInject(function($scope) {
"ngNoInject";
});
// snippets that shouldn't fool ng-annotate into generating false positives,

@@ -765,2 +809,3 @@ // whether we're inside an angular module or not

var myCtrl10 = (function() {
"use strict";
// the return statement can appear anywhere on the functions topmost level,

@@ -767,0 +812,0 @@ // including before the myCtrl function definition

@@ -723,3 +723,48 @@ "use strict";

// explicit annotations using "ngInject" Directive Prologue
function Foo2($scope) {
"ngInject";
}
Foo2.$inject = ["$scope"];
var foo3 = ["$scope", function($scope) {
// comments are ok before the Directive Prologues
// and there may be multiple Prologues
"use strict"; "ngInject";
}];
var foo4 = function($scope) {
// not first in function => not Directive Prologues
// so this function won't get annotated
1;
"ngInject";
};
// suppress false positives with /*@ngNoInject*/, ngNoInject() and "ngNoInject"
myMod.controller("suppressed", /*@ngNoInject*/function($scope) {
});
myMod.controller("suppressed", ngNoInject(function($scope) {
}));
myMod.controller("suppressed", function($scope) {
"ngNoInject";
});
// works the same as ngInject i.e. reference-following, IIFE-jumping and so on
/*@ngNoInject*/
myMod.controller("suppressed", SupFoo1);
myMod.controller("suppressed", SupFoo2);
myMod.controller("suppressed", SupFoo3);
function SupFoo1($scope) {
"ngNoInject";
}
/*@ngNoInject*/
function SupFoo2($scope) {
}
var SupFoo3 = ngNoInject(function($scope) {
"ngNoInject";
});
// snippets that shouldn't fool ng-annotate into generating false positives,

@@ -789,2 +834,3 @@ // whether we're inside an angular module or not

var myCtrl10 = (function() {
"use strict";
// the return statement can appear anywhere on the functions topmost level,

@@ -791,0 +837,0 @@ // including before the myCtrl function definition

@@ -0,1 +1,7 @@

## v0.15.0 2015-01-15
* "ngInject" directive prologue (usage like "use strict")
* /*@ngNoInject*/, ngNoInject(..) and "ngNoInject" for suppressing false positives
* Acorn is now the default and only parser
* removed the experimental --es6 option and made it the default
## v0.14.1 2014-12-04

@@ -2,0 +8,0 @@ * bugfix /* @ngInject */ not working as expected in case of other matches

// lut.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

// ng-annotate-main.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -17,3 +17,5 @@ "use strict";

const stringmap = require("stringmap");
let parser = null; // will be lazy-loaded to esprima or acorn
const require_acorn_t0 = Date.now();
const parser = require("acorn").parse;
const require_acorn_t1 = Date.now();

@@ -519,2 +521,3 @@ const chainedRouteProvider = 1;

const quot = ctx.quot;
const blocked = ctx.blocked;

@@ -532,3 +535,3 @@ const suspects = makeUnique(ctx.suspects, 1);

// create final suspects by jumping, following, uniq'ing
// create final suspects by jumping, following, uniq'ing, blocking
const finalSuspects = makeUnique(suspects.map(function(target) {

@@ -542,2 +545,6 @@ const jumped = jumpOverIife(target);

if (blocked.indexOf(jumpedAndFollowed) >= 0) {
return null;
}
return jumpedAndFollowed;

@@ -911,3 +918,21 @@ }).filter(Boolean), 2);

function isAnnotatedArray(node) {
return node.type === "ArrayExpression" && node.elements.length >= 1 && last(node.elements).type === "FunctionExpression";
if (node.type !== "ArrayExpression") {
return false;
}
const elements = node.elements;
// last should be a function expression
if (elements.length === 0 || last(elements).type !== "FunctionExpression") {
return false;
}
// all but last should be string literals
for (let i = 0; i < elements.length - 1; i++) {
const n = elements[i];
if (n.type !== "Literal" || !is.string(n.value)) {
return false;
}
}
return true;
}

@@ -947,38 +972,13 @@ function isFunctionExpressionWithArgs(node) {

stats.parser_require_t0 = Date.now();
if (!options.es6) {
parser = require("esprima").parse;
} else {
parser = require("acorn").parse;
}
stats.parser_require_t1 = Date.now();
try {
stats.parser_require_t0 = require_acorn_t0;
stats.parser_require_t1 = require_acorn_t1;
stats.parser_parse_t0 = Date.now();
if (!options.es6) {
// esprima
ast = parser(src, {
range: true,
comment: true,
loc: true,
});
// Fix Program node range (https://code.google.com/p/esprima/issues/detail?id=541)
ast.range[0] = 0;
// detach comments from ast
comments = ast.comments;
ast.comments = null;
} else {
// acorn
ast = parser(src, {
ecmaVersion: 6,
locations: true,
ranges: true,
onComment: comments,
});
}
// acorn
ast = parser(src, {
ecmaVersion: 6,
locations: true,
ranges: true,
onComment: comments,
});
stats.parser_parse_t1 = Date.now();

@@ -1012,2 +1012,7 @@ } catch(e) {

// blocked is an array of blocked suspects. Any target node
// (final, i.e. IIFE-jumped, reference-followed and such) included
// in blocked will be ignored by judgeSuspects
const blocked = [];
// Position information for all nodes in the AST,

@@ -1033,2 +1038,3 @@ // used for sourcemap generation

suspects: suspects,
blocked: blocked,
lut: lut,

@@ -1062,5 +1068,3 @@ isFunctionExpressionWithArgs: isFunctionExpressionWithArgs,

traverse(ast, {pre: function(node) {
if (node.type === "CallExpression") {
ngInject.inspectCallExpression(node, ctx);
}
ngInject.inspectNode(node, ctx);

@@ -1067,0 +1071,0 @@ }, post: function(node) {

// ng-annotate.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

@@ -1,4 +0,4 @@

// nginject-comments.js
// nginject.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -11,11 +11,73 @@ "use strict";

inspectComments: inspectComments,
inspectCallExpression: inspectCallExpression,
inspectNode: inspectNode,
};
function inspectNode(node, ctx) {
if (node.type === "CallExpression") {
inspectCallExpression(node, ctx);
} else if (node.type === "FunctionExpression" || node.type === "FunctionDeclaration") {
inspectFunction(node, ctx);
}
}
function inspectCallExpression(node, ctx) {
if (node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "ngInject" && node.arguments.length === 1) {
addSuspect(node.arguments[0], ctx);
const name = node.callee.name;
if (node.callee.type === "Identifier" && (name === "ngInject" || name === "ngNoInject") && node.arguments.length === 1) {
const block = (name === "ngNoInject");
addSuspect(node.arguments[0], ctx, block);
}
}
const ngAnnotatePrologueDirectives = ["ngInject", "ngNoInject"];
function inspectFunction(node, ctx) {
const str = matchPrologueDirectives(ngAnnotatePrologueDirectives, node);
if (!str) {
return;
}
const block = (str === "ngNoInject");
// which node that is the correct suspect in the case of a "ngInject" prologue directive varies
// between adding and removing annotations. when adding, the function (declaration or expression)
// is always the suspect. when removing, the function declaration is the suspect but in the case
// of a function expression, its parent is (because it may be an annotated array). when rebuilding,
// both may be suspects.
// add function node as a suspect, unconditionally (false suspect won't cause a problem here)
addSuspect(node, ctx, block);
if (ctx.mode !== "add") {
// remove or rebuild
// isAnnotatedArray check is there as an extra false-positives safety net
const maybeArrayExpression = node.$parent;
if (ctx.isAnnotatedArray(maybeArrayExpression)) {
addSuspect(maybeArrayExpression, ctx, block);
}
}
}
function matchPrologueDirectives(prologueDirectives, node) {
const body = node.body.body;
let found = null;
for (let i = 0; i < body.length; i++) {
if (body[i].type !== "ExpressionStatement") {
break;
}
const expr = body[i].expression;
const isStringLiteral = (expr.type === "Literal" && typeof expr.value === "string");
if (!isStringLiteral) {
break;
}
if (prologueDirectives.indexOf(expr.value) >= 0) {
found = expr.value;
break;
}
}
return found;
}
function inspectComments(ctx) {

@@ -25,4 +87,5 @@ const comments = ctx.comments;

const comment = comments[i];
const pos = comment.value.indexOf("@ngInject");
if (pos === -1) {
const yesPos = comment.value.indexOf("@ngInject");
const noPos = (yesPos === -1 ? comment.value.indexOf("@ngNoInject") : -1);
if (yesPos === -1 && noPos === -1) {
continue;

@@ -36,7 +99,7 @@ }

addSuspect(target, ctx);
addSuspect(target, ctx, noPos >= 0);
}
}
function addSuspect(target, ctx) {
function addSuspect(target, ctx, block) {
if (target.type === "ObjectExpression") {

@@ -57,15 +120,24 @@ // /*@ngInject*/ {f1: function(a), .., {f2: function(b)}}

target.value.$limitToMethodName = "*never*";
ctx.addModuleContextIndependentSuspect(target.value, ctx);
addOrBlock(target.value, ctx);
} else {
// /*@ngInject*/ function(a) {}
target.$limitToMethodName = "*never*";
ctx.addModuleContextIndependentSuspect(target, ctx);
addOrBlock(target, ctx);
}
}
function addObjectExpression(node, ctx) {
nestedObjectValues(node).forEach(function(n) {
n.$limitToMethodName = "*never*";
ctx.addModuleContextIndependentSuspect(n, ctx);
});
function addObjectExpression(node, ctx) {
nestedObjectValues(node).forEach(function(n) {
n.$limitToMethodName = "*never*";
addOrBlock(n, ctx);
});
}
function addOrBlock(node, ctx) {
if (block) {
ctx.blocked.push(node);
} else {
ctx.addModuleContextIndependentSuspect(node, ctx)
}
}
}

@@ -72,0 +144,0 @@

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

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

"dependencies": {
"acorn": "~0.9.0",
"acorn": "~0.11.0",
"alter": "~0.2.0",
"convert-source-map": "~0.4.0",
"esprima": "~1.2.0",
"convert-source-map": "~0.4.1",
"optimist": "~0.6.1",

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

"simple-is": "~0.2.0",
"source-map": "~0.1.37",
"source-map": "~0.1.43",
"stable": "~0.1.5",

@@ -29,4 +28,4 @@ "stringmap": "~0.2.2",

"coffee-script": "~1.8.0",
"defs": "~0.6.2",
"diff": "~1.0.8",
"defs": "~1.1.0",
"diff": "~1.2.1",
"find-line-column": "~0.5.2"

@@ -43,3 +42,2 @@ },

"annotations",
"non-intrusive",
"transformation"

@@ -46,0 +44,0 @@ ],

// pos-to-linecolumn.js
// MIT licensed, see LICENSE file
// Copyright (c) 2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2014-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

# 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.
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.
Without annotations:
You write your code without annotations, like this:

@@ -13,3 +14,4 @@ ```js

With annotations:
You then run ng-annotate as a build-step to produce this intermediary,
annotated, result (later sent to the minifier):

@@ -21,21 +23,13 @@ ```js

Annotations are useful because with them you're able to minify your source code using your
favorite JS minifier.
You can also use ng-annotate to rebuild or remove existing annotations.
Rebuilding is useful if you like to check-in the annotated version of your
source code. When refactoring, just change parameter names once and let
ng-annotate rebuild the annotations. Removing is useful if you want to
de-annotate an existing codebase that came with checked-in annotations
*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.
## 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"](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.
## Installation and usage

@@ -58,4 +52,2 @@

*experimental* Use the `--es6` option for ES6 support via the Acorn parser.
Use the `--sourcemap` option to generate an inline sourcemap.

@@ -84,9 +76,6 @@

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](https://docs.angularjs.org/api/ng/directive/ngApp)).
any missing dependency injection annotations. [ng-strict-di](https://docs.angularjs.org/api/ng/directive/ngApp)
is available in AngularJS 1.3 or later.
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

@@ -101,2 +90,3 @@ * [Grunt](http://gruntjs.com/): [grunt-ng-annotate](https://www.npmjs.org/package/grunt-ng-annotate) by [Michał Gołębiowski](https://github.com/mzgol)

* [Webpack](http://webpack.github.io/): [ng-annotate-webpack-plugin](https://www.npmjs.org/package/ng-annotate-webpack-plugin) by [Chris Liechty](https://github.com/cliechty)
* [Middleman](http://middlemanapp.com/): [middleman-ngannotate](http://rubygems.org/gems/middleman-ngannotate) by [Michael Siebert](https://github.com/siebertm)
* Something missing? Contributions welcome - create plugin and submit a README pull request!

@@ -109,11 +99,2 @@

## 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

@@ -186,3 +167,2 @@ ng-annotate understands the two common declaration forms:

## Reference-following
ng-annotate follows references. This works iff the referenced declaration is

@@ -204,33 +184,48 @@ a) a function declaration or

## 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. Alternatively, you can wrap an expression
inside an `ngInject(..)` function call. Use `/* @ngInject */` or `ngInject(..)` as an occasional
workaround when ng-annotate doesn't support your code style but feel free to open an issue
also.
## 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) {};
x = /*@ngInject*/ function($scope) {};
obj = {controller: /*@ngInject*/ function($scope) {}};
obj.bar = /*@ngInject*/ function($scope) {};
function ngInject(f) { return f } // define this once in your program
x = ngInject(function($scope) {});
obj = {controller: ngInject(function($scope) {})};
obj.bar = ngInject(function($scope) {});
=>
x = /* @ngInject */ ["$scope", function($scope) {}];
x = /*@ngInject*/ ["$scope", function($scope) {}];
obj = {controller: /*@ngInject*/ ["$scope", function($scope) {}]};
obj.bar = /*@ngInject*/ ["$scope", function($scope) {}];
function ngInject(f) { return f } // define this once in your program
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
Prepended to an object literal, `/*@ngInject*/` will annotate all of its contained
function expressions, recursively:

@@ -244,7 +239,2 @@

obj = ngInject({
controller: function($scope) {},
resolve: { data: function(Service) {} },
});
=>

@@ -256,7 +246,2 @@

};
obj = ngInject({
controller: ["$scope", function($scope) {}],
resolve: { data: ["Service", function(Service) {}] },
});
```

@@ -266,3 +251,3 @@

function expression or to an assignment where the rvalue is a function expression,
`/* @ngInject */` will attach an `$inject` array to the function:
`/*@ngInject*/` will attach an `$inject` array to the function:

@@ -294,7 +279,3 @@ ```js

## 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](https://github.com/olov/ng-annotate/issues?state=open).
## Build and test

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

## 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.
## 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)

@@ -321,0 +311,0 @@ ng-annotate can be used as a library. See [ng-annotate.js](ng-annotate.js) for further info about

// run-tests.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -102,6 +102,2 @@ "use strict";

console.log("testing adding annotations using single quotes");
const annotatedSingleQuotes = ngAnnotate(original, {add: true, single_quotes: true}).src;
test(slurp("tests/with_annotations_single.js"), annotatedSingleQuotes, "with_annotations_single.js");
const rename = slurp("tests/rename.js");

@@ -108,0 +104,0 @@

// scope.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

// scopetools.js
// MIT licensed, see LICENSE file
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
// Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>

@@ -5,0 +5,0 @@ "use strict";

@@ -700,3 +700,47 @@ "use strict";

// explicit annotations using "ngInject" Directive Prologue
function Foo2($scope) {
"ngInject";
}
var foo3 = function($scope) {
// comments are ok before the Directive Prologues
// and there may be multiple Prologues
"use strict"; "ngInject";
};
var foo4 = function($scope) {
// not first in function => not Directive Prologues
// so this function won't get annotated
1;
"ngInject";
};
// suppress false positives with /*@ngNoInject*/, ngNoInject() and "ngNoInject"
myMod.controller("suppressed", /*@ngNoInject*/function($scope) {
});
myMod.controller("suppressed", ngNoInject(function($scope) {
}));
myMod.controller("suppressed", function($scope) {
"ngNoInject";
});
// works the same as ngInject i.e. reference-following, IIFE-jumping and so on
/*@ngNoInject*/
myMod.controller("suppressed", SupFoo1);
myMod.controller("suppressed", SupFoo2);
myMod.controller("suppressed", SupFoo3);
function SupFoo1($scope) {
"ngNoInject";
}
/*@ngNoInject*/
function SupFoo2($scope) {
}
var SupFoo3 = ngNoInject(function($scope) {
"ngNoInject";
});
// snippets that shouldn't fool ng-annotate into generating false positives,

@@ -765,2 +809,3 @@ // whether we're inside an angular module or not

var myCtrl10 = (function() {
"use strict";
// the return statement can appear anywhere on the functions topmost level,

@@ -767,0 +812,0 @@ // including before the myCtrl function definition

@@ -723,3 +723,48 @@ "use strict";

// explicit annotations using "ngInject" Directive Prologue
function Foo2($scope) {
"ngInject";
}
Foo2.$inject = ["$scope"];
var foo3 = ["$scope", function($scope) {
// comments are ok before the Directive Prologues
// and there may be multiple Prologues
"use strict"; "ngInject";
}];
var foo4 = function($scope) {
// not first in function => not Directive Prologues
// so this function won't get annotated
1;
"ngInject";
};
// suppress false positives with /*@ngNoInject*/, ngNoInject() and "ngNoInject"
myMod.controller("suppressed", /*@ngNoInject*/function($scope) {
});
myMod.controller("suppressed", ngNoInject(function($scope) {
}));
myMod.controller("suppressed", function($scope) {
"ngNoInject";
});
// works the same as ngInject i.e. reference-following, IIFE-jumping and so on
/*@ngNoInject*/
myMod.controller("suppressed", SupFoo1);
myMod.controller("suppressed", SupFoo2);
myMod.controller("suppressed", SupFoo3);
function SupFoo1($scope) {
"ngNoInject";
}
/*@ngNoInject*/
function SupFoo2($scope) {
}
var SupFoo3 = ngNoInject(function($scope) {
"ngNoInject";
});
// snippets that shouldn't fool ng-annotate into generating false positives,

@@ -789,2 +834,3 @@ // whether we're inside an angular module or not

var myCtrl10 = (function() {
"use strict";
// the return statement can appear anywhere on the functions topmost level,

@@ -791,0 +837,0 @@ // including before the myCtrl function definition

Sorry, the diff of this file is not supported yet

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