ng-annotate.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /**
  2. * grunt-ng-annotate
  3. * https://github.com/mzgol/grunt-ng-annotate
  4. *
  5. * Author Michał Gołębiowski <m.goleb@gmail.com>
  6. * Licensed under the MIT license.
  7. */
  8. 'use strict';
  9. var path = require('path');
  10. var _ = require('lodash');
  11. var ngAnnotate = require('ng-annotate');
  12. module.exports = function (grunt) {
  13. function getPathFromTo(fromFile, toFile) {
  14. return path.relative(path.resolve(path.dirname(fromFile)), path.resolve(toFile))
  15. // URLs should have UNIX-y paths.
  16. .replace(/\\/g, '/');
  17. }
  18. function handleOptions(options) {
  19. var sourceMapOptions;
  20. if (!options.ngAnnotateOptions) {
  21. options.ngAnnotateOptions = {};
  22. }
  23. if (options.add != null) {
  24. options.ngAnnotateOptions.add = options.add;
  25. delete options.add;
  26. } else {
  27. options.ngAnnotateOptions.add = true;
  28. }
  29. if (options.remove != null) {
  30. options.ngAnnotateOptions.remove = options.remove;
  31. delete options.remove;
  32. } else {
  33. options.ngAnnotateOptions.remove = false;
  34. }
  35. if (options.regexp != null) {
  36. options.ngAnnotateOptions.regexp = options.regexp;
  37. delete options.regexp;
  38. }
  39. if (options.singleQuotes != null) {
  40. options.ngAnnotateOptions.single_quotes = options.singleQuotes;
  41. delete options.singleQuotes;
  42. }
  43. if (options.sourceMap) {
  44. sourceMapOptions = options.ngAnnotateOptions.sourcemap = {};
  45. sourceMapOptions.inline = options.sourceMap === true;
  46. }
  47. if (options.transformDest != null) {
  48. grunt.fail.fatal(
  49. [
  50. 'The `transformDest` option is no longer supported.',
  51. 'The following configuration:',
  52. '',
  53. ' app: {',
  54. ' options: {',
  55. ' transformDest: function (srcPath) {',
  56. ' return doSomethingWithSrcPath(srcPath);',
  57. ' },',
  58. ' },',
  59. ' src: [\'app/*.js\'],',
  60. ' },',
  61. '',
  62. 'should be replaced by:',
  63. '',
  64. ' app: {',
  65. ' files: [',
  66. ' {',
  67. ' expand: true,',
  68. ' src: [\'app/*.js\'],',
  69. ' rename: function (destPath, srcPath) {',
  70. ' return doSomethingWithSrcPath(srcPath);',
  71. ' },',
  72. ' },',
  73. ' ],',
  74. ' },',
  75. ].join('\n')
  76. );
  77. }
  78. if (options.outputFileSuffix != null) {
  79. grunt.fail.fatal(
  80. [
  81. 'The `outputFileSuffix` option is no longer supported.',
  82. 'The following configuration:',
  83. '',
  84. ' app: {',
  85. ' options: {',
  86. ' outputFileSuffix: \'-annotated\',',
  87. ' },',
  88. ' src: [\'app/*.js\'],',
  89. ' },',
  90. '',
  91. 'should be replaced by:',
  92. '',
  93. ' app: {',
  94. ' files: [',
  95. ' {',
  96. ' expand: true,',
  97. ' src: [\'app/*.js\'],',
  98. ' rename: function (destPath, srcPath) {',
  99. ' return srcPath + \'-annotated\';',
  100. ' },',
  101. ' },',
  102. ' ],',
  103. ' },',
  104. ].join('\n')
  105. );
  106. }
  107. }
  108. grunt.registerMultiTask('ngAnnotate',
  109. 'Add, remove and rebuild AngularJS dependency injection annotations',
  110. function () {
  111. var filesNum = 0,
  112. validRun = true,
  113. // Merge task-specific and/or target-specific options with these defaults.
  114. options = this.options();
  115. handleOptions(options);
  116. // Iterate over all specified file groups.
  117. this.files.forEach(function (mapping) {
  118. if (!runNgAnnotate(mapping, options)) {
  119. validRun = false;
  120. }
  121. });
  122. function runNgAnnotate(mapping, options) {
  123. filesNum++;
  124. var ngAnnotateOptions = _.cloneDeep(options.ngAnnotateOptions);
  125. if (ngAnnotateOptions.sourcemap) {
  126. if (mapping.src.length > 1) {
  127. grunt.fail.fatal('The ngAnnotate task doesn\'t support source maps with many-to-one mappings.');
  128. }
  129. ngAnnotateOptions.sourcemap.inFile = getPathFromTo(mapping.dest, mapping.src[0]);
  130. }
  131. var concatenatedSource = mapping.src.map(function (file) {
  132. return grunt.file.read(file);
  133. }).join(';\n');
  134. var ngAnnotateOutput = ngAnnotate(concatenatedSource, ngAnnotateOptions);
  135. // Write the destination file.
  136. if (ngAnnotateOutput.errors) {
  137. grunt.log.write('Generating "' + mapping.dest + '" from: "' + mapping.src.join('", "') + '"...');
  138. grunt.log.error();
  139. ngAnnotateOutput.errors.forEach(function (error) {
  140. grunt.log.error(error);
  141. });
  142. return false;
  143. }
  144. // Write ngAnnotate output (and a source map if requested) to the target file.
  145. if (ngAnnotateOptions.sourcemap && !ngAnnotateOptions.sourcemap.inline) {
  146. ngAnnotateOutput.src +=
  147. '\n//# sourceMappingURL=' + getPathFromTo(mapping.dest, options.sourceMap);
  148. grunt.file.write(options.sourceMap, ngAnnotateOutput.map);
  149. }
  150. grunt.file.write(mapping.dest, ngAnnotateOutput.src);
  151. return true;
  152. }
  153. if (validRun) {
  154. if (filesNum < 1) {
  155. grunt.log.ok('No files provided to the ngAnnotate task.');
  156. } else {
  157. grunt.log.ok(filesNum + (filesNum === 1 ? ' file' : ' files') + ' successfully generated.');
  158. }
  159. }
  160. return validRun;
  161. });
  162. };