1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', {
|
4 | value: true
|
5 | });
|
6 |
|
7 | 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'); } }; })();
|
8 |
|
9 | exports.addRoutes = addRoutes;
|
10 | exports.removeRoute = removeRoute;
|
11 | exports.match = match;
|
12 | exports.navigate = navigate;
|
13 | exports.navigatorFor = navigatorFor;
|
14 | exports.register = register;
|
15 | exports.getLocation = getLocation;
|
16 |
|
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
18 |
|
19 | var _urlPattern = require('url-pattern');
|
20 |
|
21 | var _urlPattern2 = _interopRequireDefault(_urlPattern);
|
22 |
|
23 | var window = global.window;
|
24 | var history = global.history;
|
25 |
|
26 | var hasHistoryApi = window !== undefined && history !== undefined && typeof history.pushState === 'function';
|
27 |
|
28 | var locationChangeCallbacks = [];
|
29 |
|
30 | var onLocationChange = function onLocationChange(location) {
|
31 | return locationChangeCallbacks.forEach(function (cb) {
|
32 | return cb(location);
|
33 | });
|
34 | };
|
35 |
|
36 | var routes = [];
|
37 |
|
38 | function addRoutes(newRoutes) {
|
39 | if (!(routes instanceof Array)) throw typeError(routes, 'lucid-router expects to be passed a routing array as its first parameter');
|
40 | for (var routeIdx in newRoutes) {
|
41 | var route = newRoutes[routeIdx];
|
42 | if (!(route instanceof Object)) throw typeError(routes, 'lucid-router expects each route definition to be an object');
|
43 | route.path = route.path || null;
|
44 | route.name = route.name || null;
|
45 | route.external = typeof route.external === 'function' ? route.external : !!route.external;
|
46 | try {
|
47 | route.pattern = new _urlPattern2['default'](route.path);
|
48 | } catch (err) {
|
49 | throw typeError(route.path, 'lucid-router expects route paths to be a string or regex expression');
|
50 | }
|
51 | routes.push(route);
|
52 | }
|
53 | }
|
54 |
|
55 | function removeRoute(name) {
|
56 | if (!name) return;
|
57 | var idx = -1;
|
58 | for (var routeIdx in routes) {
|
59 | if (routes[routeIdx].name === name) {
|
60 | idx = routeIdx;
|
61 | break;
|
62 | }
|
63 | }
|
64 | ~idx && routes.splice(idx, 1);
|
65 | }
|
66 |
|
67 | function parseQuery(query) {
|
68 | var queryArgs = {};
|
69 | if (query) {
|
70 | query.split('&').filter(function (keyValStr) {
|
71 | return !!keyValStr;
|
72 | }).map(function (keyValStr) {
|
73 | return keyValStr.split('=').map(function (encoded) {
|
74 | return decodeURIComponent(encoded);
|
75 | });
|
76 | }).forEach(function (_ref) {
|
77 | var _ref2 = _slicedToArray(_ref, 2);
|
78 |
|
79 | var key = _ref2[0];
|
80 | var val = _ref2[1];
|
81 | return key && (queryArgs[key] = val);
|
82 | });
|
83 | }
|
84 | return queryArgs;
|
85 | }
|
86 |
|
87 | function match(path) {
|
88 | var _path$split = path.split('#');
|
89 |
|
90 | var _path$split2 = _slicedToArray(_path$split, 2);
|
91 |
|
92 | var pathnameAndQuery = _path$split2[0];
|
93 | var hashAndHashQuery = _path$split2[1];
|
94 |
|
95 | var _pathnameAndQuery$split = pathnameAndQuery.split('?');
|
96 |
|
97 | var _pathnameAndQuery$split2 = _slicedToArray(_pathnameAndQuery$split, 2);
|
98 |
|
99 | var pathname = _pathnameAndQuery$split2[0];
|
100 | var search = _pathnameAndQuery$split2[1];
|
101 |
|
102 | var _ref3 = hashAndHashQuery ? hashAndHashQuery.split('?') : [];
|
103 |
|
104 | var _ref32 = _slicedToArray(_ref3, 2);
|
105 |
|
106 | var hash = _ref32[0];
|
107 | var hashSearch = _ref32[1];
|
108 |
|
109 | var state = parseQuery([search, hashSearch].join('&'));
|
110 |
|
111 | var _loop = function (routeIdx) {
|
112 | var route = routes[routeIdx];
|
113 | var m = route.pattern.match(pathname);
|
114 | if (!m) return 'continue';
|
115 | Object.keys(m).forEach(function (key) {
|
116 | return state[key] = m[key];
|
117 | });
|
118 | return {
|
119 | v: {
|
120 | route: route,
|
121 | pathname: pathname,
|
122 | search: search ? '?'.concat(search) : '',
|
123 | hash: hash ? '#'.concat(hash) : '',
|
124 | hashSearch: hashSearch ? '?'.concat(hashSearch) : '',
|
125 | state: state }
|
126 | };
|
127 | };
|
128 |
|
129 | for (var routeIdx in routes) {
|
130 | var _ret = _loop(routeIdx);
|
131 |
|
132 | switch (_ret) {
|
133 | case 'continue':
|
134 | continue;
|
135 |
|
136 | default:
|
137 | if (typeof _ret === 'object') return _ret.v;
|
138 | }
|
139 | }
|
140 | return null;
|
141 | }
|
142 |
|
143 | function navigate(path, e, replace) {
|
144 | if (e && e.defaultPrevented) return;
|
145 | if (e && e.preventDefault && e.stopPropagation) {
|
146 | e.preventDefault();
|
147 | e.stopPropagation();
|
148 | }
|
149 | path = getFullPath(path);
|
150 | if (hasHistoryApi) {
|
151 | if (typeof path !== 'string' || !path) throw typeError(path, 'lucid-router.navigate expected a non empty string as its first parameter');
|
152 | var m = match(path);
|
153 | if (m && notExternal(m)) {
|
154 | var _location = matchAndPathToLocation(m, path);
|
155 | if (replace) {
|
156 | history.replaceState(null, '', path);
|
157 | } else {
|
158 | history.pushState(null, '', path);
|
159 | }
|
160 | onLocationChange(_location);
|
161 | return;
|
162 | }
|
163 | }
|
164 | if (window) {
|
165 | window.location = path;
|
166 | }
|
167 | }
|
168 |
|
169 | function navigatorFor(path, replace) {
|
170 | return function (e) {
|
171 | return navigate(path, e, replace);
|
172 | };
|
173 | }
|
174 |
|
175 | function register(callback) {
|
176 | if (typeof callback !== 'function') throw typeError(callback, 'lucid-router.register expects to be passed a callback function');
|
177 | locationChangeCallbacks.push(callback);
|
178 | return function unregister() {
|
179 | var idx = locationChangeCallbacks.indexOf(callback);
|
180 | ~idx && locationChangeCallbacks.splice(idx, 1);
|
181 | };
|
182 | }
|
183 |
|
184 | function getFullPath(path) {
|
185 | if (window) {
|
186 | var a = window.document.createElement('a');
|
187 | a.href = path;
|
188 | if (!a.host) a.href = a.href;
|
189 | if (a.hostname === window.location.hostname) {
|
190 | path = a.pathname + a.search + a.hash;
|
191 | } else {
|
192 | path = a.href;
|
193 | }
|
194 | }
|
195 | return path;
|
196 | }
|
197 |
|
198 | function getWindowPathAndQuery() {
|
199 | var location = window.location;
|
200 |
|
201 | if (!location) return null;
|
202 | return location.pathname + location.search + location.hash;
|
203 | }
|
204 |
|
205 | function getLocation(path) {
|
206 | path = path || getWindowPathAndQuery();
|
207 | var m = match(path);
|
208 | var location = matchAndPathToLocation(m, path);
|
209 | onLocationChange(location);
|
210 | return location;
|
211 | }
|
212 |
|
213 | function matchAndPathToLocation(m, p) {
|
214 | return !m ? null : {
|
215 | path: p,
|
216 | name: m.route.name,
|
217 | pathname: m.pathname,
|
218 | search: m.search,
|
219 | hash: m.hash,
|
220 | hashSearch: m.hashSearch,
|
221 | state: m.state
|
222 | };
|
223 | }
|
224 |
|
225 | function notExternal(m) {
|
226 | var external = m.route.external;
|
227 |
|
228 | if (typeof external === 'function') {
|
229 | return !external(m);
|
230 | } else return !external;
|
231 | }
|
232 |
|
233 | if (hasHistoryApi && window) {
|
234 | window.addEventListener('popstate', function (e) {
|
235 | var path = getWindowPathAndQuery();
|
236 | var m = match(path);
|
237 | if (m && notExternal(m)) {
|
238 | var _location2 = matchAndPathToLocation(m, path);
|
239 | onLocationChange(_location2);
|
240 | return;
|
241 | }
|
242 | }, false);
|
243 | }
|
244 |
|
245 | function typeError(type, msg) {
|
246 | return new TypeError(msg + ' but got type `' + typeof type + '`!');
|
247 | }
|