1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 |
|
7 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
|
8 |
|
9 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
10 |
|
11 | var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
12 |
|
13 | exports.addRoutes = addRoutes;
|
14 | exports.removeRoute = removeRoute;
|
15 | exports.match = match;
|
16 | exports.navigate = navigate;
|
17 | exports.navigatorFor = navigatorFor;
|
18 | exports.pathFor = pathFor;
|
19 | exports.navigateToRoute = navigateToRoute;
|
20 | exports.navigatorForRoute = navigatorForRoute;
|
21 | exports.register = register;
|
22 | exports.getLocation = getLocation;
|
23 |
|
24 | var _urlPattern = require('url-pattern');
|
25 |
|
26 | var _urlPattern2 = _interopRequireDefault(_urlPattern);
|
27 |
|
28 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
29 |
|
30 | var window = global.window;
|
31 | var history = global.history;
|
32 |
|
33 | var hasHistoryApi = window !== undefined && history !== undefined && typeof history.pushState === 'function';
|
34 |
|
35 | var locationChangeCallbacks = [];
|
36 |
|
37 | var routes = [];
|
38 |
|
39 | function addRoutes(newRoutes) {
|
40 | if (!(newRoutes instanceof Array)) throw typeError(routes, 'lucid-router expects to be passed a routing array as its first parameter');
|
41 | var _iteratorNormalCompletion = true;
|
42 | var _didIteratorError = false;
|
43 | var _iteratorError = undefined;
|
44 |
|
45 | try {
|
46 | for (var _iterator = newRoutes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
47 | var route = _step.value;
|
48 |
|
49 | if (route === null || !(route instanceof Object)) throw typeError(routes, 'lucid-router expects each route definition to be an object');
|
50 | route.path = route.path || null;
|
51 | route.name = route.name || null;
|
52 | route.external = typeof route.external === 'function' ? route.external : !!route.external;
|
53 | try {
|
54 | route.pattern = new _urlPattern2.default(route.path);
|
55 | } catch (err) {
|
56 | throw typeError(route.path, 'lucid-router expects route paths to be a string or regex expression');
|
57 | }
|
58 | routes.push(route);
|
59 | }
|
60 | } catch (err) {
|
61 | _didIteratorError = true;
|
62 | _iteratorError = err;
|
63 | } finally {
|
64 | try {
|
65 | if (!_iteratorNormalCompletion && _iterator.return) {
|
66 | _iterator.return();
|
67 | }
|
68 | } finally {
|
69 | if (_didIteratorError) {
|
70 | throw _iteratorError;
|
71 | }
|
72 | }
|
73 | }
|
74 | }
|
75 |
|
76 | function removeRoute(name) {
|
77 | var idx = -1;
|
78 | for (var i = 0, l = routes.length; i < l; i++) {
|
79 | if (routes[i].name === name) {
|
80 | idx = i;
|
81 | break;
|
82 | }
|
83 | }
|
84 | ~idx && routes.splice(idx, 1);
|
85 | }
|
86 |
|
87 | function parseQuery(query) {
|
88 | var queryArgs = {};
|
89 | if (query) {
|
90 | query.split('&').filter(function (keyValStr) {
|
91 | return !!keyValStr;
|
92 | }).map(function (keyValStr) {
|
93 | return keyValStr.split('=').map(function (encoded) {
|
94 | return decodeURIComponent(encoded);
|
95 | });
|
96 | }).forEach(function (_ref) {
|
97 | var _ref2 = _slicedToArray(_ref, 2);
|
98 |
|
99 | var key = _ref2[0];
|
100 | var val = _ref2[1];
|
101 | return key && (queryArgs[key] = val);
|
102 | });
|
103 | }
|
104 | return queryArgs;
|
105 | }
|
106 |
|
107 | function match(path) {
|
108 | var _path$split = path.split('#');
|
109 |
|
110 | var _path$split2 = _slicedToArray(_path$split, 2);
|
111 |
|
112 | var pathnameAndQuery = _path$split2[0];
|
113 | var hashAndHashQuery = _path$split2[1];
|
114 |
|
115 | var _pathnameAndQuery$spl = pathnameAndQuery.split('?');
|
116 |
|
117 | var _pathnameAndQuery$spl2 = _slicedToArray(_pathnameAndQuery$spl, 2);
|
118 |
|
119 | var pathname = _pathnameAndQuery$spl2[0];
|
120 | var search = _pathnameAndQuery$spl2[1];
|
121 |
|
122 | var _ref3 = hashAndHashQuery ? hashAndHashQuery.split('?') : [];
|
123 |
|
124 | var _ref4 = _slicedToArray(_ref3, 2);
|
125 |
|
126 | var hash = _ref4[0];
|
127 | var hashSearch = _ref4[1];
|
128 |
|
129 | var queryState = parseQuery([search, hashSearch].join('&'));
|
130 | var _iteratorNormalCompletion2 = true;
|
131 | var _didIteratorError2 = false;
|
132 | var _iteratorError2 = undefined;
|
133 |
|
134 | try {
|
135 | for (var _iterator2 = routes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
136 | var route = _step2.value;
|
137 |
|
138 | var matchState = route.pattern.match(pathname);
|
139 | if (!matchState) continue;
|
140 | return {
|
141 | route: route,
|
142 | pathname: pathname,
|
143 | search: search ? '?'.concat(search) : '',
|
144 | hash: hash ? '#'.concat(hash) : '',
|
145 | hashSearch: hashSearch ? '?'.concat(hashSearch) : '',
|
146 | state: _extends({}, queryState, matchState)
|
147 | };
|
148 | }
|
149 | } catch (err) {
|
150 | _didIteratorError2 = true;
|
151 | _iteratorError2 = err;
|
152 | } finally {
|
153 | try {
|
154 | if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
155 | _iterator2.return();
|
156 | }
|
157 | } finally {
|
158 | if (_didIteratorError2) {
|
159 | throw _iteratorError2;
|
160 | }
|
161 | }
|
162 | }
|
163 |
|
164 | return null;
|
165 | }
|
166 |
|
167 | function navigate(path, e, replace) {
|
168 | path = getFullPath(path);
|
169 | if (hasHistoryApi) {
|
170 | if (typeof path !== 'string' || !path) throw typeError(path, 'lucid-router.navigate expected a non empty string as its first parameter');
|
171 | var m = match(path);
|
172 | if (m && notExternal(m)) {
|
173 | var location = matchAndPathToLocation(m, path);
|
174 | if (replace) {
|
175 | history.replaceState(null, '', path);
|
176 | } else {
|
177 | history.pushState(null, '', path);
|
178 | }
|
179 |
|
180 | if (e && e.preventDefault) {
|
181 | e.preventDefault();
|
182 | }
|
183 |
|
184 | onLocationChange(location);
|
185 | return;
|
186 | }
|
187 | }
|
188 |
|
189 | if (window && (!e || !e.target)) {
|
190 | window.location = path;
|
191 | }
|
192 | }
|
193 |
|
194 | function navigatorFor(path, replace) {
|
195 | return function (e) {
|
196 | return navigate(path, e, replace);
|
197 | };
|
198 | }
|
199 |
|
200 | function pathFor(routeName, params) {
|
201 | var _iteratorNormalCompletion3 = true;
|
202 | var _didIteratorError3 = false;
|
203 | var _iteratorError3 = undefined;
|
204 |
|
205 | try {
|
206 | for (var _iterator3 = routes[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
207 | var route = _step3.value;
|
208 |
|
209 | if (route.name === routeName) {
|
210 | return route.pattern.stringify(params);
|
211 | }
|
212 | }
|
213 | } catch (err) {
|
214 | _didIteratorError3 = true;
|
215 | _iteratorError3 = err;
|
216 | } finally {
|
217 | try {
|
218 | if (!_iteratorNormalCompletion3 && _iterator3.return) {
|
219 | _iterator3.return();
|
220 | }
|
221 | } finally {
|
222 | if (_didIteratorError3) {
|
223 | throw _iteratorError3;
|
224 | }
|
225 | }
|
226 | }
|
227 |
|
228 | throw new Error('lucid-router.pathFor failed to find a route with the name \'' + routeName + '\'');
|
229 | }
|
230 |
|
231 | function navigateToRoute(routeName, params, e) {
|
232 | navigate(pathFor(routeName, params), e);
|
233 | }
|
234 |
|
235 | function navigatorForRoute(routeName, params) {
|
236 | return function (e) {
|
237 | return navigateToRoute(routeName, params, e);
|
238 | };
|
239 | }
|
240 |
|
241 | function register(callback) {
|
242 | if (typeof callback !== 'function') throw typeError(callback, 'lucid-router.register expects to be passed a callback function');
|
243 | locationChangeCallbacks.push(callback);
|
244 | return function unregister() {
|
245 | var idx = locationChangeCallbacks.indexOf(callback);
|
246 | ~idx && locationChangeCallbacks.splice(idx, 1);
|
247 | };
|
248 | }
|
249 |
|
250 | function onLocationChange(location) {
|
251 | locationChangeCallbacks.forEach(function (cb) {
|
252 | return cb(location);
|
253 | });
|
254 | }
|
255 |
|
256 | function getFullPath(path) {
|
257 | if (window) {
|
258 | var a = window.document.createElement('a');
|
259 | a.href = path;
|
260 | if (!a.host) a.href = a.href;
|
261 | if (a.hostname === window.location.hostname) {
|
262 | path = a.pathname + a.search + a.hash;
|
263 | if (path[0] !== '/') {
|
264 |
|
265 | path = '/' + path;
|
266 | }
|
267 | } else {
|
268 | path = a.href;
|
269 | }
|
270 | }
|
271 | return path;
|
272 | }
|
273 |
|
274 | function getWindowPathAndQuery() {
|
275 | var location = window.location;
|
276 |
|
277 | if (!location) return null;
|
278 | return location.pathname + location.search + location.hash;
|
279 | }
|
280 |
|
281 | function getLocation(path) {
|
282 | path = path || getWindowPathAndQuery() || '';
|
283 | var m = match(path);
|
284 | var location = matchAndPathToLocation(m, path);
|
285 | onLocationChange(location);
|
286 | return location;
|
287 | }
|
288 |
|
289 | function matchAndPathToLocation(m, p) {
|
290 | return !m ? null : {
|
291 | path: p,
|
292 | name: m.route.name,
|
293 | pathname: m.pathname,
|
294 | search: m.search,
|
295 | hash: m.hash,
|
296 | hashSearch: m.hashSearch,
|
297 | state: m.state
|
298 | };
|
299 | }
|
300 |
|
301 | function notExternal(m) {
|
302 | var external = m.route.external;
|
303 |
|
304 | if (typeof external === 'function') {
|
305 | return !external(m);
|
306 | } else return !external;
|
307 | }
|
308 |
|
309 | if (hasHistoryApi && window) {
|
310 | window.addEventListener('popstate', function (e) {
|
311 | var path = getWindowPathAndQuery() || '';
|
312 | var m = match(path);
|
313 | if (m && notExternal(m)) {
|
314 | var location = matchAndPathToLocation(m, path);
|
315 | onLocationChange(location);
|
316 | }
|
317 | }, false);
|
318 | }
|
319 |
|
320 | function typeError(type, msg) {
|
321 | return new TypeError(msg + ' but got type `' + (typeof type === 'undefined' ? 'undefined' : _typeof(type)) + '`!');
|
322 | }
|