ngannotate-rails 0.9.2 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2dd7c00767bd1657fbdda31a2b51ceba108b0e24
4
- data.tar.gz: 31b2eb5ae4c37392f5f907da4eec8d3052114a3f
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTU4MjFkOTczODkxOTFmZjMwYjhiYWJhNzJmNGU2YmU0OTNlZWQ5Yw==
5
+ data.tar.gz: !binary |-
6
+ MDdlMjViMzY1YzgwNmE3MWUxOWZiOTFmMTA0NjgxNWZkMzUyMTA0NQ==
5
7
  SHA512:
6
- metadata.gz: 1783b877d258c6fa88d1aa9a4999e8e7484857c3965777972ec9f896f5f7ce16a63ed355919503d3ea279e234426ec3b1804a8c5d67444dcb54bf55ff7f57feb
7
- data.tar.gz: 7bd95be1b3cb4bc7a4229124bc5a1a05c8ddbde5a66f575b0da6df832207bbbdc8c44639b7f3c20de8dc514aab46b5eedad933afbeb3510e887173c5a3108e24
8
+ metadata.gz: !binary |-
9
+ NzNmODlhNjg2MWMwNTJiOWQ2YmViNWUxZTUzZmM0YTAzNTBmYzU5OTE0YTkz
10
+ OTE5ZDk5N2RlMGFjNTI0ZjQxZTkzNjg0OWE1NDdmNGZjYjk0NjBmNmZmYjU4
11
+ ZTFhNThhMzkxNTRiZTEwYTYzNzBkNWMzMjZkM2RkOTQxNGUxMjk=
12
+ data.tar.gz: !binary |-
13
+ MmQ2N2Q4YzczMjJkMjM3OWM3NDNjYTIwMWRlMjY4YjhmYzhiZDQ3YzM1Mzc4
14
+ YzhkMzVkYjI4OWVhNTE5ZjgxODhlOTQyYWYyYThiMDczMWEzMjY0MTc1ZjFk
15
+ M2FkMTg1MTBhMTdmZDUxMDRlYmUxZmExNzE1ZmUzMjY5OTE5Y2E=
@@ -7,13 +7,37 @@ module Ngannotate
7
7
  end
8
8
 
9
9
  def prepare
10
+ return if skip
10
11
  ngannotate_source = File.open(File.join(File.dirname(__FILE__), '../../vendor/ngannotate.js')).read
11
12
  @context = ExecJS.compile "window = {};" + ngannotate_source
12
13
  end
13
14
 
15
+ #
16
+ # Skip processing in environments where it does not make sense
17
+ #
18
+ def skip
19
+ ::Rails.env.development? || ::Rails.env.test?
20
+ end
21
+
14
22
  def evaluate(context, locals)
15
- r = @context.call 'window.annotate', data, { add: true }
23
+ return data if skip
24
+
25
+ opt = { add: true }.merge!(parse_opt)
26
+ r = @context.call 'window.annotate', data, opt
16
27
  r['src']
17
28
  end
29
+
30
+ def parse_opt
31
+ opt = {}
32
+ opt_str = ENV['NG_OPT']
33
+ if opt_str
34
+ opt = Hash[opt_str.split(',').map { |e| e.split('=') }]
35
+ opt.symbolize_keys!
36
+ end
37
+ if ENV['NG_REGEXP']
38
+ opt[:regexp] = ENV['NG_REGEXP']
39
+ end
40
+ opt
41
+ end
18
42
  end
19
43
  end
@@ -1,5 +1,5 @@
1
1
  module Ngannotate
2
2
  module Rails
3
- VERSION = "0.9.2"
3
+ VERSION = "0.9.5"
4
4
  end
5
5
  end
@@ -1121,8 +1121,6 @@ function match(node, re, matchPlugins) {
1121
1121
  }
1122
1122
 
