kdu-router 3.4.0-beta.0 → 3.6.0

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.
Files changed (49) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +11 -9
  3. package/dist/composables.js +253 -0
  4. package/dist/composables.mjs +244 -0
  5. package/dist/kdu-router.common.js +2682 -2572
  6. package/dist/kdu-router.esm.browser.js +2677 -2563
  7. package/dist/kdu-router.esm.browser.min.js +5 -5
  8. package/dist/kdu-router.esm.js +2685 -2572
  9. package/dist/kdu-router.js +2682 -2573
  10. package/dist/kdu-router.min.js +5 -5
  11. package/ketur/attributes.json +38 -38
  12. package/ketur/tags.json +20 -20
  13. package/package.json +115 -111
  14. package/src/components/link.js +224 -197
  15. package/src/components/view.js +155 -149
  16. package/src/composables/globals.js +34 -0
  17. package/src/composables/guards.js +68 -0
  18. package/src/composables/index.js +3 -0
  19. package/src/composables/useLink.js +113 -0
  20. package/src/composables/utils.js +11 -0
  21. package/src/create-matcher.js +226 -200
  22. package/src/create-route-map.js +220 -205
  23. package/src/entries/cjs.js +3 -0
  24. package/src/entries/esm.js +12 -0
  25. package/src/history/abstract.js +72 -68
  26. package/src/history/base.js +379 -400
  27. package/src/history/hash.js +152 -163
  28. package/src/history/html5.js +99 -94
  29. package/src/index.js +3 -277
  30. package/src/install.js +52 -52
  31. package/src/router.js +293 -0
  32. package/src/util/async.js +18 -18
  33. package/src/util/dom.js +3 -3
  34. package/src/util/errors.js +86 -85
  35. package/src/util/location.js +69 -69
  36. package/src/util/misc.js +6 -6
  37. package/src/util/params.js +37 -37
  38. package/src/util/path.js +74 -74
  39. package/src/util/push-state.js +46 -46
  40. package/src/util/query.js +113 -96
  41. package/src/util/resolve-components.js +109 -109
  42. package/src/util/route.js +151 -132
  43. package/src/util/scroll.js +175 -165
  44. package/src/util/state-key.js +22 -22
  45. package/src/util/warn.js +14 -14
  46. package/types/composables.d.ts +53 -0
  47. package/types/index.d.ts +25 -17
  48. package/types/kdu.d.ts +22 -22
  49. package/types/router.d.ts +564 -170
