kdu-router 2.7.0 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,165 +1,205 @@
1
- /* @flow */
2
-
3
- import Regexp from 'path-to-regexp'
4
- import { cleanPath } from './util/path'
5
- import { assert, warn } from './util/warn'
6
-
7
- export function createRouteMap (
8
- routes: Array<RouteConfig>,
9
- oldPathList?: Array<string>,
10
- oldPathMap?: Dictionary<RouteRecord>,
11
- oldNameMap?: Dictionary<RouteRecord>
12
- ): {
13
- pathList: Array<string>;
14
- pathMap: Dictionary<RouteRecord>;
15
- nameMap: Dictionary<RouteRecord>;
16
- } {
17
- // the path list is used to control path matching priority
18
- const pathList: Array<string> = oldPathList || []
19
- const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)
20
- const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)
21
-
22
- routes.forEach(route => {
23
- addRouteRecord(pathList, pathMap, nameMap, route)
24
- })
25
-
26
- // ensure wildcard routes are always at the end
27
- for (let i = 0, l = pathList.length; i < l; i++) {
28
- if (pathList[i] === '*') {
29
- pathList.push(pathList.splice(i, 1)[0])
30
- l--
31
- i--
32
- }
33
- }
34
-
35
- return {
36
- pathList,
37
- pathMap,
38
- nameMap
39
- }
40
- }
41
-
42
- function addRouteRecord (
43
- pathList: Array<string>,
44
- pathMap: Dictionary<RouteRecord>,
45
- nameMap: Dictionary<RouteRecord>,
46
- route: RouteConfig,
47
- parent?: RouteRecord,
48
- matchAs?: string
49
- ) {
50
- const { path, name } = route
51
- if (process.env.NODE_ENV !== 'production') {
52
- assert(path != null, `"path" is required in a route configuration.`)
53
- assert(
54
- typeof route.component !== 'string',
55
- `route config "component" for path: ${String(path || name)} cannot be a ` +
56
- `string id. Use an actual component instead.`
57
- )
58
- }
59
-
60
- const normalizedPath = normalizePath(path, parent)
61
- const pathToRegexpOptions: PathToRegexpOptions = route.pathToRegexpOptions || {}
62
-
63
- if (typeof route.caseSensitive === 'boolean') {
64
- pathToRegexpOptions.sensitive = route.caseSensitive
65
- }
66
-
67
- const record: RouteRecord = {
68
- path: normalizedPath,
69
- regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
70
- components: route.components || { default: route.component },
71
- instances: {},
72
- name,
73
- parent,
74
- matchAs,
75
- redirect: route.redirect,
76
- beforeEnter: route.beforeEnter,
77
- meta: route.meta || {},
78
- props: route.props == null
79
- ? {}
80
- : route.components
81
- ? route.props
82
- : { default: route.props }
83
- }
84
-
85
- if (route.children) {
86
- // Warn if route is named, does not redirect and has a default child route.
87
- // If users navigate to this route by name, the default child will
88
- // not be rendered (GH Issue #629)
89
- if (process.env.NODE_ENV !== 'production') {
90
- if (route.name && !route.redirect && route.children.some(child => /^\/?$/.test(child.path))) {
91
- warn(
92
- false,
93
- `Named Route '${route.name}' has a default child route. ` +
94
- `When navigating to this named route (:to="{name: '${route.name}'"), ` +
95
- `the default child route will not be rendered. Remove the name from ` +
96
- `this route and use the name of the default child route for named ` +
97
- `links instead.`
98
- )
99
- }
100
- }
101
- route.children.forEach(child => {
102
- const childMatchAs = matchAs
103
- ? cleanPath(`${matchAs}/${child.path}`)
104
- : undefined
105
- addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs)
106
- })
107
- }
108
-
109
- if (route.alias !== undefined) {
110
- const aliases = Array.isArray(route.alias)
111
- ? route.alias
112
- : [route.alias]
113
-
114
- aliases.forEach(alias => {
115
- const aliasRoute = {
116
- path: alias,
117
- children: route.children
118
- }
119
- addRouteRecord(
120
- pathList,
121
- pathMap,
122
- nameMap,
123
- aliasRoute,
124
- parent,
125
- record.path || '/' // matchAs
126
- )
127
- })
128
- }
129
-
130
- if (!pathMap[record.path]) {
131
- pathList.push(record.path)
132
- pathMap[record.path] = record
133
- }
134
-
135
- if (name) {
136
- if (!nameMap[name]) {
137
- nameMap[name] = record
138
- } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
139
- warn(
140
- false,
141
- `Duplicate named routes definition: ` +
142
- `{ name: "${name}", path: "${record.path}" }`
143
- )
144
- }
145
- }
146
- }
147
-
148
- function compileRouteRegex (path: string, pathToRegexpOptions: PathToRegexpOptions): RouteRegExp {
149
- const regex = Regexp(path, [], pathToRegexpOptions)
150
- if (process.env.NODE_ENV !== 'production') {
151
- const keys: any = {}
152
- regex.keys.forEach(key => {
153
- warn(!keys[key.name], `Duplicate param keys in route with path: "${path}"`)
154
- keys[key.name] = true
155
- })
156
- }
157
- return regex
158
- }
159
-
160
- function normalizePath (path: string, parent?: RouteRecord): string {
161
- path = path.replace(/\/$/, '')
162
- if (path[0] === '/') return path
163
- if (parent == null) return path
164
- return cleanPath(`${parent.path}/${path}`)
165
- }
1
+ /* @flow */
2
+
3
+ import Regexp from 'path-to-regexp'
4
+ import { cleanPath } from './util/path'
5
+ import { assert, warn } from './util/warn'
6
+
7
+ export function createRouteMap (
8
+ routes: Array<RouteConfig>,
9
+ oldPathList?: Array<string>,
10
+ oldPathMap?: Dictionary<RouteRecord>,
11
+ oldNameMap?: Dictionary<RouteRecord>
12
+ ): {
13
+ pathList: Array<string>,
14
+ pathMap: Dictionary<RouteRecord>,
15
+ nameMap: Dictionary<RouteRecord>
16
+ } {
17
+ // the path list is used to control path matching priority
18
+ const pathList: Array<string> = oldPathList || []
19
+ // $flow-disable-line
20
+ const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)
21
+ // $flow-disable-line
22
+ const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)
23
+
24
+ routes.forEach(route => {
25
+ addRouteRecord(pathList, pathMap, nameMap, route)
26
+ })
27
+
28
+ // ensure wildcard routes are always at the end
29
+ for (let i = 0, l = pathList.length; i < l; i++) {
30
+ if (pathList[i] === '*') {
31
+ pathList.push(pathList.splice(i, 1)[0])
32
+ l--
33
+ i--
34
+ }
35
+ }
36
+
37
+ if (process.env.NODE_ENV === 'development') {
38
+ // warn if routes do not include leading slashes
39
+ const found = pathList
40
+ // check for missing leading slash
41
+ .filter(path => path && path.charAt(0) !== '*' && path.charAt(0) !== '/')
42
+
43
+ if (found.length > 0) {
44
+ const pathNames = found.map(path => `- ${path}`).join('\n')
45
+ warn(false, `Non-nested routes must include a leading slash character. Fix the following routes: \n${pathNames}`)
46
+ }
47
+ }
48
+
49
+ return {
50
+ pathList,
51
+ pathMap,
52
+ nameMap
53
+ }
54
+ }
55
+
56
+ function addRouteRecord (
57
+ pathList: Array<string>,
58
+ pathMap: Dictionary<RouteRecord>,
59
+ nameMap: Dictionary<RouteRecord>,
60
+ route: RouteConfig,
61
+ parent?: RouteRecord,
62
+ matchAs?: string
63
+ ) {
64
+ const { path, name } = route
65
+ if (process.env.NODE_ENV !== 'production') {
66
+ assert(path != null, `"path" is required in a route configuration.`)
67
+ assert(
68
+ typeof route.component !== 'string',
69
+ `route config "component" for path: ${String(
70
+ path || name
71
+ )} cannot be a ` + `string id. Use an actual component instead.`
72
+ )
73
+ }
74
+
75
+ const pathToRegexpOptions: PathToRegexpOptions =
76
+ route.pathToRegexpOptions || {}
77
+ const normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict)
78
+
79
+ if (typeof route.caseSensitive === 'boolean') {
80
+ pathToRegexpOptions.sensitive = route.caseSensitive
81
+ }
82
+
83
+ const record: RouteRecord = {
84
+ path: normalizedPath,
85
+ regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
86
+ components: route.components || { default: route.component },
87
+ instances: {},
88
+ name,
89
+ parent,
90
+ matchAs,
91
+ redirect: route.redirect,
92
+ beforeEnter: route.beforeEnter,
93
+ meta: route.meta || {},
94
+ props:
95
+ route.props == null
96
+ ? {}
97
+ : route.components
98
+ ? route.props
99
+ : { default: route.props }
100
+ }
101
+
102
+ if (route.children) {
103
+ // Warn if route is named, does not redirect and has a default child route.
104
+ // If users navigate to this route by name, the default child will
105
+ // not be rendered (GH Issue #629)
106
+ if (process.env.NODE_ENV !== 'production') {
107
+ if (
108
+ route.name &&
109
+ !route.redirect &&
110
+ route.children.some(child => /^\/?$/.test(child.path))
111
+ ) {
112
+ warn(
113
+ false,
114
+ `Named Route '${route.name}' has a default child route. ` +
115
+ `When navigating to this named route (:to="{name: '${
116
+ route.name
117
+ }'"), ` +
118
+ `the default child route will not be rendered. Remove the name from ` +
119
+ `this route and use the name of the default child route for named ` +
120
+ `links instead.`
121
+ )
122
+ }
123
+ }
124
+ route.children.forEach(child => {
125
+ const childMatchAs = matchAs
126
+ ? cleanPath(`${matchAs}/${child.path}`)
127
+ : undefined
128
+ addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs)
129
+ })
130
+ }
131
+
132
+ if (!pathMap[record.path]) {
133
+ pathList.push(record.path)
134
+ pathMap[record.path] = record
135
+ }
136
+
137
+ if (route.alias !== undefined) {
138
+ const aliases = Array.isArray(route.alias) ? route.alias : [route.alias]
139
+ for (let i = 0; i < aliases.length; ++i) {
140
+ const alias = aliases[i]
141
+ if (process.env.NODE_ENV !== 'production' && alias === path) {
142
+ warn(
143
+ false,
144
+ `Found an alias with the same value as the path: "${path}". You have to remove that alias. It will be ignored in development.`
145
+ )
146
+ // skip in dev to make it work
147
+ continue
148
+ }
149
+
150
+ const aliasRoute = {
151
+ path: alias,
152
+ children: route.children
153
+ }
154
+ addRouteRecord(
155
+ pathList,
156
+ pathMap,
157
+ nameMap,
158
+ aliasRoute,
159
+ parent,
160
+ record.path || '/' // matchAs
161
+ )
162
+ }
163
+ }
164
+
165
+ if (name) {
166
+ if (!nameMap[name]) {
167
+ nameMap[name] = record
168
+ } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
169
+ warn(
170
+ false,
171
+ `Duplicate named routes definition: ` +
172
+ `{ name: "${name}", path: "${record.path}" }`
173
+ )
174
+ }
175
+ }
176
+ }
177
+
178
+ function compileRouteRegex (
179
+ path: string,
180
+ pathToRegexpOptions: PathToRegexpOptions
181
+ ): RouteRegExp {
182
+ const regex = Regexp(path, [], pathToRegexpOptions)
183
+ if (process.env.NODE_ENV !== 'production') {
184
+ const keys: any = Object.create(null)
185
+ regex.keys.forEach(key => {
186
+ warn(
187
+ !keys[key.name],
188
+ `Duplicate param keys in route with path: "${path}"`
189
+ )
190
+ keys[key.name] = true
191
+ })
192
+ }
193
+ return regex
194
+ }
195
+
196
+ function normalizePath (
197
+ path: string,
198
+ parent?: RouteRecord,
199
+ strict?: boolean
200
+ ): string {
201
+ if (!strict) path = path.replace(/\/$/, '')
202
+ if (path[0] === '/') return path
203
+ if (parent == null) return path
204
+ return cleanPath(`${parent.path}/${path}`)
205
+ }