1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | import { parse, tokensToFunction, } from 'path-to-regexp';
|
10 | function cacheRoutes(routesByName, route, routes) {
|
11 | if (route.name && routesByName.has(route.name)) {
|
12 | throw new Error(`Route "${route.name}" already exists`);
|
13 | }
|
14 | if (route.name) {
|
15 | routesByName.set(route.name, route);
|
16 | }
|
17 | if (routes) {
|
18 | for (let i = 0; i < routes.length; i++) {
|
19 | const childRoute = routes[i];
|
20 | childRoute.parent = route;
|
21 | cacheRoutes(routesByName, childRoute, childRoute.children);
|
22 | }
|
23 | }
|
24 | }
|
25 |
|
26 |
|
27 |
|
28 | function generateUrls(router, options) {
|
29 | if (!router) {
|
30 | throw new ReferenceError('Router is not defined');
|
31 | }
|
32 | const routesByName = new Map();
|
33 | const regexpByRoute = new Map();
|
34 | const opts = { encode: encodeURIComponent, ...options };
|
35 | return (routeName, params) => {
|
36 | let route = routesByName.get(routeName);
|
37 | if (!route) {
|
38 | routesByName.clear();
|
39 | regexpByRoute.clear();
|
40 | cacheRoutes(routesByName, router.root, router.root.children);
|
41 | route = routesByName.get(routeName);
|
42 | if (!route) {
|
43 | throw new Error(`Route "${routeName}" not found`);
|
44 | }
|
45 | }
|
46 | let regexp = regexpByRoute.get(route);
|
47 | if (!regexp) {
|
48 | let fullPath = '';
|
49 | let rt = route;
|
50 | while (rt) {
|
51 | const path = Array.isArray(rt.path) ? rt.path[0] : rt.path;
|
52 | if (path) {
|
53 | fullPath = path + fullPath;
|
54 | }
|
55 | rt = rt.parent;
|
56 | }
|
57 | const tokens = parse(fullPath, opts);
|
58 | const toPath = tokensToFunction(tokens, opts);
|
59 | const keys = Object.create(null);
|
60 | for (let i = 0; i < tokens.length; i++) {
|
61 | const token = tokens[i];
|
62 | if (typeof token !== 'string') {
|
63 | keys[token.name] = true;
|
64 | }
|
65 | }
|
66 | regexp = { toPath, keys };
|
67 | regexpByRoute.set(route, regexp);
|
68 | }
|
69 | let url = router.baseUrl + regexp.toPath(params) || '/';
|
70 | if (opts.stringifyQueryParams && params) {
|
71 | const queryParams = {};
|
72 | const keys = Object.keys(params);
|
73 | for (let i = 0; i < keys.length; i++) {
|
74 | const key = keys[i];
|
75 | if (!regexp.keys[key]) {
|
76 | queryParams[key] = params[key];
|
77 | }
|
78 | }
|
79 | const query = opts.stringifyQueryParams(queryParams);
|
80 | if (query) {
|
81 | url += query.charAt(0) === '?' ? query : `?${query}`;
|
82 | }
|
83 | }
|
84 | return url;
|
85 | };
|
86 | }
|
87 | export default generateUrls;
|
88 |
|
\ | No newline at end of file |