@@ -1,200 +1,226 @@
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
- }
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
+ import { decode } from './util/query'
11
+
12
+ export type Matcher = {
13
+ match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
14
+ addRoutes: (routes: Array<RouteConfig>) => void;
15
+ addRoute: (parentNameOrRoute: string | RouteConfig, route?: RouteConfig) => void;
16
+ getRoutes: () => Array<RouteRecord>;
17
+ };
18
+
19
+ export function createMatcher (
20
+ routes: Array<RouteConfig>,
21
+ router: KduRouter
22
+ ): Matcher {
23
+ const { pathList, pathMap, nameMap } = createRouteMap(routes)
24
+
25
+ function addRoutes (routes) {
26
+ createRouteMap(routes, pathList, pathMap, nameMap)
27
+ }
28
+
29
+ function addRoute (parentOrRoute, route) {
30
+ const parent = (typeof parentOrRoute !== 'object') ? nameMap[parentOrRoute] : undefined
31
+ // $flow-disable-line
32
+ createRouteMap([route || parentOrRoute], pathList, pathMap, nameMap, parent)
33
+
34
+ // add aliases of parent
35
+ if (parent && parent.alias.length) {
36
+ createRouteMap(
37
+ // $flow-disable-line route is defined if parent is
38
+ parent.alias.map(alias => ({ path: alias, children: [route] })),
39
+ pathList,
40
+ pathMap,
41
+ nameMap,
42
+ parent
43
+ )
44
+ }
45
+ }
46
+
47
+ function getRoutes () {
48
+ return pathList.map(path => pathMap[path])
49
+ }
50
+
51
+ function match (
52
+ raw: RawLocation,
53
+ currentRoute?: Route,
54
+ redirectedFrom?: Location
55
+ ): Route {
56
+ const location = normalizeLocation(raw, currentRoute, false, router)
57
+ const { name } = location
58
+
59
+ if (name) {
60
+ const record = nameMap[name]
61
+ if (process.env.NODE_ENV !== 'production') {
62
+ warn(record, `Route with name '${name}' does not exist`)
63
+ }
64
+ if (!record) return _createRoute(null, location)
65
+ const paramNames = record.regex.keys
66
+ .filter(key => !key.optional)
67
+ .map(key => key.name)
68
+
69
+ if (typeof location.params !== 'object') {
70
+ location.params = {}
71
+ }
72
+
73
+ if (currentRoute && typeof currentRoute.params === 'object') {
74
+ for (const key in currentRoute.params) {
75
+ if (!(key in location.params) && paramNames.indexOf(key) > -1) {
76
+ location.params[key] = currentRoute.params[key]
77
+ }
78
+ }
79
+ }
80
+
81
+ location.path = fillParams(record.path, location.params, `named route "${name}"`)
82
+ return _createRoute(record, location, redirectedFrom)
83
+ } else if (location.path) {
84
+ location.params = {}
85
+ for (let i = 0; i < pathList.length; i++) {
86
+ const path = pathList[i]
87
+ const record = pathMap[path]
88
+ if (matchRoute(record.regex, location.path, location.params)) {
89
+ return _createRoute(record, location, redirectedFrom)
90
+ }
91
+ }
92
+ }
93
+ // no match
94
+ return _createRoute(null, location)
95
+ }
96
+
97
+ function redirect (
98
+ record: RouteRecord,
99
+ location: Location
100
+ ): Route {
101
+ const originalRedirect = record.redirect
102
+ let redirect = typeof originalRedirect === 'function'
103
+ ? originalRedirect(createRoute(record, location, null, router))
104
+ : originalRedirect
105
+
106
+ if (typeof redirect === 'string') {
107
+ redirect = { path: redirect }
108
+ }
109
+
110
+ if (!redirect || typeof redirect !== 'object') {
111
+ if (process.env.NODE_ENV !== 'production') {
112
+ warn(
113
+ false, `invalid redirect option: ${JSON.stringify(redirect)}`
114
+ )
115
+ }
116
+ return _createRoute(null, location)
117
+ }
118
+
119
+ const re: Object = redirect
120
+ const { name, path } = re
121
+ let { query, hash, params } = location
122
+ query = re.hasOwnProperty('query') ? re.query : query
123
+ hash = re.hasOwnProperty('hash') ? re.hash : hash
124
+ params = re.hasOwnProperty('params') ? re.params : params
125
+
126
+ if (name) {
127
+ // resolved named direct
128
+ const targetRecord = nameMap[name]
129
+ if (process.env.NODE_ENV !== 'production') {
130
+ assert(targetRecord, `redirect failed: named route "${name}" not found.`)
131
+ }
132
+ return match({
133
+ _normalized: true,
134
+ name,
135
+ query,
136
+ hash,
137
+ params
138
+ }, undefined, location)
139
+ } else if (path) {
140
+ // 1. resolve relative redirect
141
+ const rawPath = resolveRecordPath(path, record)
142
+ // 2. resolve params
143
+ const resolvedPath = fillParams(rawPath, params, `redirect route with path "${rawPath}"`)
144
+ // 3. rematch with existing query and hash
145
+ return match({
146
+ _normalized: true,
147
+ path: resolvedPath,
148
+ query,
149
+ hash
150
+ }, undefined, location)
151
+ } else {
152
+ if (process.env.NODE_ENV !== 'production') {
153
+ warn(false, `invalid redirect option: ${JSON.stringify(redirect)}`)
154
+ }
155
+ return _createRoute(null, location)
156
+ }
157
+ }
158
+
159
+ function alias (
160
+ record: RouteRecord,
161
+ location: Location,
162
+ matchAs: string
163
+ ): Route {
164
+ const aliasedPath = fillParams(matchAs, location.params, `aliased route with path "${matchAs}"`)
165
+ const aliasedMatch = match({
166
+ _normalized: true,
167
+ path: aliasedPath
168
+ })
169
+ if (aliasedMatch) {
170
+ const matched = aliasedMatch.matched
171
+ const aliasedRecord = matched[matched.length - 1]
172
+ location.params = aliasedMatch.params
173
+ return _createRoute(aliasedRecord, location)
174
+ }
175
+ return _createRoute(null, location)
176
+ }
177
+
178
+ function _createRoute (
179
+ record: ?RouteRecord,
180
+ location: Location,
181
+ redirectedFrom?: Location
182
+ ): Route {
183
+ if (record && record.redirect) {
184
+ return redirect(record, redirectedFrom || location)
185
+ }
186
+ if (record && record.matchAs) {
187
+ return alias(record, location, record.matchAs)
188
+ }
189
+ return createRoute(record, location, redirectedFrom, router)
190
+ }
191
+
192
+ return {
193
+ match,
194
+ addRoute,
195
+ getRoutes,
196
+ addRoutes
197
+ }
198
+ }
199
+
200
+ function matchRoute (
201
+ regex: RouteRegExp,
202
+ path: string,
203
+ params: Object
204
+ ): boolean {
205
+ const m = path.match(regex)
206
+
207
+ if (!m) {
208
+ return false
209
+ } else if (!params) {
210
+ return true
211
+ }
212
+
213
+ for (let i = 1, len = m.length; i < len; ++i) {
214
+ const key = regex.keys[i - 1]
215
+ if (key) {
216
+ // Fix #1994: using * with props: true generates a param named 0
217
+ params[key.name || 'pathMatch'] = typeof m[i] === 'string' ? decode(m[i]) : m[i]
218
+ }
219
+ }
220
+
221
+ return true
222
+ }
223
+
224
+ function resolveRecordPath (path: string, record: RouteRecord): string {
225
+ return resolvePath(path, record.parent ? record.parent.path : '/', true)
226
+ }