1123
1123
  function matchDirectiveReturnObject(node) {
1124
- // TODO make these more strict by checking that we're inside an angular module?
1125
-
1126
1124
  // return { .. controller: function($scope, $timeout), ...}
1127
1125
 
1128
1126
  return node.type === "ReturnStatement" &&
@@ -1131,8 +1129,6 @@ function matchDirectiveReturnObject(node) {
1131
1129
  }
1132
1130
 
1133
1131
  function matchProviderGet(node) {
1134
- // TODO make these more strict by checking that we're inside an angular module?
1135
-
1136
1132
  // (this|self|that).$get = function($scope, $timeout)
1137
1133
  // { ... $get: function($scope, $timeout), ...}
1138
1134
  var memberExpr;
@@ -1194,7 +1190,7 @@ function matchNgUi(node) {
1194
1190
  // onExit: function($scope)
1195
1191
  // });
1196
1192
  // $stateProvider.state("myState", {... resolve: {f: function($scope) {}, ..} ..})
1197
- // $stateProvider.state("myState", {... views: {... somename: {... controller: fn, templateProvider: fn, resolve: {f: fn}}}})
1193
+ // $stateProvider.state("myState", {... views: {... somename: {... controller: fn, controllerProvider: fn, templateProvider: fn, resolve: {f: fn}}}})
1198
1194
  //
1199
1195
  // $urlRouterProvider.when(.., function($scope) {})
1200
1196
  //
@@ -1263,6 +1259,7 @@ function matchNgUi(node) {
1263
1259
  viewObject.properties.forEach(function(prop) {
1264
1260
  if (prop.value.type === "ObjectExpression") {
1265
1261
  res.push(matchProp("controller", prop.value.properties));
1262
+ res.push(matchProp("controllerProvider", prop.value.properties));
1266
1263
  res.push(matchProp("templateProvider", prop.value.properties));
1267
1264
  res.push.apply(res, matchResolve(prop.value.properties));
1268
1265
  }
@@ -1306,9 +1303,14 @@ function matchRegular(node, re) {
1306
1303
  }
1307
1304
 
1308
1305
  var args = node.arguments;
1309
- return (is.someof(method.name, ["config", "run"]) ?
1306
+ var target = (is.someof(method.name, ["config", "run"]) ?
1310
1307
  args.length === 1 && args[0] :
1311
1308
  args.length === 2 && args[0].type === "Literal" && is.string(args[0].value) && args[1]);
1309
+
1310
+ if (target) {
1311
+ target.$always = true;
1312
+ }
1313
+ return target;
1312
1314
  }
1313
1315
 
1314
1316
  // Short form: *.controller("MyCtrl", function($scope, $timeout) {});
@@ -1406,21 +1408,46 @@ function removeArray(array, fragments) {
1406
1408
  });
1407
1409
  }
1408
1410
 
1409
- function replaceRemoveOrInsertArrayForTarget(target, ctx) {
1411
+ function judgeSuspects(ctx) {
1412
+ var suspects = ctx.suspects;
1410
1413
  var mode = ctx.mode;
1411
1414
  var fragments = ctx.fragments;
1412
1415
  var quot = ctx.quot;
1413
1416
 
1414
- if (mode === "rebuild" && isAnnotatedArray(target)) {
1415
- replaceArray(target, fragments, quot);
1416
- } else if (mode === "remove" && isAnnotatedArray(target)) {
1417
- removeArray(target, fragments);
1418
- } else if (is.someof(mode, ["add", "rebuild"]) && isFunctionExpressionWithArgs(target)) {
1419
- insertArray(target, fragments, quot);
1420
- } else {
1421
- return false;
1417
+ for (var i = 0; i < suspects.length; i++) {
1418
+ var target = suspects[i];
1419
+
1420
+ if (target.$once) {
1421
+ continue;
1422
+ }
1423
+ target.$once = true;
1424
+
1425
+ if (!target.$always) {
1426
+ var $caller = target.$caller;
1427
+ for (; $caller && $caller.$chained !== chainedRegular; $caller = $caller.$caller) {
1428
+ }
1429
+ if (!$caller) {
1430
+ continue;
1431
+ }
1432
+ }
1433
+
1434
+ if (mode === "rebuild" && isAnnotatedArray(target)) {
1435
+ replaceArray(target, fragments, quot);
1436
+ } else if (mode === "remove" && isAnnotatedArray(target)) {
1437
+ removeArray(target, fragments);
1438
+ } else if (is.someof(mode, ["add", "rebuild"]) && isFunctionExpressionWithArgs(target)) {
1439
+ insertArray(target, fragments, quot);
1440
+ }
1422
1441
  }
1423
- return true;
1442
+ }
1443
+
1444
+ function addModuleContextDependentSuspect(target, ctx) {
1445
+ ctx.suspects.push(target);
1446
+ }
1447
+
1448
+ function addModuleContextIndependentSuspect(target, ctx) {
1449
+ target.$always = true;
1450
+ ctx.suspects.push(target);
1424
1451
  }
1425
1452
 
1426
1453
  function isAnnotatedArray(node) {
@@ -1485,6 +1512,14 @@ window.annotate = function ngAnnotate(src, options) {
1485
1512
  // first node at (or after) a certain pos
1486
1513
  var triggers = new Heap();
1487
1514
 
1515
+ // suspects is built up with suspect nodes by match.
1516
+ // A suspect node will get annotations added / removed if it
1517
+ // fulfills the arrayexpression or functionexpression look,
1518
+ // and if it is in the correct context (inside an angular
1519
+ // module definition) - alternatively is forced to ignore
1520
+ // context with node.$always = true
1521
+ var suspects = [];
1522
+
1488
1523
  var ctx = {
1489
1524
  mode: mode,
1490
1525
  quot: quot,
@@ -1492,10 +1527,12 @@ window.annotate = function ngAnnotate(src, options) {
1492
1527
  comments: comments,
1493
1528
  fragments: fragments,
1494
1529
  triggers: triggers,
1530
+ suspects: suspects,
1495
1531
  isFunctionExpressionWithArgs: isFunctionExpressionWithArgs,
1496
1532
  isFunctionDeclarationWithArgs: isFunctionDeclarationWithArgs,
1497
1533
  isAnnotatedArray: isAnnotatedArray,
1498
- replaceRemoveOrInsertArrayForTarget: replaceRemoveOrInsertArrayForTarget,
1534
+ addModuleContextDependentSuspect: addModuleContextDependentSuspect,
1535
+ addModuleContextIndependentSuspect: addModuleContextIndependentSuspect,
1499
1536
  stringify: stringify,
1500
1537
  };
1501
1538
 
@@ -1516,13 +1553,26 @@ window.annotate = function ngAnnotate(src, options) {
1516
1553
  plugin.init(ctx);
1517
1554
  });
1518
1555
 
1556
+ var recentCaller = undefined; // micro-optimization
1557
+ var callerIds = [];
1519
1558
  traverse(ast, {pre: function(node) {
1559
+ node.$caller = recentCaller;
1560
+ if (node.type === "CallExpression") {
1561
+ callerIds.push(node);
1562
+ recentCaller = node;
1563
+ }
1564
+
1520
1565
  var pos = node.range[0];
1521
1566
  while (pos >= triggers.pos) {
1522
1567
  var trigger = triggers.getAndRemoveNext();
1523
1568
  trigger.fn.call(null, node, trigger.ctx);
1524
1569
  }
1525
1570
  }, post: function(node) {
1571
+ if (node === recentCaller) {
1572
+ callerIds.pop();
1573
+ recentCaller = last(callerIds);
1574
+ }
1575
+
1526
1576
  var targets = match(node, re, matchPluginsOrNull);
1527
1577
  if (!targets) {
1528
1578
  return;
@@ -1531,12 +1581,13 @@ window.annotate = function ngAnnotate(src, options) {
1531
1581
  targets = [targets];
1532
1582
  }
1533
1583
 
1534
- // TODO add something to know that node has been altered so it won't happen again
1535
1584
  for (var i = 0; i < targets.length; i++) {
1536
- replaceRemoveOrInsertArrayForTarget(targets[i], ctx);
1585
+ addModuleContextDependentSuspect(targets[i], ctx);
1537
1586
  }
1538
1587
  }});
1539
1588
 
1589
+ judgeSuspects(ctx);
1590
+
1540
1591
  var out = alter(src, fragments);
1541
1592
 
1542
1593
  return {
@@ -1573,27 +1624,59 @@ function ngInjectCommentsInit(ctx) {
1573
1624
  ctx.triggers.addMany(triggers);
1574
1625
  }
1575
1626
 
1627
+ function nestedObjectValues(node, res) {
1628
+ res = res || [];
1629
+
1630
+ node.properties.forEach(function(prop) {
1631
+ var v = prop.value;
1632
+ if (is.someof(v.type, ["FunctionExpression", "ArrayExpression"])) {
1633
+ res.push(v);
1634
+ } else if (v.type === "ObjectExpression") {
1635
+ nestedObjectValues(v, res);
1636
+ }
1637
+ });
1638
+
1639
+ return res;
1640
+ }
1641
+
1576
1642
  function visitNodeFollowingNgInjectComment(node, ctx) {
1577
- // TODO objectliteral (if add or remove)
1643
+ // handle most common case: /*@ngInject*/ prepended to an array or function expression
1644
+ if (node.type === "ArrayExpression" || node.type === "FunctionExpression") {
1645
+ ctx.addModuleContextIndependentSuspect(node, ctx);
1646
+ return;
1647
+ }
1578
1648
 
1579
- if (ctx.replaceRemoveOrInsertArrayForTarget(node, ctx)) {
1649
+ if (node.type === "ObjectExpression") {
1650
+ nestedObjectValues(node).forEach(function(n) {
1651
+ ctx.addModuleContextIndependentSuspect(n, ctx);
1652
+ });
1580
1653
  return;
1581
1654
  }
1582
1655
 
1583
- // var foo = function($scope) {}
1656
+ // /*@ngInject*/ var foo = function($scope) {} and
1657
+ // /*@ngInject*/ function foo($scope) {}
1584
1658
  var d0 = null;
1585
1659
  var nr1 = node.range[1];
1586
1660
  if (node.type === "VariableDeclaration" && node.declarations.length === 1 &&
1587
1661
  (d0 = node.declarations[0]).init && ctx.isFunctionExpressionWithArgs(d0.init)) {
1588
1662
  var isSemicolonTerminated = (ctx.src[nr1 - 1] === ";");
1589
- addRemoveInjectsArray(d0.init.params, isSemicolonTerminated ? nr1 : d0.init.range[1], d0.id.name);
1663
+ addRemoveInjectArray(d0.init.params, isSemicolonTerminated ? nr1 : d0.init.range[1], d0.id.name);
1590
1664
  } else if (ctx.isFunctionDeclarationWithArgs(node)) {
1591
- addRemoveInjectsArray(node.params, nr1, node.id.name);
1665
+ addRemoveInjectArray(node.params, nr1, node.id.name);
1592
1666
  }
1593
1667
 
1668
+ function getIndent(pos) {
1669
+ var src = ctx.src;
1670
+ var lineStart = src.lastIndexOf("\n", pos - 1) + 1;
1671
+ var i = lineStart;
1672
+ for (; src[i] === " " || src[i] === "\t"; i++) {
1673
+ }
1674
+ return src.slice(lineStart, i);
1675
+ }
1594
1676
 
1595
- function addRemoveInjectsArray(params, posAfterFunctionDeclaration, name) {
1596
- var str = fmt("\n{0}.$injects = {1};", name, ctx.stringify(params, ctx.quot));
1677
+ function addRemoveInjectArray(params, posAfterFunctionDeclaration, name) {
1678
+ var indent = getIndent(posAfterFunctionDeclaration);
1679
+ var str = fmt("\n{0}{1}.$inject = {2};", indent, name, ctx.stringify(params, ctx.quot));
1597
1680
 
1598
1681
  ctx.triggers.add({
1599
1682
  pos: posAfterFunctionDeclaration,
@@ -1603,24 +1686,24 @@ function visitNodeFollowingNgInjectComment(node, ctx) {
1603
1686
  function visitNodeFollowingFunctionDeclaration(nextNode) {
1604
1687
  var assignment = nextNode.expression;
1605
1688
  var lvalue;
1606
- var hasInjectsArray = (nextNode.type === "ExpressionStatement" && assignment.type === "AssignmentExpression" &&
1689
+ var hasInjectArray = (nextNode.type === "ExpressionStatement" && assignment.type === "AssignmentExpression" &&
1607
1690
  assignment.operator === "=" &&
1608
1691
  (lvalue = assignment.left).type === "MemberExpression" &&
1609
- lvalue.computed === false && lvalue.object.name === name && lvalue.property.name === "$injects");
1692
+ lvalue.computed === false && lvalue.object.name === name && lvalue.property.name === "$inject");
1610
1693
 
1611
- if (ctx.mode === "rebuild" && hasInjectsArray) {
1694
+ if (ctx.mode === "rebuild" && hasInjectArray) {
1612
1695
  ctx.fragments.push({
1613
1696
  start: posAfterFunctionDeclaration,
1614
1697
  end: nextNode.range[1],
1615
1698
  str: str,
1616
1699
  });
1617
- } else if (ctx.mode === "remove" && hasInjectsArray) {
1700
+ } else if (ctx.mode === "remove" && hasInjectArray) {
1618
1701
  ctx.fragments.push({
1619
1702
  start: posAfterFunctionDeclaration,
1620
1703
  end: nextNode.range[1],
1621
1704
  str: "",
1622
1705
  });
1623
- } else if (is.someof(ctx.mode, ["add", "rebuild"]) && !hasInjectsArray) {
1706
+ } else if (is.someof(ctx.mode, ["add", "rebuild"]) && !hasInjectArray) {
1624
1707
  ctx.fragments.push({
1625
1708
  start: posAfterFunctionDeclaration,
1626
1709
  end: posAfterFunctionDeclaration,
@@ -3196,8 +3279,6 @@ parseStatement: true, parseSourceElement: true */
3196
3279
  }
3197
3280
  }
3198
3281
 
3199
- peek();
3200
-
3201
3282
  if (extra.trailingComments.length > 0) {
3202
3283
  if (extra.trailingComments[0].range[0] >= node.range[1]) {
3203
3284
  trailingComments = extra.trailingComments;
@@ -5521,7 +5602,7 @@ parseStatement: true, parseSourceElement: true */
5521
5602
  }
5522
5603
 
5523
5604
  // Sync with *.json manifests.
5524
- exports.version = '1.2.1';
5605
+ exports.version = '1.2.2';
5525
5606
 
5526
5607
  exports.tokenize = tokenize;
5527
5608
 
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ngannotate-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kari Ikonen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-21 00:00:00.000000000 Z
11
+ date: 2014-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.1'
27
27
  - !ruby/object:Gem::Dependency
@@ -42,14 +42,14 @@ dependencies:
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  description: Use ngannotate in the Rails asset pipeline.
@@ -82,17 +82,17 @@ require_paths:
82
82
  - lib
83
83
  required_ruby_version: !ruby/object:Gem::Requirement
84
84
  requirements:
85
- - - '>='
85
+ - - ! '>='
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  required_rubygems_version: !ruby/object:Gem::Requirement
89
89
  requirements:
90
- - - '>='
90
+ - - ! '>='
91
91
  - !ruby/object:Gem::Version
92
92
  version: '0'
93
93
  requirements: []
94
94
  rubyforge_project:
95
- rubygems_version: 2.0.3
95
+ rubygems_version: 2.2.2
96
96
  signing_key:
97
97
  specification_version: 4
98
98
  summary: Use ngannotate in the Rails asset pipeline.