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,201 +1,200 @@
1
- /* @flow */
2
-
3
- import type KduRouter from './index'
4
- import { resolvePath } from './util/path'
5
- import { assert, warn } from './util/warn'
6
- import { createRoute } from './util/route'
7
- import { fillParams } from './util/params'
8
- import { createRouteMap } from './create-route-map'
9
- import { normalizeLocation } from './util/location'
10
-
11
- export type Matcher = {
12
- match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
13
- addRoutes: (routes: Array<RouteConfig>) => void;
14
- };
15
-
16
- export function createMatcher (
17
- routes: Array<RouteConfig>,
18
- router: KduRouter
19
- ): Matcher {
20
- const { pathList, pathMap, nameMap } = createRouteMap(routes)
21
-
22
- function addRoutes (routes) {
23
- createRouteMap(routes, pathList, pathMap, nameMap)
24
- }
25
-
26
- function match (
27
- raw: RawLocation,
28
- currentRoute?: Route,
29
- redirectedFrom?: Location
30
- ): Route {
31
- const location = normalizeLocation(raw, currentRoute, false, router)
32
- const { name } = location
33
-
34
- if (name) {
35
- const record = nameMap[name]
36
- if (process.env.NODE_ENV !== 'production') {
37
- warn(record, `Route with name '${name}' does not exist`)
38
- }
39
- if (!record) return _createRoute(null, location)
40
- const paramNames = record.regex.keys
41
- .filter(key => !key.optional)
42
- .map(key => key.name)
43
-
44
- if (typeof location.params !== 'object') {
45
- location.params = {}
46
- }
47
-
48
- if (currentRoute && typeof currentRoute.params === 'object') {
49
- for (const key in currentRoute.params) {
50
- if (!(key in location.params) && paramNames.indexOf(key) > -1) {
51
- location.params[key] = currentRoute.params[key]
52
- }
53
- }
54
- }
55
-
56
- if (record) {
57
- location.path = fillParams(record.path, location.params, `named route "${name}"`)
58
- return _createRoute(record, location, redirectedFrom)
59
- }
60
- } else if (location.path) {
61
- location.params = {}
62
- for (let i = 0; i < pathList.length; i++) {
63
- const path = pathList[i]
64
- const record = pathMap[path]
65
- if (matchRoute(record.regex, location.path, location.params)) {
66
- return _createRoute(record, location, redirectedFrom)
67
- }
68
- }
69
- }
70
- // no match
71
- return _createRoute(null, location)
72
- }
73
-
74
- function redirect (
75
- record: RouteRecord,
76
- location: Location
77
- ): Route {
78
- const originalRedirect = record.redirect
79
- let redirect = typeof originalRedirect === 'function'
80
- ? originalRedirect(createRoute(record, location, null, router))
81
- : originalRedirect
82
-
83
- if (typeof redirect === 'string') {
84
- redirect = { path: redirect }
85
- }
86
-
87
- if (!redirect || typeof redirect !== 'object') {
88
- if (process.env.NODE_ENV !== 'production') {
89
- warn(
90
- false, `invalid redirect option: ${JSON.stringify(redirect)}`
91
- )
92
- }
93
- return _createRoute(null, location)
94
- }
95
-
96
- const re: Object = redirect
97
- const { name, path } = re
98
- let { query, hash, params } = location
99
- query = re.hasOwnProperty('query') ? re.query : query
100
- hash = re.hasOwnProperty('hash') ? re.hash : hash
101
- params = re.hasOwnProperty('params') ? re.params : params
102
-
103
- if (name) {
104
- // resolved named direct
105
- const targetRecord = nameMap[name]
106
- if (process.env.NODE_ENV !== 'production') {
107
- assert(targetRecord, `redirect failed: named route "${name}" not found.`)
108
- }
109
- return match({
110
- _normalized: true,
111
- name,
112
- query,
113
- hash,
114
- params
115
- }, undefined, location)
116
- } else if (path) {
117
- // 1. resolve relative redirect
118
- const rawPath = resolveRecordPath(path, record)
119
- // 2. resolve params
120
- const resolvedPath = fillParams(rawPath, params, `redirect route with path "${rawPath}"`)
121
- // 3. rematch with existing query and hash
122
- return match({
123
- _normalized: true,
124
- path: resolvedPath,
125
- query,
126
- hash
127
- }, undefined, location)
128
- } else {
129
- if (process.env.NODE_ENV !== 'production') {
130
- warn(false, `invalid redirect option: ${JSON.stringify(redirect)}`)
131
- }
132
- return _createRoute(null, location)
133
- }
134
- }
135
-
136
- function alias (
137
- record: RouteRecord,
138
- location: Location,
139
- matchAs: string
140
- ): Route {
141
- const aliasedPath = fillParams(matchAs, location.params, `aliased route with path "${matchAs}"`)
142
- const aliasedMatch = match({
143
- _normalized: true,
144
- path: aliasedPath
145
- })
146
- if (aliasedMatch) {
147
- const matched = aliasedMatch.matched
148
- const aliasedRecord = matched[matched.length - 1]
149
- location.params = aliasedMatch.params
150
- return _createRoute(aliasedRecord, location)
151
- }
152
- return _createRoute(null, location)
153
- }
154
-
155
- function _createRoute (
156
- record: ?RouteRecord,
157
- location: Location,
158
- redirectedFrom?: Location
159
- ): Route {
160
- if (record && record.redirect) {
161
- return redirect(record, redirectedFrom || location)
162
- }
163
- if (record && record.matchAs) {
164
- return alias(record, location, record.matchAs)
165
- }
166
- return createRoute(record, location, redirectedFrom, router)
167
- }
168
-
169
- return {
170
- match,
171
- addRoutes
172
- }
173
- }
174
-
175
- function matchRoute (
176
- regex: RouteRegExp,
177
- path: string,
178
- params: Object
179
- ): boolean {
180
- const m = path.match(regex)
181
-
182
- if (!m) {
183
- return false
184
- } else if (!params) {
185
- return true
186
- }
187
-
188
- for (let i = 1, len = m.length; i < len; ++i) {
189
- const key = regex.keys[i - 1]
190
- const val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i]
191
- if (key) {
192
- params[key.name] = val
193
- }
194
- }
195
-
196
- return true
197
- }
198
-
199
- function resolveRecordPath (path: string, record: RouteRecord): string {
200
- return resolvePath(path, record.parent ? record.parent.path : '/', true)
201
- }
1
+ /* @flow */
2
+
3
+ import type KduRouter from './index'
4
+ import { resolvePath } from './util/path'
5
+ import { assert, warn } from './util/warn'
6
+ import { createRoute } from './util/route'
7
+ import { fillParams } from './util/params'
8
+ import { createRouteMap } from './create-route-map'
9
+ import { normalizeLocation } from './util/location'
10
+
11
+ export type Matcher = {
12
+ match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
13
+ addRoutes: (routes: Array<RouteConfig>) => void;
14
+ };
15
+
16
+ export function createMatcher (
17
+ routes: Array<RouteConfig>,
18
+ router: KduRouter
19
+ ): Matcher {
20
+ const { pathList, pathMap, nameMap } = createRouteMap(routes)
21
+
22
+ function addRoutes (routes) {
23
+ createRouteMap(routes, pathList, pathMap, nameMap)
24
+ }
25
+
26
+ function match (
27
+ raw: RawLocation,
28
+ currentRoute?: Route,
29
+ redirectedFrom?: Location
30
+ ): Route {
31
+ const location = normalizeLocation(raw, currentRoute, false, router)
32
+ const { name } = location
33
+
34
+ if (name) {
35
+ const record = nameMap[name]
36
+ if (process.env.NODE_ENV !== 'production') {
37
+ warn(record, `Route with name '${name}' does not exist`)
38
+ }
39
+ if (!record) return _createRoute(null, location)
40
+ const paramNames = record.regex.keys
41
+ .filter(key => !key.optional)
42
+ .map(key => key.name)
43
+
44
+ if (typeof location.params !== 'object') {
45
+ location.params = {}
46
+ }
47
+
48
+ if (currentRoute && typeof currentRoute.params === 'object') {
49
+ for (const key in currentRoute.params) {
50
+ if (!(key in location.params) && paramNames.indexOf(key) > -1) {
51
+ location.params[key] = currentRoute.params[key]
52
+ }
53
+ }
54
+ }
55
+
56
+ location.path = fillParams(record.path, location.params, `named route "${name}"`)
57
+ return _createRoute(record, location, redirectedFrom)
58
+ } else if (location.path) {
59
+ location.params = {}
60
+ for (let i = 0; i < pathList.length; i++) {
61
+ const path = pathList[i]
62
+ const record = pathMap[path]
63
+ if (matchRoute(record.regex, location.path, location.params)) {
64
+ return _createRoute(record, location, redirectedFrom)
65
+ }
66
+ }
67
+ }
68
+ // no match
69
+ return _createRoute(null, location)
70
+ }
71
+
72
+ function redirect (
73
+ record: RouteRecord,
74
+ location: Location
75
+ ): Route {
76
+ const originalRedirect = record.redirect
77
+ let redirect = typeof originalRedirect === 'function'
78
+ ? originalRedirect(createRoute(record, location, null, router))
79
+ : originalRedirect
80
+
81
+ if (typeof redirect === 'string') {
82
+ redirect = { path: redirect }
83
+ }
84
+
85
+ if (!redirect || typeof redirect !== 'object') {
86
+ if (process.env.NODE_ENV !== 'production') {
87
+ warn(
88
+ false, `invalid redirect option: ${JSON.stringify(redirect)}`
89
+ )
90
+ }
91
+ return _createRoute(null, location)
92
+ }
93
+
94
+ const re: Object = redirect
95
+ const { name, path } = re
96
+ let { query, hash, params } = location
97
+ query = re.hasOwnProperty('query') ? re.query : query
98
+ hash = re.hasOwnProperty('hash') ? re.hash : hash
99
+ params = re.hasOwnProperty('params') ? re.params : params
100
+
101
+ if (name) {
102
+ // resolved named direct
103
+ const targetRecord = nameMap[name]
104
+ if (process.env.NODE_ENV !== 'production') {
105
+ assert(targetRecord, `redirect failed: named route "${name}" not found.`)
106
+ }
107
+ return match({
108
+ _normalized: true,
109
+ name,
110
+ query,
111
+ hash,
112
+ params
113
+ }, undefined, location)
114
+ } else if (path) {
115
+ // 1. resolve relative redirect
116
+ const rawPath = resolveRecordPath(path, record)
117
+ // 2. resolve params
118
+ const resolvedPath = fillParams(rawPath, params, `redirect route with path "${rawPath}"`)
119
+ // 3. rematch with existing query and hash
120
+ return match({
121
+ _normalized: true,
122
+ path: resolvedPath,
123
+ query,
124
+ hash
125
+ }, undefined, location)
126
+ } else {
127
+ if (process.env.NODE_ENV !== 'production') {
128
+ warn(false, `invalid redirect option: ${JSON.stringify(redirect)}`)
129
+ }
130
+ return _createRoute(null, location)
131
+ }
132
+ }
133
+
134
+ function alias (
135
+ record: RouteRecord,
136
+ location: Location,
137
+ matchAs: string
138
+ ): Route {
139
+ const aliasedPath = fillParams(matchAs, location.params, `aliased route with path "${matchAs}"`)
140
+ const aliasedMatch = match({
141
+ _normalized: true,
142
+ path: aliasedPath
143
+ })
144
+ if (aliasedMatch) {
145
+ const matched = aliasedMatch.matched
146
+ const aliasedRecord = matched[matched.length - 1]
147
+ location.params = aliasedMatch.params
148
+ return _createRoute(aliasedRecord, location)
149
+ }
150
+ return _createRoute(null, location)
151
+ }
152
+
153
+ function _createRoute (
154
+ record: ?RouteRecord,
155
+ location: Location,
156
+ redirectedFrom?: Location
157
+ ): Route {
158
+ if (record && record.redirect) {
159
+ return redirect(record, redirectedFrom || location)
160
+ }
161
+ if (record && record.matchAs) {
162
+ return alias(record, location, record.matchAs)
163
+ }
164
+ return createRoute(record, location, redirectedFrom, router)
165
+ }
166
+
167
+ return {
168
+ match,
169
+ addRoutes
170
+ }
171
+ }
172
+
173
+ function matchRoute (
174
+ regex: RouteRegExp,
175
+ path: string,
176
+ params: Object
177
+ ): boolean {
178
+ const m = path.match(regex)
179
+
180
+ if (!m) {
181
+ return false
182
+ } else if (!params) {
183
+ return true
184
+ }
185
+
186
+ for (let i = 1, len = m.length; i < len; ++i) {
187
+ const key = regex.keys[i - 1]
188
+ const val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i]
189
+ if (key) {
190
+ // Fix #1994: using * with props: true generates a param named 0
191
+ params[key.name || 'pathMatch'] = val
192
+ }
193
+ }
194
+
195
+ return true
196
+ }
197
+
198
+ function resolveRecordPath (path: string, record: RouteRecord): string {
199
+ return resolvePath(path, record.parent ? record.parent.path : '/', true)
200
+ }