-
-
Notifications
You must be signed in to change notification settings - Fork 105
/
generateUrls.js
96 lines (82 loc) · 2.51 KB
/
generateUrls.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* Universal Router (https://www.kriasoft.com/universal-router/)
*
* Copyright (c) 2015-present Kriasoft.
*
* This source code is licensed under the MIT license found in the
* LICENSE.txt file in the root directory of this source tree.
*/
import pathToRegexp from 'path-to-regexp'
const cache = new Map()
function cacheRoutes(routesByName, route, routes) {
if (routesByName.has(route.name)) {
throw new Error(`Route "${route.name}" already exists`)
}
if (route.name) {
routesByName.set(route.name, route)
}
if (routes) {
for (let i = 0; i < routes.length; i++) {
const childRoute = routes[i]
childRoute.parent = route
cacheRoutes(routesByName, childRoute, childRoute.children)
}
}
}
function generateUrls(router, options = {}) {
if (!router) {
throw new ReferenceError('Router is not defined')
}
router.routesByName = router.routesByName || new Map()
return (routeName, params) => {
let route = router.routesByName.get(routeName)
if (!route) {
router.routesByName.clear() // clear cache
cacheRoutes(router.routesByName, router.root, router.root.children)
route = router.routesByName.get(routeName)
if (!route) {
throw new Error(`Route "${routeName}" not found`)
}
}
let regexp = cache.get(route.fullPath)
if (!regexp) {
let fullPath = ''
let rt = route
while (rt) {
const path = Array.isArray(rt.path) ? rt.path[0] : rt.path
if (path) {
fullPath = path + fullPath
}
rt = rt.parent
}
const tokens = pathToRegexp.parse(fullPath, options)
const toPath = pathToRegexp.tokensToFunction(tokens, options)
const keys = Object.create(null)
for (let i = 0; i < tokens.length; i++) {
if (typeof tokens[i] !== 'string') {
keys[tokens[i].name] = true
}
}
regexp = { toPath, keys }
cache.set(fullPath, regexp)
route.fullPath = fullPath
}
let url = router.baseUrl + regexp.toPath(params, options) || '/'
if (options.stringifyQueryParams && params) {
const queryParams = {}
const keys = Object.keys(params)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (!regexp.keys[key]) {
queryParams[key] = params[key]
}
}
const query = options.stringifyQueryParams(queryParams)
if (query) {
url += query.charAt(0) === '?' ? query : `?${query}`
}
}
return url
}
}
export default generateUrls