@uirouter/core
Version:
UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps
202 lines • 8.85 kB
JavaScript
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
;