diff --git a/Gruntfile.js b/Gruntfile.js
index 47d30f509c5f..032039096aea 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -346,7 +346,7 @@ module.exports = function(grunt) {
grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']);
grunt.registerTask('webserver', ['connect:devserver']);
- grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
+ grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'write', 'docs', 'copy', 'compress']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'eslint']);
grunt.registerTask('default', ['package']);
};
diff --git a/docs/app/src/app.js b/docs/app/src/app.js
index 607cc0f0e1ec..df6272b0bf0b 100644
--- a/docs/app/src/app.js
+++ b/docs/app/src/app.js
@@ -6,7 +6,6 @@ angular.module('docsApp', [
'ngSanitize',
'ngAnimate',
'DocsController',
- 'versionsData',
'pagesData',
'navData',
'directives',
diff --git a/docs/app/src/docs.js b/docs/app/src/docs.js
index cb06ec646c45..e2bd613a0f90 100644
--- a/docs/app/src/docs.js
+++ b/docs/app/src/docs.js
@@ -1,12 +1,12 @@
'use strict';
-angular.module('DocsController', [])
+angular.module('DocsController', ['currentVersionData'])
.controller('DocsController', [
'$scope', '$rootScope', '$location', '$window', '$cookies',
- 'NG_PAGES', 'NG_NAVIGATION', 'NG_VERSION',
+ 'NG_PAGES', 'NG_NAVIGATION', 'CURRENT_NG_VERSION',
function($scope, $rootScope, $location, $window, $cookies,
- NG_PAGES, NG_NAVIGATION, NG_VERSION) {
+ NG_PAGES, NG_NAVIGATION, CURRENT_NG_VERSION) {
$scope.navClass = function(navItem) {
return {
@@ -58,8 +58,8 @@ angular.module('DocsController', [])
Initialize
***********************************/
- $scope.versionNumber = NG_VERSION.full;
- $scope.version = NG_VERSION.full + ' ' + NG_VERSION.codeName;
+ $scope.versionNumber = CURRENT_NG_VERSION.full;
+ $scope.version = CURRENT_NG_VERSION.full + ' ' + CURRENT_NG_VERSION.codeName;
$scope.loading = 0;
diff --git a/docs/app/src/versions.js b/docs/app/src/versions.js
index 04abeedc5615..9f0d3dc0c5c4 100644
--- a/docs/app/src/versions.js
+++ b/docs/app/src/versions.js
@@ -1,37 +1,42 @@
'use strict';
+/* global console */
-angular.module('versions', [])
+angular.module('versions', ['currentVersionData', 'allVersionsData'])
-.controller('DocsVersionsCtrl', ['$scope', '$location', '$window', 'NG_VERSIONS', function($scope, $location, $window, NG_VERSIONS) {
- $scope.docs_version = NG_VERSIONS[0];
- $scope.docs_versions = NG_VERSIONS;
+.directive('versionPicker', function() {
+ return {
+ restrict: 'E',
+ scope: true,
+ controllerAs: '$ctrl',
+ controller: ['$location', '$window', 'CURRENT_NG_VERSION', 'ALL_NG_VERSIONS',
+ /** @this VersionPickerController */
+ function VersionPickerController($location, $window, CURRENT_NG_VERSION, ALL_NG_VERSIONS) {
- for (var i = 0, minor = NaN; i < NG_VERSIONS.length; i++) {
- var version = NG_VERSIONS[i];
- if (version.isSnapshot) {
- version.isLatest = true;
- continue;
- }
- // NaN will give false here
- if (minor <= version.minor) {
- continue;
- }
- version.isLatest = true;
- minor = version.minor;
- }
+ var versionStr = CURRENT_NG_VERSION.isSnapshot ? 'snapshot' : CURRENT_NG_VERSION.version;
- $scope.getGroupName = function(v) {
- return v.isLatest ? 'Latest' : ('v' + v.major + '.' + v.minor + '.x');
+ this.versions = ALL_NG_VERSIONS;
+ this.selectedVersion = find(ALL_NG_VERSIONS, function(value) { return value.version.version === versionStr; });
+
+ this.jumpToDocsVersion = function(value) {
+ var currentPagePath = $location.path().replace(/\/$/, '');
+ $window.location = value.docsUrl + currentPagePath;
+ };
+ }],
+ template:
+ '
' +
+ ' ' +
+ '
'
};
- $scope.jumpToDocsVersion = function(version) {
- var currentPagePath = $location.path().replace(/\/$/, ''),
- url = '';
- if (version.isOldDocsUrl) {
- url = version.docsUrl;
- } else {
- url = version.docsUrl + currentPagePath;
+ function find(collection, matcherFn) {
+ for (var i = 0, ii = collection.length; i < ii; ++i) {
+ if (matcherFn(collection[i])) {
+ return collection[i];
+ }
}
- $window.location = url;
- };
-}]);
+ }
+});
diff --git a/docs/app/test/docsSpec.js b/docs/app/test/docsSpec.js
index 905a6d511181..d5424ef2ff79 100644
--- a/docs/app/test/docsSpec.js
+++ b/docs/app/test/docsSpec.js
@@ -6,8 +6,13 @@ describe('DocsController', function() {
angular.module('fake', [])
.value('$cookies', {})
.value('NG_PAGES', {})
- .value('NG_NAVIGATION', {})
- .value('NG_VERSION', {});
+ .value('NG_NAVIGATION', {});
+
+ angular.module('currentVersionData', [])
+ .value('CURRENT_NG_VERSION', {});
+
+ angular.module('allVersionsData', [])
+ .value('ALL_NG_VERSIONS', {});
beforeEach(module('fake', 'DocsController'));
beforeEach(inject(function($rootScope, $controller) {
diff --git a/docs/config/processors/versions-data.js b/docs/config/processors/versions-data.js
index 5e0fa94cb7e0..8b8d0fd52d36 100644
--- a/docs/config/processors/versions-data.js
+++ b/docs/config/processors/versions-data.js
@@ -1,6 +1,7 @@
'use strict';
-var _ = require('lodash');
+var exec = require('shelljs').exec;
+var semver = require('semver');
/**
* @dgProcessor generateVersionDocProcessor
@@ -12,23 +13,96 @@ module.exports = function generateVersionDocProcessor(gitData) {
return {
$runAfter: ['generatePagesDataProcessor'],
$runBefore: ['rendering-docs'],
+ // the blacklist is to remove rogue builds that are in npm but not on code.angularjs.org
+ blacklist: ['1.3.4-build.3588'],
$process: function(docs) {
- var versionDoc = {
- docType: 'versions-data',
- id: 'versions-data',
- template: 'versions-data.template.js',
- outputPath: 'js/versions-data.js',
- currentVersion: gitData.version
- };
-
- versionDoc.versions = _(gitData.versions)
- .filter(function(version) { return version.major > 0; })
- .push(gitData.version)
- .reverse()
- .value();
-
- docs.push(versionDoc);
+ var blacklist = this.blacklist;
+ var currentVersion = require('../../../build/version.json');
+ var output = exec('npm info angular versions --json', { silent: true }).stdout;
+ var allVersions = processAllVersionsResponse(JSON.parse(output));
+
+ docs.push({
+ docType: 'current-version-data',
+ id: 'current-version-data',
+ template: 'angular-service.template.js',
+ outputPath: 'js/current-version-data.js',
+ ngModuleName: 'currentVersionData',
+ serviceName: 'CURRENT_NG_VERSION',
+ serviceValue: currentVersion
+ });
+
+ docs.push({
+ docType: 'allversions-data',
+ id: 'allversions-data',
+ template: 'angular-service.template.js',
+ outputPath: 'js/all-versions-data.js',
+ ngModuleName: 'allVersionsData',
+ serviceName: 'ALL_NG_VERSIONS',
+ serviceValue: allVersions
+ });
+
+
+ function processAllVersionsResponse(versions) {
+
+ var latestMap = {};
+
+ versions = versions
+ .filter(function(versionStr) {
+ return blacklist.indexOf(versionStr) === -1;
+ })
+ .map(function(versionStr) {
+ return semver.parse(versionStr);
+ })
+ .filter(function(version) {
+ return version && version.major > 0;
+ })
+ .map(function(version) {
+ var key = version.major + '.' + version.minor;
+ var latest = latestMap[key];
+ if (!latest || version.compare(latest) > 0) {
+ latestMap[key] = version;
+ }
+ return version;
+ })
+ .map(function(version) {
+ return makeOption(version);
+ })
+ .reverse();
+
+ var latest = sortObject(latestMap, reverse(semver.compare))
+ .map(function(version) { return makeOption(version, 'Latest'); });
+
+ return [makeOption({version: 'snapshot'}, 'Latest', 'master')]
+ .concat(latest)
+ .concat(versions);
+ }
+
+ function makeOption(version, group, label) {
+ return {
+ version: version,
+ label: label || 'v' + version.raw,
+ group: group || 'v' + version.major + '.' + version.minor,
+ docsUrl: createDocsUrl(version)
+ };
+ }
+
+ function createDocsUrl(version) {
+ var url = 'https://code.angularjs.org/' + version.version + '/docs';
+ // Versions before 1.0.2 had a different docs folder name
+ if (version.major === 1 && version.minor === 0 && version.patch < 2) {
+ url += '-' + version.version;
+ }
+ return url;
+ }
+
+ function reverse(fn) {
+ return function(left, right) { return -fn(left, right); };
+ }
+
+ function sortObject(obj, cmp) {
+ return Object.keys(obj).map(function(key) { return obj[key]; }).sort(cmp);
+ }
}
};
};
diff --git a/docs/config/services/deployments/debug.js b/docs/config/services/deployments/debug.js
index 991474c47ea0..f7381b129697 100644
--- a/docs/config/services/deployments/debug.js
+++ b/docs/config/services/deployments/debug.js
@@ -22,7 +22,8 @@ module.exports = function debugDeployment(getVersion) {
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
- 'js/versions-data.js',
+ 'js/current-version-data.js',
+ 'js/all-versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.js'
diff --git a/docs/config/services/deployments/default.js b/docs/config/services/deployments/default.js
index 5a10e4dbddf0..c489946d8884 100644
--- a/docs/config/services/deployments/default.js
+++ b/docs/config/services/deployments/default.js
@@ -22,7 +22,8 @@ module.exports = function defaultDeployment(getVersion) {
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
- 'js/versions-data.js',
+ 'js/current-version-data.js',
+ 'js/all-versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.min.js'
diff --git a/docs/config/services/deployments/jquery.js b/docs/config/services/deployments/jquery.js
index b480b9f50056..b224830af43a 100644
--- a/docs/config/services/deployments/jquery.js
+++ b/docs/config/services/deployments/jquery.js
@@ -26,7 +26,8 @@ module.exports = function jqueryDeployment(getVersion) {
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
- 'js/versions-data.js',
+ 'js/current-version-data.js',
+ 'js/all-versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.min.js'
diff --git a/docs/config/services/deployments/production.js b/docs/config/services/deployments/production.js
index 112d20889520..2e090bf3d5a9 100644
--- a/docs/config/services/deployments/production.js
+++ b/docs/config/services/deployments/production.js
@@ -39,7 +39,8 @@ module.exports = function productionDeployment(getVersion) {
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
- 'js/versions-data.js',
+ 'js/current-version-data.js',
+ 'https://code.angularjs.org/snapshot/docs/js/all-versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.min.js'
diff --git a/docs/config/templates/angular-service.template.js b/docs/config/templates/angular-service.template.js
new file mode 100644
index 000000000000..c44925dcde96
--- /dev/null
+++ b/docs/config/templates/angular-service.template.js
@@ -0,0 +1,4 @@
+'use strict';
+
+angular.module('{$ doc.ngModuleName $}', [])
+ .value('{$ doc.serviceName $}', {$ doc.serviceValue | json $});
diff --git a/docs/config/templates/indexPage.template.html b/docs/config/templates/indexPage.template.html
index a97fc9e6ed55..884763dcc838 100644
--- a/docs/config/templates/indexPage.template.html
+++ b/docs/config/templates/indexPage.template.html
@@ -165,13 +165,7 @@ {{ key }}