diff --git a/Gruntfile.js b/Gruntfile.js index 1d5f35426d2b..968b2b820e44 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -191,6 +191,6 @@ module.exports = function(grunt) { grunt.registerTask('minify', ['shell:bower','clean', 'build', 'minall']); grunt.registerTask('test:e2e', ['connect:testserver', 'test:end2end']); grunt.registerTask('webserver', ['connect:devserver']); - grunt.registerTask('package', ['shell:bower','clean', 'buildall', 'minall', 'docs', 'copy', 'write', 'compress']); + grunt.registerTask('package', ['shell:bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']); grunt.registerTask('default', ['package']); }; diff --git a/bower.json b/bower.json index 8bdcc8389d8d..fc916a0212c8 100644 --- a/bower.json +++ b/bower.json @@ -6,6 +6,7 @@ "google-code-prettify": "1.0.0", "components-font-awesome": "3.1.0", "bootstrap": "https://raw.github.com/twitter/bootstrap/v2.0.2/docs/assets/bootstrap.zip", - "closure-compiler": "https://closure-compiler.googlecode.com/files/compiler-20130603.zip" + "closure-compiler": "https://closure-compiler.googlecode.com/files/compiler-20130603.zip", + "ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.1/assets/ng-closure-runner.zip" } } diff --git a/lib/grunt/plugins.js b/lib/grunt/plugins.js index ca2d6ec627c1..aaf1e73ef7cd 100644 --- a/lib/grunt/plugins.js +++ b/lib/grunt/plugins.js @@ -59,4 +59,8 @@ module.exports = function(grunt) { grunt.registerMultiTask('autotest', 'Run and watch the unit tests with Karma', function(){ util.startKarma.call(util, this.data, false, this.async()); }); + + grunt.registerTask('collect-errors', 'Combine stripped error files', function () { + util.collectErrors(); + }); }; diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index 1696c226fc07..09281b8aea34 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -134,12 +134,18 @@ module.exports = { var minFile = file.replace(/\.js$/, '.min.js'); var mapFile = minFile + '.map'; var mapFileName = mapFile.match(/[^\/]+$/)[0]; + var errorFileName = file.replace(/\.js$/, '-errors.json'); shell.exec( 'java ' + this.java32flags() + ' ' + - '-jar components/closure-compiler/compiler.jar ' + + '-cp ./components/closure-compiler/compiler.jar' + + ':./components/ng-closure-runner/ngcompiler.jar ' + + 'org.angularjs.closurerunner.NgClosureRunner ' + '--compilation_level SIMPLE_OPTIMIZATIONS ' + '--language_in ECMASCRIPT5_STRICT ' + + '--minerr_pass ' + + '--minerr_errors ' + errorFileName + ' ' + + '--minerr_url \'http://docs.angularjs.org/minerr/\' ' + '--source_map_format=V3 ' + '--create_source_map ' + mapFile + ' ' + '--js ' + file + ' ' + @@ -167,6 +173,44 @@ module.exports = { }, + //collects and combines error messages stripped out in minify step + collectErrors: function () { + var combined = { + id: 'ng', + generated: new Date().toString(), + errors: {} + }; + grunt.file.expand('build/*-errors.json').forEach(function (file) { + var errors = grunt.file.readJSON(file), + namespace; + Object.keys(errors).forEach(function (prop) { + if (typeof errors[prop] === 'object') { + namespace = errors[prop]; + if (combined.errors[prop]) { + Object.keys(namespace).forEach(function (code) { + if (combined.errors[prop][code] && combined.errors[prop][code] !== namespace[code]) { + grunt.warn('[collect-errors] Duplicate minErr codes don\'t match!'); + } else { + combined.errors[prop][code] = namespace[code]; + } + }); + } else { + combined.errors[prop] = namespace; + } + } else { + if (combined.errors[prop] && combined.errors[prop] !== errors[prop]) { + grunt.warn('[collect-errors] Duplicate minErr codes don\'t match!'); + } else { + combined.errors[prop] = errors[prop]; + } + } + }); + }); + grunt.file.write('build/errors.json', JSON.stringify(combined)); + grunt.file.expand('build/*-errors.json').forEach(grunt.file.delete); + }, + + //csp connect middleware csp: function(){ return function(req, res, next){