From b4d877542b9f9eb9248155d1de8adf0f5de22582 Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Wed, 11 Dec 2013 23:33:41 +0100 Subject: [PATCH 1/5] chore(grunt): adds grunt-ngdocs plugin also integrates it into existing grunt configuration. this is just the basic stuff, developer guide and tutorial to come. --- Gruntfile.js | 12 ++++++++++++ package.json | 13 ++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 66de24c05..74d80b9c7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -93,6 +93,18 @@ module.exports = function (grunt) { options: { dest: 'CHANGELOG.md' } + }, + ngdocs: { + options: { + dest: 'site', + html5Mode: false, + title: 'UI Router', + startPage: '/api', + }, + api: { + src: ['src/**/*.js'], + title: 'API Reference' + } } }); diff --git a/package.json b/package.json index b5e79face..7dd3a92eb 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,12 @@ "web": "https://github.com/ksperling" } ], - "maintainers": [{ - "name": "AngularUI", - "web": "https://github.com/angular-ui?tab=members" - }], + "maintainers": [ + { + "name": "AngularUI", + "web": "https://github.com/angular-ui?tab=members" + } + ], "repository": { "type": "git", "url": "https://github.com/angular-ui/ui-router.git" @@ -58,6 +60,7 @@ "karma": "~0.10.4", "karma-phantomjs-launcher": "~0.1.0", "load-grunt-tasks": "~0.2.0", - "grunt-conventional-changelog": "~1.0.0" + "grunt-conventional-changelog": "~1.0.0", + "grunt-ngdocs": "~0.1.7" } } From 15eaaf2a381934c9a546448477d327c7a44893aa Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Wed, 11 Dec 2013 23:34:08 +0100 Subject: [PATCH 2/5] docs(ui.router.compat): adds docs for ui.router.compat module --- src/common.js | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/common.js b/src/common.js index 323d31e03..1dd8489e2 100644 --- a/src/common.js +++ b/src/common.js @@ -164,9 +164,55 @@ function filterByKeys(keys, values) { return filtered; } +/** + * @ngdoc overview + * @name ui.router.util + * + * @description + * + */ angular.module('ui.router.util', ['ng']); + +/** + * @ngdoc overview + * @name ui.router.router + * + * @requires ui.router.util + * + * @description + * + */ angular.module('ui.router.router', ['ui.router.util']); + +/** + * @ngdoc overview + * @name ui.router.router + * + * @requires ui.router.router + * @requires ui.router.util + * + * @description + * + */ angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']); + +/** + * @ngdoc overview + * @name ui.router + * + * @requires ui.router.state + * + * @description + * + */ angular.module('ui.router', ['ui.router.state']); +/** + * @ngdoc overview + * @name ui.router.compat + * + * @requires ui.router + * + * @description + * + */ angular.module('ui.router.compat', ['ui.router']); - From ed02f294eb03d52f72c82432e597116a30f60898 Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Wed, 11 Dec 2013 23:35:42 +0100 Subject: [PATCH 3/5] docs(routerProvider): adds docs for routerProvider --- src/compat.js | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/compat.js b/src/compat.js index 63d092d93..ad30839d7 100644 --- a/src/compat.js +++ b/src/compat.js @@ -1,3 +1,21 @@ +/** + * @ngdoc object + * @name ui.router.compat.$routeProvider + * + * @requires ui.router.state.$stateProvider + * @requires ui.router.router.$urlRouterProvider + * + * @description + * `$routeProvider` of the `ui.router.compat` module overwrites the existing + * `routeProvider` from the core. This is done to provide compatibility between + * the UI Router and the core router. + * + * It also provides a `when()` method to register routes that map to certain urls. + * Behind the scenes it actually delegates either to + * {@link ui.router.router.$urlRouterProvider $urlRouterProvider} or to the + * {@link ui.router.state.$stateProvider $stateProvider} to postprocess the given + * router definition object. + */ $RouteProvider.$inject = ['$stateProvider', '$urlRouterProvider']; function $RouteProvider( $stateProvider, $urlRouterProvider) { @@ -17,6 +35,32 @@ function $RouteProvider( $stateProvider, $urlRouterProvider) { } this.when = when; + /** + * @ngdoc function + * @name ui.router.compat.$routeProvider#when + * @methodOf ui.router.compat.$routeProvider + * + * @description + * Registers a route with a given route definition object. The route definition + * object has the same interface the angular core route definition object has. + * + * @example + *
+   * var app = angular.module('app', ['ui.router.compat']);
+   *
+   * app.config(function ($routeProvider) {
+   *   $routeProvider.when('home', {
+   *     controller: function () { ... },
+   *     templateUrl: 'path/to/template'
+   *   });
+   * });
+   * 
+ * + * @param {string} url URL as string + * @param {object} route Route definition object + * + * @return {object} $routeProvider - $routeProvider instance + */ function when(url, route) { /*jshint validthis: true */ if (route.redirectTo != null) { @@ -47,6 +91,24 @@ function $RouteProvider( $stateProvider, $urlRouterProvider) { return this; } + /** + * @ngdoc object + * @name ui.router.compat.$route + * + * @requires ui.router.state.$state + * @requires $rootScope + * @requires $routeParams + * + * @property {object} routes - Array of registered routes. + * @property {object} params - Current route params as object. + * @property {string} current - Name of the current route. + * + * @description + * The `$route` service provides interfaces to access defined routes. It also let's + * you access route params through `$routeParams` service, so you have fully + * control over all the stuff you would actually get from angular's core `$route` + * service. + */ this.$get = $get; $get.$inject = ['$state', '$rootScope', '$routeParams']; function $get( $state, $rootScope, $routeParams) { From 3f06e377c6ef1f6391b5c1eecbec1c32366f3cb4 Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Wed, 11 Dec 2013 23:36:03 +0100 Subject: [PATCH 4/5] docs(urlRouter): adds docs for urlRouter --- src/urlRouter.js | 143 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 1 deletion(-) diff --git a/src/urlRouter.js b/src/urlRouter.js index 6bc0ac89a..8bc72fc60 100644 --- a/src/urlRouter.js +++ b/src/urlRouter.js @@ -1,4 +1,18 @@ - +/** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider + * + * @requires ui.router.util.$urlMatcherFactoryProvider + * + * @description + * `$urlRouterProvider` has the responsibility of watching `$location`. + * When `$location` changes it runs through a list of rules one by one until a + * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify + * a url in a state configuration. All urls are compiled into a UrlMatcher object. + * + * There are several methods on `$urlRouterProvider` that make it useful to use directly + * in your module config. + */ $UrlRouterProvider.$inject = ['$urlMatcherFactoryProvider']; function $UrlRouterProvider( $urlMatcherFactory) { var rules = [], @@ -17,6 +31,37 @@ function $UrlRouterProvider( $urlMatcherFactory) { }); } + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#rule + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines rules that are used by `$urlRouterProvider to find matches for + * specific URLs. + * + * @example + *
+   * var app = angular.module('app', ['ui.router.router']);
+   *
+   * app.config(function ($urlRouterProvider) {
+   *   // Here's an example of how you might allow case insensitive urls
+   *   $urlRouterProvider.rule(function ($injector, $location) {
+   *     var path = $location.path(),
+   *         normalized = path.toLowerCase();
+   *
+   *     if (path !== normalized) {
+   *       return normalized;
+   *     }
+   *   });
+   * });
+   * 
+ * + * @param {object} rule Handler function that takes `$injector` and `$location` + * services as arguments. You can use them to return a valid path as a string. + * + * @return {object} $urlRouterProvider - $urlRouterProvider instance + */ this.rule = function (rule) { if (!isFunction(rule)) throw new Error("'rule' must be a function"); @@ -24,6 +69,37 @@ function $UrlRouterProvider( $urlMatcherFactory) { return this; }; + /** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider#otherwise + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines a path that is used when an invalied route is requested. + * + * @example + *
+   * var app = angular.module('app', ['ui.router.router']);
+   *
+   * app.config(function ($urlRouterProvider) {
+   *   // if the path doesn't match any of the urls you configured
+   *   // otherwise will take care of routing the user to the
+   *   // specified url
+   *   $urlRouterProvider.otherwise('/index');
+   *
+   *   // Example of using function rule as param
+   *   $urlRouterProvider.otherwise(function ($injector, $location) {
+   *     ...
+   *   });
+   * });
+   * 
+ * + * @param {string|object} rule The url path you want to redirect to or a function + * rule that returns the url path. The function version is passed two params: + * `$injector` and `$location` services. + * + * @return {object} $urlRouterProvider - $urlRouterProvider instance + */ this.otherwise = function (rule) { if (isString(rule)) { @@ -42,6 +118,43 @@ function $UrlRouterProvider( $urlMatcherFactory) { return isDefined(result) ? result : true; } + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#when + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Registers a handler for a given url matching. if handle is a string, it is + * treated as a redirect, and is interpolated according to the syyntax of match + * (i.e. like String.replace() for RegExp, or like a UrlMatcher pattern otherwise). + * + * If the handler is a function, it is injectable. It gets invoked if `$location` + * matches. You have the option of inject the match object as `$match`. + * + * The handler can return + * + * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter` + * will continue trying to find another one that matches. + * - **string** which is treated as a redirect and passed to `$location.url()` + * - **void** or any **truthy** value tells `$urlRouter` that the url was handled. + * + * @example + *
+   * var app = angular.module('app', ['ui.router.router']);
+   *
+   * app.config(function ($urlRouterProvider) {
+   *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
+   *     if ($state.$current.navigable !== state ||
+   *         !equalForKeys($match, $stateParams) {
+   *      $state.transitionTo(state, $match, false);
+   *     }
+   *   });
+   * });
+   * 
+ * + * @param {string|object} what The incoming path that you want to redirect. + * @param {string|object} handler The path you want to redirect your user to. + */ this.when = function (what, handler) { var redirect, handlerIsString = isString(handler); @@ -88,6 +201,17 @@ function $UrlRouterProvider( $urlMatcherFactory) { throw new Error("invalid 'what' in when()"); }; + /** + * @ngdoc object + * @name ui.router.router.$urlRouter + * + * @requires $location + * @requires $rootScope + * @requires $injector + * + * @description + * + */ this.$get = [ '$location', '$rootScope', '$injector', function ($location, $rootScope, $injector) { @@ -113,6 +237,23 @@ function $UrlRouterProvider( $urlMatcherFactory) { $rootScope.$on('$locationChangeSuccess', update); return { + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#sync + * @methodOf ui.router.router.$urlRouter + * + * @description + * Checks registered rules until first rule is handled. + * + * @example + *
+         * var app = angular.module('app', ['ui.router.router']);
+         *
+         * app.run(function ($urlRouter) {
+         *   $urlRouter.sync();
+         * });
+         * 
+ */ sync: function () { update(); } From 558d0df9086147d832f817b21e55e148cc12de11 Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Thu, 12 Dec 2013 00:18:13 +0100 Subject: [PATCH 5/5] docs(): wip docs for ui.router.state --- src/state.js | 115 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 3 deletions(-) diff --git a/src/state.js b/src/state.js index ed9c985ef..fffa02e66 100644 --- a/src/state.js +++ b/src/state.js @@ -1,3 +1,25 @@ +/** + * @ngdoc object + * @name ui.router.state.$stateProvider + * + * @requires ui.router.router.$urlRouterProvider + * @requires ui.router.util.$urlMatcherFactoryProvider + * @requires $locationProvider + * + * @description + * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely + * on state. + * + * A state corresponds to a "place" in the application in terms of the overall UI and + * navigation. A state describes (via the controller / template / view properties) what + * the UI looks like and does at that place. + * + * States often have things in common, and the primary way of factoring out these + * commonalities in this model is via the state hierarchy, i.e. parent/child states aka + * nested states. + * + * The `$stateProvider` provides interfaces to declare these states for your app. + */ $StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider', '$locationProvider']; function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $locationProvider) { @@ -207,9 +229,96 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $ root.navigable = null; - // .decorator() - // .decorator(name) - // .decorator(name, function) + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#decorator + * @methodOf ui.router.state.$stateProvider + * + * @description + * Allows you to extend (carefully) or override (at your own peril) the + * `stateBuilder` object used internally by `$stateProvider`. This can be used + * to add custom functionality to ui-router, for example inferring templateUrl + * based on the state name. + * + * When passing only a name, it returns the current (original or decorated) builder + * function that matches `name`. + * + * The builder functions that can be decorated are listed below. Though not all + * necessarily have a good use case for decoration, that is up to you to decide. + * + * In addition, users can attach custom decorators, which will generate new + * properties within the state's internal definition. There is currently no clear + * use-case for this beyond accessing internal states (i.e. $state.$current), + * however, expect this to become increasingly relevant as we introduce additional + * meta-programming features. + * + * **Warning**: Decorators should not be interdependent because the order of + * execution of the builder functions in nondeterministic. Builder functions + * should only be dependent on the state definition object and super function. + * + * + * Existing builder functions and current return values: + * + * - parent - `{object}` - returns the parent state object. + * - data - `{object}` - returns state data, including any inherited data that is not + * overridden by own values (if any). + * - url - `{object}` - returns a UrlMatcher or null. + * - navigable - returns closest ancestor state that has a URL (aka is + * navigable). + * - params - `{object}` - returns an array of state params that are ensured to + * be a super-set of parent's params. + * - views - `{object}` - returns a views object where each key is an absolute view + * name (i.e. "viewName@stateName") and each value is the config object + * (template, controller) for the view. Even when you don't use the views object + * explicitly on a state config, one is still created for you internally. + * So by decorating this builder function you have access to decorating template + * and controller properties. + * - ownParams - `{object}` - returns an array of params that belong to the state, + * not including any params defined by ancestor states. + * - path - `{string}` - returns the full path from the root down to this state. + * Needed for state activation. + * - includes - `{object}` - returns an object that includes every state that + * would pass a '$state.includes()' test. + * + * @example + *
+   * // Override the internal 'views' builder with a function that takes the state
+   * // definition, and a reference to the internal function being overridden:
+   * $stateProvider.decorator('views', function ($state, parent) {
+   *   var result = {},
+   *       views = parent(state);
+   *
+   *   angular.forEach(view, function (config, name) {
+   *     var autoName = (state.name + '.' + name).replace('.', '/');
+   *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
+   *     result[name] = config;
+   *   });
+   *   return result;
+   * });
+   *
+   * $stateProvider.state('home', {
+   *   views: {
+   *     'contact.list': { controller: 'ListController' },
+   *     'contact.item': { controller: 'ItemController' }
+   *   }
+   * });
+   *
+   * // ...
+   *
+   * $state.go('home');
+   * // Auto-populates list and item views with /partials/home/contact/list.html,
+   * // and /partials/home/contact/item.html, respectively.
+   * 
+ * + * @param {string} name The name of the builder function to decorate. + * @param {object} func A function that is responsible for decorating the original + * builder function. The function receives two parameters: + * + * - `{object}` - state - The state config object. + * - `{object}` - super - The original builder function. + * + * @return {object} $stateProvider - $stateProvider instance + */ this.decorator = decorator; function decorator(name, func) { /*jshint validthis: true */