UNPKG

8.85 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.BaseUrlRule = exports.UrlRuleFactory = void 0;
4var urlMatcher_1 = require("./urlMatcher");
5var predicates_1 = require("../common/predicates");
6var common_1 = require("../common/common");
7var hof_1 = require("../common/hof");
8var stateObject_1 = require("../state/stateObject");
9/**
10 * Creates a [[UrlRule]]
11 *
12 * Creates a [[UrlRule]] from a:
13 *
14 * - `string`
15 * - [[UrlMatcher]]
16 * - `RegExp`
17 * - [[StateObject]]
18 */
19var UrlRuleFactory = /** @class */ (function () {
20 function UrlRuleFactory(router) {
21 this.router = router;
22 }
23 UrlRuleFactory.prototype.compile = function (str) {
24 return this.router.urlMatcherFactory.compile(str);
25 };
26 UrlRuleFactory.prototype.create = function (what, handler) {
27 var _this = this;
28 var isState = stateObject_1.StateObject.isState, isStateDeclaration = stateObject_1.StateObject.isStateDeclaration;
29 var makeRule = hof_1.pattern([
30 [predicates_1.isString, function (_what) { return makeRule(_this.compile(_what)); }],
31 [hof_1.is(urlMatcher_1.UrlMatcher), function (_what) { return _this.fromUrlMatcher(_what, handler); }],
32 [hof_1.or(isState, isStateDeclaration), function (_what) { return _this.fromState(_what, _this.router); }],
33 [hof_1.is(RegExp), function (_what) { return _this.fromRegExp(_what, handler); }],
34 [predicates_1.isFunction, function (_what) { return new BaseUrlRule(_what, handler); }],
35 ]);
36 var rule = makeRule(what);
37 if (!rule)
38 throw new Error("invalid 'what' in when()");
39 return rule;
40 };
41 /**
42 * A UrlRule which matches based on a UrlMatcher
43 *
44 * The `handler` may be either a `string`, a [[UrlRuleHandlerFn]] or another [[UrlMatcher]]
45 *
46 * ## Handler as a function
47 *
48 * If `handler` is a function, the function is invoked with:
49 *
50 * - matched parameter values ([[RawParams]] from [[UrlMatcher.exec]])
51 * - url: the current Url ([[UrlParts]])
52 * - router: the router object ([[UIRouter]])
53 *
54 * #### Example:
55 * ```js
56 * var urlMatcher = $umf.compile("/foo/:fooId/:barId");
57 * var rule = factory.fromUrlMatcher(urlMatcher, match => "/home/" + match.fooId + "/" + match.barId);
58 * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' }
59 * var result = rule.handler(match); // '/home/123/456'
60 * ```
61 *
62 * ## Handler as UrlMatcher
63 *
64 * If `handler` is a UrlMatcher, the handler matcher is used to create the new url.
65 * The `handler` UrlMatcher is formatted using the matched param from the first matcher.
66 * The url is replaced with the result.
67 *
68 * #### Example:
69 * ```js
70 * var urlMatcher = $umf.compile("/foo/:fooId/:barId");
71 * var handler = $umf.compile("/home/:fooId/:barId");
72 * var rule = factory.fromUrlMatcher(urlMatcher, handler);
73 * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' }
74 * var result = rule.handler(match); // '/home/123/456'
75 * ```
76 */
77 UrlRuleFactory.prototype.fromUrlMatcher = function (urlMatcher, handler) {
78 var _handler = handler;
79 if (predicates_1.isString(handler))
80 handler = this.router.urlMatcherFactory.compile(handler);
81 if (hof_1.is(urlMatcher_1.UrlMatcher)(handler))
82 _handler = function (match) { return handler.format(match); };
83 function matchUrlParamters(url) {
84 var params = urlMatcher.exec(url.path, url.search, url.hash);
85 return urlMatcher.validates(params) && params;
86 }
87 // Prioritize URLs, lowest to highest:
88 // - Some optional URL parameters, but none matched
89 // - No optional parameters in URL
90 // - Some optional parameters, some matched
91 // - Some optional parameters, all matched
92 function matchPriority(params) {
93 var optional = urlMatcher.parameters().filter(function (param) { return param.isOptional; });
94 if (!optional.length)
95 return 0.000001;
96 var matched = optional.filter(function (param) { return params[param.id]; });
97 return matched.length / optional.length;
98 }
99 var details = { urlMatcher: urlMatcher, matchPriority: matchPriority, type: 'URLMATCHER' };
100 return common_1.extend(new BaseUrlRule(matchUrlParamters, _handler), details);
101 };
102 /**
103 * A UrlRule which matches a state by its url
104 *
105 * #### Example:
106 * ```js
107 * var rule = factory.fromState($state.get('foo'), router);
108 * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' }
109 * var result = rule.handler(match);
110 * // Starts a transition to 'foo' with params: { fooId: '123', barId: '456' }
111 * ```
112 */
113 UrlRuleFactory.prototype.fromState = function (stateOrDecl, router) {
114 var state = stateObject_1.StateObject.isStateDeclaration(stateOrDecl) ? stateOrDecl.$$state() : stateOrDecl;
115 /**
116 * Handles match by transitioning to matched state
117 *
118 * First checks if the router should start a new transition.
119 * A new transition is not required if the current state's URL
120 * and the new URL are already identical
121 */
122 var handler = function (match) {
123 var $state = router.stateService;
124 var globals = router.globals;
125 if ($state.href(state, match) !== $state.href(globals.current, globals.params)) {
126 $state.transitionTo(state, match, { inherit: true, source: 'url' });
127 }
128 };
129 var details = { state: state, type: 'STATE' };
130 return common_1.extend(this.fromUrlMatcher(state.url, handler), details);
131 };
132 /**
133 * A UrlRule which matches based on a regular expression
134 *
135 * The `handler` may be either a [[UrlRuleHandlerFn]] or a string.
136 *
137 * ## Handler as a function
138 *
139 * If `handler` is a function, the function is invoked with:
140 *
141 * - regexp match array (from `regexp`)
142 * - url: the current Url ([[UrlParts]])
143 * - router: the router object ([[UIRouter]])
144 *
145 * #### Example:
146 * ```js
147 * var rule = factory.fromRegExp(/^\/foo\/(bar|baz)$/, match => "/home/" + match[1])
148 * var match = rule.match('/foo/bar'); // results in [ '/foo/bar', 'bar' ]
149 * var result = rule.handler(match); // '/home/bar'
150 * ```
151 *
152 * ## Handler as string
153 *
154 * If `handler` is a string, the url is *replaced by the string* when the Rule is invoked.
155 * The string is first interpolated using `string.replace()` style pattern.
156 *
157 * #### Example:
158 * ```js
159 * var rule = factory.fromRegExp(/^\/foo\/(bar|baz)$/, "/home/$1")
160 * var match = rule.match('/foo/bar'); // results in [ '/foo/bar', 'bar' ]
161 * var result = rule.handler(match); // '/home/bar'
162 * ```
163 */
164 UrlRuleFactory.prototype.fromRegExp = function (regexp, handler) {
165 if (regexp.global || regexp.sticky)
166 throw new Error('Rule RegExp must not be global or sticky');
167 /**
168 * If handler is a string, the url will be replaced by the string.
169 * If the string has any String.replace() style variables in it (like `$2`),
170 * they will be replaced by the captures from [[match]]
171 */
172 var redirectUrlTo = function (match) {
173 // Interpolates matched values into $1 $2, etc using a String.replace()-style pattern
174 return handler.replace(/\$(\$|\d{1,2})/, function (m, what) { return match[what === '$' ? 0 : Number(what)]; });
175 };
176 var _handler = predicates_1.isString(handler) ? redirectUrlTo : handler;
177 var matchParamsFromRegexp = function (url) { return regexp.exec(url.path); };
178 var details = { regexp: regexp, type: 'REGEXP' };
179 return common_1.extend(new BaseUrlRule(matchParamsFromRegexp, _handler), details);
180 };
181 UrlRuleFactory.isUrlRule = function (obj) { return obj && ['type', 'match', 'handler'].every(function (key) { return predicates_1.isDefined(obj[key]); }); };
182 return UrlRuleFactory;
183}());
184exports.UrlRuleFactory = UrlRuleFactory;
185/**
186 * A base rule which calls `match`
187 *
188 * The value from the `match` function is passed through to the `handler`.
189 * @internal
190 */
191var BaseUrlRule = /** @class */ (function () {
192 function BaseUrlRule(match, handler) {
193 var _this = this;
194 this.match = match;
195 this.type = 'RAW';
196 this.matchPriority = function (match) { return 0 - _this.$id; };
197 this.handler = handler || common_1.identity;
198 }
199 return BaseUrlRule;
200}());
201exports.BaseUrlRule = BaseUrlRule;
202//# sourceMappingURL=urlRule.js.map
\No newline at end of file