UNPKG

@uirouter/core

Version:

UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps

202 lines 8.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseUrlRule = exports.UrlRuleFactory = void 0; var urlMatcher_1 = require("./urlMatcher"); var predicates_1 = require("../common/predicates"); var common_1 = require("../common/common"); var hof_1 = require("../common/hof"); var stateObject_1 = require("../state/stateObject"); /** * Creates a [[UrlRule]] * * Creates a [[UrlRule]] from a: * * - `string` * - [[UrlMatcher]] * - `RegExp` * - [[StateObject]] */ var UrlRuleFactory = /** @class */ (function () { function UrlRuleFactory(router) { this.router = router; } UrlRuleFactory.prototype.compile = function (str) { return this.router.urlMatcherFactory.compile(str); }; UrlRuleFactory.prototype.create = function (what, handler) { var _this = this; var isState = stateObject_1.StateObject.isState, isStateDeclaration = stateObject_1.StateObject.isStateDeclaration; var makeRule = hof_1.pattern([ [predicates_1.isString, function (_what) { return makeRule(_this.compile(_what)); }], [hof_1.is(urlMatcher_1.UrlMatcher), function (_what) { return _this.fromUrlMatcher(_what, handler); }], [hof_1.or(isState, isStateDeclaration), function (_what) { return _this.fromState(_what, _this.router); }], [hof_1.is(RegExp), function (_what) { return _this.fromRegExp(_what, handler); }], [predicates_1.isFunction, function (_what) { return new BaseUrlRule(_what, handler); }], ]); var rule = makeRule(what); if (!rule) throw new Error("invalid 'what' in when()"); return rule; }; /** * A UrlRule which matches based on a UrlMatcher * * The `handler` may be either a `string`, a [[UrlRuleHandlerFn]] or another [[UrlMatcher]] * * ## Handler as a function * * If `handler` is a function, the function is invoked with: * * - matched parameter values ([[RawParams]] from [[UrlMatcher.exec]]) * - url: the current Url ([[UrlParts]]) * - router: the router object ([[UIRouter]]) * * #### Example: * ```js * var urlMatcher = $umf.compile("/foo/:fooId/:barId"); * var rule = factory.fromUrlMatcher(urlMatcher, match => "/home/" + match.fooId + "/" + match.barId); * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' } * var result = rule.handler(match); // '/home/123/456' * ``` * * ## Handler as UrlMatcher * * If `handler` is a UrlMatcher, the handler matcher is used to create the new url. * The `handler` UrlMatcher is formatted using the matched param from the first matcher. * The url is replaced with the result. * * #### Example: * ```js * var urlMatcher = $umf.compile("/foo/:fooId/:barId"); * var handler = $umf.compile("/home/:fooId/:barId"); * var rule = factory.fromUrlMatcher(urlMatcher, handler); * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' } * var result = rule.handler(match); // '/home/123/456' * ``` */ UrlRuleFactory.prototype.fromUrlMatcher = function (urlMatcher, handler) { var _handler = handler; if (predicates_1.isString(handler)) handler = this.router.urlMatcherFactory.compile(handler); if (hof_1.is(urlMatcher_1.UrlMatcher)(handler)) _handler = function (match) { return handler.format(match); }; function matchUrlParamters(url) { var params = urlMatcher.exec(url.path, url.search, url.hash); return urlMatcher.validates(params) && params; } // Prioritize URLs, lowest to highest: // - Some optional URL parameters, but none matched // - No optional parameters in URL // - Some optional parameters, some matched // - Some optional parameters, all matched function matchPriority(params) { var optional = urlMatcher.parameters().filter(function (param) { return param.isOptional; }); if (!optional.length) return 0.000001; var matched = optional.filter(function (param) { return params[param.id]; }); return matched.length / optional.length; } var details = { urlMatcher: urlMatcher, matchPriority: matchPriority, type: 'URLMATCHER' }; return common_1.extend(new BaseUrlRule(matchUrlParamters, _handler), details); }; /** * A UrlRule which matches a state by its url * * #### Example: * ```js * var rule = factory.fromState($state.get('foo'), router); * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' } * var result = rule.handler(match); * // Starts a transition to 'foo' with params: { fooId: '123', barId: '456' } * ``` */ UrlRuleFactory.prototype.fromState = function (stateOrDecl, router) { var state = stateObject_1.StateObject.isStateDeclaration(stateOrDecl) ? stateOrDecl.$$state() : stateOrDecl; /** * Handles match by transitioning to matched state * * First checks if the router should start a new transition. * A new transition is not required if the current state's URL * and the new URL are already identical */ var handler = function (match) { var $state = router.stateService; var globals = router.globals; if ($state.href(state, match) !== $state.href(globals.current, globals.params)) { $state.transitionTo(state, match, { inherit: true, source: 'url' }); } }; var details = { state: state, type: 'STATE' }; return common_1.extend(this.fromUrlMatcher(state.url, handler), details); }; /** * A UrlRule which matches based on a regular expression * * The `handler` may be either a [[UrlRuleHandlerFn]] or a string. * * ## Handler as a function * * If `handler` is a function, the function is invoked with: * * - regexp match array (from `regexp`) * - url: the current Url ([[UrlParts]]) * - router: the router object ([[UIRouter]]) * * #### Example: * ```js * var rule = factory.fromRegExp(/^\/foo\/(bar|baz)$/, match => "/home/" + match[1]) * var match = rule.match('/foo/bar'); // results in [ '/foo/bar', 'bar' ] * var result = rule.handler(match); // '/home/bar' * ``` * * ## Handler as string * * If `handler` is a string, the url is *replaced by the string* when the Rule is invoked. * The string is first interpolated using `string.replace()` style pattern. * * #### Example: * ```js * var rule = factory.fromRegExp(/^\/foo\/(bar|baz)$/, "/home/$1") * var match = rule.match('/foo/bar'); // results in [ '/foo/bar', 'bar' ] * var result = rule.handler(match); // '/home/bar' * ``` */ UrlRuleFactory.prototype.fromRegExp = function (regexp, handler) { if (regexp.global || regexp.sticky) throw new Error('Rule RegExp must not be global or sticky'); /** * If handler is a string, the url will be replaced by the string. * If the string has any String.replace() style variables in it (like `$2`), * they will be replaced by the captures from [[match]] */ var redirectUrlTo = function (match) { // Interpolates matched values into $1 $2, etc using a String.replace()-style pattern return handler.replace(/\$(\$|\d{1,2})/, function (m, what) { return match[what === '$' ? 0 : Number(what)]; }); }; var _handler = predicates_1.isString(handler) ? redirectUrlTo : handler; var matchParamsFromRegexp = function (url) { return regexp.exec(url.path); }; var details = { regexp: regexp, type: 'REGEXP' }; return common_1.extend(new BaseUrlRule(matchParamsFromRegexp, _handler), details); }; UrlRuleFactory.isUrlRule = function (obj) { return obj && ['type', 'match', 'handler'].every(function (key) { return predicates_1.isDefined(obj[key]); }); }; return UrlRuleFactory; }()); exports.UrlRuleFactory = UrlRuleFactory; /** * A base rule which calls `match` * * The value from the `match` function is passed through to the `handler`. * @internal */ var BaseUrlRule = /** @class */ (function () { function BaseUrlRule(match, handler) { var _this = this; this.match = match; this.type = 'RAW'; this.matchPriority = function (match) { return 0 - _this.$id; }; this.handler = handler || common_1.identity; } return BaseUrlRule; }()); exports.BaseUrlRule = BaseUrlRule; //# sourceMappingURL=urlRule.js